[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