r10810: This adds the hooks required to communicate the current user from the
authorAndrew Bartlett <abartlet@samba.org>
Fri, 7 Oct 2005 11:31:45 +0000 (11:31 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:39:32 +0000 (13:39 -0500)
authenticated session down into LDB.  This associates a session info
structure with the open LDB, allowing a future ldb_ntacl module to
allow/deny operations on that basis.

Along the way, I cleaned up a few things, and added new helper functions
to assist.  In particular the LSA pipe uses simpler queries for some of
the setup.

In ldap_server, I have removed the 'ldasrv:hacked' module, which hasn't
been worked on (other than making it continue to compile) since January,
and I think the features of this module are being put into ldb anyway.

I have also changed the partitions in ldap_server to be initialised
after the connection, with the private pointer used to associate the ldb
with the incoming session.

Andrew Bartlett

27 files changed:
source/auth/auth_sam.c
source/auth/auth_util.c
source/cldap_server/netlogon.c
source/dsdb/samdb/samdb.c
source/dsdb/samdb/samdb_privilege.c
source/kdc/hdb-ldb.c
source/ldap_server/config.mk
source/ldap_server/ldap_backend.c
source/ldap_server/ldap_bind.c
source/ldap_server/ldap_hacked_ldb.c [deleted file]
source/ldap_server/ldap_rootdse.c
source/ldap_server/ldap_server.c
source/ldap_server/ldap_server.h
source/ldap_server/ldap_simple_ldb.c
source/lib/ldb/tools/cmdline.c
source/libcli/security/security_token.c
source/libnet/libnet_join.c
source/libnet/libnet_samsync_ldb.c
source/nbt_server/dgram/netlogon.c
source/ntvfs/common/sidmap.c
source/rpc_server/drsuapi/dcesrv_drsuapi.c
source/rpc_server/drsuapi/drsuapi_cracknames.c
source/rpc_server/dssetup/dcesrv_dssetup.c
source/rpc_server/lsa/dcesrv_lsa.c
source/rpc_server/netlogon/dcerpc_netlogon.c
source/rpc_server/samr/dcesrv_samr.c
source/rpc_server/samr/samr_password.c

index 1df2103eb6269b3759d0df40d9959d00d13770c4..de4be9586ca9c02dac2b413991d2ce3fc2d9d818 100644 (file)
@@ -521,7 +521,7 @@ NTSTATUS sam_get_server_info(TALLOC_CTX *mem_ctx, const char *account_name, cons
        struct ldb_message **domain_msgs;
        void *sam_ctx;
 
-       sam_ctx = samdb_connect(mem_ctx);
+       sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx));
        if (sam_ctx == NULL) {
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
@@ -558,7 +558,7 @@ static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
-       sam_ctx = samdb_connect(mem_ctx);
+       sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx));
        if (sam_ctx == NULL) {
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
index 19fd63ed2e10ed7cdd25aac3c9ffa0a5cdad190b..da5df9b368f3e70b297c9acb3c44884e8e8f9130 100644 (file)
@@ -427,6 +427,73 @@ NTSTATUS auth_anonymous_server_info(TALLOC_CTX *mem_ctx, struct auth_serversuppl
        return NT_STATUS_OK;
 }
 
+NTSTATUS auth_system_server_info(TALLOC_CTX *mem_ctx, struct auth_serversupplied_info **_server_info) 
+{
+       struct auth_serversupplied_info *server_info;
+       server_info = talloc(mem_ctx, struct auth_serversupplied_info);
+       NT_STATUS_HAVE_NO_MEMORY(server_info);
+
+       server_info->account_sid = dom_sid_parse_talloc(server_info, SID_NT_SYSTEM);
+       NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid);
+
+       /* is this correct? */
+       server_info->primary_group_sid = dom_sid_parse_talloc(server_info, SID_BUILTIN_ADMINISTRATORS);
+       NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid);
+
+       server_info->n_domain_groups = 0;
+       server_info->domain_groups = NULL;
+
+       /* annoying, but the Anonymous really does have a session key, 
+          and it is all zeros! */
+       server_info->user_session_key = data_blob_talloc(server_info, NULL, 16);
+       NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data);
+
+       server_info->lm_session_key = data_blob_talloc(server_info, NULL, 16);
+       NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data);
+
+       data_blob_clear(&server_info->user_session_key);
+       data_blob_clear(&server_info->lm_session_key);
+
+       server_info->account_name = talloc_strdup(server_info, "sYSTEM");
+       NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
+
+       server_info->domain_name = talloc_strdup(server_info, "NT AUTHORITY");
+       NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
+
+       server_info->full_name = talloc_strdup(server_info, "System");
+       NT_STATUS_HAVE_NO_MEMORY(server_info->full_name);
+
+       server_info->logon_script = talloc_strdup(server_info, "");
+       NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script);
+
+       server_info->profile_path = talloc_strdup(server_info, "");
+       NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path);
+
+       server_info->home_directory = talloc_strdup(server_info, "");
+       NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory);
+
+       server_info->home_drive = talloc_strdup(server_info, "");
+       NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive);
+
+       server_info->last_logon = 0;
+       server_info->last_logoff = 0;
+       server_info->acct_expiry = 0;
+       server_info->last_password_change = 0;
+       server_info->allow_password_change = 0;
+       server_info->force_password_change = 0;
+
+       server_info->logon_count = 0;
+       server_info->bad_password_count = 0;
+
+       server_info->acct_flags = ACB_NORMAL;
+
+       server_info->authenticated = False;
+
+       *_server_info = server_info;
+
+       return NT_STATUS_OK;
+}
+
 NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, 
                                    struct auth_serversupplied_info *server_info, 
                                    struct auth_session_info **_session_info) 
@@ -482,6 +549,54 @@ NTSTATUS auth_anonymous_session_info(TALLOC_CTX *parent_ctx,
        return NT_STATUS_OK;
 }
 
+struct auth_session_info *anonymous_session(TALLOC_CTX *mem_ctx) 
+{
+       NTSTATUS nt_status;
+       struct auth_session_info *session_info = NULL;
+       nt_status = auth_anonymous_session_info(mem_ctx, &session_info);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               return NULL;
+       }
+       return session_info;
+}
+
+NTSTATUS auth_system_session_info(TALLOC_CTX *parent_ctx, 
+                                 struct auth_session_info **_session_info) 
+{
+       NTSTATUS nt_status;
+       struct auth_serversupplied_info *server_info = NULL;
+       struct auth_session_info *session_info = NULL;
+       TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
+       
+       nt_status = auth_system_server_info(mem_ctx,
+                                           &server_info);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               talloc_free(mem_ctx);
+               return nt_status;
+       }
+
+       /* references the server_info into the session_info */
+       nt_status = auth_generate_session_info(parent_ctx, server_info, &session_info);
+       talloc_free(mem_ctx);
+
+       NT_STATUS_NOT_OK_RETURN(nt_status);
+
+       *_session_info = session_info;
+
+       return NT_STATUS_OK;
+}
+
+struct auth_session_info *system_session(TALLOC_CTX *mem_ctx) 
+{
+       NTSTATUS nt_status;
+       struct auth_session_info *session_info = NULL;
+       nt_status = auth_system_session_info(mem_ctx, &session_info);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               return NULL;
+       }
+       return session_info;
+}
+
 /****************************************************************************
  prints a struct auth_session_info security token to debug output.
 ****************************************************************************/
index bfecc3576fa60f627576e3d02d2369f8db5dcf67..95d0250268cec9849b148b413a89ea2080c67343 100644 (file)
@@ -56,7 +56,7 @@ static NTSTATUS cldapd_netlogon_fill(struct cldapd_server *cldapd,
        const char *pdc_ip;
 
        if (cldapd->samctx == NULL) {
-               cldapd->samctx = samdb_connect(cldapd);
+               cldapd->samctx = samdb_connect(cldapd, anonymous_session(cldapd));
                if (cldapd->samctx == NULL) {
                        DEBUG(2,("Unable to open sam in cldap netlogon reply\n"));
                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
index 717b72ded23af3306aa51725893968b72c248b19..93cf6f4b8d338f856ec503c8347d7f97eb4fe5b6 100644 (file)
   connect to the SAM database
   return an opaque context pointer on success, or NULL on failure
  */
-struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx)
+struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx, struct auth_session_info *session_info)
 {
-       return ldb_wrap_connect(mem_ctx, lp_sam_url(), 0, NULL);
+       struct ldb_context *ldb;
+       ldb = ldb_wrap_connect(mem_ctx, lp_sam_url(), 0, NULL);
+       if (ldb_set_opaque(ldb, "sessionInfo", session_info)) {
+               return NULL;
+       }
+       return ldb;
 }
 
 /*
index 059d612225e290621dbb1d8ebf38f18a01239fe5..55dfef04aa23118ef7024043bd7261add7112e03 100644 (file)
@@ -75,11 +75,23 @@ static NTSTATUS samdb_privilege_setup_sid(void *samctx, TALLOC_CTX *mem_ctx,
 NTSTATUS samdb_privilege_setup(struct security_token *token)
 {
        void *samctx;
-       TALLOC_CTX *mem_ctx = talloc_new(token);
+       TALLOC_CTX *mem_ctx;
        int i;
        NTSTATUS status;
 
-       samctx = samdb_connect(mem_ctx);
+       /* Shortcuts to prevent recursion and avoid lookups */
+       if (is_system_token(token)) {
+               token->privilege_mask = ~0;
+               return NT_STATUS_OK;
+       }
+
+       if (is_anonymous_token(token)) {
+               token->privilege_mask = 0;
+               return NT_STATUS_OK;
+       }
+
+       mem_ctx = talloc_new(token);
+       samctx = samdb_connect(mem_ctx, system_session(mem_ctx));
        if (samctx == NULL) {
                talloc_free(mem_ctx);
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
index ecdda16150c60b3d12d04de18dc5813fb509df02..2f97fd6ee8c891b367394d5222612b8103bb46d1 100644 (file)
@@ -1040,7 +1040,7 @@ krb5_error_code hdb_ldb_create(TALLOC_CTX *mem_ctx,
        (*db)->hdb_db = NULL;
 
        /* Setup the link to LDB */
-       (*db)->hdb_db = samdb_connect(db);
+       (*db)->hdb_db = samdb_connect(db, system_session(db));
        if ((*db)->hdb_db == NULL) {
                krb5_warnx(context, "hdb_ldb_create: samdb_connect failed!");
                krb5_set_error_string(context, "samdb_connect failed!");
index 3d39b397bd07943b8ebce2f9c6d36419168a9af4..59f1d5c178c9385f3849ad3777cfc4113800a119 100644 (file)
@@ -8,8 +8,7 @@ INIT_OBJ_FILES = \
                ldap_server/ldap_backend.o \
                ldap_server/ldap_bind.o \
                ldap_server/ldap_rootdse.o \
-               ldap_server/ldap_simple_ldb.o \
-               ldap_server/ldap_hacked_ldb.o
+               ldap_server/ldap_simple_ldb.o 
 REQUIRED_SUBSYSTEMS = \
                LIBCLI_LDAP SAMDB
 # End SUBSYSTEM SMB
index 96c9b16f5dbf9b3d2baef6f82e2bafbfafff2d0a..65e6d9d4d4585544a8e9fac936b8d7c19880eb42 100644 (file)
@@ -53,10 +53,10 @@ struct ldapsrv_partition *ldapsrv_get_partition(struct ldapsrv_connection *conn,
 {
        if (scope == LDAP_SEARCH_SCOPE_BASE
            && strcasecmp("", dn) == 0) {
-               return conn->service->rootDSE;
+               return conn->rootDSE;
        }
 
-       return conn->service->default_partition;
+       return conn->default_partition;
 }
 
 NTSTATUS ldapsrv_unwilling(struct ldapsrv_call *call, int error)
@@ -257,15 +257,3 @@ NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
 }
 
 
-/*
-  connect to the sam database
-*/
-struct ldb_context *ldapsrv_sam_connect(struct ldapsrv_call *call)
-{
-       const char *url;
-       url = lp_parm_string(-1, "ldapsrv", "samdb");
-       if (url) {
-               return ldb_wrap_connect(call, url, 0, NULL);
-       }
-       return samdb_connect(call);
-}
index 166bd31edef10589e897c7200e9e472d085bdf0a..9c9cca362bac5ee9bd482312e2789ec04a4c0a79 100644 (file)
@@ -32,6 +32,8 @@ static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
 
        DEBUG(10, ("BindSimple dn: %s\n",req->dn));
 
+       /* When we add authentication here, we also need to handle telling the backends */
+
        reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
        if (!reply) {
                return NT_STATUS_NO_MEMORY;
@@ -102,14 +104,33 @@ reply:
                result = LDAP_SASL_BIND_IN_PROGRESS;
                errstr = NULL;
        } else if (NT_STATUS_IS_OK(status)) {
+               struct ldapsrv_partition *part;
+
                result = LDAP_SUCCESS;
                errstr = NULL;
                if (gensec_have_feature(call->conn->gensec, GENSEC_FEATURE_SEAL) ||
                    gensec_have_feature(call->conn->gensec, GENSEC_FEATURE_SIGN)) {
                        call->conn->enable_wrap = True;
                }
+               status = gensec_session_info(call->conn->gensec, &call->conn->session_info);
+               if (!NT_STATUS_IS_OK(status)) {
+                       result = LDAP_OPERATIONS_ERROR;
+                       errstr = talloc_asprintf(reply, "SASL:[%s]: Failed to get session info: %s", req->creds.SASL.mechanism, nt_errstr(status));
+               } else {
+                       for (part = call->conn->partitions; part; part = part->next) {
+                               if (!part->ops->Bind) {
+                                       continue;
+                               }
+                               status = part->ops->Bind(part, conn);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       result = LDAP_OPERATIONS_ERROR;
+                                       errstr = talloc_asprintf(reply, "SASL:[%s]: Failed to advise partition %s of new credentials: %s", req->creds.SASL.mechanism, part->base_dn, nt_errstr(status));
+                               }
+                       }
+               }
        } else {
-               result = 49;
+               status = auth_nt_status_squash(status);
+               result = LDAP_INVALID_CREDENTIALS;
                errstr = talloc_asprintf(reply, "SASL:[%s]: %s", req->creds.SASL.mechanism, nt_errstr(status));
        }
 
diff --git a/source/ldap_server/ldap_hacked_ldb.c b/source/ldap_server/ldap_hacked_ldb.c
deleted file mode 100644 (file)
index 8923bc5..0000000
+++ /dev/null
@@ -1,1038 +0,0 @@
-/* 
-   Unix SMB/CIFS implementation.
-   LDAP server HACKED LDB implementation to hopefully get a DsGetNCChanges() request from a
-   w2k3 box
-
-   Copyright (C) Stefan Metzmacher 2004-2005
-   Copyright (C) Simo Sorce 2004
-   
-   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
-   (at your option) any later version.
-   
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-   
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-#include "ldap_server/ldap_server.h"
-#include "lib/ldb/include/ldb.h"
-#include "librpc/gen_ndr/ndr_security.h"
-#include "librpc/gen_ndr/ndr_misc.h"
-#include "db_wrap.h"
-
-
-#define VALID_DN_SYNTAX(dn,i) do {\
-       if (!(dn)) {\
-               return NT_STATUS_NO_MEMORY;\
-       } else if ((dn)->comp_num < (i)) {\
-               result = LDAP_INVALID_DN_SYNTAX;\
-               errstr = "Invalid DN (" #i " components needed for '" #dn "')";\
-               goto reply;\
-       }\
-} while(0)
-
-#define ATTR_BLOB_CONST(val) data_blob_talloc(mem_ctx, val, sizeof(val)-1)
-
-#define ATTR_SINGLE_NOVAL(ctx, attr, blob, num, nam) do { \
-       attr->name = talloc_strdup(ctx, nam);\
-       NT_STATUS_HAVE_NO_MEMORY(attr->name);\
-       attr->num_values = num; \
-       attr->values = blob;\
-} while(0)                              
-
-
-static NTSTATUS convert_values(TALLOC_CTX *mem_ctx,
-                              struct ldb_message_element *elem,
-                              struct ldb_message_element *attrs,
-                              struct ldb_context *samdb,
-                              const char **dn,
-                              struct ldap_SearchRequest *r)
-{
-       NTSTATUS status;
-       DEBUG(10, ("convert_values for %s\n", attrs[0].name));
-
-       attrs->name = talloc_steal(mem_ctx, elem->name);
-       attrs->values[0].length = elem->values[0].length;
-       attrs->values[0].data = talloc_steal(mem_ctx, elem->values[0].data);
-
-       if (strcasecmp(attrs->name, "objectGUID") == 0 ||
-           strcasecmp(attrs->name, "invocationID") == 0)
-       {
-               struct GUID guid;
-               DATA_BLOB blob;
-
-               status = GUID_from_string((const char *)elem->values[0].data, &guid);
-               NT_STATUS_NOT_OK_RETURN(status);
-
-               status = ndr_push_struct_blob(&blob, mem_ctx, &guid,
-                             (ndr_push_flags_fn_t)ndr_push_GUID);
-               NT_STATUS_NOT_OK_RETURN(status);
-
-               attrs->values[0].length = blob.length;
-               attrs->values[0].data = talloc_steal(mem_ctx, blob.data);
-       }
-
-       if (strcasecmp(attrs->name, "objectSID") == 0)
-       {
-               struct dom_sid *sid;
-               DATA_BLOB blob;
-
-               sid = dom_sid_parse_talloc(mem_ctx, (const char *)elem->values[0].data);
-               NT_STATUS_HAVE_NO_MEMORY(sid);
-
-               status = ndr_push_struct_blob(&blob, mem_ctx, sid,
-                             (ndr_push_flags_fn_t)ndr_push_dom_sid);
-               NT_STATUS_NOT_OK_RETURN(status);
-
-               attrs->values[0].length = blob.length;
-               attrs->values[0].data = talloc_steal(mem_ctx, blob.data);
-       }
-
-       if (strcasecmp(attrs->name, "ncname") == 0)
-       {
-               char *filter = ldb_filter_from_tree(mem_ctx, r->tree);
-               struct ldb_message **res = NULL;
-               int count;
-               const char *dom_dn;
-               const char *dom_filter;
-
-               const char *dom_sid_str;
-               struct dom_sid *dom_sid;
-               DATA_BLOB dom_sid_blob;
-               const char *dom_sid_hex;
-
-               const char *dom_guid_str;
-               struct GUID dom_guid;
-               DATA_BLOB dom_guid_blob;
-               const char *dom_guid_hex;
-
-               const char *nc_filter;
-               const char *nc_guid_str;
-               struct GUID nc_guid;
-               DATA_BLOB nc_guid_blob;
-               char *nc_guid_hex;
-               const char *ncname;
-
-               const char *s_attrs[] = {"objectGUID", "objectSid", NULL};
-               char *p2;
-
-               nc_filter = talloc_asprintf(mem_ctx, "(dn=%s)", *dn);
-DEBUG(0, (__location__": convert_values(ncname): nc dn = '%s'\n", nc_filter));
-
-               
-               /* first the NC stuff */
-               count = ldb_search(samdb, NULL, LDB_SCOPE_BASE, nc_filter, s_attrs, &res);
-               if (count != 1) {
-                       DEBUG(0, (__location__": convert_values(ncname): nc_count: %d \n", count));
-                       return NT_STATUS_FOOBAR;
-               }
-DEBUG(0, (__location__": convert_values(ncname): nc_res '%s'\n", ldb_dn_linearize(mem_ctx, res[0]->dn)));
-               nc_guid_str = samdb_result_string(res[0], "objectGUID", NULL);
-
-               status = GUID_from_string(nc_guid_str, &nc_guid);
-
-               status = ndr_push_struct_blob(&nc_guid_blob, mem_ctx, &nc_guid,
-                             (ndr_push_flags_fn_t)ndr_push_GUID);
-
-               nc_guid_hex = data_blob_hex_string(mem_ctx, &nc_guid_blob);
-
-               /* overwrite the dn of the search result */
-               *dn = talloc_asprintf(mem_ctx, "<GUID=%s>;%s", nc_guid_hex, *dn);
-DEBUG(0, (__location__": convert_values(ncname): dn='%s'\n",*dn));
-               /* now the domain stuff */
-
-               dom_dn = strchr(filter, '=');
-               dom_dn++;
-
-               p2 = strchr(filter, ')');
-               *p2 ='\0';
-
-               dom_filter = talloc_asprintf(mem_ctx, "(dn=%s)", dom_dn);
-DEBUG(0, (__location__": convert_values(ncname): dom dn = '%s'\n", dom_filter));
-               count = ldb_search(samdb, NULL, LDB_SCOPE_BASE, dom_filter, s_attrs, &res);
-               if (count != 1) {
-                       DEBUG(0, (__location__": convert_values(ncname): dom_count: %d \n", count));
-                       return NT_STATUS_OK;
-               }
-
-               dom_guid_str = samdb_result_string(res[0], "objectGUID", NULL);
-
-               status = GUID_from_string(dom_guid_str, &dom_guid);
-
-               status = ndr_push_struct_blob(&dom_guid_blob, mem_ctx, &dom_guid,
-                             (ndr_push_flags_fn_t)ndr_push_GUID);
-
-               dom_guid_hex = data_blob_hex_string(mem_ctx, &dom_guid_blob);
-
-               dom_sid_str = samdb_result_string(res[0], "objectSid", NULL);
-
-               dom_sid = dom_sid_parse_talloc(mem_ctx, dom_sid_str);
-
-               status = ndr_push_struct_blob(&dom_sid_blob, mem_ctx, dom_sid,
-                             (ndr_push_flags_fn_t)ndr_push_dom_sid);
-
-               dom_sid_hex = data_blob_hex_string(mem_ctx, &dom_sid_blob);
-
-               ncname = talloc_asprintf(mem_ctx, "<GUID=%s>;<SID=%s>;%s",
-                                       dom_guid_hex, dom_sid_hex, dom_dn);
-DEBUG(0, (__location__": convert_values(ncname): ncname='%s'\n",ncname));
-
-               attrs->values[0].length = strlen(ncname);
-               attrs->values[0].data = talloc_steal(mem_ctx, ncname);
-DEBUG(0, (__location__": convert_values(ncname): end ok\n"));
-       }
-
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS hacked_wellknown_Search(struct ldapsrv_partition *partition, struct ldapsrv_call *call,
-                                    struct ldap_SearchRequest *r)
-{
-       void *local_ctx;
-       struct ldap_SearchResEntry *ent;
-       struct ldap_Result *done;
-       struct ldapsrv_reply *ent_r, *done_r;
-       int count;
-       const char *dn_prefix;
-       const char *wkdn;
-       char *p, *p2;
-       enum ldb_scope scope = LDB_SCOPE_DEFAULT;
-       char *basedn_str;
-
-       local_ctx = talloc_named(call, 0, "hacked_wellknown_Search local memory context");
-       NT_STATUS_HAVE_NO_MEMORY(local_ctx);
-
-       switch (r->scope) {
-               case LDAP_SEARCH_SCOPE_BASE:
-                       scope = LDB_SCOPE_BASE;
-                       break;
-               default:
-                       return NT_STATUS_NOT_IMPLEMENTED;
-       }
-
-#define WKGUID_prefix "<WKGUID="
-       if (strncasecmp(WKGUID_prefix, r->basedn, strlen(WKGUID_prefix)) != 0) {
-               return NT_STATUS_NOT_IMPLEMENTED;
-       }
-
-       basedn_str = talloc_strdup(call, r->basedn);
-
-#define WKGUID_Infrastructure "<WKGUID=2FBAC1870ADE11D297C400C04FD8D5CD,"
-#define WKGUID_Infrastructure_DN "CN=Infrastructure,"
-       if (strncasecmp(WKGUID_Infrastructure, r->basedn, strlen(WKGUID_Infrastructure)) == 0) {
-               dn_prefix = WKGUID_Infrastructure_DN;
-       } else
-#define WKGUID_Domain_Controllers "<WKGUID=A361B2FFFFD211D1AA4B00C04FD7D83A,"
-#define WKGUID_Domain_Controllers_DN "OU=Domain Controllers,"  
-       if (strncasecmp(WKGUID_Domain_Controllers, r->basedn, strlen(WKGUID_Domain_Controllers)) == 0) {
-               dn_prefix = WKGUID_Domain_Controllers_DN;
-       } else {
-               DEBUG(0,("UKNOWN dn '%s'\n", basedn_str));
-               return NT_STATUS_NOT_IMPLEMENTED;
-       }
-
-       p = strchr(basedn_str, ',');
-       p++;
-
-       p2 = strchr(basedn_str, '>');
-       *p2 ='\0';
-
-       wkdn = talloc_asprintf(call, "%s%s", dn_prefix, p);
-
-       count = 1;
-       ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
-       NT_STATUS_HAVE_NO_MEMORY(ent_r);
-
-       ent = &ent_r->msg->r.SearchResultEntry;
-       ent->dn = talloc_steal(ent_r, wkdn);
-       DEBUG(0,("hacked result [0] dn: %s\n", ent->dn));
-       ent->num_attributes = 0;
-       ent->attributes = NULL;
-
-       ldapsrv_queue_reply(call, ent_r);
-
-       done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
-       NT_STATUS_HAVE_NO_MEMORY(done_r);
-
-       DEBUG(10,("hacked_Search: results: [%d]\n",count));
-
-       done = &done_r->msg->r.SearchResultDone;
-       done->dn = NULL;
-       done->resultcode = LDAP_SUCCESS;
-       done->errormessage = NULL;
-       done->referral = NULL;
-
-       talloc_free(local_ctx);
-
-       ldapsrv_queue_reply(call, done_r);
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS hacked_Search(struct ldapsrv_partition *partition, struct ldapsrv_call *call,
-                                    struct ldap_SearchRequest *r, struct ldb_context *samdb)
-{
-       NTSTATUS status;
-       void *local_ctx;
-       struct ldap_SearchResEntry *ent;
-       struct ldap_Result *done;
-       struct ldb_message **res = NULL;
-       int result = LDAP_SUCCESS;
-       struct ldapsrv_reply *ent_r, *done_r;
-       const char *errstr = NULL;
-       int count, j, y, i;
-       const char **attrs = NULL;
-       enum ldb_scope scope = LDB_SCOPE_DEFAULT;
-       struct ldb_dn *basedn;
-
-       local_ctx = talloc_named(call, 0, "hacked_Search local memory context");
-       NT_STATUS_HAVE_NO_MEMORY(local_ctx);
-
-       basedn = ldb_dn_explode(local_ctx, r->basedn);
-
-       switch (r->scope) {
-               case LDAP_SEARCH_SCOPE_BASE:
-                       DEBUG(10,("hldb_Search: scope: [BASE]\n"));
-                       scope = LDB_SCOPE_BASE;
-                       break;
-               case LDAP_SEARCH_SCOPE_SINGLE:
-                       DEBUG(10,("hldb_Search: scope: [ONE]\n"));
-                       scope = LDB_SCOPE_ONELEVEL;
-                       break;
-               case LDAP_SEARCH_SCOPE_SUB:
-                       DEBUG(10,("hldb_Search: scope: [SUB]\n"));
-                       scope = LDB_SCOPE_SUBTREE;
-                       break;
-       }
-
-       if (r->num_attributes >= 1) {
-               attrs = talloc_array(samdb, const char *, r->num_attributes+1);
-               NT_STATUS_HAVE_NO_MEMORY(attrs);
-
-               for (j=0; j < r->num_attributes; j++) {
-                       DEBUG(10,("hacked_Search: attrs: [%s]\n",r->attributes[j]));
-                       attrs[j] = r->attributes[j];
-               }
-               attrs[j] = NULL;
-       }
-DEBUG(0,("hacked basedn: %s\n", ldb_dn_linearize(local_ctx, basedn)));
-DEBUGADD(0,("hacked filter: %s\n", ldb_filter_from_tree(r, r->tree)));
-       count = ldb_search_bytree(samdb, basedn, scope, r->tree, attrs, &res);
-       talloc_steal(samdb, res);
-
-       if (count < 1) {
-               DEBUG(0,("hacked not found\n"));
-               return NT_STATUS_NOT_IMPLEMENTED;
-       }
-
-       if (scope == LDAP_SEARCH_SCOPE_BASE) {
-               ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
-               NT_STATUS_HAVE_NO_MEMORY(ent_r);
-
-               ent = &ent_r->msg->r.SearchResultEntry;
-               ent->dn = ldb_dn_linearize(ent_r, res[0]->dn);
-               DEBUG(0,("hacked result [0] dn: %s\n", ent->dn));
-               ent->num_attributes = 0;
-               ent->attributes = NULL;
-               if (res[0]->num_elements == 0) {
-                       goto queue_reply;
-               }
-               ent->num_attributes = res[0]->num_elements;
-               ent->attributes = talloc_array(ent_r, struct ldb_message_element, ent->num_attributes);
-               NT_STATUS_HAVE_NO_MEMORY(ent->attributes);
-               for (j=0; j < ent->num_attributes; j++) {
-                       ent->attributes[j].name = talloc_steal(ent->attributes, res[0]->elements[j].name);
-                       ent->attributes[j].num_values = 0;
-                       ent->attributes[j].values = NULL;
-                       ent->attributes[j].num_values = res[0]->elements[j].num_values;
-                       if (ent->attributes[j].num_values == 1) {
-                               ent->attributes[j].values = talloc_array(ent->attributes,
-                                                               DATA_BLOB, ent->attributes[j].num_values);
-                               NT_STATUS_HAVE_NO_MEMORY(ent->attributes[j].values);
-                               status = convert_values(ent_r,
-                                                       &(res[0]->elements[j]),
-                                                       &(ent->attributes[j]),
-                                                       samdb, &ent->dn, r);
-                               if (!NT_STATUS_IS_OK(status)) {
-                                       return status;
-                               }
-                       } else {
-                               ent->attributes[j].values = talloc_array(ent->attributes,
-                                                               DATA_BLOB, ent->attributes[j].num_values);
-                               NT_STATUS_HAVE_NO_MEMORY(ent->attributes[j].values);
-                               for (y=0; y < ent->attributes[j].num_values; y++) {
-                                       ent->attributes[j].values[y].length = res[0]->elements[j].values[y].length;
-                                       ent->attributes[j].values[y].data = talloc_steal(ent->attributes[j].values,
-                                                                               res[0]->elements[j].values[y].data);
-                               }
-                       }
-               }
-queue_reply:
-               ldapsrv_queue_reply(call, ent_r);
-       } else {
-               for (i=0; i < count; i++) {
-                       ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
-                       NT_STATUS_HAVE_NO_MEMORY(ent_r);
-
-                       ent = &ent_r->msg->r.SearchResultEntry;
-                       ent->dn = ldb_dn_linearize(ent_r, res[i]->dn);
-                       DEBUG(0,("hacked result [%d] dn: %s\n", i, ent->dn));
-                       ent->num_attributes = 0;
-                       ent->attributes = NULL;
-                       if (res[i]->num_elements == 0) {
-                               goto queue_reply2;
-                       }
-                       ent->num_attributes = res[i]->num_elements;
-                       ent->attributes = talloc_array(ent_r, struct ldb_message_element, ent->num_attributes);
-                       NT_STATUS_HAVE_NO_MEMORY(ent->attributes);
-                       for (j=0; j < ent->num_attributes; j++) {
-                               ent->attributes[j].name = talloc_steal(ent->attributes, res[i]->elements[j].name);
-                               ent->attributes[j].num_values = 0;
-                               ent->attributes[j].values = NULL;
-                               if (r->attributesonly && (res[i]->elements[j].num_values == 0)) {
-                                       continue;
-                               }
-                               ent->attributes[j].num_values = res[i]->elements[j].num_values;
-                               ent->attributes[j].values = talloc_array(ent->attributes,
-                                                               DATA_BLOB, ent->attributes[j].num_values);
-                               NT_STATUS_HAVE_NO_MEMORY(ent->attributes[j].values);
-                               if (ent->attributes[j].num_values == 1) {
-                                       status = convert_values(ent_r,
-                                                       &(res[0]->elements[j]),
-                                                       &(ent->attributes[j]),
-                                                       samdb, &ent->dn, r);
-                                       if (!NT_STATUS_IS_OK(status)) {
-                                               return status;
-                                       }
-                               } else {
-                                       for (y=0; y < ent->attributes[j].num_values; y++) {
-                                               ent->attributes[j].values[y].length = res[i]->elements[j].values[y].length;
-                                               ent->attributes[j].values[y].data = talloc_steal(ent->attributes[j].values,
-                                                                               res[i]->elements[j].values[y].data);
-                                       }
-                               }
-                       }
-queue_reply2:
-                       ldapsrv_queue_reply(call, ent_r);
-               }
-       }
-
-       done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
-       NT_STATUS_HAVE_NO_MEMORY(done_r);
-
-       if (count > 0) {
-               DEBUG(10,("hacked_Search: results: [%d]\n",count));
-               result = LDAP_SUCCESS;
-               errstr = NULL;
-       } else if (count == 0) {
-               DEBUG(10,("hacked_Search: no results\n"));
-               result = LDAP_NO_SUCH_OBJECT;
-               errstr = ldb_errstring(samdb);  
-       } else if (count == -1) {
-               DEBUG(10,("hacked_Search: error\n"));
-               result = LDAP_OTHER;
-               errstr = ldb_errstring(samdb);
-       }
-
-       done = &done_r->msg->r.SearchResultDone;
-       done->dn = NULL;
-       done->resultcode = result;
-       done->errormessage = (errstr?talloc_strdup(done_r,errstr):NULL);;
-       done->referral = NULL;
-
-       talloc_free(local_ctx);
-
-       ldapsrv_queue_reply(call, done_r);
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS hldb_Search(struct ldapsrv_partition *partition, struct ldapsrv_call *call,
-                           struct ldap_SearchRequest *r)
-{
-       NTSTATUS status;
-       void *local_ctx;
-       struct ldb_context *samdb;
-#if 0
-       struct ldap_dn *basedn;
-       struct ldap_Result *done;
-       struct ldap_SearchResEntry *ent;
-       struct ldapsrv_reply *ent_r, *done_r;
-       int result = LDAP_SUCCESS;
-       struct ldb_message **res = NULL;
-       int i, j, y, count = 0;
-       enum ldb_scope scope = LDB_SCOPE_DEFAULT;
-       const char **attrs = NULL;
-       const char *errstr = NULL;
-#endif
-       local_ctx = talloc_named(call, 0, "hldb_Search local memory context");
-       NT_STATUS_HAVE_NO_MEMORY(local_ctx);
-
-       samdb = ldapsrv_sam_connect(call);
-       NT_STATUS_HAVE_NO_MEMORY(samdb);
-
-       status = hacked_Search(partition, call, r, samdb);
-       talloc_free(local_ctx);
-       NT_STATUS_IS_OK_RETURN(status);
-       status = hacked_wellknown_Search(partition, call, r);
-       NT_STATUS_IS_OK_RETURN(status);
-       return status;
-#if 0
-       basedn = ldap_parse_dn(local_ctx, r->basedn);
-       VALID_DN_SYNTAX(basedn,0);
-
-       DEBUG(10, ("hldb_Search: basedn: [%s]\n", basedn->dn));
-       DEBUG(10, ("hldb_Search: filter: [%s]\n", r->filter));
-
-       switch (r->scope) {
-               case LDAP_SEARCH_SCOPE_BASE:
-                       DEBUG(10,("hldb_Search: scope: [BASE]\n"));
-                       scope = LDB_SCOPE_BASE;
-                       break;
-               case LDAP_SEARCH_SCOPE_SINGLE:
-                       DEBUG(10,("hldb_Search: scope: [ONE]\n"));
-                       scope = LDB_SCOPE_ONELEVEL;
-                       break;
-               case LDAP_SEARCH_SCOPE_SUB:
-                       DEBUG(10,("hldb_Search: scope: [SUB]\n"));
-                       scope = LDB_SCOPE_SUBTREE;
-                       break;
-       }
-
-       if (r->num_attributes >= 1) {
-               attrs = talloc_array(samdb, const char *, r->num_attributes+1);
-               NT_STATUS_HAVE_NO_MEMORY(attrs);
-
-               for (i=0; i < r->num_attributes; i++) {
-                       DEBUG(10,("hldb_Search: attrs: [%s]\n",r->attributes[i]));
-                       attrs[i] = r->attributes[i];
-               }
-               attrs[i] = NULL;
-       }
-
-       count = ldb_search(samdb, basedn->dn, scope, r->filter, attrs, &res);
-       talloc_steal(samdb, res);
-
-       if (count < 1) {
-               status = hacked_Search(partition, call, r, samdb);
-               NT_STATUS_IS_OK_RETURN(status);
-               status = hacked_wellknown_Search(partition, call, r);
-               NT_STATUS_IS_OK_RETURN(status);
-       }
-
-       for (i=0; i < count; i++) {
-               ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
-               NT_STATUS_HAVE_NO_MEMORY(ent_r);
-
-               ent = &ent_r->msg.r.SearchResultEntry;
-               ent->dn = talloc_steal(ent_r, res[i]->dn);
-               ent->num_attributes = 0;
-               ent->attributes = NULL;
-               if (res[i]->num_elements == 0) {
-                       goto queue_reply;
-               }
-               ent->num_attributes = res[i]->num_elements;
-               ent->attributes = talloc_array(ent_r, struct ldb_message_element, ent->num_attributes);
-               NT_STATUS_HAVE_NO_MEMORY(ent->attributes);
-               for (j=0; j < ent->num_attributes; j++) {
-                       ent->attributes[j].name = talloc_steal(ent->attributes, res[i]->elements[j].name);
-                       ent->attributes[j].num_values = 0;
-                       ent->attributes[j].values = NULL;
-                       if (r->attributesonly && (res[i]->elements[j].num_values == 0)) {
-                               continue;
-                       }
-                       ent->attributes[j].num_values = res[i]->elements[j].num_values;
-                       ent->attributes[j].values = talloc_array(ent->attributes,
-                                                       DATA_BLOB, ent->attributes[j].num_values);
-                       NT_STATUS_HAVE_NO_MEMORY(ent->attributes[j].values);
-                       for (y=0; y < ent->attributes[j].num_values; y++) {
-                               ent->attributes[j].values[y].length = res[i]->elements[j].values[y].length;
-                               ent->attributes[j].values[y].data = talloc_steal(ent->attributes[j].values,
-                                                                       res[i]->elements[j].values[y].data);
-                       }
-               }
-queue_reply:
-               ldapsrv_queue_reply(call, ent_r);
-       }
-
-reply:
-       done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
-       NT_STATUS_HAVE_NO_MEMORY(done_r);
-
-       if (result == LDAP_SUCCESS) {
-               if (count > 0) {
-                       DEBUG(10,("hldb_Search: results: [%d]\n",count));
-                       result = LDAP_SUCCESS;
-                       errstr = NULL;
-               } else if (count == 0) {
-                       DEBUG(10,("hldb_Search: no results\n"));
-                       result = LDAP_NO_SUCH_OBJECT;
-                       errstr = ldb_errstring(samdb);
-               } else if (count == -1) {
-                       DEBUG(10,("hldb_Search: error\n"));
-                       result = LDAP_OTHER;
-                       errstr = ldb_errstring(samdb);
-               }
-       }
-
-       done = &done_r->msg.r.SearchResultDone;
-       done->dn = NULL;
-       done->resultcode = result;
-       done->errormessage = (errstr?talloc_strdup(done_r,errstr):NULL);
-       done->referral = NULL;
-
-       talloc_free(local_ctx);
-
-       ldapsrv_queue_reply(call, done_r);
-       return NT_STATUS_OK;
-#endif
-}
-
-static NTSTATUS hldb_Add(struct ldapsrv_partition *partition, struct ldapsrv_call *call,
-                                    struct ldap_AddRequest *r)
-{
-       void *local_ctx;
-       struct ldb_dn *dn;
-       struct ldap_Result *add_result;
-       struct ldapsrv_reply *add_reply;
-       int ldb_ret;
-       struct ldb_context *samdb;
-       struct ldb_message *msg = NULL;
-       int result = LDAP_SUCCESS;
-       const char *errstr = NULL;
-       int i,j;
-
-       local_ctx = talloc_named(call, 0, "hldb_Add local memory context");
-       NT_STATUS_HAVE_NO_MEMORY(local_ctx);
-
-       samdb = ldapsrv_sam_connect(call);
-       NT_STATUS_HAVE_NO_MEMORY(samdb);
-
-       msg = talloc(local_ctx, struct ldb_message);
-       NT_STATUS_HAVE_NO_MEMORY(msg);
-
-       msg->dn = ldb_dn_explode(local_ctx, r->dn);
-       VALID_DN_SYNTAX(dn, 1);
-
-       DEBUG(10, ("hldb_add: dn: [%s]\n", ldb_dn_linearize(local_ctx, dn)));
-
-       msg->private_data = NULL;
-       msg->num_elements = 0;
-       msg->elements = NULL;
-
-       if (r->num_attributes > 0) {
-               msg->num_elements = r->num_attributes;
-               msg->elements = talloc_array(msg, struct ldb_message_element, msg->num_elements);
-               NT_STATUS_HAVE_NO_MEMORY(msg->elements);
-
-               for (i=0; i < msg->num_elements; i++) {
-                       msg->elements[i].name = discard_const_p(char, r->attributes[i].name);
-                       msg->elements[i].flags = 0;
-                       msg->elements[i].num_values = 0;
-                       msg->elements[i].values = NULL;
-                       
-                       if (r->attributes[i].num_values > 0) {
-                               msg->elements[i].num_values = r->attributes[i].num_values;
-                               msg->elements[i].values = talloc_array(msg, struct ldb_val, msg->elements[i].num_values);
-                               NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values);
-
-                               for (j=0; j < msg->elements[i].num_values; j++) {
-                                       if (!(r->attributes[i].values[j].length > 0)) {
-                                               result = LDAP_OTHER;
-                                               errstr = "Empty attribute values are not allowed";
-                                               goto reply;
-                                       }
-                                       msg->elements[i].values[j].length = r->attributes[i].values[j].length;
-                                       msg->elements[i].values[j].data = r->attributes[i].values[j].data;                      
-                               }
-                       } else {
-                               result = LDAP_OTHER;
-                               errstr = "No attribute values are not allowed";
-                               goto reply;
-                       }
-               }
-       } else {
-               result = LDAP_OTHER;
-               errstr = "No attributes are not allowed";
-               goto reply;
-       }
-
-reply:
-       add_reply = ldapsrv_init_reply(call, LDAP_TAG_AddResponse);
-       NT_STATUS_HAVE_NO_MEMORY(add_reply);
-
-       if (result == LDAP_SUCCESS) {
-               ldb_ret = ldb_add(samdb, msg);
-               if (ldb_ret == 0) {
-                       DEBUG(0,("hldb_Add: added: '%s'\n", ldb_dn_linearize(msg, msg->dn)));
-                       result = LDAP_SUCCESS;
-                       errstr = NULL;
-               } else {
-                       /* currently we have no way to tell if there was an internal ldb error
-                        * or if the object was not found, return the most probable error
-                        */
-                       result = LDAP_OPERATIONS_ERROR;
-                       errstr = ldb_errstring(samdb);
-               }
-       }
-
-       add_result = &add_reply->msg->r.AddResponse;
-       add_result->dn = NULL;
-       add_result->resultcode = result;
-       add_result->errormessage = (errstr?talloc_strdup(add_reply,errstr):NULL);
-       add_result->referral = NULL;
-
-       talloc_free(local_ctx);
-
-       ldapsrv_queue_reply(call, add_reply);
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS hldb_Del(struct ldapsrv_partition *partition, struct ldapsrv_call *call,
-                                    struct ldap_DelRequest *r)
-{
-       void *local_ctx;
-       struct ldb_dn *dn;
-       struct ldap_Result *del_result;
-       struct ldapsrv_reply *del_reply;
-       int ldb_ret;
-       struct ldb_context *samdb;
-       const char *errstr = NULL;
-       int result = LDAP_SUCCESS;
-
-       local_ctx = talloc_named(call, 0, "hldb_Del local memory context");
-       NT_STATUS_HAVE_NO_MEMORY(local_ctx);
-
-       samdb = ldapsrv_sam_connect(call);
-       NT_STATUS_HAVE_NO_MEMORY(samdb);
-
-       dn = ldb_dn_explode(local_ctx, r->dn);
-       VALID_DN_SYNTAX(dn,1);
-
-       DEBUG(10, ("hldb_Del: dn: [%s]\n", ldb_dn_linearize(local_ctx, dn)));
-
-reply:
-       del_reply = ldapsrv_init_reply(call, LDAP_TAG_DelResponse);
-       NT_STATUS_HAVE_NO_MEMORY(del_reply);
-
-       if (result == LDAP_SUCCESS) {
-               ldb_ret = ldb_delete(samdb, dn);
-               if (ldb_ret == 0) {
-                       result = LDAP_SUCCESS;
-                       errstr = NULL;
-               } else {
-                       /* currently we have no way to tell if there was an internal ldb error
-                        * or if the object was not found, return the most probable error
-                        */
-                       result = LDAP_NO_SUCH_OBJECT;
-                       errstr = ldb_errstring(samdb);
-               }
-       }
-
-       del_result = &del_reply->msg->r.DelResponse;
-       del_result->dn = NULL;
-       del_result->resultcode = result;
-       del_result->errormessage = (errstr?talloc_strdup(del_reply,errstr):NULL);
-       del_result->referral = NULL;
-
-       talloc_free(local_ctx);
-
-       ldapsrv_queue_reply(call, del_reply);
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS hldb_Modify(struct ldapsrv_partition *partition, struct ldapsrv_call *call,
-                                    struct ldap_ModifyRequest *r)
-{
-       void *local_ctx;
-       struct ldb_dn *dn;
-       struct ldap_Result *modify_result;
-       struct ldapsrv_reply *modify_reply;
-       int ldb_ret;
-       struct ldb_context *samdb;
-       struct ldb_message *msg = NULL;
-       int result = LDAP_SUCCESS;
-       const char *errstr = NULL;
-       int i,j;
-
-       local_ctx = talloc_named(call, 0, "hldb_Modify local memory context");
-       NT_STATUS_HAVE_NO_MEMORY(local_ctx);
-
-       samdb = ldapsrv_sam_connect(call);
-       NT_STATUS_HAVE_NO_MEMORY(samdb);
-
-       msg = talloc(local_ctx, struct ldb_message);
-       NT_STATUS_HAVE_NO_MEMORY(msg);
-
-       msg->dn = ldb_dn_explode(local_ctx, r->dn);
-       VALID_DN_SYNTAX(dn,1);
-
-       DEBUG(10, ("hldb_modify: dn: [%s]\n", ldb_dn_linearize(local_ctx, dn)));
-
-       msg->private_data = NULL;
-       msg->num_elements = 0;
-       msg->elements = NULL;
-
-       if (r->num_mods > 0) {
-               msg->num_elements = r->num_mods;
-               msg->elements = talloc_array(msg, struct ldb_message_element, r->num_mods);
-               NT_STATUS_HAVE_NO_MEMORY(msg->elements);
-
-               for (i=0; i < msg->num_elements; i++) {
-                       msg->elements[i].name = discard_const_p(char, r->mods[i].attrib.name);
-                       msg->elements[i].num_values = 0;
-                       msg->elements[i].values = NULL;
-
-                       switch (r->mods[i].type) {
-                       default:
-                               result = LDAP_PROTOCOL_ERROR;
-                               errstr = "Invalid LDAP_MODIFY_* type";
-                               goto reply;
-                       case LDAP_MODIFY_ADD:
-                               msg->elements[i].flags = LDB_FLAG_MOD_ADD;
-                               break;
-                       case LDAP_MODIFY_DELETE:
-                               msg->elements[i].flags = LDB_FLAG_MOD_DELETE;
-                               break;
-                       case LDAP_MODIFY_REPLACE:
-                               msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
-                               break;
-                       }
-
-                       msg->elements[i].num_values = r->mods[i].attrib.num_values;
-                       if (msg->elements[i].num_values > 0) {
-                               msg->elements[i].values = talloc_array(msg, struct ldb_val, msg->elements[i].num_values);
-                               NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values);
-
-                               for (j=0; j < msg->elements[i].num_values; j++) {
-                                       if (!(r->mods[i].attrib.values[j].length > 0)) {
-                                               result = LDAP_OTHER;
-                                               errstr = "Empty attribute values are not allowed";
-                                               goto reply;
-                                       }
-                                       msg->elements[i].values[j].length = r->mods[i].attrib.values[j].length;
-                                       msg->elements[i].values[j].data = r->mods[i].attrib.values[j].data;                     
-                               }
-                       }
-               }
-       } else {
-               result = LDAP_OTHER;
-               errstr = "No mods are not allowed";
-               goto reply;
-       }
-
-reply:
-       modify_reply = ldapsrv_init_reply(call, LDAP_TAG_ModifyResponse);
-       NT_STATUS_HAVE_NO_MEMORY(modify_reply);
-
-       if (result == LDAP_SUCCESS) {
-               ldb_ret = ldb_modify(samdb, msg);
-               if (ldb_ret == 0) {
-                       result = LDAP_SUCCESS;
-                       errstr = NULL;
-               } else {
-                       /* currently we have no way to tell if there was an internal ldb error
-                        * or if the object was not found, return the most probable error
-                        */
-                               result = LDAP_ATTRIBUTE_OR_VALUE_EXISTS;
-                       result = LDAP_OPERATIONS_ERROR;
-                       errstr = ldb_errstring(samdb);
-                       if (strcmp("Type or value exists", errstr) ==0){
-                               result = LDAP_ATTRIBUTE_OR_VALUE_EXISTS;
-                       }
-                       DEBUG(0,("failed to modify: %s - %u - %s\n", ldb_dn_linearize(local_ctx, msg->dn), result, errstr));
-               }
-       }
-
-       modify_result = &modify_reply->msg->r.AddResponse;
-       modify_result->dn = NULL;
-       modify_result->resultcode = result;
-       modify_result->errormessage = (errstr?talloc_strdup(modify_reply,errstr):NULL);
-       modify_result->referral = NULL;
-
-       talloc_free(local_ctx);
-
-       ldapsrv_queue_reply(call, modify_reply);
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS hldb_Compare(struct ldapsrv_partition *partition, struct ldapsrv_call *call,
-                                    struct ldap_CompareRequest *r)
-{
-       void *local_ctx;
-       struct ldb_dn *dn;
-       struct ldap_Result *compare;
-       struct ldapsrv_reply *compare_r;
-       int result = LDAP_SUCCESS;
-       struct ldb_context *samdb;
-       struct ldb_message **res = NULL;
-       const char *attrs[1];
-       const char *errstr = NULL;
-       const char *filter = NULL;
-       int count;
-
-       local_ctx = talloc_named(call, 0, "hldb_Compare local_memory_context");
-       NT_STATUS_HAVE_NO_MEMORY(local_ctx);
-
-       samdb = ldapsrv_sam_connect(call);
-       NT_STATUS_HAVE_NO_MEMORY(samdb);
-
-       dn = ldb_dn_explode(local_ctx, r->dn);
-       VALID_DN_SYNTAX(dn,1);
-
-       DEBUG(10, ("hldb_Compare: dn: [%s]\n", ldb_dn_linearize(local_ctx, dn)));
-       filter = talloc_asprintf(local_ctx, "(%s=%*s)", r->attribute, 
-                                (int)r->value.length, r->value.data);
-       NT_STATUS_HAVE_NO_MEMORY(filter);
-
-       DEBUGADD(10, ("hldb_Compare: attribute: [%s]\n", filter));
-
-       attrs[0] = NULL;
-
-reply:
-       compare_r = ldapsrv_init_reply(call, LDAP_TAG_CompareResponse);
-       NT_STATUS_HAVE_NO_MEMORY(compare_r);
-
-       if (result == LDAP_SUCCESS) {
-               count = ldb_search(samdb, dn, LDB_SCOPE_BASE, filter, attrs, &res);
-               talloc_steal(samdb, res);
-               if (count == 1) {
-                       DEBUG(10,("hldb_Compare: matched\n"));
-                       result = LDAP_COMPARE_TRUE;
-                       errstr = NULL;
-               } else if (count == 0) {
-                       DEBUG(10,("hldb_Compare: doesn't matched\n"));
-                       result = LDAP_COMPARE_FALSE;
-                       errstr = NULL;
-               } else if (count > 1) {
-                       result = LDAP_OTHER;
-                       errstr = "too many objects match";
-                       DEBUG(10,("hldb_Compare: %d results: %s\n", count, errstr));
-               } else if (count == -1) {
-                       result = LDAP_OTHER;
-                       errstr = ldb_errstring(samdb);
-                       DEBUG(10,("hldb_Compare: error: %s\n", errstr));
-               }
-       }
-
-       compare = &compare_r->msg->r.CompareResponse;
-       compare->dn = NULL;
-       compare->resultcode = result;
-       compare->errormessage = (errstr?talloc_strdup(compare_r,errstr):NULL);
-       compare->referral = NULL;
-
-       talloc_free(local_ctx);
-
-       ldapsrv_queue_reply(call, compare_r);
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS hldb_ModifyDN(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_ModifyDNRequest *r)
-{
-       void *local_ctx;
-       struct ldb_dn *olddn, *newrdn, *newsuperior;
-       struct ldap_Result *modifydn;
-       struct ldapsrv_reply *modifydn_r;
-       int ldb_ret;
-       struct ldb_context *samdb;
-       const char *errstr = NULL;
-       int result = LDAP_SUCCESS;
-       const struct ldb_dn *newdn = NULL;
-       struct ldb_dn *parentdn = NULL;
-
-       local_ctx = talloc_named(call, 0, "hldb_ModifyDN local memory context");
-       NT_STATUS_HAVE_NO_MEMORY(local_ctx);
-
-       samdb = ldapsrv_sam_connect(call);
-       NT_STATUS_HAVE_NO_MEMORY(samdb);
-
-       olddn = ldb_dn_explode(local_ctx, r->dn);
-       VALID_DN_SYNTAX(olddn,2);
-
-       newrdn = ldb_dn_explode(local_ctx, r->newrdn);
-       VALID_DN_SYNTAX(newrdn,1);
-
-       DEBUG(10, ("hldb_ModifyDN: olddn: [%s]\n", ldb_dn_linearize(local_ctx, olddn)));
-       DEBUG(10, ("hldb_ModifyDN: newrdn: [%s]\n", ldb_dn_linearize(local_ctx, newrdn)));
-
-       /* we can't handle the rename if we should not remove the old dn */
-       if (!r->deleteolddn) {
-               result = LDAP_UNWILLING_TO_PERFORM;
-               errstr = "Old RDN must be deleted";
-               goto reply;
-       }
-
-       if (newrdn->comp_num > 1) {
-               result = LDAP_NAMING_VIOLATION;
-               errstr = "Error new RDN invalid";
-               goto reply;
-       }
-
-       if (r->newsuperior) {
-               newsuperior = ldb_dn_explode(local_ctx, r->newsuperior);
-               VALID_DN_SYNTAX(newsuperior,0);
-               DEBUG(10, ("hldb_ModifyDN: newsuperior: [%s]\n", ldb_dn_linearize(local_ctx, newsuperior)));
-               
-               if (newsuperior->comp_num < 1) {
-                       result = LDAP_AFFECTS_MULTIPLE_DSAS;
-                       errstr = "Error new Superior DN invalid";
-                       goto reply;
-               }
-               parentdn = newsuperior;
-       }
-
-       if (!parentdn) {
-               parentdn = ldb_dn_get_parent(local_ctx, olddn);
-       }
-       newdn = ldb_dn_make_child(local_ctx, ldb_dn_get_rdn(local_ctx, newrdn), parentdn);
-       NT_STATUS_HAVE_NO_MEMORY(newdn);
-
-reply:
-       modifydn_r = ldapsrv_init_reply(call, LDAP_TAG_ModifyDNResponse);
-       NT_STATUS_HAVE_NO_MEMORY(modifydn_r);
-
-       if (result == LDAP_SUCCESS) {
-               ldb_ret = ldb_rename(samdb, olddn, newdn);
-               if (ldb_ret == 0) {
-                       result = LDAP_SUCCESS;
-                       errstr = NULL;
-               } else {
-                       /* currently we have no way to tell if there was an internal ldb error
-                        * or if the object was not found, return the most probable error
-                        */
-                       result = LDAP_NO_SUCH_OBJECT;
-                       errstr = ldb_errstring(samdb);
-               }
-       }
-
-       modifydn = &modifydn_r->msg->r.ModifyDNResponse;
-       modifydn->dn = NULL;
-       modifydn->resultcode = result;
-       modifydn->errormessage = (errstr?talloc_strdup(modifydn_r,errstr):NULL);
-       modifydn->referral = NULL;
-
-       talloc_free(local_ctx);
-
-       ldapsrv_queue_reply(call, modifydn_r);
-       return NT_STATUS_OK;
-}
-
-static const struct ldapsrv_partition_ops hldb_ops = {
-       .Search         = hldb_Search,
-       .Add            = hldb_Add,
-       .Del            = hldb_Del,
-       .Modify         = hldb_Modify,
-       .Compare        = hldb_Compare,
-       .ModifyDN       = hldb_ModifyDN
-};
-
-const struct ldapsrv_partition_ops *ldapsrv_get_hldb_partition_ops(void)
-{
-       return &hldb_ops;
-}
index 2392f23799d5b5c8887d4141d8c4b5f0e5624317..75429b1843eb1baf1649307912fcbded0615e9bb 100644 (file)
@@ -52,25 +52,28 @@ static void rootdse_db_debug(void *context, enum ldb_debug_level level, const ch
 /*
   connect to the SAM database
  */
-static struct ldb_context *rootdse_db_connect(TALLOC_CTX *mem_ctx)
+NTSTATUS rootdse_Init(struct ldapsrv_partition *partition, struct ldapsrv_connection *conn)
 {
        char *db_path;
        struct ldb_context *ldb;
+       TALLOC_CTX *mem_ctx = talloc_new(partition);
 
        db_path = talloc_asprintf(mem_ctx, "tdb://%s", 
                                  private_path(mem_ctx, "rootdse.ldb"));
        if (db_path == NULL) {
-               return NULL;
+               return NT_STATUS_NO_MEMORY;
        }
 
        ldb = ldb_wrap_connect(mem_ctx, db_path, 0, NULL);
        if (ldb == NULL) {
-               return NULL;
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
 
        ldb_set_debug(ldb, rootdse_db_debug, NULL);
 
-       return ldb;
+       talloc_steal(partition, ldb);
+       partition->private = ldb;
+       return NT_STATUS_OK;
 }
 
 
@@ -258,7 +261,7 @@ static NTSTATUS fill_dynamic_values(void *mem_ctx, struct ldb_message_element *a
 }
 
 static NTSTATUS rootdse_Search(struct ldapsrv_partition *partition, struct ldapsrv_call *call,
-                                    struct ldap_SearchRequest *r)
+                              struct ldap_SearchRequest *r)
 {
        NTSTATUS status;
        void *local_ctx;
@@ -279,8 +282,7 @@ static NTSTATUS rootdse_Search(struct ldapsrv_partition *partition, struct ldaps
        local_ctx = talloc_named(call, 0, "rootdse_Search local memory context");
        NT_STATUS_HAVE_NO_MEMORY(local_ctx);
 
-       ldb = rootdse_db_connect(local_ctx);
-       NT_STATUS_HAVE_NO_MEMORY(ldb);
+       ldb = partition->private;
 
        if (r->num_attributes >= 1) {
                attrs = talloc_array(ldb, const char *, r->num_attributes+1);
@@ -359,6 +361,7 @@ queue_reply:
 }
 
 static const struct ldapsrv_partition_ops rootdse_ops = {
+       .Init           = rootdse_Init,
        .Search         = rootdse_Search
 };
 
index 83ce0597560fd0d2d9ec23a1ed0c1c928291089b..dac7feecfb1416a9c0e4c28668f4e9c3a5067a33 100644 (file)
@@ -356,6 +356,8 @@ static void ldapsrv_send(struct stream_connection *c, uint16_t flags)
 */
 static void ldapsrv_accept(struct stream_connection *c)
 {
+       struct ldapsrv_partition *rootDSE_part;
+       struct ldapsrv_partition *part;
        struct ldapsrv_service *ldapsrv_service = 
                talloc_get_type(c->private, struct ldapsrv_service);
        struct ldapsrv_connection *conn;
@@ -386,6 +388,42 @@ static void ldapsrv_accept(struct stream_connection *c)
                return;
        }
 
+       /* Connections start out anonymous */
+       if (!NT_STATUS_IS_OK(auth_anonymous_session_info(conn, &conn->session_info))) {
+               ldapsrv_terminate_connection(conn, "failed to setup anonymous session info");
+               return;
+       }
+
+       rootDSE_part = talloc(conn, struct ldapsrv_partition);
+       if (rootDSE_part == NULL) {
+               ldapsrv_terminate_connection(conn, "talloc failed");
+               return;
+       }
+
+       rootDSE_part->base_dn = ""; /* RootDSE */
+       rootDSE_part->ops = ldapsrv_get_rootdse_partition_ops();
+       if (!NT_STATUS_IS_OK(rootDSE_part->ops->Init(rootDSE_part, conn))) {
+               ldapsrv_terminate_connection(conn, "rootDSE Init failed");
+       }
+
+       conn->rootDSE = rootDSE_part;
+       DLIST_ADD_END(conn->partitions, rootDSE_part, struct ldapsrv_partition *);
+
+       part = talloc(conn, struct ldapsrv_partition);
+       if (part == NULL) {
+               ldapsrv_terminate_connection(conn, "talloc failed");
+               return;
+       }
+
+       part->base_dn = "*"; /* default partition */
+       part->ops = ldapsrv_get_sldb_partition_ops();
+       if (!NT_STATUS_IS_OK(part->ops->Init(part, conn))) {
+               ldapsrv_terminate_connection(conn, "default partition Init failed");
+       }
+
+       conn->default_partition = part;
+       DLIST_ADD_END(conn->partitions, part, struct ldapsrv_partition *);
+
        irpc_add_name(c->msg_ctx, "ldap_server");
 }
 
@@ -433,8 +471,6 @@ static NTSTATUS add_socket(struct event_context *event_context,
 static void ldapsrv_task_init(struct task_server *task)
 {      
        struct ldapsrv_service *ldap_service;
-       struct ldapsrv_partition *rootDSE_part;
-       struct ldapsrv_partition *part;
        NTSTATUS status;
 
        ldap_service = talloc_zero(task, struct ldapsrv_service);
@@ -443,28 +479,6 @@ static void ldapsrv_task_init(struct task_server *task)
        ldap_service->tls_params = tls_initialise(ldap_service);
        if (ldap_service->tls_params == NULL) goto failed;
 
-       rootDSE_part = talloc(ldap_service, struct ldapsrv_partition);
-       if (rootDSE_part == NULL) goto failed;
-
-       rootDSE_part->base_dn = ""; /* RootDSE */
-       rootDSE_part->ops = ldapsrv_get_rootdse_partition_ops();
-
-       ldap_service->rootDSE = rootDSE_part;
-       DLIST_ADD_END(ldap_service->partitions, rootDSE_part, struct ldapsrv_partition *);
-
-       part = talloc(ldap_service, struct ldapsrv_partition);
-       if (part == NULL) goto failed;
-
-       part->base_dn = "*"; /* default partition */
-       if (lp_parm_bool(-1, "ldapsrv", "hacked", False)) {
-               part->ops = ldapsrv_get_hldb_partition_ops();
-       } else {
-               part->ops = ldapsrv_get_sldb_partition_ops();
-       }
-
-       ldap_service->default_partition = part;
-       DLIST_ADD_END(ldap_service->partitions, part, struct ldapsrv_partition *);
-
        if (lp_interfaces() && lp_bind_interfaces_only()) {
                int num_interfaces = iface_count();
                int i;
index 2aa6530f9fa7da60310e22bea120adc1def4f1df..8eb02a97dbf5c7cfe268452be1603e810763f8db 100644 (file)
@@ -27,6 +27,9 @@ struct ldapsrv_connection {
        struct auth_session_info *session_info;
        struct ldapsrv_service *service;
        struct tls_context *tls;
+       struct ldapsrv_partition *rootDSE;
+       struct ldapsrv_partition *default_partition;
+       struct ldapsrv_partition *partitions;
 
        /* partially received request */
        DATA_BLOB partial;
@@ -58,6 +61,7 @@ struct ldapsrv_partition;
 struct ldapsrv_partition_ops {
        const char *name;
        NTSTATUS (*Init)(struct ldapsrv_partition *partition, struct ldapsrv_connection *conn);
+       NTSTATUS (*Bind)(struct ldapsrv_partition *partition, struct ldapsrv_connection *conn);
        NTSTATUS (*Search)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_SearchRequest *r);
        NTSTATUS (*Modify)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_ModifyRequest *r);
        NTSTATUS (*Add)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_AddRequest *r);
@@ -71,15 +75,12 @@ struct ldapsrv_partition_ops {
 struct ldapsrv_partition {
        struct ldapsrv_partition *prev,*next;
 
-       void *private_data;
+       void *private;
        const struct ldapsrv_partition_ops *ops;
 
        const char *base_dn;
 };
 
 struct ldapsrv_service {
-       struct ldapsrv_partition *rootDSE;
-       struct ldapsrv_partition *default_partition;
-       struct ldapsrv_partition *partitions;
        struct tls_params *tls_params;
 };
index fbeec2f3ca88e6ec17be0250707b80e3f5755d29..8a68004599a8e55b2676e44dd2d48e056ff4712d 100644 (file)
@@ -22,6 +22,7 @@
 #include "includes.h"
 #include "ldap_server/ldap_server.h"
 #include "lib/ldb/include/ldb.h"
+#include "auth/auth.h"
 #include "db_wrap.h"
 
 #define VALID_DN_SYNTAX(dn,i) do {\
        }\
 } while(0)
 
+/*
+  connect to the sam database
+*/
+NTSTATUS sldb_Init(struct ldapsrv_partition *partition, struct ldapsrv_connection *conn) 
+{
+       TALLOC_CTX *mem_ctx = talloc_new(partition);
+       struct ldb_context *ldb;
+       const char *url;
+       url = lp_parm_string(-1, "ldapsrv", "samdb");
+       if (url) {
+
+               ldb = ldb_wrap_connect(mem_ctx, url, 0, NULL);
+               if (ldb == NULL) {
+                       talloc_free(mem_ctx);
+                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               }
+               if (ldb_set_opaque(ldb, "sessionInfo", conn->session_info)) {
+                       talloc_free(mem_ctx);
+                       return NT_STATUS_NO_MEMORY;
+               }
+               talloc_steal(partition, ldb);
+               partition->private = ldb;
+               talloc_free(mem_ctx);
+               return NT_STATUS_OK;
+       }
+       
+       ldb = samdb_connect(mem_ctx, conn->session_info);
+       if (ldb == NULL) {
+               talloc_free(mem_ctx);
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+       talloc_steal(partition, ldb);
+       partition->private = ldb;
+       talloc_free(mem_ctx);
+       return NT_STATUS_OK;
+}
+
+/*
+  Re-connect to the ldb after a bind (this does not handle the bind
+  itself, but just notes the change in credentials)
+*/
+NTSTATUS sldb_Bind(struct ldapsrv_partition *partition, struct ldapsrv_connection *conn) 
+{
+       struct ldb_context *samdb = partition->private;
+       NTSTATUS status;
+       status = sldb_Init(partition, conn);
+       if (NT_STATUS_IS_OK(status)) {
+               /* don't leak the old LDB */
+               talloc_free(samdb);
+       }
+       return status;
+}
+
 static NTSTATUS sldb_Search(struct ldapsrv_partition *partition, struct ldapsrv_call *call,
-                                    struct ldap_SearchRequest *r)
+                           struct ldap_SearchRequest *r)
 {
        void *local_ctx;
        struct ldb_dn *basedn;
@@ -54,8 +108,7 @@ static NTSTATUS sldb_Search(struct ldapsrv_partition *partition, struct ldapsrv_
        local_ctx = talloc_named(call, 0, "sldb_Search local memory context");
        NT_STATUS_HAVE_NO_MEMORY(local_ctx);
 
-       samdb = ldapsrv_sam_connect(call);
-       NT_STATUS_HAVE_NO_MEMORY(samdb);
+       samdb = partition->private;
 
        basedn = ldb_dn_explode(local_ctx, r->basedn);
        VALID_DN_SYNTAX(basedn, 0);
@@ -182,8 +235,7 @@ static NTSTATUS sldb_Add(struct ldapsrv_partition *partition, struct ldapsrv_cal
        local_ctx = talloc_named(call, 0, "sldb_Add local memory context");
        NT_STATUS_HAVE_NO_MEMORY(local_ctx);
 
-       samdb = ldapsrv_sam_connect(call);
-       NT_STATUS_HAVE_NO_MEMORY(samdb);
+       samdb = partition->private;
 
        dn = ldb_dn_explode(local_ctx, r->dn);
        VALID_DN_SYNTAX(dn,1);
@@ -280,8 +332,7 @@ static NTSTATUS sldb_Del(struct ldapsrv_partition *partition, struct ldapsrv_cal
        local_ctx = talloc_named(call, 0, "sldb_Del local memory context");
        NT_STATUS_HAVE_NO_MEMORY(local_ctx);
 
-       samdb = ldapsrv_sam_connect(call);
-       NT_STATUS_HAVE_NO_MEMORY(samdb);
+       samdb = partition->private;
 
        dn = ldb_dn_explode(local_ctx, r->dn);
        VALID_DN_SYNTAX(dn,1);
@@ -335,8 +386,7 @@ static NTSTATUS sldb_Modify(struct ldapsrv_partition *partition, struct ldapsrv_
        local_ctx = talloc_named(call, 0, "sldb_Modify local memory context");
        NT_STATUS_HAVE_NO_MEMORY(local_ctx);
 
-       samdb = ldapsrv_sam_connect(call);
-       NT_STATUS_HAVE_NO_MEMORY(samdb);
+       samdb = partition->private;
 
        dn = ldb_dn_explode(local_ctx, r->dn);
        VALID_DN_SYNTAX(dn, 1);
@@ -447,8 +497,7 @@ static NTSTATUS sldb_Compare(struct ldapsrv_partition *partition, struct ldapsrv
        local_ctx = talloc_named(call, 0, "sldb_Compare local_memory_context");
        NT_STATUS_HAVE_NO_MEMORY(local_ctx);
 
-       samdb = ldapsrv_sam_connect(call);
-       NT_STATUS_HAVE_NO_MEMORY(samdb);
+       samdb = partition->private;
 
        dn = ldb_dn_explode(local_ctx, r->dn);
        VALID_DN_SYNTAX(dn, 1);
@@ -515,8 +564,7 @@ static NTSTATUS sldb_ModifyDN(struct ldapsrv_partition *partition, struct ldapsr
        local_ctx = talloc_named(call, 0, "sldb_ModifyDN local memory context");
        NT_STATUS_HAVE_NO_MEMORY(local_ctx);
 
-       samdb = ldapsrv_sam_connect(call);
-       NT_STATUS_HAVE_NO_MEMORY(samdb);
+       samdb = partition->private;
 
        olddn = ldb_dn_explode(local_ctx, r->dn);
        VALID_DN_SYNTAX(olddn, 2);
@@ -591,6 +639,8 @@ reply:
 }
 
 static const struct ldapsrv_partition_ops sldb_ops = {
+       .Init           = sldb_Init,
+       .Bind           = sldb_Bind,
        .Search         = sldb_Search,
        .Add            = sldb_Add,
        .Del            = sldb_Del,
index 7cdecc334f8948e551255d90231dcf7aa1898d0b..642ad127d8040d59570ff6a5264aa8a188af3d64 100644 (file)
@@ -75,6 +75,11 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const
        if (r != 0) {
                goto failed;
        }
+
+       if (ldb_set_opaque(ldb, "securityToken", system_session(ldb))) {
+               goto failed;
+       }
+
 #endif
 
        ret = talloc_zero(ldb, struct ldb_cmdline);
index a23aa92bf35614da1fc0ee167934060b25deece0..8e52759e70c1725346c7261b3a33b634646674e2 100644 (file)
@@ -165,3 +165,28 @@ void security_token_debug(int dbg_lev, const struct security_token *token)
 
        talloc_free(mem_ctx);
 }
+
+/* These really should be cheaper... */
+
+BOOL is_system_token(struct security_token *token) 
+{
+       TALLOC_CTX *mem_ctx = talloc_new(token);
+       if (dom_sid_equal(token->user_sid, dom_sid_parse_talloc(mem_ctx, SID_NT_SYSTEM))) {
+               talloc_free(mem_ctx);
+               return True;
+       }
+       talloc_free(mem_ctx);
+       return False;
+}
+
+BOOL is_anonymous_token(struct security_token *token) 
+{
+       TALLOC_CTX *mem_ctx = talloc_new(token);
+       if (dom_sid_equal(token->user_sid, dom_sid_parse_talloc(mem_ctx, SID_NT_ANONYMOUS))) {
+               talloc_free(mem_ctx);
+               return True;
+       }
+       talloc_free(mem_ctx);
+       return False;
+}
+
index a580cc6b138575f95c349300d14b04d3557989e3..c71fe0c53e33ece564dc738bae9cbca395932799 100644 (file)
@@ -701,6 +701,8 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
        domain_sid = lsa_query_info.out.info->domain.sid;
        domain_name = lsa_query_info.out.info->domain.name.string;
 
+       DEBUG(0, ("Joining domain %s\n", domain_name));
+
        /*
          establish a SAMR connection, on the same CIFS transport
        */
index 837170afac660972433a4cdf09145dfe0306cc0c..ca9dc6b0894d4b2ba57d6baa2fabef4734633566 100644 (file)
@@ -1069,9 +1069,7 @@ static NTSTATUS libnet_samsync_ldb_netlogon(struct libnet_context *ctx, TALLOC_C
        state->secrets = NULL;
        state->trusted_domains = NULL;
 
-       state->sam_ldb = samdb_connect(state);
-
-       
+       state->sam_ldb = samdb_connect(state, system_session(state));
 
        r2.error_string = NULL;
        r2.delta_fn = libnet_samsync_ldb_fn;
index ab2f1cc5790ae4f122ff18195822dd39998a0241..b007ca811433657bc9ba46306aa4d3714c6c2620 100644 (file)
@@ -48,7 +48,7 @@ static void nbtd_netlogon_getdc(struct dgram_mailslot_handler *dgmslot,
                return;
        }
 
-       samctx = samdb_connect(packet);
+       samctx = samdb_connect(packet, anonymous_session(packet));
        if (samctx == NULL) {
                DEBUG(2,("Unable to open sam in getdc reply\n"));
                return;
@@ -108,7 +108,7 @@ static void nbtd_netlogon_getdc2(struct dgram_mailslot_handler *dgmslot,
                return;
        }
 
-       samctx = samdb_connect(packet);
+       samctx = samdb_connect(packet, anonymous_session(packet));
        if (samctx == NULL) {
                DEBUG(2,("Unable to open sam in getdc reply\n"));
                return;
index 95d2b756d90e10546a6c14a3b951d0846508f210..f3ee938d847a6c13d6b1418bf2b8916239d48c65 100644 (file)
@@ -52,7 +52,7 @@ struct sidmap_context *sidmap_open(TALLOC_CTX *mem_ctx)
        if (sidmap == NULL) {
                return NULL;
        }
-       sidmap->samctx = samdb_connect(sidmap);
+       sidmap->samctx = samdb_connect(sidmap, system_session(sidmap));
        if (sidmap->samctx == NULL) {
                talloc_free(sidmap);
                return NULL;
index 94a16d0a09b152e14e615b7eb0dddc6e5514f378..c8578a7cc119a40ffc7c25ce95719cef72fbfb08 100644 (file)
@@ -25,6 +25,7 @@
 #include "rpc_server/dcerpc_server.h"
 #include "rpc_server/common/common.h"
 #include "rpc_server/drsuapi/dcesrv_drsuapi.h"
+#include "auth/auth.h"
 
 /* 
   drsuapi_DsBind 
@@ -43,7 +44,7 @@ static WERROR drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem
        b_state = talloc(dce_call->conn, struct drsuapi_bind_state);
        WERR_TALLOC_CHECK(b_state);
 
-       b_state->sam_ctx = samdb_connect(b_state);
+       b_state->sam_ctx = samdb_connect(b_state, dce_call->conn->auth_state.session_info); 
        if (!b_state->sam_ctx) {
                talloc_free(b_state);
                return WERR_FOOBAR;
index 866faf49b94688518450ddb02427f142ec82df34..fae84484ee00af7c9d9bc93c347a5d94463a7585 100644 (file)
@@ -41,6 +41,11 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX
                                 uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
                                 const char *name, struct drsuapi_DsNameInfo1 *info1);
 
+static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx,
+                                       uint32_t format_offered, uint32_t format_desired,
+                                       const struct ldb_dn *name_dn, const char *name, 
+                                       struct drsuapi_DsNameInfo1 *info1);
+
 static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, struct ldb_context *ldb_ctx, 
                                   TALLOC_CTX *mem_ctx,
                                   const char *alias_from,
@@ -349,6 +354,14 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX
                WERR_TALLOC_CHECK(result_filter);
                break;
        }
+       case DRSUAPI_DS_NAME_FORMAT_DISPLAY: {
+               domain_filter = NULL;
+
+               result_filter = talloc_asprintf(mem_ctx, "(|(displayName=%s)(samAccountName=%s))",
+                                               name, name);
+               WERR_TALLOC_CHECK(result_filter);
+               break;
+       }
        
        case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY: {
                struct dom_sid *sid = dom_sid_parse_talloc(mem_ctx, name);
@@ -424,6 +437,11 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX
        }
 
        }
+
+       if (format_flags & DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY) {
+               return DsCrackNameOneSyntactical(mem_ctx, format_offered, format_desired,
+                                                name_dn, name, info1);
+       }
        
        return DsCrackNameOneFilter(b_state, mem_ctx, 
                                    smb_krb5_context, 
@@ -433,6 +451,32 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX
                                    info1);
 }
 
+static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx,
+                                       uint32_t format_offered, uint32_t format_desired,
+                                       const struct ldb_dn *name_dn, const char *name, 
+                                       struct drsuapi_DsNameInfo1 *info1)
+{
+       if (format_offered != DRSUAPI_DS_NAME_FORMAT_FQDN_1779) {
+               info1->status = DRSUAPI_DS_NAME_STATUS_NO_SYNTACTICAL_MAPPING;
+               return WERR_OK;
+       }
+
+       switch (format_desired) {
+       case DRSUAPI_DS_NAME_FORMAT_CANONICAL: 
+               break;
+       case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
+               break;
+       default:
+               info1->status = DRSUAPI_DS_NAME_STATUS_NO_SYNTACTICAL_MAPPING;
+               return WERR_OK;
+       }
+
+       
+       
+       return WERR_OK; 
+       
+}
+
 static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
                                   struct smb_krb5_context *smb_krb5_context,
                                   uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
@@ -616,6 +660,17 @@ static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CT
                info1->status           = DRSUAPI_DS_NAME_STATUS_OK;
                return WERR_OK;
        }
+       case DRSUAPI_DS_NAME_FORMAT_DISPLAY: {
+               info1->result_name      = samdb_result_string(result_res[0], "displayName", NULL);
+               if (!info1->result_name) {
+                       info1->result_name      = samdb_result_string(result_res[0], "sAMAccountName", NULL);
+               } 
+               if (!info1->result_name) {
+                       info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+               } else {
+                       info1->status = DRSUAPI_DS_NAME_STATUS_OK;
+               }
+       }
        default:
                return WERR_OK;
        }
index fa219343c1197c91374bbcdc1653a86f60e252d1..1d391f588fdf0a03b1a4a9fe408bcc36e879160a 100644 (file)
@@ -25,8 +25,7 @@
 #include "librpc/gen_ndr/ndr_samr.h"
 #include "librpc/gen_ndr/ndr_dssetup.h"
 #include "rpc_server/common/common.h"
-
-
+#include "ldb/include/ldb.h"
 /* 
   dssetup_DsRoleGetPrimaryDomainInformation 
 */
@@ -82,13 +81,12 @@ static WERROR dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state
                        break;
                case ROLE_DOMAIN_BDC:
                case ROLE_DOMAIN_PDC:
-                       sam_ctx = samdb_connect(mem_ctx);
+                       sam_ctx = samdb_connect(mem_ctx, dce_call->conn->auth_state.session_info); 
                        if (!sam_ctx) {
                                return WERR_SERVER_UNAVAILABLE;
                        }
 
-                       ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
-                                          "(&(objectClass=domainDNS)(!(objectClass=builtinDomain)))");
+                       ret = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(mem_ctx), &res, attrs);
                        if (ret != 1) {
                                return WERR_SERVER_UNAVAILABLE;
                        }
@@ -96,15 +94,18 @@ static WERROR dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state
                        flags           = DS_ROLE_PRIMARY_DS_RUNNING;
 
                        if (samdb_result_uint(res[0], "nTMixedDomain", 0) == 1) {
-                               flags           |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
+                               flags   |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
                        }
-
-                       domain          = samdb_result_string(res[0], "name", NULL);
+                       
+                       domain          = samdb_search_string(sam_ctx, mem_ctx, NULL, "nETBIOSName", 
+                                                             "(&(objectclass=crossRef)(ncName=%s))", 
+                                                             ldb_dn_linearize(mem_ctx, samdb_base_dn(mem_ctx)));
+       
                        dns_domain      = samdb_result_string(res[0], "dnsDomain", NULL);
                        forest          = samdb_result_string(res[0], "dnsDomain", NULL);
 
-                       flags           |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
                        domain_guid     = samdb_result_guid(res[0], "objectGUID");
+                       flags   |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
                        break;
                }
 
index ba28462d5e01facd80ada566ecd55e9a7a3fe3e3..e4b0e8c8bad2c07fe2820f46a102f214f89d696b 100644 (file)
@@ -27,9 +27,9 @@
 #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 "db_wrap.h"
+#include "auth/auth.h"
 
 /*
   this type allows us to distinguish handle types
@@ -220,9 +220,6 @@ 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;
 
        state = talloc(mem_ctx, struct lsa_policy_state);
        if (!state) {
@@ -230,7 +227,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;
        }
@@ -247,16 +244,14 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_
                return NT_STATUS_NO_MEMORY;             
        }
 
-       ret_domain = gendb_search(state->sam_ldb, mem_ctx, NULL, &msgs_domain, domain_attrs,
-                                 "(&(objectclass=crossRef)(ncName=%s))", ldb_dn_linearize(mem_ctx, state->domain_dn));
+       state->domain_name
+               = samdb_search_string(state->sam_ldb, mem_ctx, NULL, "nETBIOSName", 
+                                     "(&(objectclass=crossRef)(ncName=%s))", ldb_dn_linearize(mem_ctx, state->domain_dn));
        
-       if (ret_domain == -1) {
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
-       }
-               
-       if (ret_domain != 1) {
+       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 */
@@ -273,23 +268,20 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_
                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", "dn=%s",
+                                                ldb_dn_linearize(mem_ctx, state->domain_dn));
        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;
@@ -2426,14 +2418,6 @@ 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);
 
index cea645cd02e7684399328682a76acd7e3aa4df8e..99701fc4f1de4e764a130f65d3d166c236ac89fd 100644 (file)
@@ -26,8 +26,8 @@
 #include "rpc_server/dcerpc_server.h"
 #include "rpc_server/common/common.h"
 #include "librpc/gen_ndr/ndr_dcom.h"
-#include "auth/auth.h"
 #include "lib/ldb/include/ldb.h"
+#include "auth/auth.h"
 
 struct server_pipe_state {
        struct netr_Credential client_challenge;
@@ -147,7 +147,7 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       sam_ctx = samdb_connect(mem_ctx);
+       sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx));
        if (sam_ctx == NULL) {
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
@@ -159,7 +159,7 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL
        if (num_records == 0) {
                DEBUG(3,("Couldn't find user [%s] in samdb.\n", 
                         r->in.account_name));
-               return NT_STATUS_NO_SUCH_USER;
+               return NT_STATUS_ACCESS_DENIED;
        }
 
        if (num_records > 1) {
@@ -322,7 +322,7 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO
        nt_status = netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator);
        NT_STATUS_NOT_OK_RETURN(nt_status);
 
-       sam_ctx = samdb_connect(mem_ctx);
+       sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx));
        if (sam_ctx == NULL) {
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
@@ -937,7 +937,7 @@ static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALL
                return status;
        }
 
-       sam_ctx = samdb_connect(mem_ctx);
+       sam_ctx = samdb_connect(mem_ctx, dce_call->conn->auth_state.session_info);
        if (sam_ctx == NULL) {
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
@@ -1034,7 +1034,7 @@ static NTSTATUS netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALL
        nt_status = netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator);
        NT_STATUS_NOT_OK_RETURN(nt_status);
 
-       sam_ctx = samdb_connect(mem_ctx);
+       sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx));
        if (sam_ctx == NULL) {
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
@@ -1167,7 +1167,7 @@ static WERROR netr_DrsGetDCNameEx2(struct dcesrv_call_state *dce_call, TALLOC_CT
 
        ZERO_STRUCT(r->out);
 
-       sam_ctx = samdb_connect(mem_ctx);
+       sam_ctx = samdb_connect(mem_ctx, dce_call->conn->auth_state.session_info);
        if (sam_ctx == NULL) {
                return WERR_DS_SERVICE_UNAVAILABLE;
        }
@@ -1256,13 +1256,12 @@ static WERROR netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
 
        ZERO_STRUCT(r->out);
 
-       sam_ctx = samdb_connect(mem_ctx);
+       sam_ctx = samdb_connect(mem_ctx, dce_call->conn->auth_state.session_info);
        if (sam_ctx == NULL) {
                return WERR_GENERAL_FAILURE;
        }
 
-       ret = gendb_search(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs,
-                          "(&(objectClass=domainDNS)(dnsDomain=%s))", lp_realm());
+       ret = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(mem_ctx), &dom_res, dom_attrs);
        if (ret == -1) {
                return WERR_GENERAL_FAILURE;            
        }
index 249fb1c8a4944147c6127dce183774cd1b96d8aa..c985187cd9f8b49a49acd803aff8c081b48c8bf2 100644 (file)
@@ -60,12 +60,13 @@ static NTSTATUS samr_Connect(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem
        }
 
        /* make sure the sam database is accessible */
-       c_state->sam_ctx = samdb_connect(c_state);
+       c_state->sam_ctx = samdb_connect(c_state, dce_call->conn->auth_state.session_info); 
        if (c_state->sam_ctx == NULL) {
                talloc_free(c_state);
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
 
+
        handle = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_CONNECT);
        if (!handle) {
                talloc_free(c_state);
@@ -3305,7 +3306,7 @@ static NTSTATUS samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX
 
        ZERO_STRUCT(r->out.info);
 
-       sam_ctx = samdb_connect(mem_ctx);
+       sam_ctx = samdb_connect(mem_ctx, dce_call->conn->auth_state.session_info); 
        if (sam_ctx == NULL) {
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
index ab99b6945874b979d0d86bfc3171f4a702176530..6fab23161946adaa4bba106cd49462ee6bb1f97e 100644 (file)
@@ -38,6 +38,7 @@ NTSTATUS samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, TALLOC_CTX
 {
        struct dcesrv_handle *h;
        struct samr_account_state *a_state;
+       struct ldb_context *sam_ctx;
        struct ldb_message **res, *msg;
        int ret;
        struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash;
@@ -49,8 +50,14 @@ NTSTATUS samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, TALLOC_CTX
 
        a_state = h->data;
 
+       /* To change a password we need to open as system */
+       sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx));
+       if (sam_ctx == NULL) {
+               return NT_STATUS_INVALID_SYSTEM_SERVICE;
+       }
+
        /* fetch the old hashes */
-       ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
+       ret = gendb_search_dn(sam_ctx, mem_ctx,
                              a_state->account_dn, &res, attrs);
        if (ret != 1) {
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
@@ -113,7 +120,7 @@ NTSTATUS samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, TALLOC_CTX
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = samdb_set_password(a_state->sam_ctx, mem_ctx,
+       status = samdb_set_password(sam_ctx, mem_ctx,
                                    a_state->account_dn, a_state->domain_state->domain_dn,
                                    msg, NULL, &new_lmPwdHash, &new_ntPwdHash, 
                                    True, /* this is a user password change */
@@ -124,7 +131,7 @@ NTSTATUS samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, TALLOC_CTX
        }
 
        /* modify the samdb record */
-       ret = samdb_replace(a_state->sam_ctx, mem_ctx, msg);
+       ret = samdb_replace(sam_ctx, mem_ctx, msg);
        if (ret != 0) {
                return NT_STATUS_UNSUCCESSFUL;
        }
@@ -142,7 +149,7 @@ NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_
        char new_pass[512];
        uint32_t new_pass_len;
        struct samr_CryptPassword *pwbuf = r->in.password;
-       void *sam_ctx;
+       struct ldb_context *sam_ctx;
        const struct ldb_dn *user_dn, *domain_dn;
        int ret;
        struct ldb_message **res, *mod;
@@ -157,9 +164,8 @@ NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_
                return NT_STATUS_WRONG_PASSWORD;
        }
 
-       /* this call doesn't take a policy handle, so we need to open
-          the sam db from scratch */
-       sam_ctx = samdb_connect(mem_ctx);
+       /* To change a password we need to open as system */
+       sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx));
        if (sam_ctx == NULL) {
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
@@ -260,7 +266,7 @@ NTSTATUS samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
        NTSTATUS status;
        char new_pass[512];
        uint32_t new_pass_len;
-       void *sam_ctx = NULL;
+       struct ldb_context *sam_ctx;
        const struct ldb_dn *user_dn, *domain_dn = NULL;
        int ret;
        struct ldb_message **res, *mod;
@@ -285,11 +291,10 @@ NTSTATUS samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
                goto failed;
        }
 
-       /* this call doesn't take a policy handle, so we need to open
-          the sam db from scratch */
-       sam_ctx = samdb_connect(mem_ctx);
+       /* To change a password we need to open as system */
+       sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx));
        if (sam_ctx == NULL) {
-               status = NT_STATUS_INVALID_SYSTEM_SERVICE;
+               return NT_STATUS_INVALID_SYSTEM_SERVICE;
                goto failed;
        }