Return 'not implemented' on more RPCs. (easy way to 'pass' the
[samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
index 00e27c75a85602286b62674082446ea91e37476e..3d9262b995ee65bc1d094072c2793c1df7990276 100644 (file)
@@ -4,10 +4,11 @@
    endpoint server for the netlogon pipe
 
    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
+   Copyright (C) Stefan Metzmacher <metze@samba.org>  2005
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "librpc/gen_ndr/ndr_netlogon.h"
 #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"
+#include "auth/auth_sam_reply.h"
+#include "dsdb/samdb/samdb.h"
+#include "rpc_server/samr/proto.h"
+#include "util/util_ldb.h"
+#include "libcli/auth/libcli_auth.h"
+#include "auth/gensec/schannel_state.h"
+#include "libcli/security/security.h"
+#include "param/param.h"
 
 struct server_pipe_state {
        struct netr_Credential client_challenge;
        struct netr_Credential server_challenge;
-       BOOL authenticated;
-       char *account_name;
-       char *computer_name;  /* for logging only */
-       uint32_t acct_flags;
-       uint16_t sec_chan_type;
-       struct creds_CredentialState *creds;
 };
 
 
-/*
-  a client has connected to the netlogon server using schannel, so we need
-  to re-establish the credentials state
-*/
-static NTSTATUS netlogon_schannel_setup(struct dcesrv_call_state *dce_call) 
-{
-       struct server_pipe_state *state;
-       NTSTATUS status;
-
-       state = talloc_p(dce_call->conn, struct server_pipe_state);
-       if (state == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       ZERO_STRUCTP(state);
-       state->authenticated = True;
-       
-       if (dce_call->conn->auth_state.session_info == NULL) {
-               talloc_free(state);
-               smb_panic("No session info provided by schannel level setup!");
-               return NT_STATUS_NO_USER_SESSION_KEY;
-       }
-       
-       status = dcerpc_schannel_creds(dce_call->conn->auth_state.gensec_security, 
-                                      state, 
-                                      &state->creds);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(3, ("getting schannel credentials failed with %s\n", nt_errstr(status)));
-               talloc_free(state);
-               return status;
-       }
-       
-       dce_call->conn->private = state;
-
-       return NT_STATUS_OK;
-}
-
-/*
-  a hook for bind on the netlogon pipe
-*/
-static NTSTATUS netlogon_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *di) 
-{
-       dce_call->conn->private = NULL;
-
-       /* if this is a schannel bind then we need to reconstruct the pipe state */
-       if (dce_call->conn->auth_state.auth_info &&
-           dce_call->conn->auth_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
-               NTSTATUS status;
-
-               DEBUG(5, ("schannel bind on netlogon\n"));
-
-               status = netlogon_schannel_setup(dce_call);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(3, ("schannel bind on netlogon failed with %s\n", nt_errstr(status)));
-                       return status;
-               }
-       }
-
-       return NT_STATUS_OK;
-}
-
-/* this function is called when the client disconnects the endpoint */
-static void netlogon_unbind(struct dcesrv_connection *conn, const struct dcesrv_interface *di) 
-{
-       struct server_pipe_state *pipe_state = conn->private;
-
-       if (pipe_state) {
-               talloc_free(pipe_state);
-       }
-
-       conn->private = NULL;
-}
-
-#define DCESRV_INTERFACE_NETLOGON_BIND netlogon_bind
-#define DCESRV_INTERFACE_NETLOGON_UNBIND netlogon_unbind
-
-static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                        struct netr_ServerReqChallenge *r)
 {
-       struct server_pipe_state *pipe_state = dce_call->conn->private;
+       struct server_pipe_state *pipe_state = dce_call->context->private;
 
        ZERO_STRUCTP(r->out.credentials);
 
@@ -127,18 +51,11 @@ static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALL
 
        if (pipe_state) {
                talloc_free(pipe_state);
-               dce_call->conn->private = NULL;
+               dce_call->context->private = NULL;
        }
        
-       pipe_state = talloc_p(dce_call->conn, struct server_pipe_state);
-       if (!pipe_state) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       pipe_state->authenticated = False;
-       pipe_state->creds = NULL;
-       pipe_state->account_name = NULL;
-       pipe_state->computer_name = NULL;
+       pipe_state = talloc(dce_call->context, struct server_pipe_state);
+       NT_STATUS_HAVE_NO_MEMORY(pipe_state);
 
        pipe_state->client_challenge = *r->in.credentials;
 
@@ -147,22 +64,23 @@ static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALL
 
        *r->out.credentials = pipe_state->server_challenge;
 
-       dce_call->conn->private = pipe_state;
+       dce_call->context->private = pipe_state;
 
        return NT_STATUS_OK;
 }
 
-static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                         struct netr_ServerAuthenticate3 *r)
 {
-       struct server_pipe_state *pipe_state = dce_call->conn->private;
+       struct server_pipe_state *pipe_state = dce_call->context->private;
+       struct creds_CredentialState *creds;
        void *sam_ctx;
        struct samr_Password *mach_pwd;
        uint16_t acct_flags;
        int num_records;
        struct ldb_message **msgs;
        NTSTATUS nt_status;
-       const char *attrs[] = {"unicodePwd", "lmPwdHash", "ntPwdHash", "userAccountControl", 
+       const char *attrs[] = {"unicodePwd", "userAccountControl", 
                               "objectSid", NULL};
 
        ZERO_STRUCTP(r->out.credentials);
@@ -174,19 +92,20 @@ 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, dce_call->conn->dce_ctx->lp_ctx, 
+                               system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
        if (sam_ctx == NULL) {
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
        /* pull the user attributes */
-       num_records = samdb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
+       num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
                                   "(&(sAMAccountName=%s)(objectclass=user))", 
                                   r->in.account_name);
 
        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) {
@@ -223,55 +142,44 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       pipe_state->acct_flags = acct_flags;
-       pipe_state->sec_chan_type = r->in.secure_channel_type;
-
-       *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0], "objectSid", 0);
+       *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0], 
+                                               "objectSid", 0);
 
-       nt_status = samdb_result_passwords(mem_ctx, msgs[0], NULL, &mach_pwd);
-       if (!NT_STATUS_IS_OK(nt_status) || mach_pwd == NULL) {
+       mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
+       if (mach_pwd == NULL) {
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       if (!pipe_state->creds) {
-               pipe_state->creds = talloc_p(pipe_state, struct creds_CredentialState);
-               if (!pipe_state->creds) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-       }
+       creds = talloc(mem_ctx, struct creds_CredentialState);
+       NT_STATUS_HAVE_NO_MEMORY(creds);
 
-       creds_server_init(pipe_state->creds, &pipe_state->client_challenge, 
+       creds_server_init(creds, &pipe_state->client_challenge, 
                          &pipe_state->server_challenge, mach_pwd,
                          r->out.credentials,
                          *r->in.negotiate_flags);
        
-       if (!creds_server_check(pipe_state->creds, r->in.credentials)) {
+       if (!creds_server_check(creds, r->in.credentials)) {
+               talloc_free(creds);
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       pipe_state->authenticated = True;
+       creds->account_name = talloc_steal(creds, r->in.account_name);
+       
+       creds->computer_name = talloc_steal(creds, r->in.computer_name);
+       creds->domain = talloc_strdup(creds, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
 
-       if (pipe_state->account_name) {
-               /* We don't want a memory leak on this long-lived talloc context */
-               talloc_free(pipe_state->account_name);
-       }
+       creds->secure_channel_type = r->in.secure_channel_type;
 
-       pipe_state->account_name = talloc_strdup(pipe_state, r->in.account_name);
-       
-       if (pipe_state->computer_name) {
-               /* We don't want a memory leak on this long-lived talloc context */
-               talloc_free(pipe_state->account_name);
-       }
+       creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
 
-       pipe_state->computer_name = talloc_strdup(pipe_state, r->in.computer_name);
 
        /* remember this session key state */
-       nt_status = schannel_store_session_key(mem_ctx, pipe_state->computer_name, pipe_state->creds);
+       nt_status = schannel_store_session_key(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, creds);
 
        return nt_status;
 }
                                                 
-static NTSTATUS netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                        struct netr_ServerAuthenticate *r)
 {
        struct netr_ServerAuthenticate3 r3;
@@ -282,7 +190,7 @@ static NTSTATUS netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALL
         *
         * (I think ... = 0; seems wrong here --metze)
         */
-       uint32 negotiate_flags = 0;  
+       uint32_t negotiate_flags = 0;  
 
        r3.in.server_name = r->in.server_name;
        r3.in.account_name = r->in.account_name;
@@ -294,14 +202,14 @@ static NTSTATUS netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALL
        r3.out.negotiate_flags = &negotiate_flags;
        r3.out.rid = &rid;
        
-       return netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
+       return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
 }
 
-static NTSTATUS netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                         struct netr_ServerAuthenticate2 *r)
 {
        struct netr_ServerAuthenticate3 r3;
-       uint32 rid = 0;
+       uint32_t rid = 0;
 
        r3.in.server_name = r->in.server_name;
        r3.in.account_name = r->in.account_name;
@@ -313,135 +221,159 @@ static NTSTATUS netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TAL
        r3.out.negotiate_flags = r->out.negotiate_flags;
        r3.out.rid = &rid;
        
-       return netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
+       return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
 }
 
+/*
+  Validate an incoming authenticator against the credentials for the remote machine.
 
-static BOOL netr_creds_server_step_check(struct server_pipe_state *pipe_state,
-                                        struct netr_Authenticator *received_authenticator,
-                                        struct netr_Authenticator *return_authenticator) 
-{
-       if (!pipe_state->authenticated) {
-               return False;
-       }
-       return creds_server_step_check(pipe_state->creds, 
-                                      received_authenticator, 
-                                      return_authenticator);
-}
+  The credentials are (re)read and from the schannel database, and
+  written back after the caclulations are performed.
 
+  The creds_out parameter (if not NULL) returns the credentials, if
+  the caller needs some of that information.
 
-static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                                      struct netr_ServerPasswordSet *r)
+*/
+static NTSTATUS dcesrv_netr_creds_server_step_check(struct loadparm_context *lp_ctx,
+                                                   const char *computer_name,
+                                            TALLOC_CTX *mem_ctx, 
+                                            struct netr_Authenticator *received_authenticator,
+                                            struct netr_Authenticator *return_authenticator,
+                                            struct creds_CredentialState **creds_out) 
 {
-       struct server_pipe_state *pipe_state = dce_call->conn->private;
-
-       void *sam_ctx;
-       int num_records;
-       int num_records_domain;
-       int ret;
-       struct ldb_message **msgs;
-       struct ldb_message **msgs_domain;
+       struct creds_CredentialState *creds;
        NTSTATUS nt_status;
-       struct ldb_message mod, *msg_set_pw = &mod;
-       const char *domain_dn;
-       const char *domain_sid;
+       struct ldb_context *ldb;
+       int ret;
 
-       const char *attrs[] = {"objectSid", NULL };
+       ldb = schannel_db_connect(mem_ctx, lp_ctx);
+       if (!ldb) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
 
-       const char **domain_attrs = attrs;
-       ZERO_STRUCT(mod);
+       ret = ldb_transaction_start(ldb);
+       if (ret != 0) {
+               talloc_free(ldb);
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
 
-       if (!pipe_state) {
-               DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
-               return NT_STATUS_ACCESS_DENIED;
+       /* Because this is a shared structure (even across
+        * disconnects) we must update the database every time we
+        * update the structure */ 
+       
+       nt_status = schannel_fetch_session_key_ldb(ldb, ldb, computer_name, 
+                                                  lp_workgroup(lp_ctx),
+                                                  &creds);
+       if (NT_STATUS_IS_OK(nt_status)) {
+               nt_status = creds_server_step_check(creds, 
+                                                   received_authenticator, 
+                                                   return_authenticator);
+       }
+       if (NT_STATUS_IS_OK(nt_status)) {
+               nt_status = schannel_store_session_key_ldb(ldb, ldb, creds);
        }
 
-       if (!netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator)) {
-               return NT_STATUS_ACCESS_DENIED;
+       if (NT_STATUS_IS_OK(nt_status)) {
+               ldb_transaction_commit(ldb);
+               if (creds_out) {
+                       *creds_out = creds;
+                       talloc_steal(mem_ctx, creds);
+               }
+       } else {
+               ldb_transaction_cancel(ldb);
        }
+       talloc_free(ldb);
+       return nt_status;
+}
 
-       sam_ctx = samdb_connect(mem_ctx);
+/* 
+  Change the machine account password for the currently connected
+  client.  Supplies only the NT#.
+*/
+
+static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                      struct netr_ServerPasswordSet *r)
+{
+       struct creds_CredentialState *creds;
+       struct ldb_context *sam_ctx;
+       NTSTATUS nt_status;
+
+       nt_status = dcesrv_netr_creds_server_step_check(dce_call->conn->dce_ctx->lp_ctx,
+                                                       r->in.computer_name, mem_ctx, 
+                                                &r->in.credential, &r->out.return_authenticator,
+                                                &creds);
+       NT_STATUS_NOT_OK_RETURN(nt_status);
+
+       sam_ctx = samdb_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
        if (sam_ctx == NULL) {
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
-       /* pull the user attributes */
-       num_records = samdb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
-                                  "(&(sAMAccountName=%s)(objectclass=user))", 
-                                  pipe_state->account_name);
 
-       if (num_records == 0) {
-               DEBUG(3,("Couldn't find user [%s] in samdb.\n", 
-                        pipe_state->account_name));
-               return NT_STATUS_NO_SUCH_USER;
-       }
+       creds_des_decrypt(creds, &r->in.new_password);
 
-       if (num_records > 1) {
-               DEBUG(0,("Found %d records matching user [%s]\n", num_records, 
-                        pipe_state->account_name));
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
-       }
+       /* Using the sid for the account as the key, set the password */
+       nt_status = samdb_set_password_sid(sam_ctx, mem_ctx, 
+                                          creds->sid,
+                                          NULL, /* Don't have plaintext */
+                                          NULL, &r->in.new_password,
+                                          false, /* This is not considered a password change */
+                                          NULL, NULL);
+       return nt_status;
+}
 
-       domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid");
-       if (!domain_sid) {
-               DEBUG(0,("no objectSid in user record\n"));
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
-       }
+/* 
+  Change the machine account password for the currently connected
+  client.  Supplies new plaintext.
+*/
+static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                      struct netr_ServerPasswordSet2 *r)
+{
+       struct creds_CredentialState *creds;
+       struct ldb_context *sam_ctx;
+       NTSTATUS nt_status;
+       char new_pass[512];
+       uint32_t new_pass_len;
+       bool ret;
 
-       /* find the domain's DN */
-       num_records_domain = samdb_search(sam_ctx, mem_ctx, NULL, 
-                                         &msgs_domain, domain_attrs,
-                                         "(&(objectSid=%s)(objectclass=domain))", 
-                                         domain_sid);
+       struct samr_CryptPassword password_buf;
 
-       if (num_records_domain == 0) {
-               DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n"
-                        domain_sid));
-               return NT_STATUS_NO_SUCH_USER;
-       }
+       nt_status = dcesrv_netr_creds_server_step_check(dce_call->conn->dce_ctx->lp_ctx,
+                                                       r->in.computer_name, mem_ctx
+                                                &r->in.credential, &r->out.return_authenticator,
+                                                &creds);
+       NT_STATUS_NOT_OK_RETURN(nt_status);
 
-       if (num_records_domain > 1) {
-               DEBUG(0,("Found %d records matching domain [%s]\n", 
-                        num_records_domain, domain_sid));
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       sam_ctx = samdb_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
+       if (sam_ctx == NULL) {
+               return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
 
-       domain_dn = msgs_domain[0]->dn;
-       
-       mod.dn = talloc_strdup(mem_ctx, msgs[0]->dn);
-       if (!mod.dn) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       
-       creds_des_decrypt(pipe_state->creds, &r->in.new_password);
-
-       /* set the password - samdb needs to know both the domain and user DNs,
-          so the domain password policy can be used */
-       nt_status = samdb_set_password(sam_ctx, mem_ctx,
-                                      msgs[0]->dn, domain_dn,
-                                      msg_set_pw, 
-                                      NULL, /* Don't have plaintext */
-                                      NULL, &r->in.new_password,
-                                      False /* This is not considered a password change */,
-                                      NULL);
-       
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               return nt_status;
-       }
+       memcpy(password_buf.data, r->in.new_password.data, 512);
+       SIVAL(password_buf.data,512,r->in.new_password.length);
+       creds_arcfour_crypt(creds, password_buf.data, 516);
 
-       ret = samdb_replace(sam_ctx, mem_ctx, msg_set_pw);
-       if (ret != 0) {
-               /* we really need samdb.c to return NTSTATUS */
-               return NT_STATUS_UNSUCCESSFUL;
+       ret = decode_pw_buffer(password_buf.data, new_pass, sizeof(new_pass),
+                              &new_pass_len, STR_UNICODE);
+       if (!ret) {
+               DEBUG(3,("netr_ServerPasswordSet2: failed to decode password buffer\n"));
+               return NT_STATUS_ACCESS_DENIED;
        }
 
-       return NT_STATUS_OK;
+       /* Using the sid for the account as the key, set the password */
+       nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
+                                          creds->sid,
+                                          new_pass, /* we have plaintext */
+                                          NULL, NULL,
+                                          false, /* This is not considered a password change */
+                                          NULL, NULL);
+       return nt_status;
 }
 
 
 /* 
   netr_LogonUasLogon 
 */
-static WERROR netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                 struct netr_LogonUasLogon *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -451,7 +383,7 @@ static WERROR netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX
 /* 
   netr_LogonUasLogoff 
 */
-static WERROR netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_LogonUasLogoff *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -459,191 +391,154 @@ static WERROR netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX
 
 
 /* 
-  netr_LogonSamLogonWithFlags
+  netr_LogonSamLogon_base
+
+  This version of the function allows other wrappers to say 'do not check the credentials'
 
+  We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
 */
-static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                                           struct netr_LogonSamLogonWithFlags *r)
+static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                       struct netr_LogonSamLogonEx *r, struct creds_CredentialState *creds)
 {
-       struct server_pipe_state *pipe_state = dce_call->conn->private;
-
        struct auth_context *auth_context;
        struct auth_usersupplied_info *user_info;
        struct auth_serversupplied_info *server_info;
        NTSTATUS nt_status;
-       const uint8_t *chal;
        static const char zeros[16];
        struct netr_SamBaseInfo *sam;
        struct netr_SamInfo2 *sam2;
        struct netr_SamInfo3 *sam3;
        struct netr_SamInfo6 *sam6;
        
-       if (!pipe_state) {
-               DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
-               return NT_STATUS_ACCESS_DENIED;
-       }
+       user_info = talloc(mem_ctx, struct auth_usersupplied_info);
+       NT_STATUS_HAVE_NO_MEMORY(user_info);
 
-       r->out.return_authenticator = talloc_p(mem_ctx, struct netr_Authenticator);
-       if (!r->out.return_authenticator) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       if (!netr_creds_server_step_check(pipe_state, r->in.credential, r->out.return_authenticator)) {
-               return NT_STATUS_ACCESS_DENIED;
-       }
+       user_info->flags = 0;
+       user_info->mapped_state = false;
+       user_info->remote_host = NULL;
 
        switch (r->in.logon_level) {
        case 1:
        case 3:
        case 5:
-               creds_arcfour_crypt(pipe_state->creds, 
-                                   r->in.logon.password->lmpassword.hash
-                                   sizeof(r->in.logon.password->lmpassword.hash));
-               creds_arcfour_crypt(pipe_state->creds, 
-                                   r->in.logon.password->ntpassword.hash
-                                   sizeof(r->in.logon.password->ntpassword.hash));
-
-               nt_status = make_auth_context_subsystem(pipe_state, &auth_context);
-               if (!NT_STATUS_IS_OK(nt_status)) {
-                       return nt_status;
+               if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+                       creds_arcfour_crypt(creds
+                                           r->in.logon.password->lmpassword.hash, 
+                                           sizeof(r->in.logon.password->lmpassword.hash));
+                       creds_arcfour_crypt(creds
+                                           r->in.logon.password->ntpassword.hash, 
+                                           sizeof(r->in.logon.password->ntpassword.hash));
+               } else {
+                       creds_des_decrypt(creds, &r->in.logon.password->lmpassword);
+                       creds_des_decrypt(creds, &r->in.logon.password->ntpassword);
                }
 
-               chal = auth_context->get_ntlm_challenge(auth_context);
-               nt_status = make_user_info_netlogon_interactive(auth_context, 
-                                                               &user_info,
-                                                               r->in.logon.password->identity_info.account_name.string,
-                                                               r->in.logon.password->identity_info.domain_name.string,
-                                                               r->in.logon.password->identity_info.workstation.string,
-                                                               chal,
-                                                               &r->in.logon.password->lmpassword,
-                                                               &r->in.logon.password->ntpassword);
-               break;
+               /* TODO: we need to deny anonymous access here */
+               nt_status = auth_context_create(mem_ctx, 
+                                               dce_call->event_ctx, dce_call->msg_ctx,
+                                               dce_call->conn->dce_ctx->lp_ctx,
+                                               &auth_context);
+               NT_STATUS_NOT_OK_RETURN(nt_status);
+
+               user_info->logon_parameters = r->in.logon.password->identity_info.parameter_control;
+               user_info->client.account_name = r->in.logon.password->identity_info.account_name.string;
+               user_info->client.domain_name = r->in.logon.password->identity_info.domain_name.string;
+               user_info->workstation_name = r->in.logon.password->identity_info.workstation.string;
                
+               user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
+               user_info->password_state = AUTH_PASSWORD_HASH;
+
+               user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
+               NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
+               *user_info->password.hash.lanman = r->in.logon.password->lmpassword;
+
+               user_info->password.hash.nt = talloc(user_info, struct samr_Password);
+               NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
+               *user_info->password.hash.nt = r->in.logon.password->ntpassword;
+
+               break;
        case 2:
        case 6:
-               nt_status = make_auth_context_fixed(pipe_state,
-                                                   &auth_context, r->in.logon.network->challenge);
-               if (!NT_STATUS_IS_OK(nt_status)) {
-                       return nt_status;
-               }
 
-               nt_status = make_user_info_netlogon_network(auth_context,
-                                                           &user_info,
-                                                           r->in.logon.network->identity_info.account_name.string,
-                                                           r->in.logon.network->identity_info.domain_name.string,
-                                                           r->in.logon.network->identity_info.workstation.string,
-                                                           r->in.logon.network->lm.data, r->in.logon.network->lm.length,
-                                                           r->in.logon.network->nt.data, r->in.logon.network->nt.length);
+               /* TODO: we need to deny anonymous access here */
+               nt_status = auth_context_create(mem_ctx, 
+                                               dce_call->event_ctx, dce_call->msg_ctx,
+                                               dce_call->conn->dce_ctx->lp_ctx,
+                                               &auth_context);
+               NT_STATUS_NOT_OK_RETURN(nt_status);
+
+               nt_status = auth_context_set_challenge(auth_context, r->in.logon.network->challenge, "netr_LogonSamLogonWithFlags");
+               NT_STATUS_NOT_OK_RETURN(nt_status);
+
+               user_info->logon_parameters = r->in.logon.network->identity_info.parameter_control;
+               user_info->client.account_name = r->in.logon.network->identity_info.account_name.string;
+               user_info->client.domain_name = r->in.logon.network->identity_info.domain_name.string;
+               user_info->workstation_name = r->in.logon.network->identity_info.workstation.string;
+               
+               user_info->password_state = AUTH_PASSWORD_RESPONSE;
+               user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon.network->lm.data, r->in.logon.network->lm.length);
+               user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon.network->nt.data, r->in.logon.network->nt.length);
+       
                break;
        default:
-               free_auth_context(&auth_context);
                return NT_STATUS_INVALID_PARAMETER;
        }
        
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               return nt_status;
-       }
+       nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
+       NT_STATUS_NOT_OK_RETURN(nt_status);
 
-       nt_status = auth_context->check_ntlm_password(auth_context,
-                                                     user_info, 
-                                                     mem_ctx,
-                                                     &server_info);
+       nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
+       NT_STATUS_NOT_OK_RETURN(nt_status);
 
-       /* keep the auth_context for the life of this call */
-       talloc_steal(dce_call, auth_context);
-
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               return nt_status;
-       }
-
-       sam = talloc_p(mem_ctx, struct netr_SamBaseInfo);
-
-       ZERO_STRUCTP(sam);
-       
-       sam->last_logon = server_info->last_logon;
-       sam->last_logoff = server_info->last_logoff;
-       sam->acct_expiry = server_info->acct_expiry;
-       sam->last_password_change = server_info->last_password_change;
-       sam->allow_password_change = server_info->allow_password_change;
-       sam->force_password_change = server_info->force_password_change;
-       
-       sam->account_name.string = talloc_strdup(mem_ctx, server_info->account_name);
-       sam->full_name.string = talloc_strdup(mem_ctx, server_info->full_name);
-       sam->logon_script.string = talloc_strdup(mem_ctx, server_info->logon_script);
-       sam->profile_path.string = talloc_strdup(mem_ctx, server_info->profile_path);
-       sam->home_directory.string = talloc_strdup(mem_ctx, server_info->home_directory);
-       sam->home_drive.string = talloc_strdup(mem_ctx, server_info->home_drive);
-       
-       sam->logon_count = server_info->logon_count;
-       sam->bad_password_count = sam->bad_password_count;
-       sam->rid = server_info->user_sid->sub_auths[server_info->user_sid->num_auths-1];
-       sam->primary_gid = server_info->primary_group_sid->sub_auths[server_info->primary_group_sid->num_auths-1];
-       sam->group_count = 0;
-       sam->groupids = NULL;
-       sam->user_flags = 0; /* TODO: w2k3 uses 0x120 - what is this? */
-       sam->acct_flags = server_info->acct_flags;      
-       sam->logon_server.string = lp_netbios_name();
-       
-       sam->domain.string = talloc_strdup(mem_ctx, server_info->domain);
-       
-       sam->domain_sid = dom_sid_dup(mem_ctx, server_info->user_sid);
-       sam->domain_sid->num_auths--;
-
-       if (server_info->user_session_key.length == sizeof(sam->key.key)) {
-               memcpy(sam->key.key, server_info->user_session_key.data, sizeof(sam->key.key));
-       } else {
-               ZERO_STRUCT(sam->key.key);
-       }
-       
        /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
        /* It appears that level 6 is not individually encrypted */
-       if ((r->in.validation_level != 6) 
-           && memcmp(sam->key.key, zeros,  
-                     sizeof(sam->key.key)) != 0) {
-               creds_arcfour_crypt(pipe_state->creds, 
-                                   sam->key.key, 
-                                   sizeof(sam->key.key));
-       }
-       
-       if (server_info->lm_session_key.length == sizeof(sam->LMSessKey.key)) {
-               memcpy(sam->LMSessKey.key, server_info->lm_session_key.data, 
-                      sizeof(sam->LMSessKey.key));
-       } else {
-               ZERO_STRUCT(sam->LMSessKey.key);
+       if ((r->in.validation_level != 6) &&
+           memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
+               /* This key is sent unencrypted without the ARCFOUR flag set */
+               if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+                       creds_arcfour_crypt(creds, 
+                                           sam->key.key, 
+                                           sizeof(sam->key.key));
+               }
        }
-       
+
        /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
        /* It appears that level 6 is not individually encrypted */
-       if ((r->in.validation_level != 6) 
-           && memcmp(sam->LMSessKey.key, zeros,  
-                     sizeof(sam->LMSessKey.key)) != 0) {
-               creds_arcfour_crypt(pipe_state->creds, 
-                                   sam->LMSessKey.key, 
-                                   sizeof(sam->LMSessKey.key));
+       if ((r->in.validation_level != 6) &&
+           memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
+               if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+                       creds_arcfour_crypt(creds, 
+                                           sam->LMSessKey.key, 
+                                           sizeof(sam->LMSessKey.key));
+               } else {
+                       creds_des_encrypt_LMKey(creds, 
+                                               &sam->LMSessKey);
+               }
        }
 
        switch (r->in.validation_level) {
        case 2:
-               sam2 = talloc_p(mem_ctx, struct netr_SamInfo2);
-               ZERO_STRUCTP(sam2);
+               sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
+               NT_STATUS_HAVE_NO_MEMORY(sam2);
                sam2->base = *sam;
                r->out.validation.sam2 = sam2;
                break;
 
        case 3:
-               sam3 = talloc_p(mem_ctx, struct netr_SamInfo3);
-               ZERO_STRUCTP(sam3);
+               sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
+               NT_STATUS_HAVE_NO_MEMORY(sam3);
                sam3->base = *sam;
                r->out.validation.sam3 = sam3;
                break;
 
        case 6:
-               sam6 = talloc_p(mem_ctx, struct netr_SamInfo6);
-               ZERO_STRUCTP(sam6);
+               sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
+               NT_STATUS_HAVE_NO_MEMORY(sam6);
                sam6->base = *sam;
-               sam6->forest.string = lp_realm();
+               sam6->forest.string = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
                sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s", 
                                                         sam->account_name.string, sam6->forest.string);
+               NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
                r->out.validation.sam6 = sam6;
                break;
 
@@ -653,13 +548,74 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call,
 
        r->out.authoritative = 1;
 
+       /* TODO: Describe and deal with these flags */
+       r->out.flags = 0;
+
        return NT_STATUS_OK;
 }
 
+static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                    struct netr_LogonSamLogonEx *r) 
+{
+       NTSTATUS nt_status;
+       struct creds_CredentialState *creds;
+       nt_status = schannel_fetch_session_key(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, r->in.computer_name, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx), &creds);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               return nt_status;
+       }
+
+       if (!dce_call->conn->auth_state.auth_info ||
+           dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+       return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
+}
+
+/* 
+  netr_LogonSamLogonWithFlags
+
+*/
+static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                           struct netr_LogonSamLogonWithFlags *r)
+{
+       NTSTATUS nt_status;
+       struct creds_CredentialState *creds;
+       struct netr_LogonSamLogonEx r2;
+
+       struct netr_Authenticator *return_authenticator;
+
+       return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
+       NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
+
+       nt_status = dcesrv_netr_creds_server_step_check(dce_call->conn->dce_ctx->lp_ctx,
+                                                       r->in.computer_name, mem_ctx, 
+                                                r->in.credential, return_authenticator,
+                                                &creds);
+       NT_STATUS_NOT_OK_RETURN(nt_status);
+
+       ZERO_STRUCT(r2);
+
+       r2.in.server_name       = r->in.server_name;
+       r2.in.computer_name     = r->in.computer_name;
+       r2.in.logon_level       = r->in.logon_level;
+       r2.in.logon             = r->in.logon;
+       r2.in.validation_level  = r->in.validation_level;
+       r2.in.flags             = r->in.flags;
+
+       nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
+
+       r->out.return_authenticator     = return_authenticator;
+       r->out.validation               = r2.out.validation;
+       r->out.authoritative            = r2.out.authoritative;
+       r->out.flags                    = r2.out.flags;
+
+       return nt_status;
+}
+
 /* 
   netr_LogonSamLogon
 */
-static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                   struct netr_LogonSamLogon *r)
 {
        struct netr_LogonSamLogonWithFlags r2;
@@ -668,7 +624,7 @@ static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CT
        ZERO_STRUCT(r2);
 
        r2.in.server_name = r->in.server_name;
-       r2.in.workstation = r->in.workstation;
+       r2.in.computer_name = r->in.computer_name;
        r2.in.credential  = r->in.credential;
        r2.in.return_authenticator = r->in.return_authenticator;
        r2.in.logon_level = r->in.logon_level;
@@ -676,7 +632,7 @@ static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CT
        r2.in.validation_level = r->in.validation_level;
        r2.in.flags = 0;
 
-       status = netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
+       status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
 
        r->out.return_authenticator = r2.out.return_authenticator;
        r->out.validation = r2.out.validation;
@@ -689,7 +645,7 @@ static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CT
 /* 
   netr_LogonSamLogoff 
 */
-static NTSTATUS netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_LogonSamLogoff *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -700,7 +656,7 @@ static NTSTATUS netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_C
 /* 
   netr_DatabaseDeltas 
 */
-static NTSTATUS netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_DatabaseDeltas *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -710,37 +666,40 @@ static NTSTATUS netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_C
 /* 
   netr_DatabaseSync 
 */
-static NTSTATUS netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_DatabaseSync *r)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
+       return NT_STATUS_NOT_IMPLEMENTED;
 }
 
 
 /* 
   netr_AccountDeltas 
 */
-static NTSTATUS netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_AccountDeltas *r)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       /* w2k3 returns "NOT IMPLEMENTED" for this call */
+       return NT_STATUS_NOT_IMPLEMENTED;
 }
 
 
 /* 
   netr_AccountSync 
 */
-static NTSTATUS netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_AccountSync *r)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       /* w2k3 returns "NOT IMPLEMENTED" for this call */
+       return NT_STATUS_NOT_IMPLEMENTED;
 }
 
 
 /* 
   netr_GetDcName 
 */
-static NTSTATUS netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_GetDcName *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -750,7 +709,7 @@ static NTSTATUS netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
 /* 
   netr_LogonControl 
 */
-static WERROR netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_LogonControl *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -760,7 +719,7 @@ static WERROR netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *
 /* 
   netr_GetAnyDCName 
 */
-static WERROR netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_GetAnyDCName *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -770,7 +729,7 @@ static WERROR netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *
 /* 
   netr_LogonControl2 
 */
-static WERROR netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_LogonControl2 *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -780,17 +739,18 @@ static WERROR netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX
 /* 
   netr_DatabaseSync2 
 */
-static NTSTATUS netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_DatabaseSync2 *r)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
+       return NT_STATUS_NOT_IMPLEMENTED;
 }
 
 
 /* 
   netr_DatabaseRedo 
 */
-static NTSTATUS netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_DatabaseRedo *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -800,7 +760,7 @@ static NTSTATUS netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX
 /* 
   netr_LogonControl2Ex 
 */
-static WERROR netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_LogonControl2Ex *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -808,20 +768,10 @@ static WERROR netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CT
 
 
 /* 
-  netr_NETRENUMERATETRUSTEDDOMAINS 
+  netr_NetrEnumerateTurstedDomains
 */
-static WERROR netr_NETRENUMERATETRUSTEDDOMAINS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_NETRENUMERATETRUSTEDDOMAINS *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-
-/* 
-  netr_DSRGETDCNAME 
-*/
-static WERROR netr_DSRGETDCNAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_DSRGETDCNAME *r)
+static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct netr_NetrEnumerateTrustedDomains *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
@@ -830,7 +780,7 @@ static WERROR netr_DSRGETDCNAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *
 /* 
   netr_NETRLOGONDUMMYROUTINE1 
 */
-static WERROR netr_NETRLOGONDUMMYROUTINE1(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_NETRLOGONDUMMYROUTINE1(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_NETRLOGONDUMMYROUTINE1 *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -840,7 +790,7 @@ static WERROR netr_NETRLOGONDUMMYROUTINE1(struct dcesrv_call_state *dce_call, TA
 /* 
   netr_NETRLOGONSETSERVICEBITS 
 */
-static WERROR netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_NETRLOGONSETSERVICEBITS *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -850,7 +800,7 @@ static WERROR netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, T
 /* 
   netr_NETRLOGONGETTRUSTRID 
 */
-static WERROR netr_NETRLOGONGETTRUSTRID(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_NETRLOGONGETTRUSTRID(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_NETRLOGONGETTRUSTRID *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -860,7 +810,7 @@ static WERROR netr_NETRLOGONGETTRUSTRID(struct dcesrv_call_state *dce_call, TALL
 /* 
   netr_NETRLOGONCOMPUTESERVERDIGEST 
 */
-static WERROR netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -870,28 +820,19 @@ static WERROR netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_ca
 /* 
   netr_NETRLOGONCOMPUTECLIENTDIGEST 
 */
-static WERROR netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
 
-/* 
-  netr_DSRGETDCNAMEX 
-*/
-static WERROR netr_DSRGETDCNAMEX(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_DSRGETDCNAMEX *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
 
 /* 
-  netr_DSRGETSITENAME 
+  netr_DsRGetSiteName
 */
-static WERROR netr_DSRGETSITENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_DSRGETSITENAME *r)
+static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                 struct netr_DsRGetSiteName *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
@@ -900,125 +841,127 @@ static WERROR netr_DSRGETSITENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX
 /*
   fill in a netr_DomainTrustInfo from a ldb search result
 */
-static NTSTATUS fill_domain_trust_info(TALLOC_CTX *mem_ctx, struct ldb_message *res,
-                                      struct netr_DomainTrustInfo *info)
+static NTSTATUS fill_domain_trust_info(TALLOC_CTX *mem_ctx,
+                                      struct ldb_message *res,
+                                      struct ldb_message *ref_res,
+                                      struct netr_DomainTrustInfo *info, 
+                                      bool is_local)
 {
        ZERO_STRUCTP(info);
-       
-       info->domainname.string = samdb_result_string(res, "flatName", NULL);
-       if (info->domainname.string == NULL) {
-               info->domainname.string = samdb_result_string(res, "name", NULL);
-               info->fulldomainname.string = samdb_result_string(res, "dnsDomain", NULL);
+
+       if (is_local) {
+               info->domainname.string = samdb_result_string(ref_res, "nETBIOSName", NULL);
+               info->fulldomainname.string = samdb_result_string(ref_res, "dnsRoot", NULL);
+               info->forest.string = NULL;
+               info->guid = samdb_result_guid(res, "objectGUID");
+               info->sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
        } else {
-               info->fulldomainname.string = samdb_result_string(res, "name", NULL);
+               info->domainname.string = samdb_result_string(res, "flatName", NULL);
+               info->fulldomainname.string = samdb_result_string(res, "trustPartner", NULL);
+               info->forest.string = NULL;
+               info->guid = samdb_result_guid(res, "objectGUID");
+               info->sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
        }
 
-       /* TODO: we need proper forest support */
-       info->forest.string = info->fulldomainname.string;
-
-       info->guid = samdb_result_guid(res, "objectGUID");
-       info->sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
-
        return NT_STATUS_OK;
 }
 
 /* 
   netr_LogonGetDomainInfo
   this is called as part of the ADS domain logon procedure.
+
+  It has an important role in convaying details about the client, such
+  as Operating System, Version, Service Pack etc.
 */
-static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                        struct netr_LogonGetDomainInfo *r)
 {
-       struct server_pipe_state *pipe_state = dce_call->conn->private;
-       const char * const attrs[] = { "name", "dnsDomain", "objectSid", 
-                                      "objectGUID", "flatName", NULL };
-       void *sam_ctx;
-       struct ldb_message **res1, **res2;
+       const char * const attrs[] = { "objectSid", 
+                                      "objectGUID", "flatName", "securityIdentifier",
+                                      "trustPartner", NULL };
+       const char * const ref_attrs[] = { "nETBIOSName", "dnsRoot", NULL };
+       struct ldb_context *sam_ctx;
+       struct ldb_message **res1, **res2, **ref_res;
        struct netr_DomainInfo1 *info1;
-       int ret1, ret2, i;
+       int ret, ret1, ret2, i;
        NTSTATUS status;
+       struct ldb_dn *partitions_basedn;
 
-       if (!pipe_state) {
-               return NT_STATUS_ACCESS_DENIED;
-       }
+       const char *local_domain;
 
-       if (!netr_creds_server_step_check(pipe_state, 
-                                         r->in.credential, r->out.credential)) {
-               return NT_STATUS_ACCESS_DENIED;
-       }
+       status = dcesrv_netr_creds_server_step_check(dce_call->conn->dce_ctx->lp_ctx,
+                                                    r->in.computer_name, mem_ctx, 
+                                             r->in.credential, 
+                                             r->out.return_authenticator,
+                                             NULL);
+       NT_STATUS_NOT_OK_RETURN(status);
 
-       sam_ctx = samdb_connect(mem_ctx);
+       sam_ctx = samdb_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
        if (sam_ctx == NULL) {
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
        }
 
+       partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
+
        /* we need to do two searches. The first will pull our primary
           domain and the second will pull any trusted domains. Our
           primary domain is also a "trusted" domain, so we need to
           put the primary domain into the lists of returned trusts as
           well */
-       ret1 = samdb_search(sam_ctx, mem_ctx, NULL, &res1, attrs, "(objectClass=domainDNS)");
+       ret1 = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx), &res1, attrs);
        if (ret1 != 1) {
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
 
-       ret2 = samdb_search(sam_ctx, mem_ctx, NULL, &res2, attrs, "(objectClass=trustedDomain)");
-       if (ret2 == -1) {
+       /* try and find the domain */
+       ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, 
+                          &ref_res, ref_attrs, 
+                          "(&(objectClass=crossRef)(ncName=%s))", 
+                          ldb_dn_get_linearized(res1[0]->dn));
+       if (ret != 1) {
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
 
-       info1 = talloc_p(mem_ctx, struct netr_DomainInfo1);
-       if (info1 == NULL) {
-               return NT_STATUS_NO_MEMORY;
+       local_domain = samdb_result_string(ref_res[0], "nETBIOSName", NULL);
+
+       ret2 = gendb_search(sam_ctx, mem_ctx, NULL, &res2, attrs, "(objectClass=trustedDomain)");
+       if (ret2 == -1) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
 
+       info1 = talloc(mem_ctx, struct netr_DomainInfo1);
+       NT_STATUS_HAVE_NO_MEMORY(info1);
+
        ZERO_STRUCTP(info1);
 
        info1->num_trusts = ret2 + 1;
-       info1->trusts = talloc_array_p(mem_ctx, struct netr_DomainTrustInfo, 
+       info1->trusts = talloc_array(mem_ctx, struct netr_DomainTrustInfo, 
                                       info1->num_trusts);
-       if (info1->trusts == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
+       NT_STATUS_HAVE_NO_MEMORY(info1->trusts);
 
-       status = fill_domain_trust_info(mem_ctx, res1[0], &info1->domaininfo);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       status = fill_domain_trust_info(mem_ctx, res1[0], &info1->trusts[0]);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
+       status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->domaininfo, true);
+       NT_STATUS_NOT_OK_RETURN(status);
 
        for (i=0;i<ret2;i++) {
-               status = fill_domain_trust_info(mem_ctx, res2[i], &info1->trusts[i+1]);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
-               }
+               status = fill_domain_trust_info(mem_ctx, res2[i], NULL, &info1->trusts[i], false);
+               NT_STATUS_NOT_OK_RETURN(status);
        }
 
+       status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->trusts[i], true);
+       NT_STATUS_NOT_OK_RETURN(status);
+
        r->out.info.info1 = info1;
 
        return NT_STATUS_OK;
 }
 
 
-/* 
-  netr_NETRSERVERPASSWORDSET2 
-*/
-static WERROR netr_NETRSERVERPASSWORDSET2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_NETRSERVERPASSWORDSET2 *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
 
-/* 
-  netr_NETRSERVERPASSWORDGET 
+/*
+  netr_ServerPasswordGet
 */
-static WERROR netr_NETRSERVERPASSWORDGET(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_NETRSERVERPASSWORDGET *r)
+static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct netr_ServerPasswordGet *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
@@ -1027,7 +970,7 @@ static WERROR netr_NETRSERVERPASSWORDGET(struct dcesrv_call_state *dce_call, TAL
 /* 
   netr_NETRLOGONSENDTOSAM 
 */
-static WERROR netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_NETRLOGONSENDTOSAM *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
@@ -1035,107 +978,170 @@ static WERROR netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC
 
 
 /* 
-  netr_DSRADDRESSTOSITENAMES
+  netr_DsRAddressToSitenames
 */
-static WERROR netr_DSRADDRESSTOSITENAMESW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_DSRADDRESSTOSITENAMESW *r)
+static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct netr_DsRAddressToSitenamesW *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
 
 /* 
-  netr_DrsGetDCNameEx2
+  netr_DsRGetDCNameEx2
 */
-static WERROR netr_DrsGetDCNameEx2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_DrsGetDCNameEx2 *r)
+static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                  struct netr_DsRGetDCNameEx2 *r)
 {
        const char * const attrs[] = { "dnsDomain", "objectGUID", NULL };
        void *sam_ctx;
        struct ldb_message **res;
+       struct ldb_dn *domain_dn;
        int ret;
 
        ZERO_STRUCT(r->out);
 
-       sam_ctx = samdb_connect(mem_ctx);
+       sam_ctx = samdb_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
        if (sam_ctx == NULL) {
                return WERR_DS_SERVICE_UNAVAILABLE;
        }
 
-       ret = samdb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
-                               "(&(objectClass=domainDNS)(dnsDomain=%s))",
-                               r->in.domain_name);
+       domain_dn = samdb_dns_domain_to_dn(sam_ctx, mem_ctx,
+                                          r->in.domain_name);   
+       if (domain_dn == NULL) {
+               return WERR_DS_SERVICE_UNAVAILABLE;
+       }
+
+       ret = gendb_search_dn(sam_ctx, mem_ctx, domain_dn, &res, attrs);
        if (ret != 1) {
                return WERR_NO_SUCH_DOMAIN;
        }
 
-       r->out.info = talloc_p(mem_ctx, struct netr_DrsGetDCNameEx2Info);
-       if (!r->out.info) {
-               return WERR_NOMEM;
-       }
+       r->out.info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
+       W_ERROR_HAVE_NO_MEMORY(r->out.info);
 
        /* TODO: - return real IP address
         *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
         */
-       r->out.info->dc_unc             = talloc_asprintf(mem_ctx, "\\\\%s.%s", lp_netbios_name(),lp_realm());
-       r->out.info->dc_address = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
-       r->out.info->dc_address_type    = 1;
+       r->out.info->dc_unc             = talloc_asprintf(mem_ctx, "\\\\%s.%s", 
+                                                         lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx), 
+                                                         lp_realm(dce_call->conn->dce_ctx->lp_ctx));
+       W_ERROR_HAVE_NO_MEMORY(r->out.info->dc_unc);
+       r->out.info->dc_address         = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
+       W_ERROR_HAVE_NO_MEMORY(r->out.info->dc_address);
+       r->out.info->dc_address_type    = DS_ADDRESS_TYPE_INET;
        r->out.info->domain_guid        = samdb_result_guid(res[0], "objectGUID");
        r->out.info->domain_name        = samdb_result_string(res[0], "dnsDomain", NULL);
        r->out.info->forest_name        = samdb_result_string(res[0], "dnsDomain", NULL);
-       r->out.info->dc_flags           = 0xE00001FD;
+       r->out.info->dc_flags           = DS_DNS_FOREST |
+                                         DS_DNS_DOMAIN |
+                                         DS_DNS_CONTROLLER |
+                                         DS_SERVER_WRITABLE |
+                                         DS_SERVER_CLOSEST |
+                                         DS_SERVER_TIMESERV |
+                                         DS_SERVER_KDC |
+                                         DS_SERVER_DS |
+                                         DS_SERVER_LDAP |
+                                         DS_SERVER_GC |
+                                         DS_SERVER_PDC;
        r->out.info->dc_site_name       = talloc_strdup(mem_ctx, "Default-First-Site-Name");
+       W_ERROR_HAVE_NO_MEMORY(r->out.info->dc_site_name);
        r->out.info->client_site_name   = talloc_strdup(mem_ctx, "Default-First-Site-Name");
+       W_ERROR_HAVE_NO_MEMORY(r->out.info->client_site_name);
 
        return WERR_OK;
 }
 
-
 /* 
-  netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN 
+  netr_DsRGetDCNameEx
 */
-static WERROR netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
+static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                                 struct netr_DsRGetDCNameEx *r)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       struct netr_DsRGetDCNameEx2 r2;
+       WERROR werr;
+
+       ZERO_STRUCT(r2);
+
+       r2.in.server_unc = r->in.server_unc;
+       r2.in.client_account = NULL;
+       r2.in.mask = 0;
+       r2.in.domain_guid = r->in.domain_guid;
+       r2.in.domain_name = r->in.domain_name;
+       r2.in.site_name = r->in.site_name;
+       r2.in.flags = r->in.flags;
+       r2.out.info = NULL;
+
+       werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
+       
+       r->out.info = r2.out.info;
+       
+       return werr;
 }
 
+/* 
+  netr_DsRGetDCName
+*/
+static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                               struct netr_DsRGetDCName *r)
+{
+       struct netr_DsRGetDCNameEx2 r2;
+       WERROR werr;
+
+       ZERO_STRUCT(r2);
+
+       r2.in.server_unc = r->in.server_unc;
+       r2.in.client_account = NULL;
+       r2.in.mask = 0;
+       r2.in.domain_name = r->in.domain_name;
+       r2.in.domain_guid = r->in.domain_guid;
+       
+       r2.in.site_name = NULL; /* should fill in from site GUID */
+       r2.in.flags = r->in.flags;
+       r2.out.info = NULL;
+
+       werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
+       
+       r->out.info = r2.out.info;
+       
+       return werr;
+}
 
 /* 
-  netr_NETRENUMERATETRUSTEDDOMAINSEX 
+  netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN 
 */
-static WERROR netr_NETRENUMERATETRUSTEDDOMAINSEX(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_NETRENUMERATETRUSTEDDOMAINSEX *r)
+static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
 
-/* 
-  netr_DSRADDRESSTOSITENAMESEXW 
+/*
+  netr_NetrEnumerateTrustedDomainsEx
 */
-static WERROR netr_DSRADDRESSTOSITENAMESEXW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_DSRADDRESSTOSITENAMESEXW *r)
+static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct netr_NetrEnumerateTrustedDomainsEx *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
 
 /* 
-  netr_DSRGETDCSITECOVERAGE
+  netr_DsRAddressToSitenamesEx
 */
-static WERROR netr_DSRGETDCSITECOVERAGEW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_DSRGETDCSITECOVERAGEW *r)
+static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct netr_DsRAddressToSitenamesExW *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
 
 /* 
-  netr_NETRLOGONSAMLOGONEX 
+  netr_DsrGetDcSiteCoverageW
 */
-static WERROR netr_NETRLOGONSAMLOGONEX(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_NETRLOGONSAMLOGONEX *r)
+static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct netr_DsrGetDcSiteCoverageW *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
@@ -1144,55 +1150,63 @@ static WERROR netr_NETRLOGONSAMLOGONEX(struct dcesrv_call_state *dce_call, TALLO
 /* 
   netr_DsrEnumerateDomainTrusts 
 */
-static WERROR netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                              struct netr_DsrEnumerateDomainTrusts *r)
 {
        struct netr_DomainTrust *trusts;
        void *sam_ctx;
-       int ret, i;
-       struct ldb_message **res;
-       const char * const attrs[] = { "name", "dnsDomain", "objectSid", "objectGUID", NULL };
+       int ret;
+       struct ldb_message **dom_res, **ref_res;
+       const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
+       const char * const ref_attrs[] = { "nETBIOSName", "dnsRoot", NULL };
+       struct ldb_dn *partitions_basedn;
 
        ZERO_STRUCT(r->out);
 
-       sam_ctx = samdb_connect(mem_ctx);
+       sam_ctx = samdb_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
        if (sam_ctx == NULL) {
                return WERR_GENERAL_FAILURE;
        }
 
-       ret = samdb_search(sam_ctx, mem_ctx, NULL, &res, attrs, "(objectClass=domainDNS)");
+       partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
+
+       ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
        if (ret == -1) {
                return WERR_GENERAL_FAILURE;            
        }
-
-       if (ret == 0) {
-               return WERR_OK;
+       if (ret != 1) {
+               return WERR_GENERAL_FAILURE;
        }
 
-       trusts = talloc_array_p(mem_ctx, struct netr_DomainTrust, ret);
-       if (trusts == NULL) {
-               return WERR_NOMEM;
+       ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, &ref_res, ref_attrs,
+                          "(&(objectClass=crossRef)(ncName=%s))",
+                          ldb_dn_get_linearized(dom_res[0]->dn));
+       if (ret == -1) {
+               return WERR_GENERAL_FAILURE;
+       }
+       if (ret != 1) {
+               return WERR_GENERAL_FAILURE;
        }
+
+       trusts = talloc_array(mem_ctx, struct netr_DomainTrust, ret);
+       W_ERROR_HAVE_NO_MEMORY(trusts);
        
-       r->out.count = ret;
+       r->out.count = 1;
        r->out.trusts = trusts;
 
        /* TODO: add filtering by trust_flags, and correct trust_type
           and attributes */
-       for (i=0;i<ret;i++) {
-               trusts[i].netbios_name = samdb_result_string(res[i], "name", NULL);
-               trusts[i].dns_name     = samdb_result_string(res[i], "dnsDomain", NULL);
-               trusts[i].trust_flags = 
-                       NETR_TRUST_FLAG_TREEROOT | 
-                       NETR_TRUST_FLAG_IN_FOREST | 
-                       NETR_TRUST_FLAG_PRIMARY;
-               trusts[i].parent_index = 0;
-               trusts[i].trust_type = 2;
-               trusts[i].trust_attributes = 0;
-               trusts[i].sid  = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
-               trusts[i].guid = samdb_result_guid(res[i], "objectGUID");
-       }
-       
+       trusts[0].netbios_name = samdb_result_string(ref_res[0], "nETBIOSName", NULL);
+       trusts[0].dns_name     = samdb_result_string(ref_res[0], "dnsRoot", NULL);
+       trusts[0].trust_flags = 
+               NETR_TRUST_FLAG_TREEROOT | 
+               NETR_TRUST_FLAG_IN_FOREST | 
+               NETR_TRUST_FLAG_PRIMARY;
+       trusts[0].parent_index = 0;
+       trusts[0].trust_type = 2;
+       trusts[0].trust_attributes = 0;
+       trusts[0].sid  = samdb_result_dom_sid(mem_ctx, dom_res[0], "objectSid");
+       trusts[0].guid = samdb_result_guid(dom_res[0], "objectGUID");
 
        return WERR_OK;
 }
@@ -1201,38 +1215,38 @@ static WERROR netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
 /* 
   netr_DSRDEREGISTERDNSHOSTRECORDS 
 */
-static WERROR netr_DSRDEREGISTERDNSHOSTRECORDS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_DSRDEREGISTERDNSHOSTRECORDS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_DSRDEREGISTERDNSHOSTRECORDS *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
 
-/* 
-  netr_NETRSERVERTRUSTPASSWORDSGET 
+/*
+  netr_ServerTrustPasswordsGet
 */
-static WERROR netr_NETRSERVERTRUSTPASSWORDSGET(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_NETRSERVERTRUSTPASSWORDSGET *r)
+static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct netr_ServerTrustPasswordsGet *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
 
 /* 
-  netr_DSRGETFORESTTRUSTINFORMATION 
+  netr_DsRGetForestTrustInformation 
 */
-static WERROR netr_DSRGETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_DSRGETFORESTTRUSTINFORMATION *r)
+static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct netr_DsRGetForestTrustInformation *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
 
-/* 
-  netr_NETRGETFORESTTRUSTINFORMATION 
+/*
+  netr_GetForestTrustInformation
 */
-static WERROR netr_NETRGETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_NETRGETFORESTTRUSTINFORMATION *r)
+static WERROR dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct netr_GetForestTrustInformation *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
@@ -1241,7 +1255,7 @@ static WERROR netr_NETRGETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_c
 /* 
   netr_NETRSERVERGETTRUSTINFO 
 */
-static WERROR netr_NETRSERVERGETTRUSTINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+static WERROR dcesrv_netr_NETRSERVERGETTRUSTINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_NETRSERVERGETTRUSTINFO *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);