Start implementing AD-style trusted domains in Samba4's NETLOGON server
[kai/samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
index a6e955178d225734c6921c708a6c3c5f952c5e76..b948d1210e88483d84be5113900681dde1f3fe0e 100644 (file)
@@ -3,7 +3,7 @@
 
    endpoint server for the netlogon pipe
 
-   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
    Copyright (C) Stefan Metzmacher <metze@samba.org>  2005
    
    This program is free software; you can redistribute it and/or modify
 #include "rpc_server/common/common.h"
 #include "lib/ldb/include/ldb.h"
 #include "auth/auth.h"
-#include "auth/auth_sam.h"
+#include "auth/auth_sam_reply.h"
 #include "dsdb/samdb/samdb.h"
+#include "dsdb/common/flags.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"
+#include "lib/messaging/irpc.h"
+#include "librpc/gen_ndr/ndr_irpc.h"
+#include "librpc/gen_ndr/ndr_netlogon.h"
 
 struct server_pipe_state {
        struct netr_Credential client_challenge;
@@ -76,13 +80,16 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
        struct creds_CredentialState *creds;
        void *sam_ctx;
        struct samr_Password *mach_pwd;
-       uint16_t acct_flags;
+       uint32_t user_account_control;
        int num_records;
        struct ldb_message **msgs;
        NTSTATUS nt_status;
        const char *attrs[] = {"unicodePwd", "userAccountControl", 
                               "objectSid", NULL};
 
+       const char *trust_dom_attrs[] = {"flatname", NULL};
+       const char *account_name;
+
        ZERO_STRUCTP(r->out.credentials);
        *r->out.rid = 0;
        *r->out.negotiate_flags = *r->in.negotiate_flags;
@@ -92,14 +99,59 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       sam_ctx = samdb_connect(mem_ctx, global_loadparm, system_session(mem_ctx, global_loadparm));
+       sam_ctx = samdb_connect(mem_ctx, dce_call->event_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;
        }
+
+       if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
+               char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
+               char *flatname;
+               if (!encoded_account) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               /* Kill the trailing dot */
+               if (encoded_account[strlen(encoded_account)-1] == '.') {
+                       encoded_account[strlen(encoded_account)-1] = '\0';
+               }
+
+               /* pull the user attributes */
+               num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, trust_dom_attrs,
+                                          "(&(trustPartner=%s)(objectclass=trustedDomain))", 
+                                          encoded_account);
+               
+               if (num_records == 0) {
+                       DEBUG(3,("Couldn't find trust [%s] in samdb.\n", 
+                                encoded_account));
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+               
+               if (num_records > 1) {
+                       DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
+                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               }
+               
+               flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
+               if (!flatname) {
+                       /* No flatname for this trust - we can't proceed */
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+               account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
+
+               if (!account_name) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               
+       } else {
+               account_name = r->in.account_name;
+       }
+       
        /* pull the user attributes */
        num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
                                   "(&(sAMAccountName=%s)(objectclass=user))", 
-                                  r->in.account_name);
+                                  ldb_binary_encode_string(mem_ctx, account_name));
 
        if (num_records == 0) {
                DEBUG(3,("Couldn't find user [%s] in samdb.\n", 
@@ -112,27 +164,29 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
 
-       acct_flags = samdb_result_acct_flags(msgs[0], 
-                                            "userAccountControl");
+       
+       user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
 
-       if (acct_flags & ACB_DISABLED) {
+       if (user_account_control & UF_ACCOUNTDISABLE) {
                DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
                return NT_STATUS_ACCESS_DENIED;
        }
 
        if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
-               if (!(acct_flags & ACB_WSTRUST)) {
-                       DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", acct_flags));
+               if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
+                       DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
                        return NT_STATUS_ACCESS_DENIED;
                }
-       } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN) {
-               if (!(acct_flags & ACB_DOMTRUST)) {
-                       DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", acct_flags));
+       } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN || 
+                  r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
+               if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
+                       DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
+                       
                        return NT_STATUS_ACCESS_DENIED;
                }
        } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
-               if (!(acct_flags & ACB_SVRTRUST)) {
-                       DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", acct_flags));
+               if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
+                       DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
                        return NT_STATUS_ACCESS_DENIED;
                }
        } else {
@@ -165,7 +219,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
        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(global_loadparm));
+       creds->domain = talloc_strdup(creds, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
 
        creds->secure_channel_type = r->in.secure_channel_type;
 
@@ -173,7 +227,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
 
 
        /* remember this session key state */
-       nt_status = schannel_store_session_key(mem_ctx, global_loadparm, creds);
+       nt_status = schannel_store_session_key(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, creds);
 
        return nt_status;
 }
@@ -233,7 +287,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_ca
   the caller needs some of that information.
 
 */
-static NTSTATUS dcesrv_netr_creds_server_step_check(const char *computer_name,
+static NTSTATUS dcesrv_netr_creds_server_step_check(struct event_context *event_ctx, 
+                                                   struct loadparm_context *lp_ctx,
+                                                   const char *computer_name,
                                             TALLOC_CTX *mem_ctx, 
                                             struct netr_Authenticator *received_authenticator,
                                             struct netr_Authenticator *return_authenticator,
@@ -244,7 +300,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(const char *computer_name,
        struct ldb_context *ldb;
        int ret;
 
-       ldb = schannel_db_connect(mem_ctx, global_loadparm);
+       ldb = schannel_db_connect(mem_ctx, event_ctx, lp_ctx);
        if (!ldb) {
                return NT_STATUS_ACCESS_DENIED;
        }
@@ -260,7 +316,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(const char *computer_name,
         * update the structure */ 
        
        nt_status = schannel_fetch_session_key_ldb(ldb, ldb, computer_name, 
-                                                  lp_workgroup(global_loadparm),
+                                                  lp_workgroup(lp_ctx),
                                                   &creds);
        if (NT_STATUS_IS_OK(nt_status)) {
                nt_status = creds_server_step_check(creds, 
@@ -296,12 +352,13 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call
        struct ldb_context *sam_ctx;
        NTSTATUS nt_status;
 
-       nt_status = dcesrv_netr_creds_server_step_check(r->in.computer_name, mem_ctx, 
+       nt_status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, 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, global_loadparm, system_session(mem_ctx, global_loadparm));
+       sam_ctx = samdb_connect(mem_ctx, dce_call->event_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;
        }
@@ -329,17 +386,17 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
        struct ldb_context *sam_ctx;
        NTSTATUS nt_status;
        char new_pass[512];
-       uint32_t new_pass_len;
        bool ret;
 
        struct samr_CryptPassword password_buf;
 
-       nt_status = dcesrv_netr_creds_server_step_check(r->in.computer_name, mem_ctx, 
+       nt_status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, 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, global_loadparm, system_session(mem_ctx, global_loadparm));
+       sam_ctx = samdb_connect(mem_ctx, dce_call->event_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;
        }
@@ -349,7 +406,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
        creds_arcfour_crypt(creds, password_buf.data, 516);
 
        ret = decode_pw_buffer(password_buf.data, new_pass, sizeof(new_pass),
-                              &new_pass_len, STR_UNICODE);
+                              STR_UNICODE);
        if (!ret) {
                DEBUG(3,("netr_ServerPasswordSet2: failed to decode password buffer\n"));
                return NT_STATUS_ACCESS_DENIED;
@@ -414,9 +471,10 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
        user_info->remote_host = NULL;
 
        switch (r->in.logon_level) {
-       case 1:
-       case 3:
-       case 5:
+       case NetlogonInteractiveInformation:
+       case NetlogonServiceInformation:
+       case NetlogonInteractiveTransitiveInformation:
+       case NetlogonServiceTransitiveInformation:
                if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
                        creds_arcfour_crypt(creds, 
                                            r->in.logon.password->lmpassword.hash, 
@@ -432,7 +490,7 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
                /* TODO: we need to deny anonymous access here */
                nt_status = auth_context_create(mem_ctx, 
                                                dce_call->event_ctx, dce_call->msg_ctx,
-                                               global_loadparm,
+                                               dce_call->conn->dce_ctx->lp_ctx,
                                                &auth_context);
                NT_STATUS_NOT_OK_RETURN(nt_status);
 
@@ -453,13 +511,13 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
                *user_info->password.hash.nt = r->in.logon.password->ntpassword;
 
                break;
-       case 2:
-       case 6:
+       case NetlogonNetworkInformation:
+       case NetlogonNetworkTransitiveInformation:
 
                /* TODO: we need to deny anonymous access here */
                nt_status = auth_context_create(mem_ctx, 
                                                dce_call->event_ctx, dce_call->msg_ctx,
-                                               global_loadparm,
+                                               dce_call->conn->dce_ctx->lp_ctx,
                                                &auth_context);
                NT_STATUS_NOT_OK_RETURN(nt_status);
 
@@ -476,6 +534,54 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
                user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon.network->nt.data, r->in.logon.network->nt.length);
        
                break;
+
+               
+       case NetlogonGenericInformation:
+       {
+               if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+                       creds_arcfour_crypt(creds, 
+                                           r->in.logon.generic->data, r->in.logon.generic->length);
+               } else {
+                       /* Using DES to verify kerberos tickets makes no sense */
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               if (strcmp(r->in.logon.generic->package_name.string, "Kerberos") == 0) {
+                       NTSTATUS status;
+                       struct server_id *kdc;
+                       struct kdc_check_generic_kerberos check;
+                       struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
+                       NT_STATUS_HAVE_NO_MEMORY(generic);
+                       r->out.authoritative = 1;
+                       
+                       /* TODO: Describe and deal with these flags */
+                       r->out.flags = 0;
+
+                       r->out.validation.generic = generic;
+       
+                       kdc = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, "kdc_server");
+                       if ((kdc == NULL) || (kdc[0].id == 0)) {
+                               return NT_STATUS_NO_LOGON_SERVERS;
+                       }
+                       
+                       check.in.generic_request = 
+                               data_blob_const(r->in.logon.generic->data,
+                                               r->in.logon.generic->length);   
+                       
+                       status = irpc_call(dce_call->msg_ctx, kdc[0],
+                                          &ndr_table_irpc, NDR_KDC_CHECK_GENERIC_KERBEROS,
+                                          &check, mem_ctx);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
+                       generic->length = check.out.generic_reply.length;
+                       generic->data = check.out.generic_reply.data;
+                       return NT_STATUS_OK;
+               }
+
+               /* Until we get an implemetnation of these other packages */
+               return NT_STATUS_INVALID_PARAMETER;
+       }
        default:
                return NT_STATUS_INVALID_PARAMETER;
        }
@@ -531,7 +637,7 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
                sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
                NT_STATUS_HAVE_NO_MEMORY(sam6);
                sam6->base = *sam;
-               sam6->forest.string = lp_realm(global_loadparm);
+               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);
@@ -555,7 +661,7 @@ static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call,
 {
        NTSTATUS nt_status;
        struct creds_CredentialState *creds;
-       nt_status = schannel_fetch_session_key(mem_ctx, global_loadparm, r->in.computer_name, lp_workgroup(global_loadparm), &creds);
+       nt_status = schannel_fetch_session_key(mem_ctx, dce_call->event_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;
        }
@@ -583,7 +689,8 @@ static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce
        return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
        NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
 
-       nt_status = dcesrv_netr_creds_server_step_check(r->in.computer_name, mem_ctx, 
+       nt_status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, 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);
@@ -664,7 +771,8 @@ static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, T
 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;
 }
 
 
@@ -736,7 +844,8 @@ static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALL
 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;
 }
 
 
@@ -790,11 +899,11 @@ static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_
 }
 
 
-/* 
-  netr_NETRLOGONGETTRUSTRID 
+/*
+  netr_LogonGetTrustRid
 */
-static WERROR dcesrv_netr_NETRLOGONGETTRUSTRID(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_NETRLOGONGETTRUSTRID *r)
+static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct netr_LogonGetTrustRid *r)
 {
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
@@ -838,20 +947,37 @@ 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)
+                                      bool is_local, bool is_trust_list)
 {
        ZERO_STRUCTP(info);
 
+       info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
+       info->trust_extension.length = 16;
+       info->trust_extension.info->flags = 
+               NETR_TRUST_FLAG_TREEROOT | 
+               NETR_TRUST_FLAG_IN_FOREST | 
+               NETR_TRUST_FLAG_PRIMARY;
+       info->trust_extension.info->parent_index = 0; /* should be index into array
+                                                        of parent */
+       info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
+       info->trust_extension.info->trust_attributes = LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE; /* needs to be based on ldb search */
+
+       if (is_trust_list) {
+               /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
+               info->forest.string = NULL;
+       } else {
+               /* TODO: we need a common function for pulling the forest */
+               info->forest.string = samdb_result_string(ref_res, "dnsRoot", 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->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");
        }
@@ -862,6 +988,9 @@ static NTSTATUS fill_domain_trust_info(TALLOC_CTX *mem_ctx,
 /* 
   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 dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                        struct netr_LogonGetDomainInfo *r)
@@ -879,13 +1008,17 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
 
        const char *local_domain;
 
-       status = dcesrv_netr_creds_server_step_check(r->in.computer_name, mem_ctx, 
+       status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
+                                                    r->in.computer_name, mem_ctx, 
                                              r->in.credential, 
                                              r->out.return_authenticator,
                                              NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,(__location__ " Bad credentials - error\n"));
+       }
        NT_STATUS_NOT_OK_RETURN(status);
 
-       sam_ctx = samdb_connect(mem_ctx, global_loadparm, dce_call->conn->auth_state.session_info);
+       sam_ctx = samdb_connect(mem_ctx, dce_call->event_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;
        }
@@ -928,17 +1061,25 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
                                       info1->num_trusts);
        NT_STATUS_HAVE_NO_MEMORY(info1->trusts);
 
-       status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->domaininfo, true);
+       status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->domaininfo, 
+                                       true, false);
        NT_STATUS_NOT_OK_RETURN(status);
 
        for (i=0;i<ret2;i++) {
-               status = fill_domain_trust_info(mem_ctx, res2[i], NULL, &info1->trusts[i], false);
+               status = fill_domain_trust_info(mem_ctx, res2[i], NULL, &info1->trusts[i], 
+                                               false, true);
                NT_STATUS_NOT_OK_RETURN(status);
        }
 
-       status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->trusts[i], true);
+       status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->trusts[i], 
+                                       true, true);
        NT_STATUS_NOT_OK_RETURN(status);
 
+       info1->dns_hostname.string = samdb_result_string(ref_res[0], "dnsRoot", NULL);
+       info1->workstation_flags = 
+               NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS | NETR_WS_FLAG_HANDLES_SPN_UPDATE;
+       info1->supported_enc_types = 0; /* w2008 gives this 0 */
+
        r->out.info.info1 = info1;
 
        return NT_STATUS_OK;
@@ -985,18 +1126,23 @@ static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TA
        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, global_loadparm, dce_call->conn->auth_state.session_info);
+       sam_ctx = samdb_connect(mem_ctx, dce_call->event_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 = gendb_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;
        }
@@ -1008,8 +1154,8 @@ static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TA
         *       - 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(global_loadparm), 
-                                                         lp_realm(global_loadparm));
+                                                         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);
@@ -1147,7 +1293,7 @@ static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce
 
        ZERO_STRUCT(r->out);
 
-       sam_ctx = samdb_connect(mem_ctx, global_loadparm, dce_call->conn->auth_state.session_info);
+       sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
        if (sam_ctx == NULL) {
                return WERR_GENERAL_FAILURE;
        }
@@ -1196,11 +1342,11 @@ static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce
 }
 
 
-/* 
-  netr_DSRDEREGISTERDNSHOSTRECORDS 
+/*
+  netr_DsrDeregisterDNSHostRecords
 */
-static WERROR dcesrv_netr_DSRDEREGISTERDNSHOSTRECORDS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_DSRDEREGISTERDNSHOSTRECORDS *r)
+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);
 }
@@ -1226,11 +1372,11 @@ static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state
 }
 
 
-/* 
-  netr_NETRGETFORESTTRUSTINFORMATION 
+/*
+  netr_GetForestTrustInformation
 */
-static WERROR dcesrv_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);
 }