Commit 33737423 3373742327451a83f03946e47d0dd512295303f0 by Sergey Poznyakoff

Switched to the new authentication/authorization functions.

1 parent 257c5cda
......@@ -585,27 +585,19 @@ change_user (const char *user)
char *
mailbox_path (const char *user)
{
struct passwd *pw;
struct mu_auth_data *auth;
char *mailbox_name;
pw = mu_getpwnam (user);
if (!pw)
auth = mu_get_auth_by_name (user);
if (!auth)
{
syslog (LOG_ALERT, "user nonexistent: %s", user);
return NULL;
}
if (!mu_virtual_domain)
{
mailbox_name = calloc (strlen (mu_path_maildir) + 1 +
strlen (pw->pw_name) + 1, 1);
sprintf (mailbox_name, "%s%s", mu_path_maildir, pw->pw_name);
}
else
{
mailbox_name = calloc (strlen (pw->pw_dir) + strlen ("/INBOX"), 1);
sprintf (mailbox_name, "%s/INBOX", pw->pw_dir);
}
mailbox_name = strdup (auth->mailbox);
mu_auth_data_free (auth);
return mailbox_name;
}
......
......@@ -65,7 +65,7 @@
(define (sieve-expand-filename filename)
(case (string-ref filename 0)
((#\~)
(let ((pw (mu_getpwuid (geteuid))))
(let ((pw (mu-getpwuid (geteuid))))
(if (and (vector? pw)
(let ((dir (vector-ref pw 5)))
(and
......
......@@ -29,7 +29,7 @@ struct imap_auth {
{ NULL, NULL }
};
int
void
imap4d_auth_capability ()
{
struct imap_auth *ap;
......@@ -59,18 +59,18 @@ imap4d_authenticate (struct imap4d_command *command, char *arg)
if (username)
{
struct passwd *pw = mu_getpwnam (username);
if (pw == NULL)
auth_data = mu_get_auth_by_name (username);
if (auth_data == NULL)
return util_finish (command, RESP_NO,
"User name or passwd rejected");
if (pw->pw_uid > 0 && !mu_virtual_domain)
setuid (pw->pw_uid);
if (auth_data->change_uid)
setuid (auth_data->uid);
homedir = mu_normalize_path (strdup (pw->pw_dir), "/");
homedir = mu_normalize_path (strdup (auth_data->dir), "/");
/* FIXME: Check for errors. */
chdir (homedir);
namespace_init(pw->pw_dir);
namespace_init (homedir);
syslog (LOG_INFO, "User '%s' logged in", username);
return 0;
}
......
......@@ -27,10 +27,7 @@ imap4d_bye (int reason)
int
imap4d_bye0 (int reason, struct imap4d_command *command)
{
struct passwd *pw = mu_getpwuid (getuid ());
const char *username;
int status = EXIT_FAILURE;
username = (pw) ? pw->pw_name : "Unknown";
if (mbox)
{
......@@ -57,7 +54,7 @@ imap4d_bye0 (int reason, struct imap4d_command *command)
if (state == STATE_NONAUTH)
syslog (LOG_INFO, "Session timed out for no user");
else
syslog (LOG_INFO, "Session timed out for user: %s", username);
syslog (LOG_INFO, "Session timed out for user: %s", auth_data->name);
break;
case ERR_NO_OFILE:
......@@ -69,7 +66,7 @@ imap4d_bye0 (int reason, struct imap4d_command *command)
if (state == STATE_NONAUTH)
syslog (LOG_INFO, "Session terminating");
else
syslog (LOG_INFO, "Session terminating for user: %s", username);
syslog (LOG_INFO, "Session terminating for user: %s", auth_data->name);
status = EXIT_SUCCESS;
break;
......
......@@ -16,9 +16,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "imap4d.h"
#ifdef HAVE_MYSQL
# include "../MySql/MySql.h"
#endif
FILE *ifile;
FILE *ofile;
......@@ -26,6 +23,7 @@ mailbox_t mbox;
char *homedir;
int state = STATE_NONAUTH;
int debug_mode = 0;
struct mu_auth_data *auth_data;
struct daemon_param daemon_param = {
MODE_INTERACTIVE, /* Start in interactive (inetd) mode */
......@@ -107,6 +105,7 @@ main (int argc, char **argv)
state = STATE_NONAUTH; /* Starting state in non-auth. */
MU_AUTH_REGISTER_ALL_MODULES();
mu_argp_parse (&argp, &argc, &argv, 0, imap4d_capa, NULL, &daemon_param);
#ifdef USE_LIBPAM
......@@ -145,14 +144,6 @@ main (int argc, char **argv)
list_append (bookie, path_record);
}
#ifdef HAVE_MYSQL
mu_register_getpwnam (getMpwnam);
mu_register_getpwuid (getMpwuid);
#endif
#ifdef USE_VIRTUAL_DOMAINS
mu_register_getpwnam (getpwnam_virtual);
#endif
/* Set the signal handlers. */
signal (SIGINT, imap4d_signal);
signal (SIGQUIT, imap4d_signal);
......
......@@ -17,73 +17,11 @@
#include "imap4d.h"
#ifdef HAVE_MYSQL
#include "../MySql/MySql.h"
#endif
#ifdef USE_LIBPAM
#define COPY_STRING(s) (s) ? strdup(s) : NULL
static char *_pwd;
static char *_user;
static int _perr = 0;
static int
PAM_gnuimap4d_conv (int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
int replies = 0;
struct pam_response *reply = NULL;
reply = malloc (sizeof (*reply) * num_msg);
if (!reply)
return PAM_CONV_ERR;
for (replies = 0; replies < num_msg; replies++)
{
switch (msg[replies]->msg_style)
{
case PAM_PROMPT_ECHO_ON:
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = COPY_STRING (_user);
/* PAM frees resp */
break;
case PAM_PROMPT_ECHO_OFF:
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = COPY_STRING (_pwd);
/* PAM frees resp */
break;
case PAM_TEXT_INFO:
case PAM_ERROR_MSG:
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = NULL;
break;
default:
free (reply);
_perr = 1;
return PAM_CONV_ERR;
}
}
*resp = reply;
return PAM_SUCCESS;
}
static struct pam_conv PAM_conversation = { &PAM_gnuimap4d_conv, NULL };
#endif /* USE_LIBPAM */
#define PAM_ERROR if (_perr || (pamerror != PAM_SUCCESS)) goto pam_errlab;
int
imap4d_login (struct imap4d_command *command, char *arg)
{
struct passwd *pw;
char *sp = NULL, *username, *pass;
#ifdef USE_LIBPAM
pam_handle_t *pamh;
int pamerror;
#endif /* !USE_LIBPAM */
int rc;
username = util_getword (arg, &sp);
pass = util_getword (NULL, &sp);
......@@ -97,56 +35,29 @@ imap4d_login (struct imap4d_command *command, char *arg)
else if (util_getword (NULL, &sp))
return util_finish (command, RESP_NO, "Too many args");
pw = mu_getpwnam (username);
if (pw == NULL)
return util_finish (command, RESP_NO, "User name or passwd rejected");
auth_data = mu_get_auth_by_name (username);
#ifndef USE_LIBPAM
if (pw->pw_uid < 1)
return util_finish (command, RESP_NO, "User name or passwd rejected");
if (strcmp (pw->pw_passwd, (char *)crypt (pass, pw->pw_passwd)))
if (auth_data == NULL)
{
#ifdef HAVE_SHADOW_H
struct spwd *spw;
spw = getspnam (username);
if (spw == NULL || strcmp (spw->sp_pwdp, (char *)crypt (pass, spw->sp_pwdp)))
#ifdef HAVE_MYSQL
{
spw = getMspnam (username);
if (spw == NULL || strcmp (spw->sp_pwdp, (char *)crypt (pass, spw->sp_pwdp)))
return util_finish (command, RESP_NO, "User name or passwd rejected");
}
#else /* HAVE_MYSQL */
#endif /* HAVE_SHADOW_H */
syslog (LOG_INFO, "User '%s': nonexistent", arg);
return util_finish (command, RESP_NO, "User name or passwd rejected");
#endif /* HAVE_MYSQL */
}
#else /* !USE_LIBPAM */
_user = (char *) username;
_pwd = pass;
/* libpam doesn't log to LOG_MAIL */
closelog ();
pamerror = pam_start (pam_service, username, &PAM_conversation, &pamh);
PAM_ERROR;
pamerror = pam_authenticate (pamh, 0);
PAM_ERROR;
pamerror = pam_acct_mgmt (pamh, 0);
PAM_ERROR;
pamerror = pam_setcred (pamh, PAM_ESTABLISH_CRED);
pam_errlab:
pam_end (pamh, PAM_SUCCESS);
rc = mu_authenticate (auth_data, pass);
openlog ("gnu-imap4d", LOG_PID, log_facility);
if (_perr || (pamerror != PAM_SUCCESS))
if (rc)
{
syslog (LOG_INFO, "Login failed: %s", arg);
return util_finish (command, RESP_NO, "User name or passwd rejected");
#endif /* USE_LIBPAM */
}
if (pw->pw_uid > 0 && !mu_virtual_domain)
setuid (pw->pw_uid);
if (auth_data->change_uid)
setuid (auth_data->uid);
homedir = mu_normalize_path (strdup (pw->pw_dir), "/");
homedir = mu_normalize_path (strdup (auth_data->dir), "/");
chdir (homedir);
namespace_init (pw->pw_dir);
namespace_init (homedir);
syslog (LOG_INFO, "User '%s' logged in", username);
return util_finish (command, RESP_OK, "Completed");
}
......
......@@ -197,29 +197,13 @@ namespace_checkfullpath (char *name, const char *pattern, const char *delim)
char *
namespace_getfullpath (char *name, const char *delim)
{
if (strcasecmp (name, "INBOX") == 0 && !mu_virtual_domain)
{
struct passwd *pw = mu_getpwuid (getuid ());
if (pw)
{
name = malloc (strlen (mu_path_maildir) +
strlen (pw->pw_name) + 1);
if (!name)
{
syslog (LOG_ERR, "Not enough memory");
return NULL;
}
sprintf (name, "%s%s", mu_path_maildir, pw->pw_name);
}
else
name = strdup ("/dev/null");
}
if (strcasecmp (name, "INBOX") == 0 && auth_data->change_uid)
name = strdup (auth_data->mailbox);
else
name = namespace_checkfullpath (name, NULL, delim);
return name;
}
int
namespace_init(char *path)
{
......
......@@ -68,8 +68,9 @@ imap4d_rename (struct imap4d_command *command, char *arg)
if (strcasecmp (oldname, "INBOX") == 0)
{
mailbox_t newmbox = NULL;
mailbox_t inbox = NULL;
char *name;
struct passwd *pw;
if (S_ISDIR(newst.st_mode))
{
free (newname);
......@@ -86,11 +87,8 @@ imap4d_rename (struct imap4d_command *command, char *arg)
}
free (name);
free (newname);
pw = mu_getpwuid (getuid ());
if (pw)
{
mailbox_t inbox = NULL;
if (mailbox_create_default (&inbox, pw->pw_name) == 0 &&
if (mailbox_create_default (&inbox, auth_data->name) == 0 &&
mailbox_open (inbox, MU_STREAM_RDWR) == 0)
{
size_t no;
......@@ -111,7 +109,6 @@ imap4d_rename (struct imap4d_command *command, char *arg)
mailbox_close (inbox);
mailbox_destroy (&inbox);
}
}
mailbox_close (newmbox);
mailbox_destroy (&newmbox);
return util_finish (command, RESP_OK, "Already exist");
......
......@@ -16,54 +16,52 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "mu_scm.h"
#include <pwd.h>
#include <mailutils/mu_auth.h>
SCM_DEFINE (mu_scm_getpwuid, "mu_getpwuid", 0, 1, 0,
SCM_DEFINE (mu_scm_getpwuid, "mu-getpwuid", 1, 0, 0,
(SCM USER),
"Look up an entry in the user database. USER can be an integer,\n"
"a string, or omitted, giving the behaviour of mu_getpwuid, mu_getpwnam\n"
"or (system) getpwent respectively.\n"
"Returns a vector with fields corresponding to those of the passwd\n"
"or a string, giving the behaviour of mu_get_auth_by_uid or mu_get_auth_by_name\n"
"respectively.\n"
"Returns a vector with fields corresponding to those of the mu_auth_data\n"
"entry in question. If no matching entry was found, returns #f.\n")
#define FUNC_NAME s_mu_scm_getpwuid
{
SCM result;
struct passwd *entry;
struct mu_auth_data *entry;
SCM *ve;
result = scm_make_vector (SCM_MAKINUM (7), SCM_UNSPECIFIED);
result = scm_make_vector (SCM_MAKINUM (8), SCM_UNSPECIFIED);
ve = SCM_VELTS (result);
if (SCM_UNBNDP (USER) || SCM_FALSEP (USER))
if (SCM_INUMP (USER))
{
entry = getpwent ();
}
else if (SCM_INUMP (USER))
{
entry = mu_getpwuid (SCM_INUM (USER));
entry = mu_get_auth_by_uid (SCM_INUM (USER));
}
else
{
SCM_VALIDATE_ROSTRING (1, USER);
if (SCM_SUBSTRP (USER))
USER = scm_makfromstr (SCM_ROCHARS (USER), SCM_ROLENGTH (USER), 0);
entry = mu_getpwnam (SCM_ROCHARS (USER));
entry = mu_get_auth_by_name (SCM_ROCHARS (USER));
}
if (!entry)
return SCM_BOOL_F;
ve[0] = scm_makfrom0str (entry->pw_name);
ve[1] = scm_makfrom0str (entry->pw_passwd);
ve[2] = scm_ulong2num ((unsigned long) entry->pw_uid);
ve[3] = scm_ulong2num ((unsigned long) entry->pw_gid);
ve[4] = scm_makfrom0str (entry->pw_gecos);
if (!entry->pw_dir)
ve[0] = scm_makfrom0str (entry->name);
ve[1] = scm_makfrom0str (entry->passwd);
ve[2] = scm_ulong2num ((unsigned long) entry->uid);
ve[3] = scm_ulong2num ((unsigned long) entry->gid);
ve[4] = scm_makfrom0str (entry->gecos);
if (!entry->dir)
ve[5] = scm_makfrom0str ("");
else
ve[5] = scm_makfrom0str (entry->pw_dir);
if (!entry->pw_shell)
ve[5] = scm_makfrom0str (entry->dir);
if (!entry->shell)
ve[6] = scm_makfrom0str ("");
else
ve[6] = scm_makfrom0str (entry->pw_shell);
ve[6] = scm_makfrom0str (entry->shell);
ve[7] = scm_makfrom0str (entry->mailbox);
mu_auth_data_free (entry);
return result;
}
#undef FUNC_NAME
......
......@@ -176,7 +176,7 @@ main (int argc, char *argv[])
umask (0077);
mu_argp_error_code = EX_CONFIG;
MU_AUTH_REGISTER_ALL_MODULES();
mu_argp_parse (&argp, &argc, &argv, 0, argp_capa, &arg_index, NULL);
openlog ("mail.local", LOG_PID, log_facility);
......@@ -193,16 +193,6 @@ main (int argc, char *argv[])
return EX_USAGE;
}
#ifdef HAVE_MYSQL
mu_register_getpwnam (getMpwnam);
mu_register_getpwuid (getMpwuid);
#endif
#ifdef USE_VIRTUAL_DOMAINS
mu_register_getpwnam (getpwnam_virtual);
mu_register_getpwnam (getpwnam_ip_virtual);
mu_register_getpwnam (getpwnam_host_virtual);
#endif
/* Register local mbox formats. */
{
list_t bookie;
......@@ -308,11 +298,12 @@ make_tmp (const char *from, char **tempfile)
{
if (memcmp (buf, "From ", 5))
{
struct mu_auth_data *auth;
if (!from)
{
struct passwd *pw = mu_getpwuid (uid);
if (pw)
from = pw->pw_name;
auth = mu_get_auth_by_uid (uid);
if (auth)
from = auth->name;
}
if (from)
{
......@@ -324,6 +315,8 @@ make_tmp (const char *from, char **tempfile)
mailer_err ("Can't determine sender address");
exit (EX_UNAVAILABLE);
}
if (auth)
mu_auth_data_free (auth);
}
}
else if (!memcmp (buf, "From ", 5))
......@@ -353,7 +346,7 @@ deliver (FILE *fp, char *name)
url_t url = NULL;
size_t n = 0;
locker_t lock;
struct passwd *pw;
struct mu_auth_data *auth;
int status;
stream_t stream;
size_t size;
......@@ -362,15 +355,15 @@ deliver (FILE *fp, char *name)
struct stat sb;
#endif
pw = mu_getpwnam (name);
if (!pw)
auth = mu_get_auth_by_name (name);
if (!auth)
{
mailer_err ("%s: no such user", name);
exit_code = EX_UNAVAILABLE;
return;
}
path = malloc (strlen (mu_path_maildir) + strlen (name) + 1);
path = strdup (auth->mailbox);
if (!path)
{
mailer_err ("Out of memory");
......@@ -393,7 +386,7 @@ deliver (FILE *fp, char *name)
/* Actually open the mailbox. Switch to the user's euid to make
sure the maildrop file will have right privileges, in case it
will be created */
if (switch_user_id (pw->pw_uid))
if (switch_user_id (auth->uid))
return;
status = mailbox_open (mbox, MU_STREAM_RDWR|MU_STREAM_CREAT);
if (switch_user_id (0))
......@@ -463,7 +456,7 @@ deliver (FILE *fp, char *name)
}
#endif
if (!failed && switch_user_id (pw->pw_uid) == 0)
if (!failed && switch_user_id (auth->uid) == 0)
{
off_t off = size;
size_t nwr;
......@@ -490,6 +483,7 @@ deliver (FILE *fp, char *name)
locker_unlock (lock);
mu_auth_data_free (auth);
mailbox_close (mbox);
mailbox_destroy (&mbox);
}
......
......@@ -73,15 +73,16 @@ mda_init (void *data)
static void
mda_switch_to_user (struct mda_data *md)
{
struct passwd *pw = NULL;
struct mu_auth_data *auth = NULL;
if (md && *md->argv != NULL)
pw = mu_getpwnam (*md->argv);
auth = mu_get_auth_by_name (*md->argv);
if (pw)
if (auth)
{
switch_user_id (pw->pw_uid);
chdir (pw->pw_dir);
switch_user_id (auth->uid);
chdir (auth->dir);
mu_auth_data_free (auth);
}
else
{
......
......@@ -34,6 +34,7 @@
#include <mailutils/mutil.h>
#include <mailutils/error.h>
#include <mailutils/errno.h>
#include <mailutils/mu_auth.h>
const char *mu_path_maildir = MU_PATH_MAILDIR;
......@@ -93,12 +94,13 @@ static const char *
get_homedir (const char *user)
{
const char *homedir = NULL;
struct passwd *pw = NULL;
struct mu_auth_data *auth = NULL;
if (user)
{
pw = mu_getpwnam (user);
if (pw)
homedir = pw->pw_dir;
auth = mu_get_auth_by_name (user);
if (auth)
homedir = auth->dir;
}
else
{
......@@ -107,16 +109,20 @@ get_homedir (const char *user)
homedir = getenv ("HOME");
if (homedir == NULL)
{
pw = mu_getpwuid (getuid ());
if (pw)
homedir = pw->pw_dir;
auth = mu_get_auth_by_name (user);
if (auth)
homedir = auth->dir;
}
#else
pw = mu_getpwuid (getuid ());
if (pw)
homedir = pw->pw_dir;
auth = mu_get_auth_by_name (user);
if (auth)
homedir = auth->dir;
#endif
}
if (homedir)
homedir = strdup (homedir);
mu_auth_data_free (auth);
return homedir;
}
......@@ -136,22 +142,27 @@ user_mailbox_name (const char *user, char **mailbox_name)
if (!user)
user = (getenv ("LOGNAME")) ? getenv ("LOGNAME") : getenv ("USER");
#endif
if (user == NULL)
if (user)
{
struct passwd *pw;
pw = mu_getpwuid (getuid ());
if (pw)
user = pw->pw_name;
*mailbox_name = malloc (strlen (user) + strlen (mu_path_maildir) + 2);
if (*mailbox_name == NULL)
return ENOMEM;
sprintf (*mailbox_name, "%s%s", mu_path_maildir, user);
}
else
{
struct mu_auth_data *auth = mu_get_auth_by_uid (getuid ());
if (!auth)
{
mu_error ("Who am I ?\n");
return EINVAL;
}
*mailbox_name = strdup (auth->mailbox);
mu_auth_data_free (auth);
}
*mailbox_name = malloc (strlen (user) + strlen (mu_path_maildir) + 2);
if (*mailbox_name == NULL)
return ENOMEM;
sprintf (*mailbox_name, "%s%s", mu_path_maildir, user);
return 0;
}
......@@ -188,6 +199,7 @@ plus_expand (const char *file, char **buf)
(*buf)[len-1] = 0;
free (user);
free (path);
free (home);
return 0;
}
......
......@@ -47,6 +47,7 @@
#include <mailutils/mutil.h>
#include <mailutils/observer.h>
#include <mailutils/stream.h>
#include <mailutils/mu_auth.h>
#define MESSAGE_MODIFIED 0x10000;
......@@ -971,18 +972,18 @@ message_sender (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
/* oops! We are still here */
{
struct passwd *pw;
const char *sender;
pw = mu_getpwuid (getuid ());
sender = (pw) ? pw->pw_name : "unknown";
struct mu_auth_data *auth = mu_get_auth_by_uid (getuid ());
const char *sender = auth ? auth->name : "unknown";
n = strlen (sender);
if (buf && len > 0)
{
len--; /* One for the null. */
n = (n < len) ? n : len;
memcpy (buf, pw->pw_name, n);
memcpy (buf, auth->name, n);
buf[n] = '\0';
}
if (auth)
mu_auth_data_free (auth);
}
if (pnwrite)
......
......@@ -30,6 +30,7 @@
#include <mailutils/errno.h>
#include <mailutils/mutil.h>
#include <mailutils/mu_auth.h>
#include <auth0.h>
#include <url0.h>
......@@ -399,10 +400,11 @@ get_user (url_t url, const char *filename, char **user)
}
else
{
struct passwd *pw = mu_getpwuid (getuid ());
if (pw && pw->pw_name)
struct mu_auth_data *auth = mu_get_auth_by_uid (getuid ());
if (auth)
{
u = strdup (pw->pw_name);
u = strdup (auth->name);
mu_auth_data_free (auth);
if (!u)
return ENOMEM;
}
......
......@@ -17,10 +17,6 @@
#include "pop3d.h"
#ifdef HAVE_MYSQL
# include "../MySql/MySql.h"
#endif
mailbox_t mbox;
int state;
char *username;
......@@ -91,6 +87,7 @@ main (int argc, char **argv)
struct group *gr;
int status = OK;
MU_AUTH_REGISTER_ALL_MODULES();
mu_argp_parse (&argp, &argc, &argv, 0, pop3d_argp_capa, NULL, &daemon_param);
#ifdef USE_LIBPAM
......@@ -127,16 +124,6 @@ main (int argc, char **argv)
list_append (bookie, path_record);
}
#ifdef HAVE_MYSQL
mu_register_getpwnam (getMpwnam);
mu_register_getpwuid (getMpwuid);
#endif
#ifdef USE_VIRTUAL_DOMAINS
mu_register_getpwnam (getpwnam_virtual);
mu_register_getpwnam (getpwnam_ip_virtual);
mu_register_getpwnam (getpwnam_host_virtual);
#endif
/* Set the signal handlers. */
signal (SIGINT, pop3d_signal);
signal (SIGQUIT, pop3d_signal);
......
......@@ -17,79 +17,13 @@
#include "pop3d.h"
#ifdef HAVE_MYSQL
# include "../MySql/MySql.h"
#endif
#ifdef USE_LIBPAM
#define COPY_STRING(s) (s) ? strdup(s) : NULL
static char *_pwd;
static char *_user;
static int _perr = 0;
#define PAM_ERROR if (_perr || (pamerror != PAM_SUCCESS)) \
goto pam_errlab;
static int
PAM_gnupop3d_conv (int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
int replies = 0;
struct pam_response *reply = NULL;
(void)appdata_ptr;
reply = malloc (sizeof (*reply) * num_msg);
if (!reply)
return PAM_CONV_ERR;
for (replies = 0; replies < num_msg; replies++)
{
switch (msg[replies]->msg_style)
{
case PAM_PROMPT_ECHO_ON:
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = COPY_STRING (_user);
/* PAM frees resp */
break;
case PAM_PROMPT_ECHO_OFF:
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = COPY_STRING (_pwd);
/* PAM frees resp */
break;
case PAM_TEXT_INFO:
case PAM_ERROR_MSG:
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = NULL;
break;
default:
free (reply);
_perr = 1;
return PAM_CONV_ERR;
}
}
*resp = reply;
return PAM_SUCCESS;
}
static struct pam_conv PAM_conversation = { &PAM_gnupop3d_conv, NULL };
#endif /* USE_LIBPAM */
/* Basic user authentication. This also takes the PASS command and verifies
the user name and password. Calls setuid() upon successful verification,
otherwise it will (likely) return ERR_BAD_LOGIN */
int
pop3d_user (const char *arg)
{
char *buf, pass[POP_MAXCMDLEN], *tmp, *cmd;
struct passwd *pw;
int status;
int lockit = 1;
char *mailbox_name = NULL;
struct mu_auth_data *auth_data;
if (state != AUTHORIZATION)
return ERR_WRONG_STATE;
......@@ -118,14 +52,10 @@ pop3d_user (const char *arg)
free (tmp);
}
if (strlen (cmd) > 4)
if (strcasecmp (cmd, "PASS") == 0)
{
free (cmd);
return ERR_BAD_CMD;
}
int rc;
if ((strcasecmp (cmd, "PASS") == 0))
{
free (cmd);
#ifdef _USE_APOP
......@@ -139,79 +69,40 @@ pop3d_user (const char *arg)
}
#endif
pw = mu_getpwnam (arg);
auth_data = mu_get_auth_by_name (arg);
if (pw == NULL)
if (auth_data == NULL)
{
syslog (LOG_INFO, "User '%s': nonexistent", arg);
return ERR_BAD_LOGIN;
}
#ifndef USE_LIBPAM
if (pw->pw_uid < 1)
return ERR_BAD_LOGIN;
if (strcmp (pw->pw_passwd, (char *) crypt (pass, pw->pw_passwd)))
{
#ifdef HAVE_SHADOW_H
struct spwd *spw;
spw = getspnam ((char *) arg);
#ifdef HAVE_MYSQL
if (spw == NULL)
spw = getMspnam (arg);
#endif /* HAVE_MYSQL */
if (spw == NULL || strcmp (spw->sp_pwdp,
(char *) crypt (pass, spw->sp_pwdp)))
#endif /* HAVE_SHADOW_H */
{
syslog (LOG_INFO, "User '%s': authentication failed", arg);
return ERR_BAD_LOGIN;
}
}
#else /* !USE_LIBPAM */
{
pam_handle_t *pamh;
int pamerror;
_user = (char *) arg;
_pwd = pass;
/* libpam doesn't log to LOG_MAIL */
closelog ();
pamerror = pam_start (pam_service, arg, &PAM_conversation, &pamh);
PAM_ERROR;
pamerror = pam_authenticate (pamh, 0);
PAM_ERROR;
pamerror = pam_acct_mgmt (pamh, 0);
PAM_ERROR;
pamerror = pam_setcred (pamh, PAM_ESTABLISH_CRED);
pam_errlab:
pam_end (pamh, PAM_SUCCESS);
rc = mu_authenticate (auth_data, pass);
openlog ("gnu-pop3d", LOG_PID, log_facility);
if (pamerror != PAM_SUCCESS)
if (rc)
{
syslog (LOG_INFO, "User '%s': authentication failed", _user);
syslog (LOG_INFO, "User '%s': authentication failed", arg);
mu_auth_data_free (auth_data);
return ERR_BAD_LOGIN;
}
}
#endif /* USE_LIBPAM */
if (pw->pw_uid > 0 && !mu_virtual_domain)
{
setuid (pw->pw_uid);
mailbox_name = malloc (strlen (mu_path_maildir) +
strlen (pw->pw_name) + 1);
if (!mailbox_name)
else if (strcasecmp (cmd, "QUIT") == 0)
{
syslog (LOG_ERR, "Not enough memory");
return ERR_UNKNOWN;
}
sprintf (mailbox_name, "%s%s", mu_path_maildir, pw->pw_name);
syslog (LOG_INFO, "Possible probe of account '%s'", arg);
free (cmd);
return pop3d_quit (pass);
}
else if (mu_virtual_domain)
else
{
mailbox_name = calloc (strlen (pw->pw_dir) + strlen ("/INBOX"), 1);
sprintf (mailbox_name, "%s/INBOX", pw->pw_dir);
free (cmd);
return ERR_BAD_CMD;
}
if ((status = mailbox_create (&mbox, mailbox_name)) != 0
if (auth_data->change_uid)
setuid (auth_data->uid);
if ((status = mailbox_create (&mbox, auth_data->mailbox)) != 0
|| (status = mailbox_open (mbox, MU_STREAM_RDWR)) != 0)
{
mailbox_destroy (&mbox);
......@@ -222,33 +113,35 @@ pop3d_user (const char *arg)
|| mailbox_open (mbox, MU_STREAM_READ) != 0)
{
state = AUTHORIZATION;
free (mailbox_name);
mu_auth_data_free (auth_data);
return ERR_UNKNOWN;
}
}
else
{
state = AUTHORIZATION;
free (mailbox_name);
mu_auth_data_free (auth_data);
return ERR_MBOX_LOCK;
}
lockit = 0; /* Do not attempt to lock /dev/null ! */
}
free (mailbox_name);
if (lockit && pop3d_lock ())
{
mailbox_close (mbox);
mailbox_destroy (&mbox);
mu_auth_data_free (auth_data);
state = AUTHORIZATION;
return ERR_MBOX_LOCK;
}
username = strdup (pw->pw_name);
username = strdup (auth_data->name);
if (username == NULL)
pop3d_abquit (ERR_NO_MEM);
state = TRANSACTION;
mu_auth_data_free (auth_data);
pop3d_outf ("+OK opened mailbox for %s\r\n", username);
/* mailbox name */
......@@ -261,14 +154,8 @@ pop3d_user (const char *arg)
username, url_to_string (url), total);
}
return OK;
}
else if (strcasecmp (cmd, "QUIT") == 0)
{
syslog (LOG_INFO, "Possible probe of account '%s'", arg);
free (cmd);
return pop3d_quit (pass);
}
free (cmd);
return ERR_BAD_LOGIN;
}
......