From: Andrew Tridgell Date: Tue, 26 Jul 2011 01:07:12 +0000 (+1000) Subject: s3-winbindd: add support for idmap type WBC_ID_TYPE_BOTH X-Git-Url: http://git.samba.org/?a=commitdiff_plain;h=f236c539ad39932ee3c9a5df0276147a45dd1a42;p=mat%2Fsamba.git s3-winbindd: add support for idmap type WBC_ID_TYPE_BOTH this allows the s3 code to understand and cache responses from the s4 winbindd which may include a single SID mapped to both a uid and a gid Pair-Programmed-With: Andrew Bartlett Signed-off-by: Michael Adam Autobuild-User: Michael Adam Autobuild-Date: Fri Sep 23 01:47:54 CEST 2011 on sn-devel-104 --- diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index f41809d58d..11b220eec6 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -608,7 +608,8 @@ NTSTATUS create_local_token(TALLOC_CTX *mem_ctx, for (i=1; inum_sids; i++) { - if (ids[i].type != WBC_ID_TYPE_GID) { + if (ids[i].type != WBC_ID_TYPE_GID && + ids[i].type != WBC_ID_TYPE_BOTH) { DEBUG(10, ("Could not convert SID %s to gid, " "ignoring it\n", sid_string_dbg(&t->sids[i]))); diff --git a/source3/lib/idmap_cache.c b/source3/lib/idmap_cache.c index 6783215b41..413029c7a1 100644 --- a/source3/lib/idmap_cache.c +++ b/source3/lib/idmap_cache.c @@ -261,7 +261,54 @@ void idmap_cache_set_sid2gid(const struct dom_sid *sid, gid_t gid) } } + +/** + * Store a mapping in the idmap cache + * @param[in] sid the sid to map + * @param[in] uid/gid the uid/gid to map + * + * If both parameters are valid values, then a positive mapping in both + * directions is stored. If "is_null_sid(sid)" is true, then this will be a + * negative mapping of gid, we want to cache that for this id we could not + * find anything. Likewise if "id==-1", then we want to cache that we did not + * find a mapping for the sid passed here. + */ + +void idmap_cache_set_sid2both(const struct dom_sid *sid, uid_t id) +{ + time_t now = time(NULL); + time_t timeout; + fstring sidstr, key, value; + + if (!is_null_sid(sid)) { + fstr_sprintf(key, "IDMAP/SID2BOTH/%s", + sid_to_fstring(sidstr, sid)); + fstr_sprintf(value, "%d", (int)id); + timeout = (id == -1) + ? lp_idmap_negative_cache_time() + : lp_idmap_cache_time(); + gencache_set(key, value, now + timeout); + } + if (id != -1) { + fstr_sprintf(key, "IDMAP/BOTH2SID/%d", (int)id); + if (is_null_sid(sid)) { + /* negative id mapping */ + fstrcpy(value, "-"); + timeout = lp_idmap_negative_cache_time(); + } + else { + sid_to_fstring(value, sid); + timeout = lp_idmap_cache_time(); + } + gencache_set(key, value, now + timeout); + } +} + + static char* key_xid2sid_str(TALLOC_CTX* mem_ctx, char t, const char* id) { + if (t == 'B') { + return talloc_asprintf(mem_ctx, "IDMAP/BOTH2SID/%s", id); + } return talloc_asprintf(mem_ctx, "IDMAP/%cID2SID/%s", t, id); } @@ -272,6 +319,9 @@ static char* key_xid2sid(TALLOC_CTX* mem_ctx, char t, int id) { } static char* key_sid2xid_str(TALLOC_CTX* mem_ctx, char t, const char* sid) { + if (t == 'B') { + return talloc_asprintf(mem_ctx, "IDMAP/SID2BOTH/%s", sid); + } return talloc_asprintf(mem_ctx, "IDMAP/SID2%cID/%s", t, sid); } @@ -328,6 +378,10 @@ bool idmap_cache_del_gid(gid_t gid) { return idmap_cache_del_xid('G', gid); } +bool idmap_cache_del_both(uid_t id) { + return idmap_cache_del_xid('B', id); +} + static bool idmap_cache_del_sid2xid(TALLOC_CTX* mem_ctx, char t, const char* sid) { const char* sid_key = key_sid2xid_str(mem_ctx, t, sid); @@ -367,7 +421,8 @@ bool idmap_cache_del_sid(const struct dom_sid *sid) bool ret = true; if (!idmap_cache_del_sid2xid(mem_ctx, 'U', sid_str) && - !idmap_cache_del_sid2xid(mem_ctx, 'G', sid_str)) + !idmap_cache_del_sid2xid(mem_ctx, 'G', sid_str) && + !idmap_cache_del_sid2xid(mem_ctx, 'B', sid_str)) { DEBUG(3, ("no entry: %s\n", key_xid2sid_str(mem_ctx, '?', sid_str))); ret = false; diff --git a/source3/lib/idmap_cache.h b/source3/lib/idmap_cache.h index 1a62dba64f..4c87139770 100644 --- a/source3/lib/idmap_cache.h +++ b/source3/lib/idmap_cache.h @@ -31,9 +31,11 @@ bool idmap_cache_find_sid2gid(const struct dom_sid *sid, gid_t *pgid, bool *expired); bool idmap_cache_find_gid2sid(gid_t gid, struct dom_sid *sid, bool *expired); void idmap_cache_set_sid2gid(const struct dom_sid *sid, gid_t gid); +void idmap_cache_set_sid2both(const struct dom_sid *sid, uid_t id); bool idmap_cache_del_uid(uid_t uid); bool idmap_cache_del_gid(gid_t gid); +bool idmap_cache_del_both(uid_t uid); bool idmap_cache_del_sid(const struct dom_sid *sid); #endif /* _LIB_IDMAP_CACHE_H_ */ diff --git a/source3/winbindd/winbindd_sids_to_xids.c b/source3/winbindd/winbindd_sids_to_xids.c index d08064fbf3..b416e3a338 100644 --- a/source3/winbindd/winbindd_sids_to_xids.c +++ b/source3/winbindd/winbindd_sids_to_xids.c @@ -284,6 +284,12 @@ NTSTATUS winbindd_sids_to_xids_recv(struct tevent_req *req, &state->non_cached[num_non_cached], unix_id); break; + case WBC_ID_TYPE_BOTH: + type = 'B'; + idmap_cache_set_sid2both( + &state->non_cached[num_non_cached], + unix_id); + break; default: found = false; }