LHLO
};
-typedef void (*smtp_handler)(long offest, long Flags);
-typedef struct _smtp_handler_hook {
- smtp_handler h;
- int Flags;
-} smtp_handler_hook;
-
-HashList *SMTPCmds = NULL;
-#define MaxSMTPCmdLen 10
-
-#define RegisterSmtpCMD(First, H, Flags) registerSmtpCMD(HKEY(First), H, Flags)
-void registerSmtpCMD(const char *First, long FLen, smtp_handler H, int Flags) {
- smtp_handler_hook *h;
-
- if (FLen >= MaxSMTPCmdLen) {
- abort();
- }
-
- h = (smtp_handler_hook*) malloc(sizeof(smtp_handler_hook));
- memset(h, 0, sizeof(smtp_handler_hook));
-
- h->Flags = Flags;
- h->h = H;
- Put(SMTPCmds, First, FLen, h, NULL);
-}
-
/*
* Here's where our SMTP session begins its happy day.
strcpy(CC->cs_clientname, "SMTP session");
CC->internal_pgm = 1;
CC->cs_flags |= CS_STEALTH;
- CC->session_specific_data = malloc(sizeof(citsmtp));
- memset(SMTP, 0, sizeof(citsmtp));
+ CC->session_specific_data = malloc(sizeof(struct citsmtp));
+ memset(SMTP, 0, sizeof(struct citsmtp));
SMTP->is_msa = is_msa;
SMTP->Cmd = NewStrBufPlain(NULL, SIZ);
SMTP->helo_node = NewStrBuf();
/*
* Login greeting common to all auth methods
*/
-void smtp_auth_greeting(long offset, long Flags) {
+void smtp_auth_greeting(void) {
cprintf("235 Hello, %s\r\n", CC->user.fullname);
syslog(LOG_INFO, "serv_smtp: SMTP authenticated %s", CC->user.fullname);
CC->internal_pgm = 0;
*
* which_command: 0=HELO, 1=EHLO, 2=LHLO
*/
-void smtp_hello(long offset, long which_command) {
+void smtp_hello(int which_command) {
- StrBufAppendBuf (SMTP->helo_node, SMTP->Cmd, offset);
+ if (StrLength(SMTP->Cmd) >= 6) {
+ StrBufAppendBuf(SMTP->helo_node, SMTP->Cmd, 5);
+ }
if ( (which_command != LHLO) && (SMTP->is_lmtp) ) {
cprintf("500 Only LHLO is allowed when running LMTP\r\n");
/*
* Implement HELP command.
*/
-void smtp_help(long offset, long Flags) {
+void smtp_help(void) {
cprintf("214 RTFM http://www.ietf.org/rfc/rfc2821.txt\r\n");
}
/*
*
*/
-void smtp_get_user(long offset) {
+void smtp_get_user(int offset) {
char buf[SIZ];
- StrBufDecodeBase64(SMTP->Cmd);
+ StrBuf *UserName = NewStrBufDup(SMTP->Cmd);
+ StrBufCutLeft(UserName, offset);
+ StrBufDecodeBase64(UserName);
- if (CtdlLoginExistingUser(ChrPtr(SMTP->Cmd)) == login_ok) {
+ if (CtdlLoginExistingUser(ChrPtr(UserName)) == login_ok) {
size_t len = CtdlEncodeBase64(buf, "Password:", 9, 0);
if (buf[len - 1] == '\n') {
cprintf("500 No such user.\r\n");
SMTP->command_state = smtp_command;
}
+ FreeStrBuf(&UserName);
}
/*
*
*/
-void smtp_get_pass(long offset, long Flags)
+void smtp_get_pass(void)
{
char password[SIZ];
StrBufDecodeBase64(SMTP->Cmd);
syslog(LOG_DEBUG, "serv_smtp: trying <%s>", password);
if (CtdlTryPassword(SKEY(SMTP->Cmd)) == pass_ok) {
- smtp_auth_greeting(offset, Flags);
+ smtp_auth_greeting();
}
else {
cprintf("535 Authentication failed.\r\n");
/*
* Back end for PLAIN auth method (either inline or multistate)
*/
-void smtp_try_plain(long offset, long Flags) {
+void smtp_try_plain(void) {
const char*decoded_authstring;
char ident[256] = "";
char user[256] = "";
memset(pass, 0, sizeof(pass));
decoded_len = StrBufDecodeBase64(SMTP->Cmd);
- if (decoded_len > 0)
- {
+ if (decoded_len > 0) {
decoded_authstring = ChrPtr(SMTP->Cmd);
len = safestrncpy(ident, decoded_authstring, sizeof ident);
decoded_len -= len - 1;
decoded_authstring += len + 1;
- if (decoded_len > 0)
- {
+ if (decoded_len > 0) {
len = safestrncpy(user, decoded_authstring, sizeof user);
decoded_authstring += len + 1;
decoded_len -= len - 1;
}
- if (decoded_len > 0)
- {
+ if (decoded_len > 0) {
plen = safestrncpy(pass, decoded_authstring, sizeof pass);
if (plen < 0)
if (result == login_ok) {
if (CtdlTryPassword(pass, plen) == pass_ok) {
smtp_webcit_preferences_hack();
- smtp_auth_greeting(offset, Flags);
+ smtp_auth_greeting();
return;
}
}
/*
* Attempt to perform authenticated SMTP
*/
-void smtp_auth(long offset, long Flags) {
+void smtp_auth(void) {
char username_prompt[64];
char method[64];
char encoded_authstring[1024];
return;
}
- extract_token(method, ChrPtr(SMTP->Cmd) + offset, 0, ' ', sizeof method);
+ if (StrLength(SMTP->Cmd) < 6) {
+ cprintf("501 Syntax error\r\n");
+ return;
+ }
+
+ extract_token(method, ChrPtr(SMTP->Cmd) + 5, 0, ' ', sizeof method);
if (!strncasecmp(method, "login", 5) ) {
- if (StrLength(SMTP->Cmd) - offset >= 7) {
- smtp_get_user(6);
+ if (StrLength(SMTP->Cmd) >= 12) {
+ syslog(LOG_DEBUG, "serv_smtp: username <%s> supplied inline", ChrPtr(SMTP->Cmd)+11);
+ smtp_get_user(11);
}
else {
size_t len = CtdlEncodeBase64(username_prompt, "Username:", 9, 0);
if (!strncasecmp(method, "plain", 5) ) {
long len;
- if (num_tokens(ChrPtr(SMTP->Cmd) + offset, ' ') < 2) {
+ if (num_tokens(ChrPtr(SMTP->Cmd) + 5, ' ') < 2) {
cprintf("334 \r\n");
SMTP->command_state = smtp_plain;
return;
}
len = extract_token(encoded_authstring,
- ChrPtr(SMTP->Cmd) + offset,
+ ChrPtr(SMTP->Cmd) + 5,
1, ' ',
sizeof encoded_authstring);
StrBufPlain(SMTP->Cmd, encoded_authstring, len);
- smtp_try_plain(0, Flags);
- return;
- }
-
- if (strncasecmp(method, "login", 5) ) {
- cprintf("504 Unknown authentication method.\r\n");
+ smtp_try_plain();
return;
}
+ cprintf("504 Unknown authentication method.\r\n");
+ return;
}
*
* Set do_response to nonzero to output the SMTP RSET response code.
*/
-void smtp_rset(long offset, long do_response) {
+void smtp_rset(int do_response) {
/*
* Our entire SMTP state is discarded when a RSET command is issued,
* but we need to preserve this one little piece of information, so
* Clear out the portions of the state buffer that need to be cleared out
* after the DATA command finishes.
*/
-void smtp_data_clear(long offset, long flags) {
+void smtp_data_clear(void) {
FlushStrBuf(SMTP->from);
FlushStrBuf(SMTP->recipients);
FlushStrBuf(SMTP->OneRcpt);
/*
* Implements the "MAIL FROM:" command
*/
-void smtp_mail(long offset, long flags) {
+void smtp_mail(void) {
char user[SIZ];
char node[SIZ];
char name[SIZ];
return;
}
- if (strncasecmp(ChrPtr(SMTP->Cmd) + offset, "From:", 5)) {
+ if (StrLength(SMTP->Cmd) < 6) {
+ cprintf("501 Syntax error\r\n");
+ return;
+ }
+
+ if (strncasecmp(ChrPtr(SMTP->Cmd) + 5, "From:", 5)) {
cprintf("501 Syntax error\r\n");
return;
}
- StrBufAppendBuf(SMTP->from, SMTP->Cmd, offset);
+ StrBufAppendBuf(SMTP->from, SMTP->Cmd, 5);
StrBufTrim(SMTP->from);
if (strchr(ChrPtr(SMTP->from), '<') != NULL) {
StrBufStripAllBut(SMTP->from, '<', '>');
/*
* Implements the "RCPT To:" command
*/
-void smtp_rcpt(long offset, long flags) {
+void smtp_rcpt(void) {
char message_to_spammer[SIZ];
struct recptypes *valid = NULL;
return;
}
- if (strncasecmp(ChrPtr(SMTP->Cmd) + offset, "To:", 3)) {
+ if (StrLength(SMTP->Cmd) < 6) {
+ cprintf("501 Syntax error\r\n");
+ return;
+ }
+
+ if (strncasecmp(ChrPtr(SMTP->Cmd) + 5, "To:", 3)) {
cprintf("501 Syntax error\r\n");
return;
}
FlushStrBuf(SMTP->from);
return;
}
+
FlushStrBuf(SMTP->OneRcpt);
- StrBufAppendBuf(SMTP->OneRcpt, SMTP->Cmd, offset + 3);
+ StrBufAppendBuf(SMTP->OneRcpt, SMTP->Cmd, 8);
StrBufTrim(SMTP->OneRcpt);
StrBufStripAllBut(SMTP->OneRcpt, '<', '>');
/*
* Implements the DATA command
*/
-void smtp_data(long offset, long flags) {
+void smtp_data(void) {
StrBuf *body;
StrBuf *defbody;
struct CtdlMessage *msg = NULL;
/* Clean up */
CM_Free(msg);
free_recipients(valid);
- smtp_data_clear(0, 0); /* clear out the buffers now */
+ smtp_data_clear(); /* clear out the buffers now */
}
/*
- * implements the STARTTLS command
+ * Implements the STARTTLS command
*/
-void smtp_starttls(long offset, long flags) {
+void smtp_starttls(void) {
char ok_response[SIZ];
char nosup_response[SIZ];
char error_response[SIZ];
sprintf(nosup_response, "554 TLS not supported here\r\n");
sprintf(error_response, "554 Internal error\r\n");
CtdlModuleStartCryptoMsgs(ok_response, nosup_response, error_response);
- smtp_rset(0, 0);
+ smtp_rset(0);
+}
+
+
+/*
+ * Implements the NOOP (NO OPeration) command
+ */
+void smtp_noop(void) {
+ cprintf("250 NOOP\r\n");
+}
+
+
+/*
+ * Implements the QUIT command
+ */
+void smtp_quit(void) {
+ cprintf("221 Goodbye...\r\n");
+ CC->kill_me = KILLME_CLIENT_LOGGED_OUT;
}
*/
void smtp_command_loop(void) {
static const ConstStr AuthPlainStr = {HKEY("AUTH PLAIN")};
- const char *pch, *pchs;
- long i;
- char CMD[MaxSMTPCmdLen + 1];
if (SMTP == NULL) {
syslog(LOG_ERR, "serv_smtp: Session SMTP data is null. WTF? We will crash now.");
CC->kill_me = KILLME_CLIENT_DISCONNECTED;
return;
}
- syslog(LOG_DEBUG, "serv_smtp: %s", ChrPtr(SMTP->Cmd));
if (SMTP->command_state == smtp_user) {
if (!strncmp(ChrPtr(SMTP->Cmd), AuthPlainStr.Key, AuthPlainStr.len)) {
- smtp_try_plain(0, 0);
+ smtp_try_plain();
}
else {
smtp_get_user(0);
}
else if (SMTP->command_state == smtp_password) {
- smtp_get_pass(0, 0);
+ smtp_get_pass();
return;
}
else if (SMTP->command_state == smtp_plain) {
- smtp_try_plain(0, 0);
+ smtp_try_plain();
return;
}
- pchs = pch = ChrPtr(SMTP->Cmd);
- i = 0;
- while ((*pch != '\0') && (!isblank(*pch)) && (pch - pchs <= MaxSMTPCmdLen)) {
- CMD[i] = toupper(*pch);
- pch ++;
- i++;
+ syslog(LOG_DEBUG, "serv_smtp: client sent command <%s>", ChrPtr(SMTP->Cmd));
+
+ if (!strncasecmp(ChrPtr(SMTP->Cmd), "NOOP", 4)) {
+ smtp_noop();
+ return;
}
- CMD[i] = '\0';
- if ((*pch == '\0') || (isblank(*pch))) {
- void *v;
+ if (!strncasecmp(ChrPtr(SMTP->Cmd), "QUIT", 4)) {
+ smtp_quit();
+ return;
+ }
- if (GetHash(SMTPCmds, CMD, i, &v) &&
- (v != NULL))
- {
- smtp_handler_hook *h = (smtp_handler_hook*) v;
+ if (!strncasecmp(ChrPtr(SMTP->Cmd), "HELO", 4)) {
+ smtp_hello(HELO);
+ return;
+ }
- if (isblank(pchs[i]))
- i++;
+ if (!strncasecmp(ChrPtr(SMTP->Cmd), "EHLO", 4)) {
+ smtp_hello(EHLO);
+ return;
+ }
- h->h(i, h->Flags);
+ if (!strncasecmp(ChrPtr(SMTP->Cmd), "LHLO", 4)) {
+ smtp_hello(LHLO);
+ return;
+ }
- return;
- }
+ if (!strncasecmp(ChrPtr(SMTP->Cmd), "RSET", 4)) {
+ smtp_rset(1);
+ return;
}
- cprintf("502 I'm afraid I can't do that.\r\n");
-}
+ if (!strncasecmp(ChrPtr(SMTP->Cmd), "AUTH", 4)) {
+ smtp_auth();
+ return;
+ }
-void smtp_noop(long offest, long Flags) {
- cprintf("250 NOOP\r\n");
-}
+ if (!strncasecmp(ChrPtr(SMTP->Cmd), "DATA", 4)) {
+ smtp_data();
+ return;
+ }
+ if (!strncasecmp(ChrPtr(SMTP->Cmd), "HELP", 4)) {
+ smtp_help();
+ return;
+ }
-void smtp_quit(long offest, long Flags) {
- cprintf("221 Goodbye...\r\n");
- CC->kill_me = KILLME_CLIENT_LOGGED_OUT;
+ if (!strncasecmp(ChrPtr(SMTP->Cmd), "MAIL", 4)) {
+ smtp_mail();
+ return;
+ }
+
+ if (!strncasecmp(ChrPtr(SMTP->Cmd), "RCPT", 4)) {
+ smtp_rcpt();
+ return;
+ }
+#ifdef HAVE_OPENSSL
+ if (!strncasecmp(ChrPtr(SMTP->Cmd), "STARTTLS", 8)) {
+ smtp_starttls();
+ return;
+ }
+#endif
+
+ cprintf("502 I'm afraid I can't do that.\r\n");
}
CTDL_MODULE_INIT(smtp)
{
if (!threading) {
- SMTPCmds = NewHash(1, NULL);
-
- RegisterSmtpCMD("AUTH", smtp_auth, 0);
- RegisterSmtpCMD("DATA", smtp_data, 0);
- RegisterSmtpCMD("HELO", smtp_hello, HELO);
- RegisterSmtpCMD("EHLO", smtp_hello, EHLO);
- RegisterSmtpCMD("LHLO", smtp_hello, LHLO);
- RegisterSmtpCMD("HELP", smtp_help, 0);
- RegisterSmtpCMD("MAIL", smtp_mail, 0);
- RegisterSmtpCMD("NOOP", smtp_noop, 0);
- RegisterSmtpCMD("QUIT", smtp_quit, 0);
- RegisterSmtpCMD("RCPT", smtp_rcpt, 0);
- RegisterSmtpCMD("RSET", smtp_rset, 1);
-#ifdef HAVE_OPENSSL
- RegisterSmtpCMD("STARTTLS", smtp_starttls, 0);
-#endif
-
-
CtdlRegisterServiceHook(CtdlGetConfigInt("c_smtp_port"), /* SMTP MTA */
NULL,
smtp_mta_greeting,