diff options
Diffstat (limited to 'source3/libsmb/cliconnect.c')
-rw-r--r-- | source3/libsmb/cliconnect.c | 674 |
1 files changed, 371 insertions, 303 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 46d3da3fc45..039fba2c71b 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -26,7 +26,10 @@ #include "../libcli/auth/libcli_auth.h" #include "../libcli/auth/spnego.h" #include "smb_krb5.h" -#include "../auth/ntlmssp/ntlmssp.h" +#include "auth/credentials/credentials.h" +#include "auth/gensec/gensec.h" +#include "auth/ntlmssp/ntlmssp.h" +#include "auth_generic.h" #include "libads/kerberos_proto.h" #include "krb5_env.h" #include "../lib/util/tevent_ntstatus.h" @@ -1282,218 +1285,179 @@ static void use_in_memory_ccache(void) { setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1); } +#endif /* HAVE_KRB5 */ + /**************************************************************************** - Do a spnego/kerberos encrypted session setup. + Do a spnego/NTLMSSP encrypted session setup. ****************************************************************************/ -struct cli_session_setup_kerberos_state { +struct cli_session_setup_gensec_state { + struct tevent_context *ev; struct cli_state *cli; - DATA_BLOB negTokenTarg; - DATA_BLOB session_key_krb5; - ADS_STATUS ads_status; + struct auth_generic_state *auth_generic; + bool is_anonymous; + DATA_BLOB blob_in; + uint8_t *inbuf; + struct iovec *recv_iov; + DATA_BLOB blob_out; + bool local_ready; + bool remote_ready; + DATA_BLOB session_key; }; -static void cli_session_setup_kerberos_done(struct tevent_req *subreq); +static int cli_session_setup_gensec_state_destructor( + struct cli_session_setup_gensec_state *state) +{ + TALLOC_FREE(state->auth_generic); + data_blob_clear_free(&state->session_key); + return 0; +} -static struct tevent_req *cli_session_setup_kerberos_send( +static void cli_session_setup_gensec_local_next(struct tevent_req *req); +static void cli_session_setup_gensec_local_done(struct tevent_req *subreq); +static void cli_session_setup_gensec_remote_next(struct tevent_req *req); +static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq); +static void cli_session_setup_gensec_ready(struct tevent_req *req); + +static struct tevent_req *cli_session_setup_gensec_send( TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, - const char *principal) + const char *user, const char *pass, const char *domain, + enum credentials_use_kerberos krb5_state, + const char *target_service, + const char *target_hostname, + const char *target_principal) { - struct tevent_req *req, *subreq; - struct cli_session_setup_kerberos_state *state; - int rc; - - DEBUG(2,("Doing kerberos session setup\n")); + struct tevent_req *req; + struct cli_session_setup_gensec_state *state; + NTSTATUS status; + bool use_spnego_principal = lp_client_use_spnego_principal(); req = tevent_req_create(mem_ctx, &state, - struct cli_session_setup_kerberos_state); + struct cli_session_setup_gensec_state); if (req == NULL) { return NULL; } + state->ev = ev; state->cli = cli; - state->ads_status = ADS_SUCCESS; - /* - * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if - * we have to acquire a ticket. To be fixed later :-) - */ - rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg, - &state->session_key_krb5, 0, NULL, NULL); - if (rc) { - DEBUG(1, ("cli_session_setup_kerberos: " - "spnego_gen_krb5_negTokenInit failed: %s\n", - error_message(rc))); - state->ads_status = ADS_ERROR_KRB5(rc); - tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL); + talloc_set_destructor( + state, cli_session_setup_gensec_state_destructor); + + status = auth_generic_client_prepare(state, &state->auth_generic); + if (tevent_req_nterror(req, status)) { return tevent_req_post(req, ev); } -#if 0 - file_save("negTokenTarg.dat", state->negTokenTarg.data, - state->negTokenTarg.length); -#endif - - if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { - state->cli->smb2.session = smbXcli_session_create(cli, - cli->conn); - if (tevent_req_nomem(state->cli->smb2.session, req)) { - return tevent_req_post(req, ev); + gensec_want_feature(state->auth_generic->gensec_security, + GENSEC_FEATURE_SESSION_KEY); + if (cli->use_ccache) { + gensec_want_feature(state->auth_generic->gensec_security, + GENSEC_FEATURE_NTLM_CCACHE); + if (pass != NULL && strlen(pass) == 0) { + /* + * some callers pass "" as no password + * + * GENSEC_FEATURE_NTLM_CCACHE only handles + * NULL as no password. + */ + pass = NULL; } } - subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg); - if (tevent_req_nomem(subreq, req)) { + status = auth_generic_set_username(state->auth_generic, user); + if (tevent_req_nterror(req, status)) { return tevent_req_post(req, ev); } - tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req); - return req; -} -static void cli_session_setup_kerberos_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct cli_session_setup_kerberos_state *state = tevent_req_data( - req, struct cli_session_setup_kerberos_state); - uint8_t *inbuf = NULL; - struct iovec *recv_iov = NULL; - NTSTATUS status; - - status = cli_sesssetup_blob_recv(subreq, state, - NULL, &inbuf, &recv_iov); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - tevent_req_nterror(req, status); - return; + status = auth_generic_set_domain(state->auth_generic, domain); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); } - if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) { - struct smbXcli_session *session = state->cli->smb2.session; - status = smb2cli_session_set_session_key(session, - state->session_key_krb5, - recv_iov); - if (tevent_req_nterror(req, status)) { - return; + if (cli->pw_nt_hash) { + struct samr_Password nt_hash; + size_t converted; + bool ok; + + if (pass == NULL) { + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); + return tevent_req_post(req, ev); } - } else { - struct smbXcli_session *session = state->cli->smb1.session; - status = smb1cli_session_set_session_key(session, - state->session_key_krb5); - if (tevent_req_nterror(req, status)) { - return; + converted = strhex_to_str((char *)nt_hash.hash, + sizeof(nt_hash.hash), + pass, strlen(pass)); + if (converted != sizeof(nt_hash.hash)) { + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); + return tevent_req_post(req, ev); } - if (smb1cli_conn_activate_signing(state->cli->conn, state->session_key_krb5, - data_blob_null) - && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) { - tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); - return; + ok = cli_credentials_set_nt_hash(state->auth_generic->credentials, + &nt_hash, CRED_SPECIFIED); + if (!ok) { + tevent_req_oom(req); + return tevent_req_post(req, ev); + } + } else { + status = auth_generic_set_password(state->auth_generic, pass); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); } } - tevent_req_done(req); -} + cli_credentials_set_kerberos_state(state->auth_generic->credentials, + krb5_state); -static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req) -{ - struct cli_session_setup_kerberos_state *state = tevent_req_data( - req, struct cli_session_setup_kerberos_state); - NTSTATUS status; - - if (tevent_req_is_nterror(req, &status)) { - return ADS_ERROR_NT(status); + if (krb5_state == CRED_DONT_USE_KERBEROS) { + use_spnego_principal = false; } - return state->ads_status; -} - -#endif /* HAVE_KRB5 */ - -/**************************************************************************** - Do a spnego/NTLMSSP encrypted session setup. -****************************************************************************/ - -struct cli_session_setup_ntlmssp_state { - struct tevent_context *ev; - struct cli_state *cli; - struct ntlmssp_state *ntlmssp_state; - int turn; - DATA_BLOB blob_out; -}; -static int cli_session_setup_ntlmssp_state_destructor( - struct cli_session_setup_ntlmssp_state *state) -{ - if (state->ntlmssp_state != NULL) { - TALLOC_FREE(state->ntlmssp_state); + if (target_service != NULL) { + status = gensec_set_target_service( + state->auth_generic->gensec_security, + target_service); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } } - return 0; -} -static void cli_session_setup_ntlmssp_done(struct tevent_req *req); + if (target_hostname != NULL) { + status = gensec_set_target_hostname( + state->auth_generic->gensec_security, + target_hostname); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } + } -static struct tevent_req *cli_session_setup_ntlmssp_send( - TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, - const char *user, const char *pass, const char *domain) -{ - struct tevent_req *req, *subreq; - struct cli_session_setup_ntlmssp_state *state; - NTSTATUS status; - DATA_BLOB blob_out; - const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL}; + if (target_principal != NULL) { + status = gensec_set_target_principal( + state->auth_generic->gensec_security, + target_principal); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } + use_spnego_principal = false; + } else if (target_service != NULL && target_hostname != NULL) { + use_spnego_principal = false; + } - req = tevent_req_create(mem_ctx, &state, - struct cli_session_setup_ntlmssp_state); - if (req == NULL) { - return NULL; + if (use_spnego_principal) { + const DATA_BLOB *b; + b = smbXcli_conn_server_gss_blob(cli->conn); + if (b != NULL) { + state->blob_in = *b; + } } - state->ev = ev; - state->cli = cli; - state->turn = 1; - state->ntlmssp_state = NULL; - talloc_set_destructor( - state, cli_session_setup_ntlmssp_state_destructor); + state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials); - status = ntlmssp_client_start(state, - lp_netbios_name(), - lp_workgroup(), - lp_client_ntlmv2_auth(), - &state->ntlmssp_state); - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - ntlmssp_want_feature(state->ntlmssp_state, - NTLMSSP_FEATURE_SESSION_KEY); - if (cli->use_ccache) { - ntlmssp_want_feature(state->ntlmssp_state, - NTLMSSP_FEATURE_CCACHE); - } - status = ntlmssp_set_username(state->ntlmssp_state, user); - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - status = ntlmssp_set_domain(state->ntlmssp_state, domain); - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - if (cli->pw_nt_hash) { - status = ntlmssp_set_password_hash(state->ntlmssp_state, pass); - } else { - status = ntlmssp_set_password(state->ntlmssp_state, pass); - } - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - status = ntlmssp_update(state->ntlmssp_state, data_blob_null, - &blob_out); - if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - goto fail; + status = auth_generic_client_start(state->auth_generic, + GENSEC_OID_SPNEGO); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); } - state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL); - data_blob_free(&blob_out); - if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { state->cli->smb2.session = smbXcli_session_create(cli, cli->conn); @@ -1502,150 +1466,226 @@ static struct tevent_req *cli_session_setup_ntlmssp_send( } } - subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out); - if (tevent_req_nomem(subreq, req)) { + cli_session_setup_gensec_local_next(req); + if (!tevent_req_is_in_progress(req)) { return tevent_req_post(req, ev); } - tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req); + return req; -fail: - tevent_req_nterror(req, status); - return tevent_req_post(req, ev); } -static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq) +static void cli_session_setup_gensec_local_next(struct tevent_req *req) { - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct cli_session_setup_ntlmssp_state *state = tevent_req_data( - req, struct cli_session_setup_ntlmssp_state); - DATA_BLOB blob_in, msg_in, blob_out; - uint8_t *inbuf = NULL; - struct iovec *recv_iov = NULL; - bool parse_ret; + struct cli_session_setup_gensec_state *state = + tevent_req_data(req, + struct cli_session_setup_gensec_state); + struct tevent_req *subreq = NULL; + + if (state->local_ready) { + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } + + subreq = gensec_update_send(state, state->ev, + state->auth_generic->gensec_security, + state->blob_in); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req); +} + +static void cli_session_setup_gensec_local_done(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct cli_session_setup_gensec_state *state = + tevent_req_data(req, + struct cli_session_setup_gensec_state); NTSTATUS status; - status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in, - &inbuf, &recv_iov); + status = gensec_update_recv(subreq, state, &state->blob_out); TALLOC_FREE(subreq); - data_blob_free(&state->blob_out); + state->blob_in = data_blob_null; + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) + { + tevent_req_nterror(req, status); + return; + } if (NT_STATUS_IS_OK(status)) { - if (state->cli->server_domain[0] == '\0') { - TALLOC_FREE(state->cli->server_domain); - state->cli->server_domain = talloc_strdup(state->cli, - state->ntlmssp_state->server.netbios_domain); - if (state->cli->server_domain == NULL) { - tevent_req_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - } + state->local_ready = true; + } - if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) { - struct smbXcli_session *session = state->cli->smb2.session; + if (state->local_ready && state->remote_ready) { + cli_session_setup_gensec_ready(req); + return; + } - if (ntlmssp_is_anonymous(state->ntlmssp_state)) { - /* - * Windows server does not set the - * SMB2_SESSION_FLAG_IS_GUEST nor - * SMB2_SESSION_FLAG_IS_NULL flag. - * - * This fix makes sure we do not try - * to verify a signature on the final - * session setup response. - */ - TALLOC_FREE(state->ntlmssp_state); - tevent_req_done(req); - return; - } + cli_session_setup_gensec_remote_next(req); +} - status = smb2cli_session_set_session_key(session, - state->ntlmssp_state->session_key, - recv_iov); - if (tevent_req_nterror(req, status)) { - return; - } - } else { - struct smbXcli_session *session = state->cli->smb1.session; +static void cli_session_setup_gensec_remote_next(struct tevent_req *req) +{ + struct cli_session_setup_gensec_state *state = + tevent_req_data(req, + struct cli_session_setup_gensec_state); + struct tevent_req *subreq = NULL; - status = smb1cli_session_set_session_key(session, - state->ntlmssp_state->session_key); - if (tevent_req_nterror(req, status)) { - return; - } + if (state->remote_ready) { + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } - if (smb1cli_conn_activate_signing( - state->cli->conn, state->ntlmssp_state->session_key, - data_blob_null) - && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) { - tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); - return; - } - } - TALLOC_FREE(state->ntlmssp_state); - tevent_req_done(req); + subreq = cli_sesssetup_blob_send(state, state->ev, + state->cli, state->blob_out); + if (tevent_req_nomem(subreq, req)) { return; } - if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + tevent_req_set_callback(subreq, + cli_session_setup_gensec_remote_done, + req); +} + +static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct cli_session_setup_gensec_state *state = + tevent_req_data(req, + struct cli_session_setup_gensec_state); + NTSTATUS status; + + TALLOC_FREE(state->inbuf); + TALLOC_FREE(state->recv_iov); + + status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in, + &state->inbuf, &state->recv_iov); + TALLOC_FREE(subreq); + data_blob_free(&state->blob_out); + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) + { tevent_req_nterror(req, status); return; } - if (blob_in.length == 0) { - tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL); - return; + if (NT_STATUS_IS_OK(status)) { + state->remote_ready = true; } - if ((state->turn == 1) - && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - DATA_BLOB tmp_blob = data_blob_null; - /* the server might give us back two challenges */ - parse_ret = spnego_parse_challenge(state, blob_in, &msg_in, - &tmp_blob); - data_blob_free(&tmp_blob); - } else { - parse_ret = spnego_parse_auth_response(state, blob_in, status, - OID_NTLMSSP, &msg_in); - } - state->turn += 1; - - if (!parse_ret) { - DEBUG(3,("Failed to parse auth response\n")); - if (NT_STATUS_IS_OK(status) - || NT_STATUS_EQUAL(status, - NT_STATUS_MORE_PROCESSING_REQUIRED)) { - tevent_req_nterror( - req, NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } + if (state->local_ready && state->remote_ready) { + cli_session_setup_gensec_ready(req); + return; } - status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out); + cli_session_setup_gensec_local_next(req); +} - if (!NT_STATUS_IS_OK(status) - && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - TALLOC_FREE(state->ntlmssp_state); - tevent_req_nterror(req, status); +static void cli_session_setup_gensec_ready(struct tevent_req *req) +{ + struct cli_session_setup_gensec_state *state = + tevent_req_data(req, + struct cli_session_setup_gensec_state); + const char *server_domain = NULL; + NTSTATUS status; + + if (state->blob_in.length != 0) { + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } - state->blob_out = spnego_gen_auth(state, blob_out); - if (tevent_req_nomem(state->blob_out.data, req)) { + if (state->blob_out.length != 0) { + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } - subreq = cli_sesssetup_blob_send(state, state->ev, state->cli, - state->blob_out); - if (tevent_req_nomem(subreq, req)) { + /* + * gensec_ntlmssp_server_domain() returns NULL + * if NTLMSSP is not used. + * + * We can remove this later + * and leave the server domain empty for SMB2 and above + * in future releases. + */ + server_domain = gensec_ntlmssp_server_domain( + state->auth_generic->gensec_security); + + if (state->cli->server_domain[0] == '\0' && server_domain != NULL) { + TALLOC_FREE(state->cli->server_domain); + state->cli->server_domain = talloc_strdup(state->cli, + server_domain); + if (state->cli->server_domain == NULL) { + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + } + + status = gensec_session_key(state->auth_generic->gensec_security, + state, &state->session_key); + if (tevent_req_nterror(req, status)) { return; } - tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req); + + if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) { + struct smbXcli_session *session = state->cli->smb2.session; + + if (state->is_anonymous) { + /* + * Windows server does not set the + * SMB2_SESSION_FLAG_IS_GUEST nor + * SMB2_SESSION_FLAG_IS_NULL flag. + * + * This fix makes sure we do not try + * to verify a signature on the final + * session setup response. + */ + tevent_req_done(req); + return; + } + + status = smb2cli_session_set_session_key(session, + state->session_key, + state->recv_iov); + if (tevent_req_nterror(req, status)) { + return; + } + } else { + struct smbXcli_session *session = state->cli->smb1.session; + bool active; + + status = smb1cli_session_set_session_key(session, + state->session_key); + if (tevent_req_nterror(req, status)) { + return; + } + + active = smb1cli_conn_activate_signing(state->cli->conn, + state->session_key, + data_blob_null); + if (active) { + bool ok; + + ok = smb1cli_conn_check_signing(state->cli->conn, + state->inbuf, 1); + if (!ok) { + tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); + return; + } + } + } + + tevent_req_done(req); } -static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req) +static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req) { - struct cli_session_setup_ntlmssp_state *state = tevent_req_data( - req, struct cli_session_setup_ntlmssp_state); + struct cli_session_setup_gensec_state *state = + tevent_req_data(req, + struct cli_session_setup_gensec_state); NTSTATUS status; if (tevent_req_is_nterror(req, &status)) { @@ -1725,6 +1765,7 @@ static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx, struct cli_session_setup_spnego_state { struct tevent_context *ev; struct cli_state *cli; + const char *target_hostname; const char *user; const char *account; const char *pass; @@ -1741,14 +1782,14 @@ static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq); static struct tevent_req *cli_session_setup_spnego_send( TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, - const char *user, const char *pass, const char *user_domain, - const char *dest_realm) + const char *user, const char *pass, const char *user_domain) { struct tevent_req *req, *subreq; struct cli_session_setup_spnego_state *state; char *principal = NULL; char *OIDs[ASN1_MAX_OIDS]; int i; + const char *dest_realm = cli_state_remote_realm(cli); const DATA_BLOB *server_blob; NTSTATUS status; @@ -1769,6 +1810,7 @@ static struct tevent_req *cli_session_setup_spnego_send( return tevent_req_post(req, ev); } + state->target_hostname = smbXcli_conn_remote_name(cli->conn); server_blob = smbXcli_conn_server_gss_blob(cli->conn); DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", @@ -1823,9 +1865,13 @@ static struct tevent_req *cli_session_setup_spnego_send( * and do not store results */ if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) { - const char *remote_name = smbXcli_conn_remote_name(cli->conn); char *tmp; + tmp = cli_session_setup_get_principal( + talloc_tos(), principal, state->target_hostname, dest_realm); + TALLOC_FREE(principal); + principal = tmp; + if (pass && *pass) { int ret; @@ -1833,8 +1879,8 @@ static struct tevent_req *cli_session_setup_spnego_send( ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL); if (ret){ + DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret))); TALLOC_FREE(principal); - DEBUG(0, ("Kinit failed: %s\n", error_message(ret))); if (cli->fallback_after_kerberos) goto ntlmssp; state->result = ADS_ERROR_KRB5(ret); @@ -1843,14 +1889,12 @@ static struct tevent_req *cli_session_setup_spnego_send( } } - tmp = cli_session_setup_get_principal( - talloc_tos(), principal, remote_name, dest_realm); - TALLOC_FREE(principal); - principal = tmp; - if (principal) { - subreq = cli_session_setup_kerberos_send( - state, ev, cli, principal); + subreq = cli_session_setup_gensec_send( + state, ev, cli, + state->account, pass, user_domain, + CRED_MUST_USE_KERBEROS, + "cifs", state->target_hostname, principal); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -1863,8 +1907,11 @@ static struct tevent_req *cli_session_setup_spnego_send( #endif ntlmssp: - subreq = cli_session_setup_ntlmssp_send( - state, ev, cli, state->account, pass, user_domain); + subreq = cli_session_setup_gensec_send( + state, state->ev, state->cli, + state->account, state->pass, state->user_domain, + CRED_DONT_USE_KERBEROS, + "cifs", state->target_hostname, NULL); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -1880,9 +1927,11 @@ static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq) subreq, struct tevent_req); struct cli_session_setup_spnego_state *state = tevent_req_data( req, struct cli_session_setup_spnego_state); + NTSTATUS status; - state->result = cli_session_setup_kerberos_recv(subreq); + status = cli_session_setup_gensec_recv(subreq); TALLOC_FREE(subreq); + state->result = ADS_ERROR_NT(status); if (ADS_ERR_OK(state->result) || !state->cli->fallback_after_kerberos) { @@ -1890,9 +1939,11 @@ static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq) return; } - subreq = cli_session_setup_ntlmssp_send( - state, state->ev, state->cli, state->account, state->pass, - state->user_domain); + subreq = cli_session_setup_gensec_send( + state, state->ev, state->cli, + state->account, state->pass, state->user_domain, + CRED_DONT_USE_KERBEROS, + "cifs", state->target_hostname, NULL); if (tevent_req_nomem(subreq, req)) { return; } @@ -1909,7 +1960,7 @@ static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq) req, struct cli_session_setup_spnego_state); NTSTATUS status; - status = cli_session_setup_ntlmssp_recv(subreq); + status = cli_session_setup_gensec_recv(subreq); TALLOC_FREE(subreq); state->result = ADS_ERROR_NT(status); tevent_req_done(req); @@ -2023,10 +2074,8 @@ struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx, } if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { - const char *remote_realm = cli_state_remote_realm(cli); - subreq = cli_session_setup_spnego_send( - state, ev, cli, user, pass, workgroup, remote_realm); + state, ev, cli, user, pass, workgroup); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -2086,10 +2135,8 @@ struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx, /* if the server supports extended security then use SPNEGO */ if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) { - const char *remote_realm = cli_state_remote_realm(cli); - subreq = cli_session_setup_spnego_send( - state, ev, cli, user, pass, workgroup, remote_realm); + state, ev, cli, user, pass, workgroup); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -2098,6 +2145,17 @@ struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx, return req; } else { /* otherwise do a NT1 style session setup */ + if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) { + /* + * Don't send an NTLMv2 response without NTLMSSP + * if we want to use spnego support + */ + DEBUG(1, ("Server does not support EXTENDED_SECURITY " + " but 'client use spnego = yes" + " and 'client ntlmv2 auth = yes'\n")); + tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); + return tevent_req_post(req, ev); + } subreq = cli_session_setup_nt1_send( state, ev, cli, user, pass, passlen, ntpass, ntpasslen, @@ -2410,7 +2468,7 @@ struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx, * Non-encrypted passwords - convert to DOS codepage * before using. */ - tmp_pass = talloc_array(talloc_tos(), uint8, 0); + tmp_pass = talloc_array(talloc_tos(), uint8_t, 0); if (tevent_req_nomem(tmp_pass, req)) { return tevent_req_post(req, ev); } @@ -2637,7 +2695,7 @@ static struct tevent_req *cli_raw_tcon_send( TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, const char *service, const char *pass, const char *dev); static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req, - uint16 *max_xmit, uint16 *tid); + uint16_t *max_xmit, uint16_t *tid); static void cli_tree_connect_smb2_done(struct tevent_req *subreq); static void cli_tree_connect_andx_done(struct tevent_req *subreq); @@ -3120,6 +3178,8 @@ fail: struct cli_start_connection_state { struct tevent_context *ev; struct cli_state *cli; + int min_protocol; + int max_protocol; }; static void cli_start_connection_connected(struct tevent_req *subreq); @@ -3149,6 +3209,14 @@ static struct tevent_req *cli_start_connection_send( } state->ev = ev; + if (signing_state == SMB_SIGNING_IPC_DEFAULT) { + state->min_protocol = lp_client_ipc_min_protocol(); + state->max_protocol = lp_client_ipc_max_protocol(); + } else { + state->min_protocol = lp_client_min_protocol(); + state->max_protocol = lp_client_max_protocol(); + } + subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port, 0x20, my_name, signing_state, flags); if (tevent_req_nomem(subreq, req)) { @@ -3174,8 +3242,8 @@ static void cli_start_connection_connected(struct tevent_req *subreq) subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn, state->cli->timeout, - lp_client_min_protocol(), - lp_client_max_protocol()); + state->min_protocol, + state->max_protocol); if (tevent_req_nomem(subreq, req)) { return; } @@ -3543,7 +3611,7 @@ static void cli_raw_tcon_done(struct tevent_req *subreq) } static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req, - uint16 *max_xmit, uint16 *tid) + uint16_t *max_xmit, uint16_t *tid) { struct cli_raw_tcon_state *state = tevent_req_data( req, struct cli_raw_tcon_state); @@ -3559,7 +3627,7 @@ static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req, NTSTATUS cli_raw_tcon(struct cli_state *cli, const char *service, const char *pass, const char *dev, - uint16 *max_xmit, uint16 *tid) + uint16_t *max_xmit, uint16_t *tid) { struct tevent_context *ev; struct tevent_req *req; |