17 |
|
|
18 |
#include "pop3d.h" |
#include "pop3d.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; |
|
|
|
|
|
#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 */ |
|
|
|
|
20 |
int |
int |
21 |
pop3d_user (const char *arg) |
pop3d_user (const char *arg) |
22 |
{ |
{ |
23 |
char *buf, pass[POP_MAXCMDLEN], *tmp, *cmd; |
char *buf, pass[POP_MAXCMDLEN], *tmp, *cmd; |
|
struct passwd *pw; |
|
24 |
int status; |
int status; |
25 |
int lockit = 1; |
int lockit = 1; |
26 |
char *mailbox_name = NULL; |
struct mu_auth_data *auth_data; |
27 |
|
|
28 |
if (state != AUTHORIZATION) |
if (state != AUTHORIZATION) |
29 |
return ERR_WRONG_STATE; |
return ERR_WRONG_STATE; |
30 |
|
|
52 |
free (tmp); |
free (tmp); |
53 |
} |
} |
54 |
|
|
55 |
if (strlen (cmd) > 4) |
if (strcasecmp (cmd, "PASS") == 0) |
56 |
{ |
{ |
57 |
free (cmd); |
int rc; |
|
return ERR_BAD_CMD; |
|
|
} |
|
58 |
|
|
|
if ((strcasecmp (cmd, "PASS") == 0)) |
|
|
{ |
|
59 |
free (cmd); |
free (cmd); |
60 |
|
|
61 |
#ifdef _USE_APOP |
#ifdef _USE_APOP |
69 |
} |
} |
70 |
#endif |
#endif |
71 |
|
|
72 |
pw = mu_getpwnam (arg); |
auth_data = mu_get_auth_by_name (arg); |
73 |
|
|
74 |
if (pw == NULL) |
if (auth_data == NULL) |
75 |
{ |
{ |
76 |
syslog (LOG_INFO, "User '%s': nonexistent", arg); |
syslog (LOG_INFO, "User '%s': nonexistent", arg); |
77 |
return ERR_BAD_LOGIN; |
return ERR_BAD_LOGIN; |
78 |
} |
} |
79 |
|
|
80 |
#ifndef USE_LIBPAM |
rc = mu_authenticate (auth_data, pass); |
81 |
if (pw->pw_uid < 1) |
openlog ("gnu-pop3d", LOG_PID, log_facility); |
|
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); |
|
|
openlog ("gnu-pop3d", LOG_PID, log_facility); |
|
|
if (pamerror != PAM_SUCCESS) |
|
|
{ |
|
|
syslog (LOG_INFO, "User '%s': authentication failed", _user); |
|
|
return ERR_BAD_LOGIN; |
|
|
} |
|
|
} |
|
|
#endif /* USE_LIBPAM */ |
|
82 |
|
|
83 |
if (pw->pw_uid > 0 && !mu_virtual_domain) |
if (rc) |
|
{ |
|
|
setuid (pw->pw_uid); |
|
|
mailbox_name = malloc (strlen (mu_path_maildir) + |
|
|
strlen (pw->pw_name) + 1); |
|
|
if (!mailbox_name) |
|
|
{ |
|
|
syslog (LOG_ERR, "Not enough memory"); |
|
|
return ERR_UNKNOWN; |
|
|
} |
|
|
sprintf (mailbox_name, "%s%s", mu_path_maildir, pw->pw_name); |
|
|
} |
|
|
else if (mu_virtual_domain) |
|
84 |
{ |
{ |
85 |
mailbox_name = calloc (strlen (pw->pw_dir) + strlen ("/INBOX"), 1); |
syslog (LOG_INFO, "User '%s': authentication failed", arg); |
86 |
sprintf (mailbox_name, "%s/INBOX", pw->pw_dir); |
mu_auth_data_free (auth_data); |
87 |
|
return ERR_BAD_LOGIN; |
88 |
} |
} |
89 |
|
} |
90 |
|
else if (strcasecmp (cmd, "QUIT") == 0) |
91 |
|
{ |
92 |
|
syslog (LOG_INFO, "Possible probe of account '%s'", arg); |
93 |
|
free (cmd); |
94 |
|
return pop3d_quit (pass); |
95 |
|
} |
96 |
|
else |
97 |
|
{ |
98 |
|
free (cmd); |
99 |
|
return ERR_BAD_CMD; |
100 |
|
} |
101 |
|
|
102 |
if ((status = mailbox_create (&mbox, mailbox_name)) != 0 |
if (auth_data->change_uid) |
103 |
|| (status = mailbox_open (mbox, MU_STREAM_RDWR)) != 0) |
setuid (auth_data->uid); |
104 |
|
|
105 |
|
if ((status = mailbox_create (&mbox, auth_data->mailbox)) != 0 |
106 |
|
|| (status = mailbox_open (mbox, MU_STREAM_RDWR)) != 0) |
107 |
|
{ |
108 |
|
mailbox_destroy (&mbox); |
109 |
|
/* For non existent mailbox, we fake. */ |
110 |
|
if (status == ENOENT) |
111 |
{ |
{ |
112 |
mailbox_destroy (&mbox); |
if (mailbox_create (&mbox, "/dev/null") != 0 |
113 |
/* For non existent mailbox, we fake. */ |
|| mailbox_open (mbox, MU_STREAM_READ) != 0) |
|
if (status == ENOENT) |
|
|
{ |
|
|
if (mailbox_create (&mbox, "/dev/null") != 0 |
|
|
|| mailbox_open (mbox, MU_STREAM_READ) != 0) |
|
|
{ |
|
|
state = AUTHORIZATION; |
|
|
free (mailbox_name); |
|
|
return ERR_UNKNOWN; |
|
|
} |
|
|
} |
|
|
else |
|
114 |
{ |
{ |
115 |
state = AUTHORIZATION; |
state = AUTHORIZATION; |
116 |
free (mailbox_name); |
mu_auth_data_free (auth_data); |
117 |
return ERR_MBOX_LOCK; |
return ERR_UNKNOWN; |
118 |
} |
} |
|
lockit = 0; /* Do not attempt to lock /dev/null ! */ |
|
119 |
} |
} |
120 |
free (mailbox_name); |
else |
|
|
|
|
if (lockit && pop3d_lock ()) |
|
121 |
{ |
{ |
|
mailbox_close (mbox); |
|
|
mailbox_destroy (&mbox); |
|
122 |
state = AUTHORIZATION; |
state = AUTHORIZATION; |
123 |
|
mu_auth_data_free (auth_data); |
124 |
return ERR_MBOX_LOCK; |
return ERR_MBOX_LOCK; |
125 |
} |
} |
126 |
|
lockit = 0; /* Do not attempt to lock /dev/null ! */ |
|
username = strdup (pw->pw_name); |
|
|
if (username == NULL) |
|
|
pop3d_abquit (ERR_NO_MEM); |
|
|
state = TRANSACTION; |
|
|
|
|
|
pop3d_outf ("+OK opened mailbox for %s\r\n", username); |
|
|
|
|
|
/* mailbox name */ |
|
|
{ |
|
|
url_t url = NULL; |
|
|
size_t total = 0; |
|
|
mailbox_get_url (mbox, &url); |
|
|
mailbox_messages_count (mbox, &total); |
|
|
syslog (LOG_INFO, "User '%s' logged in with mailbox '%s' (%d msgs)", |
|
|
username, url_to_string (url), total); |
|
|
} |
|
|
return OK; |
|
127 |
} |
} |
128 |
else if (strcasecmp (cmd, "QUIT") == 0) |
|
129 |
|
if (lockit && pop3d_lock ()) |
130 |
{ |
{ |
131 |
syslog (LOG_INFO, "Possible probe of account '%s'", arg); |
mailbox_close (mbox); |
132 |
free (cmd); |
mailbox_destroy (&mbox); |
133 |
return pop3d_quit (pass); |
mu_auth_data_free (auth_data); |
134 |
} |
state = AUTHORIZATION; |
135 |
|
return ERR_MBOX_LOCK; |
136 |
|
} |
137 |
|
|
138 |
|
username = strdup (auth_data->name); |
139 |
|
if (username == NULL) |
140 |
|
pop3d_abquit (ERR_NO_MEM); |
141 |
|
state = TRANSACTION; |
142 |
|
|
143 |
|
mu_auth_data_free (auth_data); |
144 |
|
|
145 |
|
pop3d_outf ("+OK opened mailbox for %s\r\n", username); |
146 |
|
|
147 |
|
/* mailbox name */ |
148 |
|
{ |
149 |
|
url_t url = NULL; |
150 |
|
size_t total = 0; |
151 |
|
mailbox_get_url (mbox, &url); |
152 |
|
mailbox_messages_count (mbox, &total); |
153 |
|
syslog (LOG_INFO, "User '%s' logged in with mailbox '%s' (%d msgs)", |
154 |
|
username, url_to_string (url), total); |
155 |
|
} |
156 |
|
return OK; |
157 |
|
|
|
free (cmd); |
|
|
return ERR_BAD_LOGIN; |
|
158 |
} |
} |
159 |
|
|
160 |
|
|
161 |
|
|