summaryrefslogtreecommitdiff
path: root/imap/src/osdep/unix/ckp_pam.c
diff options
context:
space:
mode:
Diffstat (limited to 'imap/src/osdep/unix/ckp_pam.c')
-rw-r--r--imap/src/osdep/unix/ckp_pam.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/imap/src/osdep/unix/ckp_pam.c b/imap/src/osdep/unix/ckp_pam.c
new file mode 100644
index 00000000..60c6c1f7
--- /dev/null
+++ b/imap/src/osdep/unix/ckp_pam.c
@@ -0,0 +1,136 @@
+/* ========================================================================
+ * Copyright 1988-2006 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
+ *
+ *
+ * ========================================================================
+ */
+
+/*
+ * Program: Pluggable Authentication Modules login services
+ *
+ * Author: Mark Crispin
+ * Networks and Distributed Computing
+ * Computing & Communications
+ * University of Washington
+ * Administration Building, AG-44
+ * Seattle, WA 98195
+ * Internet: MRC@CAC.Washington.EDU
+ *
+ * Date: 1 August 1988
+ * Last Edited: 31 August 2006
+ */
+
+
+#ifdef MAC_OSX_KLUDGE /* why can't Apple be compatible? */
+#include <pam/pam_appl.h>
+#else
+#include <security/pam_appl.h>
+#endif
+
+struct checkpw_cred {
+ char *uname; /* user name */
+ char *pass; /* password */
+};
+
+/* PAM conversation function
+ * Accepts: number of messages
+ * vector of messages
+ * pointer to response return
+ * application data
+ * Returns: PAM_SUCCESS if OK, response vector filled in, else PAM_CONV_ERR
+ */
+
+static int checkpw_conv (int num_msg,const struct pam_message **msg,
+ struct pam_response **resp,void *appdata_ptr)
+{
+ int i;
+ struct checkpw_cred *cred = (struct checkpw_cred *) appdata_ptr;
+ struct pam_response *reply = fs_get (sizeof (struct pam_response) * num_msg);
+ for (i = 0; i < num_msg; i++) switch (msg[i]->msg_style) {
+ case PAM_PROMPT_ECHO_ON: /* assume want user name */
+ reply[i].resp_retcode = PAM_SUCCESS;
+ reply[i].resp = cpystr (cred->uname);
+ break;
+ case PAM_PROMPT_ECHO_OFF: /* assume want password */
+ reply[i].resp_retcode = PAM_SUCCESS;
+ reply[i].resp = cpystr (cred->pass);
+ break;
+ case PAM_TEXT_INFO:
+ case PAM_ERROR_MSG:
+ reply[i].resp_retcode = PAM_SUCCESS;
+ reply[i].resp = NULL;
+ break;
+ default: /* unknown message style */
+ fs_give ((void **) &reply);
+ return PAM_CONV_ERR;
+ }
+ *resp = reply;
+ return PAM_SUCCESS;
+}
+
+
+/* PAM cleanup
+ * Accepts: handle
+ */
+
+static void checkpw_cleanup (pam_handle_t *hdl)
+{
+#if 0 /* see checkpw() for why this is #if 0 */
+ pam_close_session (hdl,NIL); /* close session [uw]tmp */
+#endif
+ pam_setcred (hdl,PAM_DELETE_CRED);
+ pam_end (hdl,PAM_SUCCESS);
+}
+
+/* Server log in
+ * Accepts: user name string
+ * password string
+ * Returns: T if password validated, NIL otherwise
+ */
+
+struct passwd *checkpw (struct passwd *pw,char *pass,int argc,char *argv[])
+{
+ pam_handle_t *hdl;
+ struct pam_conv conv;
+ struct checkpw_cred cred;
+ char *name = cpystr (pw->pw_name);
+ conv.conv = &checkpw_conv;
+ conv.appdata_ptr = &cred;
+ cred.uname = name;
+ cred.pass = pass;
+ if (pw = ((pam_start ((char *) mail_parameters (NIL,GET_SERVICENAME,NIL),
+ pw->pw_name,&conv,&hdl) == PAM_SUCCESS) &&
+ (pam_set_item (hdl,PAM_RHOST,tcp_clientaddr ()) == PAM_SUCCESS) &&
+ (pam_authenticate (hdl,NIL) == PAM_SUCCESS) &&
+ (pam_acct_mgmt (hdl,NIL) == PAM_SUCCESS) &&
+ (pam_setcred (hdl,PAM_ESTABLISH_CRED) == PAM_SUCCESS)) ?
+ getpwnam (name) : NIL) {
+#if 0
+ /*
+ * Some people have reported that this causes a SEGV in strncpy() from
+ * pam_unix.so.1
+ */
+ /*
+ * This pam_open_session() call is inconsistant with how we handle other
+ * platforms, where we don't write [uw]tmp records. However, unlike our
+ * code on other platforms, pam_acct_mgmt() will check those records for
+ * inactivity and deny the authentication.
+ */
+ pam_open_session (hdl,NIL); /* make sure account doesn't go inactive */
+#endif
+ /* arm hook to delete credentials */
+ mail_parameters (NIL,SET_LOGOUTHOOK,(void *) checkpw_cleanup);
+ mail_parameters (NIL,SET_LOGOUTDATA,(void *) hdl);
+ }
+ else checkpw_cleanup (hdl); /* clean up */
+ fs_give ((void **) &name);
+ /* reset log facility in case PAM broke it */
+ if (myServerName) openlog (myServerName,LOG_PID,syslog_facility);
+ return pw;
+}