Patch to enhance Heimdal support in rlm_krb5

Thomas Kula kula at tproa.net
Sat Apr 21 04:07:16 CEST 2007


Included is a patch that adds two enhancements to the
Heimdal support in rlm_krb5:

 - Logging of the parsed name is changed so that if a
   user is using an instance the instance is logged.
   This threw me off when I was first setting up rlm_krb5,
   since I was using the kula/wireless at TPROA.NET and it
   was logging the parsed name as kula at TPROA.NET.

 - I've switched to using krb5_verify_user_opt and set
   up the options so that you can supply something other
   than the default service principal and can specify
   to use a keytab for verification that isn't the 
   system default keytab. 

This patch has undergone some light testing with radclient,
using all combinations of default/non-default service name
and keytab. It was tested on a NetBSD 3.1 system using
Heimdal 0.72. I suspect more recent versions of Heimdal
would work with this just fine, but have not verified that.

The patch is also located at 
 http://kula.tproa.net/code/rlm_krb5.diff


##### begin patch ######

--- src/modules/rlm_krb5/rlm_krb5.c.orig	2005-12-19 17:21:37.000000000 -0500
+++ src/modules/rlm_krb5/rlm_krb5.c	2007-04-20 21:43:21.000000000 -0400
@@ -323,16 +323,41 @@
 #else /* HEIMDAL_KRB5 */
 
 /* validate user/pass, heimdal krb5 way */
-static int krb5_auth(void *instance, REQUEST *request)
+static int krb5_auth(rlm_krb5_t *instance, REQUEST *request)
 {
 	int r;
-	krb5_error_code ret;
+	krb5_error_code ret, ret2;
 	krb5_ccache id;
 	krb5_principal userP;
 
 	krb5_context context = *((rlm_krb5_t *)instance)->context; /* copy data */
 	const char *user, *pass;
 
+	/* arbitrary 64-byte limit on service names; I've never seen a
+	   service name this long, and hope never to. -srl */
+	/* stolen from the above mit kerb stuff -- kula */
+        
+	char service[64] = "host";
+	char *servername = NULL;
+	char *princ_name;   
+
+	krb5_verify_opt krb_verify_options;
+	krb5_keytab keytab;
+        
+	if (instance->service_princ != NULL) {
+		servername = strchr(instance->service_princ, '/');
+		if (servername != NULL) {
+			*servername = '\0';
+		}
+
+		strncpy(service,instance->service_princ,sizeof(service));
+		service[sizeof(service)-1] = '\0';
+		if (servername != NULL) {
+			*servername = '/';
+			servername++;
+		}
+	}
+	
 	/*
 	 *	We can only authenticate user requests which HAVE
 	 *	a User-Name attribute.
@@ -375,26 +400,71 @@
 	/*
 	 * Heimdal krb5 verification
 	 */
-	radlog(L_AUTH, "rlm_krb5: Parsed name is: %s@%s\n",
-	       *userP->name.name_string.val,
-	       userP->realm);
+	
+
+	/* 
+	 *  The following bit allows us to also log user/instance at REALM if someone
+	 *  logs in using an instance 
+	 */
+
+	ret = krb5_unparse_name(context, userP, &princ_name);
+	if ( ret != 0 ) {
+		radlog(L_AUTH, "rlm_krb5: krb5_unparse_name unparsable name\n");
+	} else {
+		radlog(L_AUTH, "rlm_krb5: Parsed name is: %s\n", princ_name); 
+		free(princ_name);
+	}
 
 	krb5_cc_default(context, &id);
 
-	ret = krb5_verify_user(context,
-			       userP,
-			       id,
-			       pass, 1, "radius");
-
-       if (ret == 0)
-	 return RLM_MODULE_OK;
-
-       radlog(L_AUTH, "rlm_krb5: failed verify_user: %s (%s@%s )",
-	      error_message(ret),
-	      *userP->name.name_string.val,
-	      userP->realm);
+        /* Set up krb5_verify_user options */
+        krb5_verify_opt_init(&krb_verify_options);
+
+        krb5_verify_opt_set_ccache(&krb_verify_options, id);
+ 
+        /*
+	 *  Resolve keytab name. This allows us to use something other than 
+	 *  the default system keytab
+	 */  
+	
+	if (instance->keytab != NULL)
+	{ 
+		ret = krb5_kt_resolve(context, instance->keytab, &keytab);
+		
+		if ( ret )
+		{
+			radlog(L_AUTH, "rlm_krb: unable to resolve keytab %s: %s",
+			       instance->keytab, error_message(ret));
+			krb5_kt_close(context, keytab);
+			return RLM_MODULE_REJECT;
+		} 
+		krb5_verify_opt_set_keytab(&krb_verify_options, keytab);
+	}
+
+	/* Verify aquired credentials against the keytab */
+ 
+	krb5_verify_opt_set_secure(&krb_verify_options, 1);
+	
+	/* Allow us to use an arbitrary service name */
+
+        krb5_verify_opt_set_service(&krb_verify_options, service);
+
+
+	/* Verify the user, using the above set options */
+	ret = krb5_verify_user_opt(context, userP, pass, &krb_verify_options);
+
+	/* We are done with the keytab, close it */
+        ret2 =  krb5_kt_close(context, keytab); 
+
+	if (ret == 0)
+		return RLM_MODULE_OK;
+
+	radlog(L_AUTH, "rlm_krb5: failed verify_user: %s (%s@%s )",
+	       error_message(ret),
+	       *userP->name.name_string.val,
+	       userP->realm);
 
-       return RLM_MODULE_REJECT;
+	return RLM_MODULE_REJECT;
 }
 
 #endif /* HEIMDAL_KRB5 */

##### end patch #####

-- 
Thomas L. Kula | kula at tproa.net 



More information about the Freeradius-Devel mailing list