[PATCH] Display status of encryption and signing in smbstatus

Ralph Boehme rb at sernet.de
Wed Dec 9 12:57:56 UTC 2015


Hi!

Attached is a patchset that adds support for displaying the current
status of signing and encryption per session and tcon.

Example:

# smbstatus

Samba version 4.4.0pre1-DEVELOPERBUILD
PID     Username     Group        Machine                                   Protocol Version  Encryption           Signing
----------------------------------------------------------------------------------------------------------------------------------------
25597   slow         men          10.10.11.1 (ipv4:10.10.11.1:51241)        SMB3_02           partial(AES-128-CCM) partial(AES-128-CMAC)

Service      pid     Machine       Connected at                     Encryption   Signing
---------------------------------------------------------------------------------------------
encrypted    25597   10.10.11.1    Wed Dec  9 01:40:20 PM 2015 CET  AES-128-CCM  AES-128-CMAC
clear        25597   10.10.11.1    Wed Dec  9 01:40:17 PM 2015 CET  -            -

The main changes involve modifying smbXsrv tdbs and packet processing
to track signing and encryption per incoming and outgoing packets.

tcons are either shown as encrpyted or unencrpyted, signed or
unsigned, sessions can be shown as partially encrypted in order to
give a consistent summary, otherwise it would look strange displaying
a sessions as unencryped when one of its tcons is encrypted.

Per the nature of SMB3 encryption where sessions and tcons may be
encrypted (smb encrypt = desired), but not enforced (smb encrypt !=
required), the output is NOT a guarantee that all future packets will
be encrypted too. The output is only a summary of what has been seen
so far.

Please review and push if ok.

Thanks!
-Ralph

-- 
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@sernet.de
-------------- next part --------------
From 8ecde31bf3478f518d96338ee8a6e03dfb26d44d 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>
---
 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;
 		}
-- 
2.5.0


From 1a84f6be2e2bb73fe77f4f32516de51b867e20aa 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>
---
 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,
-- 
2.5.0


From b555c2f81078f59b5dfdcb0e331db6fc951b6561 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>
---
 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) {
-- 
2.5.0


From 103528863b01c797b9be04a27555c5acd95fafa1 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] 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);
-- 
2.5.0


From 619b588ea31b1611865683d95da5242cecdae689 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>
---
 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;
 }
-- 
2.5.0


From 1479ccf7efcad419a099d8cb44a1b1585020faf5 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>
---
 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;
-- 
2.5.0


From 2b69c304a44637a1799fb0d92118fd36b87d7931 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>
---
 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");
 
-- 
2.5.0


From f2a755d2be8cf6dd98a0c40fe03c9fc22aa46cbe 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] 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);
 
-- 
2.5.0


From f77cf2b3605f1e3236d0837a3876b4a3c251c8bd 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>
---
 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);
 
-- 
2.5.0


From a0cc7e56eaf3a69c9210be71d912f32bbeb68577 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>
---
 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);
 
-- 
2.5.0


From 8e07480d93818201c6a2a78ce605c962c8f41e7d 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>
---
 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);
 
-- 
2.5.0


From 252602abdb01697a0c0e4701cbb087c216b2d931 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>
---
 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;
 	}
 
-- 
2.5.0


From b5c4715d1b7064dbffd2fdd0d96a478f05b5ef02 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] 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) {
-- 
2.5.0


From 7af0e4a2ed7d45b5cd185403e758ac7c2ba19557 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>
---
 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  */
-- 
2.5.0


From 498f88aedf535ff2f33fc902d83dd17d62818f2c 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>
---
 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);
 
-- 
2.5.0


From 803c52520662be007ce0a056fa7643827c86af55 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>
---
 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
-- 
2.5.0


From b47813831d919c31322fa3dfe2a5250f0dcbe857 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] 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) {
-- 
2.5.0



More information about the samba-technical mailing list