diff options
author | Andrew Bartlett <abartlet@samba.org> | 2008-06-10 13:19:56 +1000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2008-06-10 13:19:56 +1000 |
commit | 7721ea8f9c75d304111935048167dd27525cc91a (patch) | |
tree | fdc6563d085003cf6fe003748fb85291166a5454 /source4/libcli | |
parent | 7974ccbebf5c684200850a726d79b976eaeea261 (diff) | |
parent | 1384f836b601d35f3c499a9e26c3e3b0d12b3ad0 (diff) | |
download | samba-7721ea8f9c75d304111935048167dd27525cc91a.tar.gz samba-7721ea8f9c75d304111935048167dd27525cc91a.tar.bz2 samba-7721ea8f9c75d304111935048167dd27525cc91a.zip |
Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into 4-0-local
(This used to be commit 1d52d9cc70158dbe30325220aa5c1e6203c8b72b)
Diffstat (limited to 'source4/libcli')
-rw-r--r-- | source4/libcli/raw/raweas.c | 2 | ||||
-rw-r--r-- | source4/libcli/smb2/session.c | 10 | ||||
-rw-r--r-- | source4/libcli/smb2/signing.c | 74 | ||||
-rw-r--r-- | source4/libcli/smb2/smb2.h | 2 | ||||
-rw-r--r-- | source4/libcli/smb2/tcon.c | 1 | ||||
-rw-r--r-- | source4/libcli/smb2/transport.c | 32 |
6 files changed, 49 insertions, 72 deletions
diff --git a/source4/libcli/raw/raweas.c b/source4/libcli/raw/raweas.c index 07b517ade3..6317c49fd7 100644 --- a/source4/libcli/raw/raweas.c +++ b/source4/libcli/raw/raweas.c @@ -131,6 +131,8 @@ uint_t ea_pull_struct(const DATA_BLOB *blob, uint8_t nlen; uint16_t vlen; + ZERO_STRUCTP(ea); + if (blob->length < 6) { return 0; } diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c index 54915d8535..91616319d5 100644 --- a/source4/libcli/smb2/session.c +++ b/source4/libcli/smb2/session.c @@ -164,7 +164,7 @@ static void session_request_handler(struct smb2_request *req) session_key_err = gensec_session_key(session->gensec, &session_key); if (NT_STATUS_IS_OK(session_key_err)) { - session->transport->signing.session_key = session_key; + session->session_key = session_key; } } @@ -188,11 +188,13 @@ static void session_request_handler(struct smb2_request *req) } if (session->transport->signing.doing_signing) { - c->status = smb2_start_signing(session->transport); - if (!NT_STATUS_IS_OK(c->status)) { - composite_error(c, c->status); + if (session->session_key.length != 16) { + DEBUG(2,("Wrong session key length %u for SMB2 signing\n", + (unsigned)session->session_key.length)); + composite_error(c, NT_STATUS_ACCESS_DENIED); return; } + session->transport->signing.signing_started = true; } composite_done(c); diff --git a/source4/libcli/smb2/signing.c b/source4/libcli/smb2/signing.c index 16c0ff99c1..fb2c22db4e 100644 --- a/source4/libcli/smb2/signing.c +++ b/source4/libcli/smb2/signing.c @@ -26,41 +26,13 @@ #include "lib/crypto/crypto.h" /* - NOTE: this code does not yet interoperate with the windows SMB2 - implementation. We are waiting on feedback on the docs to find out - why - */ - - -/* - setup signing on a transport - */ -NTSTATUS smb2_start_signing(struct smb2_transport *transport) -{ - if (transport->signing.session_key.length != 16) { - DEBUG(2,("Wrong session key length %u for SMB2 signing\n", - (unsigned)transport->signing.session_key.length)); - return NT_STATUS_ACCESS_DENIED; - } - - transport->signing.signing_started = true; - return NT_STATUS_OK; -} - -/* sign an outgoing message */ -NTSTATUS smb2_sign_message(struct smb2_request *req) +NTSTATUS smb2_sign_message(struct smb2_request_buffer *buf, DATA_BLOB session_key) { - struct smb2_request_buffer *buf = &req->out; - uint64_t session_id; struct HMACSHA256Context m; uint8_t res[32]; - - if (!req->transport->signing.doing_signing || - !req->transport->signing.signing_started) { - return NT_STATUS_OK; - } + uint64_t session_id; if (buf->size < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) { /* can't sign non-SMB2 messages */ @@ -74,9 +46,9 @@ NTSTATUS smb2_sign_message(struct smb2_request *req) return NT_STATUS_OK; } - if (req->transport->signing.session_key.length != 16) { + if (session_key.length != 16) { DEBUG(2,("Wrong session key length %u for SMB2 signing\n", - (unsigned)req->transport->signing.session_key.length)); + (unsigned)session_key.length)); return NT_STATUS_ACCESS_DENIED; } @@ -85,7 +57,7 @@ NTSTATUS smb2_sign_message(struct smb2_request *req) SIVAL(buf->hdr, SMB2_HDR_FLAGS, IVAL(buf->hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED); ZERO_STRUCT(m); - hmac_sha256_init(req->transport->signing.session_key.data, 16, &m); + hmac_sha256_init(session_key.data, 16, &m); hmac_sha256_update(buf->buffer+NBT_HDR_SIZE, buf->size-NBT_HDR_SIZE, &m); hmac_sha256_final(res, &m); @@ -93,66 +65,56 @@ NTSTATUS smb2_sign_message(struct smb2_request *req) memcpy(buf->hdr + SMB2_HDR_SIGNATURE, res, 16); - if (DEBUGLVL(5)) { - /* check our own signature */ - smb2_check_signature(req->transport, buf->buffer, buf->size); - } - return NT_STATUS_OK; } /* check an incoming signature */ -NTSTATUS smb2_check_signature(struct smb2_transport *transport, - uint8_t *buffer, uint_t length) +NTSTATUS smb2_check_signature(struct smb2_request_buffer *buf, DATA_BLOB session_key) { uint64_t session_id; struct HMACSHA256Context m; uint8_t res[SHA256_DIGEST_LENGTH]; uint8_t sig[16]; - if (!transport->signing.signing_started || - !transport->signing.doing_signing) { - return NT_STATUS_OK; - } - - if (length < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) { + if (buf->size < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) { /* can't check non-SMB2 messages */ return NT_STATUS_OK; } - session_id = BVAL(buffer+NBT_HDR_SIZE, SMB2_HDR_SESSION_ID); + session_id = BVAL(buf->hdr, SMB2_HDR_SESSION_ID); if (session_id == 0) { /* don't sign messages with a zero session_id. See MS-SMB2 3.2.4.1.1 */ return NT_STATUS_OK; } - if (transport->signing.session_key.length == 0) { + if (session_key.length == 0) { /* we don't have the session key yet */ return NT_STATUS_OK; } - if (transport->signing.session_key.length != 16) { + if (session_key.length != 16) { DEBUG(2,("Wrong session key length %u for SMB2 signing\n", - (unsigned)transport->signing.session_key.length)); + (unsigned)session_key.length)); return NT_STATUS_ACCESS_DENIED; } - memcpy(sig, buffer+NBT_HDR_SIZE+SMB2_HDR_SIGNATURE, 16); + memcpy(sig, buf->hdr+SMB2_HDR_SIGNATURE, 16); - memset(buffer + NBT_HDR_SIZE + SMB2_HDR_SIGNATURE, 0, 16); + memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16); ZERO_STRUCT(m); - hmac_sha256_init(transport->signing.session_key.data, 16, &m); - hmac_sha256_update(buffer+NBT_HDR_SIZE, length-NBT_HDR_SIZE, &m); + hmac_sha256_init(session_key.data, 16, &m); + hmac_sha256_update(buf->hdr, buf->size-NBT_HDR_SIZE, &m); hmac_sha256_final(res, &m); - memcpy(buffer+NBT_HDR_SIZE+SMB2_HDR_SIGNATURE, sig, 16); + memcpy(buf->hdr+SMB2_HDR_SIGNATURE, sig, 16); if (memcmp(res, sig, 16) != 0) { - DEBUG(0,("Bad SMB2 signature for message of size %u\n", length)); + DEBUG(0,("Bad SMB2 signature for message of size %u\n", + (unsigned)buf->size-NBT_HDR_SIZE)); dump_data(0, sig, 16); dump_data(0, res, 16); return NT_STATUS_ACCESS_DENIED; diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index 0903509528..2b468d3dc9 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -30,7 +30,6 @@ struct smb2_handle; struct smb2_signing_context { bool doing_signing; bool signing_started; - DATA_BLOB session_key; }; /* @@ -98,6 +97,7 @@ struct smb2_session { struct smb2_transport *transport; struct gensec_security *gensec; uint64_t uid; + DATA_BLOB session_key; }; diff --git a/source4/libcli/smb2/tcon.c b/source4/libcli/smb2/tcon.c index db35669d41..ec7152b264 100644 --- a/source4/libcli/smb2/tcon.c +++ b/source4/libcli/smb2/tcon.c @@ -57,6 +57,7 @@ struct smb2_request *smb2_tree_connect_send(struct smb2_tree *tree, if (req == NULL) return NULL; SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, tree->session->uid); + req->session = tree->session; SSVAL(req->out.body, 0x02, io->in.reserved); status = smb2_push_o16s16_string(&req->out, 0x04, io->in.path); diff --git a/source4/libcli/smb2/transport.c b/source4/libcli/smb2/transport.c index 561b6e528e..6e0d523e21 100644 --- a/source4/libcli/smb2/transport.c +++ b/source4/libcli/smb2/transport.c @@ -205,12 +205,6 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob) goto error; } - status = smb2_check_signature(transport, buffer, len); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(buffer); - return status; - } - flags = IVAL(hdr, SMB2_HDR_FLAGS); seqnum = BVAL(hdr, SMB2_HDR_MESSAGE_ID); @@ -241,6 +235,17 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob) req->in.body_size = req->in.size - (SMB2_HDR_BODY+NBT_HDR_SIZE); req->status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS)); + if (req->session && transport->signing.doing_signing) { + status = smb2_check_signature(&req->in, + req->session->session_key); + if (!NT_STATUS_IS_OK(status)) { + /* the spec says to ignore packets with a bad signature */ + talloc_free(buffer); + return status; + } + } + + if (NT_STATUS_EQUAL(req->status, STATUS_PENDING)) { if (flags & 0x00000002) { req->cancel.can_cancel = true; @@ -346,11 +351,16 @@ void smb2_transport_send(struct smb2_request *req) return; } - status = smb2_sign_message(req); - if (!NT_STATUS_IS_OK(status)) { - req->state = SMB2_REQUEST_ERROR; - req->status = status; - return; + /* possibly sign the message */ + if (req->transport->signing.doing_signing && + req->transport->signing.signing_started && + req->session) { + status = smb2_sign_message(&req->out, req->session->session_key); + if (!NT_STATUS_IS_OK(status)) { + req->state = SMB2_REQUEST_ERROR; + req->status = status; + return; + } } blob = data_blob_const(req->out.buffer, req->out.size); |