s3-winbindd: add support for idmap type WBC_ID_TYPE_BOTH
authorAndrew Tridgell <tridge@samba.org>
Tue, 26 Jul 2011 01:07:12 +0000 (11:07 +1000)
committerMichael Adam <obnox@samba.org>
Thu, 22 Sep 2011 23:47:54 +0000 (01:47 +0200)
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 <abartlet@samba.org>

Signed-off-by: Michael Adam <obnox@samba.org>
Autobuild-User: Michael Adam <obnox@samba.org>
Autobuild-Date: Fri Sep 23 01:47:54 CEST 2011 on sn-devel-104

source3/auth/auth_util.c
source3/lib/idmap_cache.c
source3/lib/idmap_cache.h
source3/winbindd/winbindd_sids_to_xids.c

index f41809d58d10a5ed898a1effa0de8ac52555d77b..11b220eec6b9035d17b7f686283a522bbb6ac0d7 100644 (file)
@@ -608,7 +608,8 @@ NTSTATUS create_local_token(TALLOC_CTX *mem_ctx,
 
        for (i=1; i<t->num_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])));
index 6783215b4167ba96f8946834aff8148fbd6d0995..413029c7a15887c537e3030da7947d6d53c61287 100644 (file)
@@ -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;
index 1a62dba64fc0d5ed133bfc60e5eeb90db7feb883..4c87139770b1b3a3b0a0f4be17e2052b8315a34a 100644 (file)
@@ -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_ */
index d08064fbf389d6cbcf60377b570a68c4465dceb5..b416e3a3384bb8e7b260201d42dc59b8e76d8266 100644 (file)
@@ -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;
                        }