s4-lsaprc: Don't call lsa_OpenPolicy2 in lsa_LookupNames4.
[mat/samba.git] / source4 / rpc_server / lsa / lsa_lookup.c
index 005c7d4f06b5b1b7cbca42a98c098704f48ebc78..4b2a37a21076b8d9653f09e6a4b4b0ea183e6c16 100644 (file)
 */
 
 #include "rpc_server/lsa/lsa.h"
+#include "libds/common/flag_mapping.h"
 
 static const struct {
        const char *domain;
        const char *name;
        const char *sid;
-       int rtype;
+       enum lsa_SidType rtype;
 } well_known[] = {
        {
                .name = "EVERYONE",
@@ -193,9 +194,9 @@ static const struct {
 
 static NTSTATUS lookup_well_known_names(TALLOC_CTX *mem_ctx, const char *domain,
                                        const char *name, const char **authority_name, 
-                                       struct dom_sid **sid, uint32_t *rtype) 
+                                       struct dom_sid **sid, enum lsa_SidType *rtype)
 {
-       int i;
+       unsigned int i;
        for (i=0; well_known[i].sid; i++) {
                if (domain) {
                        if (strcasecmp_m(domain, well_known[i].domain) == 0
@@ -219,9 +220,9 @@ static NTSTATUS lookup_well_known_names(TALLOC_CTX *mem_ctx, const char *domain,
 
 static NTSTATUS lookup_well_known_sids(TALLOC_CTX *mem_ctx, 
                                       const char *sid_str, const char **authority_name, 
-                                      const char **name, uint32_t *rtype) 
+                                      const char **name, enum lsa_SidType *rtype) 
 {
-       int i;
+       unsigned int i;
        for (i=0; well_known[i].sid; i++) {
                if (strcasecmp_m(sid_str, well_known[i].sid) == 0) {
                        *authority_name = well_known[i].domain;
@@ -239,10 +240,12 @@ static NTSTATUS lookup_well_known_sids(TALLOC_CTX *mem_ctx,
 static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx, 
                                       struct loadparm_context *lp_ctx,
                                       struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
-                               const char *name, const char **authority_name, 
-                               struct dom_sid **sid, enum lsa_SidType *rtype)
+                                      const char *name, const char **authority_name, 
+                                      struct dom_sid **sid, enum lsa_SidType *rtype,
+                                      uint32_t *rid)
 {
-       int ret, atype, i;
+       int ret, i;
+       uint32_t atype;
        struct ldb_message **res;
        const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
        const char *p;
@@ -274,6 +277,15 @@ static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx,
                /* Look up table of well known names */
                status = lookup_well_known_names(mem_ctx, NULL, username, authority_name, sid, rtype);
                if (NT_STATUS_IS_OK(status)) {
+                       dom_sid_split_rid(NULL, *sid, NULL, rid);
+                       return NT_STATUS_OK;
+               }
+
+               if (username == NULL) {
+                       *authority_name = NAME_BUILTIN;
+                       *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
+                       *rtype = SID_NAME_DOMAIN;
+                       *rid = 0xFFFFFFFF;
                        return NT_STATUS_OK;
                }
 
@@ -281,24 +293,28 @@ static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx,
                        *authority_name = NAME_NT_AUTHORITY;
                        *sid =  dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
                        *rtype = SID_NAME_DOMAIN;
+                       dom_sid_split_rid(NULL, *sid, NULL, rid);
                        return NT_STATUS_OK;
                }
                if (strcasecmp_m(username, NAME_BUILTIN) == 0) { 
                        *authority_name = NAME_BUILTIN;
                        *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
                        *rtype = SID_NAME_DOMAIN;
+                       *rid = 0xFFFFFFFF;
                        return NT_STATUS_OK;
                }
                if (strcasecmp_m(username, state->domain_dns) == 0) { 
                        *authority_name = state->domain_name;
                        *sid =  state->domain_sid;
                        *rtype = SID_NAME_DOMAIN;
+                       *rid = 0xFFFFFFFF;
                        return NT_STATUS_OK;
                }
                if (strcasecmp_m(username, state->domain_name) == 0) { 
                        *authority_name = state->domain_name;
                        *sid =  state->domain_sid;
                        *rtype = SID_NAME_DOMAIN;
+                       *rid = 0xFFFFFFFF;
                        return NT_STATUS_OK;
                }
                
@@ -307,7 +323,7 @@ static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx,
                if (!name) {
                        return NT_STATUS_NO_MEMORY;
                }
-               status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype);
+               status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
                if (NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -317,7 +333,7 @@ static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx,
                if (!name) {
                        return NT_STATUS_NO_MEMORY;
                }
-               status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype);
+               status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
                if (NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -327,7 +343,7 @@ static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx,
                if (!name) {
                        return NT_STATUS_NO_MEMORY;
                }
-               status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype);
+               status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
                if (NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -338,12 +354,17 @@ static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx,
                        *authority_name = NAME_NT_AUTHORITY;
                        *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
                        *rtype = SID_NAME_DOMAIN;
+                       dom_sid_split_rid(NULL, *sid, NULL, rid);
                        return NT_STATUS_OK;
                }
 
                /* Look up table of well known names */
-               return lookup_well_known_names(mem_ctx, domain, username, authority_name, 
-                                              sid, rtype);
+               status = lookup_well_known_names(mem_ctx, domain, username, authority_name, 
+                                                sid, rtype);
+               if (NT_STATUS_IS_OK(status)) {
+                       dom_sid_split_rid(NULL, *sid, NULL, rid);
+               }
+               return status;
        } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) {
                *authority_name = NAME_BUILTIN;
                domain_dn = state->builtin_dn;
@@ -359,26 +380,26 @@ static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx,
        }
 
        ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs);
-       if (ret == 1) {
-               domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
-               if (domain_sid == NULL) {
-                       return NT_STATUS_INVALID_SID;
-               }
-       } else {
+       if (ret != 1) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+       domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
+       if (domain_sid == NULL) {
                return NT_STATUS_INVALID_SID;
        }
 
        if (!*username) {
                *sid = domain_sid;
                *rtype = SID_NAME_DOMAIN;
+               *rid = 0xFFFFFFFF;
                return NT_STATUS_OK;
        }
        
        ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs, 
                           "(&(sAMAccountName=%s)(objectSid=*))", 
                           ldb_binary_encode_string(mem_ctx, username));
-       if (ret == -1) {
-               return NT_STATUS_INVALID_SID;
+       if (ret < 0) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
 
        for (i=0; i < ret; i++) {
@@ -392,13 +413,14 @@ static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx,
                        continue;
                }
 
-               atype = samdb_result_uint(res[i], "sAMAccountType", 0);
+               atype = ldb_msg_find_attr_as_uint(res[i], "sAMAccountType", 0);
                        
                *rtype = ds_atype_map(atype);
                if (*rtype == SID_NAME_UNKNOWN) {
                        return STATUS_SOME_UNMAPPED;
                }
 
+               dom_sid_split_rid(NULL, *sid, NULL, rid);
                return NT_STATUS_OK;
        }
 
@@ -419,7 +441,7 @@ static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC
                                          uint32_t *sid_index)
 {
        struct dom_sid *authority_sid;
-       int i;
+       uint32_t i;
 
        if (rtype != SID_NAME_DOMAIN) {
                authority_sid = dom_sid_dup(mem_ctx, sid);
@@ -489,28 +511,30 @@ static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX
                return NT_STATUS_NOT_FOUND;
        }
 
+       /* need to re-add a check for an allocated sid */
+
        ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs, 
                           "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
-       if (ret == 1) {
-               *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
+       if ((ret < 0) || (ret > 1)) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+       if (ret == 0) {
+               return NT_STATUS_NOT_FOUND;
+       }
+
+       *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
+       if (!*name) {
+               *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
                if (!*name) {
-                       *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
-                       if (!*name) {
-                               *name = talloc_strdup(mem_ctx, sid_str);
-                               NT_STATUS_HAVE_NO_MEMORY(*name);
-                       }
+                       *name = talloc_strdup(mem_ctx, sid_str);
+                       NT_STATUS_HAVE_NO_MEMORY(*name);
                }
-
-               atype = samdb_result_uint(res[0], "sAMAccountType", 0);
-
-               *rtype = ds_atype_map(atype);
-
-               return NT_STATUS_OK;
        }
 
-       /* need to re-add a check for an allocated sid */
+       atype = ldb_msg_find_attr_as_uint(res[0], "sAMAccountType", 0);
+       *rtype = ds_atype_map(atype);
 
-       return NT_STATUS_NOT_FOUND;
+       return NT_STATUS_OK;
 }
 
 
@@ -523,14 +547,19 @@ NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
 {
        struct lsa_policy_state *state;
        struct lsa_RefDomainList *domains = NULL;
-       int i;
+       uint32_t i;
        NTSTATUS status = NT_STATUS_OK;
+       struct dcesrv_handle *h;
+
+       DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
 
        if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
            r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
+       state = h->data;
+
        *r->out.domains = NULL;
 
        /* NOTE: the WSPP test suite tries SIDs with invalid revision numbers,
@@ -539,11 +568,6 @@ NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
           MS-DTYP 2.4.2
        */
 
-       status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
        domains = talloc_zero(r->out.domains,  struct lsa_RefDomainList);
        if (domains == NULL) {
                return NT_STATUS_NO_MEMORY;
@@ -658,8 +682,8 @@ NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
        r2.in.names    = r->in.names;
        r2.in.level    = r->in.level;
        r2.in.count    = r->in.count;
-       r2.in.unknown1 = r->in.unknown1;
-       r2.in.unknown2 = r->in.unknown2;
+       r2.in.lookup_options = r->in.lookup_options;
+       r2.in.client_revision = r->in.client_revision;
        r2.out.count   = r->out.count;
        r2.out.names   = r->out.names;
        r2.out.domains = r->out.domains;
@@ -682,7 +706,7 @@ NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
 {
        struct lsa_LookupSids2 r2;
        NTSTATUS status;
-       int i;
+       uint32_t i;
 
        ZERO_STRUCT(r2);
 
@@ -691,8 +715,8 @@ NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
        r2.in.names    = NULL;
        r2.in.level    = r->in.level;
        r2.in.count    = r->in.count;
-       r2.in.unknown1 = 0;
-       r2.in.unknown2 = 0;
+       r2.in.lookup_options = 0;
+       r2.in.client_revision = 0;
        r2.out.count   = r->out.count;
        r2.out.names   = NULL;
        r2.out.domains = r->out.domains;
@@ -726,29 +750,20 @@ NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
        return status;
 }
 
-
-/*
-  lsa_LookupNames3
-*/
-NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
-                                TALLOC_CTX *mem_ctx,
-                                struct lsa_LookupNames3 *r)
+static NTSTATUS dcesrv_lsa_LookupNames_common(struct dcesrv_call_state *dce_call,
+                                             TALLOC_CTX *mem_ctx,
+                                             struct lsa_policy_state *policy_state,
+                                             struct lsa_LookupNames3 *r)
 {
-       struct lsa_policy_state *policy_state;
-       struct dcesrv_handle *policy_handle;
-       int i;
        struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
        struct lsa_RefDomainList *domains;
-
-       DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
+       uint32_t i;
 
        if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
            r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       policy_state = policy_handle->data;
-
        *r->out.domains = NULL;
 
        domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
@@ -774,7 +789,7 @@ NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
                const char *name = r->in.names[i].string;
                const char *authority_name;
                struct dom_sid *sid;
-               uint32_t sid_index;
+               uint32_t sid_index, rid;
                enum lsa_SidType rtype;
                NTSTATUS status2;
 
@@ -785,7 +800,8 @@ NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
                r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
                r->out.sids->sids[i].flags       = 0;
 
-               status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name, &authority_name, &sid, &rtype);
+               status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name,
+                                                &authority_name, &sid, &rtype, &rid);
                if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
                        continue;
                }
@@ -814,6 +830,26 @@ NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
        return NT_STATUS_OK;
 }
 
+/*
+  lsa_LookupNames3
+*/
+NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
+                                TALLOC_CTX *mem_ctx,
+                                struct lsa_LookupNames3 *r)
+{
+       struct lsa_policy_state *policy_state;
+       struct dcesrv_handle *policy_handle;
+
+       DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
+
+       policy_state = policy_handle->data;
+
+       return dcesrv_lsa_LookupNames_common(dce_call,
+                                            mem_ctx,
+                                            policy_state,
+                                            r);
+}
+
 /* 
   lsa_LookupNames4
 
@@ -823,48 +859,41 @@ NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
 NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                 struct lsa_LookupNames4 *r)
 {
-       struct lsa_LookupNames3 r2;
-       struct lsa_OpenPolicy2 pol;
+       struct lsa_policy_state *policy_state;
+       struct lsa_LookupNames3 q;
        NTSTATUS status;
-       struct dcesrv_handle *h;
-
-       ZERO_STRUCT(r2);
-
-       /* No policy handle on the wire, so make one up here */
-       r2.in.handle = talloc(mem_ctx, struct policy_handle);
-       if (!r2.in.handle) {
-               return NT_STATUS_NO_MEMORY;
-       }
 
-       pol.out.handle = r2.in.handle;
-       pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
-       pol.in.attr = NULL;
-       pol.in.system_name = NULL;
-       status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
+       status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &policy_state);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       /* ensure this handle goes away at the end of this call */
-       DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
-       talloc_steal(mem_ctx, h);
+       ZERO_STRUCT(q);
+
+       q.in.handle = NULL;
+       q.in.num_names = r->in.num_names;
+       q.in.names = r->in.names;
+       q.in.level = r->in.level;
+       q.in.sids = r->in.sids;
+       q.in.count = r->in.count;
+       q.in.lookup_options = r->in.lookup_options;
+       q.in.client_revision = r->in.client_revision;
+
+       q.out.count = r->out.count;
+       q.out.sids = r->out.sids;
+       q.out.domains = r->out.domains;
+
+       status = dcesrv_lsa_LookupNames_common(dce_call,
+                                              mem_ctx,
+                                              policy_state,
+                                              &q);
+
+       talloc_free(policy_state);
+
+       r->out.count = q.out.count;
+       r->out.sids = q.out.sids;
+       r->out.domains = q.out.domains;
 
-       r2.in.num_names = r->in.num_names;
-       r2.in.names = r->in.names;
-       r2.in.level = r->in.level;
-       r2.in.sids = r->in.sids;
-       r2.in.count = r->in.count;
-       r2.in.lookup_options = r->in.lookup_options;
-       r2.in.client_revision = r->in.client_revision;
-       r2.out.domains = r->out.domains;
-       r2.out.sids = r->out.sids;
-       r2.out.count = r->out.count;
-       
-       status = dcesrv_lsa_LookupNames3(dce_call, mem_ctx, &r2);
-       
-       r->out.domains = r2.out.domains;
-       r->out.sids = r2.out.sids;
-       r->out.count = r2.out.count;
        return status;
 }
 
@@ -877,7 +906,7 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
 {
        struct lsa_policy_state *state;
        struct dcesrv_handle *h;
-       int i;
+       uint32_t i;
        struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
        struct lsa_RefDomainList *domains;
 
@@ -915,7 +944,8 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
                const char *name = r->in.names[i].string;
                const char *authority_name;
                struct dom_sid *sid;
-               uint32_t rtype, sid_index;
+               uint32_t sid_index, rid=0;
+               enum lsa_SidType rtype;
                NTSTATUS status2;
 
                r->out.sids->count++;
@@ -928,8 +958,8 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
                r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
                r->out.sids->sids[i].unknown     = 0;
 
-               status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, state, mem_ctx, name, 
-                                                &authority_name, &sid, &rtype);
+               status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, state, mem_ctx, name,
+                                                &authority_name, &sid, &rtype, &rid);
                if (!NT_STATUS_IS_OK(status2)) {
                        continue;
                }
@@ -941,7 +971,7 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
                }
 
                r->out.sids->sids[i].sid_type    = rtype;
-               r->out.sids->sids[i].rid         = sid->sub_auths[sid->num_auths-1];
+               r->out.sids->sids[i].rid         = rid;
                r->out.sids->sids[i].sid_index   = sid_index;
                r->out.sids->sids[i].unknown     = 0;
 
@@ -966,7 +996,7 @@ NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *
 {
        struct lsa_LookupNames2 r2;
        NTSTATUS status;
-       int i;
+       uint32_t i;
 
        ZERO_STRUCT(r2);