The branch, master has been updated via 069db9b s3:smb2_break: encrypt OPLOCK BREAK notifications via 54dfd08 s3:smb2_server: use smbXsrv_session->nonce_* via 6f9610e smbXsrv.idl: add nonce_* to smbsrv_session via 6c7ffa9 s3:smb2_server: remove dump_data() from smbd_smb2_request_pending_timer() from 27bc6cf Extending space for fqdn in wbinfo --trusted-domains in verbose mode
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 069db9b630b19835e8a008b50c0bed4d7245bf51 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Aug 22 10:33:07 2012 +0200 s3:smb2_break: encrypt OPLOCK BREAK notifications metze Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Thu Aug 23 10:01:14 CEST 2012 on sn-devel-104 commit 54dfd08cb2970fcf2ad915f1ac0caec626cdd44e Author: Stefan Metzmacher <me...@samba.org> Date: Wed Aug 22 10:30:52 2012 +0200 s3:smb2_server: use smbXsrv_session->nonce_* metze commit 6f9610e618a6abbdd41c135e4a3d306fb8ce8743 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Aug 22 10:29:21 2012 +0200 smbXsrv.idl: add nonce_* to smbsrv_session metze commit 6c7ffa90925f074fb93f578b7c0582394aee557d Author: Stefan Metzmacher <me...@samba.org> Date: Wed Aug 22 10:32:09 2012 +0200 s3:smb2_server: remove dump_data() from smbd_smb2_request_pending_timer() This was just for debugging... metze ----------------------------------------------------------------------- Summary of changes: source3/librpc/idl/smbXsrv.idl | 2 + source3/smbd/globals.h | 5 +- source3/smbd/smb2_break.c | 27 +++++++- source3/smbd/smb2_server.c | 143 +++++++++++++++++++++++++++++----------- source3/smbd/smb2_sesssetup.c | 3 + 5 files changed, 136 insertions(+), 44 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl index b3f2250..90572e5 100644 --- a/source3/librpc/idl/smbXsrv.idl +++ b/source3/librpc/idl/smbXsrv.idl @@ -145,6 +145,8 @@ interface smbXsrv [ref] smbXsrv_session_global0 *global; NTSTATUS status; NTTIME idle_time; + hyper nonce_high; + hyper nonce_low; [ignore] gensec_security *gensec; [ignore] user_struct *compat; [ignore] smbXsrv_tcon_table *tcon_table; diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index b024fb3..6af17a4 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -235,8 +235,9 @@ NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req, smbd_smb2_request_done_ex(req, NT_STATUS_OK, body, dyn, __location__) NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn, - uint64_t file_id_persistent, - uint64_t file_id_volatile, + struct smbXsrv_session *session, + struct smbXsrv_tcon *tcon, + struct smbXsrv_open *op, uint8_t oplock_level); NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, diff --git a/source3/smbd/smb2_break.c b/source3/smbd/smb2_break.c index 8143b8b..8db9e6d 100644 --- a/source3/smbd/smb2_break.c +++ b/source3/smbd/smb2_break.c @@ -235,6 +235,26 @@ void send_break_message_smb2(files_struct *fsp, int level) SMB2_OPLOCK_LEVEL_II : SMB2_OPLOCK_LEVEL_NONE; NTSTATUS status; + struct smbXsrv_session *session = NULL; + struct timeval tv = timeval_current(); + NTTIME now = timeval_to_nttime(&tv); + + status = smb2srv_session_lookup(fsp->conn->sconn->conn, + fsp->vuid, + now, + &session); + if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED) || + (session == NULL)) + { + + DEBUG(10,("send_break_message_smb2: skip oplock break " + "for file %s, %s, smb2 level %u session %llu not found\n", + fsp_str_dbg(fsp), + fsp_fnum_dbg(fsp), + (unsigned int)smb2_oplock_level, + (unsigned long long)fsp->vuid)); + return; + } DEBUG(10,("send_break_message_smb2: sending oplock break " "for file %s, %s, smb2 level %u\n", @@ -243,9 +263,10 @@ void send_break_message_smb2(files_struct *fsp, int level) (unsigned int)smb2_oplock_level )); status = smbd_smb2_send_oplock_break(fsp->conn->sconn, - fsp->op->global->open_persistent_id, - fsp->op->global->open_volatile_id, - smb2_oplock_level); + session, + fsp->conn->tcon, + fsp->op, + smb2_oplock_level); if (!NT_STATUS_IS_OK(status)) { smbd_server_connection_terminate(fsp->conn->sconn, nt_errstr(status)); diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 106e6ac..be7997f 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -1431,8 +1431,8 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev, uint32_t flags = 0; uint64_t session_id = 0; uint64_t message_id = 0; - uint64_t nonce_high; - uint64_t nonce_low; + uint64_t nonce_high = 0; + uint64_t nonce_low = 0; uint64_t async_id = 0; struct tevent_req *subreq = NULL; @@ -1476,15 +1476,18 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev, body = hdr + SMB2_HDR_BODY; dyn = body + 8; - /* - * We may have 2 responses (PENDING, FINAL), - * so alter the nonce. - * - * The PENDING response has the SMB2_HDR_FLAG_ASYNC bit - * set. - */ - nonce_high = session_id | SMB2_HDR_FLAG_ASYNC; - nonce_low = message_id; + if (req->do_encryption) { + struct smbXsrv_session *x = req->session; + + nonce_high = x->nonce_high; + nonce_low = x->nonce_low; + + x->nonce_low += 1; + if (x->nonce_low == 0) { + x->nonce_low += 1; + x->nonce_high += 1; + } + } SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC); SBVAL(tf, SMB2_TF_NONCE+0, nonce_low); @@ -1553,7 +1556,6 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev, (unsigned int)i, (unsigned int)ARRAY_SIZE(state->vector), (unsigned int)state->vector[i].iov_len); - dump_data(0, state->vector[i].iov_base, state->vector[i].iov_len); } } @@ -2311,22 +2313,18 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) { DATA_BLOB encryption_key = req->session->global->encryption_key; uint8_t *tf; - const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req); uint64_t session_id = req->session->global->session_wire_id; - uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID); - uint64_t async_id = BVAL(inhdr, SMB2_HDR_ASYNC_ID); - /* - * We may have 2 responses (PENDING, FINAL), - * so alter the nonce. - * - * The FINAL response has the SMB2_HDR_FLAG_ASYNC bit - * cleared. - */ - uint64_t nonce_high = session_id & ~SMB2_HDR_FLAG_ASYNC; - uint64_t nonce_low = message_id; + struct smbXsrv_session *x = req->session; + uint64_t nonce_high; + uint64_t nonce_low; + + nonce_high = x->nonce_high; + nonce_low = x->nonce_low; - if (nonce_low == 0) { - nonce_low = async_id; + x->nonce_low += 1; + if (x->nonce_low == 0) { + x->nonce_low += 1; + x->nonce_high += 1; } /* @@ -2696,21 +2694,35 @@ NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req, struct smbd_smb2_send_oplock_break_state { struct smbd_server_connection *sconn; - uint8_t buf[4 + SMB2_HDR_BODY + 0x18]; - struct iovec vector; + uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x18]; + struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ]; }; static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq); NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn, - uint64_t file_id_persistent, - uint64_t file_id_volatile, + struct smbXsrv_session *session, + struct smbXsrv_tcon *tcon, + struct smbXsrv_open *op, uint8_t oplock_level) { struct smbd_smb2_send_oplock_break_state *state; + struct smbXsrv_connection *conn = sconn->conn; struct tevent_req *subreq; + uint8_t *tf; + size_t tf_len; uint8_t *hdr; uint8_t *body; + size_t body_len; + uint8_t *dyn; + size_t dyn_len; + bool do_encryption = session->global->encryption_required; + uint64_t nonce_high = 0; + uint64_t nonce_low = 0; + + if (tcon->global->encryption_required) { + do_encryption = true; + } state = talloc(sconn, struct smbd_smb2_send_oplock_break_state); if (state == NULL) { @@ -2718,12 +2730,29 @@ NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn, } state->sconn = sconn; - state->vector.iov_base = (void *)state->buf; - state->vector.iov_len = sizeof(state->buf); - - _smb2_setlen(state->buf, sizeof(state->buf) - 4); - hdr = state->buf + 4; + tf = state->buf + NBT_HDR_SIZE; + tf_len = SMB2_TF_HDR_SIZE; + hdr = tf + tf_len; body = hdr + SMB2_HDR_BODY; + body_len = 0x18; + dyn = body + body_len; + dyn_len = 0; + + if (do_encryption) { + nonce_high = session->nonce_high; + nonce_low = session->nonce_low; + + session->nonce_low += 1; + if (session->nonce_low == 0) { + session->nonce_low += 1; + session->nonce_high += 1; + } + } + + SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC); + SBVAL(tf, SMB2_TF_NONCE+0, nonce_low); + SBVAL(tf, SMB2_TF_NONCE+8, nonce_high); + SBVAL(tf, SMB2_TF_SESSION_ID, session->global->session_wire_id); SIVAL(hdr, 0, SMB2_MAGIC); SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY); @@ -2739,19 +2768,55 @@ NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn, SBVAL(hdr, SMB2_HDR_SESSION_ID, 0); memset(hdr+SMB2_HDR_SIGNATURE, 0, 16); - SSVAL(body, 0x00, 0x18); + SSVAL(body, 0x00, body_len); SCVAL(body, 0x02, oplock_level); SCVAL(body, 0x03, 0); /* reserved */ SIVAL(body, 0x04, 0); /* reserved */ - SBVAL(body, 0x08, file_id_persistent); - SBVAL(body, 0x10, file_id_volatile); + SBVAL(body, 0x08, op->global->open_persistent_id); + SBVAL(body, 0x10, op->global->open_volatile_id); + + state->vector[0].iov_base = (void *)state->buf; + state->vector[0].iov_len = NBT_HDR_SIZE; + + if (do_encryption) { + state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf; + state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len; + } else { + state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL; + state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0; + } + + state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr; + state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY; + + state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body; + state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = body_len; + + state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn; + state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_len; + + smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ); + + if (do_encryption) { + NTSTATUS status; + DATA_BLOB encryption_key = session->global->encryption_key; + + status = smb2_signing_encrypt_pdu(encryption_key, + conn->protocol, + &state->vector[1+SMBD_SMB2_TF_IOV_OFS], + SMBD_SMB2_NUM_IOV_PER_REQ); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } subreq = tstream_writev_queue_send(state, sconn->ev_ctx, sconn->smb2.stream, sconn->smb2.send_queue, - &state->vector, 1); + state->vector, + ARRAY_SIZE(state->vector)); if (subreq == NULL) { return NT_STATUS_NO_MEMORY; } diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c index 12a9d22..a03abf7 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -277,6 +277,9 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session, label.data, label.length, context.data, context.length, x->global->encryption_key.data); + + generate_random_buffer((uint8_t *)&x->nonce_high, sizeof(x->nonce_high)); + x->nonce_low = 1; } x->global->application_key = data_blob_dup_talloc(x->global, -- Samba Shared Repository