[PATCH] Display status of encryption and signing in smbstatus

Volker Lendecke Volker.Lendecke at SerNet.DE
Fri Dec 11 08:23:09 UTC 2015


Hi!

On Wed, Dec 09, 2015 at 01:57:56PM +0100, Ralph Boehme wrote:
> Attached is a patchset that adds support for displaying the current
> status of signing and encryption per session and tcon.

Great stuff! I've added mostly r-b's, but also a few
comments. Superficially it's the 80-column thingy, but I do
think readability would benefit from helper functions here,
if possible.

Volker

-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From 874194d7e9857ef5dc9b2cf703349ccb54535b33 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 13 Nov 2015 17:00:29 +0100
Subject: [PATCH 01/17] smbstatus: remove obsolete verbose message

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/utils/status.c |   11 -----------
 1 file changed, 11 deletions(-)

diff --git a/source3/utils/status.c b/source3/utils/status.c
index 8d84537..876e0f0 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -500,17 +500,6 @@ int main(int argc, const char *argv[])
 	}
 
 	if ( show_shares ) {
-		if (verbose) {
-			db_path = lock_path("connections.tdb");
-			if (db_path == NULL) {
-				d_printf("Out of memory - exiting\n");
-				ret = -1;
-				goto done;
-			}
-			d_printf("Opened %s\n", db_path);
-			TALLOC_FREE(db_path);
-		}
-
 		if (brief) {
 			goto done;
 		}
-- 
1.7.9.5


From 7d8608761e5d4a55a61d49518b779918a86ff461 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 9 Nov 2015 17:23:29 +0100
Subject: [PATCH 02/17] s3:smb2_server: convert encryption desired and
 required bools to flags

This adds a bitmap smbXsrv_encrpytion_flags with flags to the
smbXsrv_session_global.tdb and smbXsrv_tcon_global.tdb that we use
instead of bools for desired and required.

We need this info in the smbXsrv tdbs for smbstatus. Subsequent commits
for smbstatus will use it.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/librpc/idl/smbXsrv.idl |   11 +++++++----
 source3/smbd/smb2_server.c     |   12 ++++++------
 source3/smbd/smb2_sesssetup.c  |   12 ++++++------
 source3/smbd/smb2_tcon.c       |   12 ++++++++----
 4 files changed, 27 insertions(+), 20 deletions(-)

diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl
index 4062610..ab4937e 100644
--- a/source3/librpc/idl/smbXsrv.idl
+++ b/source3/librpc/idl/smbXsrv.idl
@@ -116,6 +116,11 @@ interface smbXsrv
 
 	/* sessions */
 
+	typedef [public,bitmap8bit] bitmap {
+		SMBXSRV_ENCRYPTION_REQUIRED		= 0x01,
+		SMBXSRV_ENCRYPTION_DESIRED		= 0x02
+	} smbXsrv_encrpytion_flags;
+
 	typedef struct {
 		server_id				server_id;
 		[charset(UTF8),string] char		local_address[];
@@ -141,7 +146,7 @@ interface smbXsrv
 		auth_session_info			*auth_session_info;
 		uint16					connection_dialect;
 		boolean8				signing_required;
-		boolean8				encryption_required;
+		smbXsrv_encrpytion_flags		encryption_flags;
 		[noprint] DATA_BLOB			signing_key;
 		[noprint] DATA_BLOB			encryption_key;
 		[noprint] DATA_BLOB			decryption_key;
@@ -206,7 +211,6 @@ interface smbXsrv
 		[ignore] user_struct			*compat;
 		[ignore] smbXsrv_tcon_table		*tcon_table;
 		smbXsrv_session_auth0			*pending_auth;
-		boolean8				encryption_desired;
 	} smbXsrv_session;
 
 	typedef union {
@@ -259,7 +263,7 @@ interface smbXsrv
 		server_id				server_id;
 		NTTIME					creation_time;
 		[charset(UTF8),string] char		share_name[];
-		boolean8				encryption_required;
+		smbXsrv_encrpytion_flags		encryption_flags;
 		/*
 		 * for SMB1 this is the session that the tcon was opened on
 		 */
@@ -301,7 +305,6 @@ interface smbXsrv
 		NTSTATUS				status;
 		NTTIME					idle_time;
 		[ignore] connection_struct		*compat;
-		boolean8				encryption_desired;
 	} smbXsrv_tcon;
 
 	typedef union {
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index cdcead0..bd8261a 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -2067,8 +2067,8 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 	x = req->session;
 	if (x != NULL) {
 		signing_required = x->global->signing_required;
-		encryption_desired = x->encryption_desired;
-		encryption_required = x->global->encryption_required;
+		encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
+		encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
 	}
 
 	req->do_signing = false;
@@ -2224,10 +2224,10 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		if (!NT_STATUS_IS_OK(status)) {
 			return smbd_smb2_request_error(req, status);
 		}
-		if (req->tcon->encryption_desired) {
+		if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
 			encryption_desired = true;
 		}
-		if (req->tcon->global->encryption_required) {
+		if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
 			encryption_required = true;
 		}
 		if (encryption_required && !req->was_encrypted) {
@@ -2882,8 +2882,8 @@ static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
 
 	if (session != NULL) {
 		session_wire_id = session->global->session_wire_id;
-		do_encryption = session->encryption_desired;
-		if (tcon->encryption_desired) {
+		do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
+		if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
 			do_encryption = true;
 		}
 	}
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
index 14249df..394bcf5 100644
--- a/source3/smbd/smb2_sesssetup.c
+++ b/source3/smbd/smb2_sesssetup.c
@@ -268,12 +268,12 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
 
 	if ((lp_smb_encrypt(-1) >= SMB_SIGNING_DESIRED) &&
 	    (xconn->smb2.client.capabilities & SMB2_CAP_ENCRYPTION)) {
-		x->encryption_desired = true;
+		x->global->encryption_flags = SMBXSRV_ENCRYPTION_DESIRED;
 	}
 
 	if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED) {
-		x->encryption_desired = true;
-		x->global->encryption_required = true;
+		x->global->encryption_flags = SMBXSRV_ENCRYPTION_REQUIRED |
+			SMBXSRV_ENCRYPTION_DESIRED;
 	}
 
 	if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
@@ -285,13 +285,13 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
 		guest = true;
 	}
 
-	if (guest && x->global->encryption_required) {
+	if (guest && (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED)) {
 		DEBUG(1,("reject guest session as encryption is required\n"));
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
 	if (xconn->smb2.server.cipher == 0) {
-		if (x->global->encryption_required) {
+		if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
 			DEBUG(1,("reject session with dialect[0x%04X] "
 				 "as encryption is required\n",
 				 xconn->smb2.server.dialect));
@@ -299,7 +299,7 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
 		}
 	}
 
-	if (x->encryption_desired) {
+	if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
 		*out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
 	}
 
diff --git a/source3/smbd/smb2_tcon.c b/source3/smbd/smb2_tcon.c
index 99e2f21..61e2a36 100644
--- a/source3/smbd/smb2_tcon.c
+++ b/source3/smbd/smb2_tcon.c
@@ -193,8 +193,8 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
 	connection_struct *compat_conn = NULL;
 	struct user_struct *compat_vuser = req->session->compat;
 	NTSTATUS status;
-	bool encryption_desired = req->session->encryption_desired;
-	bool encryption_required = req->session->global->encryption_required;
+	bool encryption_desired = req->session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
+	bool encryption_required = req->session->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
 	bool guest_session = false;
 	bool require_signed_tcon = false;
 
@@ -298,8 +298,12 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
 		return status;
 	}
 
-	tcon->encryption_desired = encryption_desired;
-	tcon->global->encryption_required = encryption_required;
+	if (encryption_desired) {
+		tcon->global->encryption_flags |= SMBXSRV_ENCRYPTION_DESIRED;
+	}
+	if (encryption_required) {
+		tcon->global->encryption_flags |= SMBXSRV_ENCRYPTION_REQUIRED;
+	}
 
 	compat_conn = make_connection_smb2(req,
 					tcon, snum,
-- 
1.7.9.5


From 35d203d4080fb5b9483bad8f1ab0c11c0b0fdd40 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 13 Nov 2015 10:35:58 +0100
Subject: [PATCH 03/17] s3:smb2_server: store encryption cipher in the channel

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/librpc/idl/smbXsrv.idl |    1 +
 source3/smbd/smb2_sesssetup.c  |    2 ++
 2 files changed, 3 insertions(+)

diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl
index ab4937e..109151b 100644
--- a/source3/librpc/idl/smbXsrv.idl
+++ b/source3/librpc/idl/smbXsrv.idl
@@ -129,6 +129,7 @@ interface smbXsrv
 		[noprint] DATA_BLOB			signing_key;
 		uint32					auth_session_info_seqnum;
 		[ignore] smbXsrv_connection		*connection;
+		uint16					encryption_cipher;
 	} smbXsrv_channel_global0;
 
 	typedef struct {
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
index 394bcf5..b599fc4 100644
--- a/source3/smbd/smb2_sesssetup.c
+++ b/source3/smbd/smb2_sesssetup.c
@@ -297,6 +297,8 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
 				 xconn->smb2.server.dialect));
 			return NT_STATUS_ACCESS_DENIED;
 		}
+	} else {
+		x->global->channels[0].encryption_cipher = xconn->smb2.server.cipher;
 	}
 
 	if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
-- 
1.7.9.5


From cb159c933d6131de1ca120ec0dd244e22ee5643f Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 13 Nov 2015 10:30:50 +0100
Subject: [PATCH 04/17] VL: Can we get the lines under 80 columns, possibly
 via a helper function?

s3:smb2_server: add encryption state tracking flags

Add two encryption state tracking flags that can be used to tell whether
a session or tcon is "encrypted" and add a helper function to calculate
the encryption state from those flags.

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/librpc/idl/smbXsrv.idl |    4 ++-
 source3/smbd/globals.h         |    2 ++
 source3/smbd/smb2_server.c     |   62 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl
index 109151b..5078d0d 100644
--- a/source3/librpc/idl/smbXsrv.idl
+++ b/source3/librpc/idl/smbXsrv.idl
@@ -118,7 +118,9 @@ interface smbXsrv
 
 	typedef [public,bitmap8bit] bitmap {
 		SMBXSRV_ENCRYPTION_REQUIRED		= 0x01,
-		SMBXSRV_ENCRYPTION_DESIRED		= 0x02
+		SMBXSRV_ENCRYPTION_DESIRED		= 0x02,
+		SMBXSRV_PROCESSED_ENCRYPTED_PACKET	= 0x04,
+		SMBXSRV_PROCESSED_UNENCRYPTED_PACKET	= 0x08
 	} smbXsrv_encrpytion_flags;
 
 	typedef struct {
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 0422cbe..822cced 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -636,6 +636,8 @@ NTSTATUS smbXsrv_open_global_traverse(
 	void *private_data);
 
 NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id);
+bool smbXsrv_is_encrypted(uint8_t encryption_flags);
+bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags);
 
 struct smbd_smb2_send_queue {
 	struct smbd_smb2_send_queue *prev, *next;
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index bd8261a..1e9da26 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -2004,6 +2004,21 @@ NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
 	return NT_STATUS_OK;
 }
 
+bool smbXsrv_is_encrypted(uint8_t encryption_flags)
+{
+	return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
+		&&
+		(encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
+				     SMBXSRV_ENCRYPTION_DESIRED |
+				     SMBXSRV_ENCRYPTION_REQUIRED)));
+}
+
+bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
+{
+	return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
+		(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
+}
+
 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 {
 	struct smbXsrv_connection *xconn = req->xconn;
@@ -2240,6 +2255,53 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		req->do_encryption = true;
 	}
 
+	/*
+	 * Update encryption state tracking flags, this can be used to
+	 * determine whether whether the session or tcon is
+	 * "encrypted".
+	 */
+	if (x) {
+		bool update_session_global = false;
+		bool update_tcon_global = false;
+
+		if (req->was_encrypted && req->do_encryption) {
+			if (!(x->global->encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET)) {
+				x->global->encryption_flags |= SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
+				update_session_global = true;
+			}
+			if (call->need_tcon) {
+				if (!(req->tcon->global->encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET)) {
+					req->tcon->global->encryption_flags |= SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
+					update_tcon_global = true;
+				}
+			}
+		} else {
+			if (!(x->global->encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)) {
+				x->global->encryption_flags |= SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
+				update_session_global = true;
+			}
+			if (call->need_tcon) {
+				if (!(req->tcon->global->encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)) {
+					req->tcon->global->encryption_flags |= SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
+					update_tcon_global = true;
+				}
+			}
+		}
+
+		if (update_session_global) {
+			status = smbXsrv_session_update(x);
+			if (!NT_STATUS_IS_OK(status)) {
+				return smbd_smb2_request_error(req, status);
+			}
+		}
+		if (update_tcon_global) {
+			status = smbXsrv_tcon_update(req->tcon);
+			if (!NT_STATUS_IS_OK(status)) {
+				return smbd_smb2_request_error(req, status);
+			}
+		}
+	}
+
 	if (call->fileid_ofs != 0) {
 		size_t needed = call->fileid_ofs + 16;
 		const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
-- 
1.7.9.5


From 796efe5028668675288e68f38f33d08b11a5bb74 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 30 Nov 2015 10:48:12 +0100
Subject: [PATCH 05/17] smbstatus: rework connection dialect printing

In a later change I want to print the signing cipher which depends upon
the connection dialect. So let's store the connection dialect in the
sessionid struct and move the code that maps dialect integers to strings
to smbstatus.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/include/session.h   |    2 +-
 source3/lib/sessionid_tdb.c |   35 +----------------------------------
 source3/utils/status.c      |   32 +++++++++++++++++++++++++++++++-
 3 files changed, 33 insertions(+), 36 deletions(-)

diff --git a/source3/include/session.h b/source3/include/session.h
index fe41954..92fc74f 100644
--- a/source3/include/session.h
+++ b/source3/include/session.h
@@ -38,6 +38,6 @@ struct sessionid {
 	struct server_id pid;
 	fstring ip_addr_str;
 	time_t connect_start;
-	fstring protocol_ver;
+	uint16_t connection_dialect;
 };
 
diff --git a/source3/lib/sessionid_tdb.c b/source3/lib/sessionid_tdb.c
index 68f9c43..88a2ff2 100644
--- a/source3/lib/sessionid_tdb.c
+++ b/source3/lib/sessionid_tdb.c
@@ -43,42 +43,9 @@ static int sessionid_traverse_read_fn(struct smbXsrv_session_global0 *global,
 		.id_num = global->session_global_id,
 		.connect_start = nt_time_to_unix(global->creation_time),
 		.pid = global->channels[0].server_id,
+		.connection_dialect = global->connection_dialect,
 	};
 
-	switch(global->connection_dialect){
-	case SMB2_DIALECT_REVISION_000:
-		fstrcpy(session.protocol_ver, "NT1");
-		break;
-	case SMB2_DIALECT_REVISION_202:
-		fstrcpy(session.protocol_ver, "SMB2_02");
-		break;
-	case SMB2_DIALECT_REVISION_210:
-		fstrcpy(session.protocol_ver, "SMB2_10");
-		break;
-	case SMB2_DIALECT_REVISION_222:
-		fstrcpy(session.protocol_ver, "SMB2_22");
-		break;
-	case SMB2_DIALECT_REVISION_224:
-		fstrcpy(session.protocol_ver, "SMB2_24");
-		break;
-	case SMB3_DIALECT_REVISION_300:
-		fstrcpy(session.protocol_ver, "SMB3_00");
-		break;
-	case SMB3_DIALECT_REVISION_302:
-		fstrcpy(session.protocol_ver, "SMB3_02");
-		break;
-	case SMB3_DIALECT_REVISION_310:
-		fstrcpy(session.protocol_ver, "SMB3_10");
-		break;
-	case SMB3_DIALECT_REVISION_311:
-		fstrcpy(session.protocol_ver, "SMB3_11");
-		break;
-	default:
-		fstr_sprintf(session.protocol_ver, "Unknown (0x%04x)",
-			     global->connection_dialect);
-		break;
-	}
-
 	if (session_info != NULL) {
 		session.uid = session_info->unix_token->uid;
 		session.gid = session_info->unix_token->gid;
diff --git a/source3/utils/status.c b/source3/utils/status.c
index 876e0f0..36c7023 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -266,6 +266,35 @@ static void print_brl(struct file_id id,
 	TALLOC_FREE(share_mode);
 }
 
+static const char *session_dialect_str(uint16_t dialect)
+{
+	static fstring unkown_dialect;
+
+	switch(dialect){
+	case SMB2_DIALECT_REVISION_000:
+		return "NT1";
+	case SMB2_DIALECT_REVISION_202:
+		return "SMB2_02";
+	case SMB2_DIALECT_REVISION_210:
+		return "SMB2_10";
+	case SMB2_DIALECT_REVISION_222:
+		return "SMB2_22";
+	case SMB2_DIALECT_REVISION_224:
+		return "SMB2_24";
+	case SMB3_DIALECT_REVISION_300:
+		return "SMB3_00";
+	case SMB3_DIALECT_REVISION_302:
+		return "SMB3_02";
+	case SMB3_DIALECT_REVISION_310:
+		return "SMB3_10";
+	case SMB3_DIALECT_REVISION_311:
+		return "SMB3_11";
+	}
+
+	fstr_sprintf(unkown_dialect, "Unknown (0x%04x)", dialect);
+	return unkown_dialect;
+}
+
 static int traverse_connections(const struct connections_key *key,
 				const struct connections_data *crec,
 				void *state)
@@ -325,7 +354,8 @@ static int traverse_sessionid(const char *key, struct sessionid *session,
 	d_printf("%-7s   %-12s  %-12s  %-12s (%s) %-12s\n",
 		 server_id_str_buf(session->pid, &tmp),
 		 uid_str, gid_str,
-		 session->remote_machine, session->hostname, session->protocol_ver);
+		 session->remote_machine, session->hostname,
+		 session_dialect_str(session->connection_dialect));
 
 	return 0;
 }
-- 
1.7.9.5


From 472cbd015c6703fcaf4ace688ec1f2439fcc2a84 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 19 Nov 2015 10:40:29 +0100
Subject: [PATCH 06/17] smbstatus: pass talloc context to traverse_sessionid

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/utils/status.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/source3/utils/status.c b/source3/utils/status.c
index 36c7023..aa78f77 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -320,6 +320,7 @@ static int traverse_connections(const struct connections_key *key,
 static int traverse_sessionid(const char *key, struct sessionid *session,
 			      void *private_data)
 {
+	TALLOC_CTX *mem_ctx = (TALLOC_CTX *)private_data;
 	fstring uid_str, gid_str;
 	struct server_id_buf tmp;
 
@@ -522,7 +523,7 @@ int main(int argc, const char *argv[])
 		d_printf("PID     Username      Group         Machine            Protocol Version       \n");
 		d_printf("------------------------------------------------------------------------------\n");
 
-		sessionid_traverse_read(traverse_sessionid, NULL);
+		sessionid_traverse_read(traverse_sessionid, frame);
 
 		if (processes_only) {
 			goto done;
-- 
1.7.9.5


From 40dc69ff8610ea805651a76d80448b7d7a7f0f76 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 19 Nov 2015 15:54:17 +0100
Subject: [PATCH 07/17] smbstatus: pass talloc context to traverse_connections

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/utils/status.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/source3/utils/status.c b/source3/utils/status.c
index aa78f77..3764e88 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -297,8 +297,9 @@ static const char *session_dialect_str(uint16_t dialect)
 
 static int traverse_connections(const struct connections_key *key,
 				const struct connections_data *crec,
-				void *state)
+				void *private_data)
 {
+	TALLOC_CTX *mem_ctx = (TALLOC_CTX *)private_data;
 	struct server_id_buf tmp;
 
 	if (crec->cnum == TID_FIELD_INVALID)
@@ -538,7 +539,7 @@ int main(int argc, const char *argv[])
 		d_printf("\nService      pid     machine       Connected at\n");
 		d_printf("-------------------------------------------------------\n");
 
-		connections_forall_read(traverse_connections, NULL);
+		connections_forall_read(traverse_connections, frame);
 
 		d_printf("\n");
 
-- 
1.7.9.5


From 71e009e2b0f00900ce57d79294df79f2139ba562 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 9 Nov 2015 17:02:38 +0100
Subject: [PATCH 08/17] VL: Why the first hunk? The effect would be that two
 fields fit into one 41 byte output fields. Why the
 separate talloc_asprintf?

smbstatus: align session list header and ouput

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/utils/status.c |   18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/source3/utils/status.c b/source3/utils/status.c
index 3764e88..1bf315a 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -324,6 +324,7 @@ static int traverse_sessionid(const char *key, struct sessionid *session,
 	TALLOC_CTX *mem_ctx = (TALLOC_CTX *)private_data;
 	fstring uid_str, gid_str;
 	struct server_id_buf tmp;
+	char *machine_hostname = NULL;
 
 	if (do_checks &&
 	    (!process_exists(session->pid) ||
@@ -353,12 +354,21 @@ static int traverse_sessionid(const char *key, struct sessionid *session,
 		}
 	}
 
-	d_printf("%-7s   %-12s  %-12s  %-12s (%s) %-12s\n",
+	machine_hostname = talloc_asprintf(mem_ctx, "%s (%s)",
+					   session->remote_machine,
+					   session->hostname);
+	if (machine_hostname == NULL) {
+		return -1;
+	}
+
+	d_printf("%-7s %-12s %-12s %-41s %-17s\n",
 		 server_id_str_buf(session->pid, &tmp),
 		 uid_str, gid_str,
-		 session->remote_machine, session->hostname,
+		 machine_hostname,
 		 session_dialect_str(session->connection_dialect));
 
+	TALLOC_FREE(machine_hostname);
+
 	return 0;
 }
 
@@ -521,8 +531,8 @@ int main(int argc, const char *argv[])
 
 	if ( show_processes ) {
 		d_printf("\nSamba version %s\n",samba_version_string());
-		d_printf("PID     Username      Group         Machine            Protocol Version       \n");
-		d_printf("------------------------------------------------------------------------------\n");
+		d_printf("%-7s %-12s %-12s %-41s %-17s\n", "PID", "Username", "Group", "Machine", "Protocol Version");
+		d_printf("--------------------------------------------------------------------------------------------\n");
 
 		sessionid_traverse_read(traverse_sessionid, frame);
 
-- 
1.7.9.5


From 9c1eb8d50641e5ece8dd998395314cf0fe3d0c63 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 9 Nov 2015 17:17:17 +0100
Subject: [PATCH 09/17] smbstatus: show encrpytion state of sessions

Show the encrpytion state of sessions in smbstatus. This is SMB3
only. CIFS UNIX extensions encryption will be added in a later commit.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/include/session.h   |    2 ++
 source3/lib/sessionid_tdb.c |    3 +++
 source3/utils/status.c      |   42 +++++++++++++++++++++++++++++++++++++-----
 3 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/source3/include/session.h b/source3/include/session.h
index 92fc74f..c73f9ee 100644
--- a/source3/include/session.h
+++ b/source3/include/session.h
@@ -39,5 +39,7 @@ struct sessionid {
 	fstring ip_addr_str;
 	time_t connect_start;
 	uint16_t connection_dialect;
+	uint8_t encryption_flags;
+	uint16_t cipher;
 };
 
diff --git a/source3/lib/sessionid_tdb.c b/source3/lib/sessionid_tdb.c
index 88a2ff2..02ed138 100644
--- a/source3/lib/sessionid_tdb.c
+++ b/source3/lib/sessionid_tdb.c
@@ -69,6 +69,9 @@ static int sessionid_traverse_read_fn(struct smbXsrv_session_global0 *global,
 		global->channels[0].remote_address,
 		sizeof(fstring)-1);
 
+	session.encryption_flags = global->encryption_flags;
+	session.cipher = global->channels[0].encryption_cipher;
+
 	return state->fn(NULL, &session, state->private_data);
 }
 
diff --git a/source3/utils/status.c b/source3/utils/status.c
index 1bf315a..41438af 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -31,6 +31,7 @@
  */
 
 #include "includes.h"
+#include "smbd/globals.h"
 #include "system/filesys.h"
 #include "popt_common.h"
 #include "dbwrap/dbwrap.h"
@@ -325,6 +326,8 @@ static int traverse_sessionid(const char *key, struct sessionid *session,
 	fstring uid_str, gid_str;
 	struct server_id_buf tmp;
 	char *machine_hostname = NULL;
+	int result = 0;
+	const char *encryption = "-";
 
 	if (do_checks &&
 	    (!process_exists(session->pid) ||
@@ -361,15 +364,44 @@ static int traverse_sessionid(const char *key, struct sessionid *session,
 		return -1;
 	}
 
-	d_printf("%-7s %-12s %-12s %-41s %-17s\n",
+	if (smbXsrv_is_encrypted(session->encryption_flags)) {
+		switch (session->cipher) {
+		case SMB2_ENCRYPTION_AES128_CCM:
+			encryption = "AES-128-CCM";
+			break;
+		case SMB2_ENCRYPTION_AES128_GCM:
+			encryption = "AES-128-GCM";
+			break;
+		default:
+			encryption = "???";
+			result = -1;
+			break;
+		}
+	} else if (smbXsrv_is_partially_encrypted(session->encryption_flags)) {
+		switch (session->cipher) {
+		case SMB2_ENCRYPTION_AES128_CCM:
+			encryption = "partial(AES-128-CCM)";
+			break;
+		case SMB2_ENCRYPTION_AES128_GCM:
+			encryption = "partial(AES-128-GCM)";
+			break;
+		default:
+			encryption = "???";
+			result = -1;
+			break;
+		}
+	}
+
+	d_printf("%-7s %-12s %-12s %-41s %-17s %-20s\n",
 		 server_id_str_buf(session->pid, &tmp),
 		 uid_str, gid_str,
 		 machine_hostname,
-		 session_dialect_str(session->connection_dialect));
+		 session_dialect_str(session->connection_dialect),
+		 encryption);
 
 	TALLOC_FREE(machine_hostname);
 
-	return 0;
+	return result;
 }
 
 
@@ -531,8 +563,8 @@ int main(int argc, const char *argv[])
 
 	if ( show_processes ) {
 		d_printf("\nSamba version %s\n",samba_version_string());
-		d_printf("%-7s %-12s %-12s %-41s %-17s\n", "PID", "Username", "Group", "Machine", "Protocol Version");
-		d_printf("--------------------------------------------------------------------------------------------\n");
+		d_printf("%-7s %-12s %-12s %-41s %-17s %-20s\n", "PID", "Username", "Group", "Machine", "Protocol Version", "Encryption");
+		d_printf("------------------------------------------------------------------------------------------------------------------\n");
 
 		sessionid_traverse_read(traverse_sessionid, frame);
 
-- 
1.7.9.5


From 0e841fcab4673cfc9b13760962c8259e9642f33f Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 9 Nov 2015 18:01:47 +0100
Subject: [PATCH 10/17] smbstatus: align tree connect header and output

Align output and use timestring() instead of time_to_asc(). The latter calls
asctime() which forces a \n into the time string.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/utils/status.c |   17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/source3/utils/status.c b/source3/utils/status.c
index 41438af..f92c84f 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -302,6 +302,7 @@ static int traverse_connections(const struct connections_key *key,
 {
 	TALLOC_CTX *mem_ctx = (TALLOC_CTX *)private_data;
 	struct server_id_buf tmp;
+	char *timestr = NULL;
 
 	if (crec->cnum == TID_FIELD_INVALID)
 		return 0;
@@ -311,10 +312,16 @@ static int traverse_connections(const struct connections_key *key,
 		return 0;
 	}
 
-	d_printf("%-10s   %s   %-12s  %s",
+	timestr = timestring(mem_ctx, crec->start);
+	if (timestr == NULL) {
+		return -1;
+	}
+
+	d_printf("%-12s %-7s %-13s %-32s\n",
 		 crec->servicename, server_id_str_buf(crec->pid, &tmp),
-		 crec->machine,
-		 time_to_asc(crec->start));
+		 crec->machine, timestr);
+
+	TALLOC_FREE(timestr);
 
 	return 0;
 }
@@ -578,8 +585,8 @@ int main(int argc, const char *argv[])
 			goto done;
 		}
 
-		d_printf("\nService      pid     machine       Connected at\n");
-		d_printf("-------------------------------------------------------\n");
+		d_printf("\n%-12s %-7s %-13s %-32s\n", "Service", "pid", "machine", "Connected at");
+		d_printf("-------------------------------------------------------------\n");
 
 		connections_forall_read(traverse_connections, frame);
 
-- 
1.7.9.5


From 74b37559a62353f6c5625f9a43a77631bfc5828f Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 9 Nov 2015 17:26:51 +0100
Subject: [PATCH 11/17] smbstatus: show encrpytion state of tree connects

Show the encrpytion state of tcons in smbstatus. This is SMB3 only. CIFS
UNIX extensions encryption will be added in a later commit.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/conn_tdb.c |    4 ++++
 source3/lib/conn_tdb.h |    2 ++
 source3/utils/status.c |   29 ++++++++++++++++++++++++-----
 3 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/source3/lib/conn_tdb.c b/source3/lib/conn_tdb.c
index bf66d7d..8eca0a0 100644
--- a/source3/lib/conn_tdb.c
+++ b/source3/lib/conn_tdb.c
@@ -41,6 +41,7 @@ struct connections_forall_session {
 	gid_t gid;
 	fstring machine;
 	fstring addr;
+	uint16_t cipher;
 };
 
 static int collect_sessions_fn(struct smbXsrv_session_global0 *global,
@@ -62,6 +63,7 @@ static int collect_sessions_fn(struct smbXsrv_session_global0 *global,
 	}
 	fstrcpy(sess.machine, global->channels[0].remote_name);
 	fstrcpy(sess.addr, global->channels[0].remote_address);
+	sess.cipher = global->channels[0].encryption_cipher;
 
 	status = dbwrap_store(state->session_by_pid,
 			      make_tdb_data((void*)&id, sizeof(id)),
@@ -123,6 +125,8 @@ static int traverse_tcon_fn(struct smbXsrv_tcon_global0 *global,
 	fstrcpy(data.addr, sess.addr);
 	fstrcpy(data.machine, sess.machine);
 	data.start = nt_time_to_unix(global->creation_time);
+	data.encryption_flags = global->encryption_flags;
+	data.cipher = sess.cipher;
 
 	state->count++;
 
diff --git a/source3/lib/conn_tdb.h b/source3/lib/conn_tdb.h
index 217814f..b57fef8 100644
--- a/source3/lib/conn_tdb.h
+++ b/source3/lib/conn_tdb.h
@@ -33,6 +33,8 @@ struct connections_data {
 	fstring addr;
 	fstring machine;
 	time_t start;
+	uint8_t encryption_flags;
+	uint16_t cipher;
 };
 
 /* The following definitions come from lib/conn_tdb.c  */
diff --git a/source3/utils/status.c b/source3/utils/status.c
index f92c84f..fd5522c 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -303,6 +303,8 @@ static int traverse_connections(const struct connections_key *key,
 	TALLOC_CTX *mem_ctx = (TALLOC_CTX *)private_data;
 	struct server_id_buf tmp;
 	char *timestr = NULL;
+	int result = 0;
+	const char *encryption = "-";
 
 	if (crec->cnum == TID_FIELD_INVALID)
 		return 0;
@@ -317,13 +319,30 @@ static int traverse_connections(const struct connections_key *key,
 		return -1;
 	}
 
-	d_printf("%-12s %-7s %-13s %-32s\n",
+	if (smbXsrv_is_encrypted(crec->encryption_flags)) {
+		switch (crec->cipher) {
+		case SMB2_ENCRYPTION_AES128_CCM:
+			encryption = "AES-128-CCM";
+			break;
+		case SMB2_ENCRYPTION_AES128_GCM:
+			encryption = "AES-128-GCM";
+			break;
+		default:
+			encryption = "???";
+			result = -1;
+			break;
+		}
+	}
+
+	d_printf("%-12s %-7s %-13s %-32s %-10s\n",
 		 crec->servicename, server_id_str_buf(crec->pid, &tmp),
-		 crec->machine, timestr);
+		 crec->machine,
+		 timestr,
+		 encryption);
 
 	TALLOC_FREE(timestr);
 
-	return 0;
+	return result;
 }
 
 static int traverse_sessionid(const char *key, struct sessionid *session,
@@ -585,8 +604,8 @@ int main(int argc, const char *argv[])
 			goto done;
 		}
 
-		d_printf("\n%-12s %-7s %-13s %-32s\n", "Service", "pid", "machine", "Connected at");
-		d_printf("-------------------------------------------------------------\n");
+		d_printf("\n%-12s %-7s %-13s %-32s %-10s\n", "Service", "pid", "Machine", "Connected at", "Encryption");
+		d_printf("---------------------------------------------------------------------------------\n");
 
 		connections_forall_read(traverse_connections, frame);
 
-- 
1.7.9.5


From 234266b23533da55f3b23ac001825378f0c7a73f Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 15 Nov 2015 10:49:38 +0100
Subject: [PATCH 12/17] s3:smb2_server: convert signing_required bool to flags
 bitmap

Use a flags bitmap for storing the signing state. This is in preparation
of a subsequent patch that adds more flags to the bitmap.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/librpc/idl/smbXsrv.idl |    6 +++++-
 source3/smbd/smb2_server.c     |    2 +-
 source3/smbd/smb2_sesssetup.c  |    4 ++--
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl
index 5078d0d..f6a5fd9 100644
--- a/source3/librpc/idl/smbXsrv.idl
+++ b/source3/librpc/idl/smbXsrv.idl
@@ -123,6 +123,10 @@ interface smbXsrv
 		SMBXSRV_PROCESSED_UNENCRYPTED_PACKET	= 0x08
 	} smbXsrv_encrpytion_flags;
 
+	typedef [public,bitmap8bit] bitmap {
+		SMBXSRV_SIGNING_REQUIRED		= 0x01
+	} smbXsrv_signing_flags;
+
 	typedef struct {
 		server_id				server_id;
 		[charset(UTF8),string] char		local_address[];
@@ -148,7 +152,7 @@ interface smbXsrv
 		uint32					auth_session_info_seqnum;
 		auth_session_info			*auth_session_info;
 		uint16					connection_dialect;
-		boolean8				signing_required;
+		smbXsrv_signing_flags			signing_flags;
 		smbXsrv_encrpytion_flags		encryption_flags;
 		[noprint] DATA_BLOB			signing_key;
 		[noprint] DATA_BLOB			encryption_key;
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 1e9da26..1a4a98c 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -2081,7 +2081,7 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 	session_status = smbd_smb2_request_check_session(req);
 	x = req->session;
 	if (x != NULL) {
-		signing_required = x->global->signing_required;
+		signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
 		encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
 		encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
 	}
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
index b599fc4..33d57bb 100644
--- a/source3/smbd/smb2_sesssetup.c
+++ b/source3/smbd/smb2_sesssetup.c
@@ -263,7 +263,7 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
 
 	if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
 	    lp_server_signing() == SMB_SIGNING_REQUIRED) {
-		x->global->signing_required = true;
+		x->global->signing_flags = SMBXSRV_SIGNING_REQUIRED;
 	}
 
 	if ((lp_smb_encrypt(-1) >= SMB_SIGNING_DESIRED) &&
@@ -281,7 +281,7 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
 		*out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
 		*out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
 		/* force no signing */
-		x->global->signing_required = false;
+		x->global->signing_flags &= ~SMBXSRV_SIGNING_REQUIRED;
 		guest = true;
 	}
 
-- 
1.7.9.5


From 4cde6ffdc5ff1274c3d2036125efd49e627e001b Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 15 Nov 2015 11:12:34 +0100
Subject: [PATCH 13/17] VL: Same 80-char comment. Boolean logic is always
 spooky for me. A good descriptive helper function
 would help me :-)

s3:smb2_server: add signing state tracking flags

Add flags that track the signing state of all incoming and outgoing SMB2
packets and a helper function that can be used to determine whether a
session of tcon can be considered "signed".

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/librpc/idl/smbXsrv.idl |    5 ++++-
 source3/smbd/globals.h         |    2 ++
 source3/smbd/smb2_server.c     |   47 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl
index f6a5fd9..8528770 100644
--- a/source3/librpc/idl/smbXsrv.idl
+++ b/source3/librpc/idl/smbXsrv.idl
@@ -124,7 +124,9 @@ interface smbXsrv
 	} smbXsrv_encrpytion_flags;
 
 	typedef [public,bitmap8bit] bitmap {
-		SMBXSRV_SIGNING_REQUIRED		= 0x01
+		SMBXSRV_SIGNING_REQUIRED		= 0x01,
+		SMBXSRV_PROCESSED_SIGNED_PACKET		= 0x02,
+		SMBXSRV_PROCESSED_UNSIGNED_PACKET	= 0x04
 	} smbXsrv_signing_flags;
 
 	typedef struct {
@@ -275,6 +277,7 @@ interface smbXsrv
 		 * for SMB1 this is the session that the tcon was opened on
 		 */
 		uint32					session_global_id;
+		smbXsrv_signing_flags                   signing_flags;
 	} smbXsrv_tcon_global0;
 
 	typedef union {
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 822cced..bf23df6 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -638,6 +638,8 @@ NTSTATUS smbXsrv_open_global_traverse(
 NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id);
 bool smbXsrv_is_encrypted(uint8_t encryption_flags);
 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags);
+bool smbXsrv_is_signed(uint8_t signing_flags);
+bool smbXsrv_is_partially_signed(uint8_t signing_flags);
 
 struct smbd_smb2_send_queue {
 	struct smbd_smb2_send_queue *prev, *next;
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 1a4a98c..3507cb6 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -2019,6 +2019,23 @@ bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
 		(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
 }
 
+bool smbXsrv_is_signed(uint8_t signing_flags)
+{
+	/*
+	 * Signing is always enabled, so unless we got an unsigned
+	 * packet and at least one signed packet that was not
+	 * encrypted, the session or tcon is "signed".
+	 */
+	return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
+		(signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
+}
+
+bool smbXsrv_is_partially_signed(uint8_t signing_flags)
+{
+	return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
+		(signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
+}
+
 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 {
 	struct smbXsrv_connection *xconn = req->xconn;
@@ -2265,17 +2282,21 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		bool update_tcon_global = false;
 
 		if (req->was_encrypted && req->do_encryption) {
+			/* Encrypted packets are, well, encrypted and signed */
 			if (!(x->global->encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET)) {
 				x->global->encryption_flags |= SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
+				x->global->signing_flags |= SMBXSRV_PROCESSED_SIGNED_PACKET;
 				update_session_global = true;
 			}
 			if (call->need_tcon) {
 				if (!(req->tcon->global->encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET)) {
 					req->tcon->global->encryption_flags |= SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
+					req->tcon->global->signing_flags |= SMBXSRV_PROCESSED_SIGNED_PACKET;
 					update_tcon_global = true;
 				}
 			}
 		} else {
+			/* Unencrypted packets are unencrypted... */
 			if (!(x->global->encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)) {
 				x->global->encryption_flags |= SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
 				update_session_global = true;
@@ -2286,6 +2307,32 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 					update_tcon_global = true;
 				}
 			}
+
+			/* ..., but can be signed or unsigned */
+			if (req->do_signing) {
+				if (!(x->global->signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET)) {
+					x->global->signing_flags |= SMBXSRV_PROCESSED_SIGNED_PACKET;
+					update_session_global = true;
+				}
+				if (call->need_tcon) {
+					if (!(req->tcon->global->signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET)) {
+						req->tcon->global->signing_flags |= SMBXSRV_PROCESSED_SIGNED_PACKET;
+						update_tcon_global = true;
+					}
+				}
+			} else if (opcode != SMB2_OP_CANCEL) {
+				/* Cancel requests are allowed to skip signing */
+				if (!(x->global->signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET)) {
+					x->global->signing_flags |= SMBXSRV_PROCESSED_UNSIGNED_PACKET;
+					update_session_global = true;
+				}
+				if (call->need_tcon) {
+					if (!(req->tcon->global->signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET)) {
+						req->tcon->global->signing_flags |= SMBXSRV_PROCESSED_UNSIGNED_PACKET;
+						update_tcon_global = true;
+					}
+				}
+			}
 		}
 
 		if (update_session_global) {
-- 
1.7.9.5


From 6e94650995272dd069799be5f3903b2264f38b29 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 30 Nov 2015 11:14:34 +0100
Subject: [PATCH 14/17] s3:lib/conn_tdb: store the connection dialect

This will be used in a subsequent commit that will print the signing
cipher in smbstatus. We need the connection dialect for that.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/conn_tdb.c |    3 +++
 source3/lib/conn_tdb.h |    1 +
 2 files changed, 4 insertions(+)

diff --git a/source3/lib/conn_tdb.c b/source3/lib/conn_tdb.c
index 8eca0a0..b6dd11f 100644
--- a/source3/lib/conn_tdb.c
+++ b/source3/lib/conn_tdb.c
@@ -42,6 +42,7 @@ struct connections_forall_session {
 	fstring machine;
 	fstring addr;
 	uint16_t cipher;
+	uint16_t dialect;
 };
 
 static int collect_sessions_fn(struct smbXsrv_session_global0 *global,
@@ -64,6 +65,7 @@ static int collect_sessions_fn(struct smbXsrv_session_global0 *global,
 	fstrcpy(sess.machine, global->channels[0].remote_name);
 	fstrcpy(sess.addr, global->channels[0].remote_address);
 	sess.cipher = global->channels[0].encryption_cipher;
+	sess.dialect = global->connection_dialect;
 
 	status = dbwrap_store(state->session_by_pid,
 			      make_tdb_data((void*)&id, sizeof(id)),
@@ -127,6 +129,7 @@ static int traverse_tcon_fn(struct smbXsrv_tcon_global0 *global,
 	data.start = nt_time_to_unix(global->creation_time);
 	data.encryption_flags = global->encryption_flags;
 	data.cipher = sess.cipher;
+	data.dialect = sess.dialect;
 
 	state->count++;
 
diff --git a/source3/lib/conn_tdb.h b/source3/lib/conn_tdb.h
index b57fef8..c760ab7 100644
--- a/source3/lib/conn_tdb.h
+++ b/source3/lib/conn_tdb.h
@@ -35,6 +35,7 @@ struct connections_data {
 	time_t start;
 	uint8_t encryption_flags;
 	uint16_t cipher;
+	uint16_t dialect;
 };
 
 /* The following definitions come from lib/conn_tdb.c  */
-- 
1.7.9.5


From 1b644e242859d0c4e43380b33b9d50e2bd83a2d1 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 30 Nov 2015 11:20:43 +0100
Subject: [PATCH 15/17] smbstatus: show signing state of sessions and tcons

Show the signing state of sesssions tcons in smbstatus. This is SMB2/3
only. SMB1 support will be added in a later commit.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/include/session.h   |    1 +
 source3/lib/conn_tdb.c      |    3 +++
 source3/lib/conn_tdb.h      |    1 +
 source3/lib/sessionid_tdb.c |    1 +
 source3/utils/status.c      |   45 +++++++++++++++++++++++++++++++++++--------
 5 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/source3/include/session.h b/source3/include/session.h
index c73f9ee..c32c8b0 100644
--- a/source3/include/session.h
+++ b/source3/include/session.h
@@ -41,5 +41,6 @@ struct sessionid {
 	uint16_t connection_dialect;
 	uint8_t encryption_flags;
 	uint16_t cipher;
+	uint8_t signing_flags;
 };
 
diff --git a/source3/lib/conn_tdb.c b/source3/lib/conn_tdb.c
index b6dd11f..36d5fae 100644
--- a/source3/lib/conn_tdb.c
+++ b/source3/lib/conn_tdb.c
@@ -43,6 +43,7 @@ struct connections_forall_session {
 	fstring addr;
 	uint16_t cipher;
 	uint16_t dialect;
+	uint8_t signing_flags;
 };
 
 static int collect_sessions_fn(struct smbXsrv_session_global0 *global,
@@ -66,6 +67,7 @@ static int collect_sessions_fn(struct smbXsrv_session_global0 *global,
 	fstrcpy(sess.addr, global->channels[0].remote_address);
 	sess.cipher = global->channels[0].encryption_cipher;
 	sess.dialect = global->connection_dialect;
+	sess.signing_flags = global->signing_flags;
 
 	status = dbwrap_store(state->session_by_pid,
 			      make_tdb_data((void*)&id, sizeof(id)),
@@ -130,6 +132,7 @@ static int traverse_tcon_fn(struct smbXsrv_tcon_global0 *global,
 	data.encryption_flags = global->encryption_flags;
 	data.cipher = sess.cipher;
 	data.dialect = sess.dialect;
+	data.signing_flags = global->signing_flags;
 
 	state->count++;
 
diff --git a/source3/lib/conn_tdb.h b/source3/lib/conn_tdb.h
index c760ab7..34f0019 100644
--- a/source3/lib/conn_tdb.h
+++ b/source3/lib/conn_tdb.h
@@ -36,6 +36,7 @@ struct connections_data {
 	uint8_t encryption_flags;
 	uint16_t cipher;
 	uint16_t dialect;
+	uint8_t signing_flags;
 };
 
 /* The following definitions come from lib/conn_tdb.c  */
diff --git a/source3/lib/sessionid_tdb.c b/source3/lib/sessionid_tdb.c
index 02ed138..cac0730 100644
--- a/source3/lib/sessionid_tdb.c
+++ b/source3/lib/sessionid_tdb.c
@@ -71,6 +71,7 @@ static int sessionid_traverse_read_fn(struct smbXsrv_session_global0 *global,
 
 	session.encryption_flags = global->encryption_flags;
 	session.cipher = global->channels[0].encryption_cipher;
+	session.signing_flags = global->signing_flags;
 
 	return state->fn(NULL, &session, state->private_data);
 }
diff --git a/source3/utils/status.c b/source3/utils/status.c
index fd5522c..02a9677 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -305,6 +305,7 @@ static int traverse_connections(const struct connections_key *key,
 	char *timestr = NULL;
 	int result = 0;
 	const char *encryption = "-";
+	const char *signing = "-";
 
 	if (crec->cnum == TID_FIELD_INVALID)
 		return 0;
@@ -334,11 +335,20 @@ static int traverse_connections(const struct connections_key *key,
 		}
 	}
 
-	d_printf("%-12s %-7s %-13s %-32s %-10s\n",
+	if (smbXsrv_is_signed(crec->signing_flags)) {
+		if (crec->dialect >= SMB3_DIALECT_REVISION_302) {
+			signing = "AES-128-CMAC";
+		} else if (crec->dialect >= SMB2_DIALECT_REVISION_202) {
+			signing = "HMAC-SHA256";
+		}
+	}
+
+	d_printf("%-12s %-7s %-13s %-32s %-12s %-12s\n",
 		 crec->servicename, server_id_str_buf(crec->pid, &tmp),
 		 crec->machine,
 		 timestr,
-		 encryption);
+		 encryption,
+		 signing);
 
 	TALLOC_FREE(timestr);
 
@@ -354,6 +364,7 @@ static int traverse_sessionid(const char *key, struct sessionid *session,
 	char *machine_hostname = NULL;
 	int result = 0;
 	const char *encryption = "-";
+	const char *signing = "-";
 
 	if (do_checks &&
 	    (!process_exists(session->pid) ||
@@ -418,12 +429,30 @@ static int traverse_sessionid(const char *key, struct sessionid *session,
 		}
 	}
 
-	d_printf("%-7s %-12s %-12s %-41s %-17s %-20s\n",
+	if (smbXsrv_is_signed(session->signing_flags)) {
+		if (session->connection_dialect >= SMB3_DIALECT_REVISION_302) {
+			signing = "AES-128-CMAC";
+		} else if (session->connection_dialect >= SMB2_DIALECT_REVISION_202) {
+			signing = "HMAC-SHA256";
+		}
+	} else if (smbXsrv_is_partially_signed(session->signing_flags)) {
+		if (session->connection_dialect >= SMB3_DIALECT_REVISION_302) {
+			signing = "partial(AES-128-CMAC)";
+		} else if (session->connection_dialect >= SMB2_DIALECT_REVISION_202) {
+			signing = "partial(HMAC-SHA256)";
+		} else {
+			signing = "partial(HMAC-MD5)";
+		}
+	}
+
+
+	d_printf("%-7s %-12s %-12s %-41s %-17s %-20s %-21s\n",
 		 server_id_str_buf(session->pid, &tmp),
 		 uid_str, gid_str,
 		 machine_hostname,
 		 session_dialect_str(session->connection_dialect),
-		 encryption);
+		 encryption,
+		 signing);
 
 	TALLOC_FREE(machine_hostname);
 
@@ -589,8 +618,8 @@ int main(int argc, const char *argv[])
 
 	if ( show_processes ) {
 		d_printf("\nSamba version %s\n",samba_version_string());
-		d_printf("%-7s %-12s %-12s %-41s %-17s %-20s\n", "PID", "Username", "Group", "Machine", "Protocol Version", "Encryption");
-		d_printf("------------------------------------------------------------------------------------------------------------------\n");
+		d_printf("%-7s %-12s %-12s %-41s %-17s %-20s %-21s\n", "PID", "Username", "Group", "Machine", "Protocol Version", "Encryption", "Signing");
+		d_printf("----------------------------------------------------------------------------------------------------------------------------------------\n");
 
 		sessionid_traverse_read(traverse_sessionid, frame);
 
@@ -604,8 +633,8 @@ int main(int argc, const char *argv[])
 			goto done;
 		}
 
-		d_printf("\n%-12s %-7s %-13s %-32s %-10s\n", "Service", "pid", "Machine", "Connected at", "Encryption");
-		d_printf("---------------------------------------------------------------------------------\n");
+		d_printf("\n%-12s %-7s %-13s %-32s %-12s %-12s\n", "Service", "pid", "Machine", "Connected at", "Encryption", "Signing");
+		d_printf("---------------------------------------------------------------------------------------------\n");
 
 		connections_forall_read(traverse_connections, frame);
 
-- 
1.7.9.5


From 4dbdcae28973d699554eb0acd99c0f890a80df59 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 3 Dec 2015 12:17:50 +0100
Subject: [PATCH 16/17] libcli/smb: add define SMB_ENCRYPTION_GSSAPI for CIFS
 encryption type

Add a define for the CIFS UNIX extensions encryption type. We store this
in smbXsrv_channel and use it in smbstatus for showing the
CIFS/SMB2/SMB3 encryption cipher used.

The SMB3 encryption cipher constants start at 1, carefully choosing the
highest available bit for the CIFS UNIX extensions encryption cipher
should avoid collisions and leaves room for many SMB3 ciphers in the
future.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 libcli/smb/smb_unix_ext.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcli/smb/smb_unix_ext.h b/libcli/smb/smb_unix_ext.h
index ff705aa..e74976b 100644
--- a/libcli/smb/smb_unix_ext.h
+++ b/libcli/smb/smb_unix_ext.h
@@ -358,7 +358,7 @@ enum smb_whoami_flags {
  */
 
 #define SMB_REQUEST_TRANSPORT_ENCRYPTION     0x203 /* QFSINFO */
-
+#define SMB_ENCRYPTION_GSSAPI                0x8000
 
 /* The query/set info levels for POSIX ACLs. */
 #define SMB_QUERY_POSIX_ACL  0x204
-- 
1.7.9.5


From 815b84c76423a0ad05bdd50bc735810f4fc9bc3a Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 30 Nov 2015 17:03:26 +0100
Subject: [PATCH 17/17] VL: Again -- the logic looks sane, but to me it's hard
 to follow. I know I might be a bit of a pain here,
 but I'd love to see this easier to grasp.

smbstatus: add support for CIFS UNIX extensions encryption and signing

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/smbd/process.c |   79 +++++++++++++++++++++++++++++++++++++++++++++++-
 source3/utils/status.c |   10 ++++++
 2 files changed, 88 insertions(+), 1 deletion(-)

diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index c99c75e..f53b932 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -1452,6 +1452,8 @@ static connection_struct *switch_message(uint8_t type, struct smb_request *req)
 	NTTIME now = timeval_to_nttime(&req->request_time);
 	struct smbXsrv_session *session = NULL;
 	NTSTATUS status;
+	bool update_session_global = false;
+	bool update_tcon_global = false;
 
 	errno = 0;
 
@@ -1647,7 +1649,82 @@ static connection_struct *switch_message(uint8_t type, struct smb_request *req)
 	}
 
 	smb_messages[type].fn(req);
-	return req->conn;
+	conn = req->conn;
+
+	/*
+	 * Update encryption and signing state tracking flags that are
+	 * used by smbstatus to display signing and encryption status.
+	 */
+	if (session != NULL) {
+		if (ENCRYPTION_REQUIRED(conn)) {
+			/*
+			 * conn->encrypt_level = SMB_SIGNING_REQUIRED
+			 * guarantees that all further packets will be
+			 * encrypted, so set the encryption state flags to
+			 * signalize encryption to smbstatus
+			 */
+			if (!(conn->tcon && conn->tcon->global->encryption_flags &
+			      SMBXSRV_PROCESSED_ENCRYPTED_PACKET))
+			{
+				session->global->encryption_flags |= SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
+				conn->tcon->global->encryption_flags |= SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
+				session->global->channels[0].encryption_cipher = SMB_ENCRYPTION_GSSAPI;
+				update_session_global = true;
+				update_tcon_global = true;
+			}
+		} else {
+			if (!(session->global->encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)) {
+				session->global->encryption_flags |= SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
+				update_session_global = true;
+			}
+		}
+
+		if (srv_is_signing_active(xconn)) {
+			if (!(session->global->signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET)) {
+				session->global->signing_flags |= SMBXSRV_PROCESSED_SIGNED_PACKET;
+				update_session_global = true;
+			}
+
+			/* Being overly careful here with conn->tcon. Can it really be NULL? */
+			if (conn && conn->tcon &&
+			    !(conn->tcon->global->signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET))
+			{
+				conn->tcon->global->signing_flags |= SMBXSRV_PROCESSED_SIGNED_PACKET;
+				update_tcon_global = true;
+			}
+		} else if ((type != SMBecho) && (type != SMBsesssetupX)) {
+			if (!(session->global->signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET)) {
+				session->global->signing_flags |= SMBXSRV_PROCESSED_UNSIGNED_PACKET;
+				update_session_global = true;
+			}
+
+			/* Being overly careful here with conn->tcon. Can it really be NULL? */
+			if (conn && conn->tcon &&
+			    !(conn->tcon->global->signing_flags |= SMBXSRV_PROCESSED_UNSIGNED_PACKET))
+			{
+				conn->tcon->global->signing_flags |= SMBXSRV_PROCESSED_UNSIGNED_PACKET;
+				update_tcon_global = true;
+			}
+		}
+
+		if (update_session_global) {
+			status = smbXsrv_session_update(session);
+			if (!NT_STATUS_IS_OK(status)) {
+				reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
+				return conn;
+			}
+		}
+
+		if (update_tcon_global) {
+			status = smbXsrv_tcon_update(conn->tcon);
+			if (!NT_STATUS_IS_OK(status)) {
+				reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
+				return conn;
+			}
+		}
+	}
+
+	return conn;
 }
 
 /****************************************************************************
diff --git a/source3/utils/status.c b/source3/utils/status.c
index 02a9677..9aefd5e 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -322,6 +322,9 @@ static int traverse_connections(const struct connections_key *key,
 
 	if (smbXsrv_is_encrypted(crec->encryption_flags)) {
 		switch (crec->cipher) {
+		case SMB_ENCRYPTION_GSSAPI:
+			encryption = "GSSAPI";
+			break;
 		case SMB2_ENCRYPTION_AES128_CCM:
 			encryption = "AES-128-CCM";
 			break;
@@ -340,6 +343,8 @@ static int traverse_connections(const struct connections_key *key,
 			signing = "AES-128-CMAC";
 		} else if (crec->dialect >= SMB2_DIALECT_REVISION_202) {
 			signing = "HMAC-SHA256";
+		} else {
+			signing = "HMAC-MD5";
 		}
 	}
 
@@ -416,6 +421,9 @@ static int traverse_sessionid(const char *key, struct sessionid *session,
 		}
 	} else if (smbXsrv_is_partially_encrypted(session->encryption_flags)) {
 		switch (session->cipher) {
+		case SMB_ENCRYPTION_GSSAPI:
+			encryption = "partial(GSSAPI)";
+			break;
 		case SMB2_ENCRYPTION_AES128_CCM:
 			encryption = "partial(AES-128-CCM)";
 			break;
@@ -434,6 +442,8 @@ static int traverse_sessionid(const char *key, struct sessionid *session,
 			signing = "AES-128-CMAC";
 		} else if (session->connection_dialect >= SMB2_DIALECT_REVISION_202) {
 			signing = "HMAC-SHA256";
+		} else {
+			signing = "HMAC-MD5";
 		}
 	} else if (smbXsrv_is_partially_signed(session->signing_flags)) {
 		if (session->connection_dialect >= SMB3_DIALECT_REVISION_302) {
-- 
1.7.9.5



More information about the samba-technical mailing list