[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Tue Dec 7 10:24:02 MST 2010


The branch, master has been updated
       via  15c33ad libcli/auth: let spnego_write_mech_types() check the asn1_load() return
       via  f802075 s3:ntlm_auth: support clients which offer a spnego mechs we don't support
       via  ee4f5ac s3:ntlm_auth: free session key, as we don't use it (at least for now)
       via  9a56ade s3:ntlm_auth: fix memory leak in the raw ntlmssp code path
      from  6acbcd1 Make sure that user exists after running add user script before adding sam account.

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


- Log -----------------------------------------------------------------
commit 15c33ada6b897ac46141aaae0f0333816b94448b
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

commit f802075f08fe0d86f3d176f2302236aeb5834f3d
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

commit ee4f5ac6182969bcab91955e6d6581e408d222f1
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

commit 9a56ade6b1d627126418c75de4602610b4482503
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

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

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