[Date Prev] [Date Index] [Date Next] [Thread Prev] [Thread Index] [Thread Next]

Re: Kerberos authentication?

Andras.Horvath Andras.Horvath@cern.ch
Fri, 18 Sep 2009 12:47:26 GMT


On Thu, Sep 17, 2009 at 03:03:04PM +0200, Andras.Horvath@cern.ch wrote:
> 
> Note: authentication info has to be in username@REALM.DOMAIN format
> instead of just 'username' for krb5 to work.  This prevents users from
> falling back to password authentication if they don't have a token (PAM 
> will come back with 'username' only). :-/ Perhaps a default realm could
> be supplied somehow? I'm no gssapi expert :-/

Ahm, well, attached is a hack that, if logging in with a given username
fails, retries login with any '@REALM' parts stripped off.
(The whole patch only makes sense together with Nate's GSSAPI patch.)

This serves me right for Kerberos and should be backwards compatible
unless you use both 'bozouser' and 'bozouser@bozo.com' as usernames and
they're two different people.

Disclaimer: I'm not an experienced C programmer -- please feel free to
criticize and/or fix.

Andras
diff --git a/conserver/group.c b/conserver/group.c
index ea6bd76..86e87a0 100644
--- a/conserver/group.c
+++ b/conserver/group.c
@@ -77,6 +77,11 @@
 #include <security/pam_appl.h>
 #endif
 
+# if HAVE_GSSAPI
+#include <stdio.h>
+#include <stdlib.h>
+#endif
+
 
 /* flags that a signal has occurred */
 static sig_atomic_t fSawChldHUP = 0, fSawReUp = 0, fSawGoAway =
@@ -519,10 +524,47 @@ ClientAccess(pCE, user)
     char *user;
 #endif
 {
-    if (ConsentUserOk(pCE->rw, user) == 1)
-	return 0;
-    if (ConsentUserOk(pCE->ro, user) == 1)
-	return 1;
+#if HAVE_GSSAPI
+	/* this will be 'user@REALM' stripped of '@REALM', if any */
+	char *shortname;
+#endif
+    if (ConsentUserOk(pCE->rw, user) == 1) {
+		return 0;
+	}
+    if (ConsentUserOk(pCE->ro, user) == 1) {
+		return 1;
+	}
+#if HAVE_GSSAPI
+	/* try the username without @REALM against the ACL
+	 * this allows for falling back to PAM from kerberos5/gssapi
+	 * as the latter uses 'user@REALM' and the former only 'user'
+	 */
+	CONDDEBUG((1, "Authenticating user %s",user ));
+	/* %m is defined in glibc 2.7 and onwards, and %a stops working there */
+#if defined GLIBC_2_7
+	if (1==sscanf(user,"%m[^@]",&shortname)) {
+#else
+	if (1==sscanf(user,"%a[^@]",&shortname)) {
+#endif
+		CONDDEBUG((1, "Shortname computed from %s is %s", user, shortname));
+		if (ConsentUserOk(pCE->rw, shortname) == 1) {
+			CONDDEBUG(("User %s logged in rw, using shortname %s",user,shortname));
+			free(shortname);
+			return 0;
+		}
+		if (ConsentUserOk(pCE->ro, shortname) == 1) {
+			CONDDEBUG(("User %s logged in ro, using shortname %s",user,shortname));
+			free(shortname);
+			return 1;
+			}
+		free(shortname);
+	} else if (errno != 0) {
+		Msg( "ClientAccess(): sscanf on %s failed, errno %d",user,errno );
+	} else {
+		CONDDEBUG((1, "Sscanf on %s failed, no match for `@' for shortname",user ));
+	}
+#endif
+	CONDDEBUG((1, "Login OK but permission denied for %s", user));
     return -1;
 }