remove dependencies on my home domain
[kai/samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
index 37e6351864093e818895bb788c04837791f28514..d5f7d2afaecd77dc15d29096f45b7e18f5e7ee9a 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
@@ -34,6 +34,9 @@
 #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;
@@ -93,7 +96,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       sam_ctx = samdb_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, 
+       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;
@@ -176,7 +179,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, dce_call->conn->dce_ctx->lp_ctx, creds);
+       nt_status = schannel_store_session_key(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, creds);
 
        return nt_status;
 }
@@ -236,7 +239,8 @@ 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(struct loadparm_context *lp_ctx,
+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,
@@ -248,7 +252,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct loadparm_context *lp_
        struct ldb_context *ldb;
        int ret;
 
-       ldb = schannel_db_connect(mem_ctx, lp_ctx);
+       ldb = schannel_db_connect(mem_ctx, event_ctx, lp_ctx);
        if (!ldb) {
                return NT_STATUS_ACCESS_DENIED;
        }
@@ -300,13 +304,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(dce_call->conn->dce_ctx->lp_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, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
+       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;
        }
@@ -334,18 +338,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(dce_call->conn->dce_ctx->lp_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, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
+       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;
        }
@@ -355,7 +358,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;
@@ -420,9 +423,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, 
@@ -459,8 +463,8 @@ 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, 
@@ -482,6 +486,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;
        }
@@ -561,7 +613,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, dce_call->conn->dce_ctx->lp_ctx, r->in.computer_name, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx), &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;
        }
@@ -589,7 +641,7 @@ 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(dce_call->conn->dce_ctx->lp_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);
@@ -847,20 +899,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");
        }
@@ -891,14 +960,17 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
 
        const char *local_domain;
 
-       status = dcesrv_netr_creds_server_step_check(dce_call->conn->dce_ctx->lp_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, dce_call->conn->dce_ctx->lp_ctx, 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;
        }
@@ -941,17 +1013,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;
@@ -1003,7 +1083,7 @@ static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TA
 
        ZERO_STRUCT(r->out);
 
-       sam_ctx = samdb_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, 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;
        }
@@ -1165,7 +1245,7 @@ static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce
 
        ZERO_STRUCT(r->out);
 
-       sam_ctx = samdb_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, 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;
        }