From afc93255d183eefb68e45b8ec6275f6a62cf9795 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Dec 2007 17:12:36 -0800 Subject: Add SMB encryption. Still fixing client decrypt but negotiation works. Jeremy. (This used to be commit d78045601af787731f0737b8627450018902b104) --- source3/smbd/process.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 3 deletions(-) (limited to 'source3/smbd/process.c') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ee76f90bf5..1260d52c77 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -50,6 +50,43 @@ enum smb_read_errors *get_srv_read_error(void) return &smb_read_error; } +/******************************************************************* + Setup the word count and byte count for a smb message. + copying the '0xFF X X X' bytes from incoming + buffer (so we copy any encryption context). +********************************************************************/ + +int srv_set_message(const char *frombuf, + char *buf, + int num_words, + int num_bytes, + bool zero) +{ + if (zero && (num_words || num_bytes)) { + memset(buf + smb_size,'\0',num_words*2 + num_bytes); + } + SCVAL(buf,smb_wct,num_words); + SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes); + _smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4)); + if (buf != frombuf) { + memcpy(buf+4, frombuf+4, 4); + } + return (smb_size + num_words*2 + num_bytes); +} + +static bool valid_smb_header(const char *inbuf) +{ + if (srv_encryption_on()) { + uint16_t enc_num; + NTSTATUS status = get_enc_ctx_num(inbuf, &enc_num); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + return (enc_num == 0); + } + return (strncmp(smb_base(inbuf),"\377SMB",4) == 0); +} + /* Socket functions for smbd packet processing. */ static bool valid_packet_size(size_t len) @@ -324,6 +361,18 @@ ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer, return -1; } + if (srv_encryption_on()) { + NTSTATUS status = srv_decrypt_buffer(*buffer); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("receive_smb_talloc: SMB decryption failed on " + "incoming packet! Error %s\n", + nt_errstr(status) )); + cond_set_smb_read_error(get_srv_read_error(), + SMB_READ_BAD_DECRYPT); + return -1; + } + } + /* Check the incoming SMB signature. */ if (!srv_check_sign_mac(*buffer, true)) { DEBUG(0, ("receive_smb: SMB Signature verification failed on " @@ -1239,7 +1288,8 @@ void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes) } construct_reply_common((char *)req->inbuf, (char *)req->outbuf); - set_message((char *)req->outbuf, num_words, num_bytes, False); + srv_set_message((const char *)req->inbuf, + (char *)req->outbuf, num_words, num_bytes, false); /* * Zero out the word area, the caller has to take care of the bcc area * himself @@ -1309,7 +1359,7 @@ static void switch_message(uint8 type, struct smb_request *req, int size) /* Make sure this is an SMB packet. smb_size contains NetBIOS header * so subtract 4 from it. */ - if ((strncmp(smb_base(req->inbuf),"\377SMB",4) != 0) + if (!valid_smb_header((const char *)req->inbuf) || (size < (smb_size - 4))) { DEBUG(2,("Non-SMB packet of length %d. Terminating server\n", smb_len(req->inbuf))); @@ -1551,7 +1601,7 @@ void remove_from_common_flags2(uint32 v) void construct_reply_common(const char *inbuf, char *outbuf) { - set_message(outbuf,0,0,False); + srv_set_message(inbuf,outbuf,0,0,false); SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com)); SIVAL(outbuf,smb_rcls,0); -- cgit