libcli/smb_composite: for spnego session setups check the smb signature manually
authorStefan Metzmacher <metze@samba.org>
Tue, 9 Sep 2008 16:02:07 +0000 (18:02 +0200)
committerStefan Metzmacher <metze@samba.org>
Tue, 9 Sep 2008 19:11:25 +0000 (21:11 +0200)
This is needed as the response might be signed with the krb5 acceptor subkey,
which comes within the response.

metze

source/libcli/smb_composite/sesssetup.c

index 11ac37e257abbb668c539377291dd2a41ab9eae5..b39ff69b91ab3fc66e197c49137804fcd8fabd3c 100644 (file)
@@ -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;
 }