this allows us to support foreign SIDs in winbindd and smbd
authorAndrew Tridgell <tridge@samba.org>
Wed, 27 Feb 2002 23:51:25 +0000 (23:51 +0000)
committerAndrew Tridgell <tridge@samba.org>
Wed, 27 Feb 2002 23:51:25 +0000 (23:51 +0000)
this means "xcopy /o" has a chance of working with ACLs that contain
ACEs that use SIDs that the Samba server has no knowledge of.

It's a bit hackish, Tim, can you look at my uid.c changes?

source/nsswitch/winbindd_group.c
source/nsswitch/winbindd_idmap.c
source/nsswitch/winbindd_proto.h
source/nsswitch/winbindd_sid.c
source/nsswitch/winbindd_util.c
source/smbd/uid.c

index 1818d992b7a6092442a22bfdc6a794d97c1d7c2f..c62ce54b591aca0bd8607a6eec7d029307ec62fb 100644 (file)
@@ -228,10 +228,9 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
        }
 
        /* Fill in group structure */
+       sid_peek_rid(&group_sid, &group_rid);
 
-       sid_split_rid(&group_sid, &group_rid);
-
-       if (!winbindd_idmap_get_gid_from_rid(domain->name, group_rid, &gid)) {
+       if (!winbindd_idmap_get_gid_from_sid(&group_sid, &gid)) {
                DEBUG(1, ("error converting unix gid to sid\n"));
                return WINBINDD_ERROR;
        }
index 3a8269f853854e5f5356f05fb4069bf22ac9e143..977148ad6a0a64f48561e3c3faf9fd422c4915ce 100644 (file)
@@ -27,6 +27,9 @@
 #define HWM_GROUP  "GROUP HWM"
 #define HWM_USER   "USER HWM"
 
+/* idmap version determines auto-conversion */
+#define IDMAP_VERSION 2
+
 /* Globals */
 
 static TDB_CONTEXT *idmap_tdb;
@@ -66,17 +69,14 @@ static BOOL allocate_id(uid_t *id, BOOL isgroup)
 }
 
 /* Get an id from a rid */
-
-static BOOL get_id_from_rid(char *domain_name, uint32 rid, uid_t *id,
-                            BOOL isgroup)
+static BOOL get_id_from_sid(DOM_SID *sid, uid_t *id, BOOL isgroup)
 {
     TDB_DATA data, key;
     fstring keystr;
     BOOL result = False;
 
-    /* Check if rid is present in database */
-
-    slprintf(keystr, sizeof(keystr), "%s/%d", domain_name, rid);
+    /* Check if sid is present in database */
+    sid_to_string(keystr, sid);
     
     key.dptr = keystr;
     key.dsize = strlen(keystr) + 1;
@@ -88,34 +88,29 @@ static BOOL get_id_from_rid(char *domain_name, uint32 rid, uid_t *id,
         int the_id;
 
         /* Parse and return existing uid */
-
         fstrcpy(scanstr, isgroup ? "GID" : "UID");
         fstrcat(scanstr, " %d");
 
         if (sscanf(data.dptr, scanstr, &the_id) == 1) {
-
             /* Store uid */
-
             if (id) {
-                *id = the_id;
+                   *id = the_id;
             }
 
             result = True;
         }
 
         SAFE_FREE(data.dptr);
-
     } else {
 
-        /* Allocate a new id for this rid */
+        /* Allocate a new id for this sid */
 
         if (id && allocate_id(id, isgroup)) {
             fstring keystr2;
 
             /* Store new id */
             
-            slprintf(keystr2, sizeof(keystr2), "%s %d", isgroup ? "GID" :
-                     "UID", *id);
+            slprintf(keystr2, sizeof(keystr2), "%s %d", isgroup ? "GID" : "UID", *id);
 
             data.dptr = keystr2;
             data.dsize = strlen(keystr2) + 1;
@@ -130,24 +125,52 @@ static BOOL get_id_from_rid(char *domain_name, uint32 rid, uid_t *id,
     return result;
 }
 
-/* Get a uid from a user rid */
+/* Get a uid from a user sid */
+BOOL winbindd_idmap_get_uid_from_sid(DOM_SID *sid, uid_t *uid)
+{
+    return get_id_from_sid(sid, uid, False);
+}
 
-BOOL winbindd_idmap_get_uid_from_rid(char *domain_name, uint32 user_rid, 
-                                     uid_t *uid)
+/* Get a gid from a group sid */
+BOOL winbindd_idmap_get_gid_from_sid(DOM_SID *sid, gid_t *gid)
 {
-    return get_id_from_rid(domain_name, user_rid, uid, False);
+    return get_id_from_sid(sid, gid, True);
 }
 
-/* Get a gid from a group rid */
+/* Get a uid from a user rid */
+BOOL winbindd_idmap_get_uid_from_rid(const char *dom_name, uint32 rid, uid_t *uid)
+{
+       struct winbindd_domain *domain;
+       DOM_SID sid;
+
+       if (!(domain = find_domain_from_name(dom_name))) {
+               return False;
+       }
 
-BOOL winbindd_idmap_get_gid_from_rid(char *domain_name, uint32 group_rid, 
-                                     gid_t *gid)
+       sid_copy(&sid, &domain->sid);
+       sid_append_rid(&sid, rid);
+
+       return get_id_from_sid(&sid, uid, False);
+}
+
+/* Get a gid from a group rid */
+BOOL winbindd_idmap_get_gid_from_rid(const char *dom_name, uint32 rid, gid_t *gid)
 {
-    return get_id_from_rid(domain_name, group_rid, gid, True);
+       struct winbindd_domain *domain;
+       DOM_SID sid;
+
+       if (!(domain = find_domain_from_name(dom_name))) {
+               return False;
+       }
+
+       sid_copy(&sid, &domain->sid);
+       sid_append_rid(&sid, rid);
+
+       return get_id_from_sid(&sid, gid, True);
 }
 
-BOOL get_rid_from_id(int id, uint32 *rid, struct winbindd_domain **domain,
-                     BOOL isgroup)
+
+BOOL get_sid_from_id(int id, DOM_SID *sid, BOOL isgroup)
 {
     TDB_DATA key, data;
     fstring keystr;
@@ -161,43 +184,41 @@ BOOL get_rid_from_id(int id, uint32 *rid, struct winbindd_domain **domain,
     data = tdb_fetch(idmap_tdb, key);
 
     if (data.dptr) {
-        char *p = data.dptr;
-        fstring domain_name;
-        uint32 the_rid;
-
-        if (next_token(&p, domain_name, "/", sizeof(fstring))) {
-
-            the_rid = atoi(p);
-
-            if (rid) {
-                *rid = the_rid;
-            }
-
-            if (domain) {
-                *domain = find_domain_from_name(domain_name);
-               if (*domain == NULL) {
-                       DEBUG(1, ("unknown domain %s for rid %d\n",
-                                 domain_name, the_rid));
-                       result = False;
-                       goto done;
-               }
-            }
-
-            result = True;
-        }
-    done:            
-        SAFE_FREE(data.dptr);
+           result = string_to_sid(sid, data.dptr);
+           SAFE_FREE(data.dptr);
     }
 
     return result;
 }
 
-/* Get a user rid from a uid */
+/* Get a sid from a uid */
+BOOL winbindd_idmap_get_sid_from_uid(uid_t uid, DOM_SID *sid)
+{
+       return get_sid_from_id((int)uid, sid, False);
+}
 
+/* Get a sid from a gid */
+BOOL winbindd_idmap_get_sid_from_gid(gid_t gid, DOM_SID *sid)
+{
+       return get_sid_from_id((int)gid, sid, True);
+}
+
+/* Get a user rid from a uid */
 BOOL winbindd_idmap_get_rid_from_uid(uid_t uid, uint32 *user_rid,
                                      struct winbindd_domain **domain)
 {
-    return get_rid_from_id((int)uid, user_rid, domain, False);
+       DOM_SID sid;
+
+       if (!get_sid_from_id((int)uid, &sid, False)) {
+               return False;
+       }
+
+       *domain = find_domain_from_sid(&sid);
+       if (! *domain) return False;
+
+       sid_split_rid(&sid, user_rid);
+
+       return True;
 }
 
 /* Get a group rid from a gid */
@@ -205,9 +226,79 @@ BOOL winbindd_idmap_get_rid_from_uid(uid_t uid, uint32 *user_rid,
 BOOL winbindd_idmap_get_rid_from_gid(gid_t gid, uint32 *group_rid, 
                                      struct winbindd_domain **domain)
 {
-    return get_rid_from_id((int)gid, group_rid, domain, True);
+       DOM_SID sid;
+
+       if (!get_sid_from_id((int)gid, &sid, True)) {
+               return False;
+       }
+
+       *domain = find_domain_from_sid(&sid);
+       if (! *domain) return False;
+
+       sid_split_rid(&sid, group_rid);
+
+       return True;
 }
 
+/* convert one record to the new format */
+static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *ignored)
+{
+       struct winbindd_domain *domain;
+       char *p, *dom_name;
+       DOM_SID sid;
+       uint32 rid;
+       fstring keystr;
+       TDB_DATA key2;
+
+       p = strchr(key.dptr, '/');
+       if (!p) return 0;
+
+       *p++ = 0;
+       dom_name = key.dptr;
+
+       domain = find_domain_from_name(dom_name);
+       if (!domain) {
+               /* what do we do about this?? */
+               return 0;
+       }
+
+       rid = atoi(p);
+
+       sid_copy(&sid, &domain->sid);
+       sid_append_rid(&sid, rid);
+
+       sid_to_string(keystr, &sid);
+       key2.dptr = keystr;
+       key2.dsize = strlen(keystr) + 1;
+
+       if (tdb_store(idmap_tdb, key2, data, TDB_INSERT) != 0) {
+               /* not good! */
+               return 0;
+       }
+
+       tdb_delete(idmap_tdb, key);
+
+       return 0;
+}
+
+/* convert the idmap database from an older version */
+static BOOL idmap_convert(void)
+{
+       if (tdb_fetch_int(idmap_tdb, "IDMAP_VERSION") == IDMAP_VERSION) {
+               return True;
+       }
+
+       /* the old format stored as DOMAIN/rid - now we store the SID direct */
+       tdb_traverse(idmap_tdb, convert_fn, NULL);
+
+        if (tdb_store_int(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == -1) {
+               return False;
+       }
+
+       return True;
+}
+
+
 /* Initialise idmap database */
 
 BOOL winbindd_idmap_init(void)
@@ -220,6 +311,11 @@ BOOL winbindd_idmap_init(void)
         return False;
     }
 
+    /* possibly convert from an earlier version */
+    if (!idmap_convert()) {
+           return False;
+    }
+
      /* Create high water marks for group and user id */
 
     if (tdb_fetch_int(idmap_tdb, HWM_USER) == -1) {
index 5d1081c7196cadbb176956a3d3627272482345f1..14edbfdd445a0dc92e41d2a3595ed910f4d331dd 100644 (file)
@@ -49,12 +49,13 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state);
 
 /* The following definitions come from nsswitch/winbindd_idmap.c  */
 
-BOOL winbindd_idmap_get_uid_from_rid(char *domain_name, uint32 user_rid, 
-                                     uid_t *uid);
-BOOL winbindd_idmap_get_gid_from_rid(char *domain_name, uint32 group_rid, 
-                                     gid_t *gid);
-BOOL get_rid_from_id(int id, uint32 *rid, struct winbindd_domain **domain,
-                     BOOL isgroup);
+BOOL winbindd_idmap_get_uid_from_sid(DOM_SID *sid, uid_t *uid);
+BOOL winbindd_idmap_get_gid_from_sid(DOM_SID *sid, gid_t *gid);
+BOOL winbindd_idmap_get_uid_from_rid(const char *dom_name, uint32 rid, uid_t *uid);
+BOOL winbindd_idmap_get_gid_from_rid(const char *dom_name, uint32 rid, gid_t *gid);
+BOOL get_sid_from_id(int id, DOM_SID *sid, BOOL isgroup);
+BOOL winbindd_idmap_get_sid_from_uid(uid_t uid, DOM_SID *sid);
+BOOL winbindd_idmap_get_sid_from_gid(gid_t gid, DOM_SID *sid);
 BOOL winbindd_idmap_get_rid_from_uid(uid_t uid, uint32 *user_rid,
                                      struct winbindd_domain **domain);
 BOOL winbindd_idmap_get_rid_from_gid(gid_t gid, uint32 *group_rid, 
@@ -107,7 +108,7 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state);
 struct winbindd_domain *domain_list(void);
 void free_domain_list(void);
 BOOL init_domain_list(void);
-struct winbindd_domain *find_domain_from_name(char *domain_name);
+struct winbindd_domain *find_domain_from_name(const char *domain_name);
 struct winbindd_domain *find_domain_from_sid(DOM_SID *sid);
 BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain, 
                                 const char *name, DOM_SID *sid, 
index 8153b3a3a5d0f0041ea42eedf42f028cf529f52d..227ce439d51bb620ed50cd935591e14c719d97cb 100644 (file)
@@ -103,31 +103,19 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state)
 enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
 {
        DOM_SID sid;
-       uint32 user_rid;
-       struct winbindd_domain *domain;
 
        DEBUG(3, ("[%5d]: sid to uid %s\n", state->pid,
                  state->request.data.sid));
 
        /* Split sid into domain sid and user rid */
-
-       string_to_sid(&sid, state->request.data.sid);
-       sid_split_rid(&sid, &user_rid);
-
-       /* Find domain this sid belongs to */
-
-       if ((domain = find_domain_from_sid(&sid)) == NULL) {
-               fstring sid_str;
-
-               sid_to_string(sid_str, &sid);
-               DEBUG(1, ("Could not find domain for sid %s\n", sid_str));
+       if (!string_to_sid(&sid, state->request.data.sid)) {
+               DEBUG(1, ("Could not get convert sid %s from string\n",
+                         state->request.data.sid));
                return WINBINDD_ERROR;
        }
 
        /* Find uid for this sid and return it */
-
-       if (!winbindd_idmap_get_uid_from_rid(domain->name, user_rid,
-                                            &state->response.data.uid)) {
+       if (!winbindd_idmap_get_uid_from_sid(&sid, &state->response.data.uid)) {
                DEBUG(1, ("Could not get uid for sid %s\n",
                          state->request.data.sid));
                return WINBINDD_ERROR;
@@ -142,31 +130,18 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
 enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
 {
        DOM_SID sid;
-       uint32 group_rid;
-       struct winbindd_domain *domain;
 
        DEBUG(3, ("[%5d]: sid to gid %s\n", state->pid, 
                  state->request.data.sid));
 
-       /* Split sid into domain sid and user rid */
-
-       string_to_sid(&sid, state->request.data.sid);
-       sid_split_rid(&sid, &group_rid);
-
-       /* Find domain this sid belongs to */
-
-       if ((domain = find_domain_from_sid(&sid)) == NULL) {
-               fstring sid_str;
-
-               sid_to_string(sid_str, &sid);
-               DEBUG(1, ("Could not find domain for sid %s\n", sid_str));
+       if (!string_to_sid(&sid, state->request.data.sid)) {
+               DEBUG(1, ("Could not cvt string to sid %s\n",
+                         state->request.data.sid));
                return WINBINDD_ERROR;
        }
 
-       /* Find uid for this sid and return it */
-
-       if (!winbindd_idmap_get_gid_from_rid(domain->name, group_rid,
-                                            &state->response.data.gid)) {
+       /* Find gid for this sid and return it */
+       if (!winbindd_idmap_get_gid_from_sid(&sid, &state->response.data.gid)) {
                DEBUG(1, ("Could not get gid for sid %s\n",
                          state->request.data.sid));
                return WINBINDD_ERROR;
@@ -179,8 +154,6 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
 
 enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state)
 {
-       struct winbindd_domain *domain;
-       uint32 user_rid;
        DOM_SID sid;
 
        /* Bug out if the uid isn't in the winbind range */
@@ -194,18 +167,12 @@ enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state)
                  state->request.data.uid));
 
        /* Lookup rid for this uid */
-
-       if (!winbindd_idmap_get_rid_from_uid(state->request.data.uid,
-                                            &user_rid, &domain)) {
+       if (!winbindd_idmap_get_sid_from_uid(state->request.data.uid, &sid)) {
                DEBUG(1, ("Could not convert uid %d to rid\n",
                          state->request.data.uid));
                return WINBINDD_ERROR;
        }
 
-       /* Construct sid and return it */
-
-       sid_copy(&sid, &domain->sid);
-       sid_append_rid(&sid, user_rid);
        sid_to_string(state->response.data.sid.sid, &sid);
        state->response.data.sid.type = SID_NAME_USER;
 
@@ -216,8 +183,6 @@ enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state)
 
 enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state)
 {
-       struct winbindd_domain *domain;
-       uint32 group_rid;
        DOM_SID sid;
 
        /* Bug out if the gid isn't in the winbind range */
@@ -230,19 +195,14 @@ enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state)
        DEBUG(3, ("[%5d]: gid to sid %d\n", state->pid,
                  state->request.data.gid));
 
-       /* Lookup rid for this uid */
-
-       if (!winbindd_idmap_get_rid_from_gid(state->request.data.gid,
-                                            &group_rid, &domain)) {
-               DEBUG(1, ("Could not convert gid %d to rid\n",
+       /* Lookup sid for this uid */
+       if (!winbindd_idmap_get_sid_from_gid(state->request.data.gid, &sid)) {
+               DEBUG(1, ("Could not convert gid %d to sid\n",
                          state->request.data.gid));
                return WINBINDD_ERROR;
        }
 
        /* Construct sid and return it */
-
-       sid_copy(&sid, &domain->sid);
-       sid_append_rid(&sid, group_rid);
        sid_to_string(state->response.data.sid.sid, &sid);
        state->response.data.sid.type = SID_NAME_DOM_GRP;
 
index 48c756712d7148c43609bcaaa16fd74f8c381b21..e274c78220786dd51f7403c77e38f14ce43205ee 100644 (file)
@@ -178,7 +178,7 @@ BOOL init_domain_list(void)
 /* Given a domain name, return the struct winbindd domain info for it 
    if it is actually working. */
 
-struct winbindd_domain *find_domain_from_name(char *domain_name)
+struct winbindd_domain *find_domain_from_name(const char *domain_name)
 {
        struct winbindd_domain *domain;
 
index 3a939e4fceb78887c61ab7c4897a968e4548a93f..f2b3bdbe6c505fad7048cdf0975961358a608ea1 100644 (file)
@@ -596,6 +596,11 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype)
 
        *sidtype = SID_NAME_UNKNOWN;
 
+
+/* (tridge) I commented out the slab of code below in order to support foreign SIDs
+   Do we really need to validate the type of SID we have in this case? 
+*/
+#if 0
        /*
         * First we must look up the name and decide if this is a user sid.
         */
@@ -616,7 +621,7 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype)
                                (unsigned int)name_type ));
                return False;
        }
-
+#endif
        *sidtype = SID_NAME_USER;
 
        /*
@@ -658,7 +663,13 @@ BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype)
                DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n",
                                sid_to_string(sid_str, psid) ));
 
-               return local_sid_to_gid(pgid, psid, sidtype);
+               if (!local_sid_to_gid(pgid, psid, sidtype)) {
+                       /* this was probably a foreign sid - assume its a group rid 
+                          and continue */
+                       name_type = SID_NAME_DOM_GRP;
+               } else {
+                       return True;
+               }
        }
 
        /*