Fix bug #7669.
[metze/samba/wip.git] / source3 / lib / util_sid.c
index e27c72dbc4cb88234fdd10631dcbbc3701ecdc45..130e257bdd3858d45021023bf1df1c186274c7cb 100644 (file)
@@ -172,62 +172,42 @@ const char *get_global_sam_name(void)
  Convert a SID to an ascii string.
 *****************************************************************/
 
-char *sid_to_string(fstring sidstr_out, const DOM_SID *sid)
+char *sid_to_fstring(fstring sidstr_out, const DOM_SID *sid)
 {
-       char subauth[16];
-       int i;
-       uint32 ia;
-  
-       if (!sid) {
-               fstrcpy(sidstr_out, "(NULL SID)");
-               return sidstr_out;
-       }
-
-       /*
-        * BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 
-        * in a range of 2^48.
-        */
-       ia = (sid->id_auth[5]) +
-               (sid->id_auth[4] << 8 ) +
-               (sid->id_auth[3] << 16) +
-               (sid->id_auth[2] << 24);
-
-       slprintf(sidstr_out, sizeof(fstring) - 1, "S-%u-%lu", (unsigned int)sid->sid_rev_num, (unsigned long)ia);
-
-       for (i = 0; i < sid->num_auths; i++) {
-               slprintf(subauth, sizeof(subauth)-1, "-%lu", (unsigned long)sid->sub_auths[i]);
-               fstrcat(sidstr_out, subauth);
-       }
-
+       char *str = sid_string_talloc(talloc_tos(), sid);
+       fstrcpy(sidstr_out, str);
+       TALLOC_FREE(str);
        return sidstr_out;
 }
 
 /*****************************************************************
- Useful function for debug lines.
-*****************************************************************/  
+ Essentially a renamed dom_sid_string from librpc/ndr with a
+ panic if it didn't work
 
-const char *sid_string_static(const DOM_SID *sid)
-{
-       static fstring sid_str;
-       sid_to_string(sid_str, sid);
-       return sid_str;
-}
+ This introduces a dependency on librpc/ndr/sid.o which can easily
+ be turned around if necessary
+*****************************************************************/
 
 char *sid_string_talloc(TALLOC_CTX *mem_ctx, const DOM_SID *sid)
 {
-       fstring sid_str;
-       char *result;
-       sid_to_string(sid_str, sid);
-       result = talloc_strdup(mem_ctx, sid_str);
+       char *result = dom_sid_string(mem_ctx, sid);
        SMB_ASSERT(result != NULL);
        return result;
 }
 
+/*****************************************************************
+ Useful function for debug lines.
+*****************************************************************/
+
 char *sid_string_dbg(const DOM_SID *sid)
 {
        return sid_string_talloc(debug_ctx(), sid);
 }
 
+/*****************************************************************
+ Use with care!
+*****************************************************************/
+
 char *sid_string_tos(const DOM_SID *sid)
 {
        return sid_string_talloc(talloc_tos(), sid);
@@ -402,7 +382,7 @@ bool sid_linearize(char *outbuf, size_t len, const DOM_SID *sid)
 {
        size_t i;
 
-       if (len < sid_size(sid))
+       if (len < ndr_size_dom_sid(sid, NULL, 0))
                return False;
 
        SCVAL(outbuf,0,sid->sid_rev_num);
@@ -428,6 +408,9 @@ bool sid_parse(const char *inbuf, size_t len, DOM_SID *sid)
 
        sid->sid_rev_num = CVAL(inbuf, 0);
        sid->num_auths = CVAL(inbuf, 1);
+       if (sid->num_auths > MAXSUBAUTHS) {
+               return false;
+       }
        memcpy(sid->id_auth, inbuf+2, 6);
        if (len < 8 + sid->num_auths*4)
                return False;
@@ -487,6 +470,35 @@ int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2)
        return sid_compare_auth(sid1, sid2);
 }
 
+int sid_compare_sort(const void *p1, const void *p2)
+{
+       const struct dom_sid *sid1 = (const struct dom_sid *)p1;
+       const struct dom_sid *sid2 = (const struct dom_sid *)p2;
+       int i, res;
+
+       if (sid1->sid_rev_num != sid2->sid_rev_num) {
+               return sid1->sid_rev_num - sid2->sid_rev_num;
+       }
+
+       for (i = 0; i < 6; i++) {
+               if (sid1->id_auth[i] != sid2->id_auth[i]) {
+                       return sid1->id_auth[i] - sid2->id_auth[i];
+               }
+       }
+
+       if (sid1->num_auths != sid2->num_auths) {
+               return sid1->num_auths - sid2->num_auths;
+       }
+
+       for (i = 0; i<sid1->num_auths; i++) {
+               if (sid1->sub_auths[i] != sid2->sub_auths[i]) {
+                       return sid1->sub_auths[i] - sid2->sub_auths[i];
+               }
+       }
+
+       return 0;
+}
+
 /*****************************************************************
  See if 2 SIDs are in the same domain
  this just compares the leading sub-auths
@@ -514,18 +526,6 @@ bool sid_equal(const DOM_SID *sid1, const DOM_SID *sid2)
        return sid_compare(sid1, sid2) == 0;
 }
 
-/*****************************************************************
- Calculates size of a sid.
-*****************************************************************/  
-
-size_t sid_size(const DOM_SID *sid)
-{
-       if (sid == NULL)
-               return 0;
-
-       return sid->num_auths * sizeof(uint32) + 8;
-}
-
 /*****************************************************************
  Returns true if SID is internal (and non-mappable).
 *****************************************************************/
@@ -555,7 +555,7 @@ bool non_mappable_sid(DOM_SID *sid)
 char *sid_binstring(const DOM_SID *sid)
 {
        char *buf, *s;
-       int len = sid_size(sid);
+       int len = ndr_size_dom_sid(sid, NULL, 0);
        buf = (char *)SMB_MALLOC(len);
        if (!buf)
                return NULL;
@@ -573,7 +573,7 @@ char *sid_binstring(const DOM_SID *sid)
 char *sid_binstring_hex(const DOM_SID *sid)
 {
        char *buf, *s;
-       int len = sid_size(sid);
+       int len = ndr_size_dom_sid(sid, NULL, 0);
        buf = (char *)SMB_MALLOC(len);
        if (!buf)
                return NULL;
@@ -605,20 +605,20 @@ DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, const DOM_SID *src)
  Add SID to an array SIDs
 ********************************************************************/
 
-bool add_sid_to_array(TALLOC_CTX *mem_ctx, const DOM_SID *sid, 
-                     DOM_SID **sids, size_t *num)
+NTSTATUS add_sid_to_array(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
+                         DOM_SID **sids, size_t *num)
 {
        *sids = TALLOC_REALLOC_ARRAY(mem_ctx, *sids, DOM_SID,
                                             (*num)+1);
        if (*sids == NULL) {
                *num = 0;
-               return False;
+               return NT_STATUS_NO_MEMORY;
        }
 
        sid_copy(&((*sids)[*num]), sid);
        *num += 1;
 
-       return True;
+       return NT_STATUS_OK;
 }
 
 
@@ -626,14 +626,14 @@ bool add_sid_to_array(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
  Add SID to an array SIDs ensuring that it is not already there
 ********************************************************************/
 
-bool add_sid_to_array_unique(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
-                            DOM_SID **sids, size_t *num_sids)
+NTSTATUS add_sid_to_array_unique(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
+                                DOM_SID **sids, size_t *num_sids)
 {
        size_t i;
 
        for (i=0; i<(*num_sids); i++) {
                if (sid_compare(sid, &(*sids)[i]) == 0)
-                       return True;
+                       return NT_STATUS_OK;
        }
 
        return add_sid_to_array(mem_ctx, sid, sids, num_sids);
@@ -696,48 +696,73 @@ bool is_null_sid(const DOM_SID *sid)
        return sid_equal(sid, &null_sid);
 }
 
+bool is_sid_in_token(const NT_USER_TOKEN *token, const DOM_SID *sid)
+{
+        int i;
+
+        for (i=0; i<token->num_sids; i++) {
+                if (sid_compare(sid, &token->user_sids[i]) == 0)
+                        return true;
+        }
+        return false;
+}
+
 NTSTATUS sid_array_from_info3(TALLOC_CTX *mem_ctx,
-                             const NET_USER_INFO_3 *info3,
+                             const struct netr_SamInfo3 *info3,
                              DOM_SID **user_sids,
                              size_t *num_user_sids,
-                             bool include_user_group_rid)
+                             bool include_user_group_rid,
+                             bool skip_ressource_groups)
 {
+       NTSTATUS status;
        DOM_SID sid;
        DOM_SID *sid_array = NULL;
        size_t num_sids = 0;
        int i;
 
        if (include_user_group_rid) {
-
-               if (!sid_compose(&sid, &(info3->dom_sid.sid),
-                                info3->user_rid)
-                   || !add_sid_to_array(mem_ctx, &sid,
-                                        &sid_array, &num_sids)) {
-                       DEBUG(3,("could not add user SID from rid 0x%x\n",
-                                info3->user_rid));                     
+               if (!sid_compose(&sid, info3->base.domain_sid, info3->base.rid)) {
+                       DEBUG(3, ("could not compose user SID from rid 0x%x\n",
+                                 info3->base.rid));
                        return NT_STATUS_INVALID_PARAMETER;
                }
-
-               if (!sid_compose(&sid, &(info3->dom_sid.sid),
-                                info3->group_rid)
-                   || !add_sid_to_array(mem_ctx, &sid, 
-                                        &sid_array, &num_sids)) {
-                       DEBUG(3,("could not append additional group rid 0x%x\n",
-                                info3->group_rid));                    
-                       
-                       return NT_STATUS_INVALID_PARAMETER;
+               status = add_sid_to_array(mem_ctx, &sid, &sid_array, &num_sids);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(3, ("could not append user SID from rid 0x%x\n",
+                                 info3->base.rid));
+                       return status;
                }
        }
 
-       for (i = 0; i < info3->num_groups2; i++) {
-               if (!sid_compose(&sid, &(info3->dom_sid.sid),
-                                info3->gids[i].g_rid)
-                   || !add_sid_to_array(mem_ctx, &sid,
-                                        &sid_array, &num_sids)) {
-                       DEBUG(3,("could not append additional group rid 0x%x\n",
-                                info3->gids[i].g_rid));        
+       if (!sid_compose(&sid, info3->base.domain_sid, info3->base.primary_gid)) {
+               DEBUG(3, ("could not compose group SID from rid 0x%x\n",
+                         info3->base.primary_gid));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       status = add_sid_to_array(mem_ctx, &sid, &sid_array, &num_sids);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(3, ("could not append group SID from rid 0x%x\n",
+                         info3->base.rid));
+               return status;
+       }
+
+       for (i = 0; i < info3->base.groups.count; i++) {
+               /* Don't add the primary group sid twice. */
+               if (info3->base.primary_gid == info3->base.groups.rids[i].rid) {
+                       continue;
+               }
+               if (!sid_compose(&sid, info3->base.domain_sid,
+                                info3->base.groups.rids[i].rid)) {
+                       DEBUG(3, ("could not compose SID from additional group "
+                                 "rid 0x%x\n", info3->base.groups.rids[i].rid));
                        return NT_STATUS_INVALID_PARAMETER;
                }
+               status = add_sid_to_array(mem_ctx, &sid, &sid_array, &num_sids);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(3, ("could not append SID from additional group "
+                                 "rid 0x%x\n", info3->base.groups.rids[i].rid));
+                       return status;
+               }
        }
 
        /* Copy 'other' sids.  We need to do sid filtering here to
@@ -746,12 +771,19 @@ NTSTATUS sid_array_from_info3(TALLOC_CTX *mem_ctx,
            http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
          */
 
-       for (i = 0; i < info3->num_other_sids; i++) {
-               if (!add_sid_to_array(mem_ctx, &info3->other_sids[i].sid,
-                                     &sid_array, &num_sids)) {
+       for (i = 0; i < info3->sidcount; i++) {
+
+               if (skip_ressource_groups &&
+                   (info3->sids[i].attributes & SE_GROUP_RESOURCE)) {
+                       continue;
+               }
+
+               status = add_sid_to_array(mem_ctx, info3->sids[i].sid,
+                                     &sid_array, &num_sids);
+               if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(3, ("could not add SID to array: %s\n",
-                                 sid_string_dbg(&info3->other_sids[i].sid)));
-                       return NT_STATUS_NO_MEMORY;
+                                 sid_string_dbg(info3->sids[i].sid)));
+                       return status;
                }
        }