X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmodules%2Fpop3%2Fserv_pop3.c;h=3058ef315f76cac0fa52a8ab9f3845a173c41db4;hb=e329db30593524cc2d8851a4500bac41f2340354;hp=ec98569c24c1d295718e5cd4a358fe01c9f35ecf;hpb=c793b3980c5c019211e077659847df7f09367a30;p=citadel.git diff --git a/citadel/modules/pop3/serv_pop3.c b/citadel/modules/pop3/serv_pop3.c index ec98569c2..3058ef315 100644 --- a/citadel/modules/pop3/serv_pop3.c +++ b/citadel/modules/pop3/serv_pop3.c @@ -1,21 +1,15 @@ /* * POP3 service for the Citadel system * - * Copyright (c) 1998-2009 by the citadel.org team + * Copyright (c) 1998-2018 by the citadel.org team * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. + * This program is open source software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * * Current status of standards conformance: * @@ -25,7 +19,6 @@ * there exist mail clients which insist on using it (such as Bynari * TradeMail, and certain versions of Eudora). * -> Capability detection via the method described in RFC2449 is implemented. - * */ #include "sysdep.h" @@ -65,37 +58,40 @@ #include "internet_addressing.h" #include "serv_pop3.h" #include "md5.h" - - - #include "ctdl_module.h" - /* * This cleanup function blows away the temporary memory and files used by * the POP3 server. */ -void pop3_cleanup_function(void) { +void pop3_cleanup_function(void) +{ + struct CitContext *CCC = CC; /* Don't do this stuff if this is not a POP3 session! */ - if (CC->h_command_function != pop3_command_loop) return; + if (CCC->h_command_function != pop3_command_loop) return; - syslog(LOG_DEBUG, "Performing POP3 cleanup hook"); - if (POP3->msgs != NULL) free(POP3->msgs); + struct citpop3 *pop3 = ((struct citpop3 *)CCC->session_specific_data); + syslog(LOG_DEBUG, "pop3: performing cleanup hook"); + if (pop3->msgs != NULL) { + free(pop3->msgs); + } - free(POP3); + free(pop3); } - /* * Here's where our POP3 session begins its happy day. */ -void pop3_greeting(void) { - strcpy(CC->cs_clientname, "POP3 session"); - CC->internal_pgm = 1; - CC->session_specific_data = malloc(sizeof(struct citpop3)); +void pop3_greeting(void) +{ + struct CitContext *CCC = CC; + + strcpy(CCC->cs_clientname, "POP3 session"); + CCC->internal_pgm = 1; + CCC->session_specific_data = malloc(sizeof(struct citpop3)); memset(POP3, 0, sizeof(struct citpop3)); cprintf("+OK Citadel POP3 server ready.\r\n"); @@ -105,28 +101,31 @@ void pop3_greeting(void) { /* * POP3S is just like POP3, except it goes crypto right away. */ -void pop3s_greeting(void) { +void pop3s_greeting(void) +{ + struct CitContext *CCC = CC; CtdlModuleStartCryptoMsgs(NULL, NULL, NULL); /* kill session if no crypto */ #ifdef HAVE_OPENSSL - if (!CC->redirect_ssl) CC->kill_me = 1; + if (!CCC->redirect_ssl) CCC->kill_me = KILLME_NO_CRYPTO; #else - CC->kill_me = 1; + CCC->kill_me = KILLME_NO_CRYPTO; #endif pop3_greeting(); } - /* * Specify user name (implements POP3 "USER" command) */ -void pop3_user(char *argbuf) { +void pop3_user(char *argbuf) +{ + struct CitContext *CCC = CC; char username[SIZ]; - if (CC->logged_in) { + if (CCC->logged_in) { cprintf("-ERR You are already logged in.\r\n"); return; } @@ -134,8 +133,7 @@ void pop3_user(char *argbuf) { strcpy(username, argbuf); striplt(username); - /* syslog(LOG_DEBUG, "Trying <%s>", username); */ - if (CtdlLoginExistingUser(NULL, username) == login_ok) { + if (CtdlLoginExistingUser(username) == login_ok) { cprintf("+OK Password required for %s\r\n", username); } else { @@ -144,11 +142,12 @@ void pop3_user(char *argbuf) { } - /* * Back end for pop3_grab_mailbox() */ -void pop3_add_message(long msgnum, void *userdata) { +void pop3_add_message(long msgnum, void *userdata) +{ + struct CitContext *CCC = CC; struct MetaData smi; ++POP3->num_msgs; @@ -165,38 +164,37 @@ void pop3_add_message(long msgnum, void *userdata) { */ GetMetaData(&smi, msgnum); if (smi.meta_rfc822_length <= 0L) { - CC->redirect_buffer = NewStrBufPlain(NULL, SIZ); - CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1, NULL, SUPPRESS_ENV_TO); - smi.meta_rfc822_length = StrLength(CC->redirect_buffer); - FreeStrBuf(&CC->redirect_buffer); /* TODO: WHEW, all this for just knowing the length???? */ + CCC->redirect_buffer = NewStrBufPlain(NULL, SIZ); + CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1, NULL, SUPPRESS_ENV_TO, NULL, NULL, NULL); + smi.meta_rfc822_length = StrLength(CCC->redirect_buffer); + FreeStrBuf(&CCC->redirect_buffer); PutMetaData(&smi); } POP3->msgs[POP3->num_msgs-1].rfc822_length = smi.meta_rfc822_length; } - /* * Open the inbox and read its contents. * (This should be called only once, by pop3_pass(), and returns the number * of messages in the inbox, or -1 for error) */ -int pop3_grab_mailbox(void) { +int pop3_grab_mailbox(void) +{ + struct CitContext *CCC = CC; visit vbuf; int i; - if (CtdlGetRoom(&CC->room, MAILROOM) != 0) return(-1); + if (CtdlGetRoom(&CCC->room, MAILROOM) != 0) return(-1); /* Load up the messages */ - CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, - pop3_add_message, NULL); + CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, pop3_add_message, NULL); /* Figure out which are old and which are new */ - CtdlGetRelationship(&vbuf, &CC->user, &CC->room); + CtdlGetRelationship(&vbuf, &CCC->user, &CCC->room); POP3->lastseen = (-1); if (POP3->num_msgs) for (i=0; inum_msgs; ++i) { - if (is_msg_in_sequence_set(vbuf.v_seen, - (POP3->msgs[POP3->num_msgs-1].msgnum) )) { + if (is_msg_in_sequence_set(vbuf.v_seen, (POP3->msgs[POP3->num_msgs-1].msgnum) )) { POP3->lastseen = i; } } @@ -204,15 +202,17 @@ int pop3_grab_mailbox(void) { return(POP3->num_msgs); } + void pop3_login(void) { + struct CitContext *CCC = CC; int msgs; msgs = pop3_grab_mailbox(); if (msgs >= 0) { cprintf("+OK %s is logged in (%d messages)\r\n", - CC->user.fullname, msgs); - syslog(LOG_NOTICE, "POP3 authenticated %s", CC->user.fullname); + CCC->user.fullname, msgs); + syslog(LOG_DEBUG, "pop3: authenticated %s", CCC->user.fullname); } else { cprintf("-ERR Can't open your mailbox\r\n"); @@ -230,7 +230,6 @@ void pop3_pass(char *argbuf) { safestrncpy(password, argbuf, sizeof password); striplt(password); - /* syslog(LOG_DEBUG, "Trying <%s>", password); */ if (CtdlTryPassword(password, strlen(password)) == pass_ok) { pop3_login(); } @@ -240,7 +239,6 @@ void pop3_pass(char *argbuf) { } - /* * list available msgs */ @@ -253,8 +251,7 @@ void pop3_list(char *argbuf) { /* "list one" mode */ if (which_one > 0) { if (which_one > POP3->num_msgs) { - cprintf("-ERR no such message, only %d are here\r\n", - POP3->num_msgs); + cprintf("-ERR no such message, only %d are here\r\n", POP3->num_msgs); return; } else if (POP3->msgs[which_one-1].deleted) { @@ -262,10 +259,7 @@ void pop3_list(char *argbuf) { return; } else { - cprintf("+OK %d %ld\r\n", - which_one, - (long)POP3->msgs[which_one-1].rfc822_length - ); + cprintf("+OK %d %ld\r\n", which_one, (long)POP3->msgs[which_one-1].rfc822_length); return; } } @@ -275,9 +269,7 @@ void pop3_list(char *argbuf) { cprintf("+OK Here's your mail:\r\n"); if (POP3->num_msgs > 0) for (i=0; inum_msgs; ++i) { if (! POP3->msgs[i].deleted) { - cprintf("%d %ld\r\n", - i+1, - (long)POP3->msgs[i].rfc822_length); + cprintf("%d %ld\r\n", i+1, (long)POP3->msgs[i].rfc822_length); } } cprintf(".\r\n"); @@ -304,7 +296,6 @@ void pop3_stat(char *argbuf) { } - /* * RETR command (fetch a message) */ @@ -323,9 +314,9 @@ void pop3_retr(char *argbuf) { } cprintf("+OK Message %d:\r\n", which_one); - CtdlOutputMsg(POP3->msgs[which_one - 1].msgnum, - MT_RFC822, HEADERS_ALL, 0, 1, NULL, - (ESC_DOT|SUPPRESS_ENV_TO) + CtdlOutputMsg(POP3->msgs[which_one - 1].msgnum, MT_RFC822, + HEADERS_ALL, 0, 1, NULL, + (ESC_DOT|SUPPRESS_ENV_TO), NULL, NULL, NULL ); cprintf(".\r\n"); } @@ -334,7 +325,9 @@ void pop3_retr(char *argbuf) { /* * TOP command (dumb way of fetching a partial message or headers-only) */ -void pop3_top(char *argbuf) { +void pop3_top(char *argbuf) +{ + struct CitContext *CCC = CC; int which_one; int lines_requested = 0; int lines_dumped = 0; @@ -355,10 +348,17 @@ void pop3_top(char *argbuf) { return; } - CC->redirect_buffer = NewStrBufPlain(NULL, SIZ); - CtdlOutputMsg(POP3->msgs[which_one - 1].msgnum, MT_RFC822, HEADERS_ALL, 0, 1, NULL, SUPPRESS_ENV_TO); - msgtext = CC->redirect_buffer; - CC->redirect_buffer = NULL; + CCC->redirect_buffer = NewStrBufPlain(NULL, SIZ); + + CtdlOutputMsg(POP3->msgs[which_one - 1].msgnum, + MT_RFC822, + HEADERS_ALL, + 0, 1, NULL, + SUPPRESS_ENV_TO, + NULL, NULL, NULL); + + msgtext = CCC->redirect_buffer; + CCC->redirect_buffer = NULL; cprintf("+OK Message %d:\r\n", which_one); @@ -413,7 +413,9 @@ void pop3_dele(char *argbuf) { /* Perform "UPDATE state" stuff */ -void pop3_update(void) { +void pop3_update(void) +{ + struct CitContext *CCC = CC; int i; visit vbuf; @@ -436,14 +438,11 @@ void pop3_update(void) { /* Set last read pointer */ if (POP3->num_msgs > 0) { - CtdlGetUserLock(&CC->user, CC->curr_user); - - CtdlGetRelationship(&vbuf, &CC->user, &CC->room); - snprintf(vbuf.v_seen, sizeof vbuf.v_seen, "*:%ld", - POP3->msgs[POP3->num_msgs-1].msgnum); - CtdlSetRelationship(&vbuf, &CC->user, &CC->room); - - CtdlPutUserLock(&CC->user); + CtdlLockGetCurrentUser(); + CtdlGetRelationship(&vbuf, &CCC->user, &CCC->room); + snprintf(vbuf.v_seen, sizeof vbuf.v_seen, "*:%ld", POP3->msgs[POP3->num_msgs-1].msgnum); + CtdlSetRelationship(&vbuf, &CCC->user, &CCC->room); + CtdlPutCurrentUserLock(); } } @@ -464,7 +463,6 @@ void pop3_rset(char *argbuf) { } - /* * LAST (Determine which message is the last unread message) */ @@ -474,8 +472,7 @@ void pop3_last(char *argbuf) { /* - * CAPA is a command which tells the client which POP3 extensions - * are supported. + * CAPA is a command which tells the client which POP3 extensions are supported. */ void pop3_capa(void) { cprintf("+OK Capability list follows\r\n" @@ -490,7 +487,6 @@ void pop3_capa(void) { } - /* * UIDL (Universal IDentifier Listing) is easy. Our 'unique' message * identifiers are simply the Citadel message numbers in the database. @@ -504,8 +500,7 @@ void pop3_uidl(char *argbuf) { /* "list one" mode */ if (which_one > 0) { if (which_one > POP3->num_msgs) { - cprintf("-ERR no such message, only %d are here\r\n", - POP3->num_msgs); + cprintf("-ERR no such message, only %d are here\r\n", POP3->num_msgs); return; } else if (POP3->msgs[which_one-1].deleted) { @@ -513,10 +508,7 @@ void pop3_uidl(char *argbuf) { return; } else { - cprintf("+OK %d %ld\r\n", - which_one, - POP3->msgs[which_one-1].msgnum - ); + cprintf("+OK %d %ld\r\n", which_one, POP3->msgs[which_one-1].msgnum); return; } } @@ -526,9 +518,7 @@ void pop3_uidl(char *argbuf) { cprintf("+OK Here's your mail:\r\n"); if (POP3->num_msgs > 0) for (i=0; inum_msgs; ++i) { if (! POP3->msgs[i].deleted) { - cprintf("%d %ld\r\n", - i+1, - POP3->msgs[i].msgnum); + cprintf("%d %ld\r\n", i+1, POP3->msgs[i].msgnum); } } cprintf(".\r\n"); @@ -545,39 +535,33 @@ void pop3_stls(void) char nosup_response[SIZ]; char error_response[SIZ]; - sprintf(ok_response, - "+OK Begin TLS negotiation now\r\n"); - sprintf(nosup_response, - "-ERR TLS not supported here\r\n"); - sprintf(error_response, - "-ERR Internal error\r\n"); + sprintf(ok_response, "+OK Begin TLS negotiation now\r\n"); + sprintf(nosup_response, "-ERR TLS not supported here\r\n"); + sprintf(error_response, "-ERR Internal error\r\n"); CtdlModuleStartCryptoMsgs(ok_response, nosup_response, error_response); } - - - - - /* * Main command loop for POP3 sessions. */ -void pop3_command_loop(void) { +void pop3_command_loop(void) +{ + struct CitContext *CCC = CC; char cmdbuf[SIZ]; - time(&CC->lastcmd); + time(&CCC->lastcmd); memset(cmdbuf, 0, sizeof cmdbuf); /* Clear it, just in case */ if (client_getln(cmdbuf, sizeof cmdbuf) < 1) { - syslog(LOG_ERR, "Client disconnected: ending session."); - CC->kill_me = 1; + syslog(LOG_INFO, "pop3: client disconnected; ending session."); + CCC->kill_me = KILLME_CLIENT_DISCONNECTED; return; } if (!strncasecmp(cmdbuf, "PASS", 4)) { - syslog(LOG_INFO, "POP3: PASS..."); + syslog(LOG_DEBUG, "pop3: PASS..."); } else { - syslog(LOG_INFO, "POP3: %s", cmdbuf); + syslog(LOG_DEBUG, "pop3: %s", cmdbuf); } while (strlen(cmdbuf) < 5) strcat(cmdbuf, " "); @@ -592,7 +576,7 @@ void pop3_command_loop(void) { else if (!strncasecmp(cmdbuf, "QUIT", 4)) { cprintf("+OK Goodbye...\r\n"); pop3_update(); - CC->kill_me = 1; + CCC->kill_me = KILLME_CLIENT_LOGGED_OUT; return; } @@ -610,13 +594,13 @@ void pop3_command_loop(void) { } #endif - else if (!CC->logged_in) { + else if (!CCC->logged_in) { cprintf("-ERR Not logged in.\r\n"); } - else if (CC->nologin) { + else if (CCC->nologin) { cprintf("-ERR System busy, try later.\r\n"); - CC->kill_me = 1; + CCC->kill_me = KILLME_NOLOGIN; } else if (!strncasecmp(cmdbuf, "LIST", 4)) { @@ -665,23 +649,23 @@ CTDL_MODULE_INIT(pop3) { if(!threading) { - CtdlRegisterServiceHook(config.c_pop3_port, + CtdlRegisterServiceHook(CtdlGetConfigInt("c_pop3_port"), NULL, pop3_greeting, pop3_command_loop, NULL, CitadelServicePop3); #ifdef HAVE_OPENSSL - CtdlRegisterServiceHook(config.c_pop3s_port, + CtdlRegisterServiceHook(CtdlGetConfigInt("c_pop3s_port"), NULL, pop3s_greeting, pop3_command_loop, NULL, CitadelServicePop3S); #endif - CtdlRegisterSessionHook(pop3_cleanup_function, EVT_STOP); + CtdlRegisterSessionHook(pop3_cleanup_function, EVT_STOP, PRIO_STOP + 30); } - /* return our Subversion id for the Log */ + /* return our module name for the log */ return "pop3"; }