The branch, master has been updated via 1b487ad s3:selftest: add some tests against a share the requires encryption via 45471f4 s3:smb2_negprot: annouce/negotiate SMB3 encryption support via 9397d67 s3:smb2_server: add SMB3 encryption support via 9f1dfd8 s3:smbd: don't disconnect the client when a share has "smb encrypt = required" via e5d4e8d s3:smbd: lp_smb_encrypt() returns SMB_SIGNING_* values via 8b3da9a s3:smbd: make use of ENCRYPTION_REQUIRED() via abf018e libcli/smb: make sure the SMB2_TRANSFORM pdu is complete via e2b07c0 s4:libcli/smb2: reset trsnport->compound.related when a compound chain is finished from 6ce362a build: Ensure -Werror=format works with -Wformat=2 on NULL format strings
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 1b487ad3d7f709b0a100ccdc6fc30dcf7d0b778c Author: Stefan Metzmacher <me...@samba.org> Date: Fri Aug 17 08:50:21 2012 +0200 s3:selftest: add some tests against a share the requires encryption metze Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Fri Aug 17 16:34:26 CEST 2012 on sn-devel-104 commit 45471f4d8f80d80c01197536bcf47d932dcd38e0 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Aug 8 07:07:53 2012 +0200 s3:smb2_negprot: annouce/negotiate SMB3 encryption support metze commit 9397d6709f79f2e8837401d32cd7ac584b6c5b24 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Aug 8 07:07:03 2012 +0200 s3:smb2_server: add SMB3 encryption support metze commit 9f1dfd8facaa59370afd93e89cc729de5cc3d9ba Author: Stefan Metzmacher <me...@samba.org> Date: Fri Aug 17 09:42:27 2012 +0200 s3:smbd: don't disconnect the client when a share has "smb encrypt = required" It's not the client fault, if he doesn't know that encryption is required. We should just return ACCESS_DENIED and let the client work on other shares and open files on the current SMB connection. metze commit e5d4e8df6b8186b71aa72dd7817f5579b44fee2f Author: Stefan Metzmacher <me...@samba.org> Date: Fri Aug 17 09:40:52 2012 +0200 s3:smbd: lp_smb_encrypt() returns SMB_SIGNING_* values metze commit 8b3da9a1f400040eef14b63ed0b7884a9e82d907 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Aug 17 09:41:42 2012 +0200 s3:smbd: make use of ENCRYPTION_REQUIRED() metze commit abf018e8b64b237aa029978c20bd418524fff3d0 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Aug 17 08:31:52 2012 +0200 libcli/smb: make sure the SMB2_TRANSFORM pdu is complete metze commit e2b07c0adca680d73f20744fd8dbbcb8be818ca3 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Aug 17 08:25:08 2012 +0200 s4:libcli/smb2: reset trsnport->compound.related when a compound chain is finished metze ----------------------------------------------------------------------- Summary of changes: libcli/smb/smbXcli_base.c | 15 ++- selftest/knownfail | 5 + selftest/target/Samba3.pm | 4 + selftest/target/Samba4.pm | 4 + source3/include/smb_macros.h | 2 +- source3/param/loadparm.c | 2 +- source3/selftest/tests.py | 9 +- source3/smbd/globals.h | 52 ++++-- source3/smbd/process.c | 10 +- source3/smbd/smb2_negprot.c | 8 + source3/smbd/smb2_server.c | 350 +++++++++++++++++++++++++++++++++++---- source3/smbd/trans2.c | 20 +-- source4/libcli/smb2/transport.c | 1 + 13 files changed, 412 insertions(+), 70 deletions(-) Changeset truncated at 500 lines: diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c index a9adcbb..02d0227 100644 --- a/libcli/smb/smbXcli_base.c +++ b/libcli/smb/smbXcli_base.c @@ -3041,6 +3041,7 @@ static NTSTATUS smb2cli_inbuf_parse_compound(struct smbXcli_conn *conn, struct smbXcli_session *s; uint64_t uid; struct iovec tf_iov[2]; + size_t enc_len; NTSTATUS status; if (len < SMB2_TF_HDR_SIZE) { @@ -3053,9 +3054,16 @@ static NTSTATUS smb2cli_inbuf_parse_compound(struct smbXcli_conn *conn, taken += tf_len; hdr = first_hdr + taken; - len = IVAL(tf, SMB2_TF_MSG_SIZE); + enc_len = IVAL(tf, SMB2_TF_MSG_SIZE); uid = BVAL(tf, SMB2_TF_SESSION_ID); + if (len < SMB2_TF_HDR_SIZE + enc_len) { + DEBUG(10, ("%d bytes left, expected at least %d\n", + (int)len, + (int)(SMB2_TF_HDR_SIZE + enc_len))); + goto inval; + } + s = conn->sessions; for (; s; s = s->next) { if (s->smb2->session_id != uid) { @@ -3073,7 +3081,7 @@ static NTSTATUS smb2cli_inbuf_parse_compound(struct smbXcli_conn *conn, tf_iov[0].iov_base = (void *)tf; tf_iov[0].iov_len = tf_len; tf_iov[1].iov_base = (void *)hdr; - tf_iov[1].iov_len = len; + tf_iov[1].iov_len = enc_len; status = smb2_signing_decrypt_pdu(s->smb2->decryption_key, conn->protocol, @@ -3083,7 +3091,8 @@ static NTSTATUS smb2cli_inbuf_parse_compound(struct smbXcli_conn *conn, return status; } - verified_buflen = taken + len; + verified_buflen = taken + enc_len; + len = enc_len; } /* diff --git a/selftest/knownfail b/selftest/knownfail index da3d93c..9376264 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -21,6 +21,11 @@ ^samba3.smbtorture_s3.plain\(dc\).BAD-NBT-SESSION # Fails against the s4 ntvfs server ^samba3.smbtorture_s3.plain\(dc\).SMB2-SESSION-REAUTH # Fails against the s4 ntvfs server ^samba3.smbtorture_s3.plain\(dc\).SMB2-SESSION-RECONNECT # Fails against the s4 ntvfs server + ^samba3.smbtorture_s3.crypt_server\(s3dc\).SMB2-SESSION-REAUTH # expected to give ACCESS_DENIED SMB2.1 doesn't have encryption +^samba3.smbtorture_s3.crypt_server\(s3dc\).SMB2-SESSION-RECONNECT # expected to give CONNECTION_DISCONNECTED, we need to fix the test +^samba3.smb2.session enc.reconnect # expected to give CONNECTION_DISCONNECTED, we need to fix the test +^samba3.raw.session enc # expected to give ACCESS_DENIED as SMB1 encryption isn't used +^samba3.smbtorture_s3.crypt_server # expected to give ACCESS_DENIED as SMB1 encryption isn't used ^samba3.nbt.dgram.*netlogon2\(s3dc\) ^samba3.*rap.sam.*.useradd # Not provided by Samba 3 ^samba3.*rap.sam.*.userdelete # Not provided by Samba 3 diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 149a31e..72b9c19 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -939,6 +939,10 @@ sub provision($$$$$$) [tmp] path = $shrdir comment = smb username is [%U] +[tmpenc] + path = $shrdir + comment = encrypt smb username is [%U] + smb encrypt = required [tmpguest] path = $shrdir guest ok = yes diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index b1998a6..17afab2 100644 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -1385,6 +1385,10 @@ sub provision_plugin_s4_dc($$) my $extra_smbconf_shares = " +[tmpenc] + copy = tmp + smb encrypt = required + [tmpcase] copy = tmp case sensitive = yes diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h index 73f8fb3..8b9d941 100644 --- a/source3/include/smb_macros.h +++ b/source3/include/smb_macros.h @@ -139,7 +139,7 @@ #define smb_len_large(buf) smb_len_tcp(buf) #define _smb_setlen_large(buf, len) _smb_setlen_tcp(buf, len) -#define ENCRYPTION_REQUIRED(conn) ((conn) ? ((conn)->encrypt_level == Required) : false) +#define ENCRYPTION_REQUIRED(conn) ((conn) ? ((conn)->encrypt_level == SMB_SIGNING_REQUIRED) : false) #define IS_CONN_ENCRYPTED(conn) ((conn) ? (conn)->encrypted_tid : false) /**************************************************************************** diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index d7141ae..bce1c5b 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -281,7 +281,7 @@ static struct loadparm_service sDefault = #else .iDirectoryNameCacheSize = 100, #endif - .ismb_encrypt = Auto, + .ismb_encrypt = SMB_SIGNING_DEFAULT, .param_opt = NULL, .dummy = "" }; diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 00ecd6c..f9f2e22 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -95,7 +95,11 @@ tests=[ "FDPASS", "LOCK1", "LOCK2", "LOCK3", "LOCK4", "LOCK5", "LOCK6", "LOCK7", for t in tests: plantestsuite("samba3.smbtorture_s3.plain(s3dc).%s" % t, "s3dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/tmp', '$USERNAME', '$PASSWORD', smbtorture3, "", "-l $LOCAL_PATH"]) - plantestsuite("samba3.smbtorture_s3.crypt(s3dc).%s" % t, "s3dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/tmp', '$USERNAME', '$PASSWORD', smbtorture3, "-e", "-l $LOCAL_PATH"]) + plantestsuite("samba3.smbtorture_s3.crypt_client(s3dc).%s" % t, "s3dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/tmp', '$USERNAME', '$PASSWORD', smbtorture3, "-e", "-l $LOCAL_PATH"]) + if t == "TORTURE": + # this is a negative test to verify that the server rejects + # access without encryption + plantestsuite("samba3.smbtorture_s3.crypt_server(s3dc).%s" % t, "s3dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/tmpenc', '$USERNAME', '$PASSWORD', smbtorture3, "", "-l $LOCAL_PATH"]) plantestsuite("samba3.smbtorture_s3.plain(dc).%s" % t, "dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/tmp', '$USERNAME', '$PASSWORD', smbtorture3, "", "-l $LOCAL_PATH"]) posix_tests=[ "POSIX", "POSIX-APPEND"] @@ -333,7 +337,8 @@ for t in tests: plansmbtorturetestsuite(t, "secshare", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD') plansmbtorturetestsuite(t, "plugin_s4_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD') elif t == "raw.session" or t == "smb2.session": - plansmbtorturetestsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD') + plansmbtorturetestsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD', 'plain') + plansmbtorturetestsuite(t, "s3dc", '//$SERVER_IP/tmpenc -U$USERNAME%$PASSWORD', 'enc') plansmbtorturetestsuite(t, "plugin_s4_dc", '//$SERVER/tmp -k no -U$USERNAME%$PASSWORD', 'ntlm') plansmbtorturetestsuite(t, "plugin_s4_dc", '//$SERVER/tmp -k yes -U$USERNAME%$PASSWORD', 'krb5') elif t == "rpc.lsa": diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index ac8a1b2..b024fb3 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -462,7 +462,12 @@ struct smbd_smb2_request { bool compound_related; /* - * the signing/encryption key for the last + * the encryption key for the whole + * compound chain + */ + DATA_BLOB first_key; + /* + * the signing key for the last * request/response of a compound chain */ DATA_BLOB last_key; @@ -481,15 +486,18 @@ struct smbd_smb2_request { */ struct tevent_req *subreq; -#define SMBD_SMB2_HDR_IOV_OFS 0 -#define SMBD_SMB2_BODY_IOV_OFS 1 -#define SMBD_SMB2_DYN_IOV_OFS 2 +#define SMBD_SMB2_TF_IOV_OFS 0 +#define SMBD_SMB2_HDR_IOV_OFS 1 +#define SMBD_SMB2_BODY_IOV_OFS 2 +#define SMBD_SMB2_DYN_IOV_OFS 3 -#define SMBD_SMB2_NUM_IOV_PER_REQ 3 +#define SMBD_SMB2_NUM_IOV_PER_REQ 4 #define SMBD_SMB2_IOV_IDX_OFS(req,dir,idx,ofs) \ (&req->dir.vector[(idx)+(ofs)]) +#define SMBD_SMB2_IDX_TF_IOV(req,dir,idx) \ + SMBD_SMB2_IOV_IDX_OFS(req,dir,idx,SMBD_SMB2_TF_IOV_OFS) #define SMBD_SMB2_IDX_HDR_IOV(req,dir,idx) \ SMBD_SMB2_IOV_IDX_OFS(req,dir,idx,SMBD_SMB2_HDR_IOV_OFS) #define SMBD_SMB2_IDX_BODY_IOV(req,dir,idx) \ @@ -497,6 +505,8 @@ struct smbd_smb2_request { #define SMBD_SMB2_IDX_DYN_IOV(req,dir,idx) \ SMBD_SMB2_IOV_IDX_OFS(req,dir,idx,SMBD_SMB2_DYN_IOV_OFS) +#define SMBD_SMB2_IN_TF_IOV(req) SMBD_SMB2_IDX_TF_IOV(req,in,req->current_idx) +#define SMBD_SMB2_IN_TF_PTR(req) (uint8_t *)(SMBD_SMB2_IN_TF_IOV(req)->iov_base) #define SMBD_SMB2_IN_HDR_IOV(req) SMBD_SMB2_IDX_HDR_IOV(req,in,req->current_idx) #define SMBD_SMB2_IN_HDR_PTR(req) (uint8_t *)(SMBD_SMB2_IN_HDR_IOV(req)->iov_base) #define SMBD_SMB2_IN_BODY_IOV(req) SMBD_SMB2_IDX_BODY_IOV(req,in,req->current_idx) @@ -506,6 +516,8 @@ struct smbd_smb2_request { #define SMBD_SMB2_IN_DYN_PTR(req) (uint8_t *)(SMBD_SMB2_IN_DYN_IOV(req)->iov_base) #define SMBD_SMB2_IN_DYN_LEN(req) (SMBD_SMB2_IN_DYN_IOV(req)->iov_len) +#define SMBD_SMB2_OUT_TF_IOV(req) SMBD_SMB2_IDX_TF_IOV(req,out,req->current_idx) +#define SMBD_SMB2_OUT_TF_PTR(req) (uint8_t *)(SMBD_SMB2_OUT_TF_IOV(req)->iov_base) #define SMBD_SMB2_OUT_HDR_IOV(req) SMBD_SMB2_IDX_HDR_IOV(req,out,req->current_idx) #define SMBD_SMB2_OUT_HDR_PTR(req) (uint8_t *)(SMBD_SMB2_OUT_HDR_IOV(req)->iov_base) #define SMBD_SMB2_OUT_BODY_IOV(req) SMBD_SMB2_IDX_BODY_IOV(req,out,req->current_idx) @@ -517,17 +529,19 @@ struct smbd_smb2_request { struct { /* - * vector[0] TRANSPORT HEADER + * vector[0] TRANSPORT HEADER (empty) * . - * vector[1] SMB2 - * vector[2] fixed body - * vector[3] dynamic body + * vector[1] SMB2_TRANSFORM (optional) + * vector[2] SMB2 + * vector[3] fixed body + * vector[4] dynamic body * . * . * . - * vector[4] SMB2 - * vector[5] fixed body - * vector[6] dynamic body + * vector[5] SMB2_TRANSFORM (optional) + * vector[6] SMB2 + * vector[7] fixed body + * vector[8] dynamic body * . * . * . @@ -541,15 +555,17 @@ struct smbd_smb2_request { /* * vector[0] TRANSPORT HEADER * . - * vector[1] SMB2 - * vector[2] fixed body - * vector[3] dynamic body + * vector[1] SMB2_TRANSFORM (optional) + * vector[2] SMB2 + * vector[3] fixed body + * vector[4] dynamic body * . * . * . - * vector[4] SMB2 - * vector[5] fixed body - * vector[6] dynamic body + * vector[5] SMB2_TRANSFORM (empty) + * vector[6] SMB2 + * vector[7] fixed body + * vector[8] dynamic body * . * . * . diff --git a/source3/smbd/process.c b/source3/smbd/process.c index dd26a27..fd2c6a4 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1492,11 +1492,15 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req) if (req->encrypted) { conn->encrypted_tid = true; /* encrypted required from now on. */ - conn->encrypt_level = Required; + conn->encrypt_level = SMB_SIGNING_REQUIRED; } else if (ENCRYPTION_REQUIRED(conn)) { if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) { - exit_server_cleanly("encryption required " - "on connection"); + DEBUG(1,("service[%s] requires encryption" + "%s ACCESS_DENIED. mid=%llu\n", + lp_servicename(talloc_tos(), SNUM(conn)), + smb_fn_name(type), + (unsigned long long)req->mid)); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); return conn; } } diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index d086566..11ec2a5 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -254,6 +254,14 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) capabilities |= SMB2_CAP_DFS; } + if ((protocol >= PROTOCOL_SMB2_24) && + (lp_smb_encrypt(-1) != SMB_SIGNING_OFF)) + { + if (in_capabilities & SMB2_CAP_ENCRYPTION) { + capabilities |= SMB2_CAP_ENCRYPTION; + } + } + /* * 0x10000 (65536) is the maximum allowed message size * for SMB 2.0 diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index ff4ee60..106e6ac 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -256,6 +256,7 @@ static void smb2_setup_nbt_length(struct iovec *vector, int count) static int smbd_smb2_request_destructor(struct smbd_smb2_request *req) { + data_blob_clear_free(&req->first_key); data_blob_clear_free(&req->last_key); return 0; } @@ -303,6 +304,9 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn, int num_iov = 1; size_t taken = 0; uint8_t *first_hdr = buf; + size_t verified_buflen = 0; + uint8_t *tf = NULL; + size_t tf_len = 0; /* * Note: index '0' is reserved for the transport protocol @@ -324,6 +328,87 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn, uint8_t *dyn = NULL; struct iovec *iov_tmp; + if (verified_buflen > taken) { + len = verified_buflen - taken; + } else { + tf = NULL; + tf_len = 0; + } + + if (len < 4) { + DEBUG(10, ("%d bytes left, expected at least %d\n", + (int)len, 4)); + goto inval; + } + if (IVAL(hdr, 0) == SMB2_TF_MAGIC) { + struct smbXsrv_session *s = NULL; + uint64_t uid; + struct iovec tf_iov[2]; + NTSTATUS status; + size_t enc_len; + + if (conn->protocol < PROTOCOL_SMB2_24) { + DEBUG(10, ("Got SMB2_TRANSFORM header, " + "but dialect[0x%04X] is used\n", + conn->smb2.server.dialect)); + goto inval; + } + + if (!(conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) { + DEBUG(10, ("Got SMB2_TRANSFORM header, " + "but not negotiated " + "client[0x%08X] server[0x%08X]\n", + conn->smb2.client.capabilities, + conn->smb2.server.capabilities)); + goto inval; + } + + if (len < SMB2_TF_HDR_SIZE) { + DEBUG(1, ("%d bytes left, expected at least %d\n", + (int)len, SMB2_TF_HDR_SIZE)); + goto inval; + } + tf = hdr; + tf_len = SMB2_TF_HDR_SIZE; + taken += tf_len; + + hdr = first_hdr + taken; + enc_len = IVAL(tf, SMB2_TF_MSG_SIZE); + uid = BVAL(tf, SMB2_TF_SESSION_ID); + + if (len < SMB2_TF_HDR_SIZE + enc_len) { + DEBUG(1, ("%d bytes left, expected at least %d\n", + (int)len, + (int)(SMB2_TF_HDR_SIZE + enc_len))); + goto inval; + } + + status = smb2srv_session_lookup(conn, uid, now, &s); + if (s == NULL) { + DEBUG(1, ("invalid session[%llu] in " + "SMB2_TRANSFORM header\n", + (unsigned long long)uid)); + TALLOC_FREE(iov); + return NT_STATUS_USER_SESSION_DELETED; + } + + tf_iov[0].iov_base = (void *)tf; + tf_iov[0].iov_len = tf_len; + tf_iov[1].iov_base = (void *)hdr; + tf_iov[1].iov_len = enc_len; + + status = smb2_signing_decrypt_pdu(s->global->decryption_key, + conn->protocol, + tf_iov, 2); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(iov); + return status; + } + + verified_buflen = taken + enc_len; + len = enc_len; + } + /* * We need the header plus the body length field */ @@ -382,6 +467,8 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn, cur = &iov[num_iov]; num_iov += SMBD_SMB2_NUM_IOV_PER_REQ; + cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf; + cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len; cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr; cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY; cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body; @@ -891,6 +978,12 @@ static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req) outbody = outhdr + SMB2_HDR_BODY; + /* + * SMBD_SMB2_TF_IOV_OFS might be used later + */ + current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL; + current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0; + current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr; current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY; @@ -949,10 +1042,12 @@ void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn, exit_server_cleanly(reason); } -static bool dup_smb2_vec3(TALLOC_CTX *ctx, +static bool dup_smb2_vec4(TALLOC_CTX *ctx, struct iovec *outvec, const struct iovec *srcvec) { + const uint8_t *srctf; + size_t srctf_len; const uint8_t *srchdr; size_t srchdr_len; const uint8_t *srcbody; @@ -961,10 +1056,13 @@ static bool dup_smb2_vec3(TALLOC_CTX *ctx, const uint8_t *srcdyn; size_t srcdyn_len; const uint8_t *expected_srcdyn; + uint8_t *dsttf; uint8_t *dsthdr; uint8_t *dstbody; uint8_t *dstdyn; + srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base; + srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len; srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base; srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len; srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base; @@ -974,10 +1072,25 @@ static bool dup_smb2_vec3(TALLOC_CTX *ctx, srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len; expected_srcdyn = srcbody + 8; + if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) { + return false; + } + if (srchdr_len != SMB2_HDR_BODY) { return false; } + if (srctf_len == SMB2_TF_HDR_SIZE) { + dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE); + if (dsttf == NULL) { + return false; + } + } else { + dsttf = NULL; + } + outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf; + outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len; + /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must * be allocated with size OUTVEC_ALLOC_SIZE. */ @@ -1061,7 +1174,7 @@ static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *re /* Setup the vectors identically to the ones in req. */ for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) { - if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) { + if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) { break; } } @@ -1083,6 +1196,8 @@ static void smbd_smb2_request_writev_done(struct tevent_req *subreq); static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req) { struct smbXsrv_connection *conn = req->sconn->conn; + int first_idx = 1; -- Samba Shared Repository