r17956: LSA Cleanup!
authorAndrew Bartlett <abartlet@samba.org>
Thu, 31 Aug 2006 08:22:13 +0000 (08:22 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:16:57 +0000 (14:16 -0500)
This commit cleans up a number of aspects of the LSA interface.

Firstly, we do 2 simple searches on opening the LSA policy, to obtain
the basic information we need.  This also avoids us searching for
dnsDomain (an invented attribute).

While I was at it, I added and tested new LSA calls, including the
enumTrustedDomainsEx call.  I have also merged the identical structures
lsa_DomainInformation and lsa_DomainList.

Also in this commit: Fix netlogon use of uninitialised variables.

Andrew Bartlett
(This used to be commit 3f3fa7f466df56612064029143fbae8effb668aa)

source4/librpc/idl/lsa.idl
source4/rpc_server/lsa/dcesrv_lsa.c
source4/rpc_server/netlogon/dcerpc_netlogon.c
source4/torture/rpc/lsa.c
source4/torture/rpc/netlogon.c
source4/winbind/wb_async_helpers.c

index 0953c6d02547ffa6b47ae902a432b784b99db94c..3c05ab2e935b2ee3a58668fd93206067b501b4ef 100644 (file)
        /*************************************************/
        /* Function: 0x0c                                */
 
-       typedef struct {
-               lsa_StringLarge name;
-               dom_sid2  *sid;
-       } lsa_TrustInformation;
-
        NTSTATUS lsa_CreateTrustedDomain(
                [in]         policy_handle *handle,
-               [in]         lsa_TrustInformation *info,
+               [in]         lsa_DomainInfo *info,
                [in]         uint32 access_mask,
                [out]        policy_handle *trustdom_handle
                );
        /* w2k3 treats max_size as max_domains*60       */
        const int LSA_ENUM_TRUST_DOMAIN_MULTIPLIER = 60;
 
-       typedef struct {
-               lsa_StringLarge name;
-               dom_sid2 *sid;
-       } lsa_DomainInformation;
-
        typedef struct {
                uint32 count;
-               [size_is(count)] lsa_DomainInformation *domains;
+               [size_is(count)] lsa_DomainInfo *domains;
        } lsa_DomainList;
 
        NTSTATUS lsa_EnumTrustDom (
                [size_is(count)] lsa_TranslatedSid *sids;
        } lsa_TransSidArray;
 
+       const int LSA_REF_DOMAIN_LIST_MULTIPLIER = 32;
        typedef struct {
                [range(0,1000)] uint32 count;
-               [size_is(count)] lsa_TrustInformation *domains;
-               uint32 max_count;
+               [size_is(count)] lsa_DomainInfo *domains;
+               uint32 max_size;
        } lsa_RefDomainList;
 
        NTSTATUS lsa_LookupNames (
         );
 
        /* Function:     0x28 */
-       NTSTATUS lsa_SetTrustDomainInfo();
+       NTSTATUS lsa_SetTrustedDomainInfo();
        /* Function:      0x29 */
-       NTSTATUS lsa_DeleteTrustDomain();
+       NTSTATUS lsa_DeleteTrustedDomain(
+               [in]               policy_handle         *handle,
+               [in]               dom_sid2              *dom_sid
+       );
+
        /* Function:       0x2a */
        NTSTATUS lsa_StorePrivateData();
        /* Function:        0x2b */
                [out,unique,switch_is(level)] lsa_TrustedDomainInfo *info
                );
 
+       /**********************/
        /* Function 0x31 */
-       NTSTATUS lsa_SetTrustedDomainInfoByName();
+       NTSTATUS lsa_SetTrustedDomainInfoByName(
+               [in]                   policy_handle         *handle,
+               [in]                   lsa_String             trusted_domain,
+               [in]                   lsa_TrustDomInfoEnum   level, 
+               [in,unique,switch_is(level)] lsa_TrustedDomainInfo *info
+               );
 
        /* Function 0x32 */
-       NTSTATUS lsa_EnumTrustedDomainsEx();
+
+       /* w2k3 treats max_size as max_domains*82       */
+       const int LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER = 82;
+
+       typedef struct {
+               uint32 count;
+               [size_is(count)] lsa_TrustDomainInfoInfoEx *domains;
+       } lsa_DomainListEx;
+
+       NTSTATUS lsa_EnumTrustedDomainsEx (
+               [in]               policy_handle *handle,
+               [in,out]           uint32 *resume_handle,
+               [out]              lsa_DomainListEx *domains,
+               [in]               uint32 max_size
+               );
+
 
        /* Function 0x33 */
        NTSTATUS lsa_CreateTrustedDomainEx();
 
        /* Function 0x34 */
-       NTSTATUS lsa_CloseTrustedDomainEx();
+       NTSTATUS lsa_CloseTrustedDomainEx(
+               [in,out]                   policy_handle         *handle
+       );
 
        /* Function 0x35 */
 
index 43bc91b14927e7a341d6b94d189087ca3f3a840c..5b3de2c22b2150a1749a47b30e0b06935bfafe21 100644 (file)
@@ -55,7 +55,9 @@ struct lsa_policy_state {
        const struct ldb_dn *builtin_dn;
        const struct ldb_dn *system_dn;
        const char *domain_name;
+       const char *domain_dns;
        struct dom_sid *domain_sid;
+       struct GUID domain_guid;
        struct dom_sid *builtin_sid;
 };
 
@@ -76,7 +78,7 @@ struct lsa_account_state {
 struct lsa_secret_state {
        struct lsa_policy_state *policy;
        uint32_t access_mask;
-       const struct ldb_dn *secret_dn;
+       struct ldb_dn *secret_dn;
        struct ldb_context *sam_ldb;
        BOOL global;
 };
@@ -268,6 +270,20 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_
 {
        struct lsa_policy_state *state;
        const struct ldb_dn *partitions_basedn;
+       struct ldb_result *dom_res;
+       const char *dom_attrs[] = {
+               "objectSid", 
+               "objectGUID", 
+               NULL
+       };
+       struct ldb_result *ref_res;
+       const char *ref_attrs[] = {
+               "nETBIOSName",
+               "dnsRoot",
+               NULL
+       };
+       char *ref_filter;
+       int ret;
 
        state = talloc(mem_ctx, struct lsa_policy_state);
        if (!state) {
@@ -294,15 +310,59 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_
                return NT_STATUS_NO_MEMORY;             
        }
 
-       state->domain_name
-               = samdb_search_string(state->sam_ldb, state, partitions_basedn, "nETBIOSName", 
-                                     "(&(objectclass=crossRef)(ncName=%s))", ldb_dn_linearize(mem_ctx, state->domain_dn));
+       ret = ldb_search(state->sam_ldb, state->domain_dn, LDB_SCOPE_BASE, NULL, dom_attrs, &dom_res);
        
+       if (ret != LDB_SUCCESS) {
+               return NT_STATUS_INVALID_SYSTEM_SERVICE;
+       }
+       talloc_steal(state, dom_res);
+       if (dom_res->count != 1) {
+               return NT_STATUS_NO_SUCH_DOMAIN;                
+       }
+
+       state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
+       if (!state->domain_sid) {
+               return NT_STATUS_NO_SUCH_DOMAIN;                
+       }
+
+       state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
+       if (!state->domain_sid) {
+               return NT_STATUS_NO_SUCH_DOMAIN;                
+       }
+
+       talloc_free(dom_res);
+
+       ref_filter = talloc_asprintf(state, "(&(objectclass=crossRef)(ncName=%s))", 
+                                    ldb_dn_linearize(mem_ctx, state->domain_dn)); 
+       if (!ref_filter) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       ret = ldb_search(state->sam_ldb, partitions_basedn, LDB_SCOPE_SUBTREE, ref_filter, ref_attrs, &ref_res);
+       talloc_steal(state, ref_res);
+       talloc_free(ref_filter);
+       
+       if (ret != LDB_SUCCESS) {
+               return NT_STATUS_INVALID_SYSTEM_SERVICE;
+       }
+       if (ref_res->count != 1) {
+               return NT_STATUS_NO_SUCH_DOMAIN;                
+       }
+
+       state->domain_name = ldb_msg_find_attr_as_string(ref_res->msgs[0], "nETBIOSName", NULL);
        if (!state->domain_name) {
                return NT_STATUS_NO_SUCH_DOMAIN;                
        }
        talloc_steal(state, state->domain_name);
 
+       state->domain_dns = ldb_msg_find_attr_as_string(ref_res->msgs[0], "dnsRoot", NULL);
+       if (!state->domain_dns) {
+               return NT_STATUS_NO_SUCH_DOMAIN;                
+       }
+       talloc_steal(state, state->domain_dns);
+
+       talloc_free(ref_res);
+
        /* work out the builtin_dn - useful for so many calls its worth
           fetching here */
        state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
@@ -318,14 +378,6 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_
                return NT_STATUS_NO_SUCH_DOMAIN;                
        }
 
-       state->domain_sid = samdb_search_dom_sid(state->sam_ldb, state,
-                                                state->domain_dn, "objectSid", NULL);
-       if (!state->domain_sid) {
-               return NT_STATUS_NO_SUCH_DOMAIN;                
-       }
-
-       talloc_steal(state, state->domain_sid);
-
        state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
        if (!state->builtin_sid) {
                return NT_STATUS_NO_SUCH_DOMAIN;                
@@ -409,20 +461,11 @@ static NTSTATUS lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CT
 static NTSTATUS lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
                             struct lsa_DnsDomainInfo *info)
 {
-       const char * const attrs[] = { "dnsDomain", "objectGUID", "objectSid", NULL };
-       int ret;
-       struct ldb_message **res;
-
-       ret = gendb_search_dn(state->sam_ldb, mem_ctx, state->domain_dn, &res, attrs);
-       if (ret != 1) {
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
-       }
-
        info->name.string = state->domain_name;
        info->sid         = state->domain_sid;
-       info->dns_domain.string = samdb_result_string(res[0],           "dnsDomain", NULL);
-       info->dns_forest.string = samdb_result_string(res[0],           "dnsDomain", NULL);
-       info->domain_guid       = samdb_result_guid(res[0],             "objectGUID");
+       info->dns_domain.string = state->domain_dns;
+       info->dns_forest.string = state->domain_dns;
+       info->domain_guid       = state->domain_guid;
 
        return NT_STATUS_OK;
 }
@@ -702,10 +745,10 @@ static NTSTATUS lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALL
        trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
 
        /* create the trusted_domain */
-       ret = samdb_add(trusted_domain_state->policy->sam_ldb, mem_ctx, msg);
-       if (ret != 0) {
-               DEBUG(0,("Failed to create trusted_domain record %s\n",
-                        ldb_dn_linearize(mem_ctx, msg->dn)));
+       ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg);
+       if (ret != LDB_SUCCESS) {
+               DEBUG(0,("Failed to create trusted_domain record %s: %s\n",
+                        ldb_dn_linearize(mem_ctx, msg->dn), ldb_errstring(trusted_domain_state->policy->sam_ldb)));
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
 
@@ -857,35 +900,81 @@ static NTSTATUS lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
 }
 
 
+
 /* 
-  lsa_QueryTrustedDomainInfoBySid
+  lsa_SetTrustedDomainInfo
 */
-static NTSTATUS lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                                               struct lsa_QueryTrustedDomainInfoBySid *r)
+static NTSTATUS lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                        struct lsa_SetTrustedDomainInfo *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
 
+
 /* 
-  lsa_SetTrustDomainInfo
+  lsa_SetInfomrationTrustedDomain
 */
-static NTSTATUS lsa_SetTrustDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_SetTrustDomainInfo *r)
+static NTSTATUS lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call, 
+                                               TALLOC_CTX *mem_ctx,
+                                               struct lsa_SetInformationTrustedDomain *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
 
 /* 
-  lsa_DeleteTrustDomain
+  lsa_DeleteTrustedDomain
 */
-static NTSTATUS lsa_DeleteTrustDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                                     struct lsa_DeleteTrustDomain *r)
+static NTSTATUS lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                     struct lsa_DeleteTrustedDomain *r)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       NTSTATUS status;
+       struct lsa_OpenTrustedDomain open;
+       struct lsa_Delete delete;
+       struct dcesrv_handle *h;
+
+       open.in.handle = r->in.handle;
+       open.in.sid = r->in.dom_sid;
+       open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+       open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
+       if (!open.out.trustdom_handle) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       status = lsa_OpenTrustedDomain(dce_call, mem_ctx, &open);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY);
+       talloc_steal(mem_ctx, h);
+
+       delete.in.handle = open.out.trustdom_handle;
+       status = lsa_Delete(dce_call, mem_ctx, &delete);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       return NT_STATUS_OK;
 }
 
+static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx, 
+                                    struct ldb_message *msg, 
+                                    struct lsa_TrustDomainInfoInfoEx *info_ex) 
+{
+       info_ex->domain_name.string
+               = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
+       info_ex->netbios_name.string
+               = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
+       info_ex->sid 
+               = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
+       info_ex->trust_direction
+               = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
+       info_ex->trust_type
+               = ldb_msg_find_attr_as_int(msg, "trustType", 0);
+       info_ex->trust_attributes
+               = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);  
+       return NT_STATUS_OK;
+}
 
 /* 
   lsa_QueryTrustedDomainInfo
@@ -899,10 +988,12 @@ static NTSTATUS lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, T
        int ret;
        struct ldb_message **res;
        const char *attrs[] = {
-               "cn",
-               "flatname",
-               "posixOffset",
+               "flatname", 
+               "trustPartner",
                "securityIdentifier",
+               "trustDirection",
+               "trustType",
+               "trustAttributes", 
                NULL
        };
 
@@ -931,6 +1022,31 @@ static NTSTATUS lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, T
                r->out.info->posix_offset.posix_offset
                        = samdb_result_uint(msg, "posixOffset", 0);                                        
                break;
+#if 0  /* Win2k3 doesn't implement this */
+       case LSA_TRUSTED_DOMAIN_INFO_BASIC:
+               r->out.info->info_basic.netbios_name.string 
+                       = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
+               r->out.info->info_basic.sid
+                       = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
+               break;
+#endif
+       case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
+               return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info_ex);
+
+       case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
+               ZERO_STRUCT(r->out.info->full_info);
+               return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->full_info.info_ex);
+
+       case LSA_TRUSTED_DOMAIN_INFO_INFO_ALL:
+               ZERO_STRUCT(r->out.info->info_all);
+               return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info_all.info_ex);
+
+       case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS_INFO:
+       case LSA_TRUSTED_DOMAIN_INFO_11:
+               /* oops, we don't want to return the info after all */
+               talloc_free(r->out.info);
+               r->out.info = NULL;
+               return NT_STATUS_INVALID_PARAMETER;
        default:
                /* oops, we don't want to return the info after all */
                talloc_free(r->out.info);
@@ -943,23 +1059,40 @@ static NTSTATUS lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, T
 
 
 /* 
-  lsa_SetInformationTrustedDomain
+  lsa_QueryTrustedDomainInfoBySid
 */
-static NTSTATUS lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_SetInformationTrustedDomain *r)
+static NTSTATUS lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                               struct lsa_QueryTrustedDomainInfoBySid *r)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
+       NTSTATUS status;
+       struct lsa_OpenTrustedDomain open;
+       struct lsa_QueryTrustedDomainInfo query;
+       struct dcesrv_handle *h;
+       open.in.handle = r->in.handle;
+       open.in.sid = r->in.dom_sid;
+       open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+       open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
+       if (!open.out.trustdom_handle) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       status = lsa_OpenTrustedDomain(dce_call, mem_ctx, &open);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
-/*
-  lsa_QueryTrustedDomainInfoByName
-*/
-static NTSTATUS lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
-                                                TALLOC_CTX *mem_ctx,
-                                                struct lsa_QueryTrustedDomainInfoByName *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       /* Ensure this handle goes away at the end of this call */
+       DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY);
+       talloc_steal(mem_ctx, h);
+       
+       query.in.trustdom_handle = open.out.trustdom_handle;
+       query.in.level = r->in.level;
+       status = lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       
+       r->out.info = query.out.info;
+       return NT_STATUS_OK;
 }
 
 /*
@@ -972,31 +1105,62 @@ static NTSTATUS lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_cal
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
-/*
-  lsa_EnumTrustedDomainsEx
+/* 
+   lsa_QueryTrustedDomainInfoByName
 */
-static NTSTATUS lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call,
-                                        TALLOC_CTX *mem_ctx,
-                                        struct lsa_EnumTrustedDomainsEx *r)
+static NTSTATUS lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
+                                                TALLOC_CTX *mem_ctx,
+                                                struct lsa_QueryTrustedDomainInfoByName *r)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       NTSTATUS status;
+       struct lsa_OpenTrustedDomainByName open;
+       struct lsa_QueryTrustedDomainInfo query;
+       struct dcesrv_handle *h;
+       open.in.handle = r->in.handle;
+       open.in.name = r->in.trusted_domain;
+       open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+       open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
+       if (!open.out.trustdom_handle) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       status = lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &open);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       
+       /* Ensure this handle goes away at the end of this call */
+       DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY);
+       talloc_steal(mem_ctx, h);
+
+       query.in.trustdom_handle = open.out.trustdom_handle;
+       query.in.level = r->in.level;
+       status = lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       
+       r->out.info = query.out.info;
+       return NT_STATUS_OK;
 }
 
 /*
-  lsa_CloseTrustedDomainEx
+  lsa_CloseTrustedDomainEx 
 */
 static NTSTATUS lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
                                         TALLOC_CTX *mem_ctx,
                                         struct lsa_CloseTrustedDomainEx *r)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       /* The result of a bad hair day from an IDL programmer?  Not
+        * implmented in Win2k3.  You should always just lsa_Close
+        * anyway. */
+       return NT_STATUS_NOT_IMPLEMENTED;
 }
 
 
 /*
   comparison function for sorting lsa_DomainInformation array
 */
-static int compare_DomainInformation(struct lsa_DomainInformation *e1, struct lsa_DomainInformation *e2)
+static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
 {
        return strcasecmp(e1->name.string, e2->name.string);
 }
@@ -1008,7 +1172,7 @@ static NTSTATUS lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX
                                 struct lsa_EnumTrustDom *r)
 {
        struct dcesrv_handle *policy_handle;
-       struct lsa_DomainInformation *entries;
+       struct lsa_DomainInfo *entries;
        struct lsa_policy_state *policy_state;
        struct ldb_message **domains;
        const char *attrs[] = {
@@ -1040,8 +1204,8 @@ static NTSTATUS lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX
                return NT_STATUS_OK;
        }
 
-       /* convert to lsa_DomainInformation format */
-       entries = talloc_array(mem_ctx, struct lsa_DomainInformation, count);
+       /* convert to lsa_TrustInformation format */
+       entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
        if (!entries) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -1051,8 +1215,8 @@ static NTSTATUS lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX
        }
 
        /* sort the results by name */
-       qsort(entries, count, sizeof(struct lsa_DomainInformation), 
-             (comparison_fn_t)compare_DomainInformation);
+       qsort(entries, count, sizeof(*entries), 
+             (comparison_fn_t)compare_DomainInfo);
 
        if (*r->in.resume_handle >= count) {
                *r->out.resume_handle = -1;
@@ -1077,6 +1241,96 @@ static NTSTATUS lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX
        return NT_STATUS_OK;
 }
 
+/*
+  comparison function for sorting lsa_DomainInformation array
+*/
+static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
+{
+       return strcasecmp(e1->domain_name.string, e2->domain_name.string);
+}
+
+/* 
+  lsa_EnumTrustedDomainsEx 
+*/
+static NTSTATUS lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                       struct lsa_EnumTrustedDomainsEx *r)
+{
+       struct dcesrv_handle *policy_handle;
+       struct lsa_TrustDomainInfoInfoEx *entries;
+       struct lsa_policy_state *policy_state;
+       struct ldb_message **domains;
+       const char *attrs[] = {
+               "flatname", 
+               "trustPartner",
+               "securityIdentifier",
+               "trustDirection",
+               "trustType",
+               "trustAttributes", 
+               NULL
+       };
+       NTSTATUS nt_status;
+
+       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 = gendb_search(policy_state->sam_ldb, 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(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
+       if (!entries) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       for (i=0;i<count;i++) {
+               nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       return nt_status;
+               }
+       }
+
+       /* sort the results by name */
+       qsort(entries, count, sizeof(*entries), 
+             (comparison_fn_t)compare_TrustDomainInfoInfoEx);
+
+       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_EX_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;
+}
+
 
 /*
   return the authority name and authority sid, given a sid
@@ -1141,7 +1395,7 @@ static NTSTATUS lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *m
 
        domains->domains = talloc_realloc(domains, 
                                          domains->domains,
-                                         struct lsa_TrustInformation,
+                                         struct lsa_DomainInfo,
                                          domains->count+1);
        if (domains->domains == NULL) {
                return NT_STATUS_NO_MEMORY;
@@ -1149,6 +1403,7 @@ static NTSTATUS lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *m
        domains->domains[i].name.string = authority_name;
        domains->domains[i].sid         = authority_sid;
        domains->count++;
+       domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count;
        *sid_index = i;
        
        return NT_STATUS_OK;
index dd6bdf3f6a159de87cd5741368b3e8fc38b07d4c..29b57ec2b2aa4ecc8cda775ba11174c0db42f52a 100644 (file)
@@ -889,7 +889,7 @@ static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALL
        struct netr_DomainInfo1 *info1;
        int ret, ret1, ret2, i;
        NTSTATUS status;
-       const struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
+       const struct ldb_dn *partitions_basedn;
 
        const char *local_domain;
 
@@ -904,6 +904,8 @@ static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALL
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
 
+       partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
+
        /* we need to do two searches. The first will pull our primary
           domain and the second will pull any trusted domains. Our
           primary domain is also a "trusted" domain, so we need to
@@ -1143,7 +1145,7 @@ static WERROR netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
        struct ldb_message **dom_res, **ref_res;
        const char * const dom_attrs[] = { "dnsDomain", "objectSid", "objectGUID", NULL };
        const char * const ref_attrs[] = { "nETBIOSName", NULL };
-       const struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
+       const struct ldb_dn *partitions_basedn;
 
        ZERO_STRUCT(r->out);
 
@@ -1152,6 +1154,8 @@ static WERROR netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
                return WERR_GENERAL_FAILURE;
        }
 
+       partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
+
        ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
        if (ret == -1) {
                return WERR_GENERAL_FAILURE;            
index 099dd414301a7d12e1f3387d16910e0143450543..7395a814e03fcba45f49db61a5c45915e5ad9ad0 100644 (file)
@@ -807,6 +807,26 @@ static BOOL test_DeleteTrustedDomain(struct dcerpc_pipe *p,
        return True;
 }
 
+static BOOL test_DeleteTrustedDomainBySid(struct dcerpc_pipe *p, 
+                                         TALLOC_CTX *mem_ctx, 
+                                         struct policy_handle *handle,
+                                         struct dom_sid *sid)
+{
+       NTSTATUS status;
+       struct lsa_DeleteTrustedDomain r;
+
+       r.in.handle = handle;
+       r.in.dom_sid = sid;
+
+       status = dcerpc_lsa_DeleteTrustedDomain(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("lsa_DeleteTrustedDomain failed - %s\n", nt_errstr(status));
+               return False;
+       }
+
+       return True;
+}
+
 
 static BOOL test_CreateSecret(struct dcerpc_pipe *p, 
                              TALLOC_CTX *mem_ctx, 
@@ -1437,8 +1457,10 @@ static BOOL test_query_each_TrustDom(struct dcerpc_pipe *p,
                struct policy_handle trustdom_handle;
                struct policy_handle handle2;
                struct lsa_Close c;
-               int levels [] = {1, 3, 6, 8, 12};
-                       
+               struct lsa_CloseTrustedDomainEx c_trust;
+               int levels [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+               int ok[]      = {1, 0, 1, 0, 0, 1, 0, 1, 0,  0,  0,  1};
+
                if (domains->domains[i].sid) {
                        trust.in.handle = handle;
                        trust.in.sid = domains->domains[i].sid;
@@ -1455,6 +1477,9 @@ static BOOL test_query_each_TrustDom(struct dcerpc_pipe *p,
                        c.in.handle = &trustdom_handle;
                        c.out.handle = &handle2;
                        
+                       c_trust.in.handle = &trustdom_handle;
+                       c_trust.out.handle = &handle2;
+                       
                        for (j=0; j < ARRAY_SIZE(levels); j++) {
                                struct lsa_QueryTrustedDomainInfo q;
                                union lsa_TrustedDomainInfo info;
@@ -1462,18 +1487,32 @@ static BOOL test_query_each_TrustDom(struct dcerpc_pipe *p,
                                q.in.level = levels[j];
                                q.out.info = &info;
                                status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q);
-                               if (!NT_STATUS_IS_OK(status)) {
+                               if (!NT_STATUS_IS_OK(status) && ok[j]) {
                                        printf("QueryTrustedDomainInfo level %d failed - %s\n", 
                                               levels[j], nt_errstr(status));
                                        ret = False;
+                               } else if (NT_STATUS_IS_OK(status) && !ok[j]) {
+                                       printf("QueryTrustedDomainInfo level %d unexpectedly succeeded - %s\n", 
+                                              levels[j], nt_errstr(status));
+                                       ret = False;
                                }
                        }
                        
+                       status = dcerpc_lsa_CloseTrustedDomainEx(p, mem_ctx, &c_trust);
+                       if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
+                               printf("Expected CloseTrustedDomainEx to return NT_STATUS_NOT_IMPLEMENTED, instead - %s\n", nt_errstr(status));
+                               return False;
+                       }
+                       
+                       c.in.handle = &trustdom_handle;
+                       c.out.handle = &handle2;
+                       
                        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;
@@ -1495,10 +1534,14 @@ static BOOL test_query_each_TrustDom(struct dcerpc_pipe *p,
                        q.in.level = levels[j];
                        q.out.info = &info;
                        status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q);
-                       if (!NT_STATUS_IS_OK(status)) {
+                       if (!NT_STATUS_IS_OK(status) && ok[j]) {
                                printf("QueryTrustedDomainInfo level %d failed - %s\n", 
                                       levels[j], nt_errstr(status));
                                ret = False;
+                       } else if (NT_STATUS_IS_OK(status) && !ok[j]) {
+                               printf("QueryTrustedDomainInfo level %d unexpectedly succeeded - %s\n", 
+                                      levels[j], nt_errstr(status));
+                               ret = False;
                        }
                }
                
@@ -1524,10 +1567,14 @@ static BOOL test_query_each_TrustDom(struct dcerpc_pipe *p,
                        q.in.level   = levels[j];
                        q.out.info   = &info;
                        status = dcerpc_lsa_QueryTrustedDomainInfoBySid(p, mem_ctx, &q);
-                       if (!NT_STATUS_IS_OK(status)) {
+                       if (!NT_STATUS_IS_OK(status) && ok[j]) {
                                printf("QueryTrustedDomainInfoBySid level %d failed - %s\n", 
                                       levels[j], nt_errstr(status));
                                ret = False;
+                       } else if (NT_STATUS_IS_OK(status) && !ok[j]) {
+                               printf("QueryTrustedDomainInfoBySid level %d unexpectedly succeeded - %s\n", 
+                                      levels[j], nt_errstr(status));
+                               ret = False;
                        }
                }
                
@@ -1539,10 +1586,14 @@ static BOOL test_query_each_TrustDom(struct dcerpc_pipe *p,
                        q.in.level          = levels[j];
                        q.out.info          = &info;
                        status = dcerpc_lsa_QueryTrustedDomainInfoByName(p, mem_ctx, &q);
-                       if (!NT_STATUS_IS_OK(status)) {
+                       if (!NT_STATUS_IS_OK(status) && ok[j]) {
                                printf("QueryTrustedDomainInfoByName level %d failed - %s\n", 
                                       levels[j], nt_errstr(status));
                                ret = False;
+                       } else if (NT_STATUS_IS_OK(status) && !ok[j]) {
+                               printf("QueryTrustedDomainInfoByName level %d unexpectedly succeeded - %s\n", 
+                                      levels[j], nt_errstr(status));
+                               ret = False;
                        }
                }
        }
@@ -1554,9 +1605,11 @@ static BOOL test_EnumTrustDom(struct dcerpc_pipe *p,
                              struct policy_handle *handle)
 {
        struct lsa_EnumTrustDom r;
+       struct lsa_EnumTrustedDomainsEx r_ex;
        NTSTATUS enum_status;
        uint32_t resume_handle = 0;
        struct lsa_DomainList domains;
+       struct lsa_DomainListEx domains_ex;
        BOOL ret = True;
 
        printf("\nTesting EnumTrustDom\n");
@@ -1587,14 +1640,43 @@ static BOOL test_EnumTrustDom(struct dcerpc_pipe *p,
                        return False;
                }
                
-               if (lp_parm_bool(-1, "target", "samba4", False)) {
-                       printf("skipping 'each' Trusted Domains tests against Samba4\n");
-               } else {
-                       ret &= test_query_each_TrustDom(p, mem_ctx, handle, &domains);
-               }
+               ret &= test_query_each_TrustDom(p, mem_ctx, handle, &domains);
                
        } while ((NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES)));
 
+       printf("\nTesting EnumTrustedDomainsEx\n");
+
+       resume_handle = 0;
+       do {
+               r_ex.in.handle = handle;
+               r_ex.in.resume_handle = &resume_handle;
+               r_ex.in.max_size = LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER * 3;
+               r_ex.out.domains = &domains_ex;
+               r_ex.out.resume_handle = &resume_handle;
+               
+               enum_status = dcerpc_lsa_EnumTrustedDomainsEx(p, mem_ctx, &r_ex);
+               
+               /* 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_ex.out.domains->count < 3 || r_ex.out.domains->count > 4) {
+                               printf("EnumTrustDom didn't fill the buffer we "
+                                      "asked it to (got %d, expected %d / %d == %d entries)\n",
+                                      r_ex.out.domains->count, 
+                                      r_ex.in.max_size,
+                                      LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER, 
+                                      r_ex.in.max_size / LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER);
+                               ret = False;
+                               exit(1);
+                       }
+               } else if (!NT_STATUS_IS_OK(enum_status)) {
+                       printf("EnumTrustedDomainEx failed - %s\n", nt_errstr(enum_status));
+                       return False;
+               }
+       } while ((NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES)));
+
        return ret;
 }
 
@@ -1605,7 +1687,7 @@ static BOOL test_CreateTrustedDomain(struct dcerpc_pipe *p,
        NTSTATUS status;
        BOOL ret = True;
        struct lsa_CreateTrustedDomain r;
-       struct lsa_TrustInformation trustinfo;
+       struct lsa_DomainInfo trustinfo;
        struct dom_sid *domsid[12];
        struct policy_handle trustdom_handle[12];
        struct lsa_QueryTrustedDomainInfo q;
@@ -1661,7 +1743,7 @@ static BOOL test_CreateTrustedDomain(struct dcerpc_pipe *p,
        }
        
        for (i=0; i<12; i++) {
-               if (!test_Delete(p, mem_ctx, &trustdom_handle[i])) {
+               if (!test_DeleteTrustedDomainBySid(p, mem_ctx, handle, domsid[i])) {
                        ret = False;
                }
        }
@@ -1714,7 +1796,7 @@ static BOOL test_QueryInfoPolicy(struct dcerpc_pipe *p,
        printf("\nTesting QueryInfoPolicy\n");
 
        if (lp_parm_bool(-1, "target", "samba4", False)) {
-               printf("skipping QueryInfoPolicy2 against Samba4\n");
+               printf("skipping QueryInfoPolicy against Samba4\n");
                return True;
        }
 
index 5b6575893dbeeb0f3b6e6b6edc9d8083d70d75c1..66c344bb266d1f41e252930a15d86a7b94caa6cf 100644 (file)
@@ -1481,7 +1481,7 @@ static BOOL test_ManyGetDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
                                            dcerpc_server_name(p));
 
        for (i=0; i<domains.count * 4; i++) {
-               struct lsa_DomainInformation *info =
+               struct lsa_DomainInfo *info =
                        &domains.domains[rand()%domains.count];
 
                d.in.domainname = info->name.string;
index 7fe64ebcd132689c31d78dc2a85fda8a36702a14..53abcf5f65f003d03645ed589fdd5a4ed3d47396 100644 (file)
@@ -337,7 +337,7 @@ static void lsa_lookupsids_recv_names(struct rpc_request *req)
        for (i=0; i<state->num_sids; i++) {
                struct lsa_TranslatedName *name =
                        &state->r.out.names->names[i];
-               struct lsa_TrustInformation *dom;
+               struct lsa_DomainInfo *dom;
 
                state->result[i] = talloc_zero(state->result,
                                               struct wb_sid_object);
@@ -494,7 +494,7 @@ static void lsa_lookupnames_recv_sids(struct rpc_request *req)
 
        for (i=0; i<state->num_names; i++) {
                struct lsa_TranslatedSid *sid = &state->r.out.sids->sids[i];
-               struct lsa_TrustInformation *dom;
+               struct lsa_DomainInfo *dom;
 
                state->result[i] = talloc_zero(state->result,
                                               struct wb_sid_object);