diff options
author | Stefan Metzmacher <metze@samba.org> | 2016-03-01 18:31:50 +0100 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2016-03-10 06:52:30 +0100 |
commit | 576257f6e1488a623306dc368c806e218b1fcdf2 (patch) | |
tree | 700a51a063bee76f41948493cb003b15d4e9c0de /source3/libsmb | |
parent | afffe797547a97ec839913e1ca89045989bbea49 (diff) | |
download | samba-576257f6e1488a623306dc368c806e218b1fcdf2.tar.gz |
s3:libsmb: let cli_session_setup_ntlmssp*() use gensec_update_send/recv()
This pares a fix for https://bugzilla.samba.org/show_bug.cgi?id=10288
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Günther Deschner <gd@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/cliconnect.c | 283 |
1 files changed, 191 insertions, 92 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index e71b8cb9ff2..9f75b897fe0 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -1420,7 +1420,11 @@ struct cli_session_setup_ntlmssp_state { 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; }; @@ -1432,13 +1436,17 @@ static int cli_session_setup_ntlmssp_state_destructor( return 0; } -static void cli_session_setup_ntlmssp_done(struct tevent_req *req); +static void cli_session_setup_ntlmssp_local_next(struct tevent_req *req); +static void cli_session_setup_ntlmssp_local_done(struct tevent_req *subreq); +static void cli_session_setup_ntlmssp_remote_next(struct tevent_req *req); +static void cli_session_setup_ntlmssp_remote_done(struct tevent_req *subreq); +static void cli_session_setup_ntlmssp_ready(struct tevent_req *req); 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 tevent_req *req; struct cli_session_setup_ntlmssp_state *state; NTSTATUS status; @@ -1521,13 +1529,6 @@ static struct tevent_req *cli_session_setup_ntlmssp_send( return tevent_req_post(req, ev); } - status = gensec_update(state->auth_generic->gensec_security, - state, state->blob_in, &state->blob_out); - if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - tevent_req_nterror(req, status); - return tevent_req_post(req, ev); - } - if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { state->cli->smb2.session = smbXcli_session_create(cli, cli->conn); @@ -1536,125 +1537,223 @@ 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_ntlmssp_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; } -static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq) +static void cli_session_setup_ntlmssp_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); - uint8_t *inbuf = NULL; - struct iovec *recv_iov = NULL; + struct cli_session_setup_ntlmssp_state *state = + tevent_req_data(req, + struct cli_session_setup_ntlmssp_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_ntlmssp_local_done, req); +} + +static void cli_session_setup_ntlmssp_local_done(struct tevent_req *subreq) +{ + 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); NTSTATUS status; - status = cli_sesssetup_blob_recv(subreq, state, &state->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)) { - const char *server_domain = NULL; + state->local_ready = true; + } - server_domain = gensec_ntlmssp_server_domain( - state->auth_generic->gensec_security); + if (state->local_ready && state->remote_ready) { + cli_session_setup_ntlmssp_ready(req); + return; + } - 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; - } - } + cli_session_setup_ntlmssp_remote_next(req); +} - status = gensec_session_key(state->auth_generic->gensec_security, - state, &state->session_key); - if (tevent_req_nterror(req, status)) { - return; - } +static void cli_session_setup_ntlmssp_remote_next(struct tevent_req *req) +{ + struct cli_session_setup_ntlmssp_state *state = + tevent_req_data(req, + struct cli_session_setup_ntlmssp_state); + struct tevent_req *subreq = NULL; - if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) { - struct smbXcli_session *session = state->cli->smb2.session; + if (state->remote_ready) { + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } - 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; - } + subreq = cli_sesssetup_blob_send(state, state->ev, + state->cli, state->blob_out); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, + cli_session_setup_ntlmssp_remote_done, + req); +} - status = smb2cli_session_set_session_key(session, - 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_ntlmssp_remote_done(struct tevent_req *subreq) +{ + 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); + NTSTATUS status; - status = smb1cli_session_set_session_key(session, - state->session_key); - if (tevent_req_nterror(req, status)) { - return; - } + TALLOC_FREE(state->inbuf); + TALLOC_FREE(state->recv_iov); - if (smb1cli_conn_activate_signing( - state->cli->conn, state->session_key, - data_blob_null) - && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) { - tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); - return; - } - } - tevent_req_done(req); + 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 (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - tevent_req_nterror(req, status); + + if (NT_STATUS_IS_OK(status)) { + state->remote_ready = true; + } + + if (state->local_ready && state->remote_ready) { + cli_session_setup_ntlmssp_ready(req); return; } - if (state->blob_in.length == 0) { - tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL); + cli_session_setup_ntlmssp_local_next(req); +} + +static void cli_session_setup_ntlmssp_ready(struct tevent_req *req) +{ + struct cli_session_setup_ntlmssp_state *state = + tevent_req_data(req, + struct cli_session_setup_ntlmssp_state); + const char *server_domain = NULL; + NTSTATUS status; + + if (state->blob_in.length != 0) { + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } - status = gensec_update(state->auth_generic->gensec_security, - state, state->blob_in, &state->blob_out); - data_blob_free(&state->blob_in); - if (!NT_STATUS_IS_OK(status) - && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - tevent_req_nterror(req, status); + 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)) { + /* + * 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) { - struct cli_session_setup_ntlmssp_state *state = tevent_req_data( - req, struct cli_session_setup_ntlmssp_state); + struct cli_session_setup_ntlmssp_state *state = + tevent_req_data(req, + struct cli_session_setup_ntlmssp_state); NTSTATUS status; if (tevent_req_is_nterror(req, &status)) { |