[pubcookie-dev] pubcookie PAM verifier

Christos Ricudis pubcookie at komodino.itc.auth.gr
Thu Jun 9 07:10:24 PDT 2005


Dear pubcookie developers,

I have developed a first prototype for a PAM verifier module for
pubcookie. The verifier checks a user against a PAM stack,
and can be used to seamlessly plug PAM authentication backends to
pubcookie.

I send you a patch against pubcookie-3.2.1-beta1. Please consider it as
a contribution to pubcookie project.

The module is a first working prototype. Some work is needed to polish it.

I'm not sure I patched right the autoconf files, it's the first time I
use autoconf. You need to run autoconf after patching, to generate a new
configure file.

Code compiles without warnings on my Debian Linux system, I'm not sure
about Solaris/HP/other PAM implementations.

Other things that need fixing (look at verify_pam.c comments) :

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

The PAM verifier ALWAYS assumes that the pam module asks for the user's
password in its first conversation message, and replies ALL other 
conversation messages with a space. It is NOT precisely obvious how to 
fix this. Perhaps the pam conversation message_id which should be 
responsed with the user's password should be a configuration option.

PAM conversation response buffer should NOT be statically sized to 1024
bytes

Also, the PAM service name should be a configurable option.

We should NOT make a copy of pool pointer in a static variable, we 
should instead pass this together with the password in a struct to 
appdata_ptr.

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

-------------- next part --------------
diff -ruN pubcookie-3.2.1-beta1/configure.ac pubcookie-3.2.1-beta1-PAM/configure.ac
--- pubcookie-3.2.1-beta1/configure.ac	2005-05-14 01:08:47.000000000 +0300
+++ pubcookie-3.2.1-beta1-PAM/configure.ac	2005-06-09 16:17:15.000000000 +0300
@@ -740,6 +740,19 @@
     AC_CHECK_LIB(crypt, crypt)
 fi
 
+AC_ARG_ENABLE(pam,
+    AC_HELP_STRING([--enable-pam],[Enable PAM Verifier ]),
+[ case "${enableval}" in
+   yes)
+    AC_DEFINE(ENABLE_PAM, 1, [Define to 1 to support PAM verifiers])
+    ;;
+  esac ])
+
+if test "$enable_pam" = "yes"; then
+    AC_CHECK_HEADERS([security/pam_appl.h])
+    AC_CHECK_LIB(pam, pam_start)
+fi
+
 AC_ARG_ENABLE(uwsecurid,
     AC_HELP_STRING([--enable-uwsecurid],[Enable U. Wash. SecurID Verifier ]),
 [ case "${enableval}" in
@@ -830,6 +843,11 @@
     AC_CHECK_LIB(crypt, crypt)
 fi
 
+if test "$enable_pam" = "yes"; then
+    AC_CHECK_HEADERS([security/pam_appl.h])
+    AC_CHECK_LIB(pam, pam_start)
+fi
+
 # See if we are to enable the unsafe relay
 AC_ARG_ENABLE(unsafe-relay,
     AC_HELP_STRING([--enable-unsafe-relay],[Enable unsafe relay. (Compatibility)]),
diff -ruN pubcookie-3.2.1-beta1/Makefile.in pubcookie-3.2.1-beta1-PAM/Makefile.in
--- pubcookie-3.2.1-beta1/Makefile.in	2005-05-14 01:08:47.000000000 +0300
+++ pubcookie-3.2.1-beta1-PAM/Makefile.in	2005-06-09 14:40:48.000000000 +0300
@@ -95,6 +95,7 @@
 		  $(builddir)/src/verify_kerberos4.o \
 		  $(builddir)/src/verify_kerberos5.o \
 		  $(builddir)/src/verify_shadow.o \
+		  $(builddir)/src/verify_pam.o \
 		  $(builddir)/src/verify_uwsecurid.o \
 		  $(builddir)/src/verify_ldap.o \
 		  @SNPRINTF_0@ \
diff -ruN pubcookie-3.2.1-beta1/src/config.h.in pubcookie-3.2.1-beta1-PAM/src/config.h.in
--- pubcookie-3.2.1-beta1/src/config.h.in	2005-05-14 01:08:47.000000000 +0300
+++ pubcookie-3.2.1-beta1-PAM/src/config.h.in	2005-06-09 16:20:51.000000000 +0300
@@ -1,4 +1,4 @@
-/* src/config.h.in.  Generated from ./configure.ac by autoheader.  */
+/* src/config.h.in.  Generated from configure.ac by autoheader.  */
 
 /* Define to 1 to enable dmalloc debugging */
 #undef ENABLE_DMALLOC
@@ -9,6 +9,9 @@
 /* Define to 1 to support LDAP verifiers */
 #undef ENABLE_LDAP
 
+/* Define to 1 to support PAM verifiers */
+#undef ENABLE_PAM
+
 /* Define to 1 to support shadow verifiers */
 #undef ENABLE_SHADOW
 
@@ -135,6 +138,9 @@
 /* Define to 1 if you have the `nss3' library (-lnss3). */
 #undef HAVE_LIBNSS3
 
+/* Define to 1 if you have the `pam' library (-lpam). */
+#undef HAVE_LIBPAM
+
 /* Define to 1 if you have the `prldap50' library (-lprldap50). */
 #undef HAVE_LIBPRLDAP50
 
@@ -201,6 +207,9 @@
 /* Define to 1 if you have the <rand.h> header file. */
 #undef HAVE_RAND_H
 
+/* Define to 1 if you have the <security/pam_appl.h> header file. */
+#undef HAVE_SECURITY_PAM_APPL_H
+
 /* Define to 1 if you have the <shadow.h> header file. */
 #undef HAVE_SHADOW_H
 
diff -ruN pubcookie-3.2.1-beta1/src/verify.c pubcookie-3.2.1-beta1-PAM/src/verify.c
--- pubcookie-3.2.1-beta1/src/verify.c	2005-05-14 01:08:47.000000000 +0300
+++ pubcookie-3.2.1-beta1-PAM/src/verify.c	2005-06-09 14:45:29.000000000 +0300
@@ -58,6 +58,7 @@
 extern verifier shadow_verifier;
 extern verifier fork_verifier;
 extern verifier uwsecurid_verifier;
+extern verifier pam_verifier;
 
 /* verifiers that we actually compiled */
 static verifier *verifiers[] = {
@@ -68,6 +69,7 @@
     &shadow_verifier,
     &fork_verifier,
     &uwsecurid_verifier,
+    &pam_verifier,
     NULL
 };
 
diff -ruN pubcookie-3.2.1-beta1/src/verify_pam.c pubcookie-3.2.1-beta1-PAM/src/verify_pam.c
--- pubcookie-3.2.1-beta1/src/verify_pam.c	1970-01-01 02:00:00.000000000 +0200
+++ pubcookie-3.2.1-beta1-PAM/src/verify_pam.c	2005-06-09 16:10:37.000000000 +0300
@@ -0,0 +1,190 @@
+/* ========================================================================
+ * Copyright 2005 University of Washington
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================================
+ */
+
+/** @file verify_pam.c
+ * PAM verifier
+ * 
+ * written by Christos Ricudis <ricudis at itc.auth.gr> 9 Jun 2005 
+ * 
+ * Checks user against a PAM stack. Must pass auth and accounting PAM stacks. 
+ * Based on PAM check_user by Shane Watts <shane at icarus.bofh.asn.au> with
+ * slight modifications by AGM.
+ *
+ * You need to add the following (or equivalent) to the /etc/pam.conf file.
+ * # check authorization
+ * pubcookie   auth       required     pam_unix_auth.so
+ * pubcookie   account    required     pam_unix_acct.so
+ *
+ *
+ * KNOWN PROBLEMS : it ALWAYS assumes that the pam module asks for password 
+ * in its first conversation message, and replies ALL other conversation messages
+ * with a space. It is NOT precisely obvious how to fix this. Perhaps the 
+ * pam conversation message_id which should be responsed with the user's 
+ * password should be a configuration option. 
+ *
+ * PAM conversation response buffer should NOT be statically sized to 1024 bytes
+ *  
+ * Also, the PAM service name should be a configurable option.  
+ *
+ * We should NOT make a copy of pool pointer in a static variable, we should
+ * instead pass this together with the password in a struct to appdata_ptr. 
+ *  
+ *    @return 0 on success, -1 if user/pass doesn't match, -2 on system error
+ *  
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+# include "pbc_path.h"
+#endif
+
+typedef void pool;
+
+/* login cgi includes */
+#include "index.cgi.h"
+#include "verify.h"
+#include "pbc_config.h"
+#include "pbc_configure.h"
+#include "pbc_myconfig.h"
+#include "pbc_logging.h"
+#include "snprintf.h"
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
+#endif /* HAVE_STDIO_H */
+
+#include "verify.h"
+
+#ifdef ENABLE_PAM
+
+#include <security/pam_appl.h>
+
+static struct pam_conv conv;
+static pool *poolcopy;
+
+int pubcookie_pam_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) 
+{
+  int i;
+  struct pam_response *pammy;
+  for (i=0;i<num_msg;i++) { 
+    pbc_log_activity (poolcopy, PBC_LOG_DEBUG_VERBOSE, "pubcookie_pam_conv : pam_message->msg[%d]='%s' (msg_style %d)",i,msg[i]->msg,msg[i]->msg_style);
+    pammy=malloc(sizeof(struct pam_response));
+    pammy->resp_retcode=0;
+    if (i==0) {
+      pbc_log_activity (poolcopy, PBC_LOG_DEBUG_VERBOSE, "pubcookie_pam_conv : pam_message->msg[] index is 0, we ASSUME this is the password prompt and respond with user password");
+      pammy->resp=malloc(1024);
+      strncpy(pammy->resp,appdata_ptr,1023);
+    } else { 
+      pammy->resp=malloc(2);
+      strncpy(pammy->resp," ",2);
+      pbc_log_activity (poolcopy, PBC_LOG_DEBUG_VERBOSE, "pubcookie_pam_conv : pam_message->msg[] index is not 0, we respond with a dummy response");
+    }
+    resp[i]=pammy;
+  }
+  return(PAM_SUCCESS);
+}
+
+
+static int pam_v (pool * p, const char *userid,
+                     const char *passwd,
+                     const char *service,
+                     const char *user_realm,
+                     struct credentials **creds, const char **errstr)
+{
+
+//	FIX THIS
+    poolcopy=p;
+
+    pam_handle_t *pamh=NULL;
+    int retval;
+
+    if (errstr)
+        *errstr = NULL;
+    if (creds)
+        *creds = NULL;
+
+    if (!userid) {
+        *errstr = "no userid to verify";
+        return -1;
+    }
+
+    if (!passwd) {
+        *errstr = "no password to verify";
+        return -1;
+    }
+    
+    conv.conv=&pubcookie_pam_conv;
+    conv.appdata_ptr=(void *)passwd;
+    retval = pam_start("pubcookie", userid, &conv, &pamh);
+    pbc_log_activity (p, PBC_LOG_DEBUG_VERBOSE, "verify_pam : pam_start return value : %d",retval);
+    
+	
+    if (retval == PAM_SUCCESS)
+        retval = pam_authenticate(pamh, 0);    /* is user really user? */
+
+    pbc_log_activity (p, PBC_LOG_DEBUG_VERBOSE, "verify_pam : pam_authenticate return value : %d",retval);
+
+    if (retval == PAM_SUCCESS)
+        retval = pam_acct_mgmt(pamh, 0);       /* permitted access? */
+        
+    pbc_log_activity (p, PBC_LOG_DEBUG_VERBOSE, "verify_pam : pam_acct_mgmt return value : %d",retval);
+
+    /* This is where we have been authorized or not. */
+
+    if (retval == PAM_SUCCESS) {
+      pbc_log_activity (p, PBC_LOG_DEBUG_VERBOSE, "verify_pam : return value from PAM stack : PAM_SUCCESS, return SUCCESS to verifier");
+      retval=0;
+    } else {
+      pbc_log_activity (p, PBC_LOG_DEBUG_VERBOSE, "verify_pam : return value from PAM stack : %d, return FAILURE to verifier",retval);
+      *errstr="Authentication Failed";
+      retval=-1;
+    }
+      
+    if (pam_end(pamh,retval) != PAM_SUCCESS) {     /* close Linux-PAM */
+	pamh = NULL;
+
+        pbc_log_activity (p, PBC_LOG_ERROR, "verify_pam : PAM error : Failed to release authenticator");
+
+        *errstr="Authentication Failed";
+
+	retval=-2;
+    }
+    
+    return(retval);
+}
+
+#else /* ENABLE_PAM */
+static int pam_v (pool * p, const char *userid,
+                   const char *passwd,
+                   const char *service,
+                   const char *user_realm,
+                   struct credentials **creds, const char **errstr)
+{
+    if (creds)
+        *creds = NULL;
+
+    *errstr = "PAM not implemented";
+    return -1;
+}
+#endif
+
+verifier pam_verifier = { "pam", &pam_v, NULL, NULL };



More information about the pubcookie-dev mailing list