s3:auth_domain: make use of rpccli_{create,setup}_netlogon_creds()
authorStefan Metzmacher <metze@samba.org>
Tue, 27 Aug 2013 13:01:10 +0000 (15:01 +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/auth/auth_domain.c

index ae27bf0f1155ee635eb7335337a9fa4803e2d7c3..bf2671c17123dd0f4daa226cb5bd89d415c49736 100644 (file)
@@ -27,6 +27,7 @@
 #include "secrets.h"
 #include "passdb.h"
 #include "libsmb/libsmb.h"
+#include "libcli/auth/netlogon_creds_cli.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_AUTH
@@ -53,9 +54,20 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret,
                                                const struct sockaddr_storage *dc_ss,
                                                struct rpc_pipe_client **pipe_ret)
 {
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct messaging_context *msg_ctx = server_messaging_context();
        NTSTATUS result;
        struct cli_state *cli = NULL;
        struct rpc_pipe_client *netlogon_pipe = NULL;
+       struct netlogon_creds_cli_context *netlogon_creds = NULL;
+       struct netlogon_creds_CredentialState *creds = NULL;
+       uint32_t netlogon_flags = 0;
+       enum netr_SchannelType sec_chan_type = 0;
+       const char *_account_name = NULL;
+       const char *account_name = NULL;
+       struct samr_Password current_nt_hash;
+       struct samr_Password *previous_nt_hash = NULL;
+       bool ok;
 
        *cli_ret = NULL;
 
@@ -77,6 +89,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret,
 
        mutex = grab_named_mutex(NULL, dc_name, 10);
        if (mutex == NULL) {
+               TALLOC_FREE(frame);
                return NT_STATUS_NO_LOGON_SERVERS;
        }
 
@@ -91,6 +104,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret,
                }
 
                TALLOC_FREE(mutex);
+               TALLOC_FREE(frame);
                return result;
        }
 
@@ -98,67 +112,85 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret,
         * We now have an anonymous connection to IPC$ on the domain password server.
         */
 
-       /*
-        * Even if the connect succeeds we need to setup the netlogon
-        * pipe here. We do this as we may just have changed the domain
-        * account password on the PDC and yet we may be talking to
-        * a BDC that doesn't have this replicated yet. In this case
-        * a successful connect to a DC needs to take the netlogon connect
-        * into account also. This patch from "Bjart Kvarme" <bjart.kvarme@usit.uio.no>.
-        */
+       ok = get_trust_pw_hash(domain,
+                              current_nt_hash.hash,
+                              &_account_name,
+                              &sec_chan_type);
+       if (!ok) {
+               cli_shutdown(cli);
+               TALLOC_FREE(mutex);
+               TALLOC_FREE(frame);
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       }
 
-       /* open the netlogon pipe. */
-       if (lp_client_schannel()) {
-               /* We also setup the creds chain in the open_schannel call. */
-               result = cli_rpc_pipe_open_schannel(
-                       cli, &ndr_table_netlogon, NCACN_NP,
-                       DCERPC_AUTH_LEVEL_PRIVACY, domain, &netlogon_pipe);
-       } else {
-               result = cli_rpc_pipe_open_noauth(
-                       cli, &ndr_table_netlogon, &netlogon_pipe);
+       account_name = talloc_asprintf(talloc_tos(), "%s$", _account_name);
+       if (account_name == NULL) {
+               cli_shutdown(cli);
+               TALLOC_FREE(mutex);
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
        }
 
+       result = rpccli_create_netlogon_creds(dc_name,
+                                             domain,
+                                             account_name,
+                                             sec_chan_type,
+                                             msg_ctx,
+                                             talloc_tos(),
+                                             &netlogon_creds);
        if (!NT_STATUS_IS_OK(result)) {
-               DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \
-machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
                cli_shutdown(cli);
                TALLOC_FREE(mutex);
+               TALLOC_FREE(frame);
+               SAFE_FREE(previous_nt_hash);
                return result;
        }
 
-       if (!lp_client_schannel()) {
-               /* We need to set up a creds chain on an unauthenticated netlogon pipe. */
-               uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS |
-                                       NETLOGON_NEG_SUPPORTS_AES;
-               enum netr_SchannelType sec_chan_type = 0;
-               unsigned char machine_pwd[16];
-               const char *account_name;
-
-               if (!get_trust_pw_hash(domain, machine_pwd, &account_name,
-                                      &sec_chan_type))
-               {
-                       DEBUG(0, ("connect_to_domain_password_server: could not fetch "
-                       "trust account password for domain '%s'\n",
-                               domain));
-                       cli_shutdown(cli);
-                       TALLOC_FREE(mutex);
-                       return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-               }
+       result = rpccli_setup_netlogon_creds(cli,
+                                            netlogon_creds,
+                                            false, /* force_reauth */
+                                            current_nt_hash,
+                                            previous_nt_hash);
+       SAFE_FREE(previous_nt_hash);
+       if (!NT_STATUS_IS_OK(result)) {
+               cli_shutdown(cli);
+               TALLOC_FREE(mutex);
+               TALLOC_FREE(frame);
+               return result;
+       }
 
-               result = rpccli_netlogon_setup_creds(netlogon_pipe,
-                                       dc_name, /* server name */
-                                       domain, /* domain */
-                                       lp_netbios_name(), /* client name */
-                                       account_name, /* machine account name */
-                                       machine_pwd,
-                                       sec_chan_type,
-                                       &neg_flags);
-
-               if (!NT_STATUS_IS_OK(result)) {
-                       cli_shutdown(cli);
-                       TALLOC_FREE(mutex);
-                       return result;
-               }
+       result = netlogon_creds_cli_get(netlogon_creds,
+                                       talloc_tos(),
+                                       &creds);
+       if (!NT_STATUS_IS_OK(result)) {
+               cli_shutdown(cli);
+               TALLOC_FREE(mutex);
+               TALLOC_FREE(frame);
+               return result;
+       }
+       netlogon_flags = creds->negotiate_flags;
+       TALLOC_FREE(creds);
+
+       if (netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC) {
+               result = cli_rpc_pipe_open_schannel_with_key(
+                       cli, &ndr_table_netlogon, NCACN_NP,
+                       domain, netlogon_creds, &netlogon_pipe);
+       } else {
+               result = cli_rpc_pipe_open_noauth(cli,
+                                       &ndr_table_netlogon,
+                                       &netlogon_pipe);
+       }
+
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(0,("connect_to_domain_password_server: "
+                        "unable to open the domain client session to "
+                        "machine %s. Flags[0x%08X] Error was : %s.\n",
+                        dc_name, (unsigned)netlogon_flags,
+                        nt_errstr(result)));
+               cli_shutdown(cli);
+               TALLOC_FREE(mutex);
+               TALLOC_FREE(frame);
+               return result;
        }
 
        if(!netlogon_pipe) {
@@ -167,6 +199,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
                          "was : %s.\n", dc_name, nt_errstr(result)));
                cli_shutdown(cli);
                TALLOC_FREE(mutex);
+               TALLOC_FREE(frame);
                return NT_STATUS_NO_LOGON_SERVERS;
        }
 
@@ -175,6 +208,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
        *cli_ret = cli;
        *pipe_ret = netlogon_pipe;
 
+       TALLOC_FREE(frame);
        return NT_STATUS_OK;
 }