Attached is a patch which in my environment (Linux/Heimdal 1.2.1) fixes
cross-realm GSSAPI authentication.

Changes it makes:
1.  When using krb5_kuserok, do not call gss_compare_name to check that
authn_name and authz_name are the same.  Instead, make TWO calls to
krb5_kuserok, one for each ID.  If both IDs are acceptable, allow the
login.
2.  Disable checking that the name is a GSS_KRB5_PRINCIPAL_NAME, as
this doesn't appear to be always the case for the authz_name.

If I create a .k5login listing both usern...@realm1 and
usern...@realm2, and make that file follow the appropriate security
restrictions (world read, user only write permissions), this lets me
use GSSAPI logins with principals from either REALM1 or REALM2.

This leaves untouched the behavior in the case where krb5_kuserok is
not available.

Bryan Jacobs
Index: dovecot-1.1.11/src/auth/mech-gssapi.c
===================================================================
--- dovecot-1.1.11.orig/src/auth/mech-gssapi.c
+++ dovecot-1.1.11/src/auth/mech-gssapi.c
@@ -310,7 +310,7 @@ static void gssapi_wrap(struct gssapi_au
 }
 
 #ifdef USE_KRB5_USEROK
-static bool gssapi_krb5_userok(struct gssapi_auth_request *request)
+static bool gssapi_krb5_userok(struct gssapi_auth_request *request, gss_name_t name)
 {
 	krb5_context ctx;
 	krb5_principal princ;
@@ -322,7 +322,7 @@ static bool gssapi_krb5_userok(struct gs
 	bool ret = FALSE;
 
 	/* Parse out the principal's username */
-	major_status = gss_display_name(&minor_status, request->authn_name,
+	major_status = gss_display_name(&minor_status, name,
 					&princ_name, &name_type);
 	if (major_status != GSS_S_COMPLETE) {
 		auth_request_log_gss_error(&request->auth_request, major_status,
@@ -330,11 +330,11 @@ static bool gssapi_krb5_userok(struct gs
 					   "gssapi_krb5_userok");
 		return FALSE;
 	}
-	if (name_type != GSS_KRB5_NT_PRINCIPAL_NAME) {
+	/*if (name_type != GSS_KRB5_NT_PRINCIPAL_NAME && name_type != GSS_KRB5_NT_USER_NAME) {
 		auth_request_log_error(&request->auth_request, "gssapi",
 				       "OID not kerberos principal name");
 		return FALSE;
-	}
+	}*/
 	princ_display_name = t_strndup(princ_name.value, princ_name.length);
 	gss_release_buffer(&minor_status, &princ_name);
 
@@ -433,21 +433,35 @@ static void gssapi_unwrap(struct gssapi_
 			  (unsigned char *)outbuf.value + 4,
 			  outbuf.length - 4);
 
+#ifdef USE_KRB5_USEROK
+	equal_authn_authz = gssapi_krb5_userok(request, request->authn_name);
+	if (equal_authn_authz == 0) {
+		auth_request_log_error(&request->auth_request, "gssapi",
+			"authn_name not authorized");
+		auth_request_fail(&request->auth_request);
+		return;
+	}
+	
+	equal_authn_authz = gssapi_krb5_userok(request, request->authz_name);
+	if (equal_authn_authz == 0) {
+		auth_request_log_error(&request->auth_request, "gssapi",
+			"authz_name not authorized");
+		auth_request_fail(&request->auth_request);
+		return;
+	}
+#else
 	major_status = gss_compare_name(&minor_status,
 					request->authn_name,
 					request->authz_name,
 					&equal_authn_authz);
-#ifdef USE_KRB5_USEROK
-	if (equal_authn_authz == 0)
-		equal_authn_authz = gssapi_krb5_userok(request);
-#endif
-	if (equal_authn_authz == 0) {
+	if (equal_authn_authz != 0) {
 		auth_request_log_error(&request->auth_request, "gssapi",
 			"authn_name and authz_name differ: not supported");
 		auth_request_fail(&request->auth_request);
 		return;
 	}
 #endif
+#endif
 	auth_request_success(&request->auth_request, NULL, 0);
 }
 

Attachment: signature.asc
Description: PGP signature

Reply via email to