summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2012-08-22 10:33:07 +0200
committerStefan Metzmacher <metze@samba.org>2012-08-23 10:01:14 +0200
commit069db9b630b19835e8a008b50c0bed4d7245bf51 (patch)
tree6bda1f4e48526b4b4d507235a3df7c0b1f4ee706 /source3
parent54dfd08cb2970fcf2ad915f1ac0caec626cdd44e (diff)
downloadsamba-069db9b630b19835e8a008b50c0bed4d7245bf51.tar.gz
samba-069db9b630b19835e8a008b50c0bed4d7245bf51.tar.bz2
samba-069db9b630b19835e8a008b50c0bed4d7245bf51.zip
s3:smb2_break: encrypt OPLOCK BREAK notifications
metze Autobuild-User(master): Stefan Metzmacher <metze@samba.org> Autobuild-Date(master): Thu Aug 23 10:01:14 CEST 2012 on sn-devel-104
Diffstat (limited to 'source3')
-rw-r--r--source3/smbd/globals.h5
-rw-r--r--source3/smbd/smb2_break.c27
-rw-r--r--source3/smbd/smb2_server.c93
3 files changed, 107 insertions, 18 deletions
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index b024fb35f8..6af17a47c3 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 8143b8b976..8db9e6ddec 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 ad5b70e928..be7997febf 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -2694,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) {
@@ -2716,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);
@@ -2737,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;
}