r25026: Move param/param.h out of includes.h
[kai/samba-autobuild/.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
index d6e0854968efa8f8df786a032fdd245b01714ef4..144e61cd75dedf4c35e947ca87fac0ce24e1558d 100644 (file)
@@ -8,7 +8,7 @@
    
    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 2 of the License, or
+   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,
    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, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "librpc/gen_ndr/ndr_lsa.h"
-#include "librpc/gen_ndr/ndr_samr.h"
 #include "rpc_server/dcerpc_server.h"
 #include "rpc_server/common/common.h"
-#include "lib/ldb/include/ldb.h"
 #include "auth/auth.h"
-#include "system/time.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"
 
 /*
   this type allows us to distinguish handle types
@@ -36,7 +40,8 @@
 enum lsa_handle {
        LSA_HANDLE_POLICY,
        LSA_HANDLE_ACCOUNT,
-       LSA_HANDLE_SECRET
+       LSA_HANDLE_SECRET,
+       LSA_HANDLE_TRUSTED_DOMAIN
 };
 
 /*
@@ -44,15 +49,20 @@ enum lsa_handle {
 */
 struct lsa_policy_state {
        struct dcesrv_handle *handle;
-       struct ldb_wrap *sam_ctx;
+       struct ldb_context *sam_ldb;
        struct sidmap_context *sidmap;
        uint32_t access_mask;
-       const char *domain_dn;
-       const char *builtin_dn;
-       const char *system_dn;
+       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;
 };
 
 
@@ -63,8 +73,6 @@ struct lsa_account_state {
        struct lsa_policy_state *policy;
        uint32_t access_mask;
        struct dom_sid *account_sid;
-       const char *account_sid_str;
-       const char *account_dn;
 };
 
 
@@ -74,14 +82,35 @@ struct lsa_account_state {
 struct lsa_secret_state {
        struct lsa_policy_state *policy;
        uint32_t access_mask;
-       const char *secret_dn;
-       struct ldb_wrap *sam_ctx;
+       struct ldb_dn *secret_dn;
+       struct ldb_context *sam_ldb;
+       BOOL global;
 };
 
+/*
+  state associated with a lsa_OpenTrustedDomain() operation
+*/
+struct lsa_trusted_domain_state {
+       struct lsa_policy_state *policy;
+       uint32_t access_mask;
+       struct ldb_dn *trusted_domain_dn;
+};
+
+static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
+                                     TALLOC_CTX *mem_ctx,
+                                     struct lsa_EnumAccountRights *r);
+
+static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
+                                          TALLOC_CTX *mem_ctx,
+                                          struct lsa_policy_state *state,
+                                          int ldb_flag,
+                                          struct dom_sid *sid,
+                                          const struct lsa_RightSet *rights);
+
 /* 
   lsa_Close 
 */
-static NTSTATUS lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                          struct lsa_Close *r)
 {
        struct dcesrv_handle *h;
@@ -101,17 +130,77 @@ static NTSTATUS lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ct
 /* 
   lsa_Delete 
 */
-static NTSTATUS lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                           struct lsa_Delete *r)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       struct dcesrv_handle *h;
+       int ret;
+
+       DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
+       if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
+               struct lsa_secret_state *secret_state = h->data;
+               ret = samdb_delete(secret_state->sam_ldb, mem_ctx, secret_state->secret_dn);
+               talloc_free(h);
+               if (ret != 0) {
+                       return NT_STATUS_INVALID_HANDLE;
+               }
+
+               return NT_STATUS_OK;
+       } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
+               struct lsa_trusted_domain_state *trusted_domain_state = h->data;
+               ret = samdb_delete(trusted_domain_state->policy->sam_ldb, mem_ctx, 
+                                  trusted_domain_state->trusted_domain_dn);
+               talloc_free(h);
+               if (ret != 0) {
+                       return NT_STATUS_INVALID_HANDLE;
+               }
+
+               return NT_STATUS_OK;
+       } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
+               struct lsa_RightSet *rights;
+               struct lsa_account_state *astate;
+               struct lsa_EnumAccountRights r2;
+               NTSTATUS status;
+
+               rights = talloc(mem_ctx, struct lsa_RightSet);
+
+               DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
+               
+               astate = h->data;
+
+               r2.in.handle = &astate->policy->handle->wire_handle;
+               r2.in.sid = astate->account_sid;
+               r2.out.rights = rights;
+
+               status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+                       return NT_STATUS_OK;
+               }
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
+               status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
+                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
+                                                   r2.out.rights);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+                       return NT_STATUS_OK;
+               }
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+       } 
+       
+       return NT_STATUS_INVALID_HANDLE;
 }
 
 
 /* 
   lsa_EnumPrivs 
 */
-static NTSTATUS lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                              struct lsa_EnumPrivs *r)
 {
        struct dcesrv_handle *h;
@@ -130,7 +219,7 @@ static NTSTATUS lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
               r->out.privs->count < r->in.max_count) {
                struct lsa_PrivEntry *e;
 
-               r->out.privs->privs = talloc_realloc_p(r->out.privs,
+               r->out.privs->privs = talloc_realloc(r->out.privs,
                                                       r->out.privs->privs, 
                                                       struct lsa_PrivEntry, 
                                                       r->out.privs->count+1);
@@ -154,7 +243,7 @@ static NTSTATUS lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
 /* 
   lsa_QuerySecObj 
 */
-static NTSTATUS lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                  struct lsa_QuerySecurity *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -164,7 +253,7 @@ static NTSTATUS lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX
 /* 
   lsa_SetSecObj 
 */
-static NTSTATUS lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                              struct lsa_SetSecObj *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -174,86 +263,160 @@ static NTSTATUS lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
 /* 
   lsa_ChangePassword 
 */
-static NTSTATUS lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                   struct lsa_ChangePassword *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
-static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+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;
-       const char *sid_str;
+       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_p(mem_ctx, struct lsa_policy_state);
+       state = talloc(mem_ctx, struct lsa_policy_state);
        if (!state) {
                return NT_STATUS_NO_MEMORY;
        }
 
        /* make sure the sam database is accessible */
-       state->sam_ctx = samdb_connect(state);
-       if (state->sam_ctx == NULL) {
-               talloc_free(state);
+       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) {
-               talloc_free(state);
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
 
        /* work out the domain_dn - useful for so many calls its worth
           fetching here */
-       state->domain_dn = samdb_search_string(state->sam_ctx, state, NULL,
-                                              "dn", "(&(objectClass=domain)(!(objectclass=builtinDomain)))");
+       state->domain_dn = samdb_base_dn(state->sam_ldb);
        if (!state->domain_dn) {
-               talloc_free(state);
-               return NT_STATUS_NO_SUCH_DOMAIN;                
+               return NT_STATUS_NO_MEMORY;             
        }
 
-       /* work out the builtin_dn - useful for so many calls its worth
+       /* work out the forest root_dn - useful for so many calls its worth
           fetching here */
-       state->builtin_dn = samdb_search_string(state->sam_ctx, state, NULL,
-                                               "dn", "objectClass=builtinDomain");
-       if (!state->builtin_dn) {
-               talloc_free(state);
-               return NT_STATUS_NO_SUCH_DOMAIN;                
+       state->forest_dn = samdb_root_dn(state->sam_ldb);
+       if (!state->forest_dn) {
+               return NT_STATUS_NO_MEMORY;             
        }
 
-       /* work out the system_dn - useful for so many calls its worth
-          fetching here */
-       state->system_dn = samdb_search_string(state->sam_ctx, state, state->domain_dn,
-                                              "dn", "(&(objectClass=container)(cn=System))");
-       if (!state->system_dn) {
-               talloc_free(state);
+       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;                
        }
 
-       sid_str = samdb_search_string(state->sam_ctx, state, NULL,
-                                     "objectSid", "dn=%s", state->domain_dn);
-       if (!sid_str) {
-               talloc_free(state);
+       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_sid = dom_sid_parse_talloc(state, sid_str);
+       state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
        if (!state->domain_sid) {
-               talloc_free(state);
                return NT_STATUS_NO_SUCH_DOMAIN;                
        }
 
-       state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
-       if (!state->builtin_sid) {
-               talloc_free(state);
+       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 = samdb_search_string(state->sam_ctx, state, NULL,
-                                                "name", "dn=%s", state->domain_dn);
+       state->domain_name = ldb_msg_find_attr_as_string(ref_res->msgs[0], "nETBIOSName", NULL);
        if (!state->domain_name) {
-               talloc_free(state);
+               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;                
        }
 
@@ -262,10 +425,117 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_
        return NT_STATUS_OK;
 }
 
+/* 
+  dssetup_DsRoleGetPrimaryDomainInformation 
+
+  This is not an LSA call, but is the only call left on the DSSETUP
+  pipe (after the pipe was truncated), and needs lsa_get_policy_state
+*/
+static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call, 
+                                                TALLOC_CTX *mem_ctx,
+                                                struct dssetup_DsRoleGetPrimaryDomainInformation *r)
+{
+       union dssetup_DsRoleInfo *info;
+
+       info = talloc(mem_ctx, union dssetup_DsRoleInfo);
+       W_ERROR_HAVE_NO_MEMORY(info);
+
+       switch (r->in.level) {
+       case DS_ROLE_BASIC_INFORMATION:
+       {
+               enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
+               uint32_t flags = 0;
+               const char *domain = NULL;
+               const char *dns_domain = NULL;
+               const char *forest = NULL;
+               struct GUID domain_guid;
+               struct lsa_policy_state *state;
+
+               NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return ntstatus_to_werror(status);
+               }
+
+               ZERO_STRUCT(domain_guid);
+
+               switch (lp_server_role()) {
+               case ROLE_STANDALONE:
+                       role            = DS_ROLE_STANDALONE_SERVER;
+                       break;
+               case ROLE_DOMAIN_MEMBER:
+                       role            = DS_ROLE_MEMBER_SERVER;
+                       break;
+               case ROLE_DOMAIN_CONTROLLER:
+                       if (samdb_is_pdc(state->sam_ldb)) {
+                               role    = DS_ROLE_PRIMARY_DC;
+                       } else {
+                               role    = DS_ROLE_BACKUP_DC;
+                       }
+                       break;
+               }
+
+               switch (lp_server_role()) {
+               case ROLE_STANDALONE:
+                       domain          = talloc_strdup(mem_ctx, lp_workgroup());
+                       W_ERROR_HAVE_NO_MEMORY(domain);
+                       break;
+               case ROLE_DOMAIN_MEMBER:
+                       domain          = talloc_strdup(mem_ctx, lp_workgroup());
+                       W_ERROR_HAVE_NO_MEMORY(domain);
+                       /* TODO: what is with dns_domain and forest and guid? */
+                       break;
+               case ROLE_DOMAIN_CONTROLLER:
+                       flags           = DS_ROLE_PRIMARY_DS_RUNNING;
+
+                       if (state->mixed_domain == 1) {
+                               flags   |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
+                       }
+                       
+                       domain          = state->domain_name;
+                       dns_domain      = state->domain_dns;
+                       forest          = state->forest_dns;
+
+                       domain_guid     = state->domain_guid;
+                       flags   |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
+                       break;
+               }
+
+               info->basic.role        = role; 
+               info->basic.flags       = flags;
+               info->basic.domain      = domain;
+               info->basic.dns_domain  = dns_domain;
+               info->basic.forest      = forest;
+               info->basic.domain_guid = domain_guid;
+
+               r->out.info = info;
+               return WERR_OK;
+       }
+       case DS_ROLE_UPGRADE_STATUS:
+       {
+               info->upgrade.upgrading     = DS_ROLE_NOT_UPGRADING;
+               info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
+
+               r->out.info = info;
+               return WERR_OK;
+       }
+       case DS_ROLE_OP_STATUS:
+       {
+               info->opstatus.status = DS_ROLE_OP_IDLE;
+
+               r->out.info = info;
+               return WERR_OK;
+       }
+       default:
+               return WERR_INVALID_PARAM;
+       }
+
+       return WERR_INVALID_PARAM;
+}
+
 /* 
   lsa_OpenPolicy2
 */
-static NTSTATUS lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                               struct lsa_OpenPolicy2 *r)
 {
        NTSTATUS status;
@@ -274,7 +544,7 @@ static NTSTATUS lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *
 
        ZERO_STRUCTP(r->out.handle);
 
-       status = lsa_get_policy_state(dce_call, mem_ctx, &state);
+       status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -301,7 +571,7 @@ static NTSTATUS lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *
   lsa_OpenPolicy
   a wrapper around lsa_OpenPolicy2
 */
-static NTSTATUS lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                struct lsa_OpenPolicy *r)
 {
        struct lsa_OpenPolicy2 r2;
@@ -311,7 +581,7 @@ static NTSTATUS lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
        r2.in.access_mask = r->in.access_mask;
        r2.out.handle = r->out.handle;
 
-       return lsa_OpenPolicy2(dce_call, mem_ctx, &r2);
+       return dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &r2);
 }
 
 
@@ -320,219 +590,893 @@ static NTSTATUS lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
 /*
   fill in the AccountDomain info
 */
-static NTSTATUS lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
-                                      struct lsa_DomainInfo *info)
+static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
+                                      struct lsa_DomainInfo *info)
+{
+       info->name.string = state->domain_name;
+       info->sid         = state->domain_sid;
+
+       return NT_STATUS_OK;
+}
+
+/*
+  fill in the DNS domain info
+*/
+static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
+                            struct lsa_DnsDomainInfo *info)
+{
+       info->name.string = state->domain_name;
+       info->sid         = state->domain_sid;
+       info->dns_domain.string = state->domain_dns;
+       info->dns_forest.string = state->forest_dns;
+       info->domain_guid       = state->domain_guid;
+
+       return NT_STATUS_OK;
+}
+
+/* 
+  lsa_QueryInfoPolicy2
+*/
+static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                    struct lsa_QueryInfoPolicy2 *r)
+{
+       struct lsa_policy_state *state;
+       struct dcesrv_handle *h;
+
+       r->out.info = NULL;
+
+       DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
+
+       state = h->data;
+
+       r->out.info = talloc(mem_ctx, union lsa_PolicyInformation);
+       if (!r->out.info) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       ZERO_STRUCTP(r->out.info);
+
+       switch (r->in.level) {
+       case LSA_POLICY_INFO_DOMAIN:
+       case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
+               return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &r->out.info->account_domain);
+
+       case LSA_POLICY_INFO_DNS:
+               return dcesrv_lsa_info_DNS(state, mem_ctx, &r->out.info->dns);
+       }
+
+       return NT_STATUS_INVALID_INFO_CLASS;
+}
+
+/* 
+  lsa_QueryInfoPolicy 
+*/
+static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                   struct lsa_QueryInfoPolicy *r)
+{
+       struct lsa_QueryInfoPolicy2 r2;
+       NTSTATUS status;
+
+       r2.in.handle = r->in.handle;
+       r2.in.level = r->in.level;
+       
+       status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
+
+       r->out.info = r2.out.info;
+
+       return status;
+}
+
+/* 
+  lsa_SetInfoPolicy 
+*/
+static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                 struct lsa_SetInfoPolicy *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/* 
+  lsa_ClearAuditLog 
+*/
+static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                 struct lsa_ClearAuditLog *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/* 
+  lsa_CreateAccount 
+*/
+static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                 struct lsa_CreateAccount *r)
+{
+       struct lsa_account_state *astate;
+
+       struct lsa_policy_state *state;
+       struct dcesrv_handle *h, *ah;
+
+       ZERO_STRUCTP(r->out.acct_handle);
+
+       DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
+
+       state = h->data;
+
+       astate = talloc(dce_call->conn, struct lsa_account_state);
+       if (astate == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       astate->account_sid = dom_sid_dup(astate, r->in.sid);
+       if (astate->account_sid == NULL) {
+               talloc_free(astate);
+               return NT_STATUS_NO_MEMORY;
+       }
+       
+       astate->policy = talloc_reference(astate, state);
+       astate->access_mask = r->in.access_mask;
+
+       ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
+       if (!ah) {
+               talloc_free(astate);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       ah->data = talloc_steal(ah, astate);
+
+       *r->out.acct_handle = ah->wire_handle;
+
+       return NT_STATUS_OK;
+}
+
+
+/* 
+  lsa_EnumAccounts 
+*/
+static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                struct lsa_EnumAccounts *r)
+{
+       struct dcesrv_handle *h;
+       struct lsa_policy_state *state;
+       int ret, i;
+       struct ldb_message **res;
+       const char * const attrs[] = { "objectSid", NULL};
+       uint32_t count;
+
+       DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
+
+       state = h->data;
+
+       /* NOTE: This call must only return accounts that have at least
+          one privilege set 
+       */
+       ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
+                          "(&(objectSid=*)(privilege=*))");
+       if (ret < 0) {
+               return NT_STATUS_NO_SUCH_USER;
+       }
+
+       if (*r->in.resume_handle >= ret) {
+               return NT_STATUS_NO_MORE_ENTRIES;
+       }
+
+       count = ret - *r->in.resume_handle;
+       if (count > r->in.num_entries) {
+               count = r->in.num_entries;
+       }
+
+       if (count == 0) {
+               return NT_STATUS_NO_MORE_ENTRIES;
+       }
+
+       r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
+       if (r->out.sids->sids == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0;i<count;i++) {
+               r->out.sids->sids[i].sid = 
+                       samdb_result_dom_sid(r->out.sids->sids, 
+                                            res[i + *r->in.resume_handle],
+                                            "objectSid");
+               NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
+       }
+
+       r->out.sids->num_sids = count;
+       *r->out.resume_handle = count + *r->in.resume_handle;
+
+       return NT_STATUS_OK;
+       
+}
+
+
+/*
+  lsa_CreateTrustedDomainEx2
+*/
+static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
+                                          TALLOC_CTX *mem_ctx,
+                                          struct lsa_CreateTrustedDomainEx2 *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+  lsa_CreateTrustedDomainEx
+*/
+static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
+                                         TALLOC_CTX *mem_ctx,
+                                         struct lsa_CreateTrustedDomainEx *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/* 
+  lsa_CreateTrustedDomain 
+*/
+static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                       struct lsa_CreateTrustedDomain *r)
+{
+       struct dcesrv_handle *policy_handle;
+       struct lsa_policy_state *policy_state;
+       struct lsa_trusted_domain_state *trusted_domain_state;
+       struct dcesrv_handle *handle;
+       struct ldb_message **msgs, *msg;
+       const char *attrs[] = {
+               NULL
+       };
+       const char *name;
+       int ret;
+
+       DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
+       ZERO_STRUCTP(r->out.trustdom_handle);
+       
+       policy_state = policy_handle->data;
+
+       if (!r->in.info->name.string) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       name = r->in.info->name.string;
+       
+       trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
+       if (!trusted_domain_state) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       trusted_domain_state->policy = policy_state;
+
+       msg = ldb_msg_new(mem_ctx);
+       if (msg == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* search for the trusted_domain record */
+       ret = gendb_search(trusted_domain_state->policy->sam_ldb,
+                          mem_ctx, policy_state->system_dn, &msgs, attrs,
+                          "(&(cn=%s)(objectclass=trustedDomain))", 
+                          ldb_binary_encode_string(mem_ctx, r->in.info->name.string));
+       if (ret > 0) {
+               return NT_STATUS_OBJECT_NAME_COLLISION;
+       }
+       
+       if (ret < 0 || ret > 1) {
+               DEBUG(0,("Found %d records matching DN %s\n", ret,
+                        ldb_dn_get_linearized(policy_state->system_dn)));
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+       
+       msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
+       if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       
+       samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "flatname", name);
+
+       if (r->in.info->sid) {
+               const char *sid_string = dom_sid_string(mem_ctx, r->in.info->sid);
+               if (!sid_string) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+                       
+               samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "securityIdentifier", sid_string);
+       }
+
+       samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
+       
+       trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
+
+       /* create the trusted_domain */
+       ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg);
+       if (ret != LDB_SUCCESS) {
+               DEBUG(0,("Failed to create trusted_domain record %s: %s\n",
+                        ldb_dn_get_linearized(msg->dn), ldb_errstring(trusted_domain_state->policy->sam_ldb)));
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
+       if (!handle) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       
+       handle->data = talloc_steal(handle, trusted_domain_state);
+       
+       trusted_domain_state->access_mask = r->in.access_mask;
+       trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
+       
+       *r->out.trustdom_handle = handle->wire_handle;
+       
+       return NT_STATUS_OK;
+}
+
+/* 
+  lsa_OpenTrustedDomain
+*/
+static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                     struct lsa_OpenTrustedDomain *r)
+{
+       struct dcesrv_handle *policy_handle;
+       
+       struct lsa_policy_state *policy_state;
+       struct lsa_trusted_domain_state *trusted_domain_state;
+       struct dcesrv_handle *handle;
+       struct ldb_message **msgs;
+       const char *attrs[] = {
+               NULL
+       };
+
+       const char *sid_string;
+       int ret;
+
+       DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
+       ZERO_STRUCTP(r->out.trustdom_handle);
+       policy_state = policy_handle->data;
+
+       trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
+       if (!trusted_domain_state) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       trusted_domain_state->policy = policy_state;
+
+       sid_string = dom_sid_string(mem_ctx, r->in.sid);
+       if (!sid_string) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* search for the trusted_domain record */
+       ret = gendb_search(trusted_domain_state->policy->sam_ldb,
+                          mem_ctx, policy_state->system_dn, &msgs, attrs,
+                          "(&(securityIdentifier=%s)(objectclass=trustedDomain))", 
+                          sid_string);
+       if (ret == 0) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+       
+       if (ret != 1) {
+               DEBUG(0,("Found %d records matching DN %s\n", ret,
+                        ldb_dn_get_linearized(policy_state->system_dn)));
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
+       
+       handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
+       if (!handle) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       
+       handle->data = talloc_steal(handle, trusted_domain_state);
+       
+       trusted_domain_state->access_mask = r->in.access_mask;
+       trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
+       
+       *r->out.trustdom_handle = handle->wire_handle;
+       
+       return NT_STATUS_OK;
+}
+
+
+/*
+  lsa_OpenTrustedDomainByName
+*/
+static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
+                                           TALLOC_CTX *mem_ctx,
+                                           struct lsa_OpenTrustedDomainByName *r)
+{
+       struct dcesrv_handle *policy_handle;
+       
+       struct lsa_policy_state *policy_state;
+       struct lsa_trusted_domain_state *trusted_domain_state;
+       struct dcesrv_handle *handle;
+       struct ldb_message **msgs;
+       const char *attrs[] = {
+               NULL
+       };
+
+       int ret;
+
+       DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
+       ZERO_STRUCTP(r->out.trustdom_handle);
+       policy_state = policy_handle->data;
+
+       if (!r->in.name.string) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       
+       trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
+       if (!trusted_domain_state) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       trusted_domain_state->policy = policy_state;
+
+       /* search for the trusted_domain record */
+       ret = gendb_search(trusted_domain_state->policy->sam_ldb,
+                          mem_ctx, policy_state->system_dn, &msgs, attrs,
+                          "(&(flatname=%s)(objectclass=trustedDomain))", 
+                          ldb_binary_encode_string(mem_ctx, r->in.name.string));
+       if (ret == 0) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+       
+       if (ret != 1) {
+               DEBUG(0,("Found %d records matching DN %s\n", ret,
+                        ldb_dn_get_linearized(policy_state->system_dn)));
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
+       
+       handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
+       if (!handle) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       
+       handle->data = talloc_steal(handle, trusted_domain_state);
+       
+       trusted_domain_state->access_mask = r->in.access_mask;
+       trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
+       
+       *r->out.trustdom_handle = handle->wire_handle;
+       
+       return NT_STATUS_OK;
+}
+
+
+
+/* 
+  lsa_SetTrustedDomainInfo
+*/
+static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                        struct lsa_SetTrustedDomainInfo *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+
+/* 
+  lsa_SetInfomrationTrustedDomain
+*/
+static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call, 
+                                               TALLOC_CTX *mem_ctx,
+                                               struct lsa_SetInformationTrustedDomain *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/* 
+  lsa_DeleteTrustedDomain
+*/
+static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                     struct lsa_DeleteTrustedDomain *r)
+{
+       NTSTATUS status;
+       struct lsa_OpenTrustedDomain open;
+       struct lsa_Delete delete;
+       struct dcesrv_handle *h;
+
+       open.in.handle = r->in.handle;
+       open.in.sid = r->in.dom_sid;
+       open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+       open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
+       if (!open.out.trustdom_handle) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &open);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY);
+       talloc_steal(mem_ctx, h);
+
+       delete.in.handle = open.out.trustdom_handle;
+       status = dcesrv_lsa_Delete(dce_call, mem_ctx, &delete);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx, 
+                                    struct ldb_message *msg, 
+                                    struct lsa_TrustDomainInfoInfoEx *info_ex) 
+{
+       info_ex->domain_name.string
+               = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
+       info_ex->netbios_name.string
+               = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
+       info_ex->sid 
+               = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
+       info_ex->trust_direction
+               = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
+       info_ex->trust_type
+               = ldb_msg_find_attr_as_int(msg, "trustType", 0);
+       info_ex->trust_attributes
+               = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);  
+       return NT_STATUS_OK;
+}
+
+/* 
+  lsa_QueryTrustedDomainInfo
+*/
+static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                          struct lsa_QueryTrustedDomainInfo *r)
+{
+       struct dcesrv_handle *h;
+       struct lsa_trusted_domain_state *trusted_domain_state;
+       struct ldb_message *msg;
+       int ret;
+       struct ldb_message **res;
+       const char *attrs[] = {
+               "flatname", 
+               "trustPartner",
+               "securityIdentifier",
+               "trustDirection",
+               "trustType",
+               "trustAttributes", 
+               NULL
+       };
+
+       DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
+
+       trusted_domain_state = h->data;
+
+       /* pull all the user attributes */
+       ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
+                             trusted_domain_state->trusted_domain_dn, &res, attrs);
+       if (ret != 1) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+       msg = res[0];
+       
+       r->out.info = talloc(mem_ctx, union lsa_TrustedDomainInfo);
+       if (!r->out.info) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       switch (r->in.level) {
+       case LSA_TRUSTED_DOMAIN_INFO_NAME:
+               r->out.info->name.netbios_name.string
+                       = samdb_result_string(msg, "flatname", NULL);                                      
+               break;
+       case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
+               r->out.info->posix_offset.posix_offset
+                       = samdb_result_uint(msg, "posixOffset", 0);                                        
+               break;
+#if 0  /* Win2k3 doesn't implement this */
+       case LSA_TRUSTED_DOMAIN_INFO_BASIC:
+               r->out.info->info_basic.netbios_name.string 
+                       = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
+               r->out.info->info_basic.sid
+                       = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
+               break;
+#endif
+       case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
+               return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info_ex);
+
+       case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
+               ZERO_STRUCT(r->out.info->full_info);
+               return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->full_info.info_ex);
+
+       case LSA_TRUSTED_DOMAIN_INFO_INFO_ALL:
+               ZERO_STRUCT(r->out.info->info_all);
+               return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info_all.info_ex);
+
+       case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS_INFO:
+       case LSA_TRUSTED_DOMAIN_INFO_11:
+               /* oops, we don't want to return the info after all */
+               talloc_free(r->out.info);
+               r->out.info = NULL;
+               return NT_STATUS_INVALID_PARAMETER;
+       default:
+               /* oops, we don't want to return the info after all */
+               talloc_free(r->out.info);
+               r->out.info = NULL;
+               return NT_STATUS_INVALID_INFO_CLASS;
+       }
+
+       return NT_STATUS_OK;
+}
+
+
+/* 
+  lsa_QueryTrustedDomainInfoBySid
+*/
+static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                               struct lsa_QueryTrustedDomainInfoBySid *r)
+{
+       NTSTATUS status;
+       struct lsa_OpenTrustedDomain open;
+       struct lsa_QueryTrustedDomainInfo query;
+       struct dcesrv_handle *h;
+       open.in.handle = r->in.handle;
+       open.in.sid = r->in.dom_sid;
+       open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+       open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
+       if (!open.out.trustdom_handle) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &open);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       /* Ensure this handle goes away at the end of this call */
+       DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY);
+       talloc_steal(mem_ctx, h);
+       
+       query.in.trustdom_handle = open.out.trustdom_handle;
+       query.in.level = r->in.level;
+       status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       
+       r->out.info = query.out.info;
+       return NT_STATUS_OK;
+}
+
+/*
+  lsa_SetTrustedDomainInfoByName
+*/
+static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
+                                              TALLOC_CTX *mem_ctx,
+                                              struct lsa_SetTrustedDomainInfoByName *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/* 
+   lsa_QueryTrustedDomainInfoByName
+*/
+static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
+                                                TALLOC_CTX *mem_ctx,
+                                                struct lsa_QueryTrustedDomainInfoByName *r)
 {
-       const char * const attrs[] = { "objectSid", "name", NULL};
-       int ret;
-       struct ldb_message **res;
-
-       ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs, 
-                          "dn=%s", state->domain_dn);
-       if (ret != 1) {
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       NTSTATUS status;
+       struct lsa_OpenTrustedDomainByName open;
+       struct lsa_QueryTrustedDomainInfo query;
+       struct dcesrv_handle *h;
+       open.in.handle = r->in.handle;
+       open.in.name = r->in.trusted_domain;
+       open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+       open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
+       if (!open.out.trustdom_handle) {
+               return NT_STATUS_NO_MEMORY;
        }
+       status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &open);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       
+       /* Ensure this handle goes away at the end of this call */
+       DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY);
+       talloc_steal(mem_ctx, h);
 
-       info->name.string = samdb_result_string(res[0], "name", NULL);
-       info->sid         = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
-
+       query.in.trustdom_handle = open.out.trustdom_handle;
+       query.in.level = r->in.level;
+       status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       
+       r->out.info = query.out.info;
        return NT_STATUS_OK;
 }
 
 /*
-  fill in the DNS domain info
+  lsa_CloseTrustedDomainEx 
 */
-static NTSTATUS lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
-                            struct lsa_DnsDomainInfo *info)
+static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
+                                        TALLOC_CTX *mem_ctx,
+                                        struct lsa_CloseTrustedDomainEx *r)
 {
-       const char * const attrs[] = { "name", "dnsDomain", "objectGUID", "objectSid", NULL };
-       int ret;
-       struct ldb_message **res;
-
-       ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs, 
-                          "dn=%s", state->domain_dn);
-       if (ret != 1) {
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
-       }
+       /* The result of a bad hair day from an IDL programmer?  Not
+        * implmented in Win2k3.  You should always just lsa_Close
+        * anyway. */
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
 
-       info->name.string       = samdb_result_string(res[0],           "name", NULL);
-       info->dns_domain.string = samdb_result_string(res[0],           "dnsDomain", NULL);
-       info->dns_forest.string = samdb_result_string(res[0],           "dnsDomain", NULL);
-       info->domain_guid       = samdb_result_guid(res[0],             "objectGUID");
-       info->sid               = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
 
-       return NT_STATUS_OK;
+/*
+  comparison function for sorting lsa_DomainInformation array
+*/
+static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
+{
+       return strcasecmp_m(e1->name.string, e2->name.string);
 }
 
 /* 
-  lsa_QueryInfoPolicy2
+  lsa_EnumTrustDom 
 */
-static NTSTATUS lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                                    struct lsa_QueryInfoPolicy2 *r)
+static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                struct lsa_EnumTrustDom *r)
 {
-       struct lsa_policy_state *state;
-       struct dcesrv_handle *h;
+       struct dcesrv_handle *policy_handle;
+       struct lsa_DomainInfo *entries;
+       struct lsa_policy_state *policy_state;
+       struct ldb_message **domains;
+       const char *attrs[] = {
+               "flatname", 
+               "securityIdentifier",
+               NULL
+       };
 
-       r->out.info = NULL;
 
-       DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
+       int count, i;
 
-       state = h->data;
+       *r->out.resume_handle = 0;
 
-       r->out.info = talloc_p(mem_ctx, union lsa_PolicyInformation);
-       if (!r->out.info) {
-               return NT_STATUS_NO_MEMORY;
-       }
+       r->out.domains->domains = NULL;
+       r->out.domains->count = 0;
 
-       ZERO_STRUCTP(r->out.info);
+       DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
 
-       switch (r->in.level) {
-       case LSA_POLICY_INFO_DOMAIN:
-       case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
-               return lsa_info_AccountDomain(state, mem_ctx, &r->out.info->account_domain);
+       policy_state = policy_handle->data;
 
-       case LSA_POLICY_INFO_DNS:
-               return lsa_info_DNS(state, mem_ctx, &r->out.info->dns);
+       /* search for all users in this domain. This could possibly be cached and 
+          resumed based on resume_key */
+       count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
+                            "objectclass=trustedDomain");
+       if (count == -1) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+       if (count == 0 || r->in.max_size == 0) {
+               return NT_STATUS_OK;
        }
 
-       return NT_STATUS_INVALID_INFO_CLASS;
-}
+       /* convert to lsa_TrustInformation format */
+       entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
+       if (!entries) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       for (i=0;i<count;i++) {
+               entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
+               entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
+       }
 
-/* 
-  lsa_QueryInfoPolicy 
-*/
-static NTSTATUS lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                                   struct lsa_QueryInfoPolicy *r)
-{
-       struct lsa_QueryInfoPolicy2 r2;
-       NTSTATUS status;
+       /* sort the results by name */
+       qsort(entries, count, sizeof(*entries), 
+             (comparison_fn_t)compare_DomainInfo);
 
-       r2.in.handle = r->in.handle;
-       r2.in.level = r->in.level;
-       
-       status = lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
+       if (*r->in.resume_handle >= count) {
+               *r->out.resume_handle = -1;
 
-       r->out.info = r2.out.info;
+               return NT_STATUS_NO_MORE_ENTRIES;
+       }
 
-       return status;
-}
+       /* return the rest, limit by max_size. Note that we 
+          use the w2k3 element size value of 60 */
+       r->out.domains->count = count - *r->in.resume_handle;
+       r->out.domains->count = MIN(r->out.domains->count, 
+                                1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
 
-/* 
-  lsa_SetInfoPolicy 
-*/
-static NTSTATUS lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                                 struct lsa_SetInfoPolicy *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
+       r->out.domains->domains = entries + *r->in.resume_handle;
+       r->out.domains->count = r->out.domains->count;
 
+       if (r->out.domains->count < count - *r->in.resume_handle) {
+               *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
+               return STATUS_MORE_ENTRIES;
+       }
 
-/* 
-  lsa_ClearAuditLog 
-*/
-static NTSTATUS lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                                 struct lsa_ClearAuditLog *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       return NT_STATUS_OK;
 }
 
-
-/* 
-  lsa_CreateAccount 
+/*
+  comparison function for sorting lsa_DomainInformation array
 */
-static NTSTATUS lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                                 struct lsa_CreateAccount *r)
+static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
 }
 
-
 /* 
-  lsa_EnumAccounts 
+  lsa_EnumTrustedDomainsEx 
 */
-static NTSTATUS lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                                struct lsa_EnumAccounts *r)
+static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                       struct lsa_EnumTrustedDomainsEx *r)
 {
-       struct dcesrv_handle *h;
-       struct lsa_policy_state *state;
-       int ret, i;
-       struct ldb_message **res;
-       const char * const attrs[] = { "objectSid", NULL};
-       uint32_t count;
+       struct dcesrv_handle *policy_handle;
+       struct lsa_TrustDomainInfoInfoEx *entries;
+       struct lsa_policy_state *policy_state;
+       struct ldb_message **domains;
+       const char *attrs[] = {
+               "flatname", 
+               "trustPartner",
+               "securityIdentifier",
+               "trustDirection",
+               "trustType",
+               "trustAttributes", 
+               NULL
+       };
+       NTSTATUS nt_status;
 
-       DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
+       int count, i;
 
-       state = h->data;
+       *r->out.resume_handle = 0;
 
-       ret = samdb_search(state->sam_ctx, mem_ctx, state->builtin_dn, &res, attrs, 
-                          "privilege=*");
-       if (ret <= 0) {
-               return NT_STATUS_NO_SUCH_USER;
-       }
+       r->out.domains->domains = NULL;
+       r->out.domains->count = 0;
 
-       if (*r->in.resume_handle >= ret) {
-               return NT_STATUS_NO_MORE_ENTRIES;
-       }
+       DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
 
-       count = ret - *r->in.resume_handle;
-       if (count > r->in.num_entries) {
-               count = r->in.num_entries;
-       }
+       policy_state = policy_handle->data;
 
-       if (count == 0) {
-               return NT_STATUS_NO_MORE_ENTRIES;
+       /* search for all users in this domain. This could possibly be cached and 
+          resumed based on resume_key */
+       count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
+                            "objectclass=trustedDomain");
+       if (count == -1) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+       if (count == 0 || r->in.max_size == 0) {
+               return NT_STATUS_OK;
        }
 
-       r->out.sids->sids = talloc_array_p(r->out.sids, struct lsa_SidPtr, count);
-       if (r->out.sids->sids == NULL) {
+       /* convert to lsa_DomainInformation format */
+       entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
+       if (!entries) {
                return NT_STATUS_NO_MEMORY;
        }
-
        for (i=0;i<count;i++) {
-               const char *sidstr;
-
-               sidstr = samdb_result_string(res[i + *r->in.resume_handle], "objectSid", NULL);
-               if (sidstr == NULL) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-               r->out.sids->sids[i].sid = dom_sid_parse_talloc(r->out.sids->sids, sidstr);
-               if (r->out.sids->sids[i].sid == NULL) {
-                       return NT_STATUS_NO_MEMORY;
+               nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       return nt_status;
                }
        }
 
-       r->out.sids->num_sids = count;
-       *r->out.resume_handle = count + *r->in.resume_handle;
+       /* sort the results by name */
+       qsort(entries, count, sizeof(*entries), 
+             (comparison_fn_t)compare_TrustDomainInfoInfoEx);
 
-       return NT_STATUS_OK;
-       
-}
+       if (*r->in.resume_handle >= count) {
+               *r->out.resume_handle = -1;
 
+               return NT_STATUS_NO_MORE_ENTRIES;
+       }
 
-/* 
-  lsa_CreateTrustedDomain 
-*/
-static NTSTATUS lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                                       struct lsa_CreateTrustedDomain *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
+       /* return the rest, limit by max_size. Note that we 
+          use the w2k3 element size value of 60 */
+       r->out.domains->count = count - *r->in.resume_handle;
+       r->out.domains->count = MIN(r->out.domains->count, 
+                                1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
 
+       r->out.domains->domains = entries + *r->in.resume_handle;
+       r->out.domains->count = r->out.domains->count;
 
-/* 
-  lsa_EnumTrustDom 
-*/
-static NTSTATUS lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_EnumTrustDom *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       if (r->out.domains->count < count - *r->in.resume_handle) {
+               *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
+               return STATUS_MORE_ENTRIES;
+       }
+
+       return NT_STATUS_OK;
 }
 
 
 /*
   return the authority name and authority sid, given a sid
 */
-static NTSTATUS lsa_authority_name(struct lsa_policy_state *state,
+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)
@@ -565,7 +1509,7 @@ static NTSTATUS lsa_authority_name(struct lsa_policy_state *state,
 /*
   add to the lsa_RefDomainList for LookupSids and LookupNames
 */
-static NTSTATUS lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, 
+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)
@@ -576,7 +1520,7 @@ static NTSTATUS lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *m
        int i;
 
        /* work out the authority name */
-       status = lsa_authority_name(state, mem_ctx, sid, 
+       status = dcesrv_lsa_authority_name(state, mem_ctx, sid, 
                                    &authority_name, &authority_sid);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -590,16 +1534,17 @@ static NTSTATUS lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *m
                }
        }
 
-       domains->domains = talloc_realloc_p(domains, 
-                                           domains->domains,
-                                           struct lsa_TrustInformation,
-                                           domains->count+1);
+       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;
@@ -608,7 +1553,7 @@ static NTSTATUS lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *m
 /*
   lookup a name for 1 SID
 */
-static NTSTATUS lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
+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)
 {
@@ -617,15 +1562,15 @@ static NTSTATUS lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_c
        const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "name", NULL};
        NTSTATUS status;
 
-       ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs, 
-                          "objectSid=%s", sid_str);
+       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_string(res[0], "sAMAccountName", NULL);
+               *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
                if (!*name) {
-                       *name = ldb_msg_find_string(res[0], "name", NULL);
+                       *name = ldb_msg_find_attr_as_string(res[0], "name", NULL);
                        if (!*name) {
                                *name = talloc_strdup(mem_ctx, sid_str);
-                               NTSTATUS_TALLOC_CHECK(*name);
+                               NT_STATUS_HAVE_NO_MEMORY(*name);
                        }
                }
 
@@ -641,11 +1586,11 @@ static NTSTATUS lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_c
 
 
 /*
-  lsa_LookupSids3
+  lsa_LookupSids2
 */
-static NTSTATUS lsa_LookupSids3(struct dcesrv_call_state *dce_call,
+static NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
                                TALLOC_CTX *mem_ctx,
-                               struct lsa_LookupSids3 *r)
+                               struct lsa_LookupSids2 *r)
 {
        struct lsa_policy_state *state;
        int i;
@@ -653,24 +1598,24 @@ static NTSTATUS lsa_LookupSids3(struct dcesrv_call_state *dce_call,
 
        r->out.domains = NULL;
 
-       status = lsa_get_policy_state(dce_call, mem_ctx, &state);
+       status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       r->out.domains = talloc_zero_p(mem_ctx,  struct lsa_RefDomainList);
+       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_p(mem_ctx,  struct lsa_TransNameArray2);
+       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_p(r->out.names, struct lsa_TranslatedName2, 
+       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;
@@ -698,12 +1643,12 @@ static NTSTATUS lsa_LookupSids3(struct dcesrv_call_state *dce_call,
                }
 
                /* work out the authority name */
-               status2 = lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
+               status2 = dcesrv_lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
                if (!NT_STATUS_IS_OK(status2)) {
                        return status2;
                }
 
-               status2 = lsa_lookup_sid(state, mem_ctx, sid, sid_str, 
+               status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str, 
                                         &name, &atype);
                if (!NT_STATUS_IS_OK(status2)) {
                        status = STATUS_SOME_UNMAPPED;
@@ -727,32 +1672,56 @@ static NTSTATUS lsa_LookupSids3(struct dcesrv_call_state *dce_call,
 
 
 /*
-  lsa_LookupSids2
+  lsa_LookupSids3
+
+  Identical to LookupSids2, but doesn't take a policy handle
+  
 */
-static NTSTATUS lsa_LookupSids2(struct dcesrv_call_state *dce_call,
+static NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
                                TALLOC_CTX *mem_ctx,
-                               struct lsa_LookupSids2 *r)
+                               struct lsa_LookupSids3 *r)
 {
-       struct lsa_LookupSids3 r3;
+       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);
 
-       r3.in.sids     = r->in.sids;
-       r3.in.names    = r->in.names;
-       r3.in.level    = r->in.level;
-       r3.in.count    = r->in.count;
-       r3.in.unknown1 = r->in.unknown1;
-       r3.in.unknown2 = r->in.unknown2;
-       r3.out.count   = r->out.count;
-       r3.out.names   = r->out.names;
+       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 = lsa_LookupSids3(dce_call, mem_ctx, &r3);
+       status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
        if (dce_call->fault_code != 0) {
                return status;
        }
 
-       r->out.domains = r3.out.domains;
-       r->out.names   = r3.out.names;
-       r->out.count   = r3.out.count;
+       r->out.domains = r2.out.domains;
+       r->out.names   = r2.out.names;
+       r->out.count   = r2.out.count;
 
        return status;
 }
@@ -761,41 +1730,48 @@ static NTSTATUS lsa_LookupSids2(struct dcesrv_call_state *dce_call,
 /* 
   lsa_LookupSids 
 */
-static NTSTATUS lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                               struct lsa_LookupSids *r)
 {
-       struct lsa_LookupSids3 r3;
+       struct lsa_LookupSids2 r2;
        NTSTATUS status;
        int i;
 
-       r3.in.sids     = r->in.sids;
-       r3.in.names    = NULL;
-       r3.in.level    = r->in.level;
-       r3.in.count    = r->in.count;
-       r3.in.unknown1 = 0;
-       r3.in.unknown2 = 0;
-       r3.out.count   = r->out.count;
-
-       status = lsa_LookupSids3(dce_call, mem_ctx, &r3);
+       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 = r3.out.domains;
-       r->out.names = talloc_p(mem_ctx, struct lsa_TransNameArray);
+       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 = r3.out.names->count;
-       r->out.names->names = talloc_array_p(r->out.names, struct lsa_TranslatedName, 
+       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    = r3.out.names->names[i].sid_type;
-               r->out.names->names[i].name.string = r3.out.names->names[i].name.string;
-               r->out.names->names[i].sid_index   = r3.out.names->names[i].sid_index;
+               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;
@@ -805,7 +1781,7 @@ static NTSTATUS lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
 /* 
   lsa_OpenAccount 
 */
-static NTSTATUS lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                struct lsa_OpenAccount *r)
 {
        struct dcesrv_handle *h, *ah;
@@ -818,7 +1794,7 @@ static NTSTATUS lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *
 
        state = h->data;
 
-       astate = talloc_p(dce_call->conn, struct lsa_account_state);
+       astate = talloc(dce_call->conn, struct lsa_account_state);
        if (astate == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -829,22 +1805,6 @@ static NTSTATUS lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *
                return NT_STATUS_NO_MEMORY;
        }
        
-       astate->account_sid_str = dom_sid_string(astate, astate->account_sid);
-       if (astate->account_sid_str == NULL) {
-               talloc_free(astate);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       /* check it really exists */
-       astate->account_dn = samdb_search_string(state->sam_ctx, astate,
-                                                NULL, "dn", 
-                                                "(&(objectSid=%s)(objectClass=group))", 
-                                                astate->account_sid_str);
-       if (astate->account_dn == NULL) {
-               talloc_free(astate);
-               return NT_STATUS_NO_SUCH_USER;
-       }
-       
        astate->policy = talloc_reference(astate, state);
        astate->access_mask = r->in.access_mask;
 
@@ -865,7 +1825,7 @@ static NTSTATUS lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *
 /* 
   lsa_EnumPrivsAccount 
 */
-static NTSTATUS lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call, 
+static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call, 
                                     TALLOC_CTX *mem_ctx,
                                     struct lsa_EnumPrivsAccount *r)
 {
@@ -875,18 +1835,24 @@ static NTSTATUS lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
        struct ldb_message **res;
        const char * const attrs[] = { "privilege", NULL};
        struct ldb_message_element *el;
+       const char *sidstr;
 
        DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
 
        astate = h->data;
 
-       r->out.privs = talloc_p(mem_ctx, struct lsa_PrivilegeSet);
+       r->out.privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
        r->out.privs->count = 0;
        r->out.privs->unknown = 0;
        r->out.privs->set = NULL;
 
-       ret = samdb_search(astate->policy->sam_ctx, mem_ctx, NULL, &res, attrs, 
-                          "dn=%s", astate->account_dn);
+       sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
+       if (sidstr == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       ret = gendb_search(astate->policy->sam_ldb, mem_ctx, NULL, &res, attrs, 
+                          "objectSid=%s", sidstr);
        if (ret != 1) {
                return NT_STATUS_OK;
        }
@@ -896,14 +1862,14 @@ static NTSTATUS lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
                return NT_STATUS_OK;
        }
 
-       r->out.privs->set = talloc_array_p(r->out.privs, 
-                                          struct lsa_LUIDAttribute, el->num_values);
+       r->out.privs->set = talloc_array(r->out.privs, 
+                                        struct lsa_LUIDAttribute, el->num_values);
        if (r->out.privs->set == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
 
        for (i=0;i<el->num_values;i++) {
-               int id = sec_privilege_id(el->values[i].data);
+               int id = sec_privilege_id((const char *)el->values[i].data);
                if (id == -1) {
                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
                }
@@ -920,7 +1886,7 @@ static NTSTATUS lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
 /* 
   lsa_EnumAccountRights 
 */
-static NTSTATUS lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
+static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
                                      TALLOC_CTX *mem_ctx,
                                      struct lsa_EnumAccountRights *r)
 {
@@ -936,16 +1902,25 @@ static NTSTATUS lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
 
        state = h->data;
 
-       sidstr = dom_sid_string(mem_ctx, r->in.sid);
+       sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
        if (sidstr == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs, 
-                          "objectSid=%s", sidstr);
-       if (ret != 1) {
+       ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
+                          "(&(objectSid=%s)(privilege=*))", sidstr);
+       if (ret == 0) {
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
+       if (ret > 1) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+       if (ret == -1) {
+               DEBUG(3, ("searching for account rights for SID: %s failed: %s", 
+                         dom_sid_string(mem_ctx, r->in.sid),
+                         ldb_errstring(state->sam_ldb)));
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
 
        el = ldb_msg_find_element(res[0], "privilege");
        if (el == NULL || el->num_values == 0) {
@@ -953,14 +1928,14 @@ static NTSTATUS lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
        }
 
        r->out.rights->count = el->num_values;
-       r->out.rights->names = talloc_array_p(r->out.rights, 
-                                             struct lsa_String, r->out.rights->count);
+       r->out.rights->names = talloc_array(r->out.rights, 
+                                           struct lsa_StringLarge, r->out.rights->count);
        if (r->out.rights->names == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
 
        for (i=0;i<el->num_values;i++) {
-               r->out.rights->names[i].string = el->values[i].data;
+               r->out.rights->names[i].string = (const char *)el->values[i].data;
        }
 
        return NT_STATUS_OK;
@@ -971,7 +1946,7 @@ static NTSTATUS lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
 /* 
   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
 */
-static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
+static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
                                           TALLOC_CTX *mem_ctx,
                                           struct lsa_policy_state *state,
                                           int ldb_flag,
@@ -979,32 +1954,37 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
                                           const struct lsa_RightSet *rights)
 {
        const char *sidstr;
-       struct ldb_message msg;
-       struct ldb_message_element el;
+       struct ldb_message *msg;
+       struct ldb_message_element *el;
        int i, ret;
-       const char *dn;
        struct lsa_EnumAccountRights r2;
 
-       sidstr = dom_sid_string(mem_ctx, sid);
+       sidstr = ldap_encode_ndr_dom_sid(mem_ctx, sid);
        if (sidstr == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       dn = samdb_search_string(state->sam_ctx, mem_ctx, NULL, "dn", 
-                                "objectSid=%s", sidstr);
-       if (dn == NULL) {
-               return NT_STATUS_NO_SUCH_USER;
+       msg = ldb_msg_new(mem_ctx);
+       if (msg == NULL) {
+               return NT_STATUS_NO_MEMORY;
        }
 
-       msg.dn = talloc_strdup(mem_ctx, dn);
-       if (msg.dn == NULL) {
-               return NT_STATUS_NO_MEMORY;
+       msg->dn = samdb_search_dn(state->sam_ldb, mem_ctx, 
+                                 NULL, "objectSid=%s", sidstr);
+       if (msg->dn == NULL) {
+               NTSTATUS status;
+               if (ldb_flag == LDB_FLAG_MOD_DELETE) {
+                       return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+               }
+               status = samdb_create_foreign_security_principal(state->sam_ldb, mem_ctx, 
+                                                                sid, &msg->dn);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+               return NT_STATUS_NO_SUCH_USER;
        }
-       msg.num_elements = 1;
-       msg.elements = &el;
-       el.flags = ldb_flag;
-       el.name = talloc_strdup(mem_ctx, "privilege");
-       if (el.name == NULL) {
+
+       if (ldb_msg_add_empty(msg, "privilege", ldb_flag, NULL)) {
                return NT_STATUS_NO_MEMORY;
        }
 
@@ -1013,19 +1993,14 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
 
                r2.in.handle = &state->handle->wire_handle;
                r2.in.sid = sid;
-               r2.out.rights = talloc_p(mem_ctx, struct lsa_RightSet);
+               r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
 
-               status = lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
+               status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
                if (!NT_STATUS_IS_OK(status)) {
                        ZERO_STRUCTP(r2.out.rights);
                }
        }
 
-       el.num_values = 0;
-       el.values = talloc_array_p(mem_ctx, struct ldb_val, rights->count);
-       if (el.values == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
        for (i=0;i<rights->count;i++) {
                if (sec_privilege_id(rights->names[i].string) == -1) {
                        return NT_STATUS_NO_SUCH_PRIVILEGE;
@@ -1034,7 +2009,7 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
                if (ldb_flag == LDB_FLAG_MOD_ADD) {
                        int j;
                        for (j=0;j<r2.out.rights->count;j++) {
-                               if (StrCaseCmp(r2.out.rights->names[j].string, 
+                               if (strcasecmp_m(r2.out.rights->names[j].string, 
                                               rights->names[i].string) == 0) {
                                        break;
                                }
@@ -1042,24 +2017,25 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
                        if (j != r2.out.rights->count) continue;
                }
 
-
-               el.values[el.num_values].length = strlen(rights->names[i].string);
-               el.values[el.num_values].data = talloc_strdup(mem_ctx, rights->names[i].string);
-               if (el.values[el.num_values].data == NULL) {
+               ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
+               if (ret != LDB_SUCCESS) {
                        return NT_STATUS_NO_MEMORY;
                }
-               el.num_values++;
        }
 
-       if (el.num_values == 0) {
+       el = ldb_msg_find_element(msg, "privilege");
+       if (!el) {
                return NT_STATUS_OK;
        }
 
-       ret = samdb_modify(state->sam_ctx, mem_ctx, &msg);
+       ret = samdb_modify(state->sam_ldb, mem_ctx, msg);
        if (ret != 0) {
-               if (ldb_flag == LDB_FLAG_MOD_DELETE) {
+               if (ldb_flag == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
                        return NT_STATUS_OBJECT_NAME_NOT_FOUND;
                }
+               DEBUG(3, ("Could not %s attributes from %s: %s", 
+                         ldb_flag == LDB_FLAG_MOD_DELETE ? "delete" : "add",
+                         ldb_dn_get_linearized(msg->dn), ldb_errstring(state->sam_ldb)));
                return NT_STATUS_UNEXPECTED_IO_ERROR;
        }
 
@@ -1069,7 +2045,7 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
 /* 
   lsa_AddPrivilegesToAccount
 */
-static NTSTATUS lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                           struct lsa_AddPrivilegesToAccount *r)
 {
        struct lsa_RightSet rights;
@@ -1082,7 +2058,7 @@ static NTSTATUS lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, T
        astate = h->data;
 
        rights.count = r->in.privs->count;
-       rights.names = talloc_array_p(mem_ctx, struct lsa_String, rights.count);
+       rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
        if (rights.names == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -1097,7 +2073,7 @@ static NTSTATUS lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, T
                }
        }
 
-       return lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
+       return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
                                          LDB_FLAG_MOD_ADD, astate->account_sid,
                                          &rights);
 }
@@ -1106,7 +2082,7 @@ static NTSTATUS lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, T
 /* 
   lsa_RemovePrivilegesFromAccount
 */
-static NTSTATUS lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                                struct lsa_RemovePrivilegesFromAccount *r)
 {
        struct lsa_RightSet *rights;
@@ -1118,7 +2094,7 @@ static NTSTATUS lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_ca
 
        astate = h->data;
 
-       rights = talloc_p(mem_ctx, struct lsa_RightSet);
+       rights = talloc(mem_ctx, struct lsa_RightSet);
 
        if (r->in.remove_all == 1 && 
            r->in.privs == NULL) {
@@ -1129,12 +2105,12 @@ static NTSTATUS lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_ca
                r2.in.sid = astate->account_sid;
                r2.out.rights = rights;
 
-               status = lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
+               status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
 
-               return lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
+               return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
                                                  LDB_FLAG_MOD_DELETE, astate->account_sid,
                                                  r2.out.rights);
        }
@@ -1144,7 +2120,7 @@ static NTSTATUS lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_ca
        }
 
        rights->count = r->in.privs->count;
-       rights->names = talloc_array_p(mem_ctx, struct lsa_String, rights->count);
+       rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
        if (rights->names == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -1159,7 +2135,7 @@ static NTSTATUS lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_ca
                }
        }
 
-       return lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
+       return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
                                          LDB_FLAG_MOD_DELETE, astate->account_sid,
                                          rights);
 }
@@ -1168,7 +2144,7 @@ static NTSTATUS lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_ca
 /* 
   lsa_GetQuotasForAccount
 */
-static NTSTATUS lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_GetQuotasForAccount *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -1176,60 +2152,30 @@ static NTSTATUS lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALL
 
 
 /* 
-  lsa_SetQuotasForAccount
-*/
-static NTSTATUS lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_SetQuotasForAccount *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-
-/* 
-  lsa_GetSystemAccessAccount
-*/
-static NTSTATUS lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_GetSystemAccessAccount *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-
-/* 
-  lsa_SetSystemAccessAccount
-*/
-static NTSTATUS lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_SetSystemAccessAccount *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-
-/* 
-  lsa_OpenTrustedDomain
+  lsa_SetQuotasForAccount
 */
-static NTSTATUS lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_OpenTrustedDomain *r)
+static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct lsa_SetQuotasForAccount *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
 
 /* 
-  lsa_QueryTrustedDomainInfo
+  lsa_GetSystemAccessAccount
 */
-static NTSTATUS lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_QueryTrustedDomainInfo *r)
+static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct lsa_GetSystemAccessAccount *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
 
 /* 
-  lsa_SetInformationTrustedDomain
+  lsa_SetSystemAccessAccount
 */
-static NTSTATUS lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_SetInformationTrustedDomain *r)
+static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct lsa_SetSystemAccessAccount *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
@@ -1238,7 +2184,7 @@ static NTSTATUS lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_ca
 /* 
   lsa_CreateSecret 
 */
-static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                 struct lsa_CreateSecret *r)
 {
        struct dcesrv_handle *policy_handle;
@@ -1246,6 +2192,7 @@ static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX
        struct lsa_secret_state *secret_state;
        struct dcesrv_handle *handle;
        struct ldb_message **msgs, *msg;
+       const char *errstr;
        const char *attrs[] = {
                NULL
        };
@@ -1267,6 +2214,7 @@ static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX
        if (!secret_state) {
                return NT_STATUS_NO_MEMORY;
        }
+       secret_state->policy = policy_state;
 
        msg = ldb_msg_new(mem_ctx);
        if (msg == NULL) {
@@ -1276,15 +2224,16 @@ static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX
        if (strncmp("G$", r->in.name.string, 2) == 0) {
                const char *name2;
                name = &r->in.name.string[2];
-               secret_state->sam_ctx = talloc_reference(secret_state, policy_state->sam_ctx);
+               secret_state->sam_ldb = talloc_reference(secret_state, policy_state->sam_ldb);
+               secret_state->global = True;
 
                if (strlen(name) < 1) {
                        return NT_STATUS_INVALID_PARAMETER;
                }
 
-               name2 = talloc_asprintf(mem_ctx, "%s Secret", name);
+               name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
                /* search for the secret record */
-               ret = samdb_search(secret_state->sam_ctx,
+               ret = gendb_search(secret_state->sam_ldb,
                                   mem_ctx, policy_state->system_dn, &msgs, attrs,
                                   "(&(cn=%s)(objectclass=secret))", 
                                   name2);
@@ -1292,51 +2241,68 @@ static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX
                        return NT_STATUS_OBJECT_NAME_COLLISION;
                }
                
-               if (ret < 0 || ret > 1) {
-                       DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
+               if (ret == -1) {
+                       DEBUG(0,("Failure searching for CN=%s: %s\n", 
+                                name2, ldb_errstring(secret_state->sam_ldb)));
                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
                }
 
-               msg->dn = talloc_asprintf(mem_ctx, "cn=%s,%s", name2, policy_state->system_dn);
-               if (!name2 || !msg->dn) {
+               msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
+               if (!name2 || ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
                        return NT_STATUS_NO_MEMORY;
                }
                
-               samdb_msg_add_string(secret_state->sam_ctx, mem_ctx, msg, "cn", name2);
+               samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
        
        } else {
+               secret_state->global = False;
+
                name = r->in.name.string;
                if (strlen(name) < 1) {
                        return NT_STATUS_INVALID_PARAMETER;
                }
 
-               secret_state->sam_ctx = talloc_reference(secret_state, secrets_db_connect(mem_ctx));
+               secret_state->sam_ldb = talloc_reference(secret_state, secrets_db_connect(mem_ctx));
                /* search for the secret record */
-               ret = samdb_search(secret_state->sam_ctx,
-                                  mem_ctx, "cn=LSA Secrets", &msgs, attrs,
+               ret = gendb_search(secret_state->sam_ldb, mem_ctx,
+                                  ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
+                                  &msgs, attrs,
                                   "(&(cn=%s)(objectclass=secret))", 
-                                  name);
+                                  ldb_binary_encode_string(mem_ctx, name));
                if (ret > 0) {
                        return NT_STATUS_OBJECT_NAME_COLLISION;
                }
                
-               if (ret < 0 || ret > 1) {
-                       DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
+               if (ret == -1) {
+                       DEBUG(0,("Failure searching for CN=%s: %s\n", 
+                                name, ldb_errstring(secret_state->sam_ldb)));
                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
                }
 
-               msg->dn = talloc_asprintf(mem_ctx, "cn=%s,cn=LSA Secrets", name);
-               samdb_msg_add_string(secret_state->sam_ctx, mem_ctx, msg, "cn", name);
+               msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb, "cn=%s,cn=LSA Secrets", name);
+               samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
        } 
-       samdb_msg_add_string(secret_state->sam_ctx, mem_ctx, msg, "objectClass", "secret");
+
+       /* pull in all the template attributes.  Note this is always from the global samdb */
+       ret = samdb_copy_template(secret_state->policy->sam_ldb, msg, 
+                                 "secret", &errstr);
+       if (ret != 0) {
+               DEBUG(0,("Failed to load TemplateSecret from samdb: %s\n",
+                        errstr));
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
        
        secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
 
        /* create the secret */
-       ret = samdb_add(secret_state->sam_ctx, mem_ctx, msg);
+       ret = samdb_add(secret_state->sam_ldb, mem_ctx, msg);
        if (ret != 0) {
-               DEBUG(0,("Failed to create secret record %s\n", msg->dn));
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               DEBUG(0,("Failed to create secret record %s: %s\n",
+                        ldb_dn_get_linearized(msg->dn), 
+                        ldb_errstring(secret_state->sam_ldb)));
+               return NT_STATUS_ACCESS_DENIED;
        }
 
        handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
@@ -1358,7 +2324,7 @@ static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX
 /* 
   lsa_OpenSecret 
 */
-static NTSTATUS lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                               struct lsa_OpenSecret *r)
 {
        struct dcesrv_handle *policy_handle;
@@ -1387,47 +2353,54 @@ static NTSTATUS lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
        if (!secret_state) {
                return NT_STATUS_NO_MEMORY;
        }
+       secret_state->policy = policy_state;
 
        if (strncmp("G$", r->in.name.string, 2) == 0) {
                name = &r->in.name.string[2];
-               secret_state->sam_ctx = talloc_reference(secret_state, policy_state->sam_ctx);
+               secret_state->sam_ldb = talloc_reference(secret_state, policy_state->sam_ldb);
+               secret_state->global = True;
 
                if (strlen(name) < 1) {
                        return NT_STATUS_INVALID_PARAMETER;
                }
 
                /* search for the secret record */
-               ret = samdb_search(secret_state->sam_ctx,
+               ret = gendb_search(secret_state->sam_ldb,
                                   mem_ctx, policy_state->system_dn, &msgs, attrs,
                                   "(&(cn=%s Secret)(objectclass=secret))", 
-                                  name);
+                                  ldb_binary_encode_string(mem_ctx, name));
                if (ret == 0) {
                        return NT_STATUS_OBJECT_NAME_NOT_FOUND;
                }
                
                if (ret != 1) {
-                       DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
+                       DEBUG(0,("Found %d records matching DN %s\n", ret,
+                                ldb_dn_get_linearized(policy_state->system_dn)));
                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
                }
        
        } else {
+               secret_state->sam_ldb = talloc_reference(secret_state, secrets_db_connect(mem_ctx));
+
+               secret_state->global = False;
                name = r->in.name.string;
                if (strlen(name) < 1) {
                        return NT_STATUS_INVALID_PARAMETER;
                }
 
-               secret_state->sam_ctx = talloc_reference(secret_state, secrets_db_connect(mem_ctx));
                /* search for the secret record */
-               ret = samdb_search(secret_state->sam_ctx,
-                                  mem_ctx, "cn=LSA Secrets", &msgs, attrs,
+               ret = gendb_search(secret_state->sam_ldb, mem_ctx,
+                                  ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
+                                  &msgs, attrs,
                                   "(&(cn=%s)(objectclass=secret))", 
-                                  name);
+                                  ldb_binary_encode_string(mem_ctx, name));
                if (ret == 0) {
                        return NT_STATUS_OBJECT_NAME_NOT_FOUND;
                }
                
                if (ret != 1) {
-                       DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
+                       DEBUG(0,("Found %d records matching CN=%s\n", 
+                                ret, ldb_binary_encode_string(mem_ctx, name)));
                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
                }
        } 
@@ -1453,7 +2426,7 @@ static NTSTATUS lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
 /* 
   lsa_SetSecret 
 */
-static NTSTATUS lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                              struct lsa_SetSecret *r)
 {
 
@@ -1501,16 +2474,36 @@ static NTSTATUS lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
                val.length = secret.length;
                
                /* set value */
-               if (samdb_msg_add_value(secret_state->sam_ctx
-                                       mem_ctx, msg, "priorSecret", &val) != 0) {
+               if (samdb_msg_add_value(secret_state->sam_ldb
+                                       mem_ctx, msg, "priorValue", &val) != 0) {
                        return NT_STATUS_NO_MEMORY; 
                }
                
                /* set old value mtime */
-               if (samdb_msg_add_uint64(secret_state->sam_ctx
+               if (samdb_msg_add_uint64(secret_state->sam_ldb
                                         mem_ctx, msg, "priorSetTime", nt_now) != 0) { 
                        return NT_STATUS_NO_MEMORY; 
                }
+
+               if (!r->in.new_val) {
+                       /* This behaviour varies depending of if this is a local, or a global secret... */
+                       if (secret_state->global) {
+                               /* set old value mtime */
+                               if (samdb_msg_add_uint64(secret_state->sam_ldb, 
+                                                        mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
+                                       return NT_STATUS_NO_MEMORY; 
+                               }
+                       } else {
+                               if (samdb_msg_add_delete(secret_state->sam_ldb, 
+                                                        mem_ctx, msg, "currentValue")) {
+                                       return NT_STATUS_NO_MEMORY;
+                               }
+                               if (samdb_msg_add_delete(secret_state->sam_ldb, 
+                                                        mem_ctx, msg, "lastSetTime")) {
+                                       return NT_STATUS_NO_MEMORY;
+                               }
+                       }
+               }
        }
 
        if (r->in.new_val) {
@@ -1527,13 +2520,13 @@ static NTSTATUS lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
                val.length = secret.length;
                
                /* set value */
-               if (samdb_msg_add_value(secret_state->sam_ctx
-                                       mem_ctx, msg, "secret", &val) != 0) {
+               if (samdb_msg_add_value(secret_state->sam_ldb
+                                       mem_ctx, msg, "currentValue", &val) != 0) {
                        return NT_STATUS_NO_MEMORY; 
                }
                
                /* set new value mtime */
-               if (samdb_msg_add_uint64(secret_state->sam_ctx
+               if (samdb_msg_add_uint64(secret_state->sam_ldb
                                         mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
                        return NT_STATUS_NO_MEMORY; 
                }
@@ -1545,31 +2538,31 @@ static NTSTATUS lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
                        NTTIME last_set_time;
                        struct ldb_message **res;
                        const char *attrs[] = {
-                               "secret",
+                               "currentValue",
                                "lastSetTime",
                                NULL
                        };
                        
                        /* search for the secret record */
-                       ret = samdb_search(secret_state->sam_ctx,
-                                          mem_ctx, NULL, &res, attrs,
-                                          "(dn=%s)", secret_state->secret_dn);
+                       ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
+                                             secret_state->secret_dn, &res, attrs);
                        if (ret == 0) {
                                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
                        }
                        
                        if (ret != 1) {
-                               DEBUG(0,("Found %d records matching dn=%s\n", ret, secret_state->secret_dn));
+                               DEBUG(0,("Found %d records matching dn=%s\n", ret,
+                                        ldb_dn_get_linearized(secret_state->secret_dn)));
                                return NT_STATUS_INTERNAL_DB_CORRUPTION;
                        }
 
-                       new_val = ldb_msg_find_ldb_val(res[0], "secret");
-                       last_set_time = ldb_msg_find_uint64(res[0], "lastSetTime", 0);
+                       new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
+                       last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
                        
                        if (new_val) {
                                /* set value */
-                               if (samdb_msg_add_value(secret_state->sam_ctx
-                                                       mem_ctx, msg, "priorSecret", 
+                               if (samdb_msg_add_value(secret_state->sam_ldb
+                                                       mem_ctx, msg, "priorValue", 
                                                        new_val) != 0) {
                                        return NT_STATUS_NO_MEMORY; 
                                }
@@ -1577,7 +2570,7 @@ static NTSTATUS lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
                        
                        /* set new value mtime */
                        if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
-                               if (samdb_msg_add_uint64(secret_state->sam_ctx
+                               if (samdb_msg_add_uint64(secret_state->sam_ldb
                                                         mem_ctx, msg, "priorSetTime", last_set_time) != 0) { 
                                        return NT_STATUS_NO_MEMORY; 
                                }
@@ -1586,7 +2579,7 @@ static NTSTATUS lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
        }
 
        /* modify the samdb record */
-       ret = samdb_replace(secret_state->sam_ctx, mem_ctx, msg);
+       ret = samdb_replace(secret_state->sam_ldb, mem_ctx, msg);
        if (ret != 0) {
                /* we really need samdb.c to return NTSTATUS */
                return NT_STATUS_UNSUCCESSFUL;
@@ -1599,7 +2592,7 @@ static NTSTATUS lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
 /* 
   lsa_QuerySecret 
 */
-static NTSTATUS lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                struct lsa_QuerySecret *r)
 {
        struct dcesrv_handle *h;
@@ -1610,8 +2603,8 @@ static NTSTATUS lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *
        int ret;
        struct ldb_message **res;
        const char *attrs[] = {
-               "secret",
-               "priorSecret",
+               "currentValue",
+               "priorValue",
                "lastSetTime",
                "priorSetTime", 
                NULL
@@ -1619,17 +2612,13 @@ static NTSTATUS lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *
 
        NTSTATUS nt_status;
 
-       time_t now = time(NULL);
-       NTTIME now_nt;
-       unix_to_nt_time(&now_nt, now);
-
        DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
 
        secret_state = h->data;
 
        /* pull all the user attributes */
-       ret = samdb_search(secret_state->sam_ctx, mem_ctx, NULL, &res, attrs,
-                          "dn=%s", secret_state->secret_dn);
+       ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
+                             secret_state->secret_dn, &res, attrs);
        if (ret != 1) {
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
@@ -1642,19 +2631,25 @@ static NTSTATUS lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *
        
        if (r->in.old_val) {
                const struct ldb_val *prior_val;
-               /* Decrypt */
-               prior_val = ldb_msg_find_ldb_val(res[0], "priorSecret");
+               r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
+               if (!r->out.old_val) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
                
                if (prior_val && prior_val->length) {
                        secret.data = prior_val->data;
                        secret.length = prior_val->length;
                
+                       /* Encrypt */
                        crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
                        if (!crypt_secret.length) {
                                return NT_STATUS_NO_MEMORY;
                        }
-                       r->out.old_val = talloc(mem_ctx, struct lsa_DATA_BUF_PTR);
                        r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
+                       if (!r->out.old_val->buf) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
                        r->out.old_val->buf->size = crypt_secret.length;
                        r->out.old_val->buf->length = crypt_secret.length;
                        r->out.old_val->buf->data = crypt_secret.data;
@@ -1662,28 +2657,35 @@ static NTSTATUS lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *
        }
        
        if (r->in.old_mtime) {
-               r->out.old_mtime = talloc(mem_ctx, NTTIME_hyper);
+               r->out.old_mtime = talloc(mem_ctx, NTTIME);
                if (!r->out.old_mtime) {
                        return NT_STATUS_NO_MEMORY;
                }
-               *r->out.old_mtime = ldb_msg_find_uint64(res[0], "priorSetTime", 0);
+               *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
        }
        
        if (r->in.new_val) {
                const struct ldb_val *new_val;
-               /* Decrypt */
-               new_val = ldb_msg_find_ldb_val(res[0], "secret");
+               r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
+               if (!r->out.new_val) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
                
                if (new_val && new_val->length) {
                        secret.data = new_val->data;
                        secret.length = new_val->length;
                
+                       /* Encrypt */
                        crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
                        if (!crypt_secret.length) {
                                return NT_STATUS_NO_MEMORY;
                        }
-                       r->out.new_val = talloc(mem_ctx, struct lsa_DATA_BUF_PTR);
                        r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
+                       if (!r->out.new_val->buf) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
                        r->out.new_val->buf->length = crypt_secret.length;
                        r->out.new_val->buf->size = crypt_secret.length;
                        r->out.new_val->buf->data = crypt_secret.data;
@@ -1691,11 +2693,11 @@ static NTSTATUS lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *
        }
        
        if (r->in.new_mtime) {
-               r->out.new_mtime = talloc(mem_ctx, NTTIME_hyper);
+               r->out.new_mtime = talloc(mem_ctx, NTTIME);
                if (!r->out.new_mtime) {
                        return NT_STATUS_NO_MEMORY;
                }
-               *r->out.new_mtime = ldb_msg_find_uint64(res[0], "lastSetTime", 0);
+               *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
        }
        
        return NT_STATUS_OK;
@@ -1705,7 +2707,7 @@ static NTSTATUS lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *
 /* 
   lsa_LookupPrivValue
 */
-static NTSTATUS lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
+static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
                                    TALLOC_CTX *mem_ctx,
                                    struct lsa_LookupPrivValue *r)
 {
@@ -1732,7 +2734,7 @@ static NTSTATUS lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
 /* 
   lsa_LookupPrivName 
 */
-static NTSTATUS lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
+static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
                                   TALLOC_CTX *mem_ctx,
                                   struct lsa_LookupPrivName *r)
 {
@@ -1753,7 +2755,7 @@ static NTSTATUS lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
                return NT_STATUS_NO_SUCH_PRIVILEGE;
        }
 
-       r->out.name = talloc_p(mem_ctx, struct lsa_String);
+       r->out.name = talloc(mem_ctx, struct lsa_StringLarge);
        if (r->out.name == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -1766,7 +2768,7 @@ static NTSTATUS lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
 /* 
   lsa_LookupPrivDisplayName
 */
-static NTSTATUS lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
+static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
                                          TALLOC_CTX *mem_ctx,
                                          struct lsa_LookupPrivDisplayName *r)
 {
@@ -1783,7 +2785,7 @@ static NTSTATUS lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
                return NT_STATUS_NO_SUCH_PRIVILEGE;
        }
        
-       r->out.disp_name = talloc_p(mem_ctx, struct lsa_String);
+       r->out.disp_name = talloc(mem_ctx, struct lsa_StringLarge);
        if (r->out.disp_name == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -1800,7 +2802,7 @@ static NTSTATUS lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
 /* 
   lsa_DeleteObject
 */
-static NTSTATUS lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_DeleteObject *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -1810,7 +2812,7 @@ static NTSTATUS lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX
 /* 
   lsa_EnumAccountsWithUserRight
 */
-static NTSTATUS lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
+static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
                                              TALLOC_CTX *mem_ctx,
                                              struct lsa_EnumAccountsWithUserRight *r)
 {
@@ -1834,27 +2836,23 @@ static NTSTATUS lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call
                return NT_STATUS_NO_SUCH_PRIVILEGE;
        }
 
-       ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs, 
+       ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
                           "privilege=%s", privname);
-       if (ret <= 0) {
-               return NT_STATUS_NO_SUCH_USER;
+       if (ret == -1) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+       if (ret == 0) {
+               return NT_STATUS_NO_MORE_ENTRIES;
        }
 
-       r->out.sids->sids = talloc_array_p(r->out.sids, struct lsa_SidPtr, ret);
+       r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
        if (r->out.sids->sids == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
        for (i=0;i<ret;i++) {
-               const char *sidstr;
-               sidstr = samdb_result_string(res[i], "objectSid", NULL);
-               if (sidstr == NULL) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-               r->out.sids->sids[i].sid = dom_sid_parse_talloc(r->out.sids->sids,
-                                                               sidstr);
-               if (r->out.sids->sids[i].sid == NULL) {
-                       return NT_STATUS_NO_MEMORY;
-               }
+               r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
+                                                               res[i], "objectSid");
+               NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
        }
        r->out.sids->num_sids = ret;
 
@@ -1865,7 +2863,7 @@ static NTSTATUS lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call
 /* 
   lsa_AddAccountRights
 */
-static NTSTATUS lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
+static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
                                     TALLOC_CTX *mem_ctx,
                                     struct lsa_AddAccountRights *r)
 {
@@ -1876,7 +2874,7 @@ static NTSTATUS lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
 
        state = h->data;
 
-       return lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
+       return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
                                          LDB_FLAG_MOD_ADD,
                                          r->in.sid, r->in.rights);
 }
@@ -1885,7 +2883,7 @@ static NTSTATUS lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
 /* 
   lsa_RemoveAccountRights
 */
-static NTSTATUS lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
+static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
                                        TALLOC_CTX *mem_ctx,
                                        struct lsa_RemoveAccountRights *r)
 {
@@ -1896,46 +2894,16 @@ static NTSTATUS lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
 
        state = h->data;
 
-       return lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
+       return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
                                          LDB_FLAG_MOD_DELETE,
                                          r->in.sid, r->in.rights);
 }
 
 
-/* 
-  lsa_QueryTrustedDomainInfoBySid
-*/
-static NTSTATUS lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                                               struct lsa_QueryTrustedDomainInfoBySid *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-
-/* 
-  lsa_SetTrustDomainInfo
-*/
-static NTSTATUS lsa_SetTrustDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_SetTrustDomainInfo *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-
-/* 
-  lsa_DeleteTrustDomain
-*/
-static NTSTATUS lsa_DeleteTrustDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_DeleteTrustDomain *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-
 /* 
   lsa_StorePrivateData
 */
-static NTSTATUS lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_StorePrivateData *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -1945,7 +2913,7 @@ static NTSTATUS lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_
 /* 
   lsa_RetrievePrivateData
 */
-static NTSTATUS lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_RetrievePrivateData *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -1955,8 +2923,8 @@ static NTSTATUS lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALL
 /* 
   lsa_GetUserName
 */
-static NTSTATUS lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_GetUserName *r)
+static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                               struct lsa_GetUserName *r)
 {
        NTSTATUS status = NT_STATUS_OK;
        const char *account_name;
@@ -1978,26 +2946,18 @@ static NTSTATUS lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       /* TODO: this check should go and we should rely on the calling code that this is valid */
-       if (!dce_call->conn->auth_state.session_info ||
-           !dce_call->conn->auth_state.session_info->server_info ||
-           !dce_call->conn->auth_state.session_info->server_info->account_name ||
-           !dce_call->conn->auth_state.session_info->server_info->domain_name) {
-               return NT_STATUS_INTERNAL_ERROR;
-       }
-
        account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
        authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
 
-       _account_name = talloc_p(mem_ctx, struct lsa_String);
-       NTSTATUS_TALLOC_CHECK(_account_name);
+       _account_name = talloc(mem_ctx, struct lsa_String);
+       NT_STATUS_HAVE_NO_MEMORY(_account_name);
        _account_name->string = account_name;
 
        if (r->in.authority_name) {
-               _authority_name = talloc_p(mem_ctx, struct lsa_StringPointer);
-               NTSTATUS_TALLOC_CHECK(_authority_name);
-               _authority_name->string = talloc_p(mem_ctx, struct lsa_String);
-               NTSTATUS_TALLOC_CHECK(_authority_name->string);
+               _authority_name = talloc(mem_ctx, struct lsa_StringPointer);
+               NT_STATUS_HAVE_NO_MEMORY(_authority_name);
+               _authority_name->string = talloc(mem_ctx, struct lsa_String);
+               NT_STATUS_HAVE_NO_MEMORY(_authority_name->string);
                _authority_name->string->string = authority_name;
        }
 
@@ -2010,67 +2970,17 @@ static NTSTATUS lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *
 /*
   lsa_SetInfoPolicy2
 */
-static NTSTATUS lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
+static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
                                   TALLOC_CTX *mem_ctx,
                                   struct lsa_SetInfoPolicy2 *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
-/*
-  lsa_QueryTrustedDomainInfoByName
-*/
-static NTSTATUS lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
-                                                TALLOC_CTX *mem_ctx,
-                                                struct lsa_QueryTrustedDomainInfoByName *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-/*
-  lsa_SetTrustedDomainInfoByName
-*/
-static NTSTATUS lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
-                                              TALLOC_CTX *mem_ctx,
-                                              struct lsa_SetTrustedDomainInfoByName *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-/*
-  lsa_EnumTrustedDomainsEx
-*/
-static NTSTATUS lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call,
-                                        TALLOC_CTX *mem_ctx,
-                                        struct lsa_EnumTrustedDomainsEx *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-/*
-  lsa_CreateTrustedDomainEx
-*/
-static NTSTATUS lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
-                                         TALLOC_CTX *mem_ctx,
-                                         struct lsa_CreateTrustedDomainEx *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-/*
-  lsa_CloseTrustedDomainEx
-*/
-static NTSTATUS lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
-                                        TALLOC_CTX *mem_ctx,
-                                        struct lsa_CloseTrustedDomainEx *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
 /*
   lsa_QueryDomainInformationPolicy
 */
-static NTSTATUS lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
+static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
                                                 TALLOC_CTX *mem_ctx,
                                                 struct lsa_QueryDomainInformationPolicy *r)
 {
@@ -2080,19 +2990,9 @@ static NTSTATUS lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_c
 /*
   lsa_SetDomInfoPolicy
 */
-static NTSTATUS lsa_SetDomInfoPolicy(struct dcesrv_call_state *dce_call,
-                                    TALLOC_CTX *mem_ctx,
-                                    struct lsa_SetDomInfoPolicy *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-/*
-  lsa_OpenTrustedDomainByName
-*/
-static NTSTATUS lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
-                                           TALLOC_CTX *mem_ctx,
-                                           struct lsa_OpenTrustedDomainByName *r)
+static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
+                                             TALLOC_CTX *mem_ctx,
+                                             struct lsa_SetDomainInformationPolicy *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
@@ -2100,7 +3000,7 @@ static NTSTATUS lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
 /*
   lsa_TestCall
 */
-static NTSTATUS lsa_TestCall(struct dcesrv_call_state *dce_call,
+static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
                             TALLOC_CTX *mem_ctx,
                             struct lsa_TestCall *r)
 {
@@ -2110,7 +3010,7 @@ static NTSTATUS lsa_TestCall(struct dcesrv_call_state *dce_call,
 /*
   lookup a SID for 1 name
 */
-static NTSTATUS lsa_lookup_name(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
+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;
@@ -2125,14 +3025,9 @@ static NTSTATUS lsa_lookup_name(struct lsa_policy_state *state, TALLOC_CTX *mem_
                name = p + 1;
        }
 
-       ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs, "sAMAccountName=%s", name);
+       ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, "sAMAccountName=%s", ldb_binary_encode_string(mem_ctx, name));
        if (ret == 1) {
-               const char *sid_str = ldb_msg_find_string(res[0], "objectSid", NULL);
-               if (sid_str == NULL) {
-                       return NT_STATUS_INVALID_SID;
-               }
-
-               *sid = dom_sid_parse_talloc(mem_ctx, sid_str);
+               *sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
                if (*sid == NULL) {
                        return NT_STATUS_INVALID_SID;
                }
@@ -2151,34 +3046,34 @@ static NTSTATUS lsa_lookup_name(struct lsa_policy_state *state, TALLOC_CTX *mem_
 /*
   lsa_LookupNames3
 */
-static NTSTATUS lsa_LookupNames3(struct dcesrv_call_state *dce_call,
+static NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
                                 TALLOC_CTX *mem_ctx,
                                 struct lsa_LookupNames3 *r)
 {
-       struct lsa_policy_state *state;
-       struct dcesrv_handle *h;
+       struct lsa_policy_state *policy_state;
+       struct dcesrv_handle *policy_handle;
        int i;
        NTSTATUS status = NT_STATUS_OK;
 
-       r->out.domains = NULL;
+       DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
 
-       DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
+       policy_state = policy_handle->data;
 
-       state = h->data;
+       r->out.domains = NULL;
 
-       r->out.domains = talloc_zero_p(mem_ctx,  struct lsa_RefDomainList);
+       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_p(mem_ctx,  struct lsa_TransSidArray3);
+       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_p(r->out.sids, struct lsa_TranslatedSid3, 
+       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;
@@ -2198,7 +3093,7 @@ static NTSTATUS lsa_LookupNames3(struct dcesrv_call_state *dce_call,
                r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
                r->out.sids->sids[i].unknown     = 0;
 
-               status2 = lsa_lookup_name(state, mem_ctx, name, &sid, &atype);
+               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;
@@ -2210,7 +3105,7 @@ static NTSTATUS lsa_LookupNames3(struct dcesrv_call_state *dce_call,
                        continue;
                }
 
-               status2 = lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
+               status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, sid, r->out.domains, &sid_index);
                if (!NT_STATUS_IS_OK(status2)) {
                        return status2;
                }
@@ -2224,10 +3119,64 @@ static NTSTATUS lsa_LookupNames3(struct dcesrv_call_state *dce_call,
        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 lsa_LookupNames2(struct dcesrv_call_state *dce_call,
+static NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
                                 TALLOC_CTX *mem_ctx,
                                 struct lsa_LookupNames2 *r)
 {
@@ -2242,19 +3191,19 @@ static NTSTATUS lsa_LookupNames2(struct dcesrv_call_state *dce_call,
 
        state = h->data;
 
-       r->out.domains = talloc_zero_p(mem_ctx,  struct lsa_RefDomainList);
+       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_p(mem_ctx,  struct lsa_TransSidArray2);
+       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_p(r->out.sids, struct lsa_TranslatedSid2, 
+       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;
@@ -2274,7 +3223,7 @@ static NTSTATUS lsa_LookupNames2(struct dcesrv_call_state *dce_call,
                r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
                r->out.sids->sids[i].unknown     = 0;
 
-               status2 = lsa_lookup_name(state, mem_ctx, name, &sid, &atype);
+               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;
@@ -2286,7 +3235,7 @@ static NTSTATUS lsa_LookupNames2(struct dcesrv_call_state *dce_call,
                        continue;
                }
 
-               status2 = lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
+               status2 = dcesrv_lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
                if (!NT_STATUS_IS_OK(status2)) {
                        return status2;
                }
@@ -2303,7 +3252,7 @@ static NTSTATUS lsa_LookupNames2(struct dcesrv_call_state *dce_call,
 /* 
   lsa_LookupNames 
 */
-static NTSTATUS lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_LookupNames *r)
 {
        struct lsa_LookupNames2 r2;
@@ -2320,18 +3269,18 @@ static NTSTATUS lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *
        r2.in.unknown2  = 0;
        r2.out.count    = r->out.count;
 
-       status = lsa_LookupNames2(dce_call, mem_ctx, &r2);
+       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_p(mem_ctx, struct lsa_TransSidArray);
+       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_p(r->out.sids, struct lsa_TranslatedSid, 
+       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;
@@ -2345,22 +3294,10 @@ static NTSTATUS lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *
        return status;
 }
 
-
-
-/*
-  lsa_CreateTrustedDomainEx2
-*/
-static NTSTATUS lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
-                                          TALLOC_CTX *mem_ctx,
-                                          struct lsa_CreateTrustedDomainEx2 *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
 /* 
   lsa_CREDRWRITE 
 */
-static NTSTATUS lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_CREDRWRITE *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2370,7 +3307,7 @@ static NTSTATUS lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
 /* 
   lsa_CREDRREAD 
 */
-static NTSTATUS lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_CREDRREAD *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2380,7 +3317,7 @@ static NTSTATUS lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
 /* 
   lsa_CREDRENUMERATE 
 */
-static NTSTATUS lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_CREDRENUMERATE *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2390,7 +3327,7 @@ static NTSTATUS lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CT
 /* 
   lsa_CREDRWRITEDOMAINCREDENTIALS 
 */
-static NTSTATUS lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2400,7 +3337,7 @@ static NTSTATUS lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_ca
 /* 
   lsa_CREDRREADDOMAINCREDENTIALS 
 */
-static NTSTATUS lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_CREDRREADDOMAINCREDENTIALS *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2410,7 +3347,7 @@ static NTSTATUS lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_cal
 /* 
   lsa_CREDRDELETE 
 */
-static NTSTATUS lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_CREDRDELETE *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2420,7 +3357,7 @@ static NTSTATUS lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *
 /* 
   lsa_CREDRGETTARGETINFO 
 */
-static NTSTATUS lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_CREDRGETTARGETINFO *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2430,7 +3367,7 @@ static NTSTATUS lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLO
 /* 
   lsa_CREDRPROFILELOADED 
 */
-static NTSTATUS lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_CREDRPROFILELOADED *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2440,7 +3377,7 @@ static NTSTATUS lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLO
 /* 
   lsa_CREDRGETSESSIONTYPES 
 */
-static NTSTATUS lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_CREDRGETSESSIONTYPES *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2450,7 +3387,7 @@ static NTSTATUS lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TAL
 /* 
   lsa_LSARREGISTERAUDITEVENT 
 */
-static NTSTATUS lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_LSARREGISTERAUDITEVENT *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2460,7 +3397,7 @@ static NTSTATUS lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, T
 /* 
   lsa_LSARGENAUDITEVENT 
 */
-static NTSTATUS lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_LSARGENAUDITEVENT *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2470,7 +3407,7 @@ static NTSTATUS lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC
 /* 
   lsa_LSARUNREGISTERAUDITEVENT 
 */
-static NTSTATUS lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_LSARUNREGISTERAUDITEVENT *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2478,10 +3415,10 @@ static NTSTATUS lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call,
 
 
 /* 
-  lsa_LSARQUERYFORESTTRUSTINFORMATION 
+  lsa_lsaRQueryForestTrustInformation 
 */
-static NTSTATUS lsa_LSARQUERYFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_LSARQUERYFORESTTRUSTINFORMATION *r)
+static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct lsa_lsaRQueryForestTrustInformation *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
@@ -2490,7 +3427,7 @@ static NTSTATUS lsa_LSARQUERYFORESTTRUSTINFORMATION(struct dcesrv_call_state *dc
 /* 
   lsa_LSARSETFORESTTRUSTINFORMATION 
 */
-static NTSTATUS lsa_LSARSETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_LSARSETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_LSARSETFORESTTRUSTINFORMATION *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2500,27 +3437,18 @@ static NTSTATUS lsa_LSARSETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_
 /* 
   lsa_CREDRRENAME 
 */
-static NTSTATUS lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_CREDRRENAME *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
 
-/* 
-  lsa_LSARLOOKUPNAMES4 
-*/
-static NTSTATUS lsa_LSARLOOKUPNAMES4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct lsa_LSARLOOKUPNAMES4 *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
 
 /* 
   lsa_LSAROPENPOLICYSCE 
 */
-static NTSTATUS lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_LSAROPENPOLICYSCE *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2530,7 +3458,7 @@ static NTSTATUS lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC
 /* 
   lsa_LSARADTREGISTERSECURITYEVENTSOURCE 
 */
-static NTSTATUS lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2540,7 +3468,7 @@ static NTSTATUS lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state
 /* 
   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE 
 */
-static NTSTATUS lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2550,7 +3478,7 @@ static NTSTATUS lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_stat
 /* 
   lsa_LSARADTREPORTSECURITYEVENT 
 */
-static NTSTATUS lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_LSARADTREPORTSECURITYEVENT *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -2559,3 +3487,130 @@ static NTSTATUS lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_cal
 
 /* include the generated boilerplate */
 #include "librpc/gen_ndr/ndr_lsa_s.c"
+
+
+
+/*****************************************
+NOTE! The remaining calls below were
+removed in w2k3, so the DCESRV_FAULT()
+replies are the correct implementation. Do
+not try and fill these in with anything else
+******************************************/
+
+/* 
+  dssetup_DsRoleDnsNameToFlatName 
+*/
+static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                       struct dssetup_DsRoleDnsNameToFlatName *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/* 
+  dssetup_DsRoleDcAsDc 
+*/
+static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                            struct dssetup_DsRoleDcAsDc *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/* 
+  dssetup_DsRoleDcAsReplica 
+*/
+static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                 struct dssetup_DsRoleDcAsReplica *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/* 
+  dssetup_DsRoleDemoteDc 
+*/
+static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                              struct dssetup_DsRoleDemoteDc *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/* 
+  dssetup_DsRoleGetDcOperationProgress 
+*/
+static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                            struct dssetup_DsRoleGetDcOperationProgress *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/* 
+  dssetup_DsRoleGetDcOperationResults 
+*/
+static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                           struct dssetup_DsRoleGetDcOperationResults *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/* 
+  dssetup_DsRoleCancel 
+*/
+static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                            struct dssetup_DsRoleCancel *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/* 
+  dssetup_DsRoleServerSaveStateForUpgrade 
+*/
+static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                               struct dssetup_DsRoleServerSaveStateForUpgrade *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/* 
+  dssetup_DsRoleUpgradeDownlevelServer 
+*/
+static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                            struct dssetup_DsRoleUpgradeDownlevelServer *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/* 
+  dssetup_DsRoleAbortDownlevelServerUpgrade 
+*/
+static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                                 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
+{
+       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/* include the generated boilerplate */
+#include "librpc/gen_ndr/ndr_dssetup_s.c"
+
+NTSTATUS dcerpc_server_lsa_init(void)
+{
+       NTSTATUS ret;
+       
+       ret = dcerpc_server_dssetup_init();
+       if (!NT_STATUS_IS_OK(ret)) {
+               return ret;
+       }
+       ret = dcerpc_server_lsarpc_init();
+       if (!NT_STATUS_IS_OK(ret)) {
+               return ret;
+       }
+       return ret;
+}