NTSTATUS rpccli_setup_netlogon_creds_locked( struct cli_state *cli, enum dcerpc_transport_t transport, struct netlogon_creds_cli_context *creds_ctx, bool force_reauth, struct cli_credentials *cli_creds, uint32_t *negotiate_flags) { TALLOC_CTX *frame = talloc_stackframe(); struct rpc_pipe_client *netlogon_pipe = NULL; struct netlogon_creds_CredentialState *creds = NULL; uint8_t num_nt_hashes = 0; const struct samr_Password *nt_hashes[2] = { NULL, NULL }; uint8_t idx_nt_hashes = 0; NTSTATUS status; status = netlogon_creds_cli_get(creds_ctx, frame, &creds); if (NT_STATUS_IS_OK(status)) { const char *action = "using"; if (force_reauth) { action = "overwrite"; } DEBUG(5,("%s: %s cached netlogon_creds cli[%s/%s] to %s\n", __FUNCTION__, action, creds->account_name, creds->computer_name, smbXcli_conn_remote_name(cli->conn))); if (!force_reauth) { goto done; } TALLOC_FREE(creds); } nt_hashes[0] = cli_credentials_get_nt_hash(cli_creds, talloc_tos()); if (nt_hashes[0] == NULL) { TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } num_nt_hashes = 1; nt_hashes[1] = cli_credentials_get_old_nt_hash(cli_creds, talloc_tos()); if (nt_hashes[1] != NULL) { num_nt_hashes = 2; } status = cli_rpc_pipe_open_noauth_transport(cli, transport, &ndr_table_netlogon, &netlogon_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("%s: failed to open noauth netlogon connection to %s - %s\n", __FUNCTION__, smbXcli_conn_remote_name(cli->conn), nt_errstr(status))); TALLOC_FREE(frame); return status; } talloc_steal(frame, netlogon_pipe); status = netlogon_creds_cli_auth(creds_ctx, netlogon_pipe->binding_handle, num_nt_hashes, nt_hashes, &idx_nt_hashes); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); return status; } status = netlogon_creds_cli_get(creds_ctx, frame, &creds); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); return NT_STATUS_INTERNAL_ERROR; } DEBUG(5,("%s: using new netlogon_creds cli[%s/%s] to %s\n", __FUNCTION__, creds->account_name, creds->computer_name, smbXcli_conn_remote_name(cli->conn))); done: if (negotiate_flags != NULL) { *negotiate_flags = creds->negotiate_flags; } TALLOC_FREE(frame); return NT_STATUS_OK; }
NTSTATUS rpccli_connect_netlogon( struct cli_state *cli, enum dcerpc_transport_t transport, struct netlogon_creds_cli_context *creds_ctx, bool force_reauth, struct cli_credentials *trust_creds, struct rpc_pipe_client **_rpccli) { TALLOC_CTX *frame = talloc_stackframe(); struct netlogon_creds_CredentialState *creds = NULL; enum netlogon_creds_cli_lck_type lck_type; enum netr_SchannelType sec_chan_type; struct netlogon_creds_cli_lck *lck = NULL; uint32_t negotiate_flags; uint8_t found_session_key[16] = {0}; bool found_existing_creds = false; bool do_serverauth; struct rpc_pipe_client *rpccli; NTSTATUS status; bool retry = false; sec_chan_type = cli_credentials_get_secure_channel_type(trust_creds); if (sec_chan_type == SEC_CHAN_NULL) { DBG_ERR("secure_channel_type gave SEC_CHAN_NULL\n"); status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; goto fail; } again: /* * See whether we can use existing netlogon_creds or * whether we have to serverauthenticate. */ status = netlogon_creds_cli_get(creds_ctx, frame, &creds); if (NT_STATUS_IS_OK(status)) { int cmp = memcmp(found_session_key, creds->session_key, sizeof(found_session_key)); found_existing_creds = (cmp != 0); memcpy(found_session_key, creds->session_key, sizeof(found_session_key)); TALLOC_FREE(creds); } lck_type = (force_reauth || !found_existing_creds) ? NETLOGON_CREDS_CLI_LCK_EXCLUSIVE : NETLOGON_CREDS_CLI_LCK_SHARED; status = netlogon_creds_cli_lck(creds_ctx, lck_type, frame, &lck); if (!NT_STATUS_IS_OK(status)) { DBG_DEBUG("netlogon_creds_cli_lck failed: %s\n", nt_errstr(status)); goto fail; } if (!found_existing_creds) { /* * Try to find creds under the lock again. Someone * else might have done it for us. */ status = netlogon_creds_cli_get(creds_ctx, frame, &creds); if (NT_STATUS_IS_OK(status)) { int cmp = memcmp(found_session_key, creds->session_key, sizeof(found_session_key)); found_existing_creds = (cmp != 0); memcpy(found_session_key, creds->session_key, sizeof(found_session_key)); TALLOC_FREE(creds); } } do_serverauth = force_reauth || !found_existing_creds; if (!do_serverauth) { /* * Do the quick schannel bind without a reauth */ status = cli_rpc_pipe_open_bind_schannel( cli, &ndr_table_netlogon, transport, creds_ctx, &rpccli); if (!retry && NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) { DBG_DEBUG("Retrying with serverauthenticate\n"); TALLOC_FREE(lck); retry = true; goto again; } if (!NT_STATUS_IS_OK(status)) { DBG_DEBUG("cli_rpc_pipe_open_bind_schannel " "failed: %s\n", nt_errstr(status)); goto fail; } goto done; } if (cli_credentials_is_anonymous(trust_creds)) { DBG_WARNING("get_trust_credential for %s only gave anonymous," "unable to negotiate NETLOGON credentials\n", netlogon_creds_cli_debug_string( creds_ctx, frame)); status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; goto fail; } status = rpccli_setup_netlogon_creds_locked( cli, transport, creds_ctx, true, trust_creds, &negotiate_flags); if (!NT_STATUS_IS_OK(status)) { DBG_DEBUG("rpccli_setup_netlogon_creds failed for %s, " "unable to setup NETLOGON credentials: %s\n", netlogon_creds_cli_debug_string( creds_ctx, frame), nt_errstr(status)); goto fail; } if (!(negotiate_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { if (lp_winbind_sealed_pipes() || lp_require_strong_key()) { status = NT_STATUS_DOWNGRADE_DETECTED; DBG_WARNING("Unwilling to make connection to %s" "without connection level security, " "must set 'winbind sealed pipes = false'" " and 'require strong key = false' " "to proceed: %s\n", netlogon_creds_cli_debug_string( creds_ctx, frame), nt_errstr(status)); goto fail; } status = cli_rpc_pipe_open_noauth_transport( cli, transport, &ndr_table_netlogon, &rpccli); if (!NT_STATUS_IS_OK(status)) { DBG_DEBUG("cli_rpc_pipe_open_noauth_transport " "failed: %s\n", nt_errstr(status)); goto fail; } goto done; } status = cli_rpc_pipe_open_bind_schannel( cli, &ndr_table_netlogon, transport, creds_ctx, &rpccli); if (!NT_STATUS_IS_OK(status)) { DBG_DEBUG("cli_rpc_pipe_open_bind_schannel " "failed: %s\n", nt_errstr(status)); goto fail; } status = netlogon_creds_cli_check(creds_ctx, rpccli->binding_handle, NULL); if (!NT_STATUS_IS_OK(status)) { DBG_WARNING("netlogon_creds_cli_check failed: %s\n", nt_errstr(status)); goto fail; } done: *_rpccli = rpccli; status = NT_STATUS_OK; fail: ZERO_STRUCT(found_session_key); TALLOC_FREE(lck); TALLOC_FREE(frame); return status; }
NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, enum dcerpc_transport_t transport, struct netlogon_creds_cli_context *netlogon_creds, bool force_reauth, struct samr_Password current_nt_hash, const struct samr_Password *previous_nt_hash) { TALLOC_CTX *frame = talloc_stackframe(); struct rpc_pipe_client *netlogon_pipe = NULL; struct netlogon_creds_CredentialState *creds = NULL; NTSTATUS status; status = netlogon_creds_cli_get(netlogon_creds, frame, &creds); if (NT_STATUS_IS_OK(status)) { const char *action = "using"; if (force_reauth) { action = "overwrite"; } DEBUG(5,("%s: %s cached netlogon_creds cli[%s/%s] to %s\n", __FUNCTION__, action, creds->account_name, creds->computer_name, smbXcli_conn_remote_name(cli->conn))); if (!force_reauth) { TALLOC_FREE(frame); return NT_STATUS_OK; } TALLOC_FREE(creds); } status = cli_rpc_pipe_open_noauth_transport(cli, transport, &ndr_table_netlogon, &netlogon_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("%s: failed to open noauth netlogon connection to %s - %s\n", __FUNCTION__, smbXcli_conn_remote_name(cli->conn), nt_errstr(status))); TALLOC_FREE(frame); return status; } talloc_steal(frame, netlogon_pipe); status = netlogon_creds_cli_auth(netlogon_creds, netlogon_pipe->binding_handle, current_nt_hash, previous_nt_hash); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); return status; } status = netlogon_creds_cli_get(netlogon_creds, frame, &creds); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); return NT_STATUS_INTERNAL_ERROR; } DEBUG(5,("%s: using new netlogon_creds cli[%s/%s] to %s\n", __FUNCTION__, creds->account_name, creds->computer_name, smbXcli_conn_remote_name(cli->conn))); TALLOC_FREE(frame); return NT_STATUS_OK; }