}
+/*
+ * Login greeting common to all auth methods
+ */
+void smtp_auth_greeting(void) {
+ cprintf("235 2.0.0 Hello, %s\r\n", CC->user.fullname);
+ lprintf(CTDL_NOTICE, "SMTP authenticated %s\n", CC->user.fullname);
+ CC->internal_pgm = 0;
+ CC->cs_flags &= ~CS_STEALTH;
+}
+
+
/*
* Implement HELO and EHLO commands.
*
cprintf("250-HELP\r\n");
cprintf("250-SIZE %ld\r\n", config.c_maxmsglen);
cprintf("250-PIPELINING\r\n");
- cprintf("250-AUTH=LOGIN\r\n");
+ cprintf("250-AUTH LOGIN PLAIN\r\n");
+ cprintf("250-AUTH=LOGIN PLAIN\r\n");
#ifdef HAVE_OPENSSL
cprintf("250-STARTTLS\r\n");
#endif
char username[SIZ];
CtdlDecodeBase64(username, argbuf, SIZ);
- lprintf(9, "Trying <%s>\n", username);
+ lprintf(CTDL_DEBUG, "Trying <%s>\n", username);
if (CtdlLoginExistingUser(username) == login_ok) {
CtdlEncodeBase64(buf, "Password:", 9);
cprintf("334 %s\r\n", buf);
char password[SIZ];
CtdlDecodeBase64(password, argbuf, SIZ);
- lprintf(9, "Trying <%s>\n", password);
+ lprintf(CTDL_DEBUG, "Trying <%s>\n", password);
if (CtdlTryPassword(password) == pass_ok) {
- cprintf("235 2.0.0 Hello, %s\r\n", CC->user.fullname);
- lprintf(9, "SMTP authenticated login successful\n");
- CC->internal_pgm = 0;
- CC->cs_flags &= ~CS_STEALTH;
+ smtp_auth_greeting();
}
else {
cprintf("535 5.7.0 Authentication failed.\r\n");
*/
void smtp_auth(char *argbuf) {
char buf[SIZ];
+ char method[SIZ];
+ char encoded_authstring[SIZ];
+ char decoded_authstring[SIZ];
+ char ident[SIZ];
+ char user[SIZ];
+ char pass[SIZ];
- if (strncasecmp(argbuf, "login", 5) ) {
- cprintf("504 5.7.4 We only support LOGIN authentication.\r\n");
+ if (CC->logged_in) {
+ cprintf("504 5.7.4 Already logged in.\r\n");
return;
}
- if (strlen(argbuf) >= 7) {
- smtp_get_user(&argbuf[6]);
+ extract_token(method, argbuf, 0, ' ');
+
+ if (!strncasecmp(method, "login", 5) ) {
+ if (strlen(argbuf) >= 7) {
+ smtp_get_user(&argbuf[6]);
+ }
+ else {
+ CtdlEncodeBase64(buf, "Username:", 9);
+ cprintf("334 %s\r\n", buf);
+ SMTP->command_state = smtp_user;
+ }
+ return;
}
- else {
- CtdlEncodeBase64(buf, "Username:", 9);
- cprintf("334 %s\r\n", buf);
- SMTP->command_state = smtp_user;
+ if (!strncasecmp(method, "plain", 5) ) {
+ extract_token(encoded_authstring, argbuf, 1, ' ');
+ CtdlDecodeBase64(decoded_authstring,
+ encoded_authstring,
+ strlen(encoded_authstring) );
+ strcpy(ident, decoded_authstring);
+ strcpy(user, &decoded_authstring[strlen(ident) + 1] );
+ strcpy(pass, &decoded_authstring[strlen(ident) + strlen(user) + 2] );
+
+ if (CtdlLoginExistingUser(user) == login_ok) {
+ if (CtdlTryPassword(pass) == pass_ok) {
+ smtp_auth_greeting();
+ return;
+ }
+ }
+ cprintf("504 5.7.4 Authentication failed.\r\n");
+ }
+
+ if (strncasecmp(method, "login", 5) ) {
+ cprintf("504 5.7.4 Unknown authentication method.\r\n");
+ return;
}
+
}
return;
}
- lprintf(9, "Converting message...\n");
+ lprintf(CTDL_DEBUG, "Converting message...\n");
msg = convert_internet_message(body);
/* If the user is locally authenticated, FORCE the From: header to
time(&CC->lastcmd);
memset(cmdbuf, 0, sizeof cmdbuf); /* Clear it, just in case */
if (client_gets(cmdbuf) < 1) {
- lprintf(3, "SMTP socket is broken. Ending session.\n");
+ lprintf(CTDL_CRIT, "SMTP socket is broken. Ending session.\n");
CC->kill_me = 1;
return;
}
- lprintf(5, "SMTP: %s\n", cmdbuf);
+ lprintf(CTDL_INFO, "SMTP: %s\n", cmdbuf);
while (strlen(cmdbuf) < 5) strcat(cmdbuf, " ");
- lprintf(9, "CC->logged_in = %d\n", CC->logged_in);
-
if (SMTP->command_state == smtp_user) {
smtp_get_user(cmdbuf);
}
/* Parse out the host portion of the recipient address */
process_rfc822_addr(addr, user, node, name);
- lprintf(9, "Attempting SMTP delivery to <%s> @ <%s> (%s)\n",
+ lprintf(CTDL_DEBUG, "Attempting SMTP delivery to <%s> @ <%s> (%s)\n",
user, node, name);
/* Load the message out of the database into a temp file */
/* Figure out what mail exchanger host we have to connect to */
num_mxhosts = getmx(mxhosts, node);
- lprintf(9, "Number of MX hosts for <%s> is %d\n", node, num_mxhosts);
+ lprintf(CTDL_DEBUG, "Number of MX hosts for <%s> is %d\n", node, num_mxhosts);
if (num_mxhosts < 1) {
*status = 5;
snprintf(dsn, SIZ, "No MX hosts found for <%s>", node);
sock = (-1);
for (mx=0; (mx<num_mxhosts && sock < 0); ++mx) {
extract(buf, mxhosts, mx);
- lprintf(9, "Trying <%s>\n", buf);
+ lprintf(CTDL_DEBUG, "Trying <%s>\n", buf);
sock = sock_connect(buf, "25", "tcp");
snprintf(dsn, SIZ, "Could not connect: %s", strerror(errno));
- if (sock >= 0) lprintf(9, "Connected!\n");
+ if (sock >= 0) lprintf(CTDL_DEBUG, "Connected!\n");
if (sock < 0) snprintf(dsn, SIZ, "%s", strerror(errno));
}
strcpy(dsn, "Connection broken during SMTP conversation");
goto bail;
}
- lprintf(9, "<%s\n", buf);
+ lprintf(CTDL_DEBUG, "<%s\n", buf);
if (buf[0] != '2') {
if (buf[0] == '4') {
*status = 4;
/* Do a HELO command */
snprintf(buf, sizeof buf, "HELO %s\r\n", config.c_fqdn);
- lprintf(9, ">%s", buf);
+ lprintf(CTDL_DEBUG, ">%s", buf);
sock_write(sock, buf, strlen(buf));
if (ml_sock_gets(sock, buf) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP HELO");
goto bail;
}
- lprintf(9, "<%s\n", buf);
+ lprintf(CTDL_DEBUG, "<%s\n", buf);
if (buf[0] != '2') {
if (buf[0] == '4') {
*status = 4;
/* HELO succeeded, now try the MAIL From: command */
snprintf(buf, sizeof buf, "MAIL From: <%s>\r\n", mailfrom);
- lprintf(9, ">%s", buf);
+ lprintf(CTDL_DEBUG, ">%s", buf);
sock_write(sock, buf, strlen(buf));
if (ml_sock_gets(sock, buf) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP MAIL");
goto bail;
}
- lprintf(9, "<%s\n", buf);
+ lprintf(CTDL_DEBUG, "<%s\n", buf);
if (buf[0] != '2') {
if (buf[0] == '4') {
*status = 4;
/* MAIL succeeded, now try the RCPT To: command */
snprintf(buf, sizeof buf, "RCPT To: <%s>\r\n", addr);
- lprintf(9, ">%s", buf);
+ lprintf(CTDL_DEBUG, ">%s", buf);
sock_write(sock, buf, strlen(buf));
if (ml_sock_gets(sock, buf) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP RCPT");
goto bail;
}
- lprintf(9, "<%s\n", buf);
+ lprintf(CTDL_DEBUG, "<%s\n", buf);
if (buf[0] != '2') {
if (buf[0] == '4') {
*status = 4;
/* RCPT succeeded, now try the DATA command */
- lprintf(9, ">DATA\n");
+ lprintf(CTDL_DEBUG, ">DATA\n");
sock_write(sock, "DATA\r\n", 6);
if (ml_sock_gets(sock, buf) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP DATA");
goto bail;
}
- lprintf(9, "<%s\n", buf);
+ lprintf(CTDL_DEBUG, "<%s\n", buf);
if (buf[0] != '3') {
if (buf[0] == '4') {
*status = 3;
msg_size -= blocksize;
}
if (buf[blocksize-1] != 10) {
- lprintf(5, "Possible problem: message did not correctly "
- "terminate. (expecting 0x10, got 0x%02x)\n",
+ lprintf(CTDL_WARNING, "Possible problem: message did not "
+ "correctly terminate. (expecting 0x10, got 0x%02x)\n",
buf[blocksize-1]);
}
strcpy(dsn, "Connection broken during SMTP message transmit");
goto bail;
}
- lprintf(9, "%s\n", buf);
+ lprintf(CTDL_DEBUG, "%s\n", buf);
if (buf[0] != '2') {
if (buf[0] == '4') {
*status = 4;
safestrncpy(dsn, &buf[4], 1023);
*status = 2;
- lprintf(9, ">QUIT\n");
+ lprintf(CTDL_DEBUG, ">QUIT\n");
sock_write(sock, "QUIT\r\n", 6);
ml_sock_gets(sock, buf);
- lprintf(9, "<%s\n", buf);
+ lprintf(CTDL_DEBUG, "<%s\n", buf);
+ lprintf(CTDL_INFO, "SMTP delivery to <%s> @ <%s> (%s) succeeded\n",
+ user, node, name);
bail: if (msg_fp != NULL) fclose(msg_fp);
sock_close(sock);
struct recptypes *valid;
int successful_bounce = 0;
- lprintf(9, "smtp_do_bounce() called\n");
+ lprintf(CTDL_DEBUG, "smtp_do_bounce() called\n");
strcpy(bounceto, "");
lines = num_tokens(instr, '\n');
extract(dsn, buf, 3);
bounce_this = 0;
- lprintf(9, "key=<%s> addr=<%s> status=%d dsn=<%s>\n",
+ lprintf(CTDL_DEBUG, "key=<%s> addr=<%s> status=%d dsn=<%s>\n",
key, addr, status, dsn);
if (!strcasecmp(key, "bounceto")) {
++num_bounces;
if (bmsg->cm_fields['M'] == NULL) {
- lprintf(2, "ERROR ... M field is null "
+ lprintf(CTDL_ERR, "ERROR ... M field is null "
"(%s:%d)\n", __FILE__, __LINE__);
}
}
/* Deliver the bounce if there's anything worth mentioning */
- lprintf(9, "num_bounces = %d\n", num_bounces);
+ lprintf(CTDL_DEBUG, "num_bounces = %d\n", num_bounces);
if (num_bounces > 0) {
/* First try the user who sent the message */
- lprintf(9, "bounce to user? <%s>\n", bounceto);
+ lprintf(CTDL_DEBUG, "bounce to user? <%s>\n", bounceto);
if (strlen(bounceto) == 0) {
- lprintf(7, "No bounce address specified\n");
+ lprintf(CTDL_ERR, "No bounce address specified\n");
bounce_msgid = (-1L);
}
}
CtdlFreeMessage(bmsg);
- lprintf(9, "Done processing bounces\n");
+ lprintf(CTDL_DEBUG, "Done processing bounces\n");
}
time_t last_attempted = 0L;
time_t retry = SMTP_RETRY_INTERVAL;
- lprintf(9, "smtp_do_procmsg(%ld)\n", msgnum);
+ lprintf(CTDL_DEBUG, "smtp_do_procmsg(%ld)\n", msgnum);
msg = CtdlFetchMessage(msgnum);
if (msg == NULL) {
- lprintf(3, "SMTP: tried %ld but no such message!\n", msgnum);
+ lprintf(CTDL_ERR, "SMTP: tried %ld but no such message!\n", msgnum);
return;
}
* Postpone delivery if we've already tried recently.
*/
if (((time(NULL) - last_attempted) < retry) && (run_queue_now == 0)) {
- lprintf(7, "Retry time not yet reached.\n");
+ lprintf(CTDL_DEBUG, "Retry time not yet reached.\n");
phree(instr);
return;
}
* Bail out if there's no actual message associated with this
*/
if (text_msgid < 0L) {
- lprintf(3, "SMTP: no 'msgid' directive found!\n");
+ lprintf(CTDL_ERR, "SMTP: no 'msgid' directive found!\n");
phree(instr);
return;
}
--i;
--lines;
- lprintf(9, "SMTP: Trying <%s>\n", addr);
+ lprintf(CTDL_DEBUG, "SMTP: Trying <%s>\n", addr);
smtp_try(key, addr, &status, dsn, sizeof dsn, text_msgid);
if (status != 2) {
if (results == NULL) {
/*
* Go ahead and run the queue
*/
- lprintf(7, "SMTP: processing outbound queue\n");
+ lprintf(CTDL_INFO, "SMTP: processing outbound queue\n");
if (getroom(&CC->room, SMTP_SPOOLOUT_ROOM) != 0) {
- lprintf(3, "Cannot find room <%s>\n", SMTP_SPOOLOUT_ROOM);
+ lprintf(CTDL_ERR, "Cannot find room <%s>\n", SMTP_SPOOLOUT_ROOM);
return;
}
CtdlForEachMessage(MSGS_ALL, 0L,
SPOOLMIME, NULL, smtp_do_procmsg, NULL);
- lprintf(7, "SMTP: queue run completed\n");
+ lprintf(CTDL_INFO, "SMTP: queue run completed\n");
run_queue_now = 0;
doing_queue = 0;
}