[SCM] Samba Shared Repository - branch v3-2-test updated - initial-v3-2-test-2254-g8767a0d

Jeremy Allison jra at samba.org
Fri Feb 15 02:11:30 GMT 2008


The branch, v3-2-test has been updated
       via  8767a0dab95c544878b4187157e494e740974bb8 (commit)
       via  67768fc71f9bd7ff3d61acc50360356b524ae923 (commit)
       via  8cd04b948bfba3896d40c9e314a197f60ad76833 (commit)
       via  b41799c351c72b268ef094047a51766747671280 (commit)
       via  b7628f3a47166791db4cd6451d52ea3881a45bed (commit)
      from  e3e08c6e7d270e1be7a9d3042b1f36f5a291f90a (commit)

http://gitweb.samba.org/?samba.git;a=shortlog;h=v3-2-test


- Log -----------------------------------------------------------------
commit 8767a0dab95c544878b4187157e494e740974bb8
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Feb 14 18:10:50 2008 -0800

    Correctly use SPNEGO to negotiate down from krb5 to NTLMSSP.
    Previously we didn't implement the 'NEGO' part of SPNEGO :-).
    Jeremy.

commit 67768fc71f9bd7ff3d61acc50360356b524ae923
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Feb 14 18:08:23 2008 -0800

    Currently we don't SPNEGO negotiate back to NTLMSSP. Note this.
    Jeremy.

commit 8cd04b948bfba3896d40c9e314a197f60ad76833
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Feb 14 18:07:27 2008 -0800

    Currently we don't SPNEGO negotiate back to NTLMSSP. Note this.
    Jeremy.

commit b41799c351c72b268ef094047a51766747671280
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Feb 14 18:06:16 2008 -0800

    Ensure invalidate_vuid() deletes any ntlmssp state.
    Jeremy.

commit b7628f3a47166791db4cd6451d52ea3881a45bed
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Feb 14 18:05:37 2008 -0800

    Allow auth_ntlmssp_end() to ignore null pointers passed in.
    Jeremy.

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

Summary of changes:
 source/auth/auth_ntlmssp.c   |    7 ++-
 source/rpc_server/srv_pipe.c |   55 +++++++++++++--------
 source/smbd/password.c       |    4 ++
 source/smbd/seal.c           |   20 ++++++--
 source/smbd/sesssetup.c      |  109 +++++++++++++++++++++++++++++++-----------
 5 files changed, 142 insertions(+), 53 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source/auth/auth_ntlmssp.c b/source/auth/auth_ntlmssp.c
index 526f2c9..ed66d0d 100644
--- a/source/auth/auth_ntlmssp.c
+++ b/source/auth/auth_ntlmssp.c
@@ -186,8 +186,13 @@ NTSTATUS auth_ntlmssp_start(AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
 
 void auth_ntlmssp_end(AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
 {
-	TALLOC_CTX *mem_ctx = (*auth_ntlmssp_state)->mem_ctx;
+	TALLOC_CTX *mem_ctx;
+
+	if (*auth_ntlmssp_state == NULL) {
+		return;
+	}
 
+	mem_ctx = (*auth_ntlmssp_state)->mem_ctx;
 	if ((*auth_ntlmssp_state)->ntlmssp_state) {
 		ntlmssp_end(&(*auth_ntlmssp_state)->ntlmssp_state);
 	}
diff --git a/source/rpc_server/srv_pipe.c b/source/rpc_server/srv_pipe.c
index 06694a2..a671f89 100644
--- a/source/rpc_server/srv_pipe.c
+++ b/source/rpc_server/srv_pipe.c
@@ -1105,7 +1105,7 @@ static bool pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_
 	char *OIDs[ASN1_MAX_OIDS];
         int i;
 	NTSTATUS status;
-        bool got_kerberos_mechanism = False;
+        bool got_kerberos_mechanism = false;
 	AUTH_NTLMSSP_STATE *a = NULL;
 	RPC_HDR_AUTH auth_info;
 
@@ -1133,7 +1133,7 @@ static bool pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_
         }
 
 	if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
-		got_kerberos_mechanism = True;
+		got_kerberos_mechanism = true;
 	}
 
 	for (i=0;OIDs[i];i++) {
@@ -1154,27 +1154,38 @@ static bool pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_
 		free_pipe_ntlmssp_auth_data(&p->auth);
 	}
 
-	/* Initialize the NTLM engine. */
-	status = auth_ntlmssp_start(&a);
-	if (!NT_STATUS_IS_OK(status)) {
-		goto err;
-	}
+	if (!got_kerberos_mechanism) {
+		/* Initialize the NTLM engine. */
+		status = auth_ntlmssp_start(&a);
+		if (!NT_STATUS_IS_OK(status)) {
+			goto err;
+		}
 
-	/*
-	 * Pass the first security blob of data to it.
-	 * This can return an error or NT_STATUS_MORE_PROCESSING_REQUIRED
-	 * which means we need another packet to complete the bind.
-	 */
+		/*
+		 * Pass the first security blob of data to it.
+		 * This can return an error or NT_STATUS_MORE_PROCESSING_REQUIRED
+		 * which means we need another packet to complete the bind.
+		 */
 
-        status = auth_ntlmssp_update(a, secblob, &chal);
+		status = auth_ntlmssp_update(a, secblob, &chal);
 
-	if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-		DEBUG(3,("pipe_spnego_auth_bind_negotiate: auth_ntlmssp_update failed.\n"));
-		goto err;
-	}
+		if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+			DEBUG(3,("pipe_spnego_auth_bind_negotiate: auth_ntlmssp_update failed.\n"));
+			goto err;
+		}
 
-	/* Generate the response blob we need for step 2 of the bind. */
-	response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP);
+		/* Generate the response blob we need for step 2 of the bind. */
+		response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP);
+	} else {
+		/*
+		 * SPNEGO negotiate down to NTLMSSP. The subsequent
+		 * code to process follow-up packets is not complete
+		 * yet. JRA.
+		 */
+		response = spnego_gen_auth_response(NULL,
+					NT_STATUS_MORE_PROCESSING_REQUIRED,
+					OID_NTLMSSP);
+	}
 
 	/* Copy the blob into the pout_auth parse struct */
 	init_rpc_hdr_auth(&auth_info, RPC_SPNEGO_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1);
@@ -1231,6 +1242,10 @@ static bool pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p
 	ZERO_STRUCT(auth_reply);
 	ZERO_STRUCT(response);
 
+	/*
+	 * NB. If we've negotiated down from krb5 to NTLMSSP we'll currently
+	 * fail here as 'a' == NULL.
+	 */
 	if (p->auth.auth_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP || !a) {
 		DEBUG(0,("pipe_spnego_auth_bind_continue: not in NTLMSSP auth state.\n"));
 		goto err;
@@ -1259,7 +1274,7 @@ static bool pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p
 	 * The following call actually checks the challenge/response data.
 	 * for correctness against the given DOMAIN\user name.
 	 */
-	
+
 	if (!pipe_ntlmssp_verify_final(p, &auth_blob)) {
 		goto err;
 	}
diff --git a/source/smbd/password.c b/source/smbd/password.c
index 687b679..80eba56 100644
--- a/source/smbd/password.c
+++ b/source/smbd/password.c
@@ -121,6 +121,10 @@ void invalidate_vuid(uint16 vuid)
 
 	data_blob_free(&vuser->session_key);
 
+	if (vuser->auth_ntlmssp_state) {
+		auth_ntlmssp_end(&vuser->auth_ntlmssp_state);
+	}
+
 	DLIST_REMOVE(validated_users, vuser);
 
 	/* clear the vuid from the 'cache' on each connection, and
diff --git a/source/smbd/seal.c b/source/smbd/seal.c
index ea017e0..d4394e5 100644
--- a/source/smbd/seal.c
+++ b/source/smbd/seal.c
@@ -496,12 +496,15 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn,
 
 	srv_free_encryption_context(&partial_srv_trans_enc_ctx);
 
+	if (got_kerberos_mechanism) {
 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
-	if (got_kerberos_mechanism && lp_use_kerberos_keytab() ) {
 		status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob);
-	} else 
+#else
+		/* Currently we don't SPNEGO negotiate
+		 * back to NTLMSSP as we do in sessionsetupX. We should... */
+		return NT_STATUS_LOGON_FAILURE;
 #endif
-	{
+	} else {
 		status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, true);
 	}
 
@@ -558,7 +561,16 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn,
 	status = auth_ntlmssp_update(ec->auth_ntlmssp_state, auth, &auth_reply);
 	data_blob_free(&auth);
 
-	response = spnego_gen_auth_response(&auth_reply, status, OID_NTLMSSP);
+	/* From RFC4178.
+	 *
+	 *    supportedMech
+	 *
+	 *          This field SHALL only be present in the first reply from the
+	 *                target.
+	 * So set mechOID to NULL here.
+	 */
+
+	response = spnego_gen_auth_response(&auth_reply, status, NULL);
 	data_blob_free(&auth_reply);
 
 	if (NT_STATUS_IS_OK(status)) {
diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c
index 1e4e208..3e04da3 100644
--- a/source/smbd/sesssetup.c
+++ b/source/smbd/sesssetup.c
@@ -620,6 +620,7 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
 				 uint16 vuid,
 				 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
 				 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
+				 const char *OID,
 				 bool wrap)
 {
 	DATA_BLOB response;
@@ -680,7 +681,7 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
 
 	if (wrap) {
 		response = spnego_gen_auth_response(ntlmssp_blob,
-				nt_status, OID_NTLMSSP);
+				nt_status, OID);
 	} else {
 		response = *ntlmssp_blob;
 	}
@@ -745,6 +746,28 @@ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
 }
 
 /****************************************************************************
+ Fall back from krb5 to NTLMSSP.
+****************************************************************************/
+
+static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
+						uint16 vuid)
+{
+	DATA_BLOB response;
+
+	reply_outbuf(req, 4, 0);
+        SSVAL(req->outbuf,smb_uid,vuid);
+
+	DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
+		"but set to downgrade to NTLMSSP\n"));
+
+	response = spnego_gen_auth_response(NULL,
+			NT_STATUS_MORE_PROCESSING_REQUIRED,
+			OID_NTLMSSP);
+	reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
+	data_blob_free(&response);
+}
+
+/****************************************************************************
  Reply to a session setup spnego negotiate packet.
 ****************************************************************************/
 
@@ -789,6 +812,15 @@ static void reply_spnego_negotiate(struct smb_request *req,
 		auth_ntlmssp_end(auth_ntlmssp_state);
 	}
 
+	if (got_kerberos_mechanism) {
+		data_blob_free(&secblob);
+		/* The mechtoken is a krb5 ticket, but
+		 * we need to fall back to NTLM. */
+		reply_spnego_downgrade_to_ntlmssp(req,
+					vuid);
+		return;
+	}
+
 	status = auth_ntlmssp_start(auth_ntlmssp_state);
 	if (!NT_STATUS_IS_OK(status)) {
 		/* Kill the intermediate vuid */
@@ -803,7 +835,7 @@ static void reply_spnego_negotiate(struct smb_request *req,
 	data_blob_free(&secblob);
 
 	reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
-			     &chal, status, True);
+			     &chal, status, OID_NTLMSSP, true);
 
 	data_blob_free(&chal);
 
@@ -823,7 +855,7 @@ static void reply_spnego_auth(struct smb_request *req,
 	DATA_BLOB auth = data_blob_null;
 	DATA_BLOB auth_reply = data_blob_null;
 	DATA_BLOB secblob = data_blob_null;
-	NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
+	NTSTATUS status = NT_STATUS_LOGON_FAILURE;
 
 	if (!spnego_parse_auth(blob1, &auth)) {
 #if 0
@@ -833,7 +865,7 @@ static void reply_spnego_auth(struct smb_request *req,
 		invalidate_vuid(vuid);
 
 		reply_nterror(req, nt_status_squash(
-				      NT_STATUS_INVALID_PARAMETER));
+				      NT_STATUS_LOGON_FAILURE));
 		return;
 	}
 
@@ -843,24 +875,43 @@ static void reply_spnego_auth(struct smb_request *req,
 		bool got_krb5_mechanism = False;
 		status = parse_spnego_mechanisms(auth, &secblob,
 				&got_krb5_mechanism);
-		if (NT_STATUS_IS_OK(status)) {
-			DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
-					(unsigned long)secblob.length));
+
+		if (!NT_STATUS_IS_OK(status)) {
+			/* Kill the intermediate vuid */
+			invalidate_vuid(vuid);
+			reply_nterror(req, nt_status_squash(status));
+			return;
+		}
+
+		DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
+				(unsigned long)secblob.length));
 #ifdef HAVE_KRB5
-			if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
-						lp_use_kerberos_keytab()) ) {
-				bool destroy_vuid = True;
-				reply_spnego_kerberos(req, &secblob,
-						      vuid, &destroy_vuid);
-				data_blob_free(&secblob);
-				data_blob_free(&auth);
-				if (destroy_vuid) {
-					/* Kill the intermediate vuid */
-					invalidate_vuid(vuid);
-				}
-				return;
+		if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
+					lp_use_kerberos_keytab()) ) {
+			bool destroy_vuid = True;
+			reply_spnego_kerberos(req, &secblob,
+					      vuid, &destroy_vuid);
+			data_blob_free(&secblob);
+			data_blob_free(&auth);
+			if (destroy_vuid) {
+				/* Kill the intermediate vuid */
+				invalidate_vuid(vuid);
 			}
+			return;
+		}
 #endif
+		/* Can't blunder into NTLMSSP auth if we have
+		 * a krb5 ticket. */
+
+		if (got_krb5_mechanism) {
+			/* Kill the intermediate vuid */
+			invalidate_vuid(vuid);
+			DEBUG(3,("reply_spnego_auth: network "
+				"misconfiguration, client sent us a "
+				"krb5 ticket and kerberos security "
+				"not enabled"));
+			reply_nterror(req, nt_status_squash(
+					NT_STATUS_LOGON_FAILURE));
 		}
 	}
 
@@ -868,13 +919,13 @@ static void reply_spnego_auth(struct smb_request *req,
 	data_blob_free(&secblob);
 
 	if (!*auth_ntlmssp_state) {
-		/* Kill the intermediate vuid */
-		invalidate_vuid(vuid);
-
-		/* auth before negotiatiate? */
-		reply_nterror(req, nt_status_squash(
-				      NT_STATUS_INVALID_PARAMETER));
-		return;
+		status = auth_ntlmssp_start(auth_ntlmssp_state);
+		if (!NT_STATUS_IS_OK(status)) {
+			/* Kill the intermediate vuid */
+			invalidate_vuid(vuid);
+			reply_nterror(req, nt_status_squash(status));
+			return;
+		}
 	}
 
 	status = auth_ntlmssp_update(*auth_ntlmssp_state,
@@ -882,9 +933,11 @@ static void reply_spnego_auth(struct smb_request *req,
 
 	data_blob_free(&auth);
 
+	/* Don't send the mechid as we've already sent this (RFC4178). */
+
 	reply_spnego_ntlmssp(req, vuid,
 			     auth_ntlmssp_state,
-			     &auth_reply, status, True);
+			     &auth_reply, status, NULL, true);
 
 	data_blob_free(&auth_reply);
 
@@ -1251,7 +1304,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
 
 		reply_spnego_ntlmssp(req, vuid,
 				     &vuser->auth_ntlmssp_state,
-				     &chal, status, False);
+				     &chal, status, OID_NTLMSSP, false);
 		data_blob_free(&chal);
 		return;
 	}


-- 
Samba Shared Repository


More information about the samba-cvs mailing list