[SCM] Samba Shared Repository - branch v3-6-test updated

Jeremy Allison jra at samba.org
Tue Dec 7 16:02:01 MST 2010


The branch, v3-6-test has been updated
       via  aab5998 libcli/auth: let spnego_write_mech_types() check the asn1_load() return
       via  da8ea03 s3:ntlm_auth: support clients which offer a spnego mechs we don't support
       via  3dc4eb5 s3:ntlm_auth: free session key, as we don't use it (at least for now)
       via  84b4754 s3:ntlm_auth: fix memory leak in the raw ntlmssp code path
      from  329d865 docs: clarify the idmap_rid manpage (bug #7788)

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


- Log -----------------------------------------------------------------
commit aab5998ac9a2b103776c6707369480bf8afb0f08
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Dec 2 00:40:01 2010 +0100

    libcli/auth: let spnego_write_mech_types() check the asn1_load() return
    
    metze
    
    Autobuild-User: Stefan Metzmacher <metze at samba.org>
    Autobuild-Date: Tue Dec  7 18:23:41 CET 2010 on sn-devel-104
    (cherry picked from commit 15c33ada6b897ac46141aaae0f0333816b94448b)

commit da8ea0363d8cd5a2d86a02d61bbd43a598fd5a44
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Dec 2 00:39:23 2010 +0100

    s3:ntlm_auth: support clients which offer a spnego mechs we don't support
    
    Before we rejected the authentication if we don't support the
    first spnego mech the client offered.
    
    We now negotiate the first mech we support.
    
    This fix works arround problems, when a client
    sends the NEGOEX (1.3.6.1.4.1.311.2.2.30) oid,
    which we don't support.
    
    metze
    (cherry picked from commit f802075f08fe0d86f3d176f2302236aeb5834f3d)

commit 3dc4eb518d7efd2c4b5b89cb3b999729594d2dcb
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Dec 1 05:52:29 2010 +0100

    s3:ntlm_auth: free session key, as we don't use it (at least for now)
    
    metze
    (cherry picked from commit ee4f5ac6182969bcab91955e6d6581e408d222f1)

commit 84b4754a36d453fb35d002ce24a8301b970cdc67
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Dec 1 05:50:59 2010 +0100

    s3:ntlm_auth: fix memory leak in the raw ntlmssp code path
    
    metze
    (cherry picked from commit 9a56ade6b1d627126418c75de4602610b4482503)

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

Summary of changes:
 libcli/auth/spnego_parse.c |    4 +
 source3/utils/ntlm_auth.c  |  280 +++++++++++++++++++++++++++-----------------
 2 files changed, 175 insertions(+), 109 deletions(-)


Changeset truncated at 500 lines:

diff --git a/libcli/auth/spnego_parse.c b/libcli/auth/spnego_parse.c
index 86b083d..27ede1b 100644
--- a/libcli/auth/spnego_parse.c
+++ b/libcli/auth/spnego_parse.c
@@ -380,6 +380,10 @@ bool spnego_write_mech_types(TALLOC_CTX *mem_ctx,
 {
 	struct asn1_data *asn1 = asn1_init(mem_ctx);
 
+	if (asn1 == NULL) {
+		return false;
+	}
+
 	/* Write mechTypes */
 	if (mech_types && *mech_types) {
 		int i;
diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
index 9f0c839..43af0fd 100644
--- a/source3/utils/ntlm_auth.c
+++ b/source3/utils/ntlm_auth.c
@@ -82,6 +82,8 @@ struct ntlm_auth_state {
 	struct ntlmssp_state *ntlmssp_state;
 	uint32_t neg_flags;
 	char *want_feature_list;
+	char *spnego_mech;
+	char *spnego_mech_oid;
 	bool have_session_key;
 	DATA_BLOB session_key;
 	DATA_BLOB initial_message;
@@ -1192,11 +1194,12 @@ static void offer_gss_spnego_mechs(void) {
 
 	/* Server negTokenInit (mech offerings) */
 	spnego.type = SPNEGO_NEG_TOKEN_INIT;
-	spnego.negTokenInit.mechTypes = talloc_array(ctx, const char *, 3);
+	spnego.negTokenInit.mechTypes = talloc_array(ctx, const char *, 4);
 #ifdef HAVE_KRB5
 	spnego.negTokenInit.mechTypes[0] = talloc_strdup(ctx, OID_KERBEROS5_OLD);
-	spnego.negTokenInit.mechTypes[1] = talloc_strdup(ctx, OID_NTLMSSP);
-	spnego.negTokenInit.mechTypes[2] = NULL;
+	spnego.negTokenInit.mechTypes[1] = talloc_strdup(ctx, OID_KERBEROS5);
+	spnego.negTokenInit.mechTypes[2] = talloc_strdup(ctx, OID_NTLMSSP);
+	spnego.negTokenInit.mechTypes[3] = NULL;
 #else
 	spnego.negTokenInit.mechTypes[0] = talloc_strdup(ctx, OID_NTLMSSP);
 	spnego.negTokenInit.mechTypes[1] = NULL;
@@ -1266,9 +1269,10 @@ bool spnego_parse_krb5_wrap(TALLOC_CTX *ctx, DATA_BLOB blob, DATA_BLOB *ticket,
 static void manage_gss_spnego_request(struct ntlm_auth_state *state,
 					char *buf, int length)
 {
-	static struct ntlmssp_state *ntlmssp_state = NULL;
 	struct spnego_data request, response;
 	DATA_BLOB token;
+	DATA_BLOB raw_in_token = data_blob_null;
+	DATA_BLOB raw_out_token = data_blob_null;
 	NTSTATUS status;
 	ssize_t len;
 	TALLOC_CTX *ctx = talloc_tos();
@@ -1279,6 +1283,7 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state,
 	const char *reply_code;
 	char       *reply_base64;
 	char *reply_argument = NULL;
+	char *supportedMech = NULL;
 
 	if (strlen(buf) < 2) {
 		DEBUG(1, ("SPENGO query [%s] invalid\n", buf));
@@ -1287,7 +1292,9 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state,
 	}
 
 	if (strncmp(buf, "YR", 2) == 0) {
-		TALLOC_FREE(ntlmssp_state);
+		TALLOC_FREE(state->ntlmssp_state);
+		TALLOC_FREE(state->spnego_mech);
+		TALLOC_FREE(state->spnego_mech_oid);
 	} else if (strncmp(buf, "KK", 2) == 0) {
 		;
 	} else {
@@ -1319,6 +1326,8 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state,
 	    && (strncmp((char *)token.data, "NTLMSSP", 7) == 0)) {
 		char *reply;
 
+		data_blob_free(&token);
+
 		DEBUG(10, ("Could not parse GSS-SPNEGO, trying raw "
 			   "ntlmssp\n"));
 
@@ -1339,6 +1348,7 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state,
 		return;
 	}
 
+	ZERO_STRUCT(request);
 	len = spnego_read_data(ctx, token, &request);
 	data_blob_free(&token);
 
@@ -1349,6 +1359,20 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state,
 	}
 
 	if (request.type == SPNEGO_NEG_TOKEN_INIT) {
+#ifdef HAVE_KRB5
+		int krb5_idx = -1;
+#endif
+		int ntlm_idx = -1;
+		int used_idx = -1;
+		int i;
+
+		if (state->spnego_mech) {
+			DEBUG(1, ("Client restarted SPNEGO with NegTokenInit "
+				  "while mech[%s] was already negotiated\n",
+				  state->spnego_mech));
+			x_fprintf(x_stdout, "BH Client send NegTokenInit twice\n");
+			return;
+		}
 
 		/* Second request from Client. This is where the
 		   client offers its mechanism to use. */
@@ -1362,158 +1386,198 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state,
 		}
 
 		status = NT_STATUS_UNSUCCESSFUL;
-		if (strcmp(request.negTokenInit.mechTypes[0], OID_NTLMSSP) == 0) {
+		for (i = 0; request.negTokenInit.mechTypes[i] != NULL; i++) {
+			DEBUG(10,("got mech[%d][%s]\n",
+				i, request.negTokenInit.mechTypes[i]));
+#ifdef HAVE_KRB5
+			if (strcmp(request.negTokenInit.mechTypes[i], OID_KERBEROS5_OLD) == 0) {
+				krb5_idx = i;
+				break;
+			}
+			if (strcmp(request.negTokenInit.mechTypes[i], OID_KERBEROS5) == 0) {
+				krb5_idx = i;
+				break;
+			}
+#endif
+			if (strcmp(request.negTokenInit.mechTypes[i], OID_NTLMSSP) == 0) {
+				ntlm_idx = i;
+				break;
+			}
+		}
 
-			if ( request.negTokenInit.mechToken.data == NULL ) {
-				DEBUG(1, ("Client did not provide NTLMSSP data\n"));
-				x_fprintf(x_stdout, "BH Client did not provide "
-						    "NTLMSSP data\n");
+		used_idx = ntlm_idx;
+#ifdef HAVE_KRB5
+		if (krb5_idx != -1) {
+			ntlm_idx = -1;
+			used_idx = krb5_idx;
+		}
+#endif
+		if (ntlm_idx > -1) {
+			state->spnego_mech = talloc_strdup(state, "ntlmssp");
+			if (state->spnego_mech == NULL) {
+				x_fprintf(x_stdout, "BH Out of memory\n");
 				return;
 			}
 
-			if ( ntlmssp_state != NULL ) {
+			if (state->ntlmssp_state) {
 				DEBUG(1, ("Client wants a new NTLMSSP challenge, but "
 					  "already got one\n"));
 				x_fprintf(x_stdout, "BH Client wants a new "
 						    "NTLMSSP challenge, but "
 						    "already got one\n");
-				TALLOC_FREE(ntlmssp_state);
+				TALLOC_FREE(state->ntlmssp_state);
 				return;
 			}
 
-			if (!NT_STATUS_IS_OK(status = ntlm_auth_start_ntlmssp_server(&ntlmssp_state))) {
+			status = ntlm_auth_start_ntlmssp_server(&state->ntlmssp_state);
+			if (!NT_STATUS_IS_OK(status)) {
 				x_fprintf(x_stdout, "BH %s\n", nt_errstr(status));
 				return;
 			}
-
-			DEBUG(10, ("got NTLMSSP packet:\n"));
-			dump_data(10, request.negTokenInit.mechToken.data,
-				  request.negTokenInit.mechToken.length);
-
-			response.type = SPNEGO_NEG_TOKEN_TARG;
-			response.negTokenTarg.supportedMech = talloc_strdup(ctx, OID_NTLMSSP);
-			response.negTokenTarg.mechListMIC = data_blob_talloc(ctx, NULL, 0);
-
-			status = ntlmssp_update(ntlmssp_state,
-						       request.negTokenInit.mechToken,
-						       &response.negTokenTarg.responseToken);
 		}
 
 #ifdef HAVE_KRB5
-		if (strcmp(request.negTokenInit.mechTypes[0], OID_KERBEROS5_OLD) == 0) {
-
-			TALLOC_CTX *mem_ctx = talloc_init("manage_gss_spnego_request");
-			char *principal;
-			DATA_BLOB ap_rep;
-			DATA_BLOB session_key;
-			struct PAC_LOGON_INFO *logon_info = NULL;
-			DATA_BLOB ticket;
-			uint8_t tok_id[2];
-
-			if ( request.negTokenInit.mechToken.data == NULL ) {
-				DEBUG(1, ("Client did not provide Kerberos data\n"));
-				x_fprintf(x_stdout, "BH Client did not provide "
-						    "Kerberos data\n");
+		if (krb5_idx > -1) {
+			state->spnego_mech = talloc_strdup(state, "krb5");
+			if (state->spnego_mech == NULL) {
+				x_fprintf(x_stdout, "BH Out of memory\n");
 				return;
 			}
-
-			dump_data(10, request.negTokenInit.mechToken.data,
-				  request.negTokenInit.mechToken.length);
-
-			if (!spnego_parse_krb5_wrap(ctx, request.negTokenInit.mechToken,
-						    &ticket, tok_id)) {
-				DEBUG(1, ("spnego_parse_krb5_wrap failed\n"));
-				x_fprintf(x_stdout, "BH spnego_parse_krb5_wrap failed\n");
+		}
+#endif
+		if (used_idx > -1) {
+			state->spnego_mech_oid = talloc_strdup(state,
+				request.negTokenInit.mechTypes[used_idx]);
+			if (state->spnego_mech_oid == NULL) {
+				x_fprintf(x_stdout, "BH Out of memory\n");
 				return;
 			}
-
-			response.type = SPNEGO_NEG_TOKEN_TARG;
-			response.negTokenTarg.supportedMech = talloc_strdup(ctx, OID_KERBEROS5_OLD);
-			response.negTokenTarg.mechListMIC = data_blob_talloc(ctx, NULL, 0);
-			response.negTokenTarg.responseToken = data_blob_talloc(ctx, NULL, 0);
-
-			status = ads_verify_ticket(mem_ctx, lp_realm(), 0,
-						   &ticket,
-						   &principal, &logon_info, &ap_rep,
-						   &session_key, True);
-
-			/* Now in "principal" we have the name we are
-                           authenticated as. */
-
-			if (NT_STATUS_IS_OK(status)) {
-
-				domain = strchr_m(principal, '@');
-
-				if (domain == NULL) {
-					DEBUG(1, ("Did not get a valid principal "
-						  "from ads_verify_ticket\n"));
-					x_fprintf(x_stdout, "BH Did not get a "
-						  "valid principal from "
-						  "ads_verify_ticket\n");
-					return;
-				}
-
-				*domain++ = '\0';
-				domain = SMB_STRDUP(domain);
-				user = SMB_STRDUP(principal);
-
-				netsamlogon_cache_store(
-					user, &logon_info->info3);
-
-				data_blob_free(&ap_rep);
+			supportedMech = talloc_strdup(ctx, state->spnego_mech_oid);
+			if (supportedMech == NULL) {
+				x_fprintf(x_stdout, "BH Out of memory\n");
+				return;
 			}
 
-			TALLOC_FREE(mem_ctx);
+			status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+		} else {
+			status = NT_STATUS_NOT_SUPPORTED;
+		}
+		if (used_idx == 0) {
+			status = NT_STATUS_OK;
+			raw_in_token = request.negTokenInit.mechToken;
 		}
-#endif
-
 	} else {
+		if (state->spnego_mech == NULL) {
+			DEBUG(1,("Got netTokenTarg without negTokenInit\n"));
+			x_fprintf(x_stdout, "BH Got a negTokenTarg without "
+					    "negTokenInit\n");
+			return;
+		}
 
-		if ( (request.negTokenTarg.supportedMech == NULL) ||
-		     ( strcmp(request.negTokenTarg.supportedMech, OID_NTLMSSP) != 0 ) ) {
-			/* Kerberos should never send a negTokenTarg, OID_NTLMSSP
-			   is the only one we support that sends this stuff */
-			DEBUG(1, ("Got a negTokenTarg for something non-NTLMSSP: %s\n",
-				  request.negTokenTarg.supportedMech));
-			x_fprintf(x_stdout, "BH Got a negTokenTarg for "
-					    "something non-NTLMSSP\n");
+		if ((request.negTokenTarg.supportedMech != NULL) &&
+		     (strcmp(request.negTokenTarg.supportedMech, state->spnego_mech_oid) != 0 ) ) {
+			DEBUG(1, ("Got a negTokenTarg with mech[%s] while [%s] was already negotiated\n",
+				  request.negTokenTarg.supportedMech,
+				  state->spnego_mech_oid));
+			x_fprintf(x_stdout, "BH Got a negTokenTarg with speficied mech\n");
 			return;
 		}
 
-		if (request.negTokenTarg.responseToken.data == NULL) {
-			DEBUG(1, ("Got a negTokenTarg without a responseToken!\n"));
-			x_fprintf(x_stdout, "BH Got a negTokenTarg without a "
-					    "responseToken!\n");
+		status = NT_STATUS_OK;
+		raw_in_token = request.negTokenTarg.responseToken;
+	}
+
+	if (!NT_STATUS_IS_OK(status)) {
+		/* error or more processing */
+	} else if (strcmp(state->spnego_mech, "ntlmssp") == 0) {
+
+		DEBUG(10, ("got NTLMSSP packet:\n"));
+		dump_data(10, raw_in_token.data, raw_in_token.length);
+
+		status = ntlmssp_update(state->ntlmssp_state,
+					raw_in_token,
+					&raw_out_token);
+		if (NT_STATUS_IS_OK(status)) {
+			user = talloc_strdup(ctx, state->ntlmssp_state->user);
+			domain = talloc_strdup(ctx, state->ntlmssp_state->domain);
+		}
+		if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+			TALLOC_FREE(state->ntlmssp_state);
+		}
+#ifdef HAVE_KRB5
+	} else if (strcmp(state->spnego_mech, "krb5") == 0) {
+		char *principal;
+		DATA_BLOB ap_rep;
+		DATA_BLOB session_key;
+		struct PAC_LOGON_INFO *logon_info = NULL;
+		DATA_BLOB ticket;
+		uint8_t tok_id[2];
+
+		if (!spnego_parse_krb5_wrap(ctx, raw_in_token,
+					    &ticket, tok_id)) {
+			DEBUG(1, ("spnego_parse_krb5_wrap failed\n"));
+			x_fprintf(x_stdout, "BH spnego_parse_krb5_wrap failed\n");
 			return;
 		}
 
-		status = ntlmssp_update(ntlmssp_state,
-					       request.negTokenTarg.responseToken,
-					       &response.negTokenTarg.responseToken);
+		status = ads_verify_ticket(ctx, lp_realm(), 0,
+					   &ticket,
+					   &principal, &logon_info, &ap_rep,
+					   &session_key, True);
 
-		response.type = SPNEGO_NEG_TOKEN_TARG;
-		response.negTokenTarg.supportedMech = talloc_strdup(ctx, OID_NTLMSSP);
-		response.negTokenTarg.mechListMIC = data_blob_talloc(ctx, NULL, 0);
+		/* Now in "principal" we have the name we are authenticated as. */
 
 		if (NT_STATUS_IS_OK(status)) {
-			user = SMB_STRDUP(ntlmssp_state->user);
-			domain = SMB_STRDUP(ntlmssp_state->domain);
-			TALLOC_FREE(ntlmssp_state);
+
+			domain = strchr_m(principal, '@');
+
+			if (domain == NULL) {
+				DEBUG(1, ("Did not get a valid principal "
+					  "from ads_verify_ticket\n"));
+				x_fprintf(x_stdout, "BH Did not get a "
+					  "valid principal from "
+					  "ads_verify_ticket\n");
+				return;
+			}
+
+			*domain++ = '\0';
+			domain = talloc_strdup(ctx, domain);
+			user = talloc_strdup(ctx, principal);
+
+			if (logon_info) {
+				netsamlogon_cache_store(
+					user, &logon_info->info3);
+			}
+
+			data_blob_free(&ap_rep);
+			data_blob_free(&session_key);
 		}
+		data_blob_free(&ticket);
+#endif
 	}
 
 	spnego_free_data(&request);
+	ZERO_STRUCT(response);
+	response.type = SPNEGO_NEG_TOKEN_TARG;
 
 	if (NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(state->spnego_mech);
+		TALLOC_FREE(state->spnego_mech_oid);
 		response.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED;
+		response.negTokenTarg.responseToken = raw_out_token;
 		reply_code = "AF";
 		reply_argument = talloc_asprintf(ctx, "%s\\%s", domain, user);
 	} else if (NT_STATUS_EQUAL(status,
 				   NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+		response.negTokenTarg.supportedMech = supportedMech;
+		response.negTokenTarg.responseToken = raw_out_token;
 		response.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE;
 		reply_code = "TT";
 		reply_argument = talloc_strdup(ctx, "*");
 	} else {
+		TALLOC_FREE(state->spnego_mech);
+		TALLOC_FREE(state->spnego_mech_oid);
+		data_blob_free(&raw_out_token);
 		response.negTokenTarg.negResult = SPNEGO_REJECT;
 		reply_code = "NA";
 		reply_argument = talloc_strdup(ctx, nt_errstr(status));
@@ -1522,12 +1586,10 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state,
 	if (!reply_argument) {
 		DEBUG(1, ("Could not write SPNEGO data blob\n"));
 		x_fprintf(x_stdout, "BH Could not write SPNEGO data blob\n");
+		spnego_free_data(&response);
 		return;
 	}
 
-	SAFE_FREE(user);
-	SAFE_FREE(domain);
-
 	len = spnego_write_data(ctx, &token, &response);
 	spnego_free_data(&response);
 


-- 
Samba Shared Repository


More information about the samba-cvs mailing list