r25194: A major rework of the Samba4 LSA LookupNames and LookupSids code, with
authorAndrew Bartlett <abartlet@samba.org>
Mon, 17 Sep 2007 05:31:49 +0000 (05:31 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 20:06:51 +0000 (15:06 -0500)
a new torture suite to match.

This should fix bug #4954 by Matthias Wallnöfer <mwallnoefer@yahoo.de>

Previously we had no knowlege of BUILTIN or well-known names.

This code needs expansion to check with winbind for trusted domains.

Andrew Bartlett
(This used to be commit e6fc0e1f54ad64bdddc88e9ebd0d8d181b6ce26a)

source4/dsdb/common/sidmap.c
source4/librpc/idl/security.idl
source4/rpc_server/config.mk
source4/rpc_server/lsa/dcesrv_lsa.c
source4/rpc_server/lsa/lsa.h [new file with mode: 0644]
source4/rpc_server/lsa/lsa_init.c [new file with mode: 0644]
source4/rpc_server/lsa/lsa_lookup.c [new file with mode: 0644]
source4/torture/rpc/lsa.c

index 8a594f3fc7981db63ca1c2f1ec55cff7bce9a2b5..023c88ad7f76620a69f358ecd9949d39e9efcfe9 100644 (file)
@@ -550,13 +550,13 @@ _PUBLIC_ NTSTATUS sidmap_allocated_sid_lookup(struct sidmap_context *sidmap,
                                              TALLOC_CTX *mem_ctx, 
                                              const struct dom_sid *sid,
                                              const char **name,
-                                             uint32_t *atype)
+                                             enum lsa_SidType *rtype)
 {
        NTSTATUS status;
        struct dom_sid *domain_sid;
        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
-       uint32_t rid;
-
+       uint32_t rid, atype;
+       
        status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
        if (!NT_STATUS_IS_OK(status)) {
                return NT_STATUS_NO_SUCH_DOMAIN;
@@ -577,7 +577,9 @@ _PUBLIC_ NTSTATUS sidmap_allocated_sid_lookup(struct sidmap_context *sidmap,
        if (rid < SIDMAP_LOCAL_GROUP_BASE) {
                struct passwd *pwd;
                uid_t uid = rid - SIDMAP_LOCAL_USER_BASE;
-               *atype = ATYPE_NORMAL_ACCOUNT;
+               atype = ATYPE_NORMAL_ACCOUNT;
+               *rtype = samdb_atype_map(atype);
+
                pwd = getpwuid(uid);
                if (pwd == NULL) {
                        *name = talloc_asprintf(mem_ctx, "uid%u", uid);
@@ -587,7 +589,8 @@ _PUBLIC_ NTSTATUS sidmap_allocated_sid_lookup(struct sidmap_context *sidmap,
        } else {
                struct group *grp;
                gid_t gid = rid - SIDMAP_LOCAL_GROUP_BASE;
-               *atype = ATYPE_LOCAL_GROUP;
+               atype = ATYPE_LOCAL_GROUP;
+               *rtype = samdb_atype_map(atype);
                grp = getgrgid(gid);
                if (grp == NULL) {
                        *name = talloc_asprintf(mem_ctx, "gid%u", gid);
index f05148aecc2fac311b8f82990747fc7fdd32ba17..4e0263785bc5c122028098a6468e5e982cd508ff 100644 (file)
@@ -138,6 +138,8 @@ interface security
        const string SID_NULL = "S-1-0-0";
 
        /* the world domain */
+       const string NAME_WORLD       = "WORLD";
+
        const string SID_WORLD_DOMAIN = "S-1-1";
        const string SID_WORLD        = "S-1-1-0";
 
@@ -147,6 +149,8 @@ interface security
        const string SID_CREATOR_GROUP        = "S-1-3-1";
 
        /* SECURITY_NT_AUTHORITY */
+       const string NAME_NT_AUTHORITY            = "NT AUTHORITY";
+
        const string SID_NT_AUTHORITY             = "S-1-5";
        const string SID_NT_DIALUP                = "S-1-5-1";
        const string SID_NT_NETWORK               = "S-1-5-2";
@@ -167,6 +171,8 @@ interface security
        const string SID_NT_NETWORK_SERVICE       = "S-1-5-20";
 
        /* SECURITY_BUILTIN_DOMAIN_RID */
+       const string NAME_BUILTIN                  = "BUILTIN";
+
        const string SID_BUILTIN                   = "S-1-5-32";
        const string SID_BUILTIN_ADMINISTRATORS    = "S-1-5-32-544";
        const string SID_BUILTIN_USERS             = "S-1-5-32-545";
index 7a39e5606087a25dd980f7d6652facdf2f0ee83d..1269dcc707498a77c7ab97f6433adcbc48e3b34b 100644 (file)
@@ -135,8 +135,11 @@ PRIVATE_DEPENDENCIES = \
 [MODULE::dcerpc_lsarpc]
 INIT_FUNCTION = dcerpc_server_lsa_init
 SUBSYSTEM = dcerpc_server
+PRIVATE_PROTO_HEADER= lsa/proto.h
 OBJ_FILES = \
-               lsa/dcesrv_lsa.o
+               lsa/dcesrv_lsa.o \
+               lsa/lsa_init.o \
+               lsa/lsa_lookup.o
 PRIVATE_DEPENDENCIES = \
                SAMDB \
                DCERPC_COMMON \
index 144e61cd75dedf4c35e947ca87fac0ce24e1558d..8a695bdedf59e103408feb852f15a070b5a9bf26 100644 (file)
@@ -4,7 +4,7 @@
    endpoint server for the lsarpc pipe
 
    Copyright (C) Andrew Tridgell 2004
-   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2007
    
    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
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "includes.h"
-#include "rpc_server/dcerpc_server.h"
-#include "rpc_server/common/common.h"
-#include "auth/auth.h"
-#include "dsdb/samdb/samdb.h"
-#include "libcli/ldap/ldap.h"
-#include "lib/ldb/include/ldb_errors.h"
-#include "libcli/security/security.h"
-#include "libcli/auth/libcli_auth.h"
-#include "param/secrets.h"
-#include "db_wrap.h"
-#include "librpc/gen_ndr/ndr_dssetup.h"
-#include "param/param.h"
+#include "rpc_server/lsa/lsa.h"
 
 /*
   this type allows us to distinguish handle types
 */
-enum lsa_handle {
-       LSA_HANDLE_POLICY,
-       LSA_HANDLE_ACCOUNT,
-       LSA_HANDLE_SECRET,
-       LSA_HANDLE_TRUSTED_DOMAIN
-};
-
-/*
-  state associated with a lsa_OpenPolicy() operation
-*/
-struct lsa_policy_state {
-       struct dcesrv_handle *handle;
-       struct ldb_context *sam_ldb;
-       struct sidmap_context *sidmap;
-       uint32_t access_mask;
-       struct ldb_dn *domain_dn;
-       struct ldb_dn *forest_dn;
-       struct ldb_dn *builtin_dn;
-       struct ldb_dn *system_dn;
-       const char *domain_name;
-       const char *domain_dns;
-       const char *forest_dns;
-       struct dom_sid *domain_sid;
-       struct GUID domain_guid;
-       struct dom_sid *builtin_sid;
-       int mixed_domain;
-};
-
 
 /*
   state associated with a lsa_OpenAccount() operation
@@ -269,162 +229,6 @@ static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TA
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
-static NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                                    struct lsa_policy_state **_state)
-{
-       struct lsa_policy_state *state;
-       struct ldb_dn *partitions_basedn;
-       struct ldb_result *dom_res;
-       const char *dom_attrs[] = {
-               "objectSid", 
-               "objectGUID", 
-               "nTMixedDomain",
-               "fSMORoleOwner",
-               NULL
-       };
-       struct ldb_result *ref_res;
-       struct ldb_result *forest_ref_res;
-       const char *ref_attrs[] = {
-               "nETBIOSName",
-               "dnsRoot",
-               NULL
-       };
-       int ret;
-
-       state = talloc(mem_ctx, struct lsa_policy_state);
-       if (!state) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       /* make sure the sam database is accessible */
-       state->sam_ldb = samdb_connect(state, dce_call->conn->auth_state.session_info); 
-       if (state->sam_ldb == NULL) {
-               return NT_STATUS_INVALID_SYSTEM_SERVICE;
-       }
-
-       partitions_basedn = samdb_partitions_dn(state->sam_ldb, mem_ctx);
-
-       state->sidmap = sidmap_open(state);
-       if (state->sidmap == NULL) {
-               return NT_STATUS_INVALID_SYSTEM_SERVICE;
-       }
-
-       /* work out the domain_dn - useful for so many calls its worth
-          fetching here */
-       state->domain_dn = samdb_base_dn(state->sam_ldb);
-       if (!state->domain_dn) {
-               return NT_STATUS_NO_MEMORY;             
-       }
-
-       /* work out the forest root_dn - useful for so many calls its worth
-          fetching here */
-       state->forest_dn = samdb_root_dn(state->sam_ldb);
-       if (!state->forest_dn) {
-               return NT_STATUS_NO_MEMORY;             
-       }
-
-       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(mem_ctx, 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;                
-       }
-
-       state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
-       
-       talloc_free(dom_res);
-
-       ret = ldb_search_exp_fmt(state->sam_ldb, state, &ref_res,
-                                partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs,
-                                "(&(objectclass=crossRef)(ncName=%s))",
-                                ldb_dn_get_linearized(state->domain_dn));
-       
-       if (ret != LDB_SUCCESS) {
-               talloc_free(ref_res);
-               return NT_STATUS_INVALID_SYSTEM_SERVICE;
-       }
-       if (ref_res->count != 1) {
-               talloc_free(ref_res);
-               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) {
-               talloc_free(ref_res);
-               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) {
-               talloc_free(ref_res);
-               return NT_STATUS_NO_SUCH_DOMAIN;                
-       }
-       talloc_steal(state, state->domain_dns);
-
-       talloc_free(ref_res);
-
-       ret = ldb_search_exp_fmt(state->sam_ldb, state, &forest_ref_res,
-                                partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs,
-                                "(&(objectclass=crossRef)(ncName=%s))",
-                                ldb_dn_get_linearized(state->forest_dn));
-       
-       if (ret != LDB_SUCCESS) {
-               talloc_free(forest_ref_res);
-               return NT_STATUS_INVALID_SYSTEM_SERVICE;
-       }
-       if (forest_ref_res->count != 1) {
-               talloc_free(forest_ref_res);
-               return NT_STATUS_NO_SUCH_DOMAIN;                
-       }
-
-       state->forest_dns = ldb_msg_find_attr_as_string(forest_ref_res->msgs[0], "dnsRoot", NULL);
-       if (!state->forest_dns) {
-               talloc_free(forest_ref_res);
-               return NT_STATUS_NO_SUCH_DOMAIN;                
-       }
-       talloc_steal(state, state->forest_dns);
-
-       talloc_free(forest_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)");
-       if (!state->builtin_dn) {
-               return NT_STATUS_NO_SUCH_DOMAIN;                
-       }
-
-       /* work out the system_dn - useful for so many calls its worth
-          fetching here */
-       state->system_dn = samdb_search_dn(state->sam_ldb, state,
-                                          state->domain_dn, "(&(objectClass=container)(cn=System))");
-       if (!state->system_dn) {
-               return NT_STATUS_NO_SUCH_DOMAIN;                
-       }
-
-       state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
-       if (!state->builtin_sid) {
-               return NT_STATUS_NO_SUCH_DOMAIN;                
-       }
-
-       *_state = state;
-
-       return NT_STATUS_OK;
-}
-
 /* 
   dssetup_DsRoleGetPrimaryDomainInformation 
 
@@ -532,60 +336,6 @@ static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_cal
        return WERR_INVALID_PARAM;
 }
 
-/* 
-  lsa_OpenPolicy2
-*/
-static NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                              struct lsa_OpenPolicy2 *r)
-{
-       NTSTATUS status;
-       struct lsa_policy_state *state;
-       struct dcesrv_handle *handle;
-
-       ZERO_STRUCTP(r->out.handle);
-
-       status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_POLICY);
-       if (!handle) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       handle->data = talloc_steal(handle, state);
-
-       state->access_mask = r->in.access_mask;
-       state->handle = handle;
-       *r->out.handle = handle->wire_handle;
-
-       /* note that we have completely ignored the attr element of
-          the OpenPolicy. As far as I can tell, this is what w2k3
-          does */
-
-       return NT_STATUS_OK;
-}
-
-/* 
-  lsa_OpenPolicy
-  a wrapper around lsa_OpenPolicy2
-*/
-static NTSTATUS dcesrv_lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                               struct lsa_OpenPolicy *r)
-{
-       struct lsa_OpenPolicy2 r2;
-
-       r2.in.system_name = NULL;
-       r2.in.attr = r->in.attr;
-       r2.in.access_mask = r->in.access_mask;
-       r2.out.handle = r->out.handle;
-
-       return dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &r2);
-}
-
-
-
 
 /*
   fill in the AccountDomain info
@@ -643,6 +393,10 @@ static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call,
 
        case LSA_POLICY_INFO_DNS:
                return dcesrv_lsa_info_DNS(state, mem_ctx, &r->out.info->dns);
+       case LSA_POLICY_INFO_DB:
+       case LSA_POLICY_INFO_AUDIT_FULL_SET:
+       case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
        return NT_STATUS_INVALID_INFO_CLASS;
@@ -1473,311 +1227,6 @@ static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_ca
 }
 
 
-/*
-  return the authority name and authority sid, given a sid
-*/
-static NTSTATUS dcesrv_lsa_authority_name(struct lsa_policy_state *state,
-                                  TALLOC_CTX *mem_ctx, struct dom_sid *sid,
-                                  const char **authority_name,
-                                  struct dom_sid **authority_sid)
-{
-       if (dom_sid_in_domain(state->domain_sid, sid)) {
-               *authority_name = state->domain_name;
-               *authority_sid = state->domain_sid;
-               return NT_STATUS_OK;
-       }
-
-       if (dom_sid_in_domain(state->builtin_sid, sid)) {
-               *authority_name = "BUILTIN";
-               *authority_sid = state->builtin_sid;
-               return NT_STATUS_OK;
-       }
-
-       *authority_sid = dom_sid_dup(mem_ctx, sid);
-       if (*authority_sid == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       (*authority_sid)->num_auths = 0;
-       *authority_name = dom_sid_string(mem_ctx, *authority_sid);
-       if (*authority_name == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       return NT_STATUS_OK;
-}
-
-/*
-  add to the lsa_RefDomainList for LookupSids and LookupNames
-*/
-static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, 
-                                  struct dom_sid *sid, 
-                                  struct lsa_RefDomainList *domains,
-                                  uint32_t *sid_index)
-{
-       NTSTATUS status;
-       const char *authority_name;
-       struct dom_sid *authority_sid;
-       int i;
-
-       /* work out the authority name */
-       status = dcesrv_lsa_authority_name(state, mem_ctx, sid, 
-                                   &authority_name, &authority_sid);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-       
-       /* see if we've already done this authority name */
-       for (i=0;i<domains->count;i++) {
-               if (strcmp(authority_name, domains->domains[i].name.string) == 0) {
-                       *sid_index = i;
-                       return NT_STATUS_OK;
-               }
-       }
-
-       domains->domains = talloc_realloc(domains, 
-                                         domains->domains,
-                                         struct lsa_DomainInfo,
-                                         domains->count+1);
-       if (domains->domains == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       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;
-}
-
-/*
-  lookup a name for 1 SID
-*/
-static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
-                              struct dom_sid *sid, const char *sid_str,
-                              const char **name, uint32_t *atype)
-{
-       int ret;
-       struct ldb_message **res;
-       const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "name", NULL};
-       NTSTATUS status;
-
-       ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &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 (!*name) {
-                       *name = ldb_msg_find_attr_as_string(res[0], "name", NULL);
-                       if (!*name) {
-                               *name = talloc_strdup(mem_ctx, sid_str);
-                               NT_STATUS_HAVE_NO_MEMORY(*name);
-                       }
-               }
-
-               *atype = samdb_result_uint(res[0], "sAMAccountType", 0);
-
-               return NT_STATUS_OK;
-       }
-
-       status = sidmap_allocated_sid_lookup(state->sidmap, mem_ctx, sid, name, atype);
-
-       return status;
-}
-
-
-/*
-  lsa_LookupSids2
-*/
-static NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
-                               TALLOC_CTX *mem_ctx,
-                               struct lsa_LookupSids2 *r)
-{
-       struct lsa_policy_state *state;
-       int i;
-       NTSTATUS status = NT_STATUS_OK;
-
-       r->out.domains = NULL;
-
-       status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
-       if (r->out.domains == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       r->out.names = talloc_zero(mem_ctx,  struct lsa_TransNameArray2);
-       if (r->out.names == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       *r->out.count = 0;
-
-       r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2, 
-                                            r->in.sids->num_sids);
-       if (r->out.names->names == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       for (i=0;i<r->in.sids->num_sids;i++) {
-               struct dom_sid *sid = r->in.sids->sids[i].sid;
-               char *sid_str = dom_sid_string(mem_ctx, sid);
-               const char *name;
-               uint32_t atype, rtype, sid_index;
-               NTSTATUS status2;
-
-               r->out.names->count++;
-               (*r->out.count)++;
-
-               r->out.names->names[i].sid_type    = SID_NAME_UNKNOWN;
-               r->out.names->names[i].name.string = sid_str;
-               r->out.names->names[i].sid_index   = 0xFFFFFFFF;
-               r->out.names->names[i].unknown     = 0;
-
-               if (sid_str == NULL) {
-                       r->out.names->names[i].name.string = "(SIDERROR)";
-                       status = STATUS_SOME_UNMAPPED;
-                       continue;
-               }
-
-               /* work out the authority name */
-               status2 = dcesrv_lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
-               if (!NT_STATUS_IS_OK(status2)) {
-                       return status2;
-               }
-
-               status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str, 
-                                        &name, &atype);
-               if (!NT_STATUS_IS_OK(status2)) {
-                       status = STATUS_SOME_UNMAPPED;
-                       continue;
-               }
-
-               rtype = samdb_atype_map(atype);
-               if (rtype == SID_NAME_UNKNOWN) {
-                       status = STATUS_SOME_UNMAPPED;
-                       continue;
-               }
-
-               r->out.names->names[i].sid_type    = rtype;
-               r->out.names->names[i].name.string = name;
-               r->out.names->names[i].sid_index   = sid_index;
-               r->out.names->names[i].unknown     = 0;
-       }
-       
-       return status;
-}
-
-
-/*
-  lsa_LookupSids3
-
-  Identical to LookupSids2, but doesn't take a policy handle
-  
-*/
-static NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
-                               TALLOC_CTX *mem_ctx,
-                               struct lsa_LookupSids3 *r)
-{
-       struct lsa_LookupSids2 r2;
-       struct lsa_OpenPolicy2 pol;
-       NTSTATUS status;
-       struct dcesrv_handle *h;
-
-       /* 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);
-       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);
-
-       r2.in.sids     = r->in.sids;
-       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.out.count   = r->out.count;
-       r2.out.names   = r->out.names;
-
-       status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
-       if (dce_call->fault_code != 0) {
-               return status;
-       }
-
-       r->out.domains = r2.out.domains;
-       r->out.names   = r2.out.names;
-       r->out.count   = r2.out.count;
-
-       return status;
-}
-
-
-/* 
-  lsa_LookupSids 
-*/
-static NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                              struct lsa_LookupSids *r)
-{
-       struct lsa_LookupSids2 r2;
-       NTSTATUS status;
-       int i;
-
-       r2.in.handle   = r->in.handle;
-       r2.in.sids     = r->in.sids;
-       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.out.count   = r->out.count;
-       r2.out.names   = NULL;
-
-       status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
-       if (dce_call->fault_code != 0) {
-               return status;
-       }
-
-       r->out.domains = r2.out.domains;
-       if (!r2.out.names) {
-               r->out.names = NULL;
-               return status;
-       }
-
-       r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
-       if (r->out.names == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       r->out.names->count = r2.out.names->count;
-       r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName, 
-                                            r->out.names->count);
-       if (r->out.names->names == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       for (i=0;i<r->out.names->count;i++) {
-               r->out.names->names[i].sid_type    = r2.out.names->names[i].sid_type;
-               r->out.names->names[i].name.string = r2.out.names->names[i].name.string;
-               r->out.names->names[i].sid_index   = r2.out.names->names[i].sid_index;
-       }
-
-       return status;
-}
-
-
 /* 
   lsa_OpenAccount 
 */
@@ -3007,293 +2456,6 @@ static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
-/*
-  lookup a SID for 1 name
-*/
-static NTSTATUS dcesrv_lsa_lookup_name(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
-                               const char *name, struct dom_sid **sid, uint32_t *atype)
-{
-       int ret;
-       struct ldb_message **res;
-       const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
-       const char *p;
-
-       p = strchr_m(name, '\\');
-       if (p != NULL) {
-               /* TODO: properly parse the domain prefix here, and use it to 
-                  limit the search */
-               name = p + 1;
-       }
-
-       ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, "sAMAccountName=%s", ldb_binary_encode_string(mem_ctx, name));
-       if (ret == 1) {
-               *sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
-               if (*sid == NULL) {
-                       return NT_STATUS_INVALID_SID;
-               }
-
-               *atype = samdb_result_uint(res[0], "sAMAccountType", 0);
-
-               return NT_STATUS_OK;
-       }
-
-       /* need to add a call into sidmap to check for a allocated sid */
-
-       return NT_STATUS_INVALID_SID;
-}
-
-
-/*
-  lsa_LookupNames3
-*/
-static 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;
-       int i;
-       NTSTATUS status = NT_STATUS_OK;
-
-       DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
-
-       policy_state = policy_handle->data;
-
-       r->out.domains = NULL;
-
-       r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
-       if (r->out.domains == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray3);
-       if (r->out.sids == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       *r->out.count = 0;
-
-       r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3, 
-                                          r->in.num_names);
-       if (r->out.sids->sids == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       for (i=0;i<r->in.num_names;i++) {
-               const char *name = r->in.names[i].string;
-               struct dom_sid *sid;
-               uint32_t atype, rtype, sid_index;
-               NTSTATUS status2;
-
-               r->out.sids->count++;
-               (*r->out.count)++;
-
-               r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
-               r->out.sids->sids[i].sid         = NULL;
-               r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
-               r->out.sids->sids[i].unknown     = 0;
-
-               status2 = dcesrv_lsa_lookup_name(policy_state, mem_ctx, name, &sid, &atype);
-               if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
-                       status = STATUS_SOME_UNMAPPED;
-                       continue;
-               }
-
-               rtype = samdb_atype_map(atype);
-               if (rtype == SID_NAME_UNKNOWN) {
-                       status = STATUS_SOME_UNMAPPED;
-                       continue;
-               }
-
-               status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, sid, r->out.domains, &sid_index);
-               if (!NT_STATUS_IS_OK(status2)) {
-                       return status2;
-               }
-
-               r->out.sids->sids[i].sid_type    = rtype;
-               r->out.sids->sids[i].sid         = sid;
-               r->out.sids->sids[i].sid_index   = sid_index;
-               r->out.sids->sids[i].unknown     = 0;
-       }
-       
-       return status;
-}
-
-/* 
-  lsa_LookupNames4
-
-  Identical to LookupNames3, but doesn't take a policy handle
-  
-*/
-static 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;
-       NTSTATUS status;
-       struct dcesrv_handle *h;
-
-       /* 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);
-       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);
-
-       r2.in.num_names = r->in.num_names;
-       r2.in.names = r->in.names;
-       r2.in.sids = r->in.sids;
-       r2.in.count = r->in.count;
-       r2.in.unknown1 = r->in.unknown1;
-       r2.in.unknown2 = r->in.unknown2;
-       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);
-       if (dce_call->fault_code != 0) {
-               return status;
-       }
-       
-       r->out.domains = r2.out.domains;
-       r->out.sids = r2.out.sids;
-       r->out.count = r2.out.count;
-       return status;
-}
-
-/*
-  lsa_LookupNames2
-*/
-static NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
-                                TALLOC_CTX *mem_ctx,
-                                struct lsa_LookupNames2 *r)
-{
-       struct lsa_policy_state *state;
-       struct dcesrv_handle *h;
-       int i;
-       NTSTATUS status = NT_STATUS_OK;
-
-       r->out.domains = NULL;
-
-       DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
-
-       state = h->data;
-
-       r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
-       if (r->out.domains == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray2);
-       if (r->out.sids == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       *r->out.count = 0;
-
-       r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2, 
-                                          r->in.num_names);
-       if (r->out.sids->sids == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       for (i=0;i<r->in.num_names;i++) {
-               const char *name = r->in.names[i].string;
-               struct dom_sid *sid;
-               uint32_t atype, rtype, sid_index;
-               NTSTATUS status2;
-
-               r->out.sids->count++;
-               (*r->out.count)++;
-
-               r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
-               r->out.sids->sids[i].rid         = 0xFFFFFFFF;
-               r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
-               r->out.sids->sids[i].unknown     = 0;
-
-               status2 = dcesrv_lsa_lookup_name(state, mem_ctx, name, &sid, &atype);
-               if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
-                       status = STATUS_SOME_UNMAPPED;
-                       continue;
-               }
-
-               rtype = samdb_atype_map(atype);
-               if (rtype == SID_NAME_UNKNOWN) {
-                       status = STATUS_SOME_UNMAPPED;
-                       continue;
-               }
-
-               status2 = dcesrv_lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
-               if (!NT_STATUS_IS_OK(status2)) {
-                       return status2;
-               }
-
-               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].sid_index   = sid_index;
-               r->out.sids->sids[i].unknown     = 0;
-       }
-       
-       return status;
-}
-
-/* 
-  lsa_LookupNames 
-*/
-static NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_LookupNames *r)
-{
-       struct lsa_LookupNames2 r2;
-       NTSTATUS status;
-       int i;
-
-       r2.in.handle    = r->in.handle;
-       r2.in.num_names = r->in.num_names;
-       r2.in.names     = r->in.names;
-       r2.in.sids      = NULL;
-       r2.in.level     = r->in.level;
-       r2.in.count     = r->in.count;
-       r2.in.unknown1  = 0;
-       r2.in.unknown2  = 0;
-       r2.out.count    = r->out.count;
-
-       status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
-       if (dce_call->fault_code != 0) {
-               return status;
-       }
-
-       r->out.domains = r2.out.domains;
-       r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
-       if (r->out.sids == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       r->out.sids->count = r2.out.sids->count;
-       r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid, 
-                                          r->out.sids->count);
-       if (r->out.sids->sids == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       for (i=0;i<r->out.sids->count;i++) {
-               r->out.sids->sids[i].sid_type    = r2.out.sids->sids[i].sid_type;
-               r->out.sids->sids[i].rid         = r2.out.sids->sids[i].rid;
-               r->out.sids->sids[i].sid_index   = r2.out.sids->sids[i].sid_index;
-       }
-
-       return status;
-}
-
 /* 
   lsa_CREDRWRITE 
 */
diff --git a/source4/rpc_server/lsa/lsa.h b/source4/rpc_server/lsa/lsa.h
new file mode 100644 (file)
index 0000000..6ecda0f
--- /dev/null
@@ -0,0 +1,69 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   endpoint server for the lsarpc pipe
+
+   Copyright (C) Andrew Tridgell 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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "rpc_server/dcerpc_server.h"
+#include "rpc_server/common/common.h"
+#include "auth/auth.h"
+#include "dsdb/samdb/samdb.h"
+#include "libcli/ldap/ldap.h"
+#include "lib/ldb/include/ldb_errors.h"
+#include "libcli/security/security.h"
+#include "libcli/auth/libcli_auth.h"
+#include "param/secrets.h"
+#include "db_wrap.h"
+#include "librpc/gen_ndr/ndr_dssetup.h"
+#include "param/param.h"
+
+/*
+  state associated with a lsa_OpenPolicy() operation
+*/
+struct lsa_policy_state {
+       struct dcesrv_handle *handle;
+       struct ldb_context *sam_ldb;
+       struct sidmap_context *sidmap;
+       uint32_t access_mask;
+       struct ldb_dn *domain_dn;
+       struct ldb_dn *forest_dn;
+       struct ldb_dn *builtin_dn;
+       struct ldb_dn *system_dn;
+       const char *domain_name;
+       const char *domain_dns;
+       const char *forest_dns;
+       struct dom_sid *domain_sid;
+       struct GUID domain_guid;
+       struct dom_sid *builtin_sid;
+       struct dom_sid *nt_authority_sid;
+       struct dom_sid *creator_owner_domain_sid;
+       struct dom_sid *world_domain_sid;
+       int mixed_domain;
+};
+
+enum lsa_handle {
+       LSA_HANDLE_POLICY,
+       LSA_HANDLE_ACCOUNT,
+       LSA_HANDLE_SECRET,
+       LSA_HANDLE_TRUSTED_DOMAIN
+};
+
+#include "rpc_server/lsa/proto.h"
+
diff --git a/source4/rpc_server/lsa/lsa_init.c b/source4/rpc_server/lsa/lsa_init.c
new file mode 100644 (file)
index 0000000..6cf062a
--- /dev/null
@@ -0,0 +1,248 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   endpoint server for the lsarpc pipe
+
+   Copyright (C) Andrew Tridgell 2004
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2007
+   
+   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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rpc_server/lsa/lsa.h"
+
+NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                    struct lsa_policy_state **_state)
+{
+       struct lsa_policy_state *state;
+       struct ldb_dn *partitions_basedn;
+       struct ldb_result *dom_res;
+       const char *dom_attrs[] = {
+               "objectSid", 
+               "objectGUID", 
+               "nTMixedDomain",
+               "fSMORoleOwner",
+               NULL
+       };
+       struct ldb_result *ref_res;
+       struct ldb_result *forest_ref_res;
+       const char *ref_attrs[] = {
+               "nETBIOSName",
+               "dnsRoot",
+               NULL
+       };
+       int ret;
+
+       state = talloc(mem_ctx, struct lsa_policy_state);
+       if (!state) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* make sure the sam database is accessible */
+       state->sam_ldb = samdb_connect(state, dce_call->conn->auth_state.session_info); 
+       if (state->sam_ldb == NULL) {
+               return NT_STATUS_INVALID_SYSTEM_SERVICE;
+       }
+
+       partitions_basedn = samdb_partitions_dn(state->sam_ldb, mem_ctx);
+
+       state->sidmap = sidmap_open(state);
+       if (state->sidmap == NULL) {
+               return NT_STATUS_INVALID_SYSTEM_SERVICE;
+       }
+
+       /* work out the domain_dn - useful for so many calls its worth
+          fetching here */
+       state->domain_dn = samdb_base_dn(state->sam_ldb);
+       if (!state->domain_dn) {
+               return NT_STATUS_NO_MEMORY;             
+       }
+
+       /* work out the forest root_dn - useful for so many calls its worth
+          fetching here */
+       state->forest_dn = samdb_root_dn(state->sam_ldb);
+       if (!state->forest_dn) {
+               return NT_STATUS_NO_MEMORY;             
+       }
+
+       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(mem_ctx, 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;                
+       }
+
+       state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
+       
+       talloc_free(dom_res);
+
+       ret = ldb_search_exp_fmt(state->sam_ldb, state, &ref_res,
+                                partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs,
+                                "(&(objectclass=crossRef)(ncName=%s))",
+                                ldb_dn_get_linearized(state->domain_dn));
+       
+       if (ret != LDB_SUCCESS) {
+               talloc_free(ref_res);
+               return NT_STATUS_INVALID_SYSTEM_SERVICE;
+       }
+       if (ref_res->count != 1) {
+               talloc_free(ref_res);
+               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) {
+               talloc_free(ref_res);
+               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) {
+               talloc_free(ref_res);
+               return NT_STATUS_NO_SUCH_DOMAIN;                
+       }
+       talloc_steal(state, state->domain_dns);
+
+       talloc_free(ref_res);
+
+       ret = ldb_search_exp_fmt(state->sam_ldb, state, &forest_ref_res,
+                                partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs,
+                                "(&(objectclass=crossRef)(ncName=%s))",
+                                ldb_dn_get_linearized(state->forest_dn));
+       
+       if (ret != LDB_SUCCESS) {
+               talloc_free(forest_ref_res);
+               return NT_STATUS_INVALID_SYSTEM_SERVICE;
+       }
+       if (forest_ref_res->count != 1) {
+               talloc_free(forest_ref_res);
+               return NT_STATUS_NO_SUCH_DOMAIN;                
+       }
+
+       state->forest_dns = ldb_msg_find_attr_as_string(forest_ref_res->msgs[0], "dnsRoot", NULL);
+       if (!state->forest_dns) {
+               talloc_free(forest_ref_res);
+               return NT_STATUS_NO_SUCH_DOMAIN;                
+       }
+       talloc_steal(state, state->forest_dns);
+
+       talloc_free(forest_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)");
+       if (!state->builtin_dn) {
+               return NT_STATUS_NO_SUCH_DOMAIN;                
+       }
+
+       /* work out the system_dn - useful for so many calls its worth
+          fetching here */
+       state->system_dn = samdb_search_dn(state->sam_ldb, state,
+                                          state->domain_dn, "(&(objectClass=container)(cn=System))");
+       if (!state->system_dn) {
+               return NT_STATUS_NO_SUCH_DOMAIN;                
+       }
+
+       state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
+       if (!state->builtin_sid) {
+               return NT_STATUS_NO_SUCH_DOMAIN;                
+       }
+
+       state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY);
+       if (!state->nt_authority_sid) {
+               return NT_STATUS_NO_SUCH_DOMAIN;                
+       }
+
+       state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN);
+       if (!state->creator_owner_domain_sid) {
+               return NT_STATUS_NO_SUCH_DOMAIN;                
+       }
+
+       state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN);
+       if (!state->world_domain_sid) {
+               return NT_STATUS_NO_SUCH_DOMAIN;                
+       }
+
+       *_state = state;
+
+       return NT_STATUS_OK;
+}
+
+/* 
+  lsa_OpenPolicy2
+*/
+NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                               struct lsa_OpenPolicy2 *r)
+{
+       NTSTATUS status;
+       struct lsa_policy_state *state;
+       struct dcesrv_handle *handle;
+
+       ZERO_STRUCTP(r->out.handle);
+
+       status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_POLICY);
+       if (!handle) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       handle->data = talloc_steal(handle, state);
+
+       state->access_mask = r->in.access_mask;
+       state->handle = handle;
+       *r->out.handle = handle->wire_handle;
+
+       /* note that we have completely ignored the attr element of
+          the OpenPolicy. As far as I can tell, this is what w2k3
+          does */
+
+       return NT_STATUS_OK;
+}
+
+/* 
+  lsa_OpenPolicy
+  a wrapper around lsa_OpenPolicy2
+*/
+NTSTATUS dcesrv_lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                               struct lsa_OpenPolicy *r)
+{
+       struct lsa_OpenPolicy2 r2;
+
+       r2.in.system_name = NULL;
+       r2.in.attr = r->in.attr;
+       r2.in.access_mask = r->in.access_mask;
+       r2.out.handle = r->out.handle;
+
+       return dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &r2);
+}
+
+
diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c
new file mode 100644 (file)
index 0000000..4ca3e4d
--- /dev/null
@@ -0,0 +1,928 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   endpoint server for the lsarpc pipe
+
+   Copyright (C) Andrew Tridgell 2004
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2007
+   
+   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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rpc_server/lsa/lsa.h"
+
+static const struct {
+       const char *domain;
+       const char *name;
+       const char *sid;
+       int rtype;
+} well_known[] = {
+       {
+               .name = "EVERYONE",
+               .sid = SID_WORLD,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .name = "CREATOR OWNER",
+               .sid = SID_CREATOR_OWNER,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .name = "CREATOR GROUP",
+               .sid = SID_CREATOR_OWNER,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "Dialup",
+               .sid = SID_NT_DIALUP,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "Network",
+               .sid = SID_NT_DIALUP,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "Batch",
+               .sid = SID_NT_BATCH,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "Interactive",
+               .sid = SID_NT_INTERACTIVE,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "Service",
+               .sid = SID_NT_SERVICE,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "ANONYMOUS LOGON",
+               .sid = SID_NT_ANONYMOUS,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "Proxy",
+               .sid = SID_NT_PROXY,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "ServerLogon",
+               .sid = SID_NT_ENTERPRISE_DCS,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "Self",
+               .sid = SID_NT_SELF,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "Authenticated Users",
+               .sid = SID_NT_AUTHENTICATED_USERS,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "Restricted",
+               .sid = SID_NT_RESTRICTED,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "Termainal Server User",
+               .sid = SID_NT_TERMINAL_SERVER_USERS,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "Remote Interactive Logon",
+               .sid = SID_NT_REMOTE_INTERACTIVE,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "This Organization",
+               .sid = SID_NT_THIS_ORGANISATION,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "SYSTEM",
+               .sid = SID_NT_SYSTEM,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "Local Service",
+               .sid = SID_NT_LOCAL_SERVICE,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .domain = "NT AUTHORITY",
+               .name = "Network Service",
+               .sid = SID_NT_NETWORK_SERVICE,
+               .rtype = SID_NAME_WKN_GRP,
+       },
+       {
+               .sid = NULL,
+       }
+};
+
+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) 
+{
+       int i;
+       for (i=0; well_known[i].sid; i++) {
+               if (domain) {
+                       if (strcasecmp_m(domain, well_known[i].domain) == 0
+                           && strcasecmp_m(name, well_known[i].name) == 0) {
+                               *authority_name = well_known[i].domain;
+                               *sid = dom_sid_parse_talloc(mem_ctx, well_known[i].sid);
+                               *rtype = well_known[i].rtype;
+                               return NT_STATUS_OK;
+                       }
+               } else {
+                       if (strcasecmp_m(name, well_known[i].name) == 0) {
+                               *authority_name = well_known[i].domain;
+                               *sid = dom_sid_parse_talloc(mem_ctx, well_known[i].sid);
+                               *rtype = well_known[i].rtype;
+                               return NT_STATUS_OK;
+                       }
+               }
+       }
+       return NT_STATUS_NOT_FOUND;     
+}
+
+static NTSTATUS lookup_well_known_sids(TALLOC_CTX *mem_ctx, 
+                                      const char *sid_str, const char **authority_name, 
+                                      const char **name, uint32_t *rtype) 
+{
+       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;
+                       *name = well_known[i].name;
+                       *rtype = well_known[i].rtype;
+                       return NT_STATUS_OK;
+               }
+       }
+       return NT_STATUS_NOT_FOUND;     
+}
+
+/*
+  lookup a SID for 1 name
+*/
+static NTSTATUS dcesrv_lsa_lookup_name(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
+                               const char *name, const char **authority_name, 
+                               struct dom_sid **sid, enum lsa_SidType *rtype)
+{
+       int ret, atype, i;
+       struct ldb_message **res;
+       const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
+       const char *p;
+       const char *domain;
+       const char *username;
+       struct ldb_dn *domain_dn;
+       struct dom_sid *domain_sid;
+       NTSTATUS status;
+
+       p = strchr_m(name, '\\');
+       if (p != NULL) {
+               domain = talloc_strndup(mem_ctx, name, p-name);
+               if (!domain) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               username = p + 1;
+       } else if (strchr_m(name, '@')) {
+               status = crack_name_to_nt4_name(mem_ctx, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, name, &domain, &username);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+       } else {
+               domain = NULL;
+               username = name;
+       }
+       
+       if (!domain) {
+               /* 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)) {
+                       return NT_STATUS_OK;
+               }
+
+               if (strcasecmp_m(username, NAME_NT_AUTHORITY) == 0) { 
+                       *authority_name = NAME_NT_AUTHORITY;
+                       *sid =  dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
+                       *rtype = SID_NAME_DOMAIN;
+                       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;
+                       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;
+                       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;
+                       return NT_STATUS_OK;
+               }
+               
+               /* Perhaps this is a well known user? */
+               name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username);
+               if (!name) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               status = dcesrv_lsa_lookup_name(state, mem_ctx, name, authority_name, sid, rtype);
+               if (NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
+               /* Perhaps this is a BUILTIN user? */
+               name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username);
+               if (!name) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               status = dcesrv_lsa_lookup_name(state, mem_ctx, name, authority_name, sid, rtype);
+               if (NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
+               /* OK, I give up - perhaps we need to assume the user is in our domain? */
+               name = talloc_asprintf(mem_ctx, "%s\\%s", state->domain_name, username);
+               if (!name) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               status = dcesrv_lsa_lookup_name(state, mem_ctx, name, authority_name, sid, rtype);
+               if (NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
+               return STATUS_SOME_UNMAPPED;
+       } else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) {
+               if (!*username) {
+                       *authority_name = NAME_NT_AUTHORITY;
+                       *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
+                       *rtype = SID_NAME_DOMAIN;
+                       return NT_STATUS_OK;
+               }
+
+               /* Look up table of well known names */
+               return lookup_well_known_names(mem_ctx, domain, username, authority_name, 
+                                              sid, rtype);
+       } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) {
+               *authority_name = NAME_BUILTIN;
+               domain_dn = state->builtin_dn;
+       } else if (strcasecmp_m(domain, state->domain_dns) == 0) { 
+               *authority_name = state->domain_name;
+               domain_dn = state->domain_dn;
+       } else if (strcasecmp_m(domain, state->domain_name) == 0) { 
+               *authority_name = state->domain_name;
+               domain_dn = state->domain_dn;
+       } else {
+               /* Not local, need to ask winbind in future */
+               return STATUS_SOME_UNMAPPED;
+       }
+
+       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 {
+               return NT_STATUS_INVALID_SID;
+       }
+
+       if (!*username) {
+               *sid = domain_sid;
+               *rtype = SID_NAME_DOMAIN;
+               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;
+       }
+
+       for (i=0; i < ret; i++) {
+               *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
+               if (*sid == NULL) {
+                       return NT_STATUS_INVALID_SID;
+               }
+
+               /* Check that this is in the domain */
+               if (!dom_sid_in_domain(domain_sid, *sid)) {
+                       continue;
+               }
+
+               atype = samdb_result_uint(res[i], "sAMAccountType", 0);
+                       
+               *rtype = samdb_atype_map(atype);
+               if (*rtype == SID_NAME_UNKNOWN) {
+                       return STATUS_SOME_UNMAPPED;
+               }
+
+               return NT_STATUS_OK;
+       }
+
+       /* need to add a call into sidmap to check for a allocated sid */
+
+       return NT_STATUS_INVALID_SID;
+}
+
+
+/*
+  add to the lsa_RefDomainList for LookupSids and LookupNames
+*/
+static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, 
+                                         enum lsa_SidType rtype,
+                                         const char *authority_name,
+                                         struct dom_sid *sid, 
+                                         struct lsa_RefDomainList *domains,
+                                         uint32_t *sid_index)
+{
+       struct dom_sid *authority_sid;
+       int i;
+
+       if (rtype != SID_NAME_DOMAIN) {
+               authority_sid = dom_sid_dup(mem_ctx, sid);
+               if (authority_sid == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               authority_sid->num_auths--;
+       } else {
+               authority_sid = sid;
+       }
+
+       /* see if we've already done this authority name */
+       for (i=0;i<domains->count;i++) {
+               if (strcasecmp_m(authority_name, domains->domains[i].name.string) == 0) {
+                       *sid_index = i;
+                       return NT_STATUS_OK;
+               }
+       }
+
+       domains->domains = talloc_realloc(domains, 
+                                         domains->domains,
+                                         struct lsa_DomainInfo,
+                                         domains->count+1);
+       if (domains->domains == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       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;
+}
+
+/*
+  lookup a name for 1 SID
+*/
+static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
+                                     struct dom_sid *sid, const char *sid_str,
+                                     const char **authority_name, 
+                                     const char **name, enum lsa_SidType *rtype)
+{
+       NTSTATUS status;
+       int ret;
+       uint32_t atype;
+       struct ldb_message **res;
+       struct ldb_dn *domain_dn;
+       const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "cn", NULL};
+
+       status = lookup_well_known_sids(mem_ctx, sid_str, authority_name, name, rtype);
+       if (NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (dom_sid_in_domain(state->domain_sid, sid)) {
+               *authority_name = state->domain_name;
+               domain_dn = state->domain_dn;
+       } else if (dom_sid_in_domain(state->builtin_sid, sid)) {
+               *authority_name = NAME_BUILTIN;
+               domain_dn = state->builtin_dn;
+       } else {
+               /* Not well known, our domain or built in */
+
+               /* In future, we must look at SID histories, and at trusted domains via winbind */
+
+               return NT_STATUS_NOT_FOUND;
+       }
+
+       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 (!*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);
+                       }
+               }
+
+               atype = samdb_result_uint(res[0], "sAMAccountType", 0);
+
+               *rtype = samdb_atype_map(atype);
+
+               return NT_STATUS_OK;
+       }
+
+       /* need to re-add a call into sidmap to check for a allocated sid */
+       /* status = sidmap_allocated_sid_lookup(state->sidmap, mem_ctx, sid, name, rtype); */
+
+       return NT_STATUS_NOT_FOUND;
+}
+
+
+/*
+  lsa_LookupSids2
+*/
+NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
+                               TALLOC_CTX *mem_ctx,
+                               struct lsa_LookupSids2 *r)
+{
+       struct lsa_policy_state *state;
+       int i;
+       NTSTATUS status = NT_STATUS_OK;
+
+       r->out.domains = NULL;
+
+       status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
+       if (r->out.domains == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       r->out.names = talloc_zero(mem_ctx,  struct lsa_TransNameArray2);
+       if (r->out.names == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       *r->out.count = 0;
+
+       r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2, 
+                                            r->in.sids->num_sids);
+       if (r->out.names->names == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0;i<r->in.sids->num_sids;i++) {
+               struct dom_sid *sid = r->in.sids->sids[i].sid;
+               char *sid_str = dom_sid_string(mem_ctx, sid);
+               const char *name, *authority_name;
+               enum lsa_SidType rtype;
+               uint32_t sid_index;
+               NTSTATUS status2;
+
+               r->out.names->count++;
+
+               r->out.names->names[i].sid_type    = SID_NAME_UNKNOWN;
+               r->out.names->names[i].name.string = sid_str;
+               r->out.names->names[i].sid_index   = 0xFFFFFFFF;
+               r->out.names->names[i].unknown     = 0;
+
+               if (sid_str == NULL) {
+                       r->out.names->names[i].name.string = "(SIDERROR)";
+                       status = STATUS_SOME_UNMAPPED;
+                       continue;
+               }
+
+               status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str, 
+                                               &authority_name, &name, &rtype);
+               if (!NT_STATUS_IS_OK(status2)) {
+                       status = STATUS_SOME_UNMAPPED;
+                       continue;
+               }
+
+               /* set up the authority table */
+               status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, 
+                                                   authority_name, sid, 
+                                                   r->out.domains, &sid_index);
+               if (!NT_STATUS_IS_OK(status2)) {
+                       return status2;
+               }
+
+               r->out.names->names[i].sid_type    = rtype;
+               r->out.names->names[i].name.string = name;
+               r->out.names->names[i].sid_index   = sid_index;
+               r->out.names->names[i].unknown     = 0;
+
+               (*r->out.count)++;
+       }
+       
+       if (*r->out.count == 0) {
+               return NT_STATUS_NONE_MAPPED;
+       }
+       if (*r->out.count != r->in.sids->num_sids) {
+               return STATUS_SOME_UNMAPPED;
+       }
+
+       return NT_STATUS_OK;
+}
+
+
+/*
+  lsa_LookupSids3
+
+  Identical to LookupSids2, but doesn't take a policy handle
+  
+*/
+NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
+                               TALLOC_CTX *mem_ctx,
+                               struct lsa_LookupSids3 *r)
+{
+       struct lsa_LookupSids2 r2;
+       struct lsa_OpenPolicy2 pol;
+       NTSTATUS status;
+       struct dcesrv_handle *h;
+
+       /* 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);
+       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);
+
+       r2.in.sids     = r->in.sids;
+       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.out.count   = r->out.count;
+       r2.out.names   = r->out.names;
+
+       status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
+       if (dce_call->fault_code != 0) {
+               return status;
+       }
+
+       r->out.domains = r2.out.domains;
+       r->out.names   = r2.out.names;
+       r->out.count   = r2.out.count;
+
+       return status;
+}
+
+
+/* 
+  lsa_LookupSids 
+*/
+NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                              struct lsa_LookupSids *r)
+{
+       struct lsa_LookupSids2 r2;
+       NTSTATUS status;
+       int i;
+
+       r2.in.handle   = r->in.handle;
+       r2.in.sids     = r->in.sids;
+       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.out.count   = r->out.count;
+       r2.out.names   = NULL;
+
+       status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
+       if (dce_call->fault_code != 0) {
+               return status;
+       }
+
+       r->out.domains = r2.out.domains;
+       if (!r2.out.names) {
+               r->out.names = NULL;
+               return status;
+       }
+
+       r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
+       if (r->out.names == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       r->out.names->count = r2.out.names->count;
+       r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName, 
+                                            r->out.names->count);
+       if (r->out.names->names == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       for (i=0;i<r->out.names->count;i++) {
+               r->out.names->names[i].sid_type    = r2.out.names->names[i].sid_type;
+               r->out.names->names[i].name.string = r2.out.names->names[i].name.string;
+               r->out.names->names[i].sid_index   = r2.out.names->names[i].sid_index;
+       }
+
+       return status;
+}
+
+
+/*
+  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;
+       int i;
+
+       DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
+
+       policy_state = policy_handle->data;
+
+       r->out.domains = NULL;
+
+       r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
+       if (r->out.domains == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray3);
+       if (r->out.sids == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       *r->out.count = 0;
+
+       r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3, 
+                                          r->in.num_names);
+       if (r->out.sids->sids == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0;i<r->in.num_names;i++) {
+               const char *name = r->in.names[i].string;
+               const char *authority_name;
+               struct dom_sid *sid;
+               uint32_t sid_index;
+               enum lsa_SidType rtype;
+               NTSTATUS status2;
+
+               r->out.sids->count++;
+
+               r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
+               r->out.sids->sids[i].sid         = NULL;
+               r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
+               r->out.sids->sids[i].unknown     = 0;
+
+               status2 = dcesrv_lsa_lookup_name(policy_state, mem_ctx, name, &authority_name, &sid, &rtype);
+               if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
+                       continue;
+               }
+
+               status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, authority_name, 
+                                                   sid, r->out.domains, &sid_index);
+               if (!NT_STATUS_IS_OK(status2)) {
+                       return status2;
+               }
+
+               r->out.sids->sids[i].sid_type    = rtype;
+               r->out.sids->sids[i].sid         = sid;
+               r->out.sids->sids[i].sid_index   = sid_index;
+               r->out.sids->sids[i].unknown     = 0;
+
+               (*r->out.count)++;
+       }
+       
+       if (*r->out.count == 0) {
+               return NT_STATUS_NONE_MAPPED;
+       }
+       if (*r->out.count != r->in.num_names) {
+               return STATUS_SOME_UNMAPPED;
+       }
+
+       return NT_STATUS_OK;
+}
+
+/* 
+  lsa_LookupNames4
+
+  Identical to LookupNames3, but doesn't take a policy handle
+  
+*/
+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;
+       NTSTATUS status;
+       struct dcesrv_handle *h;
+
+       /* 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);
+       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);
+
+       r2.in.num_names = r->in.num_names;
+       r2.in.names = r->in.names;
+       r2.in.sids = r->in.sids;
+       r2.in.count = r->in.count;
+       r2.in.unknown1 = r->in.unknown1;
+       r2.in.unknown2 = r->in.unknown2;
+       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);
+       if (dce_call->fault_code != 0) {
+               return status;
+       }
+       
+       r->out.domains = r2.out.domains;
+       r->out.sids = r2.out.sids;
+       r->out.count = r2.out.count;
+       return status;
+}
+
+/*
+  lsa_LookupNames2
+*/
+NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
+                                TALLOC_CTX *mem_ctx,
+                                struct lsa_LookupNames2 *r)
+{
+       struct lsa_policy_state *state;
+       struct dcesrv_handle *h;
+       int i;
+
+       r->out.domains = NULL;
+
+       DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
+
+       state = h->data;
+
+       r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
+       if (r->out.domains == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray2);
+       if (r->out.sids == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       *r->out.count = 0;
+
+       r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2, 
+                                          r->in.num_names);
+       if (r->out.sids->sids == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0;i<r->in.num_names;i++) {
+               const char *name = r->in.names[i].string;
+               const char *authority_name;
+               struct dom_sid *sid;
+               uint32_t rtype, sid_index;
+               NTSTATUS status2;
+
+               r->out.sids->count++;
+
+               r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
+               r->out.sids->sids[i].rid         = 0xFFFFFFFF;
+               r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
+               r->out.sids->sids[i].unknown     = 0;
+
+               status2 = dcesrv_lsa_lookup_name(state, mem_ctx, name, 
+                                                &authority_name, &sid, &rtype);
+               if (!NT_STATUS_IS_OK(status2)) {
+                       continue;
+               }
+
+               status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, authority_name, 
+                                                   sid, r->out.domains, &sid_index);
+               if (!NT_STATUS_IS_OK(status2)) {
+                       return status2;
+               }
+
+               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].sid_index   = sid_index;
+               r->out.sids->sids[i].unknown     = 0;
+
+               (*r->out.count)++;
+       }
+       
+       if (*r->out.count == 0) {
+               return NT_STATUS_NONE_MAPPED;
+       }
+       if (*r->out.count != r->in.num_names) {
+               return STATUS_SOME_UNMAPPED;
+       }
+
+       return NT_STATUS_OK;
+}
+
+/* 
+  lsa_LookupNames 
+*/
+NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct lsa_LookupNames *r)
+{
+       struct lsa_LookupNames2 r2;
+       NTSTATUS status;
+       int i;
+
+       r2.in.handle    = r->in.handle;
+       r2.in.num_names = r->in.num_names;
+       r2.in.names     = r->in.names;
+       r2.in.sids      = NULL;
+       r2.in.level     = r->in.level;
+       r2.in.count     = r->in.count;
+       r2.in.unknown1  = 0;
+       r2.in.unknown2  = 0;
+       r2.out.count    = r->out.count;
+
+       status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
+       if (dce_call->fault_code != 0) {
+               return status;
+       }
+
+       r->out.domains = r2.out.domains;
+       r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
+       if (r->out.sids == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       r->out.sids->count = r2.out.sids->count;
+       r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid, 
+                                          r->out.sids->count);
+       if (r->out.sids->sids == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       for (i=0;i<r->out.sids->count;i++) {
+               r->out.sids->sids[i].sid_type    = r2.out.sids->sids[i].sid_type;
+               r->out.sids->sids[i].rid         = r2.out.sids->sids[i].rid;
+               r->out.sids->sids[i].sid_index   = r2.out.sids->sids[i].sid_index;
+       }
+
+       return status;
+}
+
index 2cc2b78a788ba52e2a89976d8bc1a1313b7fbcef..00fc30414d701e5d7453a2aa557c3391814cdc6c 100644 (file)
@@ -128,7 +128,7 @@ BOOL test_lsa_OpenPolicy2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 static BOOL test_LookupNames(struct dcerpc_pipe *p, 
                            TALLOC_CTX *mem_ctx, 
                            struct policy_handle *handle,
-                           struct lsa_TransNameArray *tnames)
+                            struct lsa_TransNameArray *tnames)
 {
        struct lsa_LookupNames r;
        struct lsa_TransSidArray sids;
@@ -157,7 +157,55 @@ static BOOL test_LookupNames(struct dcerpc_pipe *p,
        r.out.sids = &sids;
 
        status = dcerpc_lsa_LookupNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("LookupNames failed - %s\n", nt_errstr(status));
+               return False;
+       }
+
+       printf("\n");
+
+       return True;
+}
+
+static BOOL test_LookupNames_bogus(struct dcerpc_pipe *p, 
+                           TALLOC_CTX *mem_ctx, 
+                           struct policy_handle *handle)
+{
+       struct lsa_LookupNames r;
+       struct lsa_TransSidArray sids;
+       struct lsa_String *names;
+       uint32_t count = 0;
+       NTSTATUS status;
+       int i;
+
+       struct lsa_TranslatedName name;
+       struct lsa_TransNameArray tnames;
+
+       tnames.names = &name;
+       tnames.count = 1;
+       name.name.string = "NT AUTHORITY\\BOGUS";
+
+       printf("\nTesting LookupNames with bogus names\n");
+
+       sids.count = 0;
+       sids.sids = NULL;
+
+       names = talloc_array(mem_ctx, struct lsa_String, tnames.count);
+       for (i=0;i<tnames.count;i++) {
+               init_lsa_String(&names[i], tnames.names[i].name.string);
+       }
+
+       r.in.handle = handle;
+       r.in.num_names = tnames.count;
+       r.in.names = names;
+       r.in.sids = &sids;
+       r.in.level = 1;
+       r.in.count = &count;
+       r.out.count = &count;
+       r.out.sids = &sids;
+
+       status = dcerpc_lsa_LookupNames(p, mem_ctx, &r);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
                printf("LookupNames failed - %s\n", nt_errstr(status));
                return False;
        }
@@ -167,6 +215,47 @@ static BOOL test_LookupNames(struct dcerpc_pipe *p,
        return True;
 }
 
+static BOOL test_LookupNames_wellknown(struct dcerpc_pipe *p, 
+                                      TALLOC_CTX *mem_ctx, 
+                                      struct policy_handle *handle)
+{
+       struct lsa_TranslatedName name;
+       struct lsa_TransNameArray tnames;
+       bool ret = true;
+
+       printf("Testing LookupNames with well known names\n");
+
+       tnames.names = &name;
+       tnames.count = 1;
+       name.name.string = "NT AUTHORITY\\SYSTEM";
+       ret &= test_LookupNames(p, mem_ctx, handle, &tnames);
+
+       name.name.string = "NT AUTHORITY\\ANONYMOUS LOGON";
+       ret &= test_LookupNames(p, mem_ctx, handle, &tnames);
+
+       name.name.string = "NT AUTHORITY\\Authenticated Users";
+       ret &= test_LookupNames(p, mem_ctx, handle, &tnames);
+
+       name.name.string = "NT AUTHORITY";
+       ret &= test_LookupNames(p, mem_ctx, handle, &tnames);
+
+       name.name.string = "NT AUTHORITY\\";
+       ret &= test_LookupNames(p, mem_ctx, handle, &tnames);
+
+       name.name.string = "BUILTIN\\";
+       ret &= test_LookupNames(p, mem_ctx, handle, &tnames);
+
+       name.name.string = "BUILTIN\\Administrators";
+       ret &= test_LookupNames(p, mem_ctx, handle, &tnames);
+
+       name.name.string = "SYSTEM";
+       ret &= test_LookupNames(p, mem_ctx, handle, &tnames);
+
+       name.name.string = "Everyone";
+       ret &= test_LookupNames(p, mem_ctx, handle, &tnames);
+       return ret;
+}
+
 static BOOL test_LookupNames2(struct dcerpc_pipe *p, 
                              TALLOC_CTX *mem_ctx, 
                              struct policy_handle *handle,
@@ -201,7 +290,7 @@ static BOOL test_LookupNames2(struct dcerpc_pipe *p,
        r.out.sids = &sids;
 
        status = dcerpc_lsa_LookupNames2(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
+       if (!NT_STATUS_IS_OK(status)) {
                printf("LookupNames2 failed - %s\n", nt_errstr(status));
                return False;
        }
@@ -246,7 +335,7 @@ static BOOL test_LookupNames3(struct dcerpc_pipe *p,
        r.out.sids = &sids;
 
        status = dcerpc_lsa_LookupNames3(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
+       if (!NT_STATUS_IS_OK(status)) {
                printf("LookupNames3 failed - %s\n", nt_errstr(status));
                return False;
        }
@@ -288,7 +377,7 @@ static BOOL test_LookupNames4(struct dcerpc_pipe *p,
        r.out.sids = &sids;
 
        status = dcerpc_lsa_LookupNames4(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
+       if (!NT_STATUS_IS_OK(status)) {
                printf("LookupNames4 failed - %s\n", nt_errstr(status));
                return False;
        }
@@ -323,7 +412,7 @@ static BOOL test_LookupSids(struct dcerpc_pipe *p,
        r.out.names = &names;
 
        status = dcerpc_lsa_LookupSids(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
+       if (!NT_STATUS_IS_OK(status)) {
                printf("LookupSids failed - %s\n", nt_errstr(status));
                return False;
        }
@@ -364,7 +453,7 @@ static BOOL test_LookupSids2(struct dcerpc_pipe *p,
        r.out.names = &names;
 
        status = dcerpc_lsa_LookupSids2(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
+       if (!NT_STATUS_IS_OK(status)) {
                printf("LookupSids2 failed - %s\n", nt_errstr(status));
                return False;
        }
@@ -406,7 +495,7 @@ static BOOL test_LookupSids3(struct dcerpc_pipe *p,
        r.out.names = &names;
 
        status = dcerpc_lsa_LookupSids3(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
+       if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
                    NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED)) {
                        printf("not considering %s to be an error\n", nt_errstr(status));
@@ -463,8 +552,7 @@ BOOL test_many_LookupSids(struct dcerpc_pipe *p,
                r.out.names = &names;
                
                status = dcerpc_lsa_LookupSids(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status) &&
-                   !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
+               if (!NT_STATUS_IS_OK(status)) {
                        printf("LookupSids failed - %s\n", nt_errstr(status));
                        return False;
                }
@@ -493,7 +581,7 @@ BOOL test_many_LookupSids(struct dcerpc_pipe *p,
                r.out.names = &names;
                
                status = dcerpc_lsa_LookupSids3(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
+               if (!NT_STATUS_IS_OK(status)) {
                        if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
                            NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED)) {
                                printf("not considering %s to be an error\n", nt_errstr(status));
@@ -1879,16 +1967,54 @@ static BOOL test_QueryInfoPolicy(struct dcerpc_pipe *p,
 
                status = dcerpc_lsa_QueryInfoPolicy(p, mem_ctx, &r);
 
-               if ((i == 9 || i == 10 || i == 11) &&
-                   NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
-                       printf("server failed level %u (OK)\n", i);
-                       continue;
+               switch (i) {
+               case LSA_POLICY_INFO_DB:
+               case LSA_POLICY_INFO_AUDIT_FULL_SET:
+               case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
+                       if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
+                               printf("server should have failed level %u: %s\n", i, nt_errstr(status));
+                               ret = False;
+                       }
+                       break;
+               case LSA_POLICY_INFO_DOMAIN:
+               case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
+               case LSA_POLICY_INFO_DNS:
+                       if (!NT_STATUS_IS_OK(status)) {
+                               printf("QueryInfoPolicy failed - %s\n", nt_errstr(status));
+                               ret = False;
+                       }
+                       break;
+               default:
+                       if (lp_parm_bool(NULL, "torture", "samba4", false)) {
+                               /* Other levels not implemented yet */
+                               if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
+                                       printf("QueryInfoPolicy failed - %s\n", nt_errstr(status));
+                                       ret = False;
+                               }
+                       } else if (!NT_STATUS_IS_OK(status)) {
+                               printf("QueryInfoPolicy failed - %s\n", nt_errstr(status));
+                               ret = False;
+                       }
+                       break;
                }
 
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryInfoPolicy failed - %s\n", nt_errstr(status));
-                       ret = False;
-                       continue;
+               if (NT_STATUS_IS_OK(status) && i == LSA_POLICY_INFO_DNS) {
+                       /* Let's look up some of these names */
+
+                       struct lsa_TransNameArray tnames;
+                       tnames.count = 10;
+                       tnames.names = talloc_array(mem_ctx, struct lsa_TranslatedName, tnames.count);
+                       tnames.names[0].name.string = r.out.info->dns.name.string;
+                       tnames.names[1].name.string = r.out.info->dns.dns_domain.string;
+                       tnames.names[2].name.string = talloc_asprintf(mem_ctx, "%s\\", r.out.info->dns.name.string);
+                       tnames.names[3].name.string = talloc_asprintf(mem_ctx, "%s\\", r.out.info->dns.dns_domain.string);
+                       tnames.names[4].name.string = talloc_asprintf(mem_ctx, "%s\\guest", r.out.info->dns.name.string);
+                       tnames.names[5].name.string = talloc_asprintf(mem_ctx, "%s\\krbtgt", r.out.info->dns.name.string);
+                       tnames.names[6].name.string = talloc_asprintf(mem_ctx, "%s\\guest", r.out.info->dns.dns_domain.string);
+                       tnames.names[7].name.string = talloc_asprintf(mem_ctx, "%s\\krbtgt", r.out.info->dns.dns_domain.string);
+                       tnames.names[8].name.string = talloc_asprintf(mem_ctx, "krbtgt@%s", r.out.info->dns.name.string);
+                       tnames.names[9].name.string = talloc_asprintf(mem_ctx, "krbtgt@%s", r.out.info->dns.dns_domain.string);
+                       ret &= test_LookupNames(p, mem_ctx, handle, &tnames);
                }
        }
 
@@ -1904,11 +2030,6 @@ static BOOL test_QueryInfoPolicy2(struct dcerpc_pipe *p,
        int i;
        BOOL ret = True;
        printf("\nTesting QueryInfoPolicy2\n");
-       if (lp_parm_bool(NULL, "torture", "samba4", false)) {
-               printf("skipping QueryInfoPolicy2 against Samba4\n");
-               return True;
-       }
-
        for (i=1;i<13;i++) {
                r.in.handle = handle;
                r.in.level = i;
@@ -1916,17 +2037,36 @@ static BOOL test_QueryInfoPolicy2(struct dcerpc_pipe *p,
                printf("\ntrying QueryInfoPolicy2 level %d\n", i);
 
                status = dcerpc_lsa_QueryInfoPolicy2(p, mem_ctx, &r);
-
-               if ((i == 9 || i == 10 || i == 11) &&
-                   NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
-                       printf("server failed level %u (OK)\n", i);
-                       continue;
-               }
-
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryInfoPolicy2 failed - %s\n", nt_errstr(status));
-                       ret = False;
-                       continue;
+               
+               switch (i) {
+               case LSA_POLICY_INFO_DB:
+               case LSA_POLICY_INFO_AUDIT_FULL_SET:
+               case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
+                       if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
+                               printf("server should have failed level %u: %s\n", i, nt_errstr(status));
+                               ret = False;
+                       }
+                       break;
+               case LSA_POLICY_INFO_DOMAIN:
+               case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
+               case LSA_POLICY_INFO_DNS:
+                       if (!NT_STATUS_IS_OK(status)) {
+                               printf("QueryInfoPolicy2 failed - %s\n", nt_errstr(status));
+                               ret = False;
+                       }
+                       break;
+               default:
+                       if (lp_parm_bool(NULL, "torture", "samba4", false)) {
+                               /* Other levels not implemented yet */
+                               if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
+                                       printf("QueryInfoPolicy2 failed - %s\n", nt_errstr(status));
+                                       ret = False;
+                               }
+                       } else if (!NT_STATUS_IS_OK(status)) {
+                               printf("QueryInfoPolicy2 failed - %s\n", nt_errstr(status));
+                               ret = False;
+                       }
+                       break;
                }
        }
 
@@ -2013,6 +2153,14 @@ BOOL torture_rpc_lsa(struct torture_context *torture)
        }
 
        if (handle) {
+               if (!test_LookupNames_wellknown(p, mem_ctx, handle)) {
+                       ret = False;
+               }               
+
+               if (!test_LookupNames_bogus(p, mem_ctx, handle)) {
+                       ret = False;
+               }               
+
                if (!test_LookupSids_async(p, mem_ctx, handle)) {
                        ret = False;
                }