[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Wed Sep 14 01:42:04 MDT 2011


The branch, master has been updated
       via  abb24bf s3:smbd: make use of better SMB signing negotiation
       via  c682472 s3:libsmb: make use of new advanded SMB signing
       via  0a6d0f8 s3:smb_signing: add support for easier negotiation of SMB signing
       via  f205e4c s3:smbd: echo FLAGS2_SMB_SECURITY_SIGNATURES* and the signature field in the reply
      from  cb064f2 tdb2: remove bogus leftover .orig file.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit abb24bf8e874d525382e994af7ae432212775153
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Sep 12 09:19:06 2011 +0200

    s3:smbd: make use of better SMB signing negotiation
    
    metze
    
    Autobuild-User: Stefan Metzmacher <metze at samba.org>
    Autobuild-Date: Wed Sep 14 09:41:02 CEST 2011 on sn-devel-104

commit c682472fdf28894858d14eb95b13cb4214847ecd
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Sep 12 09:16:27 2011 +0200

    s3:libsmb: make use of new advanded SMB signing
    
    metze

commit 0a6d0f8edaa198898f50f274275efba8de41d843
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Sep 12 09:04:53 2011 +0200

    s3:smb_signing: add support for easier negotiation of SMB signing
    
    We don't make use of it yet, but it will follow.
    
    metze

commit f205e4cada0a2e5d1289b5a1482dd670c65b1dfd
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Sep 9 22:44:44 2011 +0200

    s3:smbd: echo FLAGS2_SMB_SECURITY_SIGNATURES* and the signature field in the reply
    
    This matches what windows is doing.
    
    metze

-----------------------------------------------------------------------

Summary of changes:
 source3/include/smb_signing.h |    5 ++-
 source3/libsmb/cliconnect.c   |   59 +++++++++++-------------
 source3/libsmb/clientgen.c    |   46 ++++++++++++-------
 source3/libsmb/clisigning.c   |   11 ++---
 source3/libsmb/proto.h        |    4 +-
 source3/libsmb/smb_signing.c  |  100 ++++++++++++++++++++++++++++-------------
 source3/smbd/negprot.c        |    1 -
 source3/smbd/process.c        |   12 ++++-
 source3/smbd/proto.h          |    3 +-
 source3/smbd/sesssetup.c      |   18 +++++++
 source3/smbd/signing.c        |   21 +++++++--
 11 files changed, 183 insertions(+), 97 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/smb_signing.h b/source3/include/smb_signing.h
index d2eda9b..481be1d 100644
--- a/source3/include/smb_signing.h
+++ b/source3/include/smb_signing.h
@@ -26,9 +26,11 @@ struct smb_signing_state;
 
 struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx,
 					   bool allowed,
+					   bool desired,
 					   bool mandatory);
 struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx,
 					      bool allowed,
+					      bool desired,
 					      bool mandatory,
 					      void *(*alloc_fn)(TALLOC_CTX *, size_t),
 					      void (*free_fn)(TALLOC_CTX *, void *));
@@ -45,7 +47,8 @@ bool smb_signing_activate(struct smb_signing_state *si,
 bool smb_signing_is_active(struct smb_signing_state *si);
 bool smb_signing_is_allowed(struct smb_signing_state *si);
 bool smb_signing_is_mandatory(struct smb_signing_state *si);
-bool smb_signing_set_negotiated(struct smb_signing_state *si);
+bool smb_signing_set_negotiated(struct smb_signing_state *si,
+				bool allowed, bool mandatory);
 bool smb_signing_is_negotiated(struct smb_signing_state *si);
 
 #endif /* _SMB_SIGNING_H_ */
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 4ebabce..54cd669 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -944,7 +944,6 @@ static struct tevent_req *cli_session_setup_nt1_send(
 			SMBsesskeygen_ntv1(nt_hash, session_key.data);
 #endif
 		}
-		cli_temp_set_signing(cli);
 	} else {
 		/* pre-encrypted password supplied.  Only used for 
 		   security=server, can't do
@@ -1444,8 +1443,6 @@ static struct tevent_req *cli_session_setup_kerberos_send(
 	state->cli = cli;
 	state->ads_status = ADS_SUCCESS;
 
-	cli_temp_set_signing(cli);
-
 	/*
 	 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
 	 * we have to acquire a ticket. To be fixed later :-)
@@ -1590,8 +1587,6 @@ static struct tevent_req *cli_session_setup_ntlmssp_send(
 	talloc_set_destructor(
 		state, cli_session_setup_ntlmssp_state_destructor);
 
-	cli_temp_set_signing(cli);
-
 	status = ntlmssp_client_start(state,
 				      lp_netbios_name(),
 				      lp_workgroup(),
@@ -2643,7 +2638,11 @@ static void cli_negprot_done(struct tevent_req *subreq)
 
 	if (cli_state_protocol(cli) >= PROTOCOL_NT1) {
 		struct timespec ts;
-		bool negotiated_smb_signing = false;
+		const char *client_signing = NULL;
+		bool server_mandatory;
+		bool server_allowed;
+		const char *server_signing = NULL;
+		bool ok;
 
 		if (wct != 0x11) {
 			tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
@@ -2678,35 +2677,33 @@ static void cli_negprot_done(struct tevent_req *subreq)
 			}
 		}
 
-		/*
-		 * As signing is slow we only turn it on if either the client or
-		 * the server require it. JRA.
-		 */
+		client_signing = "disabled";
+		if (client_is_signing_allowed(cli)) {
+			client_signing = "allowed";
+		}
+		if (client_is_signing_mandatory(cli)) {
+			client_signing = "required";
+		}
 
+		server_signing = "not supported";
+		if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
+			server_signing = "supported";
+			server_allowed = true;
+		}
 		if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
-			/* Fail if server says signing is mandatory and we don't want to support it. */
-			if (!client_is_signing_allowed(cli)) {
-				DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
-				tevent_req_nterror(req,
-						   NT_STATUS_ACCESS_DENIED);
-				return;
-			}
-			negotiated_smb_signing = true;
-		} else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
-			/* Fail if client says signing is mandatory and the server doesn't support it. */
-			if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
-				DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
-				tevent_req_nterror(req,
-						   NT_STATUS_ACCESS_DENIED);
-				return;
-			}
-			negotiated_smb_signing = true;
-		} else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
-			negotiated_smb_signing = true;
+			server_signing = "required";
+			server_mandatory = true;
 		}
 
-		if (negotiated_smb_signing) {
-			cli_set_signing_negotiated(cli);
+		ok = cli_set_signing_negotiated(cli,
+						server_allowed,
+						server_mandatory);
+		if (!ok) {
+			DEBUG(1,("cli_negprot: SMB signing is required, "
+				 "but client[%s] and server[%s] mismatch\n",
+				 client_signing, server_signing));
+			tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+			return;
 		}
 
 	} else if (cli_state_protocol(cli) >= PROTOCOL_LANMAN1) {
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index db5e545..c22cd30 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -168,8 +168,9 @@ struct cli_state *cli_state_create(TALLOC_CTX *mem_ctx,
 				   int signing_state, int flags)
 {
 	struct cli_state *cli = NULL;
-	bool allow_smb_signing = false;
-	bool mandatory_signing = false;
+	bool allow_smb_signing;
+	bool desire_smb_signing;
+	bool mandatory_signing;
 	socklen_t ss_length;
 	int ret;
 
@@ -236,30 +237,43 @@ struct cli_state *cli_state_create(TALLOC_CTX *mem_ctx,
 		cli->use_level_II_oplocks = true;
 	}
 
-	if (lp_client_signing()) {
-		allow_smb_signing = true;
-	}
-
-	if (lp_client_signing() == Required) {
-		mandatory_signing = true;
-	}
-
-	if (signing_state != Undefined) {
-		allow_smb_signing = true;
+	if (signing_state == Undefined) {
+		signing_state = lp_client_signing();
 	}
 
-	if (signing_state == false) {
+	switch (signing_state) {
+	case false:
+		/* never */
 		allow_smb_signing = false;
+		desire_smb_signing = false;
 		mandatory_signing = false;
-	}
-
-	if (signing_state == Required) {
+		break;
+	case true:
+		/* if the server supports it */
+		allow_smb_signing = true;
+		desire_smb_signing = true;
+		mandatory_signing = false;
+		break;
+	default:
+	case Undefined:
+	case Auto:
+		/* if the server requires it */
+		allow_smb_signing = true;
+		desire_smb_signing = false;
+		mandatory_signing = false;
+		break;
+	case Required:
+		/* always */
+		allow_smb_signing = true;
+		desire_smb_signing = true;
 		mandatory_signing = true;
+		break;
 	}
 
 	/* initialise signing */
 	cli->signing_state = smb_signing_init(cli,
 					      allow_smb_signing,
+					      desire_smb_signing,
 					      mandatory_signing);
 	if (!cli->signing_state) {
 		goto error;
diff --git a/source3/libsmb/clisigning.c b/source3/libsmb/clisigning.c
index ac4db76..acdc24f 100644
--- a/source3/libsmb/clisigning.c
+++ b/source3/libsmb/clisigning.c
@@ -42,11 +42,6 @@ bool cli_simple_set_signing(struct cli_state *cli,
 	return true;
 }
 
-bool cli_temp_set_signing(struct cli_state *cli)
-{
-	return smb_signing_set_bsrspyl(cli->signing_state);
-}
-
 void cli_calculate_sign_mac(struct cli_state *cli, char *buf, uint32_t *seqnum)
 {
 	*seqnum = smb_signing_next_seqnum(cli->signing_state, false);
@@ -68,9 +63,11 @@ bool cli_check_sign_mac(struct cli_state *cli, const char *buf, uint32_t seqnum)
 	return true;
 }
 
-void cli_set_signing_negotiated(struct cli_state *cli)
+bool cli_set_signing_negotiated(struct cli_state *cli,
+				bool allowed, bool mandatory)
 {
-	smb_signing_set_negotiated(cli->signing_state);
+	return smb_signing_set_negotiated(cli->signing_state,
+					  allowed, mandatory);
 }
 
 bool client_is_signing_on(struct cli_state *cli)
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index fef7ae0..4992d95 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -865,13 +865,13 @@ void cli_free_enc_buffer(struct cli_state *cli, char *buf);
 bool cli_simple_set_signing(struct cli_state *cli,
 			    const DATA_BLOB user_session_key,
 			    const DATA_BLOB response);
-bool cli_temp_set_signing(struct cli_state *cli);
 void cli_calculate_sign_mac(struct cli_state *cli, char *buf, uint32_t *seqnum);
 bool cli_check_sign_mac(struct cli_state *cli, const char *buf, uint32_t seqnum);
 bool client_is_signing_on(struct cli_state *cli);
 bool client_is_signing_allowed(struct cli_state *cli);
 bool client_is_signing_mandatory(struct cli_state *cli);
-void cli_set_signing_negotiated(struct cli_state *cli);
+bool cli_set_signing_negotiated(struct cli_state *cli,
+				bool allowed, bool mandatory);
 
 /* The following definitions come from libsmb/reparse_symlink.c  */
 
diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c
index c926b48..ba20723 100644
--- a/source3/libsmb/smb_signing.c
+++ b/source3/libsmb/smb_signing.c
@@ -29,15 +29,15 @@ struct smb_signing_state {
 	/* is signing localy allowed */
 	bool allowed;
 
+	/* is signing localy desired */
+	bool desired;
+
 	/* is signing localy mandatory */
 	bool mandatory;
 
 	/* is signing negotiated by the peer */
 	bool negotiated;
 
-	/* send BSRSPYL signatures */
-	bool bsrspyl;
-
 	bool active; /* Have I ever seen a validly signed packet? */
 
 	/* mac_key.length > 0 means signing is started */
@@ -54,7 +54,6 @@ struct smb_signing_state {
 static void smb_signing_reset_info(struct smb_signing_state *si)
 {
 	si->active = false;
-	si->bsrspyl = false;
 	si->seqnum = 0;
 
 	if (si->free_fn) {
@@ -68,6 +67,7 @@ static void smb_signing_reset_info(struct smb_signing_state *si)
 
 struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx,
 					      bool allowed,
+					      bool desired,
 					      bool mandatory,
 					      void *(*alloc_fn)(TALLOC_CTX *, size_t),
 					      void (*free_fn)(TALLOC_CTX *, void *))
@@ -92,10 +92,15 @@ struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx,
 	}
 
 	if (mandatory) {
+		desired = true;
+	}
+
+	if (desired) {
 		allowed = true;
 	}
 
 	si->allowed = allowed;
+	si->desired = desired;
 	si->mandatory = mandatory;
 
 	return si;
@@ -103,9 +108,11 @@ struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx,
 
 struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx,
 					   bool allowed,
+					   bool desired,
 					   bool mandatory)
 {
-	return smb_signing_init_ex(mem_ctx, allowed, mandatory, NULL, NULL);
+	return smb_signing_init_ex(mem_ctx, allowed, desired, mandatory,
+				   NULL, NULL);
 }
 
 static bool smb_signing_good(struct smb_signing_state *si,
@@ -210,10 +217,11 @@ void smb_signing_sign_pdu(struct smb_signing_state *si,
 			  uint8_t *outbuf, uint32_t seqnum)
 {
 	uint8_t calc_md5_mac[16];
-	uint16_t flags2;
+	uint8_t com;
+	uint8_t flags;
 
 	if (si->mac_key.length == 0) {
-		if (!si->bsrspyl) {
+		if (!si->negotiated) {
 			return;
 		}
 	}
@@ -226,15 +234,32 @@ void smb_signing_sign_pdu(struct smb_signing_state *si,
 		abort();
 	}
 
-	/* mark the packet as signed - BEFORE we sign it...*/
-	flags2 = SVAL(outbuf,smb_flg2);
-	flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
-	SSVAL(outbuf, smb_flg2, flags2);
+	com = SVAL(outbuf,smb_com);
+	flags = SVAL(outbuf,smb_flg);
+
+	if (!(flags & FLAG_REPLY)) {
+		uint16_t flags2 = SVAL(outbuf,smb_flg2);
+		/*
+		 * If this is a request, specify what is
+		 * supported or required by the client
+		 */
+		if (si->negotiated && si->desired) {
+			flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
+		}
+		if (si->negotiated && si->mandatory) {
+			flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED;
+		}
+		SSVAL(outbuf, smb_flg2, flags2);
+	}
 
-	if (si->bsrspyl) {
+	if (si->mac_key.length == 0) {
 		/* I wonder what BSRSPYL stands for - but this is what MS
 		   actually sends! */
-		memcpy(calc_md5_mac, "BSRSPYL ", 8);
+		if (com == SMBsesssetupX) {
+			memcpy(calc_md5_mac, "BSRSPYL ", 8);
+		} else {
+			memset(calc_md5_mac, 0, 8);
+		}
 	} else {
 		smb_signing_md5(&si->mac_key, outbuf,
 				seqnum, calc_md5_mac);
@@ -305,21 +330,6 @@ bool smb_signing_check_pdu(struct smb_signing_state *si,
 	return smb_signing_good(si, good, seqnum);
 }
 
-bool smb_signing_set_bsrspyl(struct smb_signing_state *si)
-{
-	if (!si->negotiated) {
-		return false;
-	}
-
-	if (si->active) {
-		return false;
-	}
-
-	si->bsrspyl = true;
-
-	return true;
-}
-
 bool smb_signing_activate(struct smb_signing_state *si,
 			  const DATA_BLOB user_session_key,
 			  const DATA_BLOB response)
@@ -398,14 +408,42 @@ bool smb_signing_is_mandatory(struct smb_signing_state *si)
 	return si->mandatory;
 }
 
-bool smb_signing_set_negotiated(struct smb_signing_state *si)
+bool smb_signing_set_negotiated(struct smb_signing_state *si,
+				bool allowed, bool mandatory)
 {
-	if (!si->allowed) {
+	if (si->active) {
+		return true;
+	}
+
+	if (!si->allowed && mandatory) {
 		return false;
 	}
 
-	si->negotiated = true;
+	if (si->mandatory && !allowed) {
+		return false;
+	}
+
+	if (si->mandatory) {
+		si->negotiated = true;
+		return true;
+	}
+
+	if (mandatory) {
+		si->negotiated = true;
+		return true;
+	}
+
+	if (!si->desired) {
+		si->negotiated = false;
+		return true;
+	}
+
+	if (si->desired && allowed) {
+		si->negotiated = true;
+		return true;
+	}
 
+	si->negotiated = false;
 	return true;
 }
 
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index 71e0291..89ef52c 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -375,7 +375,6 @@ static void reply_nt1(struct smb_request *req, uint16 choice)
 			capabilities &= ~CAP_RAW_MODE;
 			if (lp_server_signing() == Required)
 				secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
-			srv_set_signing_negotiated(sconn);
 		} else {
 			DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
 			if (lp_server_signing() == Required) {
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index c7f0ade..ab0c147 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -1674,15 +1674,21 @@ void remove_from_common_flags2(uint32 v)
 static void construct_reply_common(struct smb_request *req, const char *inbuf,
 				   char *outbuf)
 {
+	uint16_t in_flags2 = SVAL(inbuf,smb_flg2);
+	uint16_t out_flags2 = common_flags2;
+
+	out_flags2 |= in_flags2 & FLAGS2_UNICODE_STRINGS;
+	out_flags2 |= in_flags2 & FLAGS2_SMB_SECURITY_SIGNATURES;
+	out_flags2 |= in_flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED;
+
 	srv_set_message(outbuf,0,0,false);
 
 	SCVAL(outbuf, smb_com, req->cmd);
 	SIVAL(outbuf,smb_rcls,0);
 	SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); 
-	SSVAL(outbuf,smb_flg2,
-		(SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
-		common_flags2);
+	SSVAL(outbuf,smb_flg2, out_flags2);
 	memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
+	memcpy(outbuf+smb_ss_field, inbuf+smb_ss_field, 8);
 
 	SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
 	SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 8edd695..3d0665d 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -54,7 +54,8 @@ void srv_calculate_sign_mac(struct smbd_server_connection *conn,
 			    char *outbuf, uint32_t seqnum);
 void srv_cancel_sign_response(struct smbd_server_connection *conn);
 bool srv_init_signing(struct smbd_server_connection *conn);
-void srv_set_signing_negotiated(struct smbd_server_connection *conn);
+void srv_set_signing_negotiated(struct smbd_server_connection *conn,
+			        bool allowed, bool mandatory);
 bool srv_is_signing_active(struct smbd_server_connection *conn);
 bool srv_is_signing_negotiated(struct smbd_server_connection *conn);
 void srv_set_signing(struct smbd_server_connection *conn,
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 6dc8609..28ae24e 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c


-- 
Samba Shared Repository


More information about the samba-cvs mailing list