s3:winbindd: make use of rpccli_{create,setup}_netlogon_creds()
authorStefan Metzmacher <metze@samba.org>
Wed, 7 Aug 2013 09:32:44 +0000 (11:32 +0200)
committerStefan Metzmacher <metze@samba.org>
Tue, 7 Jan 2014 11:47:09 +0000 (12:47 +0100)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source3/winbindd/winbindd.h
source3/winbindd/winbindd_cm.c
source3/winbindd/winbindd_dual_srv.c

index b5fc010d07e4c7865f141b718391863787e3f6c3..8f89e275d78d8b49ed6e20bb902054b3ffde0d1b 100644 (file)
@@ -116,6 +116,9 @@ struct winbindd_cm_conn {
        struct policy_handle lsa_policy;
 
        struct rpc_pipe_client *netlogon_pipe;
+       struct netlogon_creds_cli_context *netlogon_creds;
+       uint32_t netlogon_flags;
+       bool netlogon_force_reauth;
 };
 
 /* Async child */
index 25e6d50f3ea2abc9040f2b5d6c5885a2a572e1e7..fcca94ab1219bb693dc2726ccdd2cb36218a2876 100644 (file)
@@ -79,6 +79,7 @@
 #include "auth/gensec/gensec.h"
 #include "../libcli/smb/smbXcli_base.h"
 #include "lib/param/loadparm.h"
+#include "libcli/auth/netlogon_creds_cli.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
@@ -1828,6 +1829,9 @@ void invalidate_cm_connection(struct winbindd_cm_conn *conn)
        }
 
        conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
+       conn->netlogon_force_reauth = false;
+       conn->netlogon_flags = 0;
+       TALLOC_FREE(conn->netlogon_creds);
 
        if (conn->cli) {
                cli_shutdown(conn->cli);
@@ -2294,8 +2298,18 @@ static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        struct rpc_pipe_client *netlogon_pipe;
 
-       if (lp_client_schannel() == False) {
-               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       *ppdc = NULL;
+
+       if ((!IS_DC) && (!domain->primary)) {
+               return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
+       }
+
+       if (domain->conn.netlogon_creds != NULL) {
+               if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
+                       return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
+               }
+               *ppdc = domain->conn.netlogon_creds;
+               return NT_STATUS_OK;
        }
 
        result = cm_connect_netlogon(domain, &netlogon_pipe);
@@ -2303,14 +2317,15 @@ static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
                return result;
        }
 
-       /* Return a pointer to the struct netlogon_creds_CredentialState from the
-          netlogon pipe. */
+       if (domain->conn.netlogon_creds == NULL) {
+               return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
+       }
 
-       if (!domain->conn.netlogon_pipe->netlogon_creds) {
-               return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
+       if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
+               return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
        }
 
-       *ppdc = domain->conn.netlogon_pipe->netlogon_creds;
+       *ppdc = domain->conn.netlogon_creds;
        return NT_STATUS_OK;
 }
 
@@ -2749,14 +2764,16 @@ NTSTATUS cm_connect_lsat(struct winbindd_domain *domain,
 NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
                             struct rpc_pipe_client **cli)
 {
+       struct messaging_context *msg_ctx = winbind_messaging_context();
        struct winbindd_cm_conn *conn;
        NTSTATUS result;
-
-       uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES;
-       uint8_t  mach_pwd[16];
        enum netr_SchannelType sec_chan_type;
+       const char *_account_name;
        const char *account_name;
-       struct rpc_pipe_client *netlogon_pipe = NULL;
+       struct samr_Password current_nt_hash;
+       struct samr_Password *previous_nt_hash = NULL;
+       struct netlogon_creds_CredentialState *creds = NULL;
+       bool ok;
 
        *cli = NULL;
 
@@ -2773,60 +2790,68 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
        }
 
        TALLOC_FREE(conn->netlogon_pipe);
-
-       result = cli_rpc_pipe_open_noauth(conn->cli,
-                                         &ndr_table_netlogon,
-                                         &netlogon_pipe);
-       if (!NT_STATUS_IS_OK(result)) {
-               return result;
-       }
+       conn->netlogon_flags = 0;
+       TALLOC_FREE(conn->netlogon_creds);
 
        if ((!IS_DC) && (!domain->primary)) {
-               /* Clear the schannel request bit and drop down */
-               neg_flags &= ~NETLOGON_NEG_SCHANNEL;            
                goto no_schannel;
        }
 
-       if (lp_client_schannel() != False) {
-               neg_flags |= NETLOGON_NEG_SCHANNEL;
+       ok = get_trust_pw_hash(domain->name,
+                              current_nt_hash.hash,
+                              &_account_name,
+                              &sec_chan_type);
+       if (!ok) {
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
        }
 
-       if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
-                              &sec_chan_type))
-       {
-               TALLOC_FREE(netlogon_pipe);
-               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       account_name = talloc_asprintf(talloc_tos(), "%s$", _account_name);
+       if (account_name == NULL) {
+               return NT_STATUS_NO_MEMORY;
        }
 
-       result = rpccli_netlogon_setup_creds(
-                netlogon_pipe,
-                domain->dcname, /* server name. */
-                domain->name,   /* domain name */
-                lp_netbios_name(), /* client name */
-                account_name,   /* machine account */
-                mach_pwd,       /* machine password */
-                sec_chan_type,  /* from get_trust_pw */
-                &neg_flags);
+       result = rpccli_create_netlogon_creds(domain->dcname,
+                                             domain->name,
+                                             account_name,
+                                             sec_chan_type,
+                                             msg_ctx,
+                                             domain,
+                                             &conn->netlogon_creds);
+       if (!NT_STATUS_IS_OK(result)) {
+               SAFE_FREE(previous_nt_hash);
+               return result;
+       }
 
+       result = rpccli_setup_netlogon_creds(conn->cli,
+                                            conn->netlogon_creds,
+                                            conn->netlogon_force_reauth,
+                                            current_nt_hash,
+                                            previous_nt_hash);
+       conn->netlogon_force_reauth = false;
+       SAFE_FREE(previous_nt_hash);
        if (!NT_STATUS_IS_OK(result)) {
-               TALLOC_FREE(netlogon_pipe);
                return result;
        }
 
-       if ((lp_client_schannel() == True) &&
-                       ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
-               DEBUG(3, ("Server did not offer schannel\n"));
-               TALLOC_FREE(netlogon_pipe);
-               return NT_STATUS_ACCESS_DENIED;
+       result = netlogon_creds_cli_get(conn->netlogon_creds,
+                                       talloc_tos(),
+                                       &creds);
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
        }
+       conn->netlogon_flags = creds->negotiate_flags;
+       TALLOC_FREE(creds);
 
  no_schannel:
-       if ((lp_client_schannel() == False) ||
-                       ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
+       if (!(conn->netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
+               result = cli_rpc_pipe_open_noauth(conn->cli,
+                                       &ndr_table_netlogon,
+                                       &conn->netlogon_pipe);
+               if (!NT_STATUS_IS_OK(result)) {
+                       invalidate_cm_connection(conn);
+                       return result;
+               }
 
-               /* We're done - just keep the existing connection to NETLOGON
-                * open */
-               conn->netlogon_pipe = netlogon_pipe;
                *cli = conn->netlogon_pipe;
                return NT_STATUS_OK;
        }
@@ -2839,12 +2864,8 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
        result = cli_rpc_pipe_open_schannel_with_key(
                conn->cli, &ndr_table_netlogon, NCACN_NP,
                domain->name,
-               netlogon_pipe->netlogon_creds,
+               conn->netlogon_creds,
                &conn->netlogon_pipe);
-
-       /* We can now close the initial netlogon pipe. */
-       TALLOC_FREE(netlogon_pipe);
-
        if (!NT_STATUS_IS_OK(result)) {
                DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
                          "was %s\n", nt_errstr(result)));
index e23d0487b628aea1250a31ddf6d57fa086f8e8aa..cae1ce9f7d93c235010d26123ad839b9c21695d5 100644 (file)
@@ -574,6 +574,7 @@ NTSTATUS _wbint_CheckMachineAccount(struct pipes_struct *p,
 
 again:
        invalidate_cm_connection(&domain->conn);
+       domain->conn.netlogon_force_reauth = true;
 
        {
                struct rpc_pipe_client *netlogon_pipe;