r4703: Add support for EnumTrustDomain, and expand the testsuite.
authorAndrew Bartlett <abartlet@samba.org>
Wed, 12 Jan 2005 07:57:33 +0000 (07:57 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:08:45 +0000 (13:08 -0500)
Add my copyright to the SAMR server.

Andrew Bartlett

source/librpc/idl/lsa.idl
source/rpc_server/lsa/dcesrv_lsa.c
source/rpc_server/samr/dcesrv_samr.c
source/torture/rpc/lsa.c

index 8aeb40b3bc5ce686cebd21f0a9a833181e04bcb9..9ed8756016f97ab853dcaa0edf28f7d7d0f64bb4 100644 (file)
        /******************/
        /* Function: 0x0d */
 
+       /* w2k3 treats max_size as max_domains*60       */
+       const int LSA_ENUM_TRUST_DOMAIN_MULTIPLIER = 60;
+
        typedef struct {
                lsa_String name;
                dom_sid2 *sid;
        NTSTATUS lsa_EnumTrustDom (
                [in,ref]     policy_handle *handle,
                [in,out,ref] uint32 *resume_handle,
-               [in,range(0,1000)] uint32 num_entries,
+               [in,range(0,1000)] uint32 max_size,
                [out,ref]    lsa_DomainList *domains
                );
 
index 2ea4d8aa25224335902f9d92f62ba06205f905b8..6ea8d4b78c6aab11bff5774469409961c068a74b 100644 (file)
@@ -627,7 +627,7 @@ static NTSTATUS lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALL
                        return NT_STATUS_NO_MEMORY;
                }
                        
-               samdb_msg_add_string(trusted_domain_state->policy->sam_ctx, mem_ctx, msg, "securityIdentifier", name);
+               samdb_msg_add_string(trusted_domain_state->policy->sam_ctx, mem_ctx, msg, "securityIdentifier", sid_string);
        }
 
        /* pull in all the template attributes.  Note this is always from the global samdb */
@@ -761,11 +761,12 @@ static NTSTATUS lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
        if (!trusted_domain_state) {
                return NT_STATUS_NO_MEMORY;
        }
+       trusted_domain_state->policy = policy_state;
 
        /* search for the trusted_domain record */
        ret = samdb_search(trusted_domain_state->policy->sam_ctx,
                           mem_ctx, policy_state->system_dn, &msgs, attrs,
-                          "(&(cn=%s)(objectclass=trustedDomain))", 
+                          "(&(flatname=%s)(objectclass=trustedDomain))", 
                           r->in.name.string);
        if (ret == 0) {
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
@@ -818,7 +819,7 @@ static NTSTATUS lsa_SetTrustDomainInfo(struct dcesrv_call_state *dce_call, TALLO
   lsa_DeleteTrustDomain
 */
 static NTSTATUS lsa_DeleteTrustDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_DeleteTrustDomain *r)
+                                     struct lsa_DeleteTrustDomain *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
@@ -885,13 +886,88 @@ static NTSTATUS lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
 }
 
 
+/*
+  comparison function for sorting lsa_DomainInformation array
+*/
+static int compare_DomainInformation(struct lsa_DomainInformation *e1, struct lsa_DomainInformation *e2)
+{
+       return strcasecmp(e1->name.string, e2->name.string);
+}
+
 /* 
   lsa_EnumTrustDom 
 */
 static NTSTATUS lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_EnumTrustDom *r)
+                                struct lsa_EnumTrustDom *r)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       struct dcesrv_handle *policy_handle;
+       struct lsa_DomainInformation *entries;
+       struct lsa_policy_state *policy_state;
+       struct ldb_message **domains;
+       const char *attrs[] = {
+               "flatname", 
+               "securityIdentifier",
+               NULL
+       };
+
+
+       int count, i;
+
+       *r->out.resume_handle = 0;
+
+       r->out.domains->domains = NULL;
+       r->out.domains->count = 0;
+
+       DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
+
+       policy_state = policy_handle->data;
+
+       /* search for all users in this domain. This could possibly be cached and 
+          resumed based on resume_key */
+       count = samdb_search(policy_state->sam_ctx, mem_ctx, policy_state->system_dn, &domains, attrs, 
+                            "objectclass=trustedDomain");
+       if (count == -1) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+       if (count == 0 || r->in.max_size == 0) {
+               return NT_STATUS_OK;
+       }
+
+       /* convert to lsa_DomainInformation format */
+       entries = talloc_array_p(mem_ctx, struct lsa_DomainInformation, count);
+       if (!entries) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       for (i=0;i<count;i++) {
+               entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
+               entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
+       }
+
+       /* sort the results by name */
+       qsort(entries, count, sizeof(struct lsa_DomainInformation), 
+             (comparison_fn_t)compare_DomainInformation);
+
+       if (*r->in.resume_handle >= count) {
+               *r->out.resume_handle = -1;
+
+               return NT_STATUS_NO_MORE_ENTRIES;
+       }
+
+       /* return the rest, limit by max_size. Note that we 
+          use the w2k3 element size value of 60 */
+       r->out.domains->count = count - *r->in.resume_handle;
+       r->out.domains->count = MIN(r->out.domains->count, 
+                                1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
+
+       r->out.domains->domains = entries + *r->in.resume_handle;
+       r->out.domains->count = r->out.domains->count;
+
+       if (r->out.domains->count < count - *r->in.resume_handle) {
+               *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
+               return STATUS_MORE_ENTRIES;
+       }
+
+       return NT_STATUS_OK;
 }
 
 
index 7cbe63056a66cf793a4102e00f73430c8b3ffde0..c3ec8bf80f55850fd1eaf14570d177fde7ec7ba6 100644 (file)
@@ -5,6 +5,7 @@
 
    Copyright (C) Andrew Tridgell 2004
    Copyright (C) Volker Lendecke 2004
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
index 5bb282a033002b57abdb0f7c79bc526282522d11..2c802ea5deb3e17f8c4109883822f09cf5688aa5 100644 (file)
@@ -557,7 +557,7 @@ static BOOL test_Delete(struct dcerpc_pipe *p,
        NTSTATUS status;
        struct lsa_Delete r;
 
-       printf("\ntesting Delete\n");
+       printf("testing Delete\n");
 
        r.in.handle = handle;
        status = dcerpc_lsa_Delete(p, mem_ctx, &r);
@@ -566,8 +566,6 @@ static BOOL test_Delete(struct dcerpc_pipe *p,
                return False;
        }
 
-       printf("\n");
-
        return True;
 }
 
@@ -1235,90 +1233,68 @@ static BOOL test_EnumPrivs(struct dcerpc_pipe *p,
        return ret;
 }
 
-
-static BOOL test_EnumTrustDom(struct dcerpc_pipe *p
-                             TALLOC_CTX *mem_ctx
-                             struct policy_handle *handle)
+static BOOL test_query_each_TrustDom(struct dcerpc_pipe *p, 
+                                    TALLOC_CTX *mem_ctx
+                                    struct policy_handle *handle
+                                    struct lsa_DomainList *domains) 
 {
-       struct lsa_EnumTrustDom r;
        NTSTATUS status;
-       uint32_t resume_handle = 0;
-       struct lsa_DomainList domains;
        int i,j;
        BOOL ret = True;
-
-       printf("\nTesting EnumTrustDom\n");
-
-       r.in.handle = handle;
-       r.in.resume_handle = &resume_handle;
-       r.in.num_entries = 100;
-       r.out.domains = &domains;
-       r.out.resume_handle = &resume_handle;
-
-       status = dcerpc_lsa_EnumTrustDom(p, mem_ctx, &r);
-
-       /* NO_MORE_ENTRIES is allowed */
-       if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) {
-               return True;
-       }
-
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("EnumTrustDom failed - %s\n", nt_errstr(status));
-               return False;
-       }
-
+               
        printf("\nTesting OpenTrustedDomain, OpenTrustedDomainByName and QueryInfoTrustedDomain\n");
-
-       for (i=0; i< domains.count; i++) {
+       for (i=0; i< domains->count; i++) {
                struct lsa_OpenTrustedDomain trust;
                struct lsa_OpenTrustedDomainByName trust_by_name;
                struct policy_handle trustdom_handle;
                struct policy_handle handle2;
                struct lsa_Close c;
                int levels [] = {1, 3, 6, 8, 12};
-               
-               trust.in.handle = handle;
-               trust.in.sid = domains.domains[i].sid;
-               trust.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
-               trust.out.trustdom_handle = &trustdom_handle;
-
-               status = dcerpc_lsa_OpenTrustedDomain(p, mem_ctx, &trust);
-
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("OpenTrustedDomain failed - %s\n", nt_errstr(status));
-                       return False;
-               }
-
-               c.in.handle = &trustdom_handle;
-               c.out.handle = &handle2;
-               
-               for (j=0; j < ARRAY_SIZE(levels); j++) {
-                       struct lsa_QueryTrustedDomainInfo q;
-                       union lsa_TrustedDomainInfo info;
-                       q.in.trustdom_handle = &trustdom_handle;
-                       q.in.level = levels[j];
-                       q.out.info = &info;
-                       status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q);
+                       
+               if (domains->domains[i].sid) {
+                       trust.in.handle = handle;
+                       trust.in.sid = domains->domains[i].sid;
+                       trust.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+                       trust.out.trustdom_handle = &trustdom_handle;
+                       
+                       status = dcerpc_lsa_OpenTrustedDomain(p, mem_ctx, &trust);
+                       
                        if (!NT_STATUS_IS_OK(status)) {
-                               printf("QueryTrustedDomainInfo level %d failed - %s\n", 
-                                      levels[j], nt_errstr(status));
-                               ret = False;
+                               printf("OpenTrustedDomain failed - %s\n", nt_errstr(status));
+                               return False;
+                       }
+                       
+                       c.in.handle = &trustdom_handle;
+                       c.out.handle = &handle2;
+                       
+                       for (j=0; j < ARRAY_SIZE(levels); j++) {
+                               struct lsa_QueryTrustedDomainInfo q;
+                               union lsa_TrustedDomainInfo info;
+                               q.in.trustdom_handle = &trustdom_handle;
+                               q.in.level = levels[j];
+                               q.out.info = &info;
+                               status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       printf("QueryTrustedDomainInfo level %d failed - %s\n", 
+                                              levels[j], nt_errstr(status));
+                                       ret = False;
+                               }
+                       }
+                       
+                       status = dcerpc_lsa_Close(p, mem_ctx, &c);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               printf("Close of trusted domain failed - %s\n", nt_errstr(status));
+                               return False;
                        }
-               }
-               
-               status = dcerpc_lsa_Close(p, mem_ctx, &c);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("Close of trusted domain failed - %s\n", nt_errstr(status));
-                       return False;
                }
 
                trust_by_name.in.handle = handle;
-               trust_by_name.in.name = domains.domains[i].name;
+               trust_by_name.in.name = domains->domains[i].name;
                trust_by_name.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
                trust_by_name.out.trustdom_handle = &trustdom_handle;
-               
+                       
                status = dcerpc_lsa_OpenTrustedDomainByName(p, mem_ctx, &trust_by_name);
-
+                       
                if (!NT_STATUS_IS_OK(status)) {
                        printf("OpenTrustedDomainByName failed - %s\n", nt_errstr(status));
                        return False;
@@ -1350,8 +1326,13 @@ static BOOL test_EnumTrustDom(struct dcerpc_pipe *p,
                for (j=0; j < ARRAY_SIZE(levels); j++) {
                        struct lsa_QueryTrustedDomainInfoBySid q;
                        union lsa_TrustedDomainInfo info;
+
+                       if (!domains->domains[i].sid) {
+                               continue;
+                       }
+
                        q.in.handle  = handle;
-                       q.in.dom_sid = domains.domains[i].sid;
+                       q.in.dom_sid = domains->domains[i].sid;
                        q.in.level   = levels[j];
                        q.out.info   = &info;
                        status = dcerpc_lsa_QueryTrustedDomainInfoBySid(p, mem_ctx, &q);
@@ -1366,7 +1347,7 @@ static BOOL test_EnumTrustDom(struct dcerpc_pipe *p,
                        struct lsa_QueryTrustedDomainInfoByName q;
                        union lsa_TrustedDomainInfo info;
                        q.in.handle         = handle;
-                       q.in.trusted_domain = domains.domains[i].name;
+                       q.in.trusted_domain = domains->domains[i].name;
                        q.in.level          = levels[j];
                        q.out.info          = &info;
                        status = dcerpc_lsa_QueryTrustedDomainInfoByName(p, mem_ctx, &q);
@@ -1376,10 +1357,51 @@ static BOOL test_EnumTrustDom(struct dcerpc_pipe *p,
                                ret = False;
                        }
                }
+       }
+       return ret;
+}
+
+static BOOL test_EnumTrustDom(struct dcerpc_pipe *p, 
+                             TALLOC_CTX *mem_ctx, 
+                             struct policy_handle *handle)
+{
+       struct lsa_EnumTrustDom r;
+       NTSTATUS enum_status;
+       uint32_t resume_handle = 0;
+       struct lsa_DomainList domains;
+       BOOL ret = True;
+
+       printf("\nTesting EnumTrustDom\n");
+
+       do {
+               r.in.handle = handle;
+               r.in.resume_handle = &resume_handle;
+               r.in.max_size = LSA_ENUM_TRUST_DOMAIN_MULTIPLIER * 3;
+               r.out.domains = &domains;
+               r.out.resume_handle = &resume_handle;
+               
+               enum_status = dcerpc_lsa_EnumTrustDom(p, mem_ctx, &r);
                
+               /* NO_MORE_ENTRIES is allowed */
+               if (NT_STATUS_EQUAL(enum_status, NT_STATUS_NO_MORE_ENTRIES)) {
+                       return True;
+               } else if (NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES)) {
+                       /* Windows 2003 gets this off by one on the first run */
+                       if (r.out.domains->count < 3 || r.out.domains->count > 4) {
+                               printf("EnumTrustDom didn't fill the buffer we "
+                                      "asked it to (got %d, expected %d / %d == %d entries)\n",
+                                      r.out.domains->count, LSA_ENUM_TRUST_DOMAIN_MULTIPLIER * 3, 
+                                      LSA_ENUM_TRUST_DOMAIN_MULTIPLIER, r.in.max_size);
+                               ret = False;
+                       }
+               } else if (!NT_STATUS_IS_OK(enum_status)) {
+                       printf("EnumTrustDom failed - %s\n", nt_errstr(enum_status));
+                       return False;
+               }
                
+               ret &= test_query_each_TrustDom(p, mem_ctx, handle, &domains);
 
-       }
+       } while ((NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES)));
 
        return ret;
 }
@@ -1392,46 +1414,52 @@ static BOOL test_CreateTrustedDomain(struct dcerpc_pipe *p,
        BOOL ret = True;
        struct lsa_CreateTrustedDomain r;
        struct lsa_TrustInformation trustinfo;
-       struct dom_sid *domsid;
-       struct policy_handle trustdom_handle;
+       struct dom_sid *domsid[12];
+       struct policy_handle trustdom_handle[12];
        struct lsa_QueryTrustedDomainInfo q;
+       int i;
 
-       printf("Testing CreateTrustedDomain\n");
-
-       domsid = dom_sid_parse_talloc(mem_ctx, "S-1-5-21-97398-379795-12345");
+       printf("Testing CreateTrustedDomain for 12 domains\n");
 
-       trustinfo.sid = domsid;
-       init_lsa_String(&trustinfo.name, "torturedomain");
+       for (i=0; i< 12; i++) {
+               char *trust_name = talloc_asprintf(mem_ctx, "torturedom%02d", i);
+               char *trust_sid = talloc_asprintf(mem_ctx, "S-1-5-21-97398-379795-100%02d", i);
+               
+               domsid[i] = dom_sid_parse_talloc(mem_ctx, trust_sid);
 
-       r.in.handle = handle;
-       r.in.info = &trustinfo;
-       r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
-       r.out.trustdom_handle = &trustdom_handle;
+               trustinfo.sid = domsid[i];
+               init_lsa_String(&trustinfo.name, trust_name);
 
-       status = dcerpc_lsa_CreateTrustedDomain(p, mem_ctx, &r);
-       if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
-               test_DeleteTrustedDomain(p, mem_ctx, handle, trustinfo.name);
+               r.in.handle = handle;
+               r.in.info = &trustinfo;
+               r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+               r.out.trustdom_handle = &trustdom_handle[i];
+               
                status = dcerpc_lsa_CreateTrustedDomain(p, mem_ctx, &r);
-       }
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("CreateTrustedDomain failed - %s\n", nt_errstr(status));
-               return False;
-       }
-
-       q.in.trustdom_handle = &trustdom_handle;
-       q.in.level = LSA_TRUSTED_DOMAIN_INFO_NAME;
-       status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("QueryTrustedDomainInfo level 1 failed - %s\n", nt_errstr(status));
-               ret = False;
-       }
-       if (!q.out.info) {
-               ret = False;
-       } else {
-               if (strcmp(q.out.info->name.netbios_name.string, trustinfo.name.string) != 0) {
-                       printf("QueryTrustedDomainInfo returned inconsistant short name: %s != %s\n",
-                              q.out.info->name.netbios_name.string, trustinfo.name.string);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
+                       test_DeleteTrustedDomain(p, mem_ctx, handle, trustinfo.name);
+                       status = dcerpc_lsa_CreateTrustedDomain(p, mem_ctx, &r);
+               }
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("CreateTrustedDomain failed - %s\n", nt_errstr(status));
                        ret = False;
+               } else {
+               
+                       q.in.trustdom_handle = &trustdom_handle[i];
+                       q.in.level = LSA_TRUSTED_DOMAIN_INFO_NAME;
+                       status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               printf("QueryTrustedDomainInfo level 1 failed - %s\n", nt_errstr(status));
+                               ret = False;
+                       } else if (!q.out.info) {
+                               ret = False;
+                       } else {
+                               if (strcmp(q.out.info->name.netbios_name.string, trustinfo.name.string) != 0) {
+                                       printf("QueryTrustedDomainInfo returned inconsistant short name: %s != %s\n",
+                                              q.out.info->name.netbios_name.string, trustinfo.name.string);
+                                       ret = False;
+                               }
+                       }
                }
        }
 
@@ -1439,9 +1467,11 @@ static BOOL test_CreateTrustedDomain(struct dcerpc_pipe *p,
        if (!test_EnumTrustDom(p, mem_ctx, handle)) {
                ret = False;
        }
-
-       if (!test_Delete(p, mem_ctx, &trustdom_handle)) {
-               ret = False;
+       
+       for (i=0; i<12; i++) {
+               if (!test_Delete(p, mem_ctx, &trustdom_handle[i])) {
+                       ret = False;
+               }
        }
 
        return ret;