[PATCH] Display status of encryption and signing in smbstatus

Ralph Boehme rb at sernet.de
Mon Dec 14 14:33:26 UTC 2015


Hi Volker!

On Fri, Dec 11, 2015 at 09:23:09AM +0100, Volker Lendecke wrote:
> 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.

thanks for pushing me in the right direction. :) Hopefully the split
out functions smb2srv_update_crypto_flags() and
smb1srv_update_crypto_flags() are easier to grasp.

> 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?

because we're printing two strings into *one* field/column. For
correct 41 chars alignment, we have to first concatenate both strings
and then print the resulting string with 41 characters alignment.

The previous version resulted in outout like this:

$ sudo ./bin/smbstatus

Samba version 4.4.0pre1-DEVELOPERBUILD
PID     Username      Group         Machine            Protocol Version
------------------------------------------------------------------------------
2881      slow          men           127.0.0.1    (ipv4:127.0.0.1:57668) SMB3_11
2916      slow          men           10.10.11.1   (ipv4:10.10.11.1:52320) SMB3_02

The new output is:

$ sudo ./bin/smbstatus

Samba version 4.4.0pre1-DEVELOPERBUILD
PID     Username     Group        Machine                                   Protocol Version  Encryption           Signing
----------------------------------------------------------------------------------------------------------------------------------------
5953    slow         men          127.0.0.1 (ipv4:127.0.0.1:57692)          SMB3_11           -                    AES-128-CMAC
5960    slow         men          10.10.11.1 (ipv4:10.10.11.1:52336)        SMB3_02           -                    partial(AES-128-CMAC)

For reference, this is the hunk we're discussing:

> 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");

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 5b801a203073d8489f3b551bdb22ae6382ea9766 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;
 		}
-- 
2.5.0


From b3f54b13457a98635aab8a6c537e9f2d4bbe00e2 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,
-- 
2.5.0


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


From 375cd7b07a4f21df2d764d9139990fc74ea9dd0b 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         |  3 ++
 source3/smbd/smb2_server.c     | 81 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 87 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..676ab75 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -636,6 +636,9 @@ 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);
+bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag);
 
 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..70fbdc7 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -2004,6 +2004,65 @@ 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));
+}
+
+/* Set a flag if not already set, return true if set */
+bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
+{
+	if ((flag == 0) || (*flags & flag)) {
+		return false;
+	}
+
+	*flags |= flag;
+	return true;
+}
+
+/*
+ * Update encryption state tracking flags, this can be used to
+ * determine whether whether the session or tcon is "encrypted".
+ */
+static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
+					uint16_t opcode,
+					bool *update_session_globalp,
+					bool *update_tcon_globalp)
+{
+	/* Default: assume unecrypted */
+	struct smbXsrv_session *session = req->session;
+	struct smbXsrv_tcon *tcon = req->tcon;
+	uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
+	bool update_session = false;
+	bool update_tcon = false;
+
+	if (req->was_encrypted && req->do_encryption) {
+		encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
+	}
+
+	update_session |= smbXsrv_set_crypto_flag(
+		&session->global->encryption_flags, encrypt_flag);
+
+	if (tcon) {
+		update_tcon |= smbXsrv_set_crypto_flag(
+			&tcon->global->encryption_flags, encrypt_flag);
+	}
+
+	*update_session_globalp = update_session;
+	*update_tcon_globalp = update_tcon;
+	return;
+}
+
 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 {
 	struct smbXsrv_connection *xconn = req->xconn;
@@ -2240,6 +2299,28 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		req->do_encryption = true;
 	}
 
+	if (req->session) {
+		bool update_session_global = false;
+		bool update_tcon_global = false;
+
+		smb2srv_update_crypto_flags(req, opcode,
+					    &update_session_global,
+					    &update_tcon_global);
+
+		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 a5cf2edcbd96a53fb5f68b88467782e2a89e8f7d 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;
 }
-- 
2.5.0


From 9b031ffbd4099760747654f858fc9c5efe7fe00e 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;
-- 
2.5.0


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


From 9bead21996ffbdc6424b471b60596ead3e328e39 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 ad7f16710637a0e66f0b94553021df1ac1d9bda8 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);
 
-- 
2.5.0


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


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


From 0d52b49d04704a9761da0d53321b723389ab6254 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 70fbdc7..a9916cc 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -2125,7 +2125,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 b1a638f2e8cbf4e0e902d5229295e67b1f89d4ca 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     | 33 ++++++++++++++++++++++++++++++++-
 3 files changed, 38 insertions(+), 2 deletions(-)

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 676ab75..90d8dcc 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -639,6 +639,8 @@ 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_set_crypto_flag(uint8_t *flags, uint8_t flag);
+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 a9916cc..9adbb99 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -2039,23 +2039,37 @@ static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
 					bool *update_session_globalp,
 					bool *update_tcon_globalp)
 {
-	/* Default: assume unecrypted */
+	/* Default: assume unecrypted and unsigned */
 	struct smbXsrv_session *session = req->session;
 	struct smbXsrv_tcon *tcon = req->tcon;
 	uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
+	uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
 	bool update_session = false;
 	bool update_tcon = false;
 
 	if (req->was_encrypted && req->do_encryption) {
 		encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
+		sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
+	} else {
+		/* Unencrypted packet, can be signed */
+		if (req->do_signing) {
+			sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
+		} else if (opcode == SMB2_OP_CANCEL) {
+			/* Cancel requests are allowed to skip signing */
+			sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
+		}
 	}
 
 	update_session |= smbXsrv_set_crypto_flag(
 		&session->global->encryption_flags, encrypt_flag);
+	update_session |= smbXsrv_set_crypto_flag(
+		&session->global->signing_flags, sign_flag);
 
 	if (tcon) {
 		update_tcon |= smbXsrv_set_crypto_flag(
 			&tcon->global->encryption_flags, encrypt_flag);
+		update_tcon |= smbXsrv_set_crypto_flag(
+			&tcon->global->signing_flags, sign_flag);
 	}
 
 	*update_session_globalp = update_session;
@@ -2063,6 +2077,23 @@ static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
 	return;
 }
 
+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;
-- 
2.5.0


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


From 5f666e2cd0de62115c12dbf280ac88cce8a11805 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      | 43 +++++++++++++++++++++++++++++++++++--------
 5 files changed, 41 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..4717234 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,28 @@ 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)";
+		}
+	}
+
+
+	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 +616,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 +631,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 837b0e17e01fb82a4e7c0406b8df26b1c7fd5d66 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
-- 
2.5.0


From 71690a78f3f973fa4bee1ac2288d0ddff677f2ca 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 SMB1 signing and CIFS UNIX
 extensions encryption

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

diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index c99c75e..d4d2ac1 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -1430,6 +1430,54 @@ static void smb_dump(const char *name, int type, const char *data)
 	TALLOC_FREE(fname);
 }
 
+static void smb1srv_update_crypto_flags(struct smbXsrv_session *session,
+					struct smb_request *req,
+					uint8_t type,
+					bool *update_session_globalp,
+					bool *update_tcon_globalp)
+{
+	connection_struct *conn = req->conn;
+	struct smbXsrv_tcon *tcon = conn ? conn->tcon : NULL;
+	uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
+	uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
+	bool update_session = false;
+	bool update_tcon = false;
+
+	if (ENCRYPTION_REQUIRED(conn)) {
+		encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
+	}
+
+	if (srv_is_signing_active(req->xconn)) {
+		sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
+	} else if ((type == SMBecho) || (type == SMBsesssetupX)) {
+		/*
+		 * echo can be unsigned. Sesssion setup except final
+		 * session setup response too
+		 */
+		sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
+	}
+
+	update_session |= smbXsrv_set_crypto_flag(
+		&session->global->encryption_flags, encrypt_flag);
+	update_session |= smbXsrv_set_crypto_flag(
+		&session->global->signing_flags, sign_flag);
+
+	if (tcon) {
+		update_tcon |= smbXsrv_set_crypto_flag(
+			&tcon->global->encryption_flags, encrypt_flag);
+		update_tcon |= smbXsrv_set_crypto_flag(
+			&tcon->global->signing_flags, sign_flag);
+	}
+
+	if (update_session) {
+		session->global->channels[0].encryption_cipher = SMB_ENCRYPTION_GSSAPI;
+	}
+
+	*update_session_globalp = update_session;
+	*update_tcon_globalp = update_tcon;
+	return;
+}
+
 /****************************************************************************
  Prepare everything for calling the actual request function, and potentially
  call the request function via the "new" interface.
@@ -1647,7 +1695,38 @@ 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) {
+		bool update_session_global = false;
+		bool update_tcon_global = false;
+
+		smb1srv_update_crypto_flags(session, req, type,
+					    &update_session_global,
+					    &update_tcon_global);
+
+		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 4717234..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,12 +442,16 @@ 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) {
 			signing = "partial(AES-128-CMAC)";
 		} else if (session->connection_dialect >= SMB2_DIALECT_REVISION_202) {
 			signing = "partial(HMAC-SHA256)";
+		} else {
+			signing = "partial(HMAC-MD5)";
 		}
 	}
 
-- 
2.5.0



More information about the samba-technical mailing list