#include "messages.h"
#include "auth/gensec/gensec.h"
#include "../libcli/smb/smbXcli_base.h"
-#include "lib/param/loadparm.h"
#include "libcli/auth/netlogon_creds_cli.h"
#include "auth.h"
#include "rpc_server/rpc_ncacn_np.h"
+#include "auth/credentials/credentials.h"
+#include "lib/param/param.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
}
}
+static NTSTATUS cm_get_ipc_credentials(TALLOC_CTX *mem_ctx,
+ struct cli_credentials **_creds)
+{
+
+ TALLOC_CTX *frame = talloc_stackframe();
+ NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
+ struct loadparm_context *lp_ctx;
+ char *username = NULL;
+ char *netbios_domain = NULL;
+ char *password = NULL;
+ struct cli_credentials *creds = NULL;
+ bool ok;
+
+ cm_get_ipc_userpass(&username, &netbios_domain, &password);
+
+ lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
+ if (lp_ctx == NULL) {
+ DEBUG(1, ("loadparm_init_s3 failed\n"));
+ status = NT_STATUS_INTERNAL_ERROR;
+ goto fail;
+ }
+
+ creds = cli_credentials_init(mem_ctx);
+ if (creds == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ cli_credentials_set_conf(creds, lp_ctx);
+ cli_credentials_set_kerberos_state(creds, CRED_DONT_USE_KERBEROS);
+
+ ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
+ if (!ok) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ ok = cli_credentials_set_username(creds, username, CRED_SPECIFIED);
+ if (!ok) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ ok = cli_credentials_set_password(creds, password, CRED_SPECIFIED);
+ if (!ok) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ *_creds = creds;
+ creds = NULL;
+ status = NT_STATUS_OK;
+ fail:
+ TALLOC_FREE(creds);
+ SAFE_FREE(username);
+ SAFE_FREE(netbios_domain);
+ SAFE_FREE(password);
+ TALLOC_FREE(frame);
+ return status;
+}
+
+static bool cm_is_ipc_credentials(struct cli_credentials *creds)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ char *ipc_account = NULL;
+ char *ipc_domain = NULL;
+ char *ipc_password = NULL;
+ const char *creds_account = NULL;
+ const char *creds_domain = NULL;
+ const char *creds_password = NULL;
+ bool ret = false;
+
+ cm_get_ipc_userpass(&ipc_account, &ipc_domain, &ipc_password);
+
+ creds_account = cli_credentials_get_username(creds);
+ creds_domain = cli_credentials_get_domain(creds);
+ creds_password = cli_credentials_get_password(creds);
+
+ if (!strequal(ipc_domain, creds_domain)) {
+ goto done;
+ }
+
+ if (!strequal(ipc_account, creds_account)) {
+ goto done;
+ }
+
+ if (!strcsequal(ipc_password, creds_password)) {
+ goto done;
+ }
+
+ ret = true;
+ done:
+ SAFE_FREE(ipc_account);
+ SAFE_FREE(ipc_domain);
+ SAFE_FREE(ipc_password);
+ TALLOC_FREE(frame);
+ return ret;
+}
+
static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
fstring dcname,
struct sockaddr_storage *dc_ss)
/**
* Helper function to assemble trust password and account name
*/
-static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
- char **machine_password,
- char **machine_account,
- char **machine_krb5_principal)
+static NTSTATUS get_trust_credentials(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ bool netlogon,
+ struct cli_credentials **_creds)
{
- const char *account_name;
- const char *name = NULL;
+ const struct winbindd_domain *creds_domain = NULL;
+ struct cli_credentials *creds;
+ NTSTATUS status;
/* If we are a DC and this is not our own domain */
- if (IS_DC) {
- name = domain->name;
+ if (IS_DC && netlogon) {
+ creds_domain = domain;
} else {
- struct winbindd_domain *our_domain = find_our_domain();
-
- if (!our_domain)
- return NT_STATUS_INVALID_SERVER_STATE;
-
- name = our_domain->name;
- }
-
- if (!get_trust_pw_clear(name, machine_password,
- &account_name, NULL))
- {
- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ creds_domain = find_our_domain();
+ if (creds_domain == NULL) {
+ return NT_STATUS_INVALID_SERVER_STATE;
+ }
}
- if ((machine_account != NULL) &&
- (asprintf(machine_account, "%s$", account_name) == -1))
- {
- return NT_STATUS_NO_MEMORY;
+ status = pdb_get_trust_credentials(creds_domain->name,
+ creds_domain->alt_name,
+ mem_ctx,
+ &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto ipc_fallback;
}
- /* For now assume our machine account only exists in our domain */
+ if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
+ cli_credentials_set_kerberos_state(creds,
+ CRED_MUST_USE_KERBEROS);
+ }
- if (machine_krb5_principal != NULL)
- {
- struct winbindd_domain *our_domain = find_our_domain();
+ if (domain->primary && lp_security() == SEC_ADS) {
+ cli_credentials_set_kerberos_state(creds,
+ CRED_AUTO_USE_KERBEROS);
+ } else if (!domain->active_directory) {
+ cli_credentials_set_kerberos_state(creds,
+ CRED_DONT_USE_KERBEROS);
+ }
- if (!our_domain) {
- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- }
+ if (creds_domain != domain) {
+ /*
+ * We can only use schannel against a direct trust
+ */
+ cli_credentials_set_secure_channel_type(creds,
+ SEC_CHAN_NULL);
+ }
- if (our_domain->alt_name == NULL) {
- return NT_STATUS_INVALID_PARAMETER;
- }
+ *_creds = creds;
+ return NT_STATUS_OK;
- if (asprintf(machine_krb5_principal, "%s$@%s",
- account_name, our_domain->alt_name) == -1)
- {
- return NT_STATUS_NO_MEMORY;
- }
+ ipc_fallback:
+ if (netlogon) {
+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ }
- if (!strupper_m(*machine_krb5_principal)) {
- SAFE_FREE(*machine_krb5_principal);
- return NT_STATUS_INVALID_PARAMETER;
- }
+ status = cm_get_ipc_credentials(mem_ctx, &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
+ *_creds = creds;
return NT_STATUS_OK;
}
to the pipe.
************************************************************************/
-static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
+static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
const int sockfd,
const char *controller,
struct cli_state **cli,
bool *retry)
{
- bool try_spnego = false;
bool try_ipc_auth = false;
- char *machine_password = NULL;
- char *machine_krb5_principal = NULL;
- char *machine_account = NULL;
- char *ipc_username = NULL;
- char *ipc_domain = NULL;
- char *ipc_password = NULL;
+ const char *machine_password = NULL;
+ const char *machine_krb5_principal = NULL;
+ const char *machine_account = NULL;
+ const char *machine_domain = NULL;
int flags = 0;
- uint16_t sec_mode = 0;
+ struct cli_credentials *creds = NULL;
+ enum credentials_use_kerberos krb5_state;
struct named_mutex *mutex;
result = smbXcli_negprot((*cli)->conn, (*cli)->timeout,
lp_client_min_protocol(),
- lp_client_max_protocol());
+ lp_winbindd_max_protocol());
if (!NT_STATUS_IS_OK(result)) {
DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_NT1 &&
smb1cli_conn_capabilities((*cli)->conn) & CAP_EXTENDED_SECURITY) {
- try_spnego = true;
+ try_ipc_auth = true;
} else if (smbXcli_conn_protocol((*cli)->conn) >= PROTOCOL_SMB2_02) {
- try_spnego = true;
+ try_ipc_auth = true;
+ } else if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
+ /*
+ * If we are forcing on SMB signing, then we must
+ * require authentication unless this is a one-way
+ * trust, and we have no stored user/password
+ */
+ try_ipc_auth = true;
}
- if (!is_dc_trusted_domain_situation(domain->name) && try_spnego) {
- result = get_trust_creds(domain, &machine_password,
- &machine_account,
- &machine_krb5_principal);
+ if (try_ipc_auth) {
+ result = get_trust_credentials(domain, talloc_tos(), false, &creds);
if (!NT_STATUS_IS_OK(result)) {
- goto anon_fallback;
+ DEBUG(1, ("get_trust_credentials(%s) failed: %s\n",
+ domain->name, nt_errstr(result)));
+ goto done;
+ }
+ } else {
+ /*
+ * Without SPNEGO or NTLMSSP (perhaps via SMB2) we
+ * would try and authentication with our machine
+ * account password and fail. This is very rare in
+ * the modern world however
+ */
+ creds = cli_credentials_init_anon(talloc_tos());
+ if (creds == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ DEBUG(1, ("cli_credentials_init_anon(%s) failed: %s\n",
+ domain->name, nt_errstr(result)));
+ goto done;
}
+ }
- if (lp_security() == SEC_ADS) {
+ krb5_state = cli_credentials_get_kerberos_state(creds);
- /* Try a krb5 session */
+ machine_krb5_principal = cli_credentials_get_principal(creds,
+ talloc_tos());
+ if (machine_krb5_principal == NULL) {
+ krb5_state = CRED_DONT_USE_KERBEROS;
+ }
- (*cli)->use_kerberos = True;
- DEBUG(5, ("connecting to %s from %s with kerberos principal "
- "[%s] and realm [%s]\n", controller, lp_netbios_name(),
- machine_krb5_principal, domain->alt_name));
+ machine_account = cli_credentials_get_username(creds);
+ machine_password = cli_credentials_get_password(creds);
+ machine_domain = cli_credentials_get_domain(creds);
- winbindd_set_locator_kdc_envs(domain);
+ if (krb5_state != CRED_DONT_USE_KERBEROS) {
- result = cli_session_setup(*cli,
- machine_krb5_principal,
- machine_password,
- strlen(machine_password)+1,
- machine_password,
- strlen(machine_password)+1,
- lp_workgroup());
+ /* Try a krb5 session */
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(4,("failed kerberos session setup with %s\n",
- nt_errstr(result)));
- }
+ (*cli)->use_kerberos = True;
+ DEBUG(5, ("connecting to %s from %s with kerberos principal "
+ "[%s] and realm [%s]\n", controller, lp_netbios_name(),
+ machine_krb5_principal, domain->alt_name));
- if (NT_STATUS_IS_OK(result)) {
- /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
- result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
- goto session_setup_done;
- }
+ winbindd_set_locator_kdc_envs(domain);
+
+ result = cli_session_setup(*cli,
+ machine_krb5_principal,
+ machine_password,
+ strlen(machine_password)+1,
+ machine_password,
+ strlen(machine_password)+1,
+ machine_domain);
+
+ if (NT_STATUS_IS_OK(result)) {
+ goto session_setup_done;
}
+ DEBUG(4,("failed kerberos session setup with %s\n",
+ nt_errstr(result)));
+ }
+
+ if (krb5_state != CRED_MUST_USE_KERBEROS) {
/* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
(*cli)->use_kerberos = False;
- DEBUG(5, ("connecting to %s from %s with username "
+ DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
"[%s]\\[%s]\n", controller, lp_netbios_name(),
- lp_workgroup(), machine_account));
+ machine_domain, machine_account));
result = cli_session_setup(*cli,
machine_account,
strlen(machine_password)+1,
machine_password,
strlen(machine_password)+1,
- lp_workgroup());
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(4, ("authenticated session setup failed with %s\n",
- nt_errstr(result)));
+ machine_domain);
+ }
+
+ if (NT_STATUS_IS_OK(result)) {
+ goto session_setup_done;
+ }
+
+ /*
+ * If we are not going to validiate the conneciton
+ * with SMB signing, then allow us to fall back to
+ * anonymous
+ */
+ if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
+ || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
+ || NT_STATUS_EQUAL(result, NT_STATUS_INVALID_ACCOUNT_NAME)
+ || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
+ {
+ if (cli_credentials_is_anonymous(creds)) {
+ goto done;
}
- if (NT_STATUS_IS_OK(result)) {
- /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
- result = cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
- goto session_setup_done;
+ if (!cm_is_ipc_credentials(creds)) {
+ goto ipc_fallback;
+ }
+
+ if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
+ goto done;
}
+
+ goto anon_fallback;
+ }
+
+ DEBUG(4, ("authenticated session setup failed with %s\n",
+ nt_errstr(result)));
+
+ goto done;
+
+ ipc_fallback:
+ result = cm_get_ipc_credentials(talloc_tos(), &creds);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ if (cli_credentials_is_anonymous(creds)) {
+ TALLOC_FREE(creds);
+ goto anon_fallback;
}
- /* Fall back to non-kerberos session setup with auth_user */
+ machine_account = cli_credentials_get_username(creds);
+ machine_password = cli_credentials_get_password(creds);
+ machine_domain = cli_credentials_get_domain(creds);
+ /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the ipc creds. */
(*cli)->use_kerberos = False;
- cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
+ DEBUG(5, ("connecting to %s from %s using NTLMSSP with username "
+ "[%s]\\[%s]\n", controller, lp_netbios_name(),
+ machine_domain, machine_account));
- sec_mode = smb1cli_conn_server_security_mode((*cli)->conn);
+ result = cli_session_setup(*cli,
+ machine_account,
+ machine_password,
+ strlen(machine_password)+1,
+ machine_password,
+ strlen(machine_password)+1,
+ machine_domain);
- try_ipc_auth = false;
- if (try_spnego) {
- try_ipc_auth = true;
- } else if (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
- try_ipc_auth = true;
+ if (NT_STATUS_IS_OK(result)) {
+ goto session_setup_done;
}
- if (try_ipc_auth && (strlen(ipc_username) > 0)) {
+ /*
+ * If we are not going to validiate the conneciton
+ * with SMB signing, then allow us to fall back to
+ * anonymous
+ */
+ if (NT_STATUS_EQUAL(result, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
+ || NT_STATUS_EQUAL(result, NT_STATUS_TRUSTED_DOMAIN_FAILURE)
+ || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
+ {
+ goto anon_fallback;
+ }
- /* Only try authenticated if we have a username */
+ DEBUG(4, ("authenticated session setup failed with %s\n",
+ nt_errstr(result)));
- DEBUG(5, ("connecting to %s from %s with username "
- "[%s]\\[%s]\n", controller, lp_netbios_name(),
- ipc_domain, ipc_username));
-
- if (NT_STATUS_IS_OK(cli_session_setup(
- *cli, ipc_username,
- ipc_password, strlen(ipc_password)+1,
- ipc_password, strlen(ipc_password)+1,
- ipc_domain))) {
- /* Successful logon with given username. */
- result = cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
- goto session_setup_done;
- } else {
- DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
- ipc_domain, ipc_username ));
- }
- }
+ goto done;
anon_fallback:
+ if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
+ goto done;
+ }
+
/* Fall back to anonymous connection, this might fail later */
DEBUG(10,("cm_prepare_connection: falling back to anonymous "
"connection for DC %s\n",
controller ));
- result = cli_session_setup(*cli, "", NULL, 0, NULL, 0, "");
+ (*cli)->use_kerberos = False;
+
+ result = cli_session_setup(*cli, "", "", 0, "", 0, "");
if (NT_STATUS_IS_OK(result)) {
DEBUG(5, ("Connected anonymously\n"));
- result = cli_init_creds(*cli, "", "", "");
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
goto session_setup_done;
}
smbXcli_session_set_disconnect_expired((*cli)->smb2.session);
}
+ result = cli_tree_connect(*cli, "IPC$", "IPC", "", 0);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
+ goto done;
+ }
+
/* cache the server name for later connections */
saf_store(domain->name, controller);
winbindd_set_locator_kdc_envs(domain);
- result = cli_tree_connect(*cli, "IPC$", "IPC", "", 0);
-
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
- goto done;
- }
-
TALLOC_FREE(mutex);
*retry = False;
- /* set the domain if empty; needed for schannel connections */
- if ( !(*cli)->domain[0] ) {
- result = cli_set_domain((*cli), domain->name);
- if (!NT_STATUS_IS_OK(result)) {
- SAFE_FREE(ipc_username);
- SAFE_FREE(ipc_domain);
- SAFE_FREE(ipc_password);
- return result;
- }
- }
-
result = NT_STATUS_OK;
done:
TALLOC_FREE(mutex);
- SAFE_FREE(machine_account);
- SAFE_FREE(machine_password);
- SAFE_FREE(machine_krb5_principal);
- SAFE_FREE(ipc_username);
- SAFE_FREE(ipc_domain);
- SAFE_FREE(ipc_password);
if (!NT_STATUS_IS_OK(result)) {
winbind_add_failed_connection_entry(domain, controller, result);
int num_dcs = 0;
const char **dcnames = NULL;
- int num_dcnames = 0;
+ size_t num_dcnames = 0;
struct sockaddr_storage *addrs = NULL;
int num_addrs = 0;
/* Close down all open pipes on a connection. */
-void invalidate_cm_connection(struct winbindd_cm_conn *conn)
+void invalidate_cm_connection(struct winbindd_domain *domain)
{
NTSTATUS result;
+ struct winbindd_cm_conn *conn = &domain->conn;
/* We're closing down a possibly dead
connection. Don't have impossibly long (10s) timeouts. */
smbXcli_conn_disconnect(domain->conn.cli->conn, NT_STATUS_OK);
}
- invalidate_cm_connection(&domain->conn);
+ invalidate_cm_connection(domain);
}
for (cli_state = winbindd_client_list();
return NT_STATUS_OK;
}
- invalidate_cm_connection(&domain->conn);
+ invalidate_cm_connection(domain);
if (!domain->primary && !domain->initialized) {
/*
struct winbindd_cm_conn *conn;
NTSTATUS status, result;
struct netlogon_creds_cli_context *p_creds;
- char *machine_password = NULL;
- char *machine_account = NULL;
- const char *domain_name = NULL;
+ struct cli_credentials *creds = NULL;
if (sid_check_is_our_sam(&domain->sid)) {
if (domain->rodc == false || need_rw_dc == false) {
* anonymous.
*/
- if ((conn->cli->user_name[0] == '\0') ||
- (conn->cli->domain[0] == '\0') ||
- (conn->cli->password == NULL || conn->cli->password[0] == '\0'))
- {
- status = get_trust_creds(domain, &machine_password,
- &machine_account, NULL);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("cm_connect_sam: No no user available for "
- "domain %s, trying schannel\n", conn->cli->domain));
- goto schannel;
- }
- domain_name = domain->name;
- } else {
- machine_password = SMB_STRDUP(conn->cli->password);
- machine_account = SMB_STRDUP(conn->cli->user_name);
- domain_name = conn->cli->domain;
+ result = get_trust_credentials(domain, talloc_tos(), false, &creds);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10, ("cm_connect_sam: No no user available for "
+ "domain %s, trying schannel\n", domain->name));
+ goto schannel;
}
- if (!machine_password || !machine_account) {
- status = NT_STATUS_NO_MEMORY;
- goto done;
+ if (cli_credentials_is_anonymous(creds)) {
+ goto anonymous;
}
- /* We have an authenticated connection. Use a NTLMSSP SPNEGO
- authenticated SAMR pipe with sign & seal. */
- status = cli_rpc_pipe_open_spnego(conn->cli,
- &ndr_table_samr,
- NCACN_NP,
- GENSEC_OID_NTLMSSP,
- conn->auth_level,
- smbXcli_conn_remote_name(conn->cli->conn),
- domain_name,
- machine_account,
- machine_password,
- &conn->samr_pipe);
-
+ /*
+ * We have an authenticated connection. Use a SPNEGO
+ * authenticated SAMR pipe with sign & seal.
+ */
+ status = cli_rpc_pipe_open_with_creds(conn->cli,
+ &ndr_table_samr,
+ NCACN_NP,
+ DCERPC_AUTH_TYPE_SPNEGO,
+ conn->auth_level,
+ smbXcli_conn_remote_name(conn->cli->conn),
+ creds,
+ &conn->samr_pipe);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
"pipe for domain %s using NTLMSSP "
- "authenticated pipe: user %s\\%s. Error was "
- "%s\n", domain->name, domain_name,
- machine_account, nt_errstr(status)));
+ "authenticated pipe: user %s. Error was "
+ "%s\n", domain->name,
+ cli_credentials_get_unparsed_name(creds, talloc_tos()),
+ nt_errstr(status)));
goto schannel;
}
DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
"domain %s using NTLMSSP authenticated "
- "pipe: user %s\\%s\n", domain->name,
- domain_name, machine_account));
+ "pipe: user %s\n", domain->name,
+ cli_credentials_get_unparsed_name(creds, talloc_tos())));
status = dcerpc_samr_Connect2(conn->samr_pipe->binding_handle, mem_ctx,
conn->samr_pipe->desthost,
ZERO_STRUCT(conn->sam_domain_handle);
return status;
} else if (!NT_STATUS_IS_OK(status)) {
- invalidate_cm_connection(conn);
+ invalidate_cm_connection(domain);
return status;
}
*cli = conn->samr_pipe;
*sam_handle = conn->sam_domain_handle;
- SAFE_FREE(machine_password);
- SAFE_FREE(machine_account);
return status;
}
struct winbindd_cm_conn *conn;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
struct netlogon_creds_cli_context *p_creds;
+ struct cli_credentials *creds = NULL;
result = init_dc_connection_rpc(domain, false);
if (!NT_STATUS_IS_OK(result))
TALLOC_FREE(conn->lsa_pipe);
- if ((conn->cli->user_name[0] == '\0') ||
- (conn->cli->domain[0] == '\0') ||
- (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
- DEBUG(10, ("cm_connect_lsa: No no user available for "
- "domain %s, trying schannel\n", conn->cli->domain));
+ result = get_trust_credentials(domain, talloc_tos(), false, &creds);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10, ("cm_connect_sam: No no user available for "
+ "domain %s, trying schannel\n", domain->name));
goto schannel;
}
- /* We have an authenticated connection. Use a NTLMSSP SPNEGO
- * authenticated LSA pipe with sign & seal. */
- result = cli_rpc_pipe_open_spnego
+ if (cli_credentials_is_anonymous(creds)) {
+ goto anonymous;
+ }
+
+ /*
+ * We have an authenticated connection. Use a SPNEGO
+ * authenticated LSA pipe with sign & seal.
+ */
+ result = cli_rpc_pipe_open_with_creds
(conn->cli, &ndr_table_lsarpc, NCACN_NP,
- GENSEC_OID_NTLMSSP,
+ DCERPC_AUTH_TYPE_SPNEGO,
conn->auth_level,
smbXcli_conn_remote_name(conn->cli->conn),
- conn->cli->domain, conn->cli->user_name, conn->cli->password,
+ creds,
&conn->lsa_pipe);
-
if (!NT_STATUS_IS_OK(result)) {
DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
"domain %s using NTLMSSP authenticated pipe: user "
- "%s\\%s. Error was %s. Trying schannel.\n",
- domain->name, conn->cli->domain,
- conn->cli->user_name, nt_errstr(result)));
+ "%s. Error was %s. Trying schannel.\n",
+ domain->name,
+ cli_credentials_get_unparsed_name(creds, talloc_tos()),
+ nt_errstr(result)));
goto schannel;
}
DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
- "NTLMSSP authenticated pipe: user %s\\%s\n",
- domain->name, conn->cli->domain, conn->cli->user_name ));
+ "NTLMSSP authenticated pipe: user %s\n",
+ domain->name, cli_credentials_get_unparsed_name(creds, talloc_tos())));
result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
SEC_FLAG_MAXIMUM_ALLOWED,
&conn->lsa_policy);
done:
if (!NT_STATUS_IS_OK(result)) {
- invalidate_cm_connection(conn);
+ invalidate_cm_connection(domain);
return result;
}
if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
- invalidate_cm_connection(&domain->conn);
+ invalidate_cm_connection(domain);
status = cm_connect_lsa_tcp(domain, mem_ctx, cli);
}
if (NT_STATUS_IS_OK(status)) {
* we tried twice to connect via ncan_ip_tcp and schannel and
* failed - maybe it is a trusted domain we can't connect to ?
* do not try tcp next time - gd
+ *
+ * This also prevents NETLOGON over TCP
*/
domain->can_do_ncacn_ip_tcp = false;
}
session key stored in conn->netlogon_pipe->dc->sess_key.
****************************************************************************/
-NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
- struct rpc_pipe_client **cli)
+static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
+ enum dcerpc_transport_t transport,
+ struct rpc_pipe_client **cli)
{
struct messaging_context *msg_ctx = winbind_messaging_context();
struct winbindd_cm_conn *conn;
NTSTATUS result;
enum netr_SchannelType sec_chan_type;
- const char *_account_name;
const char *account_name;
- struct samr_Password current_nt_hash;
- struct samr_Password *previous_nt_hash = NULL;
- struct netlogon_creds_CredentialState *creds = NULL;
- bool ok;
+ const char *domain_name;
+ const struct samr_Password *current_nt_hash = NULL;
+ const struct samr_Password *previous_nt_hash = NULL;
+ struct netlogon_creds_CredentialState *netlogon_creds = NULL;
+ struct cli_credentials *creds = NULL;
*cli = NULL;
conn->netlogon_flags = 0;
TALLOC_FREE(conn->netlogon_creds);
- if ((!IS_DC) && (!domain->primary)) {
- goto no_schannel;
+ result = get_trust_credentials(domain, talloc_tos(), true, &creds);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10, ("cm_connect_sam: No no user available for "
+ "domain %s when trying schannel\n", domain->name));
+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
- ok = get_trust_pw_hash(domain->name,
- current_nt_hash.hash,
- &_account_name,
- &sec_chan_type);
- if (!ok) {
- DEBUG(1, ("get_trust_pw_hash failed for %s, "
- "unable to get NETLOGON credentials\n",
+ if (cli_credentials_is_anonymous(creds)) {
+ DEBUG(1, ("get_trust_credential only gave anonymous for %s, unable to make get NETLOGON credentials\n",
domain->name));
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
- account_name = talloc_asprintf(talloc_tos(), "%s$", _account_name);
- if (account_name == NULL) {
+ sec_chan_type = cli_credentials_get_secure_channel_type(creds);
+ if (sec_chan_type == SEC_CHAN_NULL) {
+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ goto no_schannel;
+ }
+
+ account_name = cli_credentials_get_username(creds);
+ domain_name = cli_credentials_get_domain(creds);
+ current_nt_hash = cli_credentials_get_nt_hash(creds, talloc_tos());
+ if (current_nt_hash == NULL) {
return NT_STATUS_NO_MEMORY;
}
result = rpccli_create_netlogon_creds(domain->dcname,
- domain->name,
+ domain_name,
account_name,
sec_chan_type,
msg_ctx,
DEBUG(1, ("rpccli_create_netlogon_creds failed for %s, "
"unable to create NETLOGON credentials: %s\n",
domain->name, nt_errstr(result)));
- SAFE_FREE(previous_nt_hash);
return result;
}
- result = rpccli_setup_netlogon_creds(conn->cli,
+ result = rpccli_setup_netlogon_creds(conn->cli, transport,
conn->netlogon_creds,
conn->netlogon_force_reauth,
- current_nt_hash,
+ *current_nt_hash,
previous_nt_hash);
conn->netlogon_force_reauth = false;
- SAFE_FREE(previous_nt_hash);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(1, ("rpccli_setup_netlogon_creds failed for %s, "
"unable to setup NETLOGON credentials: %s\n",
result = netlogon_creds_cli_get(conn->netlogon_creds,
talloc_tos(),
- &creds);
+ &netlogon_creds);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(1, ("netlogon_creds_cli_get failed for %s, "
"unable to get NETLOGON credentials: %s\n",
domain->name, nt_errstr(result)));
return result;
}
- conn->netlogon_flags = creds->negotiate_flags;
- TALLOC_FREE(creds);
+ conn->netlogon_flags = netlogon_creds->negotiate_flags;
+ TALLOC_FREE(netlogon_creds);
no_schannel:
if (!(conn->netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
"must set 'winbind sealed pipes = false' and "
"'require strong key = false' to proceed: %s\n",
domain->name, nt_errstr(result)));
- invalidate_cm_connection(conn);
+ invalidate_cm_connection(domain);
return result;
}
- result = cli_rpc_pipe_open_noauth(conn->cli,
- &ndr_table_netlogon,
- &conn->netlogon_pipe);
+ result = cli_rpc_pipe_open_noauth_transport(conn->cli,
+ transport,
+ &ndr_table_netlogon,
+ &conn->netlogon_pipe);
if (!NT_STATUS_IS_OK(result)) {
- invalidate_cm_connection(conn);
+ invalidate_cm_connection(domain);
return result;
}
*/
result = cli_rpc_pipe_open_schannel_with_key(
- conn->cli, &ndr_table_netlogon, NCACN_NP,
+ conn->cli, &ndr_table_netlogon, transport,
domain->name,
conn->netlogon_creds,
&conn->netlogon_pipe);
DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
"was %s\n", nt_errstr(result)));
- invalidate_cm_connection(conn);
+ invalidate_cm_connection(domain);
return result;
}
return NT_STATUS_OK;
}
+/****************************************************************************
+Open a LSA connection to a DC, suiteable for LSA lookup calls.
+****************************************************************************/
+
+NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
+ struct rpc_pipe_client **cli)
+{
+ NTSTATUS status;
+
+ if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
+ status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
+ NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
+ NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
+ invalidate_cm_connection(domain);
+ status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
+ }
+ if (NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /*
+ * we tried twice to connect via ncan_ip_tcp and schannel and
+ * failed - maybe it is a trusted domain we can't connect to ?
+ * do not try tcp next time - gd
+ *
+ * This also prevents LSA over TCP
+ */
+ domain->can_do_ncacn_ip_tcp = false;
+ }
+
+ status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
+
+ return status;
+}
+
void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
void *private_data,
uint32_t msg_type,