17 |
|
|
18 |
#include "imap4d.h" |
#include "imap4d.h" |
19 |
|
|
|
#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; |
|
|
|
|
20 |
int |
int |
21 |
imap4d_login (struct imap4d_command *command, char *arg) |
imap4d_login (struct imap4d_command *command, char *arg) |
22 |
{ |
{ |
|
struct passwd *pw; |
|
23 |
char *sp = NULL, *username, *pass; |
char *sp = NULL, *username, *pass; |
24 |
#ifdef USE_LIBPAM |
int rc; |
|
pam_handle_t *pamh; |
|
|
int pamerror; |
|
|
#endif /* !USE_LIBPAM */ |
|
25 |
|
|
26 |
username = util_getword (arg, &sp); |
username = util_getword (arg, &sp); |
27 |
pass = util_getword (NULL, &sp); |
pass = util_getword (NULL, &sp); |
35 |
else if (util_getword (NULL, &sp)) |
else if (util_getword (NULL, &sp)) |
36 |
return util_finish (command, RESP_NO, "Too many args"); |
return util_finish (command, RESP_NO, "Too many args"); |
37 |
|
|
38 |
pw = mu_getpwnam (username); |
auth_data = mu_get_auth_by_name (username); |
39 |
if (pw == NULL) |
|
40 |
return util_finish (command, RESP_NO, "User name or passwd rejected"); |
if (auth_data == NULL) |
|
|
|
|
#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))) |
|
41 |
{ |
{ |
42 |
#ifdef HAVE_SHADOW_H |
syslog (LOG_INFO, "User '%s': nonexistent", arg); |
43 |
struct spwd *spw; |
return util_finish (command, RESP_NO, "User name or passwd rejected"); |
|
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 */ |
|
|
return util_finish (command, RESP_NO, "User name or passwd rejected"); |
|
|
#endif /* HAVE_MYSQL */ |
|
44 |
} |
} |
45 |
|
|
46 |
#else /* !USE_LIBPAM */ |
rc = mu_authenticate (auth_data, pass); |
47 |
_user = (char *) username; |
openlog ("gnu-imap4d", LOG_PID, log_facility); |
48 |
_pwd = pass; |
if (rc) |
49 |
/* libpam doesn't log to LOG_MAIL */ |
{ |
50 |
closelog (); |
syslog (LOG_INFO, "Login failed: %s", arg); |
51 |
pamerror = pam_start (pam_service, username, &PAM_conversation, &pamh); |
return util_finish (command, RESP_NO, "User name or passwd rejected"); |
52 |
PAM_ERROR; |
} |
53 |
pamerror = pam_authenticate (pamh, 0); |
|
54 |
PAM_ERROR; |
if (auth_data->change_uid) |
55 |
pamerror = pam_acct_mgmt (pamh, 0); |
setuid (auth_data->uid); |
|
PAM_ERROR; |
|
|
pamerror = pam_setcred (pamh, PAM_ESTABLISH_CRED); |
|
|
pam_errlab: |
|
|
pam_end (pamh, PAM_SUCCESS); |
|
|
openlog ("gnu-imap4d", LOG_PID, log_facility); |
|
|
if (_perr || (pamerror != PAM_SUCCESS)) |
|
|
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); |
|
56 |
|
|
57 |
homedir = mu_normalize_path (strdup (pw->pw_dir), "/"); |
homedir = mu_normalize_path (strdup (auth_data->dir), "/"); |
58 |
chdir (homedir); |
chdir (homedir); |
59 |
namespace_init (pw->pw_dir); |
namespace_init (homedir); |
60 |
syslog (LOG_INFO, "User '%s' logged in", username); |
syslog (LOG_INFO, "User '%s' logged in", username); |
61 |
return util_finish (command, RESP_OK, "Completed"); |
return util_finish (command, RESP_OK, "Completed"); |
62 |
} |
} |
63 |
|
|