From b3c46674a670ea51607d5c2a73271dff531ae7d6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 16 Jul 2004 02:54:57 +0000 Subject: r1521: Updates to our SMB signing code. - 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 | 34 +-------- source4/include/includes.h | 1 + source4/libcli/auth/gensec_krb5.c | 4 +- source4/libcli/auth/spnego.c | 43 ++++++----- source4/libcli/raw/clisession.c | 43 +++++++---- source4/libcli/raw/smb_signing.c | 152 +++++++++++++++++++++----------------- source4/smb_server/signing.c | 60 ++------------- source4/smb_server/smb_server.h | 33 +-------- 8 files changed, 153 insertions(+), 217 deletions(-) diff --git a/source4/include/cli_context.h b/source4/include/cli_context.h index b2a68de0cb..22a9898188 100644 --- a/source4/include/cli_context.h +++ b/source4/include/cli_context.h @@ -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 diff --git a/source4/include/includes.h b/source4/include/includes.h index 9ce2b71982..1e6cc0e5a4 100644 --- a/source4/include/includes.h +++ b/source4/include/includes.h @@ -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" diff --git a/source4/libcli/auth/gensec_krb5.c b/source4/libcli/auth/gensec_krb5.c index 8268eb6051..c7c1a18d24 100644 --- a/source4/libcli/auth/gensec_krb5.c +++ b/source4/libcli/auth/gensec_krb5.c @@ -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); diff --git a/source4/libcli/auth/spnego.c b/source4/libcli/auth/spnego.c index d4910eb92f..c16d77dad9 100644 --- a/source4/libcli/auth/spnego.c +++ b/source4/libcli/auth/spnego.c @@ -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: diff --git a/source4/libcli/raw/clisession.c b/source4/libcli/raw/clisession.c index e31cf07bf8..c6d7f800a4 100644 --- a/source4/libcli/raw/clisession.c +++ b/source4/libcli/raw/clisession.c @@ -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); diff --git a/source4/libcli/raw/smb_signing.c b/source4/libcli/raw/smb_signing.c index fc10413108..20f8921acb 100644 --- a/source4/libcli/raw/smb_signing.c +++ b/source4/libcli/raw/smb_signing.c @@ -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; } diff --git a/source4/smb_server/signing.c b/source4/smb_server/signing.c index d6ccebb174..37c1f6f7b1 100644 --- a/source4/smb_server/signing.c +++ b/source4/smb_server/signing.c @@ -20,34 +20,6 @@ #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; } diff --git a/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h index 2eb87f09a3..ae72bb5da4 100644 --- a/source4/smb_server/smb_server.h +++ b/source4/smb_server/smb_server.h @@ -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 -- cgit