r1521: Updates to our SMB signing code.
authorAndrew Bartlett <abartlet@samba.org>
Fri, 16 Jul 2004 02:54:57 +0000 (02:54 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:57:39 +0000 (12:57 -0500)
- This causes our client and server code to use the same core code,
  with the same debugs etc.
- In turn, this will allow the 'mandetory/fallback' signing algorithms
  to be shared, and only written once.

Updates to the SPNEGO code
- Don't wrap an empty token to the server, if we are actually already finished.

Andrew Bartlett
(This used to be commit 35b83eb329482ac1b3bc67285854cc47844ff353)

source4/include/cli_context.h
source4/include/includes.h
source4/libcli/auth/gensec_krb5.c
source4/libcli/auth/spnego.c
source4/libcli/raw/clisession.c
source4/libcli/raw/smb_signing.c
source4/smb_server/signing.c
source4/smb_server/smb_server.h

index b2a68de0cb338614f4de835867590303126d2faa..22a98981888f58f980db1daf2901cd3944df19f6 100644 (file)
@@ -215,6 +215,7 @@ struct cli_tree {
        char *fs_type;
 };
 
+
 /* the context for a single SMB request. This is passed to any request-context 
  * functions (similar to context.h, the server version).
  * This will allow requests to be multi-threaded. */
@@ -249,37 +250,8 @@ struct cli_request {
        /* the mid of this packet - used to match replies */
        uint16_t mid;
 
-       struct {
-               /* the raw SMB buffer, including the 4 byte length header */
-               char *buffer;
-               
-               /* the size of the raw buffer, including 4 byte header */
-               uint_t size;
-
-               /* how much has been allocated - on reply the buffer is over-allocated to 
-                  prevent too many realloc() calls 
-               */
-               uint_t allocated;
-
-               /* the start of the SMB header - this is always buffer+4 */
-               char *hdr;
-
-               /* the command words and command word count. vwv points
-                  into the raw buffer */
-               char *vwv;
-               uint_t wct;
-
-               /* the data buffer and size. data points into the raw buffer */
-               char *data;
-               uint_t data_size;
-
-               /* ptr is used as a moving pointer into the data area
-                * of the packet. The reason its here and not a local
-                * variable in each function is that when a realloc of
-                * a send packet is done we need to move this
-                * pointer */
-               char *ptr;
-       } in, out;
+       struct request_buffer in;
+       struct request_buffer out;
 
        /* information on what to do with a reply when it is received
           asyncronously. If this is not setup when a reply is received then
index 9ce2b719820fafa068c75a224cd2d49564eca434..1e6cc0e5a48119e2cf576e5790e02c2bbb23c048 100644 (file)
@@ -671,6 +671,7 @@ extern int errno;
 #include "smbd/server.h"
 #include "smbd/service.h"
 #include "rpc_server/dcerpc_server.h"
+#include "request.h"
 #include "smb_server/smb_server.h"
 #include "ntvfs/ntvfs.h"
 #include "cli_context.h"
index 8268eb6051634edec73a412fc1739a46acfc65bd..c7c1a18d24647389074625e4dfa63b31996602a9 100644 (file)
@@ -304,6 +304,8 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security, TALL
                DATA_BLOB unwrapped_in;
 
                if (!gensec_gssapi_parse_krb5_wrap(out_mem_ctx, &in, &unwrapped_in, tok_id)) {
+                       DEBUG(1,("gensec_gssapi_parse_krb5_wrap(mutual authentication) failed to parse\n"));
+                       dump_data_pw("Mutual authentication message:\n", in.data, in.length);
                        return NT_STATUS_INVALID_PARAMETER;
                }
                /* TODO: check the tok_id */
@@ -316,7 +318,7 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security, TALL
                if (ret) {
                        DEBUG(1,("krb5_rd_rep (mutual authentication) failed (%s)\n",
                                 error_message(ret)));
-                       dump_data_pw("Mutual authentication message:\n", in.data, in.length);
+                       dump_data_pw("Mutual authentication message:\n", inbuf.data, inbuf.length);
                        nt_status = NT_STATUS_ACCESS_DENIED;
                } else {
                        *out = data_blob(NULL, 0);
index d4910eb92f95e4fa44437b812111b654745934cf..c16d77dad92ea149eaba133fdb99cca68f8646d7 100644 (file)
@@ -41,7 +41,6 @@ struct spnego_state {
        uint_t ref_count;
        enum spnego_message_type expected_packet;
        enum spnego_state_position state_position;
-       enum spnego_negResult result;
        struct gensec_security *sub_sec_security;
 };
 
@@ -60,7 +59,6 @@ static NTSTATUS gensec_spnego_client_start(struct gensec_security *gensec_securi
 
        spnego_state->expected_packet = SPNEGO_NEG_TOKEN_INIT;
        spnego_state->state_position = SPNEGO_CLIENT_START;
-       spnego_state->result = SPNEGO_ACCEPT_INCOMPLETE;
        spnego_state->mem_ctx = mem_ctx;
        spnego_state->sub_sec_security = NULL;
 
@@ -140,8 +138,7 @@ static NTSTATUS gensec_spnego_session_key(struct gensec_security *gensec_securit
                                    DATA_BLOB *session_key)
 {
        struct spnego_state *spnego_state = gensec_security->private_data;
-       if (spnego_state->state_position != SPNEGO_DONE 
-           && spnego_state->state_position != SPNEGO_FALLBACK) {
+       if (!spnego_state->sub_sec_security) {
                return NT_STATUS_INVALID_PARAMETER;
        }
        
@@ -450,7 +447,6 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
                                          spnego.negTokenTarg.responseToken, 
                                          &unwrapped_out);
                
-               spnego_state->result = spnego.negTokenTarg.negResult;
                spnego_free_data(&spnego);
                
                /* compose reply */
@@ -514,38 +510,45 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
                                          spnego.negTokenTarg.responseToken, 
                                          &unwrapped_out);
                
-               if (NT_STATUS_IS_OK(nt_status) 
-                   && (spnego.negTokenTarg.negResult != SPNEGO_ACCEPT_COMPLETED)) {
+               
+               if ((spnego.negTokenTarg.negResult == SPNEGO_ACCEPT_COMPLETED) 
+                   && !NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(1,("gensec_update ok but not accepted\n"));
                        nt_status = NT_STATUS_INVALID_PARAMETER;
-               }
+               } 
                
-               spnego_state->result = spnego.negTokenTarg.negResult;
                spnego_free_data(&spnego);
-               
-               spnego_out.type = SPNEGO_NEG_TOKEN_TARG;
-               spnego_out.negTokenTarg.negResult = SPNEGO_NONE_RESULT;
-               spnego_out.negTokenTarg.supportedMech = NULL;
-               spnego_out.negTokenTarg.responseToken = unwrapped_out;
-               spnego_out.negTokenTarg.mechListMIC = null_data_blob;
+
+               if (unwrapped_out.length) {
+                       spnego_out.type = SPNEGO_NEG_TOKEN_TARG;
+                       spnego_out.negTokenTarg.negResult = SPNEGO_NONE_RESULT;
+                       spnego_out.negTokenTarg.supportedMech = NULL;
+                       spnego_out.negTokenTarg.responseToken = unwrapped_out;
+                       spnego_out.negTokenTarg.mechListMIC = null_data_blob;
+                       
+                       if (spnego_write_data(out_mem_ctx, out, &spnego_out) == -1) {
+                               DEBUG(1, ("Failed to write SPNEGO reply to NEG_TOKEN_TARG\n"));
+                               return NT_STATUS_INVALID_PARAMETER;
+                       }
+               } else {
+                       *out = null_data_blob;
+               }
 
                if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
                        /* compose reply */
                        
+               
                        spnego_state->state_position = SPNEGO_CLIENT_TARG;
                } else if (NT_STATUS_IS_OK(nt_status)) {
+                       /* all done - server has accepted, and we agree */
                        spnego_state->state_position = SPNEGO_DONE;
+                       return NT_STATUS_OK;
                } else {
                        DEBUG(1, ("SPNEGO(%s) login failed: %s\n", 
                                  spnego_state->sub_sec_security->ops->name, 
                                  nt_errstr(nt_status)));
                        return nt_status;
                }
-               if (spnego_write_data(out_mem_ctx, out, &spnego_out) == -1) {
-                       DEBUG(1, ("Failed to write SPNEGO reply to NEG_TOKEN_TARG\n"));
-                       return NT_STATUS_INVALID_PARAMETER;
-               }
-               
                return nt_status;
        }
        case SPNEGO_DONE:
index e31cf07bf819ca845f739c05e961e63e07a63f68..c6d7f800a4ef2c51284b75e351ebe71826217252 100644 (file)
@@ -260,7 +260,7 @@ static void use_nt1_session_keys(struct cli_session *session,
        E_md4hash(password, nt_hash);
        SMBsesskeygen_ntv1(nt_hash, session_key.data);
 
-       cli_transport_simple_set_signing(transport, session_key, *nt_response, 0);
+       cli_transport_simple_set_signing(transport, session_key, *nt_response);
 
        cli_session_set_user_session_key(session, &session_key);
        data_blob_free(&session_key);
@@ -380,6 +380,7 @@ static NTSTATUS smb_raw_session_setup_generic_spnego(struct cli_session *session
                                                  union smb_sesssetup *parms) 
 {
        NTSTATUS status;
+       NTSTATUS session_key_err = NT_STATUS_NO_USER_SESSION_KEY;
        union smb_sesssetup s2;
        DATA_BLOB session_key = data_blob(NULL, 0);
        DATA_BLOB null_data_blob = data_blob(NULL, 0);
@@ -443,15 +444,20 @@ static NTSTATUS smb_raw_session_setup_generic_spnego(struct cli_session *session
                               &s2.spnego.in.secblob);
 
        while(1) {
+               if (NT_STATUS_IS_OK(status) && s2.spnego.in.secblob.length == 0) {
+                       break;
+               }
                if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
                        break;
                }
 
-               status = gensec_session_key(session->gensec, &session_key);
-               if (NT_STATUS_IS_OK(status)) {
-                       cli_transport_simple_set_signing(session->transport, session_key, null_data_blob, 0);
+               if (!NT_STATUS_IS_OK(session_key_err)) {
+                       session_key_err = gensec_session_key(session->gensec, &session_key);
                }
-
+               if (NT_STATUS_IS_OK(session_key_err)) {
+                       cli_transport_simple_set_signing(session->transport, session_key, null_data_blob);
+               }
+               
                session->vuid = s2.spnego.out.vuid;
                status = smb_raw_session_setup(session, mem_ctx, &s2);
                session->vuid = UID_FIELD_INVALID;
@@ -464,19 +470,14 @@ static NTSTATUS smb_raw_session_setup_generic_spnego(struct cli_session *session
                                       s2.spnego.out.secblob,
                                       &s2.spnego.in.secblob);
 
-               if (NT_STATUS_IS_OK(status)) {
-                       break;
-               }
        }
 
 done:
        if (NT_STATUS_IS_OK(status)) {
-               status = gensec_session_key(session->gensec, &session_key);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
+               if (!NT_STATUS_IS_OK(session_key_err)) {
+                       DEBUG(1, ("Failed to get user session key: %s\n", nt_errstr(session_key_err)));
+                       return session_key_err;
                }
-               
-               cli_transport_simple_set_signing(session->transport, session_key, null_data_blob, 2 /* two legs on last packet */);
 
                cli_session_set_user_session_key(session, &session_key);
 
@@ -484,6 +485,9 @@ done:
                parms->generic.out.os = s2.spnego.out.os;
                parms->generic.out.lanman = s2.spnego.out.lanman;
                parms->generic.out.domain = s2.spnego.out.domain;
+       } else {
+               DEBUG(1, ("Failed to login with SPNEGO: %s\n", nt_errstr(status)));
+               return status;
        }
 
        return status;
@@ -528,7 +532,18 @@ NTSTATUS smb_raw_session_setup(struct cli_session *session, TALLOC_CTX *mem_ctx,
        struct cli_request *req;
 
        if (parms->generic.level == RAW_SESSSETUP_GENERIC) {
-               return smb_raw_session_setup_generic(session, mem_ctx, parms);
+               NTSTATUS ret = smb_raw_session_setup_generic(session, mem_ctx, parms);
+
+               if (NT_STATUS_IS_OK(ret) 
+                   && parms->generic.in.user 
+                   && *parms->generic.in.user) {
+                       if (!session->transport->negotiate.sign_info.doing_signing 
+                           && session->transport->negotiate.sign_info.mandatory_signing) {
+                               DEBUG(0, ("SMB signing required, but server does not support it\n"));
+                               return NT_STATUS_ACCESS_DENIED;
+                       }
+               }
+               return ret;
        }
 
        req = smb_raw_session_setup_send(session, parms);
index fc104131081b49b1350cfead441873dcf7b383a7..20f8921acb89f46c0a9a75c29d80d1598e361c04 100644 (file)
@@ -69,15 +69,15 @@ static BOOL set_smb_signing_real_common(struct cli_transport *transport)
        return True;
 }
 
-static void mark_packet_signed(struct cli_request *req
+static void mark_packet_signed(struct request_buffer *out
 {
        uint16_t flags2;
-       flags2 = SVAL(req->out.hdr, HDR_FLG2);
+       flags2 = SVAL(out->hdr, HDR_FLG2);
        flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
-       SSVAL(req->out.hdr, HDR_FLG2, flags2);
+       SSVAL(out->hdr, HDR_FLG2, flags2);
 }
 
-static BOOL signing_good(struct cli_request *req, int seq, BOOL good) 
+static BOOL signing_good(struct cli_request *req, unsigned int seq, BOOL good) 
 {
        if (good) {
                if (!req->transport->negotiate.sign_info.doing_signing) {
@@ -87,9 +87,8 @@ static BOOL signing_good(struct cli_request *req, int seq, BOOL good)
                        req->transport->negotiate.sign_info.seen_valid = True;
                }
        } else {
-               if (!req->transport->negotiate.sign_info.mandatory_signing && !req->transport->negotiate.sign_info.seen_valid) {
-
-                       /* Non-mandatory signing - just turn off if this is the first bad packet.. */
+               if (!req->transport->negotiate.sign_info.seen_valid) {
+                       /* If we have never seen a good packet, just turn it off */
                        DEBUG(5, ("signing_good: signing negotiated but not required and peer\n"
                                  "isn't sending correct signatures. Turning off.\n"));
                        req->transport->negotiate.sign_info.negotiated_smb_signing = False;
@@ -100,119 +99,97 @@ static BOOL signing_good(struct cli_request *req, int seq, BOOL good)
                        cli_null_set_signing(req->transport);
                        return True;
                } else {
-                       /* Mandatory signing or bad packet after signing started - fail and disconnect. */
-                       if (seq)
-                               DEBUG(0, ("signing_good: BAD SIG: seq %u\n", (unsigned int)seq));
+                       /* bad packet after signing started - fail and disconnect. */
+                       DEBUG(0, ("signing_good: BAD SIG: seq %u\n", seq));
                        return False;
                }
        }
        return True;
 }
 
-/***********************************************************
- SMB signing - Simple implementation - calculate a MAC to send.
-************************************************************/
-static void cli_request_simple_sign_outgoing_message(struct cli_request *req)
+void sign_outgoing_message(struct request_buffer *out, DATA_BLOB *mac_key, uint_t seq_num) 
 {
        uint8_t calc_md5_mac[16];
        struct MD5Context md5_ctx;
-       struct smb_basic_signing_context *data = req->transport->negotiate.sign_info.signing_context;
-
-#if 0
-       /* enable this when packet signing is preventing you working out why valgrind 
-          says that data is uninitialised */
-       file_save("pkt.dat", req->out.buffer, req->out.size);
-#endif
-
-       req->seq_num = data->next_seq_num;
-       
-       /* some requests (eg. NTcancel) are one way, and the sequence number
-          should be increased by 1 not 2 */
-       if (req->one_way_request) {
-               data->next_seq_num += 1;
-       } else {
-               data->next_seq_num += 2;
-       }
-
        /*
         * Firstly put the sequence number into the first 4 bytes.
         * and zero out the next 4 bytes.
         */
-       SIVAL(req->out.hdr, HDR_SS_FIELD, req->seq_num);
-       SIVAL(req->out.hdr, HDR_SS_FIELD + 4, 0);
+       SIVAL(out->hdr, HDR_SS_FIELD, seq_num);
+       SIVAL(out->hdr, HDR_SS_FIELD + 4, 0);
 
        /* mark the packet as signed - BEFORE we sign it...*/
-       mark_packet_signed(req);
+       mark_packet_signed(out);
 
        /* Calculate the 16 byte MAC and place first 8 bytes into the field. */
        MD5Init(&md5_ctx);
-       MD5Update(&md5_ctx, data->mac_key.data, 
-                 data->mac_key.length); 
+       MD5Update(&md5_ctx, mac_key->data, 
+                 mac_key->length); 
        MD5Update(&md5_ctx, 
-                 req->out.buffer + NBT_HDR_SIZE, 
-                 req->out.size - NBT_HDR_SIZE);
+                 out->buffer + NBT_HDR_SIZE, 
+                 out->size - NBT_HDR_SIZE);
        MD5Final(calc_md5_mac, &md5_ctx);
 
-       memcpy(&req->out.hdr[HDR_SS_FIELD], calc_md5_mac, 8);
+       memcpy(&out->hdr[HDR_SS_FIELD], calc_md5_mac, 8);
 
-       DEBUG(5, ("cli_request_simple_sign_outgoing_message: SENT SIG (seq: %d, next %d): sent SMB signature of\n", 
-                 req->seq_num, data->next_seq_num));
+       DEBUG(5, ("sign_outgoing_message: SENT SIG (seq: %d): sent SMB signature of\n", 
+                 seq_num));
        dump_data(5, calc_md5_mac, 8);
 /*     req->out.hdr[HDR_SS_FIELD+2]=0; 
        Uncomment this to test if the remote server actually verifies signitures...*/
 }
 
-
-/***********************************************************
- SMB signing - Simple implementation - check a MAC sent by server.
-************************************************************/
-static BOOL cli_request_simple_check_incoming_message(struct cli_request *req)
+BOOL check_signed_incoming_message(struct request_buffer *in, DATA_BLOB *mac_key, uint_t seq_num) 
 {
        BOOL good;
        uint8_t calc_md5_mac[16];
        uint8_t server_sent_mac[8];
        uint8_t sequence_buf[8];
        struct MD5Context md5_ctx;
-       struct smb_basic_signing_context *data = req->transport->negotiate.sign_info.signing_context;
        const size_t offset_end_of_sig = (HDR_SS_FIELD + 8);
        int i;
        const int sign_range = 0;
 
+       /* room enough for the signature? */
+       if (in->size < NBT_HDR_SIZE + HDR_SS_FIELD + 8) {
+               return False;
+       }
+
        /* its quite bogus to be guessing sequence numbers, but very useful
           when debugging signing implementations */
-       for (i = 1-sign_range; i <= 1+sign_range; i++) {
+       for (i = 0-sign_range; i <= 0+sign_range; i++) {
                /*
                 * Firstly put the sequence number into the first 4 bytes.
                 * and zero out the next 4 bytes.
                 */
-               SIVAL(sequence_buf, 0, req->seq_num+i);
+               SIVAL(sequence_buf, 0, seq_num + i);
                SIVAL(sequence_buf, 4, 0);
                
                /* get a copy of the server-sent mac */
-               memcpy(server_sent_mac, &req->in.hdr[HDR_SS_FIELD], sizeof(server_sent_mac));
+               memcpy(server_sent_mac, &in->hdr[HDR_SS_FIELD], sizeof(server_sent_mac));
                
                /* Calculate the 16 byte MAC and place first 8 bytes into the field. */
                MD5Init(&md5_ctx);
-               MD5Update(&md5_ctx, data->mac_key.data, 
-                         data->mac_key.length); 
-               MD5Update(&md5_ctx, req->in.hdr, HDR_SS_FIELD);
+               MD5Update(&md5_ctx, mac_key->data, 
+                         mac_key->length); 
+               MD5Update(&md5_ctx, in->hdr, HDR_SS_FIELD);
                MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));
                
-               MD5Update(&md5_ctx, req->in.hdr + offset_end_of_sig, 
-                         req->in.size - NBT_HDR_SIZE - (offset_end_of_sig));
+               MD5Update(&md5_ctx, in->hdr + offset_end_of_sig, 
+                         in->size - NBT_HDR_SIZE - (offset_end_of_sig));
                MD5Final(calc_md5_mac, &md5_ctx);
                
                good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
 
-               if (i == 1) {
+               if (i == 0) {
                        if (!good) {
-                               DEBUG(5, ("cli_request_simple_check_incoming_message: BAD SIG (seq: %d): wanted SMB signature of\n", req->seq_num + i));
+                               DEBUG(5, ("check_signed_incoming_message: BAD SIG (seq: %d): wanted SMB signature of\n", seq_num + i));
                                dump_data(5, calc_md5_mac, 8);
                                
-                               DEBUG(5, ("cli_request_simple_check_incoming_message: BAD SIG (seq: %d): got SMB signature of\n", req->seq_num + i));
+                               DEBUG(5, ("check_signed_incoming_message: BAD SIG (seq: %d): got SMB signature of\n", seq_num + i));
                                dump_data(5, server_sent_mac, 8);
                        } else {
-                               DEBUG(15, ("cli_request_simple_check_incoming_message: GOOD SIG (seq: %d): got SMB signature of\n", req->seq_num + i));
+                               DEBUG(15, ("check_signed_incoming_message: GOOD SIG (seq: %d): got SMB signature of\n", seq_num + i));
                                dump_data(5, server_sent_mac, 8);
                        }
                }
@@ -220,10 +197,51 @@ static BOOL cli_request_simple_check_incoming_message(struct cli_request *req)
                if (good) break;
        }
 
-       if (good && i != 1) {
-               DEBUG(0,("SIGNING OFFSET %d (should be %d)\n", i, req->seq_num+1));
+       if (good && i != 0) {
+               DEBUG(0,("SIGNING OFFSET %d (should be %d)\n", i, seq_num));
+       }
+       return good;
+}
+
+/***********************************************************
+ SMB signing - Simple implementation - calculate a MAC to send.
+************************************************************/
+static void cli_request_simple_sign_outgoing_message(struct cli_request *req)
+{
+       struct smb_basic_signing_context *data = req->transport->negotiate.sign_info.signing_context;
+
+#if 0
+       /* enable this when packet signing is preventing you working out why valgrind 
+          says that data is uninitialised */
+       file_save("pkt.dat", req->out.buffer, req->out.size);
+#endif
+
+       req->seq_num = data->next_seq_num;
+       
+       /* some requests (eg. NTcancel) are one way, and the sequence number
+          should be increased by 1 not 2 */
+       if (req->one_way_request) {
+               data->next_seq_num += 1;
+       } else {
+               data->next_seq_num += 2;
        }
+       
+       sign_outgoing_message(&req->out, &data->mac_key, req->seq_num);
+}
+
 
+/***********************************************************
+ SMB signing - Simple implementation - check a MAC sent by server.
+************************************************************/
+static BOOL cli_request_simple_check_incoming_message(struct cli_request *req)
+{
+       struct smb_basic_signing_context *data 
+               = req->transport->negotiate.sign_info.signing_context;
+
+       BOOL good = check_signed_incoming_message(&req->in, 
+                                                 &data->mac_key, 
+                                                 req->seq_num+1);
+                                                 
        return signing_good(req, req->seq_num+1, good);
 }
 
@@ -247,8 +265,7 @@ static void cli_transport_simple_free_signing_context(struct cli_transport *tran
 ************************************************************/
 BOOL cli_transport_simple_set_signing(struct cli_transport *transport,
                                      const DATA_BLOB user_session_key, 
-                                     const DATA_BLOB response,
-                                     int seq_num)
+                                     const DATA_BLOB response)
 {
        struct smb_basic_signing_context *data;
 
@@ -271,8 +288,10 @@ BOOL cli_transport_simple_set_signing(struct cli_transport *transport,
                memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
        }
 
+       dump_data_pw("Started Signing with key:\n", data->mac_key.data, data->mac_key.length);
+
        /* Initialise the sequence number */
-       data->next_seq_num = seq_num;
+       data->next_seq_num = 0;
 
        transport->negotiate.sign_info.sign_outgoing_message = cli_request_simple_sign_outgoing_message;
        transport->negotiate.sign_info.check_incoming_message = cli_request_simple_check_incoming_message;
@@ -332,11 +351,12 @@ BOOL cli_null_set_signing(struct cli_transport *transport)
 static void cli_request_temp_sign_outgoing_message(struct cli_request *req)
 {
        /* mark the packet as signed - BEFORE we sign it...*/
-       mark_packet_signed(req);
+       mark_packet_signed(&req->out);
 
        /* I wonder what BSRSPYL stands for - but this is what MS 
           actually sends! */
        memcpy((req->out.hdr + HDR_SS_FIELD), "BSRSPYL ", 8);
+
        return;
 }
 
index d6ccebb17403e6f10ff24436f02e6ba226d1db03..37c1f6f7b147c1a427048d94e90a588bc27b6394 100644 (file)
 
 #include "includes.h"
 
-/*
-  mark the flags2 field in a packet as signed
-*/
-static void mark_packet_signed(struct smbsrv_request *req) 
-{
-       uint16_t flags2;
-       flags2 = SVAL(req->out.hdr, HDR_FLG2);
-       flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
-       SSVAL(req->out.hdr, HDR_FLG2, flags2);
-}
-
-/*
-  calculate the signature for a message
-*/
-static void calc_signature(uint8_t *buffer, size_t length,
-                          DATA_BLOB *mac_key, uint8_t signature[8])
-{
-       uint8_t calc_md5_mac[16];
-       struct MD5Context md5_ctx;
-
-       MD5Init(&md5_ctx);
-       MD5Update(&md5_ctx, mac_key->data, mac_key->length); 
-       MD5Update(&md5_ctx, buffer, length);
-       MD5Final(calc_md5_mac, &md5_ctx);
-       memcpy(signature, calc_md5_mac, 8);
-}
-                          
-
 /*
   sign an outgoing packet
 */
@@ -57,14 +29,9 @@ void req_sign_packet(struct smbsrv_request *req)
        if (req->smb_conn->signing.signing_state != SMB_SIGNING_REQUIRED) {
                return;
        }
-
-       SBVAL(req->out.hdr, HDR_SS_FIELD, req->seq_num+1);
-
-       mark_packet_signed(req);
-
-       calc_signature(req->out.hdr, req->out.size - NBT_HDR_SIZE,
-                      &req->smb_conn->signing.mac_key, 
-                      &req->out.hdr[HDR_SS_FIELD]);
+       sign_outgoing_message(&req->out, 
+                             &req->smb_conn->signing.mac_key, 
+                             req->seq_num+1);
 }
 
 
@@ -127,23 +94,8 @@ BOOL req_signing_check_incoming(struct smbsrv_request *req)
                return True;
        }
 
-       /* room enough for the signature? */
-       if (req->in.size < NBT_HDR_SIZE + HDR_SS_FIELD + 8) {
-               return False;
-       }
-
-       memcpy(client_md5_mac, req->in.hdr + HDR_SS_FIELD, 8);
-
-       SBVAL(req->in.hdr, HDR_SS_FIELD, req->seq_num);
-
-       calc_signature(req->in.hdr, req->in.size - NBT_HDR_SIZE,
-                      &req->smb_conn->signing.mac_key, 
-                      signature);
-
-       if (memcmp(client_md5_mac, signature, 8) != 0) {
-               DEBUG(2,("Bad SMB signature seq_num=%d\n", (int)req->seq_num));
-               return False;
-       }
+       return check_signed_incoming_message(&req->in,
+                                            &req->smb_conn->signing.mac_key,
+                                            req->seq_num);
 
-       return True;
 }
index 2eb87f09a33da1b0e8e65a47764e86454305f8d3..ae72bb5da4e0f7854185c5f5ffd6a81c43574724 100644 (file)
@@ -141,37 +141,8 @@ struct smbsrv_request {
                NTSTATUS status;
        } async;
 
-       struct {
-               /* the raw SMB buffer, including the 4 byte length header */
-               char *buffer;
-               
-               /* the size of the raw buffer, including 4 byte header */
-               unsigned size;
-
-               /* how much has been allocated - on reply the buffer is over-allocated to 
-                  prevent too many realloc() calls 
-               */
-               unsigned allocated;
-
-               /* the start of the SMB header - this is always buffer+4 */
-               char *hdr;
-
-               /* the command words and command word count. vwv points
-                  into the raw buffer */
-               char *vwv;
-               unsigned wct;
-
-               /* the data buffer and size. data points into the raw buffer */
-               char *data;
-               unsigned data_size;
-
-               /* ptr is used as a moving pointer into the data area
-                * of the packet. The reason its here and not a local
-                * variable in each function is that when a realloc of
-                * a reply packet is done we need to move this
-                * pointer */
-               char *ptr;
-       } in, out;
+       struct request_buffer in;
+       struct request_buffer out;
 };
 
 /* this contains variables that should be used in % substitutions for