libcli/smb: don't overwrite status code
[vlendec/samba-autobuild/.git] / libcli / smb / smbXcli_base.c
index b7bf5796ba81470cd2756c55234e4d1fd960515c..40480c83aa05b62949b93bae543342f5716880d5 100644 (file)
@@ -161,6 +161,7 @@ struct smb2cli_session {
        uint64_t nonce_low;
        uint16_t channel_sequence;
        bool replay_active;
+       bool require_signed_response;
 };
 
 struct smbXcli_session {
@@ -289,6 +290,7 @@ struct smbXcli_req_state {
                uint64_t encryption_session_id;
 
                bool signing_skipped;
+               bool require_signed_response;
                bool notify_async;
                bool got_async;
                uint16_t cancel_flags;
@@ -1585,10 +1587,8 @@ struct tevent_req *smb1cli_req_create(TALLOC_CTX *mem_ctx,
        state->smb1.iov_count = iov_count + 4;
 
        if (timeout_msec > 0) {
-               struct timeval endtime;
-
-               endtime = timeval_current_ofs_msec(timeout_msec);
-               if (!tevent_req_set_endtime(req, ev, endtime)) {
+               state->endtime = timeval_current_ofs_msec(timeout_msec);
+               if (!tevent_req_set_endtime(req, ev, state->endtime)) {
                        return req;
                }
        }
@@ -2964,6 +2964,8 @@ struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx,
 
                state->smb2.should_sign = session->smb2->should_sign;
                state->smb2.should_encrypt = session->smb2->should_encrypt;
+               state->smb2.require_signed_response =
+                       session->smb2->require_signed_response;
 
                if (cmd == SMB2_OP_SESSSETUP &&
                    session->smb2_channel.signing_key.length == 0 &&
@@ -3051,10 +3053,8 @@ struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx,
        }
 
        if (timeout_msec > 0) {
-               struct timeval endtime;
-
-               endtime = timeval_current_ofs_msec(timeout_msec);
-               if (!tevent_req_set_endtime(req, ev, endtime)) {
+               state->endtime = timeval_current_ofs_msec(timeout_msec);
+               if (!tevent_req_set_endtime(req, ev, state->endtime)) {
                        return req;
                }
        }
@@ -3753,12 +3753,6 @@ static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
                }
                last_session = session;
 
-               if (state->smb2.should_sign) {
-                       if (!(flags & SMB2_HDR_FLAG_SIGNED)) {
-                               return NT_STATUS_ACCESS_DENIED;
-                       }
-               }
-
                if (flags & SMB2_HDR_FLAG_SIGNED) {
                        uint64_t uid = BVAL(inhdr, SMB2_HDR_SESSION_ID);
 
@@ -3805,6 +3799,27 @@ static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
                                 */
                                signing_key = NULL;
                        }
+
+                       if (!NT_STATUS_IS_OK(status)) {
+                               /*
+                                * Only check the signature of the last response
+                                * of a successfull session auth. This matches
+                                * Windows behaviour for NTLM auth and reauth.
+                                */
+                               state->smb2.require_signed_response = false;
+                       }
+               }
+
+               if (state->smb2.should_sign ||
+                   state->smb2.require_signed_response)
+               {
+                       if (!(flags & SMB2_HDR_FLAG_SIGNED)) {
+                               return NT_STATUS_ACCESS_DENIED;
+                       }
+               }
+
+               if (signing_key == NULL && state->smb2.require_signed_response) {
+                       signing_key = &session->smb2_channel.signing_key;
                }
 
                if (cur[0].iov_len == SMB2_TF_HDR_SIZE) {
@@ -3893,15 +3908,17 @@ static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
                }
 
                if (signing_key) {
-                       status = smb2_signing_check_pdu(*signing_key,
-                                                       state->conn->protocol,
-                                                       &cur[1], 3);
-                       if (!NT_STATUS_IS_OK(status)) {
+                       NTSTATUS signing_status;
+
+                       signing_status = smb2_signing_check_pdu(*signing_key,
+                                                               state->conn->protocol,
+                                                               &cur[1], 3);
+                       if (!NT_STATUS_IS_OK(signing_status)) {
                                /*
                                 * If the signing check fails, we disconnect
                                 * the connection.
                                 */
-                               return status;
+                               return signing_status;
                        }
                }
 
@@ -5723,6 +5740,12 @@ void smb2cli_session_stop_replay(struct smbXcli_session *session)
        session->smb2->replay_active = false;
 }
 
+void smb2cli_session_require_signed_response(struct smbXcli_session *session,
+                                            bool require_signed_response)
+{
+       session->smb2->require_signed_response = require_signed_response;
+}
+
 NTSTATUS smb2cli_session_update_preauth(struct smbXcli_session *session,
                                        const struct iovec *iov)
 {