From: Stefan Metzmacher Date: Tue, 9 Sep 2008 16:02:07 +0000 (+0200) Subject: libcli/smb_composite: for spnego session setups check the smb signature manually X-Git-Url: http://git.samba.org/?p=metze%2Fsamba%2Fwip.git;a=commitdiff_plain;h=79ca1a29fd329df1de4f9b22d34aaab1806c5307 libcli/smb_composite: for spnego session setups check the smb signature manually This is needed as the response might be signed with the krb5 acceptor subkey, which comes within the response. metze --- diff --git a/source/libcli/smb_composite/sesssetup.c b/source/libcli/smb_composite/sesssetup.c index 11ac37e257ab..b39ff69b91ab 100644 --- a/source/libcli/smb_composite/sesssetup.c +++ b/source/libcli/smb_composite/sesssetup.c @@ -85,6 +85,12 @@ static void request_handler(struct smbcli_request *req) DATA_BLOB session_key = data_blob(NULL, 0); DATA_BLOB null_data_blob = data_blob(NULL, 0); NTSTATUS session_key_err, nt_status; + struct smbcli_request *check_req = NULL; + + if (req->sign_caller_checks) { + req->do_not_free = true; + check_req = req; + } c->status = smb_raw_sesssetup_recv(req, state, &state->setup); state->req = NULL; @@ -102,6 +108,7 @@ static void request_handler(struct smbcli_request *req) state->io, &state->req); if (NT_STATUS_IS_OK(nt_status)) { + talloc_free(check_req); c->status = nt_status; composite_continue_smb(c, state->req, request_handler, c); return; @@ -120,6 +127,7 @@ static void request_handler(struct smbcli_request *req) state->io, &state->req); if (NT_STATUS_IS_OK(nt_status)) { + talloc_free(check_req); c->status = nt_status; composite_continue_smb(c, state->req, request_handler, c); return; @@ -138,6 +146,7 @@ static void request_handler(struct smbcli_request *req) state->io, &state->req); if (NT_STATUS_IS_OK(nt_status)) { + talloc_free(check_req); c->status = nt_status; composite_continue_smb(c, state->req, request_handler, c); return; @@ -146,6 +155,7 @@ static void request_handler(struct smbcli_request *req) } if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(c->status)) { + talloc_free(check_req); break; } if (NT_STATUS_EQUAL(state->gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { @@ -163,6 +173,7 @@ static void request_handler(struct smbcli_request *req) c->status = state->gensec_status; if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(c->status)) { + talloc_free(check_req); break; } } else { @@ -178,6 +189,16 @@ static void request_handler(struct smbcli_request *req) } if (state->setup.spnego.in.secblob.length) { + if (check_req) { + check_req->sign_caller_checks = false; + if (!smbcli_request_check_sign_mac(check_req)) { + talloc_free(check_req); + c->status = NT_STATUS_ACCESS_DENIED; + break; + } + talloc_free(check_req); + } + /* * set the session->vuid value only for calling * smb_raw_sesssetup_send() @@ -196,6 +217,14 @@ static void request_handler(struct smbcli_request *req) break; } + if (check_req) { + check_req->sign_caller_checks = false; + if (!smbcli_request_check_sign_mac(check_req)) { + c->status = NT_STATUS_ACCESS_DENIED; + } + talloc_free(check_req); + } + /* enforce the local signing required flag */ if (NT_STATUS_IS_OK(c->status) && !cli_credentials_is_anonymous(state->io->in.credentials)) { if (!session->transport->negotiate.sign_info.doing_signing @@ -449,6 +478,15 @@ static NTSTATUS session_setup_spnego(struct composite_context *c, if (!*req) { return NT_STATUS_NO_MEMORY; } + + if (NT_STATUS_IS_OK(session_key_err)) { + /* + * as the response might be signed with a session key from within the response + * we need to check the signiture of the response ourself. + */ + (*req)->sign_caller_checks = true; + } + return (*req)->status; }