r17516: Change helper function names to make more clear what they are meant to do
[kamenim/samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
index 55fc9920809847bf768767adef38162de7c8e37f..000f4fd8106c22afc8e5d91680c4d5d347c766ff 100644 (file)
 */
 
 #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 "passdb/secrets.h"
 #include "db_wrap.h"
 
 /*
@@ -65,7 +67,6 @@ struct lsa_account_state {
        struct lsa_policy_state *policy;
        uint32_t access_mask;
        struct dom_sid *account_sid;
-       const struct ldb_dn *account_dn;
 };
 
 
@@ -89,6 +90,17 @@ struct lsa_trusted_domain_state {
        const struct ldb_dn *trusted_domain_dn;
 };
 
+static NTSTATUS lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
+                                     TALLOC_CTX *mem_ctx,
+                                     struct lsa_EnumAccountRights *r);
+
+static NTSTATUS 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 
 */
@@ -138,6 +150,41 @@ static NTSTATUS lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_c
                }
 
                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 = 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 = 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;
@@ -220,9 +267,7 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_
                                     struct lsa_policy_state **_state)
 {
        struct lsa_policy_state *state;
-       const char *domain_attrs[] =  {"nETBIOSName", "nCName", NULL};
-       int ret_domain;
-       struct ldb_message **msgs_domain;
+       const struct ldb_dn *partitions_basedn = ldb_dn_string_compose(mem_ctx, samdb_base_dn(mem_ctx), "CN=Partitions,CN=Configuration");
 
        state = talloc(mem_ctx, struct lsa_policy_state);
        if (!state) {
@@ -230,7 +275,7 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_
        }
 
        /* make sure the sam database is accessible */
-       state->sam_ldb = samdb_connect(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;
        }
@@ -240,57 +285,50 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
 
-       ret_domain = gendb_search(state->sam_ldb, mem_ctx, NULL, &msgs_domain, domain_attrs,
-                                 "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))", 
-                                 lp_workgroup());
-       
-       if (ret_domain == -1) {
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
-       }
-               
-       if (ret_domain != 1) {
-               return NT_STATUS_NO_SUCH_DOMAIN;                
-       }
-
        /* work out the domain_dn - useful for so many calls its worth
           fetching here */
-       state->domain_dn = samdb_result_dn(state, msgs_domain[0], "nCName", NULL);
+       state->domain_dn = samdb_base_dn(state);
        if (!state->domain_dn) {
+               return NT_STATUS_NO_MEMORY;             
+       }
+
+       state->domain_name
+               = samdb_search_string(state->sam_ldb, state, partitions_basedn, "nETBIOSName", 
+                                     "(&(objectclass=crossRef)(ncName=%s))", ldb_dn_linearize(mem_ctx, state->domain_dn));
+       
+       if (!state->domain_name) {
                return NT_STATUS_NO_SUCH_DOMAIN;                
        }
+       talloc_steal(state, state->domain_name);
 
        /* work out the builtin_dn - useful for so many calls its worth
           fetching here */
-       state->builtin_dn = samdb_search_dn(state->sam_ldb, mem_ctx, NULL, "objectClass=builtinDomain");
+       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, mem_ctx,
+       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->domain_sid = talloc_steal(state, 
-                                        samdb_search_dom_sid(state->sam_ldb, state,
-                                                             state->domain_dn, "objectSid", "dn=%s",
-                                                             ldb_dn_linearize(mem_ctx, state->domain_dn)));
+       state->domain_sid = samdb_search_dom_sid(state->sam_ldb, state,
+                                                state->domain_dn, "objectSid", NULL);
        if (!state->domain_sid) {
                return NT_STATUS_NO_SUCH_DOMAIN;                
        }
 
+       talloc_steal(state, state->domain_sid);
+
        state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
        if (!state->builtin_sid) {
                return NT_STATUS_NO_SUCH_DOMAIN;                
        }
 
-       state->domain_name = talloc_strdup(state, 
-                                          samdb_result_string(msgs_domain[0], "nETBIOSName", 
-                                                              lp_workgroup()));
-
        *_state = state;
 
        return NT_STATUS_OK;
@@ -466,7 +504,42 @@ static NTSTATUS lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX
 static NTSTATUS lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                  struct lsa_CreateAccount *r)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       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;
 }
 
 
@@ -487,9 +560,12 @@ static NTSTATUS lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX
 
        state = h->data;
 
-       ret = gendb_search(state->sam_ldb, mem_ctx, state->builtin_dn, &res, attrs, 
-                          "privilege=*");
-       if (ret <= 0) {
+       /* NOTE: This call must only return accounts that have at least
+          one privilege set 
+       */
+       ret = gendb_search(state->sam_ldb, mem_ctx, samdb_base_dn(mem_ctx), &res, attrs, 
+                          "(&(objectSid=*)(privilege=*))");
+       if (ret < 0) {
                return NT_STATUS_NO_SUCH_USER;
        }
 
@@ -589,7 +665,7 @@ static NTSTATUS lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALL
        ret = gendb_search(trusted_domain_state->policy->sam_ldb,
                           mem_ctx, policy_state->system_dn, &msgs, attrs,
                           "(&(cn=%s)(objectclass=trustedDomain))", 
-                          r->in.info->name.string);
+                          ldb_binary_encode_string(mem_ctx, r->in.info->name.string));
        if (ret > 0) {
                return NT_STATUS_OBJECT_NAME_COLLISION;
        }
@@ -750,7 +826,7 @@ static NTSTATUS lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
        ret = gendb_search(trusted_domain_state->policy->sam_ldb,
                           mem_ctx, policy_state->system_dn, &msgs, attrs,
                           "(&(flatname=%s)(objectclass=trustedDomain))", 
-                          r->in.name.string);
+                          ldb_binary_encode_string(mem_ctx, r->in.name.string));
        if (ret == 0) {
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
@@ -1062,9 +1138,9 @@ static NTSTATUS lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *m
        }
 
        domains->domains = talloc_realloc(domains, 
-                                           domains->domains,
-                                           struct lsa_TrustInformation,
-                                           domains->count+1);
+                                         domains->domains,
+                                         struct lsa_TrustInformation,
+                                         domains->count+1);
        if (domains->domains == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -1091,12 +1167,12 @@ static NTSTATUS lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_c
        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);
                        }
                }
 
@@ -1246,6 +1322,7 @@ static NTSTATUS lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
        r3.in.unknown1 = 0;
        r3.in.unknown2 = 0;
        r3.out.count   = r->out.count;
+       r3.out.names   = NULL;
 
        status = lsa_LookupSids3(dce_call, mem_ctx, &r3);
        if (dce_call->fault_code != 0) {
@@ -1253,6 +1330,11 @@ static NTSTATUS lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
        }
 
        r->out.domains = r3.out.domains;
+       if (!r3.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;
@@ -1300,15 +1382,6 @@ static NTSTATUS lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *
                return NT_STATUS_NO_MEMORY;
        }
        
-       /* check it really exists */
-       astate->account_dn = samdb_search_string(state->sam_ldb, astate,
-                                                NULL, "(&(objectSid=%s)(objectClass=group))", 
-                                                ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid));
-       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;
 
@@ -1339,6 +1412,7 @@ 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);
 
@@ -1349,8 +1423,13 @@ static NTSTATUS lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
        r->out.privs->unknown = 0;
        r->out.privs->set = NULL;
 
-       ret = gendb_search_dn(astate->policy->sam_ldb, mem_ctx,
-                             astate->account_dn, &res, attrs);
+       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, samdb_base_dn(mem_ctx), &res, attrs, 
+                          "objectSid=%s", sidstr);
        if (ret != 1) {
                return NT_STATUS_OK;
        }
@@ -1361,7 +1440,7 @@ static NTSTATUS lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
        }
 
        r->out.privs->set = talloc_array(r->out.privs, 
-                                          struct lsa_LUIDAttribute, el->num_values);
+                                        struct lsa_LUIDAttribute, el->num_values);
        if (r->out.privs->set == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -1405,11 +1484,20 @@ static NTSTATUS lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
                return NT_STATUS_NO_MEMORY;
        }
 
-       ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
-                          "objectSid=%s", sidstr);
-       if (ret != 1) {
+       ret = gendb_search(state->sam_ldb, mem_ctx, samdb_base_dn(mem_ctx), &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) {
@@ -1418,7 +1506,7 @@ static NTSTATUS lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
 
        r->out.rights->count = el->num_values;
        r->out.rights->names = talloc_array(r->out.rights, 
-                                             struct lsa_String, r->out.rights->count);
+                                           struct lsa_StringLarge, r->out.rights->count);
        if (r->out.rights->names == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -1444,9 +1532,8 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
 {
        const char *sidstr;
        struct ldb_message *msg;
-       struct ldb_message_element el;
+       struct ldb_message_element *el;
        int i, ret;
-       const char *dn;
        struct lsa_EnumAccountRights r2;
 
        sidstr = ldap_encode_ndr_dom_sid(mem_ctx, sid);
@@ -1459,17 +1546,22 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
                return NT_STATUS_NO_MEMORY;
        }
 
-       dn = samdb_search_dn(state->sam_ldb, mem_ctx, NULL, "objectSid=%s", sidstr);
-       if (dn == NULL) {
-               return NT_STATUS_NO_SUCH_USER;
-       }
-
-       msg->dn = ldb_dn_explode(mem_ctx, dn);
+       msg->dn = samdb_search_dn(state->sam_ldb, mem_ctx, 
+                                 samdb_base_dn(mem_ctx), "objectSid=%s", sidstr);
        if (msg->dn == NULL) {
-               return NT_STATUS_NO_MEMORY;
+               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;
        }
 
-       if (ldb_msg_add_empty(state->sam_ldb, msg, "privilege", ldb_flag)) {
+       if (ldb_msg_add_empty(msg, "privilege", ldb_flag)) {
                return NT_STATUS_NO_MEMORY;
        }
 
@@ -1486,11 +1578,6 @@ static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
                }
        }
 
-       el.num_values = 0;
-       el.values = talloc_array(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;
@@ -1507,24 +1594,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 = (uint8_t *)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_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_linearize(mem_ctx, msg->dn), ldb_errstring(state->sam_ldb)));
                return NT_STATUS_UNEXPECTED_IO_ERROR;
        }
 
@@ -1547,7 +1635,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(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;
        }
@@ -1609,7 +1697,7 @@ static NTSTATUS lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_ca
        }
 
        rights->count = r->in.privs->count;
-       rights->names = talloc_array(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;
        }
@@ -1719,7 +1807,7 @@ static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX
                        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 = gendb_search(secret_state->sam_ldb,
                                   mem_ctx, policy_state->system_dn, &msgs, attrs,
@@ -1729,9 +1817,9 @@ 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,
-                                ldb_dn_linearize(mem_ctx, 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;
                }
 
@@ -1755,14 +1843,15 @@ static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX
                ret = gendb_search(secret_state->sam_ldb, mem_ctx,
                                   ldb_dn_explode(mem_ctx, "cn=LSA Secrets"),
                                   &msgs, attrs,
-                                  "(&(cn=%s)(objectclass=secret))", name);
+                                  "(&(cn=%s)(objectclass=secret))", 
+                                  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,
-                                ldb_dn_linearize(mem_ctx, 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;
                }
 
@@ -1771,10 +1860,11 @@ static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX
        } 
 
        /* pull in all the template attributes.  Note this is always from the global samdb */
-       ret = samdb_copy_template(secret_state->policy->sam_ldb, mem_ctx, msg, 
-                                 "(&(name=TemplateSecret)(objectclass=secretTemplate))");
+       ret = samdb_copy_template(secret_state->policy->sam_ldb, msg, 
+                                 "(&(cn=TemplateSecret)(objectclass=secretTemplate))");
        if (ret != 0) {
-               DEBUG(0,("Failed to load TemplateSecret from samdb\n"));
+               DEBUG(0,("Failed to load TemplateSecret from samdb: %s\n", 
+                        ldb_errstring(secret_state->policy->sam_ldb)));
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
 
@@ -1785,8 +1875,9 @@ static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX
        /* create the secret */
        ret = samdb_add(secret_state->sam_ldb, mem_ctx, msg);
        if (ret != 0) {
-               DEBUG(0,("Failed to create secret record %s\n",
-                        ldb_dn_linearize(mem_ctx, msg->dn)));
+               DEBUG(0,("Failed to create secret record %s: %s\n",
+                        ldb_dn_linearize(mem_ctx, msg->dn), 
+                        ldb_errstring(secret_state->sam_ldb)));
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
 
@@ -1853,7 +1944,7 @@ static NTSTATUS lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
                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;
                }
@@ -1877,7 +1968,8 @@ static NTSTATUS lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
                ret = gendb_search(secret_state->sam_ldb, mem_ctx,
                                   ldb_dn_explode(mem_ctx, "cn=LSA Secrets"),
                                   &msgs, attrs,
-                                  "(&(cn=%s)(objectclass=secret))", name);
+                                  "(&(cn=%s)(objectclass=secret))", 
+                                  ldb_binary_encode_string(mem_ctx, name));
                if (ret == 0) {
                        return NT_STATUS_OBJECT_NAME_NOT_FOUND;
                }
@@ -2041,7 +2133,7 @@ static NTSTATUS lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
                        }
 
                        new_val = ldb_msg_find_ldb_val(res[0], "secret");
-                       last_set_time = ldb_msg_find_uint64(res[0], "lastSetTime", 0);
+                       last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
                        
                        if (new_val) {
                                /* set value */
@@ -2145,7 +2237,7 @@ static NTSTATUS lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *
                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) {
@@ -2181,7 +2273,7 @@ static NTSTATUS lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *
                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;
@@ -2239,7 +2331,7 @@ static NTSTATUS lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
                return NT_STATUS_NO_SUCH_PRIVILEGE;
        }
 
-       r->out.name = talloc(mem_ctx, struct lsa_String);
+       r->out.name = talloc(mem_ctx, struct lsa_StringLarge);
        if (r->out.name == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -2269,7 +2361,7 @@ static NTSTATUS lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
                return NT_STATUS_NO_SUCH_PRIVILEGE;
        }
        
-       r->out.disp_name = talloc(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;
        }
@@ -2320,10 +2412,13 @@ static NTSTATUS lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call
                return NT_STATUS_NO_SUCH_PRIVILEGE;
        }
 
-       ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
+       ret = gendb_search(state->sam_ldb, mem_ctx, samdb_base_dn(mem_ctx), &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(r->out.sids, struct lsa_SidPtr, ret);
@@ -2405,7 +2500,7 @@ 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)
+                               struct lsa_GetUserName *r)
 {
        NTSTATUS status = NT_STATUS_OK;
        const char *account_name;
@@ -2427,26 +2522,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(mem_ctx, struct lsa_String);
-       NTSTATUS_TALLOC_CHECK(_account_name);
+       NT_STATUS_HAVE_NO_MEMORY(_account_name);
        _account_name->string = account_name;
 
        if (r->in.authority_name) {
                _authority_name = talloc(mem_ctx, struct lsa_StringPointer);
-               NTSTATUS_TALLOC_CHECK(_authority_name);
+               NT_STATUS_HAVE_NO_MEMORY(_authority_name);
                _authority_name->string = talloc(mem_ctx, struct lsa_String);
-               NTSTATUS_TALLOC_CHECK(_authority_name->string);
+               NT_STATUS_HAVE_NO_MEMORY(_authority_name->string);
                _authority_name->string->string = authority_name;
        }
 
@@ -2514,7 +2601,7 @@ static NTSTATUS lsa_lookup_name(struct lsa_policy_state *state, TALLOC_CTX *mem_
                name = p + 1;
        }
 
-       ret = gendb_search(state->sam_ldb, 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) {
                *sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
                if (*sid == NULL) {
@@ -2533,22 +2620,22 @@ static NTSTATUS lsa_lookup_name(struct lsa_policy_state *state, TALLOC_CTX *mem_
 
 
 /*
-  lsa_LookupNames3
+  lsa_LookupNames4
 */
-static NTSTATUS lsa_LookupNames3(struct dcesrv_call_state *dce_call,
+static NTSTATUS lsa_LookupNames4(struct dcesrv_call_state *dce_call,
                                 TALLOC_CTX *mem_ctx,
-                                struct lsa_LookupNames3 *r)
+                                struct lsa_LookupNames4 *r)
 {
        struct lsa_policy_state *state;
-       struct dcesrv_handle *h;
        int i;
        NTSTATUS status = NT_STATUS_OK;
 
-       r->out.domains = NULL;
-
-       DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
+       status = lsa_get_policy_state(dce_call, mem_ctx, &state);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
-       state = h->data;
+       r->out.domains = NULL;
 
        r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
        if (r->out.domains == NULL) {
@@ -2608,6 +2695,38 @@ static NTSTATUS lsa_LookupNames3(struct dcesrv_call_state *dce_call,
        return status;
 }
 
+/* 
+  lsa_LookupNames3
+*/
+static NTSTATUS lsa_LookupNames3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                struct lsa_LookupNames3 *r)
+{
+       struct lsa_LookupNames4 r2;
+       NTSTATUS status;
+       struct dcesrv_handle *h;
+       DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
+       
+       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 = lsa_LookupNames4(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
 */
@@ -2879,15 +2998,6 @@ static NTSTATUS lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *
 }
 
 
-/* 
-  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