summaryrefslogtreecommitdiff
path: root/contrib/libpam/modules/pam_mail/pam_mail.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libpam/modules/pam_mail/pam_mail.c')
-rw-r--r--contrib/libpam/modules/pam_mail/pam_mail.c246
1 files changed, 172 insertions, 74 deletions
diff --git a/contrib/libpam/modules/pam_mail/pam_mail.c b/contrib/libpam/modules/pam_mail/pam_mail.c
index 15160f3d52083..df00315ab3049 100644
--- a/contrib/libpam/modules/pam_mail/pam_mail.c
+++ b/contrib/libpam/modules/pam_mail/pam_mail.c
@@ -1,29 +1,14 @@
/* pam_mail module */
/*
- * $Id: pam_mail.c,v 1.2 1997/02/15 16:06:14 morgan Exp morgan $
+ * $Id: pam_mail.c,v 1.3 2000/12/04 20:59:13 baggins Exp $
*
- * Written by Andrew Morgan <morgan@parc.power.net> 1996/3/11
+ * Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11
* $HOME additions by David Kinchlea <kinch@kinch.ark.com> 1997/1/7
- *
- * $Log: pam_mail.c,v $
- * Revision 1.2 1997/02/15 16:06:14 morgan
- * session -> setcred, also added "~"=$HOME
- *
- * Revision 1.1 1997/01/04 20:33:02 morgan
- * Initial revision
+ * mailhash additions by Chris Adams <cadams@ro.com> 1998/7/11
*/
-#define DEFAULT_MAIL_DIRECTORY "/var/spool/mail"
-#define MAIL_FILE_FORMAT "%s/%s"
-#define MAIL_ENV_NAME "MAIL"
-#define MAIL_ENV_FORMAT MAIL_ENV_NAME "=%s"
-#define YOUR_MAIL_FORMAT "You have %s mail in %s"
-
-#ifdef linux
-# define _GNU_SOURCE
-# include <features.h>
-#endif
+#include <security/_pam_aconf.h>
#include <ctype.h>
#include <pwd.h>
@@ -35,11 +20,20 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+#include <dirent.h>
#ifdef WANT_PWDB
#include <pwdb/pwdb_public.h>
#endif
+#define DEFAULT_MAIL_DIRECTORY PAM_PATH_MAILDIR
+#define MAIL_FILE_FORMAT "%s%s/%s"
+#define MAIL_ENV_NAME "MAIL"
+#define MAIL_ENV_FORMAT MAIL_ENV_NAME "=%s"
+#define YOUR_MAIL_VERBOSE_FORMAT "You have %s mail in %s."
+#define YOUR_MAIL_STANDARD_FORMAT "You have %smail."
+#define NO_MAIL_STANDARD_FORMAT "No mail."
+
/*
* here, we make a definition for the externally accessible function
* in this file (this definition is required for static a module
@@ -47,6 +41,7 @@
* modules include file to define the function prototypes.
*/
+#define PAM_SM_SESSION
#define PAM_SM_AUTH
#include <security/pam_modules.h>
@@ -67,16 +62,19 @@ static void _log_err(int err, const char *format, ...)
/* argument parsing */
-#define PAM_DEBUG_ARG 01
-#define PAM_NO_LOGIN 02
-#define PAM_LOGOUT_TOO 04
-#define PAM_NEW_MAIL_DIR 010
-#define PAM_MAIL_SILENT 020
-#define PAM_NO_ENV 040
-#define PAM_HOME_MAIL 0100
-#define PAM_EMPTY_TOO 0200
-
-static int _pam_parse(int flags, int argc, const char **argv, char **maildir)
+#define PAM_DEBUG_ARG 0x0001
+#define PAM_NO_LOGIN 0x0002
+#define PAM_LOGOUT_TOO 0x0004
+#define PAM_NEW_MAIL_DIR 0x0010
+#define PAM_MAIL_SILENT 0x0020
+#define PAM_NO_ENV 0x0040
+#define PAM_HOME_MAIL 0x0100
+#define PAM_EMPTY_TOO 0x0200
+#define PAM_STANDARD_MAIL 0x0400
+#define PAM_QUIET_MAIL 0x1000
+
+static int _pam_parse(int flags, int argc, const char **argv, char **maildir,
+ int *hashcount)
{
int ctrl=0;
@@ -84,6 +82,8 @@ static int _pam_parse(int flags, int argc, const char **argv, char **maildir)
ctrl |= PAM_MAIL_SILENT;
}
+ *hashcount = 0;
+
/* step through arguments */
for (; argc-- > 0; ++argv) {
@@ -91,6 +91,10 @@ static int _pam_parse(int flags, int argc, const char **argv, char **maildir)
if (!strcmp(*argv,"debug"))
ctrl |= PAM_DEBUG_ARG;
+ else if (!strcmp(*argv,"quiet"))
+ ctrl |= PAM_QUIET_MAIL;
+ else if (!strcmp(*argv,"standard"))
+ ctrl |= PAM_STANDARD_MAIL | PAM_EMPTY_TOO;
else if (!strncmp(*argv,"dir=",4)) {
*maildir = x_strdup(4+*argv);
if (*maildir != NULL) {
@@ -100,6 +104,12 @@ static int _pam_parse(int flags, int argc, const char **argv, char **maildir)
_log_err(LOG_CRIT,
"failed to duplicate mail directory - ignored");
}
+ } else if (!strncmp(*argv,"hash=",5)) {
+ char *ep = NULL;
+ *hashcount = strtol(*argv+5,&ep,10);
+ if (!ep || (*hashcount < 0)) {
+ *hashcount = 0;
+ }
} else if (!strcmp(*argv,"close")) {
ctrl |= PAM_LOGOUT_TOO;
} else if (!strcmp(*argv,"nopen")) {
@@ -113,6 +123,11 @@ static int _pam_parse(int flags, int argc, const char **argv, char **maildir)
}
}
+ if ((*hashcount != 0) && !(ctrl & PAM_NEW_MAIL_DIR)) {
+ *maildir = x_strdup(DEFAULT_MAIL_DIRECTORY);
+ ctrl |= PAM_NEW_MAIL_DIR;
+ }
+
return ctrl;
}
@@ -150,8 +165,8 @@ static int converse(pam_handle_t *pamh, int ctrl, int nargs
return retval; /* propagate error status */
}
-static int get_folder(pam_handle_t *pamh, int ctrl
- , char **path_mail, char **folder_p)
+static int get_folder(pam_handle_t *pamh, int ctrl,
+ char **path_mail, char **folder_p, int hashcount)
{
int retval;
const char *user, *path;
@@ -184,6 +199,9 @@ static int get_folder(pam_handle_t *pamh, int ctrl
return PAM_ABORT;
}
ctrl |= PAM_HOME_MAIL;
+ if (hashcount != 0) {
+ _log_err(LOG_ALERT, "can't do hash= and home directory mail");
+ }
}
} else {
path = DEFAULT_MAIL_DIRECTORY;
@@ -195,14 +213,29 @@ static int get_folder(pam_handle_t *pamh, int ctrl
folder = malloc(sizeof(MAIL_FILE_FORMAT)
+strlen(pwd->pw_dir)+strlen(path));
} else {
- folder = malloc(sizeof(MAIL_FILE_FORMAT)+strlen(path)+strlen(user));
+ folder = malloc(sizeof(MAIL_FILE_FORMAT)+strlen(path)+strlen(user)
+ +2*hashcount);
}
if (folder != NULL) {
if (ctrl & PAM_HOME_MAIL) {
- sprintf(folder, MAIL_FILE_FORMAT, pwd->pw_dir, path);
+ sprintf(folder, MAIL_FILE_FORMAT, pwd->pw_dir, "", path);
} else {
- sprintf(folder, MAIL_FILE_FORMAT, path, user);
+ int i;
+ char *hash = malloc(2*hashcount+1);
+
+ if (hash) {
+ for (i = 0; i < hashcount; i++) {
+ hash[2*i] = '/';
+ hash[2*i+1] = user[i];
+ }
+ hash[2*i] = '\0';
+ sprintf(folder, MAIL_FILE_FORMAT, path, hash, user);
+ _pam_overwrite(hash);
+ _pam_drop(hash);
+ } else {
+ sprintf(folder, "error");
+ }
}
D(("folder =[%s]", folder));
}
@@ -226,17 +259,52 @@ static int get_folder(pam_handle_t *pamh, int ctrl
static const char *get_mail_status(int ctrl, const char *folder)
{
- const char *type;
+ const char *type = NULL;
+ static char dir[256];
struct stat mail_st;
-
- if (stat(folder, &mail_st) == 0 && mail_st.st_size > 0) {
- type = (mail_st.st_atime < mail_st.st_mtime) ? "new":"old" ;
- } else if (ctrl & PAM_EMPTY_TOO) {
- type = "no";
- } else {
- type = NULL;
+ struct dirent **namelist;
+ int i;
+
+ if (stat(folder, &mail_st) == 0) {
+ if (S_ISDIR(mail_st.st_mode)) { /* Assume Maildir format */
+ sprintf(dir, "%.250s/new", folder);
+ i = scandir(dir, &namelist, 0, alphasort);
+ if (i > 2) {
+ type = "new";
+ while (--i)
+ free(namelist[i]);
+ } else {
+ while (--i >= 0)
+ free(namelist[i]);
+ sprintf(dir, "%.250s/cur", folder);
+ i = scandir(dir, &namelist, 0, alphasort);
+ if (i > 2) {
+ type = "old";
+ while (--i)
+ free(namelist[i]);
+ } else if (ctrl & PAM_EMPTY_TOO) {
+ while (--i >= 0)
+ free(namelist[i]);
+ type = "no";
+ } else {
+ type = NULL;
+ }
+ }
+ } else {
+ if (mail_st.st_size > 0) {
+ if (mail_st.st_atime < mail_st.st_mtime) /* new */
+ type = (ctrl & PAM_STANDARD_MAIL) ? "new " : "new";
+ else /* old */
+ type = (ctrl & PAM_STANDARD_MAIL) ? "" : "old";
+ } else if (ctrl & PAM_EMPTY_TOO) {
+ type = "no";
+ } else {
+ type = NULL;
+ }
+ }
}
+ memset(dir, 0, 256);
memset(&mail_st, 0, sizeof(mail_st));
D(("user has %s mail in %s folder", type, folder));
return type;
@@ -247,17 +315,29 @@ static int report_mail(pam_handle_t *pamh, int ctrl
{
int retval;
- if (!(ctrl & PAM_MAIL_SILENT)) {
+ if (!(ctrl & PAM_MAIL_SILENT) || ((ctrl & PAM_QUIET_MAIL) && strcmp(type, "new"))) {
char *remark;
- remark = malloc(sizeof(YOUR_MAIL_FORMAT)+strlen(type)+strlen(folder));
+ if (ctrl & PAM_STANDARD_MAIL)
+ if (!strcmp(type, "no"))
+ remark = malloc(strlen(NO_MAIL_STANDARD_FORMAT)+1);
+ else
+ remark = malloc(strlen(YOUR_MAIL_STANDARD_FORMAT)+strlen(type)+1);
+ else
+ remark = malloc(strlen(YOUR_MAIL_VERBOSE_FORMAT)+strlen(type)+strlen(folder)+1);
if (remark == NULL) {
retval = PAM_BUF_ERR;
} else {
struct pam_message msg[1], *mesg[1];
struct pam_response *resp=NULL;
- sprintf(remark, YOUR_MAIL_FORMAT, type, folder);
+ if (ctrl & PAM_STANDARD_MAIL)
+ if (!strcmp(type, "no"))
+ sprintf(remark, NO_MAIL_STANDARD_FORMAT);
+ else
+ sprintf(remark, YOUR_MAIL_STANDARD_FORMAT, type);
+ else
+ sprintf(remark, YOUR_MAIL_VERBOSE_FORMAT, type, folder);
mesg[0] = &msg[0];
msg[0].msg_style = PAM_TEXT_INFO;
@@ -279,28 +359,51 @@ static int report_mail(pam_handle_t *pamh, int ctrl
return retval;
}
-/* --- authentication management functions (only) --- */
+static int _do_mail(pam_handle_t *, int, int, const char **, int);
-/*
- * Cannot use mail to authenticate yourself
- */
+/* --- authentication functions --- */
PAM_EXTERN
-int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
- ,const char **argv)
+int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc,
+ const char **argv)
{
return PAM_IGNORE;
}
-/*
- * MAIL is a "credential"
- */
+/* Checking mail as part of authentication */
+PAM_EXTERN
+int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc,
+ const char **argv)
+{
+ if (!(flags & (PAM_ESTABLISH_CRED|PAM_DELETE_CRED)))
+ return PAM_IGNORE;
+ return _do_mail(pamh,flags,argc,argv,(flags & PAM_ESTABLISH_CRED));
+}
+
+/* --- session management functions --- */
+
+PAM_EXTERN
+int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc
+ ,const char **argv)
+{
+ return _do_mail(pamh,flags,argc,argv,0);;
+}
+/* Checking mail as part of the session management */
PAM_EXTERN
-int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc
- , const char **argv)
+int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc,
+ const char **argv)
{
- int retval, ctrl;
+ return _do_mail(pamh,flags,argc,argv,1);
+}
+
+
+/* --- The Beaf (Tm) --- */
+
+static int _do_mail(pam_handle_t *pamh, int flags, int argc,
+ const char **argv, int est)
+{
+ int retval, ctrl, hashcount;
char *path_mail=NULL, *folder;
const char *type;
@@ -309,17 +412,16 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc
* the user has any new mail.
*/
- ctrl = _pam_parse(flags, argc, argv, &path_mail);
+ ctrl = _pam_parse(flags, argc, argv, &path_mail, &hashcount);
/* Do we have anything to do? */
- if (!(flags & (PAM_ESTABLISH_CRED|PAM_DELETE_CRED))) {
+ if (flags & PAM_SILENT)
return PAM_SUCCESS;
- }
/* which folder? */
- retval = get_folder(pamh, ctrl, &path_mail, &folder);
+ retval = get_folder(pamh, ctrl, &path_mail, &folder, hashcount);
if (retval != PAM_SUCCESS) {
D(("failed to find folder"));
return retval;
@@ -327,7 +429,7 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc
/* set the MAIL variable? */
- if (!(ctrl & PAM_NO_ENV) && (flags & PAM_ESTABLISH_CRED)) {
+ if (!(ctrl & PAM_NO_ENV) && est) {
char *tmp;
tmp = malloc(strlen(folder)+sizeof(MAIL_ENV_FORMAT));
@@ -357,24 +459,20 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc
* OK. we've got the mail folder... what about its status?
*/
- if (((flags & PAM_ESTABLISH_CRED) && !(ctrl & PAM_NO_LOGIN))
- || ((flags & PAM_DELETE_CRED) && (ctrl & PAM_LOGOUT_TOO))) {
+ if ((est && !(ctrl & PAM_NO_LOGIN))
+ || (!est && (ctrl & PAM_LOGOUT_TOO))) {
type = get_mail_status(ctrl, folder);
if (type != NULL) {
retval = report_mail(pamh, ctrl, type, folder);
type = NULL;
}
}
-
- /*
- * Delete environment variable?
- */
-
- if (flags & PAM_DELETE_CRED) {
+
+ /* Delete environment variable? */
+ if (!est)
(void) pam_putenv(pamh, MAIL_ENV_NAME);
- }
- _pam_overwrite(folder); /* clean up */
+ _pam_overwrite(folder); /* clean up */
_pam_drop(folder);
/* indicate success or failure */
@@ -391,8 +489,8 @@ struct pam_module _pam_mail_modstruct = {
pam_sm_authenticate,
pam_sm_setcred,
NULL,
- NULL,
- NULL,
+ pam_sm_open_session,
+ pam_sm_close_session,
NULL,
};