Annotation of sbbs/src/sbbs3/mailsrvr.c, revision 1.1.1.1

1.1       root        1: /* mailsrvr.c */
                      2: 
                      3: /* Synchronet Mail (SMTP/POP3) server and sendmail threads */
                      4: 
                      5: /* $Id: mailsrvr.c,v 1.412 2006/12/29 01:23:05 rswindell Exp $ */
                      6: 
                      7: /****************************************************************************
                      8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
                      9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
                     10:  *                                                                                                                                                     *
                     11:  * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html         *
                     12:  *                                                                                                                                                     *
                     13:  * This program is free software; you can redistribute it and/or                       *
                     14:  * modify it under the terms of the GNU General Public License                         *
                     15:  * as published by the Free Software Foundation; either version 2                      *
                     16:  * of the License, or (at your option) any later version.                                      *
                     17:  * See the GNU General Public License for more details: gpl.txt or                     *
                     18:  * http://www.fsf.org/copyleft/gpl.html                                                                                *
                     19:  *                                                                                                                                                     *
                     20:  * Anonymous FTP access to the most recent released source is available at     *
                     21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
                     22:  *                                                                                                                                                     *
                     23:  * Anonymous CVS access to the development source and modification history     *
                     24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
                     25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
                     26:  *     (just hit return, no password is necessary)                                                     *
                     27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
                     28:  *                                                                                                                                                     *
                     29:  * For Synchronet coding style and modification guidelines, see                                *
                     30:  * http://www.synchro.net/source.html                                                                          *
                     31:  *                                                                                                                                                     *
                     32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
                     33:  * format) via e-mail to [email protected]                                                                      *
                     34:  *                                                                                                                                                     *
                     35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
                     36:  ****************************************************************************/
                     37: 
                     38: /* ANSI C Library headers */
                     39: #include <stdio.h>
                     40: #include <stdlib.h>                    /* ltoa in GNU C lib */
                     41: #include <stdarg.h>                    /* va_list */
                     42: #include <string.h>                    /* strrchr */
                     43: #include <ctype.h>                     /* isdigit */
                     44: #include <fcntl.h>                     /* Open flags */
                     45: #include <errno.h>                     /* errno */
                     46: 
                     47: /* Synchronet-specific headers */
                     48: #undef SBBS    /* this shouldn't be defined unless building sbbs.dll/libsbbs.so */
                     49: #include "sbbs.h"
                     50: #include "mailsrvr.h"
                     51: #include "mime.h"
                     52: #include "md5.h"
                     53: #include "crc32.h"
                     54: #include "base64.h"
                     55: #include "ini_file.h"
                     56: #include "netwrap.h"   /* getNameServerList() */
                     57: 
                     58: /* Constants */
                     59: #define FORWARD                        "forward:"
                     60: #define NO_FORWARD             "local:"
                     61: 
                     62: int dns_getmx(char* name, char* mx, char* mx2
                     63:                          ,DWORD intf, DWORD ip_addr, BOOL use_tcp, int timeout);
                     64: 
                     65: static char* pop_err   =       "-ERR";
                     66: static char* ok_rsp            =       "250 OK";
                     67: static char* auth_ok   =       "235 User Authenticated";
                     68: static char* sys_error =       "421 System error";
                     69: static char* sys_unavail=      "421 System unavailable, try again later";
                     70: static char* badarg_rsp =      "501 Bad argument";
                     71: static char* badseq_rsp        =       "503 Bad sequence of commands";
                     72: static char* badauth_rsp=      "535 Authentication failure";
                     73: static char* badrsp_err        =       "%s replied with:\r\n\"%s\"\r\n"
                     74:                                                        "instead of the expected reply:\r\n\"%s ...\"";
                     75: 
                     76: #define TIMEOUT_THREAD_WAIT            60              /* Seconds */
                     77: #define DNSBL_THROTTLE_VALUE   5000    /* Milliseconds */
                     78: 
                     79: #define STATUS_WFC     "Listening"
                     80: 
                     81: static mail_startup_t* startup=NULL;
                     82: static scfg_t  scfg;
                     83: static SOCKET  server_socket=INVALID_SOCKET;
                     84: static SOCKET  pop3_socket=INVALID_SOCKET;
                     85: static DWORD   active_clients=0;
                     86: static int             active_sendmail=0;
                     87: static DWORD   thread_count=0;
                     88: static BOOL            sendmail_running=FALSE;
                     89: static DWORD   sockets=0;
                     90: static DWORD   served=0;
                     91: static BOOL            terminate_server=FALSE;
                     92: static BOOL            terminate_sendmail=FALSE;
                     93: static sem_t   sendmail_wakeup_sem;
                     94: static char            revision[16];
                     95: static time_t  uptime;
                     96: static str_list_t recycle_semfiles;
                     97: static str_list_t shutdown_semfiles;
                     98: static int             mailproc_count;
                     99: 
                    100: struct mailproc {
                    101:        char            cmdline[INI_MAX_VALUE_LEN];
                    102:        str_list_t      to;
                    103:        BOOL            passthru;
                    104:        BOOL            native;
                    105: } *mailproc_list;
                    106: 
                    107: typedef struct {
                    108:        SOCKET                  socket;
                    109:        SOCKADDR_IN             client_addr;
                    110: } smtp_t,pop3_t;
                    111: 
                    112: static int lprintf(int level, char *fmt, ...)
                    113: {
                    114:        va_list argptr;
                    115:        char sbuf[1024];
                    116: 
                    117:     if(startup==NULL || startup->lputs==NULL)
                    118:         return(0);
                    119: 
                    120:        va_start(argptr,fmt);
                    121:     vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
                    122:        sbuf[sizeof(sbuf)-1]=0;
                    123:     va_end(argptr);
                    124:     return(startup->lputs(startup->cbdata,level,sbuf));
                    125: }
                    126: 
                    127: #ifdef _WINSOCKAPI_
                    128: 
                    129: static WSADATA WSAData;
                    130: #define SOCKLIB_DESC WSAData.szDescription
                    131: static BOOL WSAInitialized=FALSE;
                    132: 
                    133: static BOOL winsock_startup(void)
                    134: {
                    135:        int             status;             /* Status Code */
                    136: 
                    137:     if((status = WSAStartup(MAKEWORD(1,1), &WSAData))==0) {
                    138:                lprintf(LOG_INFO,"%s %s",WSAData.szDescription, WSAData.szSystemStatus);
                    139:                WSAInitialized=TRUE;
                    140:                return (TRUE);
                    141:        }
                    142: 
                    143:     lprintf(LOG_CRIT,"!WinSock startup ERROR %d", status);
                    144:        return (FALSE);
                    145: }
                    146: 
                    147: #else /* No WINSOCK */
                    148: 
                    149: #define winsock_startup()      (TRUE)
                    150: #define SOCKLIB_DESC NULL
                    151: 
                    152: #endif
                    153: 
                    154: static void update_clients(void)
                    155: {
                    156:        if(startup!=NULL && startup->clients!=NULL)
                    157:                startup->clients(startup->cbdata,active_clients+active_sendmail);
                    158: }
                    159: 
                    160: static void client_on(SOCKET sock, client_t* client, BOOL update)
                    161: {
                    162:        if(startup!=NULL && startup->client_on!=NULL)
                    163:                startup->client_on(startup->cbdata,TRUE,sock,client,update);
                    164: }
                    165: 
                    166: static void client_off(SOCKET sock)
                    167: {
                    168:        if(startup!=NULL && startup->client_on!=NULL)
                    169:                startup->client_on(startup->cbdata,FALSE,sock,NULL,FALSE);
                    170: }
                    171: 
                    172: static void thread_up(BOOL setuid)
                    173: {
                    174:        thread_count++;
                    175:        if(startup!=NULL && startup->thread_up!=NULL)
                    176:                startup->thread_up(startup->cbdata,TRUE,setuid);
                    177: }
                    178: 
                    179: static void thread_down(void)
                    180: {
                    181:        if(thread_count>0)
                    182:                thread_count--;
                    183:        if(startup!=NULL && startup->thread_up!=NULL)
                    184:                startup->thread_up(startup->cbdata,FALSE,FALSE);
                    185: }
                    186: 
                    187: SOCKET mail_open_socket(int type, const char* protocol)
                    188: {
                    189:        char    error[256];
                    190:        char    section[128];
                    191:        SOCKET  sock;
                    192: 
                    193:        sock=socket(AF_INET, type, IPPROTO_IP);
                    194:        if(sock!=INVALID_SOCKET && startup!=NULL && startup->socket_open!=NULL) 
                    195:                startup->socket_open(startup->cbdata,TRUE);
                    196:        if(sock!=INVALID_SOCKET) {
                    197:                SAFEPRINTF(section,"mail|%s",protocol);
                    198:                if(set_socket_options(&scfg, sock, section, error, sizeof(error)))
                    199:                        lprintf(LOG_ERR,"%04d !ERROR %s",sock,error);
                    200: 
                    201:                sockets++;
                    202: #if 0 /*def _DEBUG */
                    203:                lprintf(LOG_DEBUG,"%04d Socket opened (%d sockets in use)",sock,sockets);
                    204: #endif
                    205:        }
                    206:        return(sock);
                    207: }
                    208: 
                    209: int mail_close_socket(SOCKET sock)
                    210: {
                    211:        int             result;
                    212: 
                    213:        if(sock==INVALID_SOCKET)
                    214:                return(-1);
                    215: 
                    216:        shutdown(sock,SHUT_RDWR);       /* required on Unix */
                    217:        result=closesocket(sock);
                    218:        if(startup!=NULL && startup->socket_open!=NULL)
                    219:                startup->socket_open(startup->cbdata,FALSE);
                    220:        sockets--;
                    221:        if(result!=0) {
                    222:                if(ERROR_VALUE!=ENOTSOCK)
                    223:                        lprintf(LOG_ERR,"%04d !ERROR %d closing socket",sock, ERROR_VALUE);
                    224:        }
                    225: #if 0 /*def _DEBUG */
                    226:        else 
                    227:                lprintf(LOG_DEBUG,"%04d Socket closed (%d sockets in use)",sock,sockets);
                    228: #endif
                    229: 
                    230:        return(result);
                    231: }
                    232: 
                    233: static void status(char* str)
                    234: {
                    235:        if(startup!=NULL && startup->status!=NULL)
                    236:            startup->status(startup->cbdata,str);
                    237: }
                    238: 
                    239: int sockprintf(SOCKET sock, char *fmt, ...)
                    240: {
                    241:        int             len;
                    242:        int             maxlen;
                    243:        int             result;
                    244:        va_list argptr;
                    245:        char    sbuf[1024];
                    246:        fd_set  socket_set;
                    247:        struct timeval tv;
                    248: 
                    249:     va_start(argptr,fmt);
                    250:     len=vsnprintf(sbuf,maxlen=sizeof(sbuf)-2,fmt,argptr);
                    251:     va_end(argptr);
                    252: 
                    253:        if(len<0 || len > maxlen) /* format error or output truncated */
                    254:                len=maxlen;
                    255:        if(startup->options&MAIL_OPT_DEBUG_TX)
                    256:                lprintf(LOG_DEBUG,"%04d TX: %.*s", sock, len, sbuf);
                    257:        memcpy(sbuf+len,"\r\n",2);
                    258:        len+=2;
                    259: 
                    260:        if(sock==INVALID_SOCKET) {
                    261:                lprintf(LOG_WARNING,"!INVALID SOCKET in call to sockprintf");
                    262:                return(0);
                    263:        }
                    264: 
                    265:        /* Check socket for writability (using select) */
                    266:        tv.tv_sec=300;
                    267:        tv.tv_usec=0;
                    268: 
                    269:        FD_ZERO(&socket_set);
                    270:        FD_SET(sock,&socket_set);
                    271: 
                    272:        if((result=select(sock+1,NULL,&socket_set,NULL,&tv))<1) {
                    273:                if(result==0)
                    274:                        lprintf(LOG_NOTICE,"%04d !TIMEOUT selecting socket for send"
                    275:                                ,sock);
                    276:                else
                    277:                        lprintf(LOG_NOTICE,"%04d !ERROR %d selecting socket for send"
                    278:                                ,sock, ERROR_VALUE);
                    279:                return(0);
                    280:        }
                    281: 
                    282:        while((result=sendsocket(sock,sbuf,len))!=len) {
                    283:                if(result==SOCKET_ERROR) {
                    284:                        if(ERROR_VALUE==EWOULDBLOCK) {
                    285:                                YIELD();
                    286:                                continue;
                    287:                        }
                    288:                        if(ERROR_VALUE==ECONNRESET) 
                    289:                                lprintf(LOG_NOTICE,"%04d Connection reset by peer on send",sock);
                    290:                        else if(ERROR_VALUE==ECONNABORTED) 
                    291:                                lprintf(LOG_NOTICE,"%04d Connection aborted by peer on send",sock);
                    292:                        else
                    293:                                lprintf(LOG_NOTICE,"%04d !ERROR %d sending on socket",sock,ERROR_VALUE);
                    294:                        return(0);
                    295:                }
                    296:                lprintf(LOG_WARNING,"%04d !ERROR: short send on socket: %d instead of %d",sock,result,len);
                    297:        }
                    298:        return(len);
                    299: }
                    300: 
                    301: static time_t checktime(void)
                    302: {
                    303:        struct tm tm;
                    304: 
                    305:     memset(&tm,0,sizeof(tm));
                    306:     tm.tm_year=94;
                    307:     tm.tm_mday=1;
                    308:     return(mktime(&tm)-0x2D24BD00L);
                    309: }
                    310: 
                    311: static void recverror(SOCKET socket, int rd, int line)
                    312: {
                    313:        if(rd==0) 
                    314:                lprintf(LOG_NOTICE,"%04d Socket closed by peer on receive (line %d)"
                    315:                        ,socket, line);
                    316:        else if(rd==SOCKET_ERROR) {
                    317:                if(ERROR_VALUE==ECONNRESET) 
                    318:                        lprintf(LOG_NOTICE,"%04d Connection reset by peer on receive (line %d)"
                    319:                                ,socket, line);
                    320:                else if(ERROR_VALUE==ECONNABORTED) 
                    321:                        lprintf(LOG_NOTICE,"%04d Connection aborted by peer on receive (line %d)"
                    322:                                ,socket, line);
                    323:                else
                    324:                        lprintf(LOG_NOTICE,"%04d !ERROR %d receiving on socket (line %d)"
                    325:                                ,socket, ERROR_VALUE, line);
                    326:        } else
                    327:                lprintf(LOG_WARNING,"%04d !ERROR: recv on socket returned unexpected value: %d (line %d)"
                    328:                        ,socket, rd, line);
                    329: }
                    330: 
                    331: 
                    332: static int sockreadline(SOCKET socket, char* buf, int len)
                    333: {
                    334:        char    ch;
                    335:        int             i,rd=0;
                    336:        fd_set  socket_set;
                    337:        struct  timeval tv;
                    338:        time_t  start;
                    339: 
                    340:        buf[0]=0;
                    341: 
                    342:        start=time(NULL);
                    343: 
                    344:        if(socket==INVALID_SOCKET) {
                    345:                lprintf(LOG_WARNING,"!INVALID SOCKET in call to sockreadline");
                    346:                return(-1);
                    347:        }
                    348:        
                    349:        while(rd<len-1) {
                    350: 
                    351:                if(server_socket==INVALID_SOCKET || terminate_server) {
                    352:                        lprintf(LOG_WARNING,"%04d !ABORTING sockreadline",socket);
                    353:                        return(-1);
                    354:                }
                    355: 
                    356:                tv.tv_sec=startup->max_inactivity;
                    357:                tv.tv_usec=0;
                    358: 
                    359:                FD_ZERO(&socket_set);
                    360:                FD_SET(socket,&socket_set);
                    361: 
                    362:                i=select(socket+1,&socket_set,NULL,NULL,&tv);
                    363: 
                    364:                if(i<1) {
                    365:                        if(i==0) {
                    366:                                if((time(NULL)-start)>startup->max_inactivity) {
                    367:                                        lprintf(LOG_WARNING,"%04d !SOCKET INACTIVE",socket);
                    368:                                        return(-1);
                    369:                                }
                    370:                                continue;
                    371:                        }
                    372:                        recverror(socket,i,__LINE__);
                    373:                        return(-1);
                    374:                }
                    375:                i=recv(socket, &ch, 1, 0);
                    376:                if(i<1) {
                    377:                        recverror(socket,i,__LINE__);
                    378:                        return(-1);
                    379:                }
                    380:                if(ch=='\n' /* && rd>=1 */ ) { /* Mar-9-2003: terminate on sole LF */
                    381:                        break;
                    382:                }       
                    383:                buf[rd++]=ch;
                    384:        }
                    385:        if(rd>0 && buf[rd-1]=='\r')
                    386:                rd--;
                    387:        buf[rd]=0;
                    388:        
                    389:        return(rd);
                    390: }
                    391: 
                    392: static BOOL sockgetrsp(SOCKET socket, char* rsp, char *buf, int len)
                    393: {
                    394:        int rd;
                    395: 
                    396:        while(1) {
                    397:                rd = sockreadline(socket, buf, len);
                    398:                if(rd<1) 
                    399:                        return(FALSE);
                    400:                if(buf[3]=='-') { /* Multi-line response */
                    401:                        if(startup->options&MAIL_OPT_DEBUG_RX_RSP) 
                    402:                                lprintf(LOG_DEBUG,"%04d RX: %s",socket,buf);
                    403:                        continue;
                    404:                }
                    405:                if(rsp!=NULL && strnicmp(buf,rsp,strlen(rsp))) {
                    406:                        lprintf(LOG_WARNING,"%04d !INVALID RESPONSE: '%s' Expected: '%s'", socket, buf, rsp);
                    407:                        return(FALSE);
                    408:                }
                    409:                break;
                    410:        }
                    411:        if(startup->options&MAIL_OPT_DEBUG_RX_RSP) 
                    412:                lprintf(LOG_DEBUG,"%04d RX: %s",socket,buf);
                    413:        return(TRUE);
                    414: }
                    415: 
                    416: #define MAX_LINE_LEN   1000
                    417: 
                    418: static ulong sockmimetext(SOCKET socket, smbmsg_t* msg, char* msgtxt, ulong maxlines
                    419:                                                  ,str_list_t file_list, char* mime_boundary)
                    420: {
                    421:        char            toaddr[256]="";
                    422:        char            fromaddr[256]="";
                    423:        char            fromhost[256];
                    424:        char            date[64];
                    425:        char*           p;
                    426:        char*           tp;
                    427:        char*           content_type=NULL;
                    428:        int                     i;
                    429:        int                     s;
                    430:        ulong           lines;
                    431: 
                    432:        /* HEADERS (in recommended order per RFC822 4.1) */
                    433:        if(!sockprintf(socket,"Date: %s",msgdate(msg->hdr.when_written,date)))
                    434:                return(0);
                    435: 
                    436:        if((p=smb_get_hfield(msg,RFC822FROM,NULL))!=NULL)
                    437:                s=sockprintf(socket,"From: %s",p);      /* use original RFC822 header field */
                    438:        else {
                    439:                if(msg->from_net.type==NET_QWK && msg->from_net.addr!=NULL)
                    440:                        SAFEPRINTF2(fromaddr,"%s!%s"
                    441:                                ,(char*)msg->from_net.addr
                    442:                                ,usermailaddr(&scfg,fromhost,msg->from));
                    443:                else if(msg->from_net.type==NET_FIDO && msg->from_net.addr!=NULL)
                    444:                        SAFECOPY(fromaddr,smb_faddrtoa((faddr_t *)msg->from_net.addr,NULL));
                    445:                else if(msg->from_net.type!=NET_NONE && msg->from_net.addr!=NULL)
                    446:                        SAFECOPY(fromaddr,(char*)msg->from_net.addr);
                    447:                else 
                    448:                        usermailaddr(&scfg,fromaddr,msg->from);
                    449:                if(fromaddr[0]=='<')
                    450:                        s=sockprintf(socket,"From: \"%s\" %s",msg->from,fromaddr);
                    451:                else
                    452:                        s=sockprintf(socket,"From: \"%s\" <%s>",msg->from,fromaddr);
                    453:        }
                    454:        if(!s)
                    455:                return(0);
                    456: 
                    457:        if(msg->from_org!=NULL || msg->from_net.type==NET_NONE)
                    458:                if(!sockprintf(socket,"Organization: %s"
                    459:                        ,msg->from_org==NULL ? scfg.sys_name : msg->from_org))
                    460:                        return(0);
                    461: 
                    462:        if(!sockprintf(socket,"Subject: %s",msg->subj))
                    463:                return(0);
                    464: 
                    465:        if((p=smb_get_hfield(msg,RFC822TO,NULL))!=NULL)
                    466:                s=sockprintf(socket,"To: %s",p);        /* use original RFC822 header field */
                    467:        else {
                    468:                if(strchr(msg->to,'@')!=NULL || msg->to_net.addr==NULL)
                    469:                        s=sockprintf(socket,"To: %s",msg->to);  /* Avoid double-@ */
                    470:                else if(msg->to_net.type==NET_INTERNET || msg->to_net.type==NET_QWK) {
                    471:                        if(strchr((char*)msg->to_net.addr,'<')!=NULL)
                    472:                                s=sockprintf(socket,"To: %s",(char*)msg->to_net.addr);
                    473:                        else
                    474:                                s=sockprintf(socket,"To: \"%s\" <%s>",msg->to,(char*)msg->to_net.addr);
                    475:                } else {
                    476:                        usermailaddr(&scfg,toaddr,msg->to);
                    477:                        s=sockprintf(socket,"To: \"%s\" <%s>",msg->to,toaddr);
                    478:                }
                    479:        }
                    480:        if(!s)
                    481:                return(0);
                    482:        if((p=smb_get_hfield(msg,RFC822REPLYTO,NULL))==NULL) {
                    483:                if(msg->replyto_net.type==NET_INTERNET)
                    484:                        p=msg->replyto_net.addr;
                    485:                else if(msg->replyto!=NULL)
                    486:                        p=msg->replyto;
                    487:        }
                    488:        if(p!=NULL)
                    489:                s=sockprintf(socket,"Reply-To: %s",p);  /* use original RFC822 header field */
                    490:        if(!s)
                    491:                return(0);
                    492:        if(!sockprintf(socket,"Message-ID: %s",get_msgid(&scfg,INVALID_SUB,msg)))
                    493:                return(0);
                    494:        if(msg->reply_id!=NULL)
                    495:                if(!sockprintf(socket,"In-Reply-To: %s",msg->reply_id))
                    496:                        return(0);
                    497: 
                    498:     for(i=0;i<msg->total_hfields;i++) { 
                    499:                if(msg->hfield[i].type==RFC822HEADER) { 
                    500:                        if(strnicmp((char*)msg->hfield_dat[i],"Content-Type:",13)==0)
                    501:                                content_type=msg->hfield_dat[i];
                    502:                        if(!sockprintf(socket,"%s",(char*)msg->hfield_dat[i]))
                    503:                                return(0);
                    504:         }
                    505:     }
                    506:        /* Default MIME Content-Type for non-Internet messages */
                    507:        if(msg->from_net.type!=NET_INTERNET && content_type==NULL && startup->default_charset[0]) {
                    508:                /* No content-type specified, so assume IBM code-page 437 (full ex-ASCII) */
                    509:                sockprintf(socket,"Content-Type: text/plain; charset=%s", startup->default_charset);
                    510:                sockprintf(socket,"Content-Transfer-Encoding: 8bit");
                    511:        }
                    512: 
                    513:        if(strListCount(file_list)) {   /* File attachments */
                    514:         mimeheaders(socket,mime_boundary);
                    515:         sockprintf(socket,"");
                    516:         mimeblurb(socket,mime_boundary);
                    517:         sockprintf(socket,"");
                    518:         mimetextpartheader(socket,mime_boundary);
                    519:        }
                    520:        if(!sockprintf(socket,""))      /* Header Terminator */
                    521:                return(0);
                    522: 
                    523:        /* MESSAGE BODY */
                    524:        lines=0;
                    525: #if 0  /* This is now handled in smb_getmsgtxt() */
                    526:     for(i=0;i<msg->total_hfields;i++) {                        /* delivery failure notification? */
                    527:                if(msg->hfield[i].type==SMTPSYSMSG || msg->hfield[i].type==SMB_COMMENT) { 
                    528:                        if(!sockprintf(socket,"%s",(char*)msg->hfield_dat[i]))
                    529:                                return(0);
                    530:                        lines++;
                    531:                }
                    532:     }
                    533: #endif
                    534:        p=msgtxt;
                    535:        while(*p && lines<maxlines) {
                    536:                tp=strchr(p,'\n');
                    537:                if(tp) {
                    538:                        if(tp-p>MAX_LINE_LEN)
                    539:                                tp=p+MAX_LINE_LEN;
                    540:                        *tp=0;
                    541:                }
                    542:                truncsp(p);     /* Takes care of '\r' or spaces */
                    543:                if(*p=='.')
                    544:                        i=sockprintf(socket,".%.*s",MAX_LINE_LEN,p);
                    545:                else
                    546:                        i=sockprintf(socket,"%.*s",MAX_LINE_LEN,p);
                    547:                if(!i)
                    548:                        break;
                    549:                if(tp==NULL)
                    550:                        break;
                    551:                p=tp+1;
                    552:                lines++;
                    553:                /* release time-slices every x lines */
                    554:                if(startup->lines_per_yield
                    555:                        && !(lines%startup->lines_per_yield))   
                    556:                        YIELD();
                    557:        }
                    558:        if(file_list!=NULL) {
                    559:                for(i=0;file_list[i];i++) { 
                    560:                        sockprintf(socket,"");
                    561:                        lprintf(LOG_INFO,"%04u MIME Encoding and sending %s",socket,file_list[i]);
                    562:                        if(!mimeattach(socket,mime_boundary,file_list[i]))
                    563:                                lprintf(LOG_ERR,"%04u !ERROR opening/encoding/sending %s",socket,file_list[i]);
                    564:                        else {
                    565:                                endmime(socket,mime_boundary);
                    566:                                if(msg->hdr.auxattr&MSG_KILLFILE)
                    567:                                        if(remove(file_list[i])!=0)
                    568:                                                lprintf(LOG_WARNING,"%04u !ERROR %d removing %s",socket,errno,file_list[i]);
                    569:                        }
                    570:                }
                    571:        }
                    572:     sockprintf(socket,".");    /* End of text */
                    573:        return(lines);
                    574: }
                    575: 
                    576: static ulong sockmsgtxt(SOCKET socket, smbmsg_t* msg, char* msgtxt, ulong maxlines)
                    577: {
                    578:        char            filepath[MAX_PATH+1];
                    579:        ulong           retval;
                    580:        char*           boundary=NULL;
                    581:        unsigned        i;
                    582:        str_list_t      file_list=NULL;
                    583:        str_list_t      split;
                    584: 
                    585:        if(msg->hdr.auxattr&MSG_FILEATTACH) {
                    586: 
                    587:                boundary = mimegetboundary();
                    588:                file_list = strListInit();
                    589: 
                    590:                /* Parse header fields */
                    591:                for(i=0;i<msg->total_hfields;i++)
                    592:                if(msg->hfield[i].type==FILEATTACH) 
                    593:                                strListPush(&file_list,(char*)msg->hfield_dat[i]);
                    594: 
                    595:                /* Parse subject (if necessary) */
                    596:                if(!strListCount(file_list)) {  /* filename(s) stored in subject */
                    597:                        split=strListSplitCopy(NULL,msg->subj," ");
                    598:                        if(split!=NULL) {
                    599:                                for(i=0;split[i];i++) {
                    600:                                        if(msg->idx.to!=0)
                    601:                                                SAFEPRINTF3(filepath,"%sfile/%04u.in/%s"
                    602:                                                        ,scfg.data_dir,msg->idx.to,getfname(truncsp(split[i])));
                    603:                                        else
                    604:                                                SAFEPRINTF3(filepath,"%sfile/%04u.out/%s"
                    605:                                                        ,scfg.data_dir,msg->idx.from,getfname(truncsp(split[i])));
                    606:                                        strListPush(&file_list,filepath);
                    607:                                }
                    608:                                strListFree(&split);
                    609:                        }
                    610:                }
                    611:     }
                    612: 
                    613:        retval = sockmimetext(socket,msg,msgtxt,maxlines,file_list,boundary);
                    614: 
                    615:        strListFree(&file_list);
                    616: 
                    617:        if(boundary!=NULL)
                    618:                free(boundary);
                    619: 
                    620:        return(retval);
                    621: }
                    622: 
                    623: static u_long resolve_ip(char *inaddr)
                    624: {
                    625:        char*           p;
                    626:        char*           addr;
                    627:        char            buf[128];
                    628:        HOSTENT*        host;
                    629: 
                    630:        SAFECOPY(buf,inaddr);
                    631:        addr=buf;
                    632:        if(*addr=='[' && *(p=lastchar(addr))==']') { /* Support [ip_address] notation */
                    633:                addr++;
                    634:                *p=0;
                    635:        }
                    636: 
                    637:        if(*addr==0)
                    638:                return((u_long)INADDR_NONE);
                    639: 
                    640:        for(p=addr;*p;p++)
                    641:                if(*p!='.' && !isdigit(*p))
                    642:                        break;
                    643:        if(!(*p))
                    644:                return(inet_addr(addr));
                    645: 
                    646:        if((host=gethostbyname(inaddr))==NULL) {
                    647:                lprintf(LOG_WARNING,"0000 !ERROR resolving hostname: %s",inaddr);
                    648:                return((u_long)INADDR_NONE);
                    649:        }
                    650:        return(*((ulong*)host->h_addr_list[0]));
                    651: }
                    652: 
                    653: 
                    654: static void pop3_thread(void* arg)
                    655: {
                    656:        char*           p;
                    657:        char            str[128];
                    658:        char            buf[512];
                    659:        char            host_name[128];
                    660:        char            host_ip[64];
                    661:        char            username[LEN_ALIAS+1];
                    662:        char            password[LEN_PASS+1];
                    663:        char            challenge[256];
                    664:        char            digest[MD5_DIGEST_SIZE];
                    665:        char*           response="";
                    666:        char*           msgtxt;
                    667:        int                     i;
                    668:        int                     rd;
                    669:        BOOL            activity=FALSE;
                    670:        BOOL            apop=FALSE;
                    671:        long            l;
                    672:        ulong           lines;
                    673:        ulong           lines_sent;
                    674:        long            msgs,msgnum;
                    675:        ulong           bytes;
                    676:        SOCKET          socket;
                    677:        HOSTENT*        host;
                    678:        smb_t           smb;
                    679:        smbmsg_t        msg;
                    680:        user_t          user;
                    681:        client_t        client;
                    682:        mail_t*         mail;
                    683:        pop3_t          pop3=*(pop3_t*)arg;
                    684: 
                    685:        SetThreadName("POP3 Thread");
                    686:        thread_up(TRUE /* setuid */);
                    687: 
                    688:        free(arg);
                    689: 
                    690:        socket=pop3.socket;
                    691: 
                    692:        if(startup->options&MAIL_OPT_DEBUG_POP3)
                    693:                lprintf(LOG_DEBUG,"%04d POP3 session thread started", socket);
                    694: 
                    695: #ifdef _WIN32
                    696:        if(startup->pop3_sound[0] && !(startup->options&MAIL_OPT_MUTE)) 
                    697:                PlaySound(startup->pop3_sound, NULL, SND_ASYNC|SND_FILENAME);
                    698: #endif
                    699: 
                    700:        SAFECOPY(host_ip,inet_ntoa(pop3.client_addr.sin_addr));
                    701: 
                    702:        if(startup->options&MAIL_OPT_DEBUG_POP3)
                    703:                lprintf(LOG_INFO,"%04d POP3 connection accepted from: %s port %u"
                    704:                        ,socket, host_ip, ntohs(pop3.client_addr.sin_port));
                    705: 
                    706:        if(startup->options&MAIL_OPT_NO_HOST_LOOKUP)
                    707:                host=NULL;
                    708:        else
                    709:                host=gethostbyaddr((char *)&pop3.client_addr.sin_addr
                    710:                        ,sizeof(pop3.client_addr.sin_addr),AF_INET);
                    711: 
                    712:        if(host!=NULL && host->h_name!=NULL)
                    713:                SAFECOPY(host_name,host->h_name);
                    714:        else
                    715:                strcpy(host_name,"<no name>");
                    716: 
                    717:        if(startup->options&MAIL_OPT_DEBUG_POP3
                    718:                && !(startup->options&MAIL_OPT_NO_HOST_LOOKUP)) {
                    719:                lprintf(LOG_INFO,"%04d POP3 Hostname: %s", socket, host_name);
                    720:                for(i=0;host!=NULL && host->h_aliases!=NULL && host->h_aliases[i]!=NULL;i++)
                    721:                        lprintf(LOG_INFO,"%04d POP3 HostAlias: %s", socket, host->h_aliases[i]);
                    722:        }
                    723: 
                    724:        if(trashcan(&scfg,host_ip,"ip")) {
                    725:                lprintf(LOG_NOTICE,"%04d !POP3 BLOCKED CLIENT IP ADDRESS: %s"
                    726:                        ,socket, host_ip);
                    727:                sockprintf(socket,"-ERR Access denied.");
                    728:                mail_close_socket(socket);
                    729:                thread_down();
                    730:                return;
                    731:        }
                    732: 
                    733:        if(trashcan(&scfg,host_name,"host")) {
                    734:                lprintf(LOG_NOTICE,"%04d !POP3 BLOCKED CLIENT HOSTNAME: %s"
                    735:                        ,socket, host_name);
                    736:                sockprintf(socket,"-ERR Access denied.");
                    737:                mail_close_socket(socket);
                    738:                thread_down();
                    739:                return;
                    740:        }
                    741: 
                    742:        active_clients++, update_clients();
                    743: 
                    744:        /* Initialize client display */
                    745:        client.size=sizeof(client);
                    746:        client.time=time(NULL);
                    747:        SAFECOPY(client.addr,host_ip);
                    748:        SAFECOPY(client.host,host_name);
                    749:        client.port=ntohs(pop3.client_addr.sin_port);
                    750:        client.protocol="POP3";
                    751:        client.user="<unknown>";
                    752:        client_on(socket,&client,FALSE /* update */);
                    753: 
                    754:        SAFEPRINTF(str,"POP3: %s", host_ip);
                    755:        status(str);
                    756: 
                    757:        mail=NULL;
                    758: 
                    759:        do {
                    760:                memset(&smb,0,sizeof(smb));
                    761:                memset(&msg,0,sizeof(msg));
                    762:                memset(&user,0,sizeof(user));
                    763:                password[0]=0;
                    764: 
                    765:                srand(time(NULL) ^ (DWORD)GetCurrentThreadId());        /* seed random number generator */
                    766:                rand(); /* throw-away first result */
                    767:                safe_snprintf(challenge,sizeof(challenge),"<%x%x%lx%lx@%.128s>"
                    768:                        ,rand(),socket,(ulong)time(NULL),clock(),startup->host_name);
                    769: 
                    770:                sockprintf(socket,"+OK Synchronet POP3 Server %s-%s Ready %s"
                    771:                        ,revision,PLATFORM_DESC,challenge);
                    772: 
                    773:                /* Requires USER command first */
                    774:                for(i=3;i;i--) {
                    775:                        if(!sockgetrsp(socket,NULL,buf,sizeof(buf)))
                    776:                                break;
                    777:                        if(!strnicmp(buf,"USER ",5))
                    778:                                break;
                    779:                        if(!strnicmp(buf,"APOP ",5)) {
                    780:                                apop=TRUE;
                    781:                                break;
                    782:                        }
                    783:                        sockprintf(socket,"-ERR USER or APOP command expected");
                    784:                }
                    785:                if(!i || buf[0]==0)     /* no USER or APOP command received */
                    786:                        break;
                    787: 
                    788:                p=buf+5;
                    789:                SKIP_WHITESPACE(p);
                    790:                if(apop) {
                    791:                        if((response=strrchr(p,' '))!=NULL)
                    792:                                *(response++)=0;
                    793:                        else
                    794:                                response=p;
                    795:                }
                    796:                SAFECOPY(username,p);
                    797:                if(!apop) {
                    798:                        sockprintf(socket,"+OK");
                    799:                        if(!sockgetrsp(socket,"PASS ",buf,sizeof(buf))) {
                    800:                                sockprintf(socket,"-ERR PASS command expected");
                    801:                                break;
                    802:                        }
                    803:                        p=buf+5;
                    804:                        SKIP_WHITESPACE(p);
                    805:                        SAFECOPY(password,p);
                    806:                }
                    807:                user.number=matchuser(&scfg,username,FALSE /*sysop_alias*/);
                    808:                if(!user.number) {
                    809:                        if(scfg.sys_misc&SM_ECHO_PW)
                    810:                                lprintf(LOG_WARNING,"%04d !POP3 UNKNOWN USER: %s (password: %s)"
                    811:                                        ,socket, username, password);
                    812:                        else
                    813:                                lprintf(LOG_WARNING,"%04d !POP3 UNKNOWN USER: %s"
                    814:                                        ,socket, username);
                    815:                        sockprintf(socket,pop_err);
                    816:                        break;
                    817:                }
                    818:                if((i=getuserdat(&scfg, &user))!=0) {
                    819:                        lprintf(LOG_ERR,"%04d !POP3 ERROR %d getting data on user (%s)"
                    820:                                ,socket, i, username);
                    821:                        sockprintf(socket, pop_err);
                    822:                        break;
                    823:                }
                    824:                if(user.misc&(DELETED|INACTIVE)) {
                    825:                        lprintf(LOG_WARNING,"%04d !POP3 DELETED or INACTIVE user #%u (%s)"
                    826:                                ,socket, user.number, username);
                    827:                        sockprintf(socket, pop_err);
                    828:                        break;
                    829:                }
                    830:                if(apop) {
                    831:                        strlwr(user.pass);      /* this is case-sensitive, so convert to lowercase */
                    832:                        strcat(challenge,user.pass);
                    833:                        MD5_calc(digest,challenge,strlen(challenge));
                    834:                        MD5_hex(str,digest);
                    835:                        if(strcmp(str,response)) {
                    836:                                lprintf(LOG_WARNING,"%04d !POP3 %s FAILED APOP authentication"
                    837:                                        ,socket,username);
                    838: #if 0
                    839:                                lprintf(LOG_DEBUG,"%04d !POP3 digest data: %s",socket,challenge);
                    840:                                lprintf(LOG_DEBUG,"%04d !POP3 calc digest: %s",socket,str);
                    841:                                lprintf(LOG_DEBUG,"%04d !POP3 resp digest: %s",socket,response);
                    842: #endif
                    843:                                sockprintf(socket,pop_err);
                    844:                                break;
                    845:                        }
                    846:                } else if(stricmp(password,user.pass)) {
                    847:                        if(scfg.sys_misc&SM_ECHO_PW)
                    848:                                lprintf(LOG_WARNING,"%04d !POP3 FAILED Password attempt for user %s: '%s' expected '%s'"
                    849:                                        ,socket, username, password, user.pass);
                    850:                        else
                    851:                                lprintf(LOG_WARNING,"%04d !POP3 FAILED Password attempt for user %s"
                    852:                                        ,socket, username);
                    853:                        sockprintf(socket, pop_err);
                    854:                        break;
                    855:                }
                    856:                putuserrec(&scfg,user.number,U_COMP,LEN_COMP,host_name);
                    857:                putuserrec(&scfg,user.number,U_NOTE,LEN_NOTE,host_ip);
                    858: 
                    859:                /* Update client display */
                    860:                client.user=user.alias;
                    861:                client_on(socket,&client,TRUE /* update */);
                    862: 
                    863:                if(startup->options&MAIL_OPT_DEBUG_POP3)                
                    864:                        lprintf(LOG_INFO,"%04d POP3 %s logged in %s", socket, user.alias, apop ? "via APOP":"");
                    865:                SAFEPRINTF(str,"POP3: %s",user.alias);
                    866:                status(str);
                    867: 
                    868:                sprintf(smb.file,"%smail",scfg.data_dir);
                    869:                if(smb_islocked(&smb)) {
                    870:                        lprintf(LOG_WARNING,"%04d !POP3 MAIL BASE LOCKED: %s",socket,smb.last_error);
                    871:                        sockprintf(socket,"-ERR database locked, try again later");
                    872:                        break;
                    873:                }
                    874:                smb.retry_time=scfg.smb_retry_time;
                    875:                smb.subnum=INVALID_SUB;
                    876:                if((i=smb_open(&smb))!=SMB_SUCCESS) {
                    877:                        lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) opening %s",socket,i,smb.last_error,smb.file);
                    878:                        sockprintf(socket,"-ERR %d opening %s",i,smb.file);
                    879:                        break;
                    880:                }
                    881: 
                    882:                mail=loadmail(&smb,&msgs,user.number,MAIL_YOUR,0);
                    883: 
                    884:                for(l=bytes=0;l<msgs;l++) {
                    885:                        msg.hdr.number=mail[l].number;
                    886:                        if((i=smb_getmsgidx(&smb,&msg))!=SMB_SUCCESS) {
                    887:                                lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) getting message index"
                    888:                                        ,socket, i, smb.last_error);
                    889:                                break;
                    890:                        }
                    891:                        if((i=smb_lockmsghdr(&smb,&msg))!=SMB_SUCCESS) {
                    892:                                lprintf(LOG_WARNING,"%04d !POP3 ERROR %d (%s) locking message header #%lu"
                    893:                                        ,socket, i, smb.last_error, msg.hdr.number);
                    894:                                break; 
                    895:                        }
                    896:                        i=smb_getmsghdr(&smb,&msg);
                    897:                        smb_unlockmsghdr(&smb,&msg);
                    898:                        if(i!=0) {
                    899:                                lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) getting message header #%lu"
                    900:                                        ,socket, i, smb.last_error, msg.hdr.number);
                    901:                                break;
                    902:                        }
                    903:                        bytes+=smb_getmsgtxtlen(&msg);
                    904:                        smb_freemsgmem(&msg);
                    905:                }
                    906: 
                    907:                if(l<msgs) {
                    908:                        sockprintf(socket,"-ERR message #%d: %d (%s)"
                    909:                                ,mail[l].number,i,smb.last_error);
                    910:                        break;
                    911:                }
                    912: 
                    913:                sockprintf(socket,"+OK %lu messages (%lu bytes)",msgs,bytes);
                    914: 
                    915:                while(1) {      /* TRANSACTION STATE */
                    916:                        rd = sockreadline(socket, buf, sizeof(buf));
                    917:                        if(rd<0) 
                    918:                                break;
                    919:                        truncsp(buf);
                    920:                        if(startup->options&MAIL_OPT_DEBUG_POP3)
                    921:                                lprintf(LOG_DEBUG,"%04d POP3 RX: %s", socket, buf);
                    922:                        if(!stricmp(buf, "NOOP")) {
                    923:                                sockprintf(socket,"+OK");
                    924:                                continue;
                    925:                        }
                    926:                        if(!stricmp(buf, "QUIT")) {
                    927:                                sockprintf(socket,"+OK");
                    928:                                break;
                    929:                        }
                    930:                        if(!stricmp(buf, "STAT")) {
                    931:                                sockprintf(socket,"+OK %lu %lu",msgs,bytes);
                    932:                                continue;
                    933:                        }
                    934:                        if(!stricmp(buf, "RSET")) {
                    935:                                if((i=smb_locksmbhdr(&smb))!=SMB_SUCCESS) {
                    936:                                        lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) locking message base"
                    937:                                                ,socket, i, smb.last_error);
                    938:                                        sockprintf(socket,"-ERR %d locking message base",i);
                    939:                                        continue;
                    940:                                }
                    941:                                for(l=0;l<msgs;l++) {
                    942:                                        msg.hdr.number=mail[l].number;
                    943:                                        if((i=smb_getmsgidx(&smb,&msg))!=SMB_SUCCESS) {
                    944:                                                lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) getting message index"
                    945:                                                        ,socket, i, smb.last_error);
                    946:                                                break;
                    947:                                        }
                    948:                                        if((i=smb_lockmsghdr(&smb,&msg))!=SMB_SUCCESS) {
                    949:                                                lprintf(LOG_WARNING,"%04d !POP3 ERROR %d (%s) locking message header #%lu"
                    950:                                                        ,socket, i, smb.last_error, msg.hdr.number);
                    951:                                                break; 
                    952:                                        }
                    953:                                        if((i=smb_getmsghdr(&smb,&msg))!=SMB_SUCCESS) {
                    954:                                                smb_unlockmsghdr(&smb,&msg);
                    955:                                                lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) getting message header #%lu"
                    956:                                                        ,socket, i, smb.last_error, msg.hdr.number);
                    957:                                                break;
                    958:                                        }
                    959:                                        msg.hdr.attr=mail[l].attr;
                    960:                                        if((i=smb_putmsg(&smb,&msg))!=SMB_SUCCESS)
                    961:                                                lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) updating message index"
                    962:                                                        ,socket, i, smb.last_error);
                    963:                                        smb_unlockmsghdr(&smb,&msg);
                    964:                                        smb_freemsgmem(&msg);
                    965:                                }
                    966:                                smb_unlocksmbhdr(&smb);
                    967: 
                    968:                                if(l<msgs)
                    969:                                        sockprintf(socket,"-ERR %d messages reset (ERROR: %d)",l,i);
                    970:                                else
                    971:                                        sockprintf(socket,"+OK %lu messages (%lu bytes)",msgs,bytes);
                    972:                                continue;
                    973:                        }
                    974:                        if(!strnicmp(buf, "LIST",4) || !strnicmp(buf,"UIDL",4)) {
                    975:                                p=buf+4;
                    976:                                SKIP_WHITESPACE(p);
                    977:                                if(isdigit(*p)) {
                    978:                                        msgnum=atol(p);
                    979:                                        if(msgnum<1 || msgnum>msgs) {
                    980:                                                lprintf(LOG_WARNING,"%04d !POP3 INVALID message #%ld"
                    981:                                                        ,socket, msgnum);
                    982:                                                sockprintf(socket,"-ERR no such message");
                    983:                                                continue;
                    984:                                        }
                    985:                                        msg.hdr.number=mail[msgnum-1].number;
                    986:                                        if((i=smb_getmsgidx(&smb,&msg))!=SMB_SUCCESS) {
                    987:                                                lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) getting message index"
                    988:                                                        ,socket, i, smb.last_error);
                    989:                                                sockprintf(socket,"-ERR %d getting message index",i);
                    990:                                                break;
                    991:                                        }
                    992:                                        if(msg.idx.attr&MSG_DELETE) {
                    993:                                                lprintf(LOG_WARNING,"%04d !POP3 ATTEMPT to list DELETED message"
                    994:                                                        ,socket);
                    995:                                                sockprintf(socket,"-ERR message deleted");
                    996:                                                continue;
                    997:                                        }
                    998:                                        if((i=smb_lockmsghdr(&smb,&msg))!=SMB_SUCCESS) {
                    999:                                                lprintf(LOG_WARNING,"%04d !POP3 ERROR %d (%s) locking message header #%lu"
                   1000:                                                        ,socket, i, smb.last_error, msg.hdr.number);
                   1001:                                                sockprintf(socket,"-ERR %d locking message header",i);
                   1002:                                                continue; 
                   1003:                                        }
                   1004:                                        i=smb_getmsghdr(&smb,&msg);
                   1005:                                        smb_unlockmsghdr(&smb,&msg);
                   1006:                                        if(i!=0) {
                   1007:                                                smb_freemsgmem(&msg);
                   1008:                                                lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) getting message header #%lu"
                   1009:                                                        ,socket, i, smb.last_error, msg.hdr.number);
                   1010:                                                sockprintf(socket,"-ERR %d getting message header",i);
                   1011:                                                continue;
                   1012:                                        }
                   1013:                                        if(!strnicmp(buf, "LIST",4)) {
                   1014:                                                sockprintf(socket,"+OK %lu %lu",msgnum,smb_getmsgtxtlen(&msg));
                   1015:                                        } else /* UIDL */
                   1016:                                                sockprintf(socket,"+OK %lu %lu",msgnum,msg.hdr.number);
                   1017: 
                   1018:                                        smb_freemsgmem(&msg);
                   1019:                                        continue;
                   1020:                                }
                   1021:                                /* List ALL messages */
                   1022:                                sockprintf(socket,"+OK %lu messages (%lu bytes)",msgs,bytes);
                   1023:                                for(l=0;l<msgs;l++) {
                   1024:                                        msg.hdr.number=mail[l].number;
                   1025:                                        if((i=smb_getmsgidx(&smb,&msg))!=SMB_SUCCESS) {
                   1026:                                                lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) getting message index"
                   1027:                                                        ,socket, i, smb.last_error);
                   1028:                                                break;
                   1029:                                        }
                   1030:                                        if(msg.idx.attr&MSG_DELETE) 
                   1031:                                                continue;
                   1032:                                        if((i=smb_lockmsghdr(&smb,&msg))!=SMB_SUCCESS) {
                   1033:                                                lprintf(LOG_WARNING,"%04d !POP3 ERROR %d (%s) locking message header #%lu"
                   1034:                                                        ,socket, i, smb.last_error, msg.hdr.number);
                   1035:                                                break; 
                   1036:                                        }
                   1037:                                        i=smb_getmsghdr(&smb,&msg);
                   1038:                                        smb_unlockmsghdr(&smb,&msg);
                   1039:                                        if(i!=0) {
                   1040:                                                smb_freemsgmem(&msg);
                   1041:                                                lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) getting message header #%lu"
                   1042:                                                        ,socket, i, smb.last_error, msg.hdr.number);
                   1043:                                                break;
                   1044:                                        }
                   1045:                                        if(!strnicmp(buf, "LIST",4)) {
                   1046:                                                sockprintf(socket,"%lu %lu",l+1,smb_getmsgtxtlen(&msg));
                   1047:                                        } else /* UIDL */
                   1048:                                                sockprintf(socket,"%lu %lu",l+1,msg.hdr.number);
                   1049: 
                   1050:                                        smb_freemsgmem(&msg);
                   1051:                                }                       
                   1052:                                sockprintf(socket,".");
                   1053:                                continue;
                   1054:                        }
                   1055:                        activity=TRUE;
                   1056:                        if(!strnicmp(buf, "RETR ",5) || !strnicmp(buf,"TOP ",4)) {
                   1057:                                SAFEPRINTF(str,"POP3: %s", user.alias);
                   1058:                                status(str);
                   1059: 
                   1060:                                lines=-1;
                   1061:                                p=buf+4;
                   1062:                                SKIP_WHITESPACE(p);
                   1063:                                msgnum=atol(p);
                   1064: 
                   1065:                                if(!strnicmp(buf,"TOP ",4)) {
                   1066:                                        SKIP_DIGIT(p);
                   1067:                                        SKIP_WHITESPACE(p);
                   1068:                                        lines=atol(p);
                   1069:                                }
                   1070:                                if(msgnum<1 || msgnum>msgs) {
                   1071:                                        lprintf(LOG_WARNING,"%04d !POP3 %s ATTEMPTED to retrieve an INVALID message #%ld"
                   1072:                                                ,socket, user.alias, msgnum);
                   1073:                                        sockprintf(socket,"-ERR no such message");
                   1074:                                        continue;
                   1075:                                }
                   1076:                                msg.hdr.number=mail[msgnum-1].number;
                   1077: 
                   1078:                                lprintf(LOG_INFO,"%04d POP3 %s retrieving message #%ld"
                   1079:                                        ,socket, user.alias, msg.hdr.number);
                   1080: 
                   1081:                                if((i=smb_getmsgidx(&smb,&msg))!=SMB_SUCCESS) {
                   1082:                                        lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) getting message index"
                   1083:                                                ,socket, i, smb.last_error);
                   1084:                                        sockprintf(socket,"-ERR %d getting message index",i);
                   1085:                                        continue;
                   1086:                                }
                   1087:                                if(msg.idx.attr&MSG_DELETE) {
                   1088:                                        lprintf(LOG_WARNING,"%04d !POP3 ATTEMPT to retrieve DELETED message"
                   1089:                                                ,socket);
                   1090:                                        sockprintf(socket,"-ERR message deleted");
                   1091:                                        continue;
                   1092:                                }
                   1093:                                if((i=smb_lockmsghdr(&smb,&msg))!=SMB_SUCCESS) {
                   1094:                                        lprintf(LOG_WARNING,"%04d !POP3 ERROR %d (%s) locking message header #%lu"
                   1095:                                                ,socket, i, smb.last_error, msg.hdr.number);
                   1096:                                        sockprintf(socket,"-ERR %d locking message header",i);
                   1097:                                        continue; 
                   1098:                                }
                   1099:                                i=smb_getmsghdr(&smb,&msg);
                   1100:                                smb_unlockmsghdr(&smb,&msg);
                   1101:                                if(i!=0) {
                   1102:                                        lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) getting message header #%lu"
                   1103:                                                ,socket, i, smb.last_error, msg.hdr.number);
                   1104:                                        sockprintf(socket,"-ERR %d getting message header",i);
                   1105:                                        continue;
                   1106:                                }
                   1107: 
                   1108:                                if((msgtxt=smb_getmsgtxt(&smb,&msg,GETMSGTXT_ALL))==NULL) {
                   1109:                                        smb_freemsgmem(&msg);
                   1110:                                        lprintf(LOG_ERR,"%04d !POP3 ERROR (%s) retrieving message %lu text"
                   1111:                                                ,socket, smb.last_error, msg.hdr.number);
                   1112:                                        sockprintf(socket,"-ERR retrieving message text");
                   1113:                                        continue;
                   1114:                                }
                   1115: 
                   1116:                                sockprintf(socket,"+OK message follows");
                   1117:                                lprintf(LOG_DEBUG,"%04d POP3 sending message text (%u bytes)"
                   1118:                                        ,socket,strlen(msgtxt));
                   1119:                                lines_sent=sockmsgtxt(socket,&msg,msgtxt,lines);
                   1120:                                /* if(startup->options&MAIL_OPT_DEBUG_POP3) */
                   1121:                                if(lines!=-1 && lines_sent<lines)       /* could send *more* lines */
                   1122:                                        lprintf(LOG_ERR,"%04d !POP3 ERROR sending message text (sent %ld of %ld lines)"
                   1123:                                                ,socket,lines_sent,lines);
                   1124:                                else {
                   1125:                                        lprintf(LOG_DEBUG,"%04d POP3 message transfer complete (%lu lines)"
                   1126:                                                ,socket,lines_sent);
                   1127: 
                   1128:                                        if((i=smb_locksmbhdr(&smb))!=SMB_SUCCESS) {
                   1129:                                                lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) locking message base"
                   1130:                                                        ,socket, i, smb.last_error);
                   1131:                                        } else {
                   1132:                                                if((i=smb_getmsgidx(&smb,&msg))!=SMB_SUCCESS) {
                   1133:                                                        lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) getting message index"
                   1134:                                                                ,socket, i, smb.last_error);
                   1135:                                                } else {
                   1136:                                                        msg.hdr.attr|=MSG_READ;
                   1137:                                                        msg.hdr.netattr|=MSG_SENT;
                   1138: 
                   1139:                                                        if((i=smb_lockmsghdr(&smb,&msg))!=SMB_SUCCESS) 
                   1140:                                                                lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) locking message header #%lu"
                   1141:                                                                        ,socket, i, smb.last_error, msg.hdr.number);
                   1142:                                                        if((i=smb_putmsg(&smb,&msg))!=SMB_SUCCESS)
                   1143:                                                                lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) marking message #%lu as read"
                   1144:                                                                        ,socket, i, smb.last_error, msg.hdr.number);
                   1145:                                                        smb_unlockmsghdr(&smb,&msg);
                   1146:                                                }
                   1147:                                                smb_unlocksmbhdr(&smb);
                   1148:                                        }
                   1149:                                }
                   1150:                                smb_freemsgmem(&msg);
                   1151:                                smb_freemsgtxt(msgtxt);
                   1152:                                continue;
                   1153:                        }
                   1154:                        if(!strnicmp(buf, "DELE ",5)) {
                   1155:                                p=buf+5;
                   1156:                                SKIP_WHITESPACE(p);
                   1157:                                msgnum=atol(p);
                   1158: 
                   1159:                                if(msgnum<1 || msgnum>msgs) {
                   1160:                                        lprintf(LOG_WARNING,"%04d !POP3 %s ATTEMPTED to delete an INVALID message #%ld"
                   1161:                                                ,socket, user.alias, msgnum);
                   1162:                                        sockprintf(socket,"-ERR no such message");
                   1163:                                        continue;
                   1164:                                }
                   1165:                                msg.hdr.number=mail[msgnum-1].number;
                   1166: 
                   1167:                                lprintf(LOG_INFO,"%04d POP3 %s deleting message #%ld"
                   1168:                                        ,socket, user.alias, msg.hdr.number);
                   1169: 
                   1170:                                if((i=smb_locksmbhdr(&smb))!=SMB_SUCCESS) {
                   1171:                                        lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) locking message base"
                   1172:                                                ,socket, i, smb.last_error);
                   1173:                                        sockprintf(socket,"-ERR %d locking message base",i);
                   1174:                                        continue;
                   1175:                                }
                   1176:                                if((i=smb_getmsgidx(&smb,&msg))!=SMB_SUCCESS) {
                   1177:                                        smb_unlocksmbhdr(&smb);
                   1178:                                        lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) getting message index"
                   1179:                                                ,socket, i, smb.last_error);
                   1180:                                        sockprintf(socket,"-ERR %d getting message index",i);
                   1181:                                        continue;
                   1182:                                }
                   1183:                                if((i=smb_lockmsghdr(&smb,&msg))!=SMB_SUCCESS) {
                   1184:                                        smb_unlocksmbhdr(&smb);
                   1185:                                        lprintf(LOG_WARNING,"%04d !POP3 ERROR %d (%s) locking message header #%lu"
                   1186:                                                ,socket, i, smb.last_error, msg.hdr.number);
                   1187:                                        sockprintf(socket,"-ERR %d locking message header",i);
                   1188:                                        continue; 
                   1189:                                }
                   1190:                                if((i=smb_getmsghdr(&smb,&msg))!=SMB_SUCCESS) {
                   1191:                                        smb_unlockmsghdr(&smb,&msg);
                   1192:                                        smb_unlocksmbhdr(&smb);
                   1193:                                        lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) getting message header #%lu"
                   1194:                                                ,socket, i, smb.last_error, msg.hdr.number);
                   1195:                                        sockprintf(socket,"-ERR %d getting message header",i);
                   1196:                                        continue;
                   1197:                                }
                   1198:                                msg.hdr.attr|=MSG_DELETE;
                   1199: 
                   1200:                                if((i=smb_putmsg(&smb,&msg))==SMB_SUCCESS && msg.hdr.auxattr&MSG_FILEATTACH)
                   1201:                                        delfattach(&scfg,&msg);
                   1202:                                smb_unlockmsghdr(&smb,&msg);
                   1203:                                smb_unlocksmbhdr(&smb);
                   1204:                                smb_freemsgmem(&msg);
                   1205:                                if(i!=SMB_SUCCESS) {
                   1206:                                        lprintf(LOG_ERR,"%04d !POP3 ERROR %d (%s) marking message as read"
                   1207:                                                , socket, i, smb.last_error);
                   1208:                                        sockprintf(socket,"-ERR %d marking message for deletion",i);
                   1209:                                        continue;
                   1210:                                }
                   1211:                                sockprintf(socket,"+OK");
                   1212:                                if(startup->options&MAIL_OPT_DEBUG_POP3)
                   1213:                                        lprintf(LOG_INFO,"%04d POP3 message deleted", socket);
                   1214:                                continue;
                   1215:                        }
                   1216:                        lprintf(LOG_WARNING,"%04d !POP3 UNSUPPORTED COMMAND from %s: '%s'"
                   1217:                                ,socket, user.alias, buf);
                   1218:                        sockprintf(socket,"-ERR UNSUPPORTED COMMAND: %s",buf);
                   1219:                }
                   1220:                if(user.number)
                   1221:                        logoutuserdat(&scfg,&user,time(NULL),client.time);
                   1222: 
                   1223:        } while(0);
                   1224: 
                   1225:        if(activity) 
                   1226:                lprintf(LOG_INFO,"%04d POP3 %s logged out from port %u on %s [%s]"
                   1227:                        ,socket, user.alias, ntohs(pop3.client_addr.sin_port), host_name, host_ip);
                   1228: 
                   1229:        status(STATUS_WFC);
                   1230: 
                   1231:        /* Free up resources here */
                   1232:        if(mail!=NULL)
                   1233:                freemail(mail);
                   1234: 
                   1235:        smb_freemsgmem(&msg);
                   1236:        smb_close(&smb);
                   1237: 
                   1238:        if(active_clients)
                   1239:                active_clients--, update_clients();
                   1240:        client_off(socket);
                   1241: 
                   1242:        thread_down();
                   1243:        if(startup->options&MAIL_OPT_DEBUG_POP3)
                   1244:                lprintf(LOG_DEBUG,"%04d POP3 session thread terminated (%u threads remain, %lu clients served)"
                   1245:                        ,socket, thread_count, served);
                   1246: 
                   1247:        /* Must be last */
                   1248:        mail_close_socket(socket);
                   1249: }
                   1250: 
                   1251: static ulong rblchk(SOCKET sock, DWORD mail_addr_n, const char* rbl_addr)
                   1252: {
                   1253:        char            name[256];
                   1254:        DWORD           mail_addr;
                   1255:        HOSTENT*        host;
                   1256:        struct in_addr dnsbl_result;
                   1257: 
                   1258:        mail_addr=ntohl(mail_addr_n);
                   1259:        safe_snprintf(name,sizeof(name),"%ld.%ld.%ld.%ld.%.128s"
                   1260:                ,mail_addr&0xff
                   1261:                ,(mail_addr>>8)&0xff
                   1262:                ,(mail_addr>>16)&0xff
                   1263:                ,(mail_addr>>24)&0xff
                   1264:                ,rbl_addr
                   1265:                );
                   1266: 
                   1267:        if(startup->options&MAIL_OPT_DNSBL_DEBUG)
                   1268:                lprintf(LOG_DEBUG,"%04d SMTP DNSBL Query: %s",sock,name);
                   1269: 
                   1270:        if((host=gethostbyname(name))==NULL)
                   1271:                return(0);
                   1272: 
                   1273:        dnsbl_result.s_addr = *((ulong*)host->h_addr_list[0]);
                   1274:        lprintf(LOG_INFO,"%04d SMTP DNSBL Query: %s resolved to: %s"
                   1275:                ,sock,name,inet_ntoa(dnsbl_result));
                   1276: 
                   1277:        return(dnsbl_result.s_addr);
                   1278: }
                   1279: 
                   1280: static ulong dns_blacklisted(SOCKET sock, IN_ADDR addr, char* host_name, char* list, char* dnsbl_ip)
                   1281: {
                   1282:        char    fname[MAX_PATH+1];
                   1283:        char    str[256];
                   1284:        char*   p;
                   1285:        char*   tp;
                   1286:        FILE*   fp;
                   1287:        ulong   found=0;
                   1288: 
                   1289:        sprintf(fname,"%sdnsbl_exempt.cfg",scfg.ctrl_dir);
                   1290:        if(findstr(inet_ntoa(addr),fname))
                   1291:                return(FALSE);
                   1292:        if(findstr(host_name,fname))
                   1293:                return(FALSE);
                   1294: 
                   1295:        sprintf(fname,"%sdns_blacklist.cfg", scfg.ctrl_dir);
                   1296:        if((fp=fopen(fname,"r"))==NULL)
                   1297:                return(FALSE);
                   1298: 
                   1299:        while(!feof(fp) && !found) {
                   1300:                if(fgets(str,sizeof(str),fp)==NULL)
                   1301:                        break;
                   1302:                truncsp(str);
                   1303: 
                   1304:                p=str;
                   1305:                SKIP_WHITESPACE(p);
                   1306:                if(*p==';' || *p==0) /* comment or blank line */
                   1307:                        continue;
                   1308: 
                   1309:                sprintf(list,"%.100s",p);
                   1310: 
                   1311:                /* terminate */
                   1312:                tp = p;
                   1313:                FIND_WHITESPACE(tp);
                   1314:                *tp=0;  
                   1315: 
                   1316:                found = rblchk(sock, addr.s_addr, p);
                   1317:        }
                   1318:        fclose(fp);
                   1319:        if(found)
                   1320:                strcpy(dnsbl_ip, inet_ntoa(addr));
                   1321: 
                   1322:        return(found);
                   1323: }
                   1324: 
                   1325: 
                   1326: static BOOL chk_email_addr(SOCKET socket, char* p, char* host_name, char* host_ip
                   1327:                                                   ,char* to, char* from, char* source)
                   1328: {
                   1329:        char    addr[64];
                   1330:        char    tmp[128];
                   1331: 
                   1332:        SKIP_WHITESPACE(p);
                   1333:        if(*p=='<') p++;                /* Skip '<' */
                   1334:        SAFECOPY(addr,p);
                   1335:        truncstr(addr,">( ");
                   1336: 
                   1337:        if(!trashcan(&scfg,addr,"email"))
                   1338:                return(TRUE);
                   1339: 
                   1340:        lprintf(LOG_NOTICE,"%04d !SMTP BLOCKED %s e-mail address: %s"
                   1341:                ,socket, source, addr);
                   1342:        SAFEPRINTF2(tmp,"Blocked %s e-mail address: %s", source, addr);
                   1343:        spamlog(&scfg, "SMTP", "REFUSED", tmp, host_name, host_ip, to, from);
                   1344: 
                   1345:        return(FALSE);
                   1346: }
                   1347: 
                   1348: static void signal_smtp_sem(void)
                   1349: {
                   1350:        int file;
                   1351: 
                   1352:        if(scfg.smtpmail_sem[0]==0) 
                   1353:                return; /* do nothing */
                   1354: 
                   1355:        if((file=open(scfg.smtpmail_sem,O_WRONLY|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE))!=-1)
                   1356:                close(file);
                   1357: }
                   1358: 
                   1359: /*****************************************************************************/
                   1360: /* Returns command line generated from instr with %c replacments             */
                   1361: /*****************************************************************************/
                   1362: static char* mailcmdstr(char* instr, char* msgpath, char* lstpath, char* errpath
                   1363:                                                ,char* host, char* ip, uint usernum
                   1364:                                                ,char* sender, char* sender_addr, char* reverse_path, char* cmd)
                   1365: {
                   1366:        char    str[1024];
                   1367:     int                i,j,len;
                   1368: 
                   1369:     len=strlen(instr);
                   1370:     for(i=j=0;i<len;i++) {
                   1371:         if(instr[i]=='%') {
                   1372:             i++;
                   1373:             cmd[j]=0;
                   1374:             switch(toupper(instr[i])) {
                   1375:                                case 'E':
                   1376:                                        strcat(cmd,errpath);
                   1377:                                        break;
                   1378:                                case 'H':
                   1379:                                        strcat(cmd,host);
                   1380:                                        break;
                   1381:                                case 'I':
                   1382:                                        strcat(cmd,ip);
                   1383:                                        break;
                   1384:                 case 'G':   /* Temp directory */
                   1385:                     strcat(cmd,scfg.temp_dir);
                   1386:                     break;
                   1387:                 case 'J':
                   1388:                     strcat(cmd,scfg.data_dir);
                   1389:                     break;
                   1390:                 case 'K':
                   1391:                     strcat(cmd,scfg.ctrl_dir);
                   1392:                     break;
                   1393:                                case 'L':
                   1394:                                        strcat(cmd,lstpath);
                   1395:                                        break;
                   1396:                                case 'F':
                   1397:                                case 'M':
                   1398:                                        strcat(cmd,msgpath);
                   1399:                                        break;
                   1400:                 case 'O':   /* SysOp */
                   1401:                     strcat(cmd,scfg.sys_op);
                   1402:                     break;
                   1403:                 case 'Q':   /* QWK ID */
                   1404:                     strcat(cmd,scfg.sys_id);
                   1405:                     break;
                   1406:                                case 'R':       /* reverse path */
                   1407:                                        strcat(cmd,reverse_path);
                   1408:                                        break;
                   1409:                                case 'S':       /* sender name */
                   1410:                                        strcat(cmd,sender);
                   1411:                                        break;
                   1412:                                case 'A':       /* sender address */
                   1413:                                        strcat(cmd,sender_addr);
                   1414:                                        break;
                   1415:                 case 'V':   /* Synchronet Version */
                   1416:                     sprintf(str,"%s%c",VERSION,REVISION);
                   1417:                                        strcat(cmd,str);
                   1418:                     break;
                   1419:                 case 'Z':
                   1420:                     strcat(cmd,scfg.text_dir);
                   1421:                     break;
                   1422:                 case '!':   /* EXEC Directory */
                   1423:                     strcat(cmd,scfg.exec_dir);
                   1424:                     break;
                   1425:                 case '@':   /* EXEC Directory for DOS/OS2/Win32, blank for Unix */
                   1426: #ifndef __unix__
                   1427:                     strcat(cmd,scfg.exec_dir);
                   1428: #endif
                   1429:                     break;
                   1430:                 case '%':   /* %% for percent sign */
                   1431:                     strcat(cmd,"%");
                   1432:                     break;
                   1433:                                case '?':       /* Platform */
                   1434: #ifdef __OS2__
                   1435:                                        SAFECOPY(str,"OS2");
                   1436: #else
                   1437:                                        SAFECOPY(str,PLATFORM_DESC);
                   1438: #endif
                   1439:                                        strlwr(str);
                   1440:                                        strcat(cmd,str);
                   1441:                                        break;
                   1442:                                case 'U':       /* User number */
                   1443:                                        sprintf(str,"%u",usernum);
                   1444:                                        strcat(cmd,str);
                   1445:                                        break;
                   1446:                 default:    /* unknown specification */
                   1447:                     break; 
                   1448:                        }
                   1449:             j=strlen(cmd); 
                   1450:                }
                   1451:         else
                   1452:             cmd[j++]=instr[i]; 
                   1453:        }
                   1454:     cmd[j]=0;
                   1455: 
                   1456:     return(cmd);
                   1457: }
                   1458: #ifdef JAVASCRIPT
                   1459: 
                   1460: static void
                   1461: js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
                   1462: {
                   1463:        char    line[64];
                   1464:        char    file[MAX_PATH+1];
                   1465:        char*   warning;
                   1466:        SOCKET*         sock;
                   1467: 
                   1468:        if((sock=(SOCKET*)JS_GetContextPrivate(cx))==NULL)
                   1469:                return;
                   1470: 
                   1471:        if(report==NULL) {
                   1472:                lprintf(LOG_ERR,"!JavaScript: %s", message);
                   1473:                return;
                   1474:     }
                   1475: 
                   1476:        if(report->filename)
                   1477:                SAFEPRINTF(file," %s",report->filename);
                   1478:        else
                   1479:                file[0]=0;
                   1480: 
                   1481:        if(report->lineno)
                   1482:                SAFEPRINTF(line," line %u",report->lineno);
                   1483:        else
                   1484:                line[0]=0;
                   1485: 
                   1486:        if(JSREPORT_IS_WARNING(report->flags)) {
                   1487:                if(JSREPORT_IS_STRICT(report->flags))
                   1488:                        warning="strict warning";
                   1489:                else
                   1490:                        warning="warning";
                   1491:        } else
                   1492:                warning="";
                   1493: 
                   1494:        lprintf(LOG_ERR,"%04d !JavaScript %s%s%s: %s"
                   1495:                ,*sock, warning ,file, line, message);
                   1496: }
                   1497: 
                   1498: static JSBool
                   1499: js_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1500: {
                   1501:     uintN              i=0;
                   1502:        int32           level=LOG_INFO;
                   1503:     JSString*  str=NULL;
                   1504:        SOCKET*         sock;
                   1505: 
                   1506:        if((sock=(SOCKET*)JS_GetContextPrivate(cx))==NULL)
                   1507:                return(JS_FALSE);
                   1508: 
                   1509:        if(JSVAL_IS_NUMBER(argv[i]))
                   1510:                JS_ValueToInt32(cx,argv[i++],&level);
                   1511: 
                   1512:        for(; i<argc; i++) {
                   1513:                if((str=JS_ValueToString(cx, argv[i]))==NULL)
                   1514:                        return(JS_FALSE);
                   1515:                lprintf(level,"%04d JavaScript: %s",*sock,JS_GetStringBytes(str));
                   1516:        }
                   1517: 
                   1518:        if(str==NULL)
                   1519:                *rval = JSVAL_VOID;
                   1520:        else
                   1521:                *rval = STRING_TO_JSVAL(str);
                   1522: 
                   1523:     return(JS_TRUE);
                   1524: }
                   1525: 
                   1526: static JSFunctionSpec js_global_functions[] = {
                   1527:        {"write",                       js_log,                         0},
                   1528:        {"writeln",                     js_log,                         0},
                   1529:        {"print",                       js_log,                         0},
                   1530:        {"log",                         js_log,                         0},
                   1531:     {0}
                   1532: };
                   1533: 
                   1534: static BOOL
                   1535: js_mailproc(SOCKET sock, client_t* client, user_t* user
                   1536:                        ,char* cmdline
                   1537:                        ,char* msgtxt_fname, char* rcptlst_fname, char* proc_err_fname
                   1538:                        ,char* sender, char* sender_addr, char* reverse_path)
                   1539: {
                   1540:        char*           p;
                   1541:        char            fname[MAX_PATH+1];
                   1542:        char            path[MAX_PATH+1];
                   1543:        char            arg[MAX_PATH+1];
                   1544:        BOOL            success=FALSE;
                   1545:        JSRuntime*      js_runtime=NULL;
                   1546:        JSContext*      js_cx=NULL;
                   1547:        JSObject*       js_glob;
                   1548:        JSObject*       argv;
                   1549:        jsuint          argc;
                   1550:        JSScript*       js_script;
                   1551:        js_branch_t     js_branch;
                   1552:        jsval           val;
                   1553:        jsval           rval=JSVAL_VOID;
                   1554: 
                   1555:        ZERO_VAR(js_branch);
                   1556: 
                   1557:        SAFECOPY(fname,cmdline);
                   1558:        truncstr(fname," \t");
                   1559:        if(getfext(fname)==NULL) /* No extension specified, assume '.js' */
                   1560:                strcat(fname,".js");
                   1561: 
                   1562:        SAFECOPY(path,fname);
                   1563:        if(getfname(path)==path) /* No path specified, assume exec_dir */
                   1564:                sprintf(path,"%s%s",scfg.exec_dir,fname);
                   1565: 
                   1566:        do {
                   1567: 
                   1568:                lprintf(LOG_DEBUG,"%04d JavaScript: Creating runtime: %lu bytes\n"
                   1569:                        ,sock, startup->js.max_bytes);
                   1570: 
                   1571:                if((js_runtime = JS_NewRuntime(startup->js.max_bytes))==NULL)
                   1572:                        break;
                   1573: 
                   1574:                lprintf(LOG_DEBUG,"%04d JavaScript: Initializing context (stack: %lu bytes)\n"
                   1575:                        ,sock, startup->js.cx_stack);
                   1576: 
                   1577:                if((js_cx = JS_NewContext(js_runtime, startup->js.cx_stack))==NULL)
                   1578:                        break;
                   1579: 
                   1580:                JS_SetErrorReporter(js_cx, js_ErrorReporter);
                   1581: 
                   1582:                JS_SetContextPrivate(js_cx, &sock);
                   1583: 
                   1584:                /* Global Object */
                   1585:                if((js_glob=js_CreateGlobalObject(js_cx, &scfg, NULL))==NULL)
                   1586:                        break;
                   1587: 
                   1588:                if (!JS_DefineFunctions(js_cx, js_glob, js_global_functions))
                   1589:                        break;
                   1590: 
                   1591:                /* Internal JS Object */
                   1592:                if(js_CreateInternalJsObject(js_cx, js_glob, &js_branch)==NULL)
                   1593:                        break;
                   1594: 
                   1595:                /* Client Object */
                   1596:                if(js_CreateClientObject(js_cx, js_glob, "client", client, sock)==NULL)
                   1597:                        break;
                   1598: 
                   1599:                /* System Object */
                   1600:                if(js_CreateSystemObject(js_cx, js_glob, &scfg, uptime, startup->host_name, SOCKLIB_DESC)==NULL)
                   1601:                        break;
                   1602: 
                   1603:                /* Socket Class */
                   1604:                if(js_CreateSocketClass(js_cx, js_glob)==NULL)
                   1605:                        break;
                   1606: 
                   1607:                /* MsgBase Class */
                   1608:                if(js_CreateMsgBaseClass(js_cx, js_glob, &scfg)==NULL)
                   1609:                        break;
                   1610: 
                   1611:                /* File Class */
                   1612:                if(js_CreateFileClass(js_cx, js_glob)==NULL)
                   1613:                        break;
                   1614: 
                   1615:                /* User class */
                   1616:                if(js_CreateUserClass(js_cx, js_glob, &scfg)==NULL) 
                   1617:                        break;
                   1618: 
                   1619:                /* Area and "user" Objects */
                   1620:                if(!js_CreateUserObjects(js_cx, js_glob, &scfg, user, NULL, NULL)) 
                   1621:                        break;
                   1622: 
                   1623:                /* Convert command-line to argv/argc */
                   1624:                argv=JS_NewArrayObject(js_cx, 0, NULL);
                   1625:                JS_DefineProperty(js_cx, js_glob, "argv", OBJECT_TO_JSVAL(argv)
                   1626:                        ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
                   1627: 
                   1628:                p=cmdline;
                   1629:                FIND_WHITESPACE(p); 
                   1630:                SKIP_WHITESPACE(p);
                   1631:                for(argc=0;*p;argc++) {
                   1632:                        SAFECOPY(arg,p);
                   1633:                        truncstr(arg," \t");
                   1634:                        val=STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,arg));
                   1635:                        if(!JS_SetElement(js_cx, argv, argc, &val))
                   1636:                                break;
                   1637:                        FIND_WHITESPACE(p);
                   1638:                        SKIP_WHITESPACE(p);
                   1639:                }
                   1640:                JS_DefineProperty(js_cx, js_glob, "argc", INT_TO_JSVAL(argc)
                   1641:                        ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
                   1642: 
                   1643:                /* Mailproc "API" filenames */
                   1644:                JS_DefineProperty(js_cx, js_glob, "message_text_filename"
                   1645:                        ,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,msgtxt_fname))
                   1646:                        ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
                   1647: 
                   1648:                JS_DefineProperty(js_cx, js_glob, "recipient_list_filename"
                   1649:                        ,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,rcptlst_fname))
                   1650:                        ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
                   1651: 
                   1652:                JS_DefineProperty(js_cx, js_glob, "processing_error_filename"
                   1653:                        ,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,proc_err_fname))
                   1654:                        ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
                   1655: 
                   1656:                JS_DefineProperty(js_cx, js_glob, "sender_name"
                   1657:                        ,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,sender))
                   1658:                        ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
                   1659: 
                   1660:                JS_DefineProperty(js_cx, js_glob, "sender_address"
                   1661:                        ,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,sender_addr))
                   1662:                        ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
                   1663: 
                   1664:                JS_DefineProperty(js_cx, js_glob, "reverse_path"
                   1665:                        ,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,reverse_path))
                   1666:                        ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
                   1667: 
                   1668:                if((js_script=JS_CompileFile(js_cx, js_glob, path))==NULL)
                   1669:                        break;
                   1670: 
                   1671:                success=JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
                   1672: 
                   1673:                js_EvalOnExit(js_cx, js_glob, &js_branch);
                   1674: 
                   1675:        } while(0);
                   1676: 
                   1677:        if(js_cx!=NULL)
                   1678:                JS_DestroyContext(js_cx);
                   1679:        if(js_runtime!=NULL)
                   1680:                JS_DestroyRuntime(js_runtime);
                   1681: 
                   1682:        return(success);
                   1683: }
                   1684: #endif
                   1685: 
                   1686: 
                   1687: static int parse_header_field(uchar* buf, smbmsg_t* msg, ushort* type)
                   1688: {
                   1689:        char*   p;
                   1690:        char    field[128];
                   1691:        int             len;
                   1692:        ushort  nettype;
                   1693: 
                   1694:        if(buf[0]<=' ' && *type!=UNKNOWN) {     /* folded header, append to previous */
                   1695:                p=buf;
                   1696:                truncsp(p);
                   1697:                smb_hfield_append_str(msg,*type,"\r\n");
                   1698:                return smb_hfield_append_str(msg, *type, p);
                   1699:        }
                   1700: 
                   1701:        if((p=strchr(buf,':'))==NULL)
                   1702:                return smb_hfield_str(msg, *type=RFC822HEADER, buf);
                   1703: 
                   1704:        len=(ulong)p-(ulong)buf;
                   1705:        if(len>sizeof(field)-1)
                   1706:                len=sizeof(field)-1;
                   1707:        sprintf(field,"%.*s",len,buf);
                   1708:        truncsp(field);
                   1709: 
                   1710:        p++;    /* skip colon */
                   1711:        SKIP_WHITESPACE(p);
                   1712:        truncsp(p);
                   1713: 
                   1714:        if(!stricmp(field, "TO"))
                   1715:                return smb_hfield_str(msg, *type=RFC822TO, p);
                   1716: 
                   1717:        if(!stricmp(field, "REPLY-TO")) {
                   1718:                smb_hfield_str(msg, *type=RFC822REPLYTO, p);
                   1719:                if(*p=='<')  {
                   1720:                        p++;
                   1721:                        truncstr(p,">");
                   1722:                }
                   1723:                nettype=NET_INTERNET;
                   1724:                smb_hfield(msg, REPLYTONETTYPE, sizeof(nettype), &nettype);
                   1725:                return smb_hfield_str(msg, *type=REPLYTONETADDR, p);
                   1726:        }
                   1727:        if(!stricmp(field, "FROM"))
                   1728:                return smb_hfield_str(msg, *type=RFC822FROM, p);
                   1729: 
                   1730:        if(!stricmp(field, "ORGANIZATION"))
                   1731:                return smb_hfield_str(msg, *type=SENDERORG, p);
                   1732: 
                   1733:        if(!stricmp(field, "DATE")) {
                   1734:                msg->hdr.when_written=rfc822date(p);
                   1735:                *type=UNKNOWN;
                   1736:                return(0);
                   1737:        }
                   1738:        if(!stricmp(field, "MESSAGE-ID"))
                   1739:                return smb_hfield_str(msg, *type=RFC822MSGID, p);
                   1740: 
                   1741:        if(!stricmp(field, "IN-REPLY-TO"))
                   1742:                return smb_hfield_str(msg, *type=RFC822REPLYID, p);
                   1743: 
                   1744:        /* Fall-through */
                   1745:        return smb_hfield_str(msg, *type=RFC822HEADER, buf);
                   1746: }
                   1747: 
                   1748: static int chk_received_hdr(SOCKET socket,const char *buf,IN_ADDR *dnsbl_result, char *dnsbl, char *dnsbl_ip)
                   1749: {
                   1750:        char            host_name[128];
                   1751:        IN_ADDR         check_addr;
                   1752:        char            *fromstr;
                   1753:        char            ip[16];
                   1754:        char            *p;
                   1755:        char            *p2;
                   1756:        char            *last;
                   1757: 
                   1758:        fromstr=(char *)malloc(strlen(buf)+1);
                   1759:        if(fromstr==NULL)
                   1760:                return(0);
                   1761:        strcpy(fromstr,buf);
                   1762:        strlwr(fromstr);
                   1763:        do {
                   1764:                p=strstr(fromstr,"from ");
                   1765:                if(p==NULL)
                   1766:                        break;
                   1767:                p+=4;
                   1768:                SKIP_WHITESPACE(p);
                   1769:                if(*p==0)
                   1770:                        break;
                   1771:                p2=host_name;
                   1772:                for(;*p && !isspace(*p) && p2<host_name+126;p++)  {
                   1773:                        *p2++=*p;
                   1774:                }
                   1775:                *p2=0;
                   1776:                p=strtok_r(fromstr,"[",&last);
                   1777:                if(p==NULL)
                   1778:                        break;
                   1779:                p=strtok_r(NULL,"]",&last);
                   1780:                if(p==NULL)
                   1781:                        break;
                   1782:                strncpy(ip,p,16);
                   1783:                ip[15]=0;
                   1784:                check_addr.s_addr = inet_addr(ip);
                   1785:                if(startup->options&MAIL_OPT_DNSBL_DEBUG)
                   1786:                        lprintf(LOG_DEBUG,"%04d DEBUG checking %s (%s)",socket,host_name,ip);
                   1787:                if((dnsbl_result->s_addr=dns_blacklisted(socket,check_addr,host_name,dnsbl,dnsbl_ip))!=0)
                   1788:                                lprintf(LOG_WARNING,"%04d !SMTP BLACKLISTED SERVER on %s: %s [%s] = %s"
                   1789:                                        ,socket, dnsbl, host_name, ip, inet_ntoa(*dnsbl_result));
                   1790:        } while(0);
                   1791:        free(fromstr);
                   1792:        return(dnsbl_result->s_addr);
                   1793: }
                   1794: 
                   1795: static void parse_mail_address(char* p
                   1796:                                                           ,char* name, size_t name_len
                   1797:                                                           ,char* addr, size_t addr_len)
                   1798: {
                   1799:        char*   tp;
                   1800:        char    tmp[128];
                   1801: 
                   1802:        SKIP_WHITESPACE(p);
                   1803: 
                   1804:        /* Get the address */
                   1805:        if((tp=strchr(p,'<'))!=NULL)
                   1806:                tp++;
                   1807:        else
                   1808:                tp=p;
                   1809:        SKIP_WHITESPACE(tp);
                   1810:        sprintf(addr,"%.*s",addr_len,tp);
                   1811:        truncstr(addr,">( ");
                   1812: 
                   1813:        SAFECOPY(tmp,p);
                   1814:        p=tmp;
                   1815:        /* Get the "name" (if possible) */
                   1816:        if((tp=strchr(p,'('))!=NULL) {                  /* name in parenthesis? */
                   1817:                p=tp+1;
                   1818:                tp=strchr(p,')');
                   1819:        } else if((tp=strchr(p,'"'))!=NULL) {   /* name in quotes? */
                   1820:                p=tp+1;
                   1821:                tp=strchr(p,'"');
                   1822:        } else if(*p=='<') {                                    /* address in brackets? */
                   1823:                p++;
                   1824:                tp=strchr(p,'>');
                   1825:        } else                                                                  /* name, then address in brackets */
                   1826:                tp=strchr(p,'<');
                   1827:        if(tp) *tp=0;
                   1828:        sprintf(name,"%.*s",name_len,p);
                   1829:        truncsp(name);
                   1830: }
                   1831: 
                   1832: static void smtp_thread(void* arg)
                   1833: {
                   1834:        int                     i,j;
                   1835:        int                     rd;
                   1836:        char            str[512];
                   1837:        char            tmp[128];
                   1838:        char            path[MAX_PATH+1];
                   1839:        char            value[INI_MAX_VALUE_LEN];
                   1840:        str_list_t      sec_list;
                   1841:        char*           section;
                   1842:        char            buf[1024],*p,*tp,*cp;
                   1843:        char            hdrfield[512];
                   1844:        char            alias_buf[128];
                   1845:        char            name_alias_buf[128];
                   1846:        char            reverse_path[128];
                   1847:        char            date[64];
                   1848:        char            qwkid[32];
                   1849:        char            rcpt_name[128];
                   1850:        char            rcpt_addr[128];
                   1851:        char            sender[128];
                   1852:        char            sender_addr[128];
                   1853:        char            hello_name[128];
                   1854:        char            user_name[LEN_ALIAS+1];
                   1855:        char            user_pass[LEN_PASS+1];
                   1856:        char            relay_list[MAX_PATH+1];
                   1857:        char            domain_list[MAX_PATH+1];
                   1858:        char            spam_bait[MAX_PATH+1];
                   1859:        char            spam_block[MAX_PATH+1];
                   1860:        char            host_name[128];
                   1861:        char            host_ip[64];
                   1862:        char            dnsbl[256];
                   1863:        char            dnsbl_ip[64];
                   1864:        char*           telegram_buf;
                   1865:        char*           msgbuf;
                   1866:        char            challenge[256];
                   1867:        char            response[128];
                   1868:        char            secret[64];
                   1869:        char            md5_data[384];
                   1870:        char            digest[MD5_DIGEST_SIZE];
                   1871:        char            dest_host[128];
                   1872:        char*           errmsg;
                   1873:        ushort          dest_port;
                   1874:        socklen_t       addr_len;
                   1875:        ushort          hfield_type;
                   1876:        ushort          nettype;
                   1877:        ushort          agent;
                   1878:        uint            usernum;
                   1879:        ulong           lines=0;
                   1880:        ulong           hdr_lines=0;
                   1881:        ulong           hdr_len=0;
                   1882:        ulong           length;
                   1883:        ulong           badcmds=0;
                   1884:        BOOL            esmtp=FALSE;
                   1885:        BOOL            telegram=FALSE;
                   1886:        BOOL            forward=FALSE;
                   1887:        BOOL            no_forward=FALSE;
                   1888:        BOOL            auth_login;
                   1889:        BOOL            routed=FALSE;
                   1890:        BOOL            dnsbl_recvhdr;
                   1891:        BOOL            msg_handled;
                   1892:        uint            subnum=INVALID_SUB;
                   1893:        FILE*           msgtxt=NULL;
                   1894:        char            msgtxt_fname[MAX_PATH+1];
                   1895:        FILE*           rcptlst;
                   1896:        char            rcptlst_fname[MAX_PATH+1];
                   1897:        ushort          rcpt_count=0;
                   1898:        FILE*           proc_err;
                   1899:        char            proc_err_fname[MAX_PATH+1];
                   1900:        char            session_id[MAX_PATH+1];
                   1901:        FILE*           spy=NULL;
                   1902:        SOCKET          socket;
                   1903:        HOSTENT*        host;
                   1904:        int                     smb_error;
                   1905:        smb_t           smb;
                   1906:        smbmsg_t        msg;
                   1907:        smbmsg_t        newmsg;
                   1908:        user_t          user;
                   1909:        user_t          relay_user;
                   1910:        node_t          node;
                   1911:        client_t        client;
                   1912:        smtp_t          smtp=*(smtp_t*)arg;
                   1913:        SOCKADDR_IN server_addr;
                   1914:        IN_ADDR         dnsbl_result;
                   1915:        BOOL*           mailproc_match;
                   1916:        enum {
                   1917:                         SMTP_STATE_INITIAL
                   1918:                        ,SMTP_STATE_HELO
                   1919:                        ,SMTP_STATE_MAIL_FROM
                   1920:                        ,SMTP_STATE_RCPT_TO
                   1921:                        ,SMTP_STATE_DATA_HEADER
                   1922:                        ,SMTP_STATE_DATA_BODY
                   1923: 
                   1924:        } state = SMTP_STATE_INITIAL;
                   1925: 
                   1926:        enum {
                   1927:                         SMTP_CMD_NONE
                   1928:                        ,SMTP_CMD_MAIL
                   1929:                        ,SMTP_CMD_SEND
                   1930:                        ,SMTP_CMD_SOML
                   1931:                        ,SMTP_CMD_SAML
                   1932: 
                   1933:        } cmd = SMTP_CMD_NONE;
                   1934: 
                   1935:        SetThreadName("SMTP Thread");
                   1936:        thread_up(TRUE /* setuid */);
                   1937: 
                   1938:        free(arg);
                   1939: 
                   1940:        socket=smtp.socket;
                   1941: 
                   1942:        lprintf(LOG_DEBUG,"%04d SMTP RX Session thread started", socket);
                   1943: 
                   1944: #ifdef _WIN32
                   1945:        if(startup->inbound_sound[0] && !(startup->options&MAIL_OPT_MUTE)) 
                   1946:                PlaySound(startup->inbound_sound, NULL, SND_ASYNC|SND_FILENAME);
                   1947: #endif
                   1948: 
                   1949:        addr_len=sizeof(server_addr);
                   1950:        if((i=getsockname(socket, (struct sockaddr *)&server_addr,&addr_len))!=0) {
                   1951:                lprintf(LOG_ERR,"%04d !SMTP ERROR %d (%d) getting address/port"
                   1952:                        ,socket, i, ERROR_VALUE);
                   1953:                sockprintf(socket,sys_error);
                   1954:                mail_close_socket(socket);
                   1955:                thread_down();
                   1956:                return;
                   1957:        } 
                   1958: 
                   1959:        if((mailproc_match=alloca(sizeof(BOOL)*mailproc_count))==NULL) {
                   1960:                lprintf(LOG_ERR,"%04d !SMTP ERROR allocating memory for mailproc_match", socket);
                   1961:                sockprintf(socket,sys_error);
                   1962:                mail_close_socket(socket);
                   1963:                thread_down();
                   1964:                return;
                   1965:        } 
                   1966:        memset(mailproc_match,FALSE,sizeof(BOOL)*mailproc_count);
                   1967: 
                   1968:        memset(&smb,0,sizeof(smb));
                   1969:        memset(&msg,0,sizeof(msg));
                   1970:        memset(&user,0,sizeof(user));
                   1971:        memset(&relay_user,0,sizeof(relay_user));
                   1972: 
                   1973:        SAFECOPY(host_ip,inet_ntoa(smtp.client_addr.sin_addr));
                   1974: 
                   1975:        lprintf(LOG_INFO,"%04d SMTP Connection accepted from: %s port %u"
                   1976:                , socket, host_ip, ntohs(smtp.client_addr.sin_port));
                   1977: 
                   1978:        if(startup->options&MAIL_OPT_NO_HOST_LOOKUP)
                   1979:                host=NULL;
                   1980:        else
                   1981:                host=gethostbyaddr ((char *)&smtp.client_addr.sin_addr
                   1982:                        ,sizeof(smtp.client_addr.sin_addr),AF_INET);
                   1983: 
                   1984:        if(host!=NULL && host->h_name!=NULL)
                   1985:                SAFECOPY(host_name,host->h_name);
                   1986:        else
                   1987:                strcpy(host_name,"<no name>");
                   1988: 
                   1989:        if(!(startup->options&MAIL_OPT_NO_HOST_LOOKUP)) {
                   1990:                lprintf(LOG_INFO,"%04d SMTP Hostname: %s", socket, host_name);
                   1991:                for(i=0;host!=NULL && host->h_aliases!=NULL && host->h_aliases[i]!=NULL;i++)
                   1992:                        lprintf(LOG_INFO,"%04d SMTP HostAlias: %s", socket, host->h_aliases[i]);
                   1993: #if 0
                   1994:                if(host!=NULL) {
                   1995:                        ip=resolve_ip(host_name);
                   1996:                        if(ip!=smtp.client_addr.sin_addr.s_addr) {
                   1997:                                smtp.client_addr.sin_addr.s_addr=ip;
                   1998:                                lprintf(LOG_WARNING,"%04d !SMTP DNS/IP ADDRESS MISMATCH: %s vs %s"
                   1999:                                        ,socket, inet_ntoa(smtp.client_addr.sin_addr), host_ip);
                   2000:                                sockprintf(socket,"550 DNS and IP address mismatch");
                   2001:                                mail_close_socket(socket);
                   2002:                                thread_down();
                   2003:                                return;
                   2004:                        }
                   2005:                }
                   2006: #endif
                   2007:        }
                   2008: 
                   2009:        SAFECOPY(hello_name,host_name);
                   2010: 
                   2011:        sprintf(spam_bait,"%sspambait.cfg",scfg.ctrl_dir);
                   2012:        sprintf(spam_block,"%sspamblock.cfg",scfg.ctrl_dir);
                   2013: 
                   2014:        if(trashcan(&scfg,host_ip,"ip") || findstr(host_ip,spam_block)) {
                   2015:                lprintf(LOG_NOTICE,"%04d !SMTP BLOCKED SERVER IP ADDRESS: %s"
                   2016:                        ,socket, host_ip);
                   2017:                sockprintf(socket,"550 Access denied.");
                   2018:                mail_close_socket(socket);
                   2019:                thread_down();
                   2020:                return;
                   2021:        }
                   2022: 
                   2023:        if(trashcan(&scfg,host_name,"host") || findstr(host_name,spam_block)) {
                   2024:                lprintf(LOG_NOTICE,"%04d !SMTP BLOCKED SERVER HOSTNAME: %s"
                   2025:                        ,socket, host_name);
                   2026:                sockprintf(socket,"550 Access denied.");
                   2027:                mail_close_socket(socket);
                   2028:                thread_down();
                   2029:                return;
                   2030:        }
                   2031: 
                   2032:        active_clients++, update_clients();
                   2033: 
                   2034:        /*  SPAM Filters (mail-abuse.org) */
                   2035:        dnsbl_result.s_addr = dns_blacklisted(socket,smtp.client_addr.sin_addr,host_name,dnsbl,dnsbl_ip);
                   2036:        if(dnsbl_result.s_addr) {
                   2037:                lprintf(LOG_WARNING,"%04d !SMTP BLACKLISTED SERVER on %s: %s [%s] = %s"
                   2038:                        ,socket, dnsbl, host_name, dnsbl_ip, inet_ntoa(dnsbl_result));
                   2039:                if(startup->options&MAIL_OPT_DNSBL_REFUSE) {
                   2040:                        SAFEPRINTF2(str,"Listed on %s as %s", dnsbl, inet_ntoa(dnsbl_result));
                   2041:                        spamlog(&scfg, "SMTP", "SESSION REFUSED", str, host_name, dnsbl_ip, NULL, NULL);
                   2042:                        sockprintf(socket
                   2043:                                ,"550 Mail from %s refused due to listing at %s"
                   2044:                                ,dnsbl_ip, dnsbl);
                   2045:                        mail_close_socket(socket);
                   2046:                        lprintf(LOG_WARNING,"%04d !SMTP REFUSED SESSION from blacklisted server"
                   2047:                                ,socket);
                   2048:                        thread_down();
                   2049:                        if(active_clients)
                   2050:                                active_clients--, update_clients();
                   2051:                        return;
                   2052:                }
                   2053:        }
                   2054: 
                   2055:        sprintf(smb.file,"%smail",scfg.data_dir);
                   2056:        if(smb_islocked(&smb)) {
                   2057:                lprintf(LOG_WARNING,"%04d !SMTP MAIL BASE LOCKED: %s"
                   2058:                        ,socket, smb.last_error);
                   2059:                sockprintf(socket,sys_unavail);
                   2060:                mail_close_socket(socket);
                   2061:                thread_down();
                   2062:                if(active_clients)
                   2063:                        active_clients--, update_clients();
                   2064:                return;
                   2065:        }
                   2066: 
                   2067:        srand(time(NULL) ^ (DWORD)GetCurrentThreadId());        /* seed random number generator */
                   2068:        rand(); /* throw-away first result */
                   2069:        SAFEPRINTF3(session_id,"%x%x%lx",socket,rand(),clock());
                   2070: 
                   2071:        SAFEPRINTF2(rcptlst_fname,"%sSBBS_SMTP.%s.lst", scfg.temp_dir, session_id);
                   2072:        rcptlst=fopen(rcptlst_fname,"w+");
                   2073:        if(rcptlst==NULL) {
                   2074:                lprintf(LOG_ERR,"%04d !SMTP ERROR %d creating recipient list: %s"
                   2075:                        ,socket, errno, rcptlst_fname);
                   2076:                sockprintf(socket,sys_error);
                   2077:                mail_close_socket(socket);
                   2078:                thread_down();
                   2079:                if(active_clients)
                   2080:                        active_clients--, update_clients();
                   2081:                return;
                   2082:        }
                   2083: 
                   2084:        if(trashcan(&scfg,host_name,"smtpspy") 
                   2085:                || trashcan(&scfg,host_ip,"smtpspy")) {
                   2086:                sprintf(str,"%ssmtpspy.txt", scfg.logs_dir);
                   2087:                spy=fopen(str,"a");
                   2088:        }
                   2089: 
                   2090:        /* Initialize client display */
                   2091:        client.size=sizeof(client);
                   2092:        client.time=time(NULL);
                   2093:        SAFECOPY(client.addr,host_ip);
                   2094:        SAFECOPY(client.host,host_name);
                   2095:        client.port=ntohs(smtp.client_addr.sin_port);
                   2096:        client.protocol="SMTP";
                   2097:        client.user="<unknown>";
                   2098:        client_on(socket,&client,FALSE /* update */);
                   2099: 
                   2100:        SAFEPRINTF(str,"SMTP: %s",host_ip);
                   2101:        status(str);
                   2102: 
                   2103:        sockprintf(socket,"220 %s Synchronet SMTP Server %s-%s Ready"
                   2104:                ,startup->host_name,revision,PLATFORM_DESC);
                   2105:        while(1) {
                   2106:                rd = sockreadline(socket, buf, sizeof(buf));
                   2107:                if(rd<0) 
                   2108:                        break;
                   2109:                truncsp(buf);
                   2110:                if(spy!=NULL)
                   2111:                        fprintf(spy,"%s\n",buf);
                   2112:                if(relay_user.number==0 && dnsbl_result.s_addr && startup->options&MAIL_OPT_DNSBL_THROTTLE)
                   2113:                        mswait(DNSBL_THROTTLE_VALUE);
                   2114:                if(state>=SMTP_STATE_DATA_HEADER) {
                   2115:                        if(!strcmp(buf,".")) {
                   2116: 
                   2117:                                state=SMTP_STATE_HELO;  /* RESET state machine here in case of error */
                   2118:                                cmd=SMTP_CMD_NONE;
                   2119: 
                   2120:                                if(msgtxt==NULL) {
                   2121:                                        lprintf(LOG_ERR,"%04d !SMTP NO MESSAGE TEXT FILE POINTER?", socket);
                   2122:                                        sockprintf(socket,"554 No message text");
                   2123:                                        continue;
                   2124:                                }
                   2125: 
                   2126:                                if(ftell(msgtxt)<1) {
                   2127:                                        lprintf(LOG_ERR,"%04d !SMTP INVALID MESSAGE LENGTH: %ld (%lu lines)"
                   2128:                                                , socket, ftell(msgtxt), lines);
                   2129:                                        sockprintf(socket,"554 No message text");
                   2130:                                        continue;
                   2131:                                }
                   2132: 
                   2133:                                lprintf(LOG_INFO,"%04d SMTP End of message (body: %lu lines, %lu bytes, header: %lu lines, %lu bytes)"
                   2134:                                        , socket, lines, ftell(msgtxt)-hdr_len, hdr_lines, hdr_len);
                   2135: 
                   2136:                                /* Twit-listing (sender's name and e-mail addresses) here */
                   2137:                                sprintf(path,"%stwitlist.cfg",scfg.ctrl_dir);
                   2138:                                if(fexist(path) && (findstr(sender,path) || findstr(sender_addr,path))) {
                   2139:                                        lprintf(LOG_NOTICE,"%04d !SMTP FILTERING TWIT-LISTED SENDER: %s <%s>"
                   2140:                                                ,socket, sender, sender_addr);
                   2141:                                        SAFEPRINTF2(tmp,"Twit-listed sender: %s <%s>", sender, sender_addr);
                   2142:                                        spamlog(&scfg, "SMTP", "REFUSED", tmp, host_name, host_ip, rcpt_addr, reverse_path);
                   2143:                                        sockprintf(socket, "554 Sender not allowed.");
                   2144:                                        continue;
                   2145:                                }
                   2146: 
                   2147:                                if(telegram==TRUE) {            /* Telegram */
                   2148:                                        const char* head="\1n\1h\1cInstant Message\1n from \1h\1y";
                   2149:                                        const char* tail="\1n:\r\n\1h";
                   2150:                                        rewind(msgtxt);
                   2151:                                        length=filelength(fileno(msgtxt));
                   2152:                                        
                   2153:                                        p=strchr(sender_addr,'@');
                   2154:                                        if(p==NULL || resolve_ip(p+1)!=smtp.client_addr.sin_addr.s_addr) 
                   2155:                                                /* Append real IP and hostname if different */
                   2156:                                                safe_snprintf(str,sizeof(str),"%s%s\r\n\1w[\1n%s\1h] (\1n%s\1h)%s"
                   2157:                                                        ,head,sender_addr,host_ip,host_name,tail);
                   2158:                                        else
                   2159:                                                safe_snprintf(str,sizeof(str),"%s%s%s",head,sender_addr,tail);
                   2160:                                        
                   2161:                                        if((telegram_buf=(char*)malloc(length+strlen(str)+1))==NULL) {
                   2162:                                                lprintf(LOG_CRIT,"%04d !SMTP ERROR allocating %lu bytes of memory for telegram from %s"
                   2163:                                                        ,socket,length+strlen(str)+1,sender_addr);
                   2164:                                                sockprintf(socket, "452 Insufficient system storage");
                   2165:                                                continue; 
                   2166:                                        }
                   2167:                                        strcpy(telegram_buf,str);       /* can't use SAFECOPY here */
                   2168:                                        if(fread(telegram_buf+strlen(str),1,length,msgtxt)!=length) {
                   2169:                                                lprintf(LOG_ERR,"%04d !SMTP ERROR reading %lu bytes from telegram file"
                   2170:                                                        ,socket,length);
                   2171:                                                sockprintf(socket, "452 Insufficient system storage");
                   2172:                                                free(telegram_buf);
                   2173:                                                continue; 
                   2174:                                        }
                   2175:                                        telegram_buf[length+strlen(str)]=0;     /* Need ASCIIZ */
                   2176: 
                   2177:                                        /* Send telegram to users */
                   2178:                                        sec_list=iniReadSectionList(rcptlst,NULL);      /* Each section is a recipient */
                   2179:                                        for(rcpt_count=0; sec_list!=NULL
                   2180:                                                && sec_list[rcpt_count]!=NULL 
                   2181:                                                && rcpt_count<startup->max_recipients; rcpt_count++) {
                   2182: 
                   2183:                                                section=sec_list[rcpt_count];
                   2184: 
                   2185:                                                SAFECOPY(rcpt_name,iniReadString(rcptlst,section        ,smb_hfieldtype(RECIPIENT),"unknown",value));
                   2186:                                                usernum=iniReadInteger(rcptlst,section                          ,smb_hfieldtype(RECIPIENTEXT),0);
                   2187:                                                SAFECOPY(rcpt_addr,iniReadString(rcptlst,section        ,smb_hfieldtype(RECIPIENTNETADDR),rcpt_name,value));
                   2188: 
                   2189:                                                if((i=putsmsg(&scfg,usernum,telegram_buf))==0)
                   2190:                                                        lprintf(LOG_INFO,"%04d SMTP Created telegram (%ld/%u bytes) from %s to %s <%s>"
                   2191:                                                                ,socket, length, strlen(telegram_buf), sender_addr, rcpt_name, rcpt_addr);
                   2192:                                                else
                   2193:                                                        lprintf(LOG_ERR,"%04d !SMTP ERROR %d creating telegram from %s to %s <%s>"
                   2194:                                                                ,socket, i, sender_addr, rcpt_name, rcpt_addr);
                   2195:                                        }
                   2196:                                        iniFreeStringList(sec_list);
                   2197:                                        free(telegram_buf);
                   2198:                                        sockprintf(socket,ok_rsp);
                   2199:                                        telegram=FALSE;
                   2200:                                        continue;
                   2201:                                }
                   2202: 
                   2203:                                fclose(msgtxt), msgtxt=NULL;
                   2204:                                fclose(rcptlst), rcptlst=NULL;
                   2205: 
                   2206:                                /* External Mail Processing here */
                   2207:                                msg_handled=FALSE;
                   2208:                                if(mailproc_count) {
                   2209:                                        SAFEPRINTF2(proc_err_fname,"%sSBBS_SMTP.%s.err", scfg.temp_dir, session_id);
                   2210:                                        remove(proc_err_fname);
                   2211: 
                   2212:                                        for(i=0;i<mailproc_count;i++) {
                   2213: 
                   2214:                                                /* This processor is for specific recipients only and did not match */
                   2215:                                                if(strListCount(mailproc_list[i].to) && !mailproc_match[i])
                   2216:                                                        continue;
                   2217: 
                   2218:                                                if(!mailproc_list[i].passthru)
                   2219:                                                        msg_handled=TRUE;
                   2220: 
                   2221:                                                mailcmdstr(mailproc_list[i].cmdline
                   2222:                                                        ,msgtxt_fname, rcptlst_fname, proc_err_fname
                   2223:                                                        ,host_name, host_ip, relay_user.number
                   2224:                                                        ,sender, sender_addr, reverse_path, str);
                   2225:                                                lprintf(LOG_DEBUG,"%04d SMTP Executing external process: %s"
                   2226:                                                        ,socket, str);
                   2227: 
                   2228:                                                if(mailproc_list[i].native) {
                   2229:                                                        if((j=system(str))!=0)
                   2230:                                                                lprintf(LOG_WARNING,"%04d !SMTP system(%s) returned %d (errno: %d)"
                   2231:                                                                        ,socket, str, j, errno);
                   2232:                                                } else  /* JavaScript */
                   2233:                                                        js_mailproc(socket, &client, &relay_user, str /* cmdline */
                   2234:                                                                ,msgtxt_fname, rcptlst_fname, proc_err_fname
                   2235:                                                                ,sender, sender_addr, reverse_path);
                   2236:                                                if(flength(proc_err_fname)>0)
                   2237:                                                        break;
                   2238:                                                if(!fexist(msgtxt_fname) || !fexist(rcptlst_fname))
                   2239:                                                        break;
                   2240:                                        }
                   2241:                                        if(flength(proc_err_fname)>0 
                   2242:                                                && (proc_err=fopen(proc_err_fname,"r"))!=NULL) {
                   2243:                                                while(!feof(proc_err)) {
                   2244:                                                        if(!fgets(str,sizeof(str),proc_err))
                   2245:                                                                break;
                   2246:                                                        truncsp(str);
                   2247:                                                        lprintf(LOG_WARNING,"%04d !SMTP external process error: %s", socket, str);
                   2248:                                                        i=atoi(str);
                   2249:                                                        if(i>=100 && i<1000)
                   2250:                                                                sockprintf(socket,"%s", str);
                   2251:                                                        else
                   2252:                                                                sockprintf(socket,"554%c%s"
                   2253:                                                                        ,ftell(proc_err)<filelength(fileno(proc_err)) ? '-' : ' '
                   2254:                                                                        ,str);
                   2255:                                                }
                   2256:                                                fclose(proc_err);
                   2257:                                                msg_handled=TRUE;
                   2258:                                        }
                   2259:                                        else if(!fexist(msgtxt_fname) || !fexist(rcptlst_fname)) {
                   2260:                                                lprintf(LOG_WARNING,"%04d SMTP External process removed %s file"
                   2261:                                                        ,socket, fexist(msgtxt_fname)==FALSE ? "message text" : "recipient list");
                   2262:                                                sockprintf(socket,ok_rsp);
                   2263:                                                msg_handled=TRUE;
                   2264:                                        }
                   2265:                                        else if(msg_handled)
                   2266:                                                sockprintf(socket,ok_rsp);
                   2267:                                        remove(proc_err_fname); /* Remove error file here */
                   2268:                                }
                   2269: 
                   2270:                                /* Re-open files */
                   2271:                                /* We must do this before continuing for handled msgs */
                   2272:                                /* to prevent freopen(NULL) and orphaned temp files */
                   2273:                                if((rcptlst=fopen(rcptlst_fname,fexist(rcptlst_fname) ? "r":"w+"))==NULL) {
                   2274:                                        lprintf(LOG_ERR,"%04d !SMTP ERROR %d re-opening recipient list: %s"
                   2275:                                                ,socket, errno, rcptlst_fname);
                   2276:                                        if(!msg_handled)
                   2277:                                                sockprintf(socket,sys_error);
                   2278:                                        continue;
                   2279:                                }
                   2280:                        
                   2281:                                if(msg_handled) {
                   2282:                                        lprintf(LOG_NOTICE,"%04d SMTP Message handled by external mail processor"
                   2283:                                                ,socket);
                   2284:                                        continue;
                   2285:                                }
                   2286: 
                   2287:                                if((msgtxt=fopen(msgtxt_fname,"rb"))==NULL) {
                   2288:                                        lprintf(LOG_ERR,"%04d !SMTP ERROR %d re-opening message file: %s"
                   2289:                                                ,socket, errno, msgtxt_fname);
                   2290:                                        sockprintf(socket,sys_error);
                   2291:                                        continue;
                   2292:                                }
                   2293: 
                   2294:                                /* Initialize message header */
                   2295:                                smb_freemsgmem(&msg);
                   2296:                                memset(&msg,0,sizeof(smbmsg_t));                
                   2297: 
                   2298:                                /* Parse message header here */
                   2299:                                hfield_type=UNKNOWN;
                   2300:                                smb_error=SMB_SUCCESS; /* no SMB error */
                   2301:                                errmsg="452 Insufficient system storage";
                   2302:                                while(!feof(msgtxt)) {
                   2303:                                        if(!fgets(buf,sizeof(buf),msgtxt))
                   2304:                                                break;
                   2305:                                        truncsp(buf);
                   2306:                                        if(buf[0]==0)   /* blank line marks end of header */
                   2307:                                                break;
                   2308: 
                   2309:                                        if(!strnicmp(buf, "SUBJECT:",8)) {
                   2310:                                                p=buf+8;
                   2311:                                                SKIP_WHITESPACE(p);
                   2312:                                                if(relay_user.number==0 && dnsbl_result.s_addr && startup->dnsbl_tag[0]
                   2313:                                                        && !(startup->options&MAIL_OPT_DNSBL_IGNORE)) {
                   2314:                                                        safe_snprintf(str,sizeof(str),"%.*s: %.*s"
                   2315:                                                                ,(int)sizeof(str)/2, startup->dnsbl_tag
                   2316:                                                                ,(int)sizeof(str)/2, p);
                   2317:                                                        p=str;
                   2318:                                                        lprintf(LOG_WARNING,"%04d !SMTP TAGGED MAIL SUBJECT from blacklisted server with: %s"
                   2319:                                                                ,socket, startup->dnsbl_tag);
                   2320:                                                }
                   2321:                                                smb_hfield_str(&msg, SUBJECT, p);
                   2322:                                                continue;
                   2323:                                        }
                   2324:                                        if(!strnicmp(buf, "FROM:", 5)
                   2325:                                                && !chk_email_addr(socket,buf+5,host_name,host_ip,rcpt_addr,reverse_path,"FROM")) {
                   2326:                                                errmsg="554 Sender not allowed.";
                   2327:                                                smb_error=SMB_FAILURE;
                   2328:                                                break;
                   2329:                                        }
                   2330:                                        if(!strnicmp(buf, "TO:", 3)
                   2331:                                                && !chk_email_addr(socket,buf+3,host_name,host_ip,rcpt_addr,reverse_path,"TO")) {
                   2332:                                                errmsg="550 Unknown user.";
                   2333:                                                smb_error=SMB_FAILURE;
                   2334:                                                break;
                   2335:                                        }
                   2336:                                        if((smb_error=parse_header_field(buf,&msg,&hfield_type))!=SMB_SUCCESS) {
                   2337:                                                if(smb_error==SMB_ERR_HDR_LEN)
                   2338:                                                        lprintf(LOG_WARNING,"%04d !SMTP MESSAGE HEADER EXCEEDS %u BYTES"
                   2339:                                                                ,socket, SMB_MAX_HDR_LEN);
                   2340:                                                else
                   2341:                                                        lprintf(LOG_ERR,"%04d !SMTP ERROR %d adding header field: %s"
                   2342:                                                                ,socket, smb_error, buf);
                   2343:                                                break;
                   2344:                                        }
                   2345:                                }
                   2346:                                if(smb_error!=SMB_SUCCESS) {    /* SMB Error */
                   2347:                                        sockprintf(socket, errmsg);
                   2348:                                        continue;
                   2349:                                }
                   2350:                                if((p=smb_get_hfield(&msg, RFC822TO, NULL))!=NULL) {
                   2351:                                        if(*p=='<')     p++;
                   2352:                                        SAFECOPY(rcpt_name,p);
                   2353:                                        truncstr(rcpt_name,">");
                   2354:                                }
                   2355:                                if((p=smb_get_hfield(&msg, RFC822FROM, NULL))!=NULL) {
                   2356:                                        parse_mail_address(p 
                   2357:                                                ,sender         ,sizeof(sender)-1
                   2358:                                                ,sender_addr,sizeof(sender_addr)-1);
                   2359:                                }
                   2360: 
                   2361:                                /* SPAM Filtering/Logging */
                   2362:                                if(relay_user.number==0 && msg.subj!=NULL && trashcan(&scfg,msg.subj,"subject")) {
                   2363:                                        lprintf(LOG_WARNING,"%04d !SMTP BLOCKED SUBJECT (%s) from: %s"
                   2364:                                                ,socket, msg.subj, reverse_path);
                   2365:                                        SAFEPRINTF2(tmp,"Blocked subject (%s) from: %s"
                   2366:                                                ,msg.subj, reverse_path);
                   2367:                                        spamlog(&scfg, "SMTP", "REFUSED"
                   2368:                                                ,tmp, host_name, host_ip, rcpt_addr, reverse_path);
                   2369:                                        sockprintf(socket, "554 Subject not allowed.");
                   2370:                                        continue;
                   2371:                                }
                   2372:                                dnsbl_recvhdr=FALSE;
                   2373:                                if(startup->options&MAIL_OPT_DNSBL_CHKRECVHDRS)  {
                   2374:                                        for(i=0;!dnsbl_result.s_addr && i<msg.total_hfields;i++)  {
                   2375:                                                if(msg.hfield[i].type == RFC822HEADER
                   2376:                                                        && strnicmp(msg.hfield_dat[i],"Received:",9)==0)  {
                   2377:                                                        if(chk_received_hdr(socket,msg.hfield_dat[i],&dnsbl_result,dnsbl,dnsbl_ip)) {
                   2378:                                                                dnsbl_recvhdr=TRUE;
                   2379:                                                                break;
                   2380:                                                        }
                   2381:                                                }
                   2382:                                        }
                   2383:                                }
                   2384:                                if(relay_user.number==0 && dnsbl_result.s_addr) {
                   2385:                                        if(startup->options&MAIL_OPT_DNSBL_IGNORE) {
                   2386:                                                lprintf(LOG_WARNING,"%04d !SMTP IGNORED MAIL from blacklisted server"
                   2387:                                                        ,socket);
                   2388:                                                SAFEPRINTF2(str,"Listed on %s as %s", dnsbl, inet_ntoa(dnsbl_result));
                   2389:                                                spamlog(&scfg, "SMTP", "IGNORED"
                   2390:                                                        ,str, host_name, dnsbl_ip, rcpt_addr, reverse_path);
                   2391:                                                /* pretend we received it */
                   2392:                                                sockprintf(socket,ok_rsp);
                   2393:                                                continue;
                   2394:                                        }
                   2395:                                        /* tag message as spam */
                   2396:                                        if(startup->dnsbl_hdr[0]) {
                   2397:                                                safe_snprintf(str,sizeof(str),"%s: %s is listed on %s as %s"
                   2398:                                                        ,startup->dnsbl_hdr, dnsbl_ip
                   2399:                                                        ,dnsbl, inet_ntoa(dnsbl_result));
                   2400:                                                smb_hfield_str(&msg, RFC822HEADER, str);
                   2401:                                                lprintf(LOG_WARNING,"%04d !SMTP TAGGED MAIL HEADER from blacklisted server with: %s"
                   2402:                                                        ,socket, startup->dnsbl_hdr);
                   2403:                                        }
                   2404:                                        if(startup->dnsbl_hdr[0] || startup->dnsbl_tag[0]) {
                   2405:                                                SAFEPRINTF2(str,"Listed on %s as %s", dnsbl, inet_ntoa(dnsbl_result));
                   2406:                                                spamlog(&scfg, "SMTP", "TAGGED", str, host_name, dnsbl_ip, rcpt_addr, reverse_path);
                   2407:                                        }
                   2408:                                }
                   2409:                                if(dnsbl_recvhdr)                       /* DNSBL-listed IP found in Received header? */
                   2410:                                        dnsbl_result.s_addr=0;  /* Reset DNSBL look-up result between messages */
                   2411: 
                   2412:                                if(sender[0]==0) {
                   2413:                                        lprintf(LOG_WARNING,"%04d !SMTP MISSING mail header 'FROM' field", socket);
                   2414:                                        sockprintf(socket, "554 Mail header missing 'FROM' field");
                   2415:                                        subnum=INVALID_SUB;
                   2416:                                        continue;
                   2417:                                }
                   2418:                                nettype=NET_INTERNET;
                   2419:                                smb_hfield_str(&msg, SMTPREVERSEPATH, reverse_path);
                   2420:                                smb_hfield_str(&msg, SENDER, sender);
                   2421:                                smb_hfield(&msg, SENDERNETTYPE, sizeof(nettype), &nettype);
                   2422:                                smb_hfield_str(&msg, SENDERNETADDR, sender_addr);
                   2423:                                if(msg.subj==NULL)
                   2424:                                        smb_hfield(&msg, SUBJECT, 0, NULL);
                   2425: 
                   2426:                                length=filelength(fileno(msgtxt))-ftell(msgtxt);
                   2427: 
                   2428:                                if(startup->max_msg_size && length>startup->max_msg_size) {
                   2429:                                        lprintf(LOG_WARNING,"%04d !SMTP message size (%lu) exceeds maximum: %lu bytes"
                   2430:                                                ,socket,length,startup->max_msg_size);
                   2431:                                        sockprintf(socket, "552 Message size (%lu) exceeds maximum: %lu bytes"
                   2432:                                                ,length,startup->max_msg_size);
                   2433:                                        subnum=INVALID_SUB;
                   2434:                                        continue;
                   2435:                                }
                   2436: 
                   2437:                                if((msgbuf=(char*)malloc(length+1))==NULL) {
                   2438:                                        lprintf(LOG_CRIT,"%04d !SMTP ERROR allocating %d bytes of memory"
                   2439:                                                ,socket,length+1);
                   2440:                                        sockprintf(socket, "452 Insufficient system storage");
                   2441:                                        subnum=INVALID_SUB;
                   2442:                                        continue;
                   2443:                                }
                   2444:                                fread(msgbuf,length,1,msgtxt);
                   2445:                                msgbuf[length]=0;       /* ASCIIZ */
                   2446: 
                   2447:                                /* Do external JavaScript processing here? */
                   2448: 
                   2449:                                if(subnum!=INVALID_SUB) {       /* Message Base */
                   2450:                                        if(relay_user.number==0)
                   2451:                                                memset(&relay_user,0,sizeof(relay_user));
                   2452: 
                   2453:                                        if(!chk_ar(&scfg,scfg.grp[scfg.sub[subnum]->grp]->ar, &relay_user)
                   2454:                                                || !chk_ar(&scfg,scfg.sub[subnum]->ar, &relay_user)
                   2455:                                                || !chk_ar(&scfg,scfg.sub[subnum]->post_ar, &relay_user)) {
                   2456:                                                lprintf(LOG_WARNING,"%04d !SMTP %s has insufficient access to post on %s"
                   2457:                                                        ,socket, sender_addr, scfg.sub[subnum]->sname);
                   2458:                                                sockprintf(socket,"550 Insufficient access");
                   2459:                                                subnum=INVALID_SUB;
                   2460:                                                continue;
                   2461:                                        }
                   2462: 
                   2463:                                        if(rcpt_name[0]==0)
                   2464:                                                strcpy(rcpt_name,"All");
                   2465:                                        smb_hfield_str(&msg, RECIPIENT, rcpt_name);
                   2466: 
                   2467:                                        smb.subnum=subnum;
                   2468:                                        if((i=savemsg(&scfg, &smb, &msg, &client, msgbuf))!=SMB_SUCCESS) {
                   2469:                                                lprintf(LOG_WARNING,"%04d !SMTP ERROR %d (%s) saving message"
                   2470:                                                        ,socket,i,smb.last_error);
                   2471:                                                sockprintf(socket, "452 ERROR %d (%s) saving message"
                   2472:                                                        ,i,smb.last_error);
                   2473:                                        } else {
                   2474:                                                lprintf(LOG_INFO,"%04d SMTP %s posted a message on %s"
                   2475:                                                        ,socket, sender_addr, scfg.sub[subnum]->sname);
                   2476:                                                sockprintf(socket,ok_rsp);
                   2477:                                                signal_smtp_sem();
                   2478:                                        }
                   2479:                                        free(msgbuf);
                   2480:                                        smb_close(&smb);
                   2481:                                        subnum=INVALID_SUB;
                   2482:                                        continue;
                   2483:                                }
                   2484: 
                   2485:                                /* E-mail */
                   2486:                                smb.subnum=INVALID_SUB;
                   2487:                                i=savemsg(&scfg, &smb, &msg, &client, msgbuf);
                   2488:                                free(msgbuf);
                   2489:                                if(i!=SMB_SUCCESS) {
                   2490:                                        smb_close(&smb);
                   2491:                                        lprintf(LOG_ERR,"%04d !SMTP ERROR %d (%s) saving message"
                   2492:                                                ,socket,i,smb.last_error);
                   2493:                                        sockprintf(socket, "452 ERROR %d (%s) saving message"
                   2494:                                                ,i,smb.last_error);
                   2495:                                        continue;
                   2496:                                }
                   2497: 
                   2498:                                sec_list=iniReadSectionList(rcptlst,NULL);      /* Each section is a recipient */
                   2499:                                for(rcpt_count=0; sec_list!=NULL
                   2500:                                        && sec_list[rcpt_count]!=NULL 
                   2501:                                        && rcpt_count<startup->max_recipients; rcpt_count++) {
                   2502:                                
                   2503:                                        section=sec_list[rcpt_count];
                   2504: 
                   2505:                                        SAFECOPY(rcpt_name,iniReadString(rcptlst,section        ,smb_hfieldtype(RECIPIENT),"unknown",value));
                   2506:                                        usernum=iniReadInteger(rcptlst,section                          ,smb_hfieldtype(RECIPIENTEXT),0);
                   2507:                                        agent=iniReadShortInt(rcptlst,section                           ,smb_hfieldtype(RECIPIENTAGENT),AGENT_PERSON);
                   2508:                                        nettype=iniReadShortInt(rcptlst,section                         ,smb_hfieldtype(RECIPIENTNETTYPE),NET_NONE);
                   2509:                                        sprintf(str,"#%u",usernum);
                   2510:                                        SAFECOPY(rcpt_addr,iniReadString(rcptlst,section        ,smb_hfieldtype(RECIPIENTNETADDR),str,value));
                   2511: 
                   2512:                                        if(nettype==NET_NONE /* Local destination */ && usernum==0) {
                   2513:                                                lprintf(LOG_ERR,"%04d !SMTP can't deliver mail to user #0"
                   2514:                                                        ,socket);
                   2515:                                                break;
                   2516:                                        }
                   2517: 
                   2518:                                        if((i=smb_copymsgmem(&smb,&newmsg,&msg))!=SMB_SUCCESS) {
                   2519:                                                lprintf(LOG_ERR,"%04d !SMTP ERROR %d (%s) copying message"
                   2520:                                                        ,socket, i, smb.last_error);
                   2521:                                                break;
                   2522:                                        }
                   2523: 
                   2524:                                        snprintf(hdrfield,sizeof(hdrfield),
                   2525:                                                "Received: from %s (%s [%s])\r\n"
                   2526:                                                "          by %s [%s] (Synchronet Mail Server %s-%s) with %s\r\n"
                   2527:                                                "          for %s; %s"
                   2528:                                                ,host_name,hello_name,host_ip
                   2529:                                                ,startup->host_name,inet_ntoa(server_addr.sin_addr)
                   2530:                                                ,revision,PLATFORM_DESC
                   2531:                                                ,esmtp ? "ESMTP" : "SMTP"
                   2532:                                                ,rcpt_name,msgdate(msg.hdr.when_imported,date));
                   2533:                                        smb_hfield_str(&newmsg, RFC822HEADER, hdrfield);
                   2534: 
                   2535:                                        smb_hfield_str(&newmsg, RECIPIENT, rcpt_name);
                   2536: 
                   2537:                                        if(usernum) {   /* Local destination or QWKnet routed */
                   2538:                                                /* This is required for fixsmb to be able to rebuild the index */
                   2539:                                                sprintf(str,"%u",usernum);
                   2540:                                                smb_hfield_str(&newmsg, RECIPIENTEXT, str);
                   2541:                                        }
                   2542:                                        if(nettype!=NET_NONE) {
                   2543:                                                smb_hfield(&newmsg, RECIPIENTNETTYPE, sizeof(nettype), &nettype);
                   2544:                                                smb_hfield_str(&newmsg, RECIPIENTNETADDR, rcpt_addr);
                   2545:                                        }
                   2546:                                        if(agent!=newmsg.to_agent)
                   2547:                                                smb_hfield(&newmsg, RECIPIENTAGENT, sizeof(agent), &agent);
                   2548: 
                   2549:                                        i=smb_addmsghdr(&smb,&newmsg,SMB_SELFPACK);
                   2550:                                        smb_freemsgmem(&newmsg);
                   2551:                                        if(i!=SMB_SUCCESS) {
                   2552:                                                lprintf(LOG_ERR,"%04d !SMTP ERROR %d (%s) adding message header"
                   2553:                                                        ,socket, i, smb.last_error);
                   2554:                                                break;
                   2555:                                        }
                   2556:                                        lprintf(LOG_INFO,"%04d SMTP Created message #%ld from %s to %s <%s>"
                   2557:                                                ,socket, newmsg.hdr.number, sender, rcpt_name, rcpt_addr);
                   2558:                                        if(!(startup->options&MAIL_OPT_NO_NOTIFY) && usernum
                   2559:                                                && !dnsbl_recvhdr && !dnsbl_result.s_addr) {
                   2560:                                                safe_snprintf(str,sizeof(str)
                   2561:                                                        ,"\7\1n\1hOn %.24s\r\n\1m%s \1n\1msent you e-mail from: "
                   2562:                                                        "\1h%s\1n\r\n"
                   2563:                                                        ,timestr(&scfg,(time_t*)&newmsg.hdr.when_imported.time,tmp)
                   2564:                                                        ,sender,sender_addr);
                   2565:                                                if(!newmsg.idx.to) {    /* Forwarding */
                   2566:                                                        strcat(str,"\1mand it was automatically forwarded to: \1h");
                   2567:                                                        strcat(str,user.netmail);
                   2568:                                                        strcat(str,"\1n\r\n");
                   2569:                                                }
                   2570:                                                putsmsg(&scfg, usernum, str);
                   2571:                                        }
                   2572:                                }
                   2573:                                iniFreeStringList(sec_list);
                   2574:                                if(rcpt_count<1) {
                   2575:                                        smb_freemsg_dfields(&smb,&msg,SMB_ALL_REFS);
                   2576:                                        sockprintf(socket, "452 Insufficient system storage");
                   2577:                                }
                   2578:                                else {
                   2579:                                        if(rcpt_count>1)
                   2580:                                                smb_incmsg_dfields(&smb,&msg,(ushort)(rcpt_count-1));
                   2581:                                        sockprintf(socket,ok_rsp);
                   2582:                                        signal_smtp_sem();
                   2583:                                }
                   2584: #if 0 /* This shouldn't be necessary here */
                   2585:                                smb_close_da(&smb);
                   2586: #endif
                   2587:                                smb_close(&smb);
                   2588:                                continue;
                   2589:                        }
                   2590:                        if(buf[0]==0 && state==SMTP_STATE_DATA_HEADER) {        
                   2591:                                state=SMTP_STATE_DATA_BODY;     /* Null line separates header and body */
                   2592:                                lines=0;
                   2593:                                if(msgtxt!=NULL) {
                   2594:                                        fprintf(msgtxt, "\r\n");
                   2595:                                        hdr_len=ftell(msgtxt);
                   2596:                                }
                   2597:                                continue;
                   2598:                        }
                   2599:                        if(state==SMTP_STATE_DATA_BODY) {
                   2600:                                p=buf;
                   2601:                                if(*p=='.') p++;        /* Transparency (RFC821 4.5.2) */
                   2602:                                if(msgtxt!=NULL) 
                   2603:                                        fprintf(msgtxt, "%s\r\n", p);
                   2604:                                lines++;
                   2605:                                /* release time-slices every x lines */
                   2606:                                if(startup->lines_per_yield &&
                   2607:                                        !(lines%startup->lines_per_yield))      
                   2608:                                        YIELD();
                   2609:                                continue;
                   2610:                        }
                   2611:                        /* RFC822 Header parsing */
                   2612:                        if(startup->options&MAIL_OPT_DEBUG_RX_HEADER)
                   2613:                                lprintf(LOG_DEBUG,"%04d SMTP %s",socket, buf);
                   2614: 
                   2615:                        if(!strnicmp(buf, "FROM:", 5))
                   2616:                                parse_mail_address(buf+5
                   2617:                                        ,sender,                sizeof(sender)-1
                   2618:                                        ,sender_addr,   sizeof(sender_addr)-1);
                   2619: 
                   2620:                        if(msgtxt!=NULL) 
                   2621:                                fprintf(msgtxt, "%s\r\n", buf);
                   2622:                        hdr_lines++;
                   2623:                        continue;
                   2624:                }
                   2625:                strip_ctrl(buf);
                   2626:                lprintf(LOG_DEBUG,"%04d SMTP RX: %s", socket, buf);
                   2627:                if(!strnicmp(buf,"HELO",4)) {
                   2628:                        p=buf+4;
                   2629:                        SKIP_WHITESPACE(p);
                   2630:                        SAFECOPY(hello_name,p);
                   2631:                        sockprintf(socket,"250 %s",startup->host_name);
                   2632:                        esmtp=FALSE;
                   2633:                        state=SMTP_STATE_HELO;
                   2634:                        cmd=SMTP_CMD_NONE;
                   2635:                        telegram=FALSE;
                   2636:                        subnum=INVALID_SUB;
                   2637:                        continue;
                   2638:                }
                   2639:                if(!strnicmp(buf,"EHLO",4)) {
                   2640:                        p=buf+4;
                   2641:                        SKIP_WHITESPACE(p);
                   2642:                        SAFECOPY(hello_name,p);
                   2643:                        sockprintf(socket,"250-%s",startup->host_name);
                   2644:                        sockprintf(socket,"250 AUTH PLAIN LOGIN CRAM-MD5");
                   2645:                        esmtp=TRUE;
                   2646:                        state=SMTP_STATE_HELO;
                   2647:                        cmd=SMTP_CMD_NONE;
                   2648:                        telegram=FALSE;
                   2649:                        subnum=INVALID_SUB;
                   2650:                        continue;
                   2651:                }
                   2652:                if((auth_login=(stricmp(buf,"AUTH LOGIN")==0))==TRUE 
                   2653:                        || stricmp(buf,"AUTH PLAIN")==0) {
                   2654:                        if(auth_login)
                   2655:                                sockprintf(socket,"334 VXNlcm5hbWU6");  /* Base64-encoded "Username:" */
                   2656:                        else
                   2657:                                sockprintf(socket,"334 Username:");
                   2658:                        if((rd=sockreadline(socket, buf, sizeof(buf)))<1) {
                   2659:                                sockprintf(socket,badarg_rsp);
                   2660:                                continue;
                   2661:                        }
                   2662:                        if(startup->options&MAIL_OPT_DEBUG_RX_RSP) 
                   2663:                                lprintf(LOG_DEBUG,"%04d RX: %s",socket,buf);
                   2664:                        if(auth_login) {
                   2665:                                if(b64_decode(user_name,sizeof(user_name),buf,rd)<1) {
                   2666:                                        sockprintf(socket,badarg_rsp);
                   2667:                                        continue;
                   2668:                                }
                   2669:                        } else
                   2670:                                SAFECOPY(user_name,buf);
                   2671: 
                   2672:                        if(auth_login)
                   2673:                                sockprintf(socket,"334 UGFzc3dvcmQ6");  /* Base64-encoded "Password:" */
                   2674:                        else
                   2675:                                sockprintf(socket,"334 Password:");
                   2676:                        if((rd=sockreadline(socket, buf, sizeof(buf)))<1) {
                   2677:                                sockprintf(socket,badarg_rsp);
                   2678:                                continue;
                   2679:                        }
                   2680:                        if(startup->options&MAIL_OPT_DEBUG_RX_RSP) 
                   2681:                                lprintf(LOG_DEBUG,"%04d RX: %s",socket,buf);
                   2682:                        if(auth_login) {
                   2683:                                if(b64_decode(user_pass,sizeof(user_pass),buf,rd)<1) {
                   2684:                                        sockprintf(socket,badarg_rsp);
                   2685:                                        continue;
                   2686:                                }
                   2687:                        } else
                   2688:                                SAFECOPY(user_pass,buf);
                   2689:                        if((relay_user.number=matchuser(&scfg,user_name,FALSE))==0) {
                   2690:                                if(scfg.sys_misc&SM_ECHO_PW)
                   2691:                                        lprintf(LOG_WARNING,"%04d !SMTP UNKNOWN USER: %s (password: %s)"
                   2692:                                                ,socket, user_name, user_pass);
                   2693:                                else
                   2694:                                        lprintf(LOG_WARNING,"%04d !SMTP UNKNOWN USER: %s"
                   2695:                                                ,socket, user_name);
                   2696:                                sockprintf(socket,badauth_rsp);
                   2697:                                continue;
                   2698:                        }
                   2699:                        if((i=getuserdat(&scfg, &relay_user))!=0) {
                   2700:                                lprintf(LOG_ERR,"%04d !SMTP ERROR %d getting data on user (%s)"
                   2701:                                        ,socket, i, user_name);
                   2702:                                sockprintf(socket,badauth_rsp);
                   2703:                                relay_user.number=0;
                   2704:                                continue;
                   2705:                        }
                   2706:                        if(relay_user.misc&(DELETED|INACTIVE)) {
                   2707:                                lprintf(LOG_WARNING,"%04d !SMTP DELETED or INACTIVE user #%u (%s)"
                   2708:                                        ,socket, relay_user.number, user_name);
                   2709:                                sockprintf(socket,badauth_rsp);
                   2710:                                relay_user.number=0;
                   2711:                                break;
                   2712:                        }
                   2713:                        if(stricmp(user_pass,relay_user.pass)) {
                   2714:                                if(scfg.sys_misc&SM_ECHO_PW)
                   2715:                                        lprintf(LOG_WARNING,"%04d !SMTP FAILED Password attempt for user %s: '%s' expected '%s'"
                   2716:                                                ,socket, user_name, user_pass, relay_user.pass);
                   2717:                                else
                   2718:                                        lprintf(LOG_WARNING,"%04d !SMTP FAILED Password attempt for user %s"
                   2719:                                                ,socket, user_name);
                   2720:                                sockprintf(socket,badauth_rsp);
                   2721:                                relay_user.number=0;
                   2722:                                break;
                   2723:                        }
                   2724:                        /* Update client display */
                   2725:                        client.user=relay_user.alias;
                   2726:                        client_on(socket,&client,TRUE /* update */);
                   2727: 
                   2728:                        lprintf(LOG_INFO,"%04d SMTP %s authenticated using %s authentication"
                   2729:                                ,socket,relay_user.alias,auth_login ? "LOGIN" : "PLAIN");
                   2730:                        sockprintf(socket,auth_ok);
                   2731:                        continue;
                   2732:                }
                   2733:                if(!stricmp(buf,"AUTH CRAM-MD5")) {
                   2734:                        safe_snprintf(challenge,sizeof(challenge),"<%x%x%lx%lx@%s>"
                   2735:                                ,rand(),socket,(ulong)time(NULL),clock(),startup->host_name);
                   2736: #if 0
                   2737:                        lprintf(LOG_DEBUG,"%04d SMTP CRAM-MD5 challenge: %s"
                   2738:                                ,socket,challenge);
                   2739: #endif
                   2740:                        b64_encode(str,sizeof(str),challenge,0);
                   2741:                        sockprintf(socket,"334 %s",str);
                   2742:                        if((rd=sockreadline(socket, buf, sizeof(buf)))<1) {
                   2743:                                sockprintf(socket,badarg_rsp);
                   2744:                                continue;
                   2745:                        }
                   2746:                        if(startup->options&MAIL_OPT_DEBUG_RX_RSP) 
                   2747:                                lprintf(LOG_DEBUG,"%04d RX: %s",socket,buf);
                   2748: 
                   2749:                        if(b64_decode(response,sizeof(response),buf,rd)<1) {
                   2750:                                sockprintf(socket,badarg_rsp);
                   2751:                                continue;
                   2752:                        }
                   2753: #if 0
                   2754:                        lprintf(LOG_DEBUG,"%04d SMTP CRAM-MD5 response: %s"
                   2755:                                ,socket,response);
                   2756: #endif
                   2757:                        if((p=strrchr(response,' '))!=NULL)
                   2758:                                *(p++)=0;
                   2759:                        else
                   2760:                                p=response;
                   2761:                        SAFECOPY(user_name,response);
                   2762:                        if((relay_user.number=matchuser(&scfg,user_name,FALSE))==0) {
                   2763:                                lprintf(LOG_WARNING,"%04d !SMTP UNKNOWN USER: %s"
                   2764:                                        ,socket, user_name);
                   2765:                                sockprintf(socket,badauth_rsp);
                   2766:                                continue;
                   2767:                        }
                   2768:                        if((i=getuserdat(&scfg, &relay_user))!=0) {
                   2769:                                lprintf(LOG_ERR,"%04d !SMTP ERROR %d getting data on user (%s)"
                   2770:                                        ,socket, i, user_name);
                   2771:                                sockprintf(socket,badauth_rsp);
                   2772:                                relay_user.number=0;
                   2773:                                continue;
                   2774:                        }
                   2775:                        if(relay_user.misc&(DELETED|INACTIVE)) {
                   2776:                                lprintf(LOG_WARNING,"%04d !SMTP DELETED or INACTIVE user #%u (%s)"
                   2777:                                        ,socket, relay_user.number, user_name);
                   2778:                                sockprintf(socket,badauth_rsp);
                   2779:                                relay_user.number=0;
                   2780:                                continue;
                   2781:                        }
                   2782:                        /* Calculate correct response */
                   2783:                        memset(secret,0,sizeof(secret));
                   2784:                        SAFECOPY(secret,relay_user.pass);
                   2785:                        strlwr(secret); /* this is case sensitive, so convert to lowercase first */
                   2786:                        for(i=0;i<sizeof(secret);i++)
                   2787:                                md5_data[i]=secret[i]^0x36;     /* ipad */
                   2788:                        strcpy(md5_data+i,challenge);
                   2789:                        MD5_calc(digest,md5_data,sizeof(secret)+strlen(challenge));
                   2790:                        for(i=0;i<sizeof(secret);i++)
                   2791:                                md5_data[i]=secret[i]^0x5c;     /* opad */
                   2792:                        memcpy(md5_data+i,digest,sizeof(digest));
                   2793:                        MD5_calc(digest,md5_data,sizeof(secret)+sizeof(digest));
                   2794:                        MD5_hex(str,digest);
                   2795:                        if(strcmp(p,str)) {
                   2796:                                lprintf(LOG_WARNING,"%04d !SMTP %s FAILED CRAM-MD5 authentication"
                   2797:                                        ,socket,relay_user.alias);
                   2798: #if 0
                   2799:                                lprintf(LOG_DEBUG,"%04d !SMTP calc digest: %s"
                   2800:                                        ,socket,str);
                   2801:                                lprintf(LOG_DEBUG,"%04d !SMTP resp digest: %s"
                   2802:                                        ,socket,p);
                   2803: #endif
                   2804:                                sockprintf(socket,badauth_rsp);
                   2805:                                relay_user.number=0;
                   2806:                                continue;
                   2807:                        }
                   2808:                        /* Update client display */
                   2809:                        client.user=relay_user.alias;
                   2810:                        client_on(socket,&client,TRUE /* update */);
                   2811: 
                   2812:                        lprintf(LOG_INFO,"%04d SMTP %s authenticated using CRAM-MD5 authentication"
                   2813:                                ,socket,relay_user.alias);
                   2814:                        sockprintf(socket,auth_ok);
                   2815:                        continue;
                   2816:                }
                   2817:                if(!strnicmp(buf,"AUTH",4)) {
                   2818:                        sockprintf(socket,"504 Unrecognized authentication type.");
                   2819:                        continue;
                   2820:                }
                   2821:                if(!stricmp(buf,"QUIT")) {
                   2822:                        sockprintf(socket,"221 %s Service closing transmission channel",startup->host_name);
                   2823:                        break;
                   2824:                } 
                   2825:                if(!stricmp(buf,"NOOP")) {
                   2826:                        sockprintf(socket, ok_rsp);
                   2827:                        badcmds=0;
                   2828:                        continue;
                   2829:                }
                   2830:                if(state<SMTP_STATE_HELO) {
                   2831:                        /* RFC 821 4.1.1 "The first command in a session must be the HELO command." */
                   2832:                        lprintf(LOG_WARNING,"%04d !SMTP MISSING 'HELO' command",socket);
                   2833:                        sockprintf(socket, badseq_rsp);
                   2834:                        continue;
                   2835:                }
                   2836:                if(!stricmp(buf,"TURN")) {
                   2837:                        sockprintf(socket,"502 command not supported");
                   2838:                        badcmds=0;
                   2839:                        continue;
                   2840:                }
                   2841:                if(!stricmp(buf,"RSET")) {
                   2842:                        smb_freemsgmem(&msg);
                   2843:                        memset(&msg,0,sizeof(smbmsg_t));                /* Initialize message header */
                   2844:                        reverse_path[0]=0;
                   2845:                        state=SMTP_STATE_HELO;
                   2846:                        cmd=SMTP_CMD_NONE;
                   2847:                        telegram=FALSE;
                   2848:                        subnum=INVALID_SUB;
                   2849: 
                   2850:                        /* reset recipient list */
                   2851:                        if((rcptlst=freopen(rcptlst_fname,"w+",rcptlst))==NULL) {
                   2852:                                lprintf(LOG_ERR,"%04d !SMTP ERROR %d re-opening %s"
                   2853:                                        ,socket, errno, rcptlst_fname);
                   2854:                                sockprintf(socket,sys_error);
                   2855:                                break;
                   2856:                        }
                   2857:                        rcpt_count=0;
                   2858: 
                   2859:                        sockprintf(socket,ok_rsp);
                   2860:                        badcmds=0;
                   2861:                        lprintf(LOG_INFO,"%04d SMTP Session reset",socket);
                   2862:                        continue;
                   2863:                }
                   2864:                if(!strnicmp(buf,"MAIL FROM:",10)
                   2865:                        || !strnicmp(buf,"SEND FROM:",10)       /* Send a Message (Telegram) to a local ONLINE user */
                   2866:                        || !strnicmp(buf,"SOML FROM:",10)       /* Send OR Mail a Message to a local user */
                   2867:                        || !strnicmp(buf,"SAML FROM:",10)       /* Send AND Mail a Message to a local user */
                   2868:                        ) {
                   2869:                        p=buf+10;
                   2870:                        if(!chk_email_addr(socket,p,host_name,host_ip,NULL,NULL,"REVERSE PATH")) {
                   2871:                                sockprintf(socket, "554 Sender not allowed.");
                   2872:                                break;
                   2873:                        }
                   2874:                        SKIP_WHITESPACE(p);
                   2875:                        SAFECOPY(reverse_path,p);
                   2876: 
                   2877:                        /* Update client display */
                   2878:                        if(relay_user.number==0) {
                   2879:                                client.user=reverse_path;
                   2880:                                client_on(socket,&client,TRUE /* update */);
                   2881:                        }
                   2882: 
                   2883:                        /* Setup state */
                   2884:                        state=SMTP_STATE_MAIL_FROM;
                   2885:                        if(!strnicmp(buf,"MAIL FROM:",10))
                   2886:                                cmd=SMTP_CMD_MAIL;
                   2887:                        else if(!strnicmp(buf,"SEND FROM:",10))
                   2888:                                cmd=SMTP_CMD_SEND;
                   2889:                        else if(!strnicmp(buf,"SOML FROM:",10))
                   2890:                                cmd=SMTP_CMD_SOML;
                   2891:                        else if(!strnicmp(buf,"SAML FROM:",10))
                   2892:                                cmd=SMTP_CMD_SAML;
                   2893: 
                   2894:                        /* reset recipient list */
                   2895:                        if((rcptlst=freopen(rcptlst_fname,"w+",rcptlst))==NULL) {
                   2896:                                lprintf(LOG_ERR,"%04d !SMTP ERROR %d re-opening %s"
                   2897:                                        ,socket, errno, rcptlst_fname);
                   2898:                                sockprintf(socket,sys_error);
                   2899:                                break;
                   2900:                        }
                   2901:                        rcpt_count=0;
                   2902:                        sockprintf(socket,ok_rsp);
                   2903:                        badcmds=0;
                   2904:                        continue;
                   2905:                }
                   2906: 
                   2907: #if 0  /* No one uses this command */
                   2908:                if(!strnicmp(buf,"VRFY",4)) {
                   2909:                        p=buf+4;
                   2910:                        SKIP_WHITESPACE(p);
                   2911:                        if(*p==0) {
                   2912:                                sockprintf(socket,"550 No user specified.");
                   2913:                                continue;
                   2914:                        }
                   2915: #endif
                   2916: 
                   2917:                /* Add to Recipient list */
                   2918:                if(!strnicmp(buf,"RCPT TO:",8)) {
                   2919: 
                   2920:                        if(state<SMTP_STATE_MAIL_FROM) {
                   2921:                                lprintf(LOG_WARNING,"%04d !SMTP MISSING 'MAIL' command",socket);
                   2922:                                sockprintf(socket, badseq_rsp);
                   2923:                                continue;
                   2924:                        }
                   2925: 
                   2926:                        if(spy==NULL && trashcan(&scfg,reverse_path,"smtpspy")) {
                   2927:                                sprintf(str,"%ssmtpspy.txt", scfg.logs_dir);
                   2928:                                spy=fopen(str,"a");
                   2929:                        }
                   2930: 
                   2931:                        p=buf+8;
                   2932:                        SKIP_WHITESPACE(p);
                   2933:                        SAFECOPY(str,p);
                   2934:                        p=strrchr(str,'<');
                   2935:                        if(p==NULL)
                   2936:                                p=str;
                   2937:                        else
                   2938:                                p++;
                   2939: 
                   2940:                        truncstr(str,">");      /* was truncating at space too */
                   2941: 
                   2942:                        routed=FALSE;
                   2943:                        forward=FALSE;
                   2944:                        no_forward=FALSE;
                   2945:                        if(!strnicmp(p,FORWARD,strlen(FORWARD))) {
                   2946:                                forward=TRUE;           /* force forward to user's netmail address */
                   2947:                                p+=strlen(FORWARD);
                   2948:                        }
                   2949:                        if(!strnicmp(p,NO_FORWARD,strlen(NO_FORWARD))) {
                   2950:                                no_forward=TRUE;        /* do not forward to user's netmail address */
                   2951:                                p+=strlen(NO_FORWARD);
                   2952:                        }
                   2953: 
                   2954:                        if(*p==0) {
                   2955:                                lprintf(LOG_WARNING,"%04d !SMTP NO RECIPIENT SPECIFIED"
                   2956:                                        ,socket);
                   2957:                                sockprintf(socket, "500 No recipient specified");
                   2958:                                continue;
                   2959:                        }
                   2960: 
                   2961:                        rcpt_name[0]=0;
                   2962:                        SAFECOPY(rcpt_addr,p);
                   2963: 
                   2964:                        /* Check recipient counter */
                   2965:                        if(rcpt_count>=startup->max_recipients) {
                   2966:                                lprintf(LOG_WARNING,"%04d !SMTP MAXIMUM RECIPIENTS (%d) REACHED"
                   2967:                                        ,socket, startup->max_recipients);
                   2968:                                sprintf(tmp,"Maximum recipient count (%d)",startup->max_recipients);
                   2969:                                spamlog(&scfg, "SMTP", "REFUSED", tmp
                   2970:                                        ,host_name, host_ip, rcpt_addr, reverse_path);
                   2971:                                sockprintf(socket, "552 Too many recipients");
                   2972:                                continue;
                   2973:                        }
                   2974: 
                   2975:                        /* Check for SPAM bait recipient */
                   2976:                        if(findstr(rcpt_addr,spam_bait)) {
                   2977:                                SAFEPRINTF(str,"SPAM BAIT (%s) taken", rcpt_addr);
                   2978:                                lprintf(LOG_WARNING,"%04d !SMTP %s by: %s"
                   2979:                                        ,socket, str, reverse_path);
                   2980:                                strcpy(tmp,"REFUSED");
                   2981:                                if(dnsbl_result.s_addr==0)      { /* Don't double-filter */
                   2982:                                        lprintf(LOG_WARNING,"%04d !BLOCKING IP ADDRESS: %s in %s", socket, host_ip, spam_block);
                   2983:                                        filter_ip(&scfg, "SMTP", str, host_name, host_ip, reverse_path, spam_block);
                   2984:                                        strcat(tmp," and BLOCKED");
                   2985:                                }
                   2986:                                spamlog(&scfg, "SMTP", tmp, "Attempted recipient in SPAM BAIT list"
                   2987:                                        ,host_name, host_ip, rcpt_addr, reverse_path);
                   2988:                                break;
                   2989:                        }
                   2990: 
                   2991:                        /* Check for blocked recipients */
                   2992:                        if(!chk_email_addr(socket,rcpt_addr,host_name,host_ip,rcpt_addr,reverse_path,"RECIPIENT")) {
                   2993:                                sockprintf(socket, "550 Unknown User:%s", buf+8);
                   2994:                                continue;
                   2995:                        }
                   2996: 
                   2997:                        if(relay_user.number==0 && dnsbl_result.s_addr && startup->options&MAIL_OPT_DNSBL_BADUSER) {
                   2998:                                lprintf(LOG_WARNING,"%04d !SMTP REFUSED MAIL from blacklisted server"
                   2999:                                        ,socket);
                   3000:                                SAFEPRINTF2(str,"Listed on %s as %s", dnsbl, inet_ntoa(dnsbl_result));
                   3001:                                spamlog(&scfg, "SMTP", "REFUSED", str, host_name, host_ip, rcpt_addr, reverse_path);
                   3002:                                sockprintf(socket
                   3003:                                        ,"550 Mail from %s refused due to listing at %s"
                   3004:                                        ,host_ip, dnsbl);
                   3005:                                continue;
                   3006:                        }
                   3007: 
                   3008:                        /* Check for full address aliases */
                   3009:                        p=alias(&scfg,p,alias_buf);
                   3010:                        if(p==alias_buf) 
                   3011:                                lprintf(LOG_INFO,"%04d SMTP ADDRESS ALIAS: %s",socket,p);
                   3012: 
                   3013:                        tp=strrchr(p,'@');
                   3014:                        if(cmd==SMTP_CMD_MAIL && tp!=NULL) {
                   3015:                                
                   3016:                                /* RELAY */
                   3017:                                dest_port=server_addr.sin_port;
                   3018:                                SAFECOPY(dest_host,tp+1);
                   3019:                                cp=strrchr(dest_host,':');
                   3020:                                if(cp!=NULL) {
                   3021:                                        *cp=0;
                   3022:                                        dest_port=atoi(cp+1);
                   3023:                                }
                   3024:                                sprintf(domain_list,"%sdomains.cfg",scfg.ctrl_dir);
                   3025:                                if((stricmp(dest_host,scfg.sys_inetaddr)!=0
                   3026:                                                && stricmp(dest_host,startup->host_name)!=0
                   3027:                                                && resolve_ip(dest_host)!=server_addr.sin_addr.s_addr
                   3028:                                                && findstr(dest_host,domain_list)==FALSE)
                   3029:                                        || dest_port!=server_addr.sin_port) {
                   3030: 
                   3031:                                        sprintf(relay_list,"%srelay.cfg",scfg.ctrl_dir);
                   3032:                                        if(relay_user.number==0 /* not authenticated, search for IP */
                   3033:                                                && startup->options&MAIL_OPT_SMTP_AUTH_VIA_IP) { 
                   3034:                                                relay_user.number=userdatdupe(&scfg, 0, U_NOTE, LEN_NOTE, host_ip, FALSE);
                   3035:                                                if(relay_user.number) {
                   3036:                                                        getuserdat(&scfg,&relay_user);
                   3037:                                                        if(relay_user.laston < time(NULL)-(60*60))      /* logon in past hour? */
                   3038:                                                                relay_user.number=0;
                   3039:                                                }
                   3040:                                        } else
                   3041:                                                getuserdat(&scfg,&relay_user);
                   3042:                                        if(p!=alias_buf /* forced relay by alias */ &&
                   3043:                                                (!(startup->options&MAIL_OPT_ALLOW_RELAY)
                   3044:                                                        || relay_user.number==0
                   3045:                                                        || relay_user.rest&(FLAG('G')|FLAG('M'))) &&
                   3046:                                                !findstr(host_name,relay_list) && 
                   3047:                                                !findstr(host_ip,relay_list)) {
                   3048:                                                lprintf(LOG_WARNING,"%04d !SMTP ILLEGAL RELAY ATTEMPT from %s [%s] to %s"
                   3049:                                                        ,socket, reverse_path, host_ip, p);
                   3050:                                                SAFEPRINTF(tmp,"Relay attempt to: %s", p);
                   3051:                                                spamlog(&scfg, "SMTP", "REFUSED", tmp, host_name, host_ip, rcpt_addr, reverse_path);
                   3052:                                                if(startup->options&MAIL_OPT_ALLOW_RELAY)
                   3053:                                                        sockprintf(socket, "553 Relaying through this server "
                   3054:                                                        "requires authentication.  "
                   3055:                                                        "Please authenticate before sending.");
                   3056:                                                else
                   3057:                                                        sockprintf(socket, "550 Relay not allowed.");
                   3058:                                                break;
                   3059:                                        }
                   3060: 
                   3061:                                        if(relay_user.number==0)
                   3062:                                                SAFECOPY(relay_user.alias,"Unknown User");
                   3063: 
                   3064:                                        lprintf(LOG_INFO,"%04d SMTP %s relaying to external mail service: %s"
                   3065:                                                ,socket, relay_user.alias, tp+1);
                   3066: 
                   3067:                                        fprintf(rcptlst,"[%u]\n",rcpt_count++);
                   3068:                                        fprintf(rcptlst,"%s=%s\n",smb_hfieldtype(RECIPIENT),rcpt_addr);
                   3069:                                        fprintf(rcptlst,"%s=%u\n",smb_hfieldtype(RECIPIENTNETTYPE),NET_INTERNET);
                   3070:                                        fprintf(rcptlst,"%s=%s\n",smb_hfieldtype(RECIPIENTNETADDR),p);
                   3071: 
                   3072:                                        sockprintf(socket,ok_rsp);
                   3073:                                        state=SMTP_STATE_RCPT_TO;
                   3074:                                        continue;
                   3075:                                }
                   3076:                        }
                   3077:                        if(tp!=NULL)
                   3078:                                *tp=0;  /* truncate at '@' */
                   3079: 
                   3080:                        tp=strchr(p,'!');       /* Routed QWKnet mail in <qwkid!user@host> format */
                   3081:                        if(tp!=NULL) {
                   3082:                                *(tp++)=0;
                   3083:                                SKIP_CHAR(tp,'"');                              /* Skip '"' */
                   3084:                                truncstr(tp,"\"");                              /* Strip '"' */
                   3085:                                SAFECOPY(rcpt_addr,tp);
                   3086:                                routed=TRUE;
                   3087:                        }
                   3088: 
                   3089:                        FIND_ALPHANUMERIC(p);                           /* Skip '<' or '"' */
                   3090:                        truncstr(p,"\"");       
                   3091: 
                   3092:                        p=alias(&scfg,p,name_alias_buf);
                   3093:                        if(p==name_alias_buf) 
                   3094:                                lprintf(LOG_INFO,"%04d SMTP NAME ALIAS: %s",socket,p);
                   3095:                
                   3096:                        if(!strnicmp(p,"sub:",4)) {             /* Post on a sub-board */
                   3097:                                p+=4;
                   3098:                                for(i=0;i<scfg.total_subs;i++)
                   3099:                                        if(!stricmp(p,scfg.sub[i]->code))
                   3100:                                                break;
                   3101:                                if(i>=scfg.total_subs) {
                   3102:                                        lprintf(LOG_WARNING,"%04d !SMTP UNKNOWN SUB-BOARD: %s", socket, p);
                   3103:                                        sockprintf(socket, "550 Unknown sub-board: %s", p);
                   3104:                                        continue;
                   3105:                                }
                   3106:                                subnum=i;
                   3107:                                sockprintf(socket,ok_rsp);
                   3108:                                state=SMTP_STATE_RCPT_TO;
                   3109:                                rcpt_count++;
                   3110:                                continue;
                   3111:                        }
                   3112: 
                   3113:                        memset(mailproc_match,FALSE,sizeof(BOOL)*mailproc_count);
                   3114:                        for(i=0;i<mailproc_count;i++) {
                   3115:                                if(mailproc_list[i].to!=NULL) {
                   3116:                                        for(j=0;mailproc_list[i].to[j]!=NULL;j++) {
                   3117:                                                if(stricmp(p,mailproc_list[i].to[j])==0) {
                   3118:                                                        mailproc_match[i]=TRUE;
                   3119:                                                        if(!mailproc_list[i].passthru)
                   3120:                                                                break;
                   3121:                                                }
                   3122:                                        }
                   3123:                                        if(mailproc_list[i].to[j]!=NULL)
                   3124:                                                break;
                   3125:                                }
                   3126:                        }
                   3127:                        /* destined for an external mail processor */
                   3128:                        if(i<mailproc_count) {
                   3129:                                fprintf(rcptlst,"[%u]\n",rcpt_count++);
                   3130:                                fprintf(rcptlst,"%s=%s\n",smb_hfieldtype(RECIPIENT),rcpt_addr);
                   3131: #if 0  /* should we fall-through to the sysop account? */
                   3132:                                fprintf(rcptlst,"%s=%u\n",smb_hfieldtype(RECIPIENTEXT),1);
                   3133: #endif
                   3134:                                lprintf(LOG_INFO,"%04d SMTP Routing mail for %s to External Mail Processor: %s"
                   3135:                                        ,socket, rcpt_addr, mailproc_list[i].cmdline);
                   3136:                                sockprintf(socket,ok_rsp);
                   3137:                                state=SMTP_STATE_RCPT_TO;
                   3138:                                continue;
                   3139:                        }
                   3140: 
                   3141:                        usernum=0;      /* unknown user at this point */
                   3142: 
                   3143:                        if(routed) {
                   3144:                                SAFECOPY(qwkid,p);
                   3145:                                truncstr(qwkid,"/");
                   3146:                                /* Search QWKnet hub-IDs for route destination */
                   3147:                                for(i=0;i<scfg.total_qhubs;i++) {
                   3148:                                        if(!stricmp(qwkid,scfg.qhub[i]->id))
                   3149:                                                break;
                   3150:                                }
                   3151:                                if(i<scfg.total_qhubs) {        /* found matching QWKnet Hub */
                   3152: 
                   3153:                                        lprintf(LOG_INFO,"%04d SMTP Routing mail for %s <%s> to QWKnet Hub: %s"
                   3154:                                                ,socket, rcpt_addr, p, scfg.qhub[i]->id);
                   3155: 
                   3156:                                        fprintf(rcptlst,"[%u]\n",rcpt_count++);
                   3157:                                        fprintf(rcptlst,"%s=%s\n",smb_hfieldtype(RECIPIENT),rcpt_addr);
                   3158:                                        fprintf(rcptlst,"%s=%u\n",smb_hfieldtype(RECIPIENTNETTYPE),NET_QWK);
                   3159:                                        fprintf(rcptlst,"%s=%s\n",smb_hfieldtype(RECIPIENTNETADDR),p);
                   3160: 
                   3161:                                        sockprintf(socket,ok_rsp);
                   3162:                                        state=SMTP_STATE_RCPT_TO;
                   3163:                                        continue;
                   3164:                                }
                   3165:                        }
                   3166: 
                   3167:                        if((p==name_alias_buf || startup->options&MAIL_OPT_ALLOW_RX_BY_NUMBER)
                   3168:                                && isdigit(*p)) {
                   3169:                                usernum=atoi(p);                        /* RX by user number */
                   3170:                                /* verify usernum */
                   3171:                                username(&scfg,usernum,str);
                   3172:                                if(!str[0] || !stricmp(str,"DELETED USER"))
                   3173:                                        usernum=0;
                   3174:                                p=str;
                   3175:                        } else {
                   3176:                                /* RX by "user alias", "user.alias" or "user_alias" */
                   3177:                                usernum=matchuser(&scfg,p,startup->options&MAIL_OPT_ALLOW_SYSOP_ALIASES);       
                   3178: 
                   3179:                                if(!usernum) { /* RX by "real name", "real.name", or "sysop.alias" */
                   3180:                                        
                   3181:                                        /* convert "user.name" to "user name" */
                   3182:                                        SAFECOPY(rcpt_name,p);
                   3183:                                        for(tp=rcpt_name;*tp;tp++)      
                   3184:                                                if(*tp=='.') *tp=' ';
                   3185: 
                   3186:                                        if(!stricmp(p,scfg.sys_op) || !stricmp(rcpt_name,scfg.sys_op))
                   3187:                                                usernum=1;                      /* RX by "sysop.alias" */
                   3188: 
                   3189:                                        if(!usernum && scfg.msg_misc&MM_REALNAME)       /* RX by "real name" */
                   3190:                                                usernum=userdatdupe(&scfg, 0, U_NAME, LEN_NAME, p, FALSE);
                   3191: 
                   3192:                                        if(!usernum && scfg.msg_misc&MM_REALNAME)       /* RX by "real.name" */
                   3193:                                                usernum=userdatdupe(&scfg, 0, U_NAME, LEN_NAME, rcpt_name, FALSE);
                   3194:                                }
                   3195:                        }
                   3196:                        if(!usernum && startup->default_user[0]) {
                   3197:                                usernum=matchuser(&scfg,startup->default_user,TRUE /* sysop_alias */);
                   3198:                                if(usernum)
                   3199:                                        lprintf(LOG_INFO,"%04d SMTP Forwarding mail for UNKNOWN USER to default user: %s #%u"
                   3200:                                                ,socket,startup->default_user,usernum);
                   3201:                                else
                   3202:                                        lprintf(LOG_WARNING,"%04d !SMTP UNKNOWN DEFAULT USER: %s"
                   3203:                                                ,socket,startup->default_user);
                   3204:                        }
                   3205: 
                   3206:                        if(!usernum) {
                   3207:                                lprintf(LOG_WARNING,"%04d !SMTP UNKNOWN USER:%s", socket, buf+8);
                   3208:                                sockprintf(socket, "550 Unknown User:%s", buf+8);
                   3209:                                continue;
                   3210:                        }
                   3211:                        user.number=usernum;
                   3212:                        if((i=getuserdat(&scfg, &user))!=0) {
                   3213:                                lprintf(LOG_ERR,"%04d !SMTP ERROR %d getting data on user #%u (%s)"
                   3214:                                        ,socket, i, usernum, p);
                   3215:                                sockprintf(socket, "550 Unknown User:%s", buf+8);
                   3216:                                continue;
                   3217:                        }
                   3218:                        if(user.misc&(DELETED|INACTIVE)) {
                   3219:                                lprintf(LOG_WARNING,"%04d !SMTP DELETED or INACTIVE user #%u (%s)"
                   3220:                                        ,socket, usernum, p);
                   3221:                                sockprintf(socket, "550 Unknown User:%s", buf+8);
                   3222:                                continue;
                   3223:                        }
                   3224:                        if(cmd==SMTP_CMD_SEND) { /* Check if user online */
                   3225:                                for(i=0;i<scfg.sys_nodes;i++) {
                   3226:                                        getnodedat(&scfg, i+1, &node, 0);
                   3227:                                        if(node.status==NODE_INUSE && node.useron==user.number
                   3228:                                                && !(node.misc&NODE_POFF))
                   3229:                                                break;
                   3230:                                }
                   3231:                                if(i>=scfg.sys_nodes) {
                   3232:                                        lprintf(LOG_WARNING,"%04d !Attempt to send telegram to unavailable user #%u (%s)"
                   3233:                                                ,socket, user.number, user.alias);
                   3234:                                        sockprintf(socket,"450 User unavailable");
                   3235:                                        continue;
                   3236:                                }
                   3237:                        }
                   3238:                        if(cmd==SMTP_CMD_MAIL) {
                   3239: #if 0  /* implement later */
                   3240:                                if(useron.etoday>=cfg.level_emailperday[useron.level]
                   3241:                                        && !(useron.rest&FLAG('Q'))) {
                   3242:                                        bputs(text[TooManyEmailsToday]);
                   3243:                                        continue; 
                   3244:                                }
                   3245: #endif
                   3246:                        } else
                   3247:                                telegram=TRUE;
                   3248: 
                   3249:                        fprintf(rcptlst,"[%u]\n",rcpt_count++);
                   3250:                        fprintf(rcptlst,"%s=%s\n",smb_hfieldtype(RECIPIENT),rcpt_addr);
                   3251:                        fprintf(rcptlst,"%s=%u\n",smb_hfieldtype(RECIPIENTEXT),user.number);
                   3252: 
                   3253: 
                   3254:                        /* Forward to Internet */
                   3255:                        tp=strrchr(user.netmail,'@');
                   3256:                        if(!telegram
                   3257:                                && !routed
                   3258:                                && !no_forward
                   3259:                                && scfg.sys_misc&SM_FWDTONET 
                   3260:                                && (user.misc&NETMAIL || forward)
                   3261:                                && tp!=NULL && smb_netaddr_type(user.netmail)==NET_INTERNET 
                   3262:                                && !strstr(tp,scfg.sys_inetaddr)) {
                   3263:                                lprintf(LOG_INFO,"%04d SMTP Forwarding to: %s"
                   3264:                                        ,socket, user.netmail);
                   3265:                                fprintf(rcptlst,"%s=%u\n",smb_hfieldtype(RECIPIENTNETTYPE),NET_INTERNET);
                   3266:                                fprintf(rcptlst,"%s=%s\n",smb_hfieldtype(RECIPIENTNETADDR),user.netmail);
                   3267:                                sockprintf(socket,"251 User not local; will forward to %s", user.netmail);
                   3268:                        } else { /* Local (no-forward) */
                   3269:                                if(routed) { /* QWKnet */
                   3270:                                        fprintf(rcptlst,"%s=%u\n",smb_hfieldtype(RECIPIENTNETTYPE),NET_QWK);
                   3271:                                        fprintf(rcptlst,"%s=%s\n",smb_hfieldtype(RECIPIENTNETADDR),user.alias);
                   3272:                                }                                               
                   3273:                                sockprintf(socket,ok_rsp);
                   3274:                        }
                   3275:                        state=SMTP_STATE_RCPT_TO;
                   3276:                        continue;
                   3277:                }
                   3278:                /* Message Data (header and body) */
                   3279:                if(!strnicmp(buf,"DATA",4)) {
                   3280:                        if(state<SMTP_STATE_RCPT_TO) {
                   3281:                                lprintf(LOG_WARNING,"%04d !SMTP MISSING 'RCPT TO' command", socket);
                   3282:                                sockprintf(socket, badseq_rsp);
                   3283:                                continue;
                   3284:                        }
                   3285:                        if(msgtxt!=NULL) {
                   3286:                                fclose(msgtxt), msgtxt=NULL;
                   3287:                                if(!(startup->options&MAIL_OPT_DEBUG_RX_BODY))
                   3288:                                        unlink(msgtxt_fname);
                   3289:                        }
                   3290:                        SAFEPRINTF2(msgtxt_fname,"%sSBBS_SMTP.%s.msg", scfg.temp_dir, session_id);
                   3291:                        if((msgtxt=fopen(msgtxt_fname,"w+b"))==NULL) {
                   3292:                                lprintf(LOG_ERR,"%04d !SMTP ERROR %d opening %s"
                   3293:                                        ,socket, errno, msgtxt_fname);
                   3294:                                sockprintf(socket, "452 Insufficient system storage");
                   3295:                                continue;
                   3296:                        }
                   3297:                        /* These vars are potentially over-written by parsing an RFC822 header */
                   3298:                        /* get sender_addr */
                   3299:                        p=strchr(reverse_path,'<');
                   3300:                        if(p==NULL)     
                   3301:                                p=reverse_path;
                   3302:                        else 
                   3303:                                p++;
                   3304:                        SAFECOPY(sender_addr,p);
                   3305:                        truncstr(sender_addr,">");
                   3306:                        /* get sender */
                   3307:                        SAFECOPY(sender,sender_addr);
                   3308:                        if(truncstr(sender,"@")==NULL)
                   3309:                                sender[0]=0;
                   3310: 
                   3311:                        sockprintf(socket, "354 send the mail data, end with <CRLF>.<CRLF>");
                   3312:                        if(telegram)
                   3313:                                state=SMTP_STATE_DATA_BODY;     /* No RFC headers in Telegrams */
                   3314:                        else
                   3315:                                state=SMTP_STATE_DATA_HEADER;
                   3316:                        hdr_lines=0;
                   3317:                        continue;
                   3318:                }
                   3319:                sockprintf(socket,"500 Syntax error");
                   3320:                lprintf(LOG_WARNING,"%04d !SMTP UNSUPPORTED COMMAND: '%s'", socket, buf);
                   3321:                if(++badcmds>9) {
                   3322:                        lprintf(LOG_WARNING,"%04d !TOO MANY INVALID COMMANDS (%u)",socket,badcmds);
                   3323:                        break;
                   3324:                }
                   3325:        }
                   3326: 
                   3327:        /* Free up resources here */
                   3328:        smb_freemsgmem(&msg);
                   3329: 
                   3330:        if(msgtxt!=NULL) {
                   3331:                fclose(msgtxt);
                   3332:                if(!(startup->options&MAIL_OPT_DEBUG_RX_BODY))
                   3333:                        unlink(msgtxt_fname);
                   3334:        }
                   3335:        if(rcptlst!=NULL) {
                   3336:                fclose(rcptlst);
                   3337:                unlink(rcptlst_fname);
                   3338:        }
                   3339:        if(spy!=NULL)
                   3340:                fclose(spy);
                   3341: 
                   3342:        status(STATUS_WFC);
                   3343: 
                   3344:        if(active_clients)
                   3345:                active_clients--, update_clients();
                   3346:        client_off(socket);
                   3347: 
                   3348:        thread_down();
                   3349:        lprintf(LOG_DEBUG,"%04d SMTP RX Session thread terminated (%u threads remain, %lu clients served)"
                   3350:                ,socket, thread_count, served);
                   3351: 
                   3352:        /* Must be last */
                   3353:        mail_close_socket(socket);
                   3354: }
                   3355: 
                   3356: BOOL bounce(smb_t* smb, smbmsg_t* msg, char* err, BOOL immediate)
                   3357: {
                   3358:        char            str[128];
                   3359:        char            attempts[64];
                   3360:        int                     i;
                   3361:        ushort          agent=AGENT_SMTPSYSMSG;
                   3362:        smbmsg_t        newmsg;
                   3363: 
                   3364:        msg->hdr.delivery_attempts++;
                   3365:        lprintf(LOG_WARNING,"0000 !Delivery attempt #%u FAILED (%s) for message #%lu from %s to %s"
                   3366:                ,msg->hdr.delivery_attempts
                   3367:                ,err
                   3368:                ,msg->hdr.number
                   3369:                ,msg->from
                   3370:                ,msg->to_net.addr);
                   3371: 
                   3372:        if((i=smb_updatemsg(smb,msg))!=SMB_SUCCESS) {
                   3373:                lprintf(LOG_ERR,"0000 !BOUNCE ERROR %d (%s) incrementing delivery attempt counter"
                   3374:                        ,i, smb->last_error);
                   3375:                return(FALSE);
                   3376:        }
                   3377: 
                   3378:        if(!immediate && msg->hdr.delivery_attempts < startup->max_delivery_attempts)
                   3379:                return(TRUE);
                   3380: 
                   3381:        newmsg=*msg;
                   3382:        /* Mark original message as deleted */
                   3383:        msg->hdr.attr|=MSG_DELETE;
                   3384: 
                   3385:        i=smb_updatemsg(smb,msg);
                   3386:        if(msg->hdr.auxattr&MSG_FILEATTACH)
                   3387:                delfattach(&scfg,msg);
                   3388:        if(i!=SMB_SUCCESS) {
                   3389:                lprintf(LOG_ERR,"0000 !BOUNCE ERROR %d (%s) deleting message"
                   3390:                        ,i, smb->last_error);
                   3391:                return(FALSE);
                   3392:        }
                   3393: 
                   3394:        if(msg->from_agent!=AGENT_PERSON        /* don't bounce 'bounce messages' */
                   3395:                || (msg->idx.from==0 && msg->from_net.type==NET_NONE)
                   3396:                || (msg->reverse_path!=NULL && *msg->reverse_path==0)) {
                   3397:                lprintf(LOG_WARNING,"0000 !Deleted undeliverable message from %s", msg->from);
                   3398:                return(TRUE);
                   3399:        }
                   3400:        
                   3401:        lprintf(LOG_WARNING,"0000 !Bouncing message back to %s", msg->from);
                   3402: 
                   3403:        newmsg.hfield=NULL;
                   3404:        newmsg.hfield_dat=NULL;
                   3405:        newmsg.total_hfields=0;
                   3406:        newmsg.hdr.delivery_attempts=0;
                   3407: 
                   3408:        SAFEPRINTF(str,"Delivery failure: %s",newmsg.subj);
                   3409:        smb_hfield_str(&newmsg, SUBJECT, str);
                   3410:        smb_hfield_str(&newmsg, RECIPIENT, newmsg.from);
                   3411:        if(newmsg.from_ext!=NULL) { /* Back to sender */
                   3412:                smb_hfield_str(&newmsg, RECIPIENTEXT, newmsg.from_ext);
                   3413:                newmsg.from_ext=NULL;   /* Clear the sender extension */
                   3414:        }
                   3415: 
                   3416:        if((newmsg.from_net.type==NET_QWK || newmsg.from_net.type==NET_INTERNET)
                   3417:                && newmsg.reverse_path!=NULL) {
                   3418:                smb_hfield(&newmsg, RECIPIENTNETTYPE, sizeof(newmsg.from_net.type), &newmsg.from_net.type);
                   3419:                smb_hfield_str(&newmsg, RECIPIENTNETADDR, newmsg.reverse_path);
                   3420:        }
                   3421:        strcpy(str,"Mail Delivery Subsystem");
                   3422:        smb_hfield_str(&newmsg, SENDER, str);
                   3423:        smb_hfield(&newmsg, SENDERAGENT, sizeof(agent), &agent);
                   3424:        
                   3425:        /* Put error message in subject for now */
                   3426:        if(msg->hdr.delivery_attempts>1)
                   3427:                sprintf(attempts,"after %u attempts", msg->hdr.delivery_attempts);
                   3428:        else
                   3429:                attempts[0]=0;
                   3430:        SAFEPRINTF2(str,"%s reporting delivery failure of message %s"
                   3431:                ,startup->host_name, attempts);
                   3432:        smb_hfield_str(&newmsg, SMB_COMMENT, str);
                   3433:        SAFEPRINTF2(str,"from %s to %s\r\n"
                   3434:                ,msg->reverse_path==NULL ? msg->from : msg->reverse_path
                   3435:                ,(char*)msg->to_net.addr);
                   3436:        smb_hfield_str(&newmsg, SMB_COMMENT, str);
                   3437:        strcpy(str,"Reason:");
                   3438:        smb_hfield_str(&newmsg, SMB_COMMENT, str);
                   3439:        smb_hfield_str(&newmsg, SMB_COMMENT, err);
                   3440:        smb_hfield_str(&newmsg, SMB_COMMENT, "\r\nOriginal message text follows:\r\n");
                   3441: 
                   3442:        if((i=smb_addmsghdr(smb,&newmsg,SMB_SELFPACK))!=SMB_SUCCESS)
                   3443:                lprintf(LOG_ERR,"0000 !BOUNCE ERROR %d (%s) adding message header"
                   3444:                        ,i,smb->last_error);
                   3445:        else {
                   3446:                lprintf(LOG_WARNING,"0000 !Delivery failure notification (message #%ld) created for %s"
                   3447:                        ,newmsg.hdr.number, newmsg.from);
                   3448:                if((i=smb_incmsg_dfields(smb,&newmsg,1))!=SMB_SUCCESS)
                   3449:                        lprintf(LOG_ERR,"0000 !BOUNCE ERROR %d (%s) incrementing data allocation units"
                   3450:                                ,i,smb->last_error);
                   3451:        }
                   3452: 
                   3453:        newmsg.dfield=NULL;                             /* Don't double-free the data fields */
                   3454:        newmsg.hdr.total_dfields=0;
                   3455:        smb_freemsgmem(&newmsg);
                   3456: 
                   3457:        return(TRUE);
                   3458: }
                   3459: 
                   3460: static int remove_msg_intransit(smb_t* smb, smbmsg_t* msg)
                   3461: {
                   3462:        int i;
                   3463: 
                   3464:        if((i=smb_lockmsghdr(smb,msg))!=SMB_SUCCESS) {
                   3465:                lprintf(LOG_WARNING,"0000 !SEND ERROR %d (%s) locking message header #%lu"
                   3466:                        ,i, smb->last_error, msg->idx.number);
                   3467:                return(i);
                   3468:        }
                   3469:        msg->hdr.netattr&=~MSG_INTRANSIT;
                   3470:        i=smb_putmsghdr(smb,msg);
                   3471:        smb_unlockmsghdr(smb,msg);
                   3472:        
                   3473:        if(i!=0)
                   3474:                lprintf(LOG_ERR,"0000 !SEND ERROR %d (%s) writing message header #%lu"
                   3475:                        ,i, smb->last_error, msg->idx.number);
                   3476: 
                   3477:        return(i);
                   3478: }
                   3479: 
                   3480: void get_dns_server(char* dns_server, size_t len)
                   3481: {
                   3482:        str_list_t      list;
                   3483:        size_t          count;
                   3484: 
                   3485:        sprintf(dns_server,"%.*s",len,startup->dns_server);
                   3486:        if(!isalnum(dns_server[0])) {
                   3487:                if((list=getNameServerList())!=NULL) {
                   3488:                        if((count=strListCount(list))>0) {
                   3489:                                sprintf(dns_server,"%.*s",len,list[xp_random(count)]);
                   3490:                                lprintf(LOG_DEBUG,"0000 SEND using auto-detected DNS server address: %s"
                   3491:                                        ,dns_server);
                   3492:                        }
                   3493:                        freeNameServerList(list);
                   3494:                }
                   3495:        }
                   3496: }
                   3497: 
                   3498: #ifdef __BORLANDC__
                   3499: #pragma argsused
                   3500: #endif
                   3501: static void sendmail_thread(void* arg)
                   3502: {
                   3503:        int                     i,j;
                   3504:        char            to[128];
                   3505:        char            mx[128];
                   3506:        char            mx2[128];
                   3507:        char            err[1024];
                   3508:        char            buf[512];
                   3509:        char            str[128];
                   3510:        char            resp[512];
                   3511:        char            toaddr[256];
                   3512:        char            fromaddr[256];
                   3513:        char            challenge[256];
                   3514:        char            secret[64];
                   3515:        char            md5_data[384];
                   3516:        char            digest[MD5_DIGEST_SIZE];
                   3517:        char            numeric_ip[16];
                   3518:        char            domain_list[MAX_PATH+1];
                   3519:        char            dns_server[16];
                   3520:        char*           server;
                   3521:        char*           msgtxt=NULL;
                   3522:        char*           p;
                   3523:        char*           tp;
                   3524:        ushort          port;
                   3525:        ulong           last_msg=0;
                   3526:        ulong           ip_addr;
                   3527:        ulong           dns;
                   3528:        ulong           lines;
                   3529:        BOOL            success;
                   3530:        BOOL            first_cycle=TRUE;
                   3531:        SOCKET          sock=INVALID_SOCKET;
                   3532:        SOCKADDR_IN     addr;
                   3533:        SOCKADDR_IN     server_addr;
                   3534:        time_t          last_scan=0;
                   3535:        smb_t           smb;
                   3536:        smbmsg_t        msg;
                   3537:        mail_t*         mail;
                   3538:        long            msgs;
                   3539:        long            l;
                   3540:        BOOL            sending_locally=FALSE;
                   3541: 
                   3542:        SetThreadName("SendMail Thread");
                   3543:        thread_up(TRUE /* setuid */);
                   3544: 
                   3545:        sendmail_running=TRUE;
                   3546:        terminate_sendmail=FALSE;
                   3547: 
                   3548:        lprintf(LOG_DEBUG,"0000 SendMail thread started");
                   3549: 
                   3550:        memset(&msg,0,sizeof(msg));
                   3551:        memset(&smb,0,sizeof(smb));
                   3552: 
                   3553:        while(server_socket!=INVALID_SOCKET && !terminate_sendmail) {
                   3554: 
                   3555:                if(startup->options&MAIL_OPT_NO_SENDMAIL) {
                   3556:                        sem_trywait_block(&sendmail_wakeup_sem,1000);
                   3557:                        continue;
                   3558:                }
                   3559: 
                   3560:                if(active_sendmail!=0)
                   3561:                        active_sendmail=0, update_clients();
                   3562: 
                   3563:                smb_close(&smb);
                   3564: 
                   3565:                if(sock!=INVALID_SOCKET) {
                   3566:                        mail_close_socket(sock);
                   3567:                        sock=INVALID_SOCKET;
                   3568:                }
                   3569: 
                   3570:                if(msgtxt!=NULL) {
                   3571:                        smb_freemsgtxt(msgtxt);
                   3572:                        msgtxt=NULL;
                   3573:                }
                   3574: 
                   3575:                smb_freemsgmem(&msg);
                   3576: 
                   3577:                /* Don't delay on first loop */
                   3578:                if(first_cycle)
                   3579:                        first_cycle=FALSE;
                   3580:                else
                   3581:                        sem_trywait_block(&sendmail_wakeup_sem,startup->sem_chk_freq*1000);
                   3582: 
                   3583:                sprintf(smb.file,"%smail",scfg.data_dir);
                   3584:                smb.retry_time=scfg.smb_retry_time;
                   3585:                smb.subnum=INVALID_SUB;
                   3586:                if((i=smb_open(&smb))!=SMB_SUCCESS) 
                   3587:                        continue;
                   3588:                if((i=smb_locksmbhdr(&smb))!=SMB_SUCCESS)
                   3589:                        continue;
                   3590:                i=smb_getstatus(&smb);
                   3591:                smb_unlocksmbhdr(&smb);
                   3592:                if(i!=0)
                   3593:                        continue;
                   3594:                if(smb.status.last_msg==last_msg && time(NULL)-last_scan<startup->rescan_frequency)
                   3595:                        continue;
                   3596:                last_msg=smb.status.last_msg;
                   3597:                last_scan=time(NULL);
                   3598:                mail=loadmail(&smb,&msgs,/* to network */0,MAIL_YOUR,0);
                   3599:                for(l=0; l<msgs; l++) {
                   3600:                        if(active_sendmail!=0)
                   3601:                                active_sendmail=0, update_clients();
                   3602: 
                   3603:                        if(server_socket==INVALID_SOCKET || terminate_sendmail) /* server stopped */
                   3604:                                break;
                   3605: 
                   3606:                        if(sock!=INVALID_SOCKET) {
                   3607:                                mail_close_socket(sock);
                   3608:                                sock=INVALID_SOCKET;
                   3609:                        }
                   3610: 
                   3611:                        if(msgtxt!=NULL) {
                   3612:                                smb_freemsgtxt(msgtxt);
                   3613:                                msgtxt=NULL;
                   3614:                        }
                   3615: 
                   3616:                        smb_freemsgmem(&msg);
                   3617: 
                   3618:                        msg.hdr.number=mail[l].number;
                   3619:                        if((i=smb_getmsgidx(&smb,&msg))!=SMB_SUCCESS) {
                   3620:                                lprintf(LOG_ERR,"0000 !SEND ERROR %d (%s) getting message index #%lu"
                   3621:                                        ,i, smb.last_error, mail[l].number);
                   3622:                                break;
                   3623:                        }
                   3624:                        if((i=smb_lockmsghdr(&smb,&msg))!=SMB_SUCCESS) {
                   3625:                                lprintf(LOG_WARNING,"0000 !SEND ERROR %d (%s) locking message header #%lu"
                   3626:                                        ,i, smb.last_error, msg.idx.number);
                   3627:                                continue;
                   3628:                        }
                   3629:                        if((i=smb_getmsghdr(&smb,&msg))!=SMB_SUCCESS) {
                   3630:                                smb_unlockmsghdr(&smb,&msg);
                   3631:                                lprintf(LOG_ERR,"0000 !SEND ERROR %d (%s) reading message header #%lu"
                   3632:                                        ,i, smb.last_error, msg.idx.number);
                   3633:                                continue; 
                   3634:                        }
                   3635:                        if(msg.hdr.attr&MSG_DELETE || msg.to_net.type!=NET_INTERNET || msg.to_net.addr==NULL) {
                   3636:                                smb_unlockmsghdr(&smb,&msg);
                   3637:                                continue;
                   3638:                        }
                   3639: 
                   3640:                        if(!(startup->options&MAIL_OPT_SEND_INTRANSIT) && msg.hdr.netattr&MSG_INTRANSIT) {
                   3641:                                smb_unlockmsghdr(&smb,&msg);
                   3642:                                lprintf(LOG_ERR,"0000 SEND Message #%lu from %s to %s - in transit"
                   3643:                                        ,msg.hdr.number, msg.from, msg.to_net.addr);
                   3644:                                continue;
                   3645:                        }
                   3646:                        msg.hdr.netattr|=MSG_INTRANSIT; /* Prevent another sendmail thread from sending this msg */
                   3647:                        smb_putmsghdr(&smb,&msg);
                   3648:                        smb_unlockmsghdr(&smb,&msg);
                   3649: 
                   3650:                        active_sendmail=1, update_clients();
                   3651: 
                   3652:                        lprintf(LOG_INFO,"0000 SEND Message #%lu from %s to %s"
                   3653:                                ,msg.hdr.number, msg.from, msg.to_net.addr);
                   3654:                        status("Sending");
                   3655: #ifdef _WIN32
                   3656:                        if(startup->outbound_sound[0] && !(startup->options&MAIL_OPT_MUTE)) 
                   3657:                                PlaySound(startup->outbound_sound, NULL, SND_ASYNC|SND_FILENAME);
                   3658: #endif
                   3659: 
                   3660:                        lprintf(LOG_DEBUG,"0000 SEND getting message text");
                   3661:                        if((msgtxt=smb_getmsgtxt(&smb,&msg,GETMSGTXT_ALL))==NULL) {
                   3662:                                remove_msg_intransit(&smb,&msg);
                   3663:                                lprintf(LOG_ERR,"0000 !SEND ERROR (%s) retrieving message text",smb.last_error);
                   3664:                                continue;
                   3665:                        }
                   3666: 
                   3667:                        port=0;
                   3668: 
                   3669:                        /* Check if this is a local email ToDo */
                   3670:                        SAFECOPY(to,(char*)msg.to_net.addr);
                   3671:                        truncstr(to,"> ");
                   3672: 
                   3673:                        p=strrchr(to,'@');
                   3674:                        if(p==NULL) {
                   3675:                                remove_msg_intransit(&smb,&msg);
                   3676:                                lprintf(LOG_WARNING,"0000 !SEND INVALID destination address: %s", to);
                   3677:                                SAFEPRINTF(err,"Invalid destination address: %s", to);
                   3678:                                bounce(&smb,&msg,err,TRUE);
                   3679:                                continue;
                   3680:                        }
                   3681:                        p++;
                   3682:                        sprintf(domain_list,"%sdomains.cfg",scfg.ctrl_dir);
                   3683:                        if(stricmp(p,scfg.sys_inetaddr)==0
                   3684:                                        || stricmp(p,startup->host_name)==0
                   3685:                                        || findstr(p,domain_list)) {
                   3686:                                /* This is a local message... no need to send to remote */
                   3687:                                port = startup->smtp_port;
                   3688:                                if(startup->interface_addr==0)
                   3689:                                        server="127.0.0.1";
                   3690:                                else {
                   3691:                                        sprintf(numeric_ip, "%u.%u.%u.%u"
                   3692:                                                        , startup->interface_addr >> 24
                   3693:                                                        , (startup->interface_addr >> 16) & 0xff
                   3694:                                                        , (startup->interface_addr >> 8) & 0xff
                   3695:                                                        , startup->interface_addr & 0xff);
                   3696:                                        server = numeric_ip;
                   3697:                                }
                   3698:                                sending_locally=TRUE;
                   3699:                        }
                   3700:                        else {
                   3701:                                if(startup->options&MAIL_OPT_RELAY_TX) { 
                   3702:                                        server=startup->relay_server;
                   3703:                                        port=startup->relay_port;
                   3704:                                } else {
                   3705:                                        server=p;
                   3706:                                        tp=strrchr(p,':');      /* non-standard SMTP port */
                   3707:                                        if(tp!=NULL) {
                   3708:                                                *tp=0;
                   3709:                                                port=atoi(tp+1);
                   3710:                                        }
                   3711:                                        if(port==0) {   /* No port specified, use MX look-up */
                   3712:                                                get_dns_server(dns_server,sizeof(dns_server));
                   3713:                                                if((dns=resolve_ip(dns_server))==INADDR_NONE) {
                   3714:                                                        remove_msg_intransit(&smb,&msg);
                   3715:                                                        lprintf(LOG_WARNING,"0000 !SEND INVALID DNS server address: %s"
                   3716:                                                                ,dns_server);
                   3717:                                                        continue;
                   3718:                                                }
                   3719:                                                lprintf(LOG_DEBUG,"0000 SEND getting MX records for %s from %s",p,dns_server);
                   3720:                                                if((i=dns_getmx(p, mx, mx2, startup->interface_addr, dns
                   3721:                                                        ,startup->options&MAIL_OPT_USE_TCP_DNS ? TRUE : FALSE
                   3722:                                                        ,TIMEOUT_THREAD_WAIT/2))!=0) {
                   3723:                                                        remove_msg_intransit(&smb,&msg);
                   3724:                                                        lprintf(LOG_WARNING,"0000 !SEND ERROR %d obtaining MX records for %s from %s"
                   3725:                                                                ,i,p,startup->dns_server);
                   3726:                                                        SAFEPRINTF2(err,"Error %d obtaining MX record for %s",i,p);
                   3727:                                                        bounce(&smb,&msg,err,FALSE);
                   3728:                                                        continue;
                   3729:                                                }
                   3730:                                                server=mx;
                   3731:                                        }
                   3732:                                }
                   3733:                        }
                   3734:                        if(!port)
                   3735:                                port=IPPORT_SMTP;
                   3736: 
                   3737:                        if((sock=mail_open_socket(SOCK_STREAM,"smtp|sendmail"))==INVALID_SOCKET) {
                   3738:                                remove_msg_intransit(&smb,&msg);
                   3739:                                lprintf(LOG_ERR,"0000 !SEND ERROR %d opening socket", ERROR_VALUE);
                   3740:                                continue;
                   3741:                        }
                   3742: 
                   3743:                        memset(&addr,0,sizeof(addr));
                   3744:                        addr.sin_addr.s_addr = htonl(startup->interface_addr);
                   3745:                        addr.sin_family = AF_INET;
                   3746: 
                   3747:                        if(startup->seteuid!=NULL)
                   3748:                                startup->seteuid(FALSE);
                   3749:                        i=bind(sock,(struct sockaddr *)&addr, sizeof(addr));
                   3750:                        if(startup->seteuid!=NULL)
                   3751:                                startup->seteuid(TRUE);
                   3752:                        if(i!=0) {
                   3753:                                remove_msg_intransit(&smb,&msg);
                   3754:                                lprintf(LOG_ERR,"%04d !SEND ERROR %d (%d) binding socket", sock, i, ERROR_VALUE);
                   3755:                                continue;
                   3756:                        }
                   3757: 
                   3758:                        strcpy(err,"UNKNOWN ERROR");
                   3759:                        success=FALSE;
                   3760:                        for(j=0;j<2 && !success;j++) {
                   3761:                                if(j) {
                   3762:                                        if(startup->options&MAIL_OPT_RELAY_TX || !mx2[0])
                   3763:                                                break;
                   3764:                                        server=mx2;     /* Give second mx record a try */
                   3765:                                }
                   3766:                                
                   3767:                                lprintf(LOG_DEBUG,"%04d SEND resolving SMTP hostname: %s", sock, server);
                   3768:                                ip_addr=resolve_ip(server);
                   3769:                                if(ip_addr==INADDR_NONE) {
                   3770:                                        SAFEPRINTF(err,"Failed to resolve SMTP hostname: %s",server);
                   3771:                                        continue;
                   3772:                                }
                   3773: 
                   3774:                                memset(&server_addr,0,sizeof(server_addr));
                   3775:                                server_addr.sin_addr.s_addr = ip_addr;
                   3776:                                server_addr.sin_family = AF_INET;
                   3777:                                server_addr.sin_port = htons(port);
                   3778: 
                   3779:                                if((server==mx || server==mx2) 
                   3780:                                        && ((ip_addr&0xff)==127 || ip_addr==0)) {
                   3781:                                        SAFEPRINTF2(err,"Bad IP address (%s) for MX server: %s"
                   3782:                                                ,inet_ntoa(server_addr.sin_addr),server);
                   3783:                                        continue;
                   3784:                                }
                   3785:                                
                   3786:                                lprintf(LOG_INFO,"%04d SEND connecting to port %u on %s [%s]"
                   3787:                                        ,sock
                   3788:                                        ,ntohs(server_addr.sin_port)
                   3789:                                        ,server,inet_ntoa(server_addr.sin_addr));
                   3790:                                if((i=connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)))!=0) {
                   3791:                                        i=ERROR_VALUE;
                   3792:                                        lprintf(LOG_WARNING,"%04d !SEND ERROR %d connecting to SMTP server: %s"
                   3793:                                                ,sock
                   3794:                                                ,i, server);
                   3795:                                        SAFEPRINTF2(err,"Error %d connecting to SMTP server: %s"
                   3796:                                                ,i, server);
                   3797:                                        continue;
                   3798:                                }
                   3799:                                success=TRUE;
                   3800:                        }
                   3801:                        if(!success) {  /* Failed to send, so bounce */
                   3802:                                remove_msg_intransit(&smb,&msg);
                   3803:                                bounce(&smb,&msg,err,FALSE);    
                   3804:                                continue;
                   3805:                        }
                   3806: 
                   3807:                        lprintf(LOG_DEBUG,"%04d SEND connected to %s",sock,server);
                   3808: 
                   3809:                        /* HELO */
                   3810:                        if(!sockgetrsp(sock,"220",buf,sizeof(buf))) {
                   3811:                                remove_msg_intransit(&smb,&msg);
                   3812:                                SAFEPRINTF3(err,badrsp_err,server,buf,"220");
                   3813:                                bounce(&smb,&msg,err,buf[0]=='5');
                   3814:                                continue;
                   3815:                        }
                   3816:                        if(startup->options&MAIL_OPT_RELAY_TX 
                   3817:                                && (startup->options&MAIL_OPT_RELAY_AUTH_MASK)!=0)      /* Requires ESMTP */
                   3818:                                sockprintf(sock,"EHLO %s",startup->host_name);
                   3819:                        else
                   3820:                                sockprintf(sock,"HELO %s",startup->host_name);
                   3821:                        if(!sockgetrsp(sock,"250", buf, sizeof(buf))) {
                   3822:                                remove_msg_intransit(&smb,&msg);
                   3823:                                SAFEPRINTF3(err,badrsp_err,server,buf,"250");
                   3824:                                bounce(&smb,&msg,err,buf[0]=='5');
                   3825:                                continue;
                   3826:                        }
                   3827: 
                   3828:                        /* AUTH */
                   3829:                        if(startup->options&MAIL_OPT_RELAY_TX 
                   3830:                                && (startup->options&MAIL_OPT_RELAY_AUTH_MASK)!=0 && !sending_locally) {
                   3831:                                switch(startup->options&MAIL_OPT_RELAY_AUTH_MASK) {
                   3832:                                        case MAIL_OPT_RELAY_AUTH_PLAIN:
                   3833:                                                p="PLAIN";
                   3834:                                                break;
                   3835:                                        case MAIL_OPT_RELAY_AUTH_LOGIN:
                   3836:                                                p="LOGIN";
                   3837:                                                break;
                   3838:                                        case MAIL_OPT_RELAY_AUTH_CRAM_MD5:
                   3839:                                                p="CRAM-MD5";
                   3840:                                                break;
                   3841:                                        default:
                   3842:                                                p="<unknown>";
                   3843:                                                break;
                   3844:                                }
                   3845:                                sockprintf(sock,"AUTH %s",p);
                   3846:                                if(!sockgetrsp(sock,"334",buf,sizeof(buf))) {
                   3847:                                        SAFEPRINTF3(err,badrsp_err,server,buf,"334 Username/Challenge");
                   3848:                                        bounce(&smb,&msg,err,buf[0]=='5');
                   3849:                                        continue;
                   3850:                                }
                   3851:                                switch(startup->options&MAIL_OPT_RELAY_AUTH_MASK) {
                   3852:                                        case MAIL_OPT_RELAY_AUTH_PLAIN:
                   3853:                                                p=startup->relay_user;
                   3854:                                                break;
                   3855:                                        case MAIL_OPT_RELAY_AUTH_LOGIN:
                   3856:                                                b64_encode(p=resp,sizeof(resp),startup->relay_user,0);
                   3857:                                                break;
                   3858:                                        case MAIL_OPT_RELAY_AUTH_CRAM_MD5:
                   3859:                                                p=buf;
                   3860:                                                FIND_WHITESPACE(p);
                   3861:                                                SKIP_WHITESPACE(p);
                   3862:                                                b64_decode(challenge,sizeof(challenge),p,0);
                   3863: 
                   3864:                                                /* Calculate response */
                   3865:                                                memset(secret,0,sizeof(secret));
                   3866:                                                SAFECOPY(secret,startup->relay_pass);
                   3867:                                                for(i=0;i<sizeof(secret);i++)
                   3868:                                                        md5_data[i]=secret[i]^0x36;     /* ipad */
                   3869:                                                strcpy(md5_data+i,challenge);
                   3870:                                                MD5_calc(digest,md5_data,sizeof(secret)+strlen(challenge));
                   3871:                                                for(i=0;i<sizeof(secret);i++)
                   3872:                                                        md5_data[i]=secret[i]^0x5c;     /* opad */
                   3873:                                                memcpy(md5_data+i,digest,sizeof(digest));
                   3874:                                                MD5_calc(digest,md5_data,sizeof(secret)+sizeof(digest));
                   3875:                                                
                   3876:                                                safe_snprintf(buf,sizeof(buf),"%s %s",startup->relay_user,MD5_hex(str,digest));
                   3877:                                                b64_encode(p=resp,sizeof(resp),buf,0);
                   3878:                                                break;
                   3879:                                        default:
                   3880:                                                p="<unknown>";
                   3881:                                                break;
                   3882:                                }
                   3883:                                sockprintf(sock,"%s",p);
                   3884:                                if((startup->options&MAIL_OPT_RELAY_AUTH_MASK)!=MAIL_OPT_RELAY_AUTH_CRAM_MD5) {
                   3885:                                        if(!sockgetrsp(sock,"334",buf,sizeof(buf))) {
                   3886:                                                SAFEPRINTF3(err,badrsp_err,server,buf,"334 Password");
                   3887:                                                bounce(&smb,&msg,err,buf[0]=='5');
                   3888:                                                continue;
                   3889:                                        }
                   3890:                                        switch(startup->options&MAIL_OPT_RELAY_AUTH_MASK) {
                   3891:                                                case MAIL_OPT_RELAY_AUTH_PLAIN:
                   3892:                                                        p=startup->relay_pass;
                   3893:                                                        break;
                   3894:                                                case MAIL_OPT_RELAY_AUTH_LOGIN:
                   3895:                                                        b64_encode(p=buf,sizeof(buf),startup->relay_pass,0);
                   3896:                                                        break;
                   3897:                                                default:
                   3898:                                                        p="<unknown>";
                   3899:                                                        break;
                   3900:                                        }
                   3901:                                        sockprintf(sock,"%s",p);
                   3902:                                }
                   3903:                                if(!sockgetrsp(sock,"235",buf,sizeof(buf))) {
                   3904:                                        SAFEPRINTF3(err,badrsp_err,server,buf,"235");
                   3905:                                        bounce(&smb,&msg,err,buf[0]=='5');
                   3906:                                        continue;
                   3907:                                }
                   3908:                        }
                   3909: 
                   3910:                        /* MAIL */
                   3911:                        if(msg.from_net.type==NET_INTERNET && msg.reverse_path!=NULL)
                   3912:                                SAFECOPY(fromaddr,msg.reverse_path);
                   3913:                        else 
                   3914:                                usermailaddr(&scfg,fromaddr,msg.from);
                   3915:                        truncstr(fromaddr," ");
                   3916:                        if(fromaddr[0]=='<')
                   3917:                                sockprintf(sock,"MAIL FROM: %s",fromaddr);
                   3918:                        else
                   3919:                                sockprintf(sock,"MAIL FROM: <%s>",fromaddr);
                   3920:                        if(!sockgetrsp(sock,"250", buf, sizeof(buf))) {
                   3921:                                remove_msg_intransit(&smb,&msg);
                   3922:                                SAFEPRINTF3(err,badrsp_err,server,buf,"250");
                   3923:                                bounce(&smb,&msg,err,buf[0]=='5');
                   3924:                                continue;
                   3925:                        }
                   3926:                        /* RCPT */
                   3927:                        if(msg.forward_path!=NULL) {
                   3928:                                SAFECOPY(toaddr,msg.forward_path);
                   3929:                        } else {
                   3930:                                if((p=strrchr((char*)msg.to_net.addr,'<'))!=NULL)
                   3931:                                        p++;
                   3932:                                else
                   3933:                                        p=(char*)msg.to_net.addr;
                   3934:                                SAFECOPY(toaddr,p);
                   3935:                                truncstr(toaddr,"> ");
                   3936:                                if((p=strrchr(toaddr,'@'))!=NULL && (tp=strrchr(toaddr,':'))!=NULL
                   3937:                                        && tp > p)
                   3938:                                        *tp=0;  /* Remove ":port" designation from envelope */
                   3939:                        }
                   3940:                        sockprintf(sock,"RCPT TO: <%s>", toaddr);
                   3941:                        if(!sockgetrsp(sock,"25", buf, sizeof(buf))) {
                   3942:                                remove_msg_intransit(&smb,&msg);
                   3943:                                SAFEPRINTF3(err,badrsp_err,server,buf,"25*");
                   3944:                                bounce(&smb,&msg,err,buf[0]=='5');
                   3945:                                continue;
                   3946:                        }
                   3947:                        /* DATA */
                   3948:                        sockprintf(sock,"DATA");
                   3949:                        if(!sockgetrsp(sock,"354", buf, sizeof(buf))) {
                   3950:                                remove_msg_intransit(&smb,&msg);
                   3951:                                SAFEPRINTF3(err,badrsp_err,server,buf,"354");
                   3952:                                bounce(&smb,&msg,err,buf[0]=='5');
                   3953:                                continue;
                   3954:                        }
                   3955:                        lprintf(LOG_DEBUG,"%04d SEND sending message text (%u bytes)"
                   3956:                                ,sock, strlen(msgtxt));
                   3957:                        lines=sockmsgtxt(sock,&msg,msgtxt,-1);
                   3958:                        if(!sockgetrsp(sock,"250", buf, sizeof(buf))) {
                   3959:                                remove_msg_intransit(&smb,&msg);
                   3960:                                SAFEPRINTF3(err,badrsp_err,server,buf,"250");
                   3961:                                bounce(&smb,&msg,err,buf[0]=='5');
                   3962:                                continue;
                   3963:                        }
                   3964:                        lprintf(LOG_DEBUG,"%04d SEND message transfer complete (%lu lines)", sock, lines);
                   3965: 
                   3966:                        /* Now lets mark this message for deletion without corrupting the index */
                   3967:                        msg.hdr.attr|=MSG_DELETE;
                   3968:                        msg.hdr.netattr&=~MSG_INTRANSIT;
                   3969:                        if((i=smb_updatemsg(&smb,&msg))!=SMB_SUCCESS)
                   3970:                                lprintf(LOG_ERR,"%04d !SEND ERROR %d (%s) deleting message #%lu"
                   3971:                                        ,sock, i, smb.last_error, msg.hdr.number);
                   3972:                        if(msg.hdr.auxattr&MSG_FILEATTACH)
                   3973:                                delfattach(&scfg,&msg);
                   3974: 
                   3975:                        /* QUIT */
                   3976:                        sockprintf(sock,"QUIT");
                   3977:                        sockgetrsp(sock,"221", buf, sizeof(buf));
                   3978:                        mail_close_socket(sock);
                   3979:                        sock=INVALID_SOCKET;
                   3980:                }                               
                   3981:                status(STATUS_WFC);
                   3982:                /* Free up resources here */
                   3983:                if(mail!=NULL)
                   3984:                        freemail(mail);
                   3985:        }
                   3986:        if(sock!=INVALID_SOCKET)
                   3987:                mail_close_socket(sock);
                   3988: 
                   3989:        smb_freemsgtxt(msgtxt);
                   3990:        smb_freemsgmem(&msg);
                   3991:        smb_close(&smb);
                   3992: 
                   3993:        if(active_sendmail!=0)
                   3994:                active_sendmail=0, update_clients();
                   3995: 
                   3996:        thread_down();
                   3997:        lprintf(LOG_DEBUG,"0000 SendMail thread terminated (%u threads remain)", thread_count);
                   3998: 
                   3999:        sendmail_running=FALSE;
                   4000: }
                   4001: 
                   4002: void DLLCALL mail_terminate(void)
                   4003: {
                   4004:        lprintf(LOG_DEBUG,"%04d Mail Server terminate",server_socket);
                   4005:        terminate_server=TRUE;
                   4006: }
                   4007: 
                   4008: static void cleanup(int code)
                   4009: {
                   4010:        int i;
                   4011: 
                   4012:        free_cfg(&scfg);
                   4013: 
                   4014:        semfile_list_free(&recycle_semfiles);
                   4015:        semfile_list_free(&shutdown_semfiles);
                   4016: 
                   4017:        if(mailproc_list!=NULL) {
                   4018:                for(i=0;i<mailproc_count;i++)
                   4019:                        strListFree(&mailproc_list[i].to);
                   4020:                FREE_AND_NULL(mailproc_list);
                   4021:        }
                   4022: 
                   4023:        if(server_socket!=INVALID_SOCKET) {
                   4024:                mail_close_socket(server_socket);
                   4025:                server_socket=INVALID_SOCKET;
                   4026:        }
                   4027: 
                   4028:        if(pop3_socket!=INVALID_SOCKET) {
                   4029:                mail_close_socket(pop3_socket);
                   4030:                pop3_socket=INVALID_SOCKET;
                   4031:        }
                   4032: 
                   4033:        update_clients();
                   4034: 
                   4035: #ifdef _WINSOCKAPI_    
                   4036:        if(WSAInitialized && WSACleanup()!=0) 
                   4037:                lprintf(LOG_ERR,"0000 !WSACleanup ERROR %d",ERROR_VALUE);
                   4038: #endif
                   4039: 
                   4040:        thread_down();
                   4041:        status("Down");
                   4042:        if(terminate_server || code)
                   4043:                lprintf(LOG_INFO,"#### Mail Server thread terminated (%u threads remain, %lu clients served)"
                   4044:                        ,thread_count, served);
                   4045:        if(startup!=NULL && startup->terminated!=NULL)
                   4046:                startup->terminated(startup->cbdata,code);
                   4047: }
                   4048: 
                   4049: const char* DLLCALL mail_ver(void)
                   4050: {
                   4051:        static char ver[256];
                   4052:        char compiler[32];
                   4053: 
                   4054:        DESCRIBE_COMPILER(compiler);
                   4055: 
                   4056:        sscanf("$Revision: 1.412 $", "%*s %s", revision);
                   4057: 
                   4058:        sprintf(ver,"Synchronet Mail Server %s%s  SMBLIB %s  "
                   4059:                "Compiled %s %s with %s"
                   4060:                ,revision
                   4061: #ifdef _DEBUG
                   4062:                ," Debug"
                   4063: #else
                   4064:                ,""
                   4065: #endif
                   4066:                ,smb_lib_ver()
                   4067:                ,__DATE__, __TIME__, compiler
                   4068:                );
                   4069: 
                   4070:        return(ver);
                   4071: }
                   4072: 
                   4073: void DLLCALL mail_server(void* arg)
                   4074: {
                   4075:        char*                   p;
                   4076:        char                    path[MAX_PATH+1];
                   4077:        char                    str[256];
                   4078:        char                    error[256];
                   4079:        char                    compiler[32];
                   4080:        SOCKADDR_IN             server_addr;
                   4081:        SOCKADDR_IN             client_addr;
                   4082:        socklen_t               client_addr_len;
                   4083:        SOCKET                  client_socket;
                   4084:        int                             i;
                   4085:        int                             result;
                   4086:        ulong                   l;
                   4087:        time_t                  t;
                   4088:        time_t                  start;
                   4089:        time_t                  initialized=0;
                   4090:        fd_set                  socket_set;
                   4091:        SOCKET                  high_socket_set;
                   4092:        pop3_t*                 pop3;
                   4093:        smtp_t*                 smtp;
                   4094:        struct timeval  tv;
                   4095:        FILE*                   fp;
                   4096:        str_list_t              sec_list;
                   4097: 
                   4098:        mail_ver();
                   4099: 
                   4100:        startup=(mail_startup_t*)arg;
                   4101: 
                   4102: #ifdef _THREAD_SUID_BROKEN
                   4103:        if(thread_suid_broken)
                   4104:                startup->seteuid(TRUE);
                   4105: #endif
                   4106: 
                   4107:     if(startup==NULL) {
                   4108:        sbbs_beep(100,500);
                   4109:        fprintf(stderr, "No startup structure passed!\n");
                   4110:        return;
                   4111:     }
                   4112: 
                   4113:        if(startup->size!=sizeof(mail_startup_t)) {     /* verify size */
                   4114:                sbbs_beep(100,500);
                   4115:                sbbs_beep(300,500);
                   4116:                sbbs_beep(100,500);
                   4117:                fprintf(stderr, "Invalid startup structure!\n");
                   4118:                return;
                   4119:        }
                   4120: 
                   4121:        /* Setup intelligent defaults */
                   4122:        if(startup->relay_port==0)                              startup->relay_port=IPPORT_SMTP;
                   4123:        if(startup->smtp_port==0)                               startup->smtp_port=IPPORT_SMTP;
                   4124:        if(startup->pop3_port==0)                               startup->pop3_port=IPPORT_POP3;
                   4125:        if(startup->rescan_frequency==0)                startup->rescan_frequency=3600; /* 60 minutes */
                   4126:        if(startup->max_delivery_attempts==0)   startup->max_delivery_attempts=50;
                   4127:        if(startup->max_inactivity==0)                  startup->max_inactivity=120; /* seconds */
                   4128:        if(startup->max_recipients==0)                  startup->max_recipients=100;
                   4129:        if(startup->sem_chk_freq==0)                    startup->sem_chk_freq=2;
                   4130: 
                   4131: #ifdef JAVASCRIPT
                   4132:        if(startup->js.max_bytes==0)                    startup->js.max_bytes=JAVASCRIPT_MAX_BYTES;
                   4133:        if(startup->js.cx_stack==0)                             startup->js.cx_stack=JAVASCRIPT_CONTEXT_STACK;
                   4134: #endif
                   4135: 
                   4136:        uptime=0;
                   4137:        served=0;
                   4138:        startup->recycle_now=FALSE;
                   4139:        startup->shutdown_now=FALSE;
                   4140:        terminate_server=FALSE;
                   4141: 
                   4142:        SetThreadName("Mail Server");
                   4143: 
                   4144:        do {
                   4145: 
                   4146:                thread_up(FALSE /* setuid */);
                   4147: 
                   4148:                status("Initializing");
                   4149: 
                   4150:                memset(&scfg, 0, sizeof(scfg));
                   4151: 
                   4152:                lprintf(LOG_INFO,"Synchronet Mail Server Revision %s%s"
                   4153:                        ,revision
                   4154: #ifdef _DEBUG
                   4155:                        ," Debug"
                   4156: #else
                   4157:                        ,""
                   4158: #endif
                   4159:                        );
                   4160: 
                   4161:                DESCRIBE_COMPILER(compiler);
                   4162: 
                   4163:                lprintf(LOG_INFO,"Compiled %s %s with %s", __DATE__, __TIME__, compiler);
                   4164: 
                   4165:                lprintf(LOG_INFO,"SMBLIB %s (format %x.%02x)",smb_lib_ver(),smb_ver()>>8,smb_ver()&0xff);
                   4166: 
                   4167:                sbbs_srand();
                   4168: 
                   4169:                if(!winsock_startup()) {
                   4170:                        cleanup(1);
                   4171:                        return;
                   4172:                }
                   4173: 
                   4174:                t=time(NULL);
                   4175:                lprintf(LOG_INFO,"Initializing on %.24s with options: %lx"
                   4176:                        ,CTIME_R(&t,str),startup->options);
                   4177: 
                   4178:                /* Initial configuration and load from CNF files */
                   4179:                SAFECOPY(scfg.ctrl_dir,startup->ctrl_dir);
                   4180:                lprintf(LOG_INFO,"Loading configuration files from %s", scfg.ctrl_dir);
                   4181:                scfg.size=sizeof(scfg);
                   4182:                SAFECOPY(error,UNKNOWN_LOAD_ERROR);
                   4183:                if(!load_cfg(&scfg, NULL, TRUE, error)) {
                   4184:                        lprintf(LOG_ERR,"!ERROR %s",error);
                   4185:                        lprintf(LOG_ERR,"!Failed to load configuration files");
                   4186:                        cleanup(1);
                   4187:                        return;
                   4188:                }
                   4189: 
                   4190:                if(startup->temp_dir[0])
                   4191:                        SAFECOPY(scfg.temp_dir,startup->temp_dir);
                   4192:                else
                   4193:                        SAFECOPY(scfg.temp_dir,"../temp");
                   4194:                prep_dir(scfg.ctrl_dir, scfg.temp_dir, sizeof(scfg.temp_dir));
                   4195:                MKDIR(scfg.temp_dir);
                   4196:                lprintf(LOG_DEBUG,"Temporary file directory: %s", scfg.temp_dir);
                   4197:                if(!isdir(scfg.temp_dir)) {
                   4198:                        lprintf(LOG_ERR,"!Invalid temp directory: %s", scfg.temp_dir);
                   4199:                        cleanup(1);
                   4200:                        return;
                   4201:                }
                   4202: 
                   4203:                /* Parse the mailproc[.host].ini */
                   4204:                mailproc_list=NULL;
                   4205:                mailproc_count=0;
                   4206:                iniFileName(path,sizeof(path),scfg.ctrl_dir,"mailproc.ini");
                   4207:                if((fp=iniOpenFile(path, /* create? */FALSE))!=NULL) {
                   4208:                        lprintf(LOG_DEBUG,"Reading %s",path);
                   4209:                        sec_list = iniReadSectionList(fp,/* prefix */NULL);
                   4210:                        if((mailproc_count=strListCount(sec_list))!=0
                   4211:                                && (mailproc_list=malloc(mailproc_count*sizeof(struct mailproc)))!=NULL) {
                   4212:                                for(i=0;i<mailproc_count;i++) {
                   4213:                                        memset(&mailproc_list[i],0,sizeof(struct mailproc));
                   4214:                                        SAFECOPY(mailproc_list[i].cmdline,sec_list[i]);
                   4215:                                        mailproc_list[i].to =
                   4216:                                                iniReadStringList(fp,sec_list[i],"to",",",NULL);
                   4217:                                        mailproc_list[i].passthru =
                   4218:                                                iniReadBool(fp,sec_list[i],"passthru",TRUE);
                   4219:                                        mailproc_list[i].native =
                   4220:                                                iniReadBool(fp,sec_list[i],"native",FALSE);
                   4221:                                }
                   4222:                        }
                   4223:                        iniFreeStringList(sec_list);
                   4224:                        iniCloseFile(fp);
                   4225:                }
                   4226: 
                   4227:                if(startup->host_name[0]==0)
                   4228:                        SAFECOPY(startup->host_name,scfg.sys_inetaddr);
                   4229: 
                   4230:                if(!(scfg.sys_misc&SM_LOCAL_TZ) && !(startup->options&MAIL_OPT_LOCAL_TIMEZONE)) {
                   4231:                        if(putenv("TZ=UTC0"))
                   4232:                                lprintf(LOG_ERR,"!putenv() FAILED");
                   4233:                        tzset();
                   4234: 
                   4235:                        if((t=checktime())!=0) {   /* Check binary time */
                   4236:                                lprintf(LOG_ERR,"!TIME PROBLEM (%ld)",t);
                   4237:                                cleanup(1);
                   4238:                                return;
                   4239:                        }
                   4240:                }
                   4241: 
                   4242:                if(uptime==0)
                   4243:                        uptime=time(NULL);      /* this must be done *after* setting the timezone */
                   4244: 
                   4245:                if(startup->max_clients==0) {
                   4246:                        startup->max_clients=scfg.sys_nodes;
                   4247:                        if(startup->max_clients<10)
                   4248:                                startup->max_clients=10;
                   4249:                }
                   4250: 
                   4251:                lprintf(LOG_DEBUG,"Maximum clients: %u",startup->max_clients);
                   4252: 
                   4253:                lprintf(LOG_DEBUG,"Maximum inactivity: %u seconds",startup->max_inactivity);
                   4254: 
                   4255:                active_clients=0,update_clients();
                   4256: 
                   4257:                /* open a socket and wait for a client */
                   4258: 
                   4259:                server_socket = mail_open_socket(SOCK_STREAM,"smtp");
                   4260: 
                   4261:                if(server_socket == INVALID_SOCKET) {
                   4262:                        lprintf(LOG_ERR,"!ERROR %d opening socket", ERROR_VALUE);
                   4263:                        cleanup(1);
                   4264:                        return;
                   4265:                }
                   4266: 
                   4267:                lprintf(LOG_DEBUG,"%04d SMTP socket opened",server_socket);
                   4268: 
                   4269:                /*****************************/
                   4270:                /* Listen for incoming calls */
                   4271:                /*****************************/
                   4272:                memset(&server_addr, 0, sizeof(server_addr));
                   4273: 
                   4274:                server_addr.sin_addr.s_addr = htonl(startup->interface_addr);
                   4275:                server_addr.sin_family = AF_INET;
                   4276:                server_addr.sin_port   = htons(startup->smtp_port);
                   4277: 
                   4278:                if(startup->seteuid!=NULL)
                   4279:                        startup->seteuid(FALSE);
                   4280:                result = retry_bind(server_socket,(struct sockaddr *)&server_addr,sizeof(server_addr)
                   4281:                        ,startup->bind_retry_count,startup->bind_retry_delay,"SMTP Server",lprintf);
                   4282:                if(startup->seteuid!=NULL)
                   4283:                        startup->seteuid(TRUE);
                   4284:                if(result != 0) {
                   4285:                        lprintf(LOG_ERR,"%04d %s",server_socket, BIND_FAILURE_HELP);
                   4286:                        cleanup(1);
                   4287:                        return;
                   4288:                }
                   4289: 
                   4290:                lprintf(LOG_DEBUG,"%04d SMTP socket bound to port %u"
                   4291:                        ,server_socket, startup->smtp_port);
                   4292: 
                   4293:                result = listen (server_socket, 1);
                   4294: 
                   4295:                if(result != 0) {
                   4296:                        lprintf(LOG_ERR,"%04d !ERROR %d (%d) listening on socket"
                   4297:                                ,server_socket, result, ERROR_VALUE);
                   4298:                        cleanup(1);
                   4299:                        return;
                   4300:                }
                   4301: 
                   4302:                if(startup->options&MAIL_OPT_ALLOW_POP3) {
                   4303: 
                   4304:                        /* open a socket and wait for a client */
                   4305: 
                   4306:                        pop3_socket = mail_open_socket(SOCK_STREAM,"pop3");
                   4307: 
                   4308:                        if(pop3_socket == INVALID_SOCKET) {
                   4309:                                lprintf(LOG_ERR,"!ERROR %d opening POP3 socket", ERROR_VALUE);
                   4310:                                cleanup(1);
                   4311:                                return;
                   4312:                        }
                   4313: 
                   4314:                        lprintf(LOG_DEBUG,"%04d POP3 socket opened",pop3_socket);
                   4315: 
                   4316:                        /*****************************/
                   4317:                        /* Listen for incoming calls */
                   4318:                        /*****************************/
                   4319:                        memset(&server_addr, 0, sizeof(server_addr));
                   4320: 
                   4321:                        server_addr.sin_addr.s_addr = htonl(startup->interface_addr);
                   4322:                        server_addr.sin_family = AF_INET;
                   4323:                        server_addr.sin_port   = htons(startup->pop3_port);
                   4324: 
                   4325:                        if(startup->seteuid!=NULL)
                   4326:                                startup->seteuid(FALSE);
                   4327:                        result = retry_bind(pop3_socket,(struct sockaddr *)&server_addr,sizeof(server_addr)
                   4328:                                ,startup->bind_retry_count,startup->bind_retry_delay,"POP3 Server",lprintf);
                   4329:                        if(startup->seteuid!=NULL)
                   4330:                                startup->seteuid(TRUE);
                   4331:                        if(result != 0) {
                   4332:                                lprintf(LOG_ERR,"%04d %s",pop3_socket,BIND_FAILURE_HELP);
                   4333:                                cleanup(1);
                   4334:                                return;
                   4335:                        }
                   4336: 
                   4337:                        lprintf(LOG_DEBUG,"%04d POP3 socket bound to port %u"
                   4338:                                ,pop3_socket, startup->pop3_port);
                   4339: 
                   4340:                        result = listen (pop3_socket, 1);
                   4341: 
                   4342:                        if(result != 0) {
                   4343:                                lprintf(LOG_ERR,"%04d !ERROR %d (%d) listening on POP3 socket"
                   4344:                                        ,pop3_socket, result, ERROR_VALUE);
                   4345:                                cleanup(1);
                   4346:                                return;
                   4347:                        }
                   4348:                }
                   4349: 
                   4350:                sem_init(&sendmail_wakeup_sem,0,0);
                   4351: 
                   4352:                if(!(startup->options&MAIL_OPT_NO_SENDMAIL))
                   4353:                        _beginthread(sendmail_thread, 0, NULL);
                   4354: 
                   4355:                lprintf(LOG_NOTICE,"%04d Mail Server thread started",server_socket);
                   4356:                status(STATUS_WFC);
                   4357: 
                   4358:                /* Setup recycle/shutdown semaphore file lists */
                   4359:                shutdown_semfiles=semfile_list_init(scfg.ctrl_dir,"shutdown","mail");
                   4360:                recycle_semfiles=semfile_list_init(scfg.ctrl_dir,"recycle","mail");
                   4361:                SAFEPRINTF(path,"%smailsrvr.rec",scfg.ctrl_dir);        /* legacy */
                   4362:                semfile_list_add(&recycle_semfiles,path);
                   4363:                if(!initialized) {
                   4364:                        initialized=time(NULL);
                   4365:                        semfile_list_check(&initialized,recycle_semfiles);
                   4366:                        semfile_list_check(&initialized,shutdown_semfiles);
                   4367:                }
                   4368: 
                   4369:                /* signal caller that we've started up successfully */
                   4370:                if(startup->started!=NULL)
                   4371:                startup->started(startup->cbdata);
                   4372: 
                   4373:                while(server_socket!=INVALID_SOCKET && !terminate_server) {
                   4374: 
                   4375:                        if(active_clients==0) {
                   4376:                                if(!(startup->options&MAIL_OPT_NO_RECYCLE)) {
                   4377:                                        if((p=semfile_list_check(&initialized,recycle_semfiles))!=NULL) {
                   4378:                                                lprintf(LOG_INFO,"%04d Recycle semaphore file (%s) detected"
                   4379:                                                        ,server_socket,p);
                   4380:                                                break;
                   4381:                                        }
                   4382: #if 0  /* unused */
                   4383:                                        if(startup->recycle_sem!=NULL && sem_trywait(&startup->recycle_sem)==0)
                   4384:                                                startup->recycle_now=TRUE;
                   4385: #endif
                   4386:                                        if(startup->recycle_now==TRUE) {
                   4387:                                                lprintf(LOG_NOTICE,"%04d Recycle semaphore signaled", server_socket);
                   4388:                                                startup->recycle_now=FALSE;
                   4389:                                                break;
                   4390:                                        }
                   4391:                                }
                   4392:                                if(((p=semfile_list_check(&initialized,shutdown_semfiles))!=NULL
                   4393:                                                && lprintf(LOG_INFO,"%04d Shutdown semaphore file (%s) detected"
                   4394:                                                ,server_socket,p))
                   4395:                                        || (startup->shutdown_now==TRUE
                   4396:                                                && lprintf(LOG_INFO,"%04d Shutdown semaphore signaled",server_socket))) {
                   4397:                                        startup->shutdown_now=FALSE;
                   4398:                                        terminate_server=TRUE;
                   4399:                                        break;
                   4400:                                }
                   4401:                        }
                   4402: 
                   4403:                        /* now wait for connection */
                   4404: 
                   4405:                        FD_ZERO(&socket_set);
                   4406:                        FD_SET(server_socket,&socket_set);
                   4407:                        high_socket_set=server_socket+1;
                   4408:                        if(startup->options&MAIL_OPT_ALLOW_POP3 
                   4409:                                && pop3_socket!=INVALID_SOCKET) {
                   4410:                                FD_SET(pop3_socket,&socket_set);
                   4411:                                if(pop3_socket+1>high_socket_set)
                   4412:                                        high_socket_set=pop3_socket+1;
                   4413:                        }
                   4414: 
                   4415:                        tv.tv_sec=startup->sem_chk_freq;
                   4416:                        tv.tv_usec=0;
                   4417: 
                   4418:                        if((i=select(high_socket_set,&socket_set,NULL,NULL,&tv))<1) {
                   4419:                                if(i==0)
                   4420:                                        continue;
                   4421:                                if(ERROR_VALUE==EINTR)
                   4422:                                        lprintf(LOG_DEBUG,"%04d Mail Server listening interrupted",server_socket);
                   4423:                                else if(ERROR_VALUE == ENOTSOCK)
                   4424:                        lprintf(LOG_NOTICE,"%04d Mail Server sockets closed",server_socket);
                   4425:                                else
                   4426:                                        lprintf(LOG_WARNING,"%04d !ERROR %d selecting sockets",server_socket,ERROR_VALUE);
                   4427:                                continue;
                   4428:                        }
                   4429: 
                   4430:                        if(server_socket!=INVALID_SOCKET && !terminate_server
                   4431:                                && FD_ISSET(server_socket,&socket_set)) {
                   4432: 
                   4433:                                client_addr_len = sizeof(client_addr);
                   4434:                                client_socket = accept(server_socket, (struct sockaddr *)&client_addr
                   4435:                                ,&client_addr_len);
                   4436: 
                   4437:                                if(client_socket == INVALID_SOCKET)
                   4438:                                {
                   4439: #if 0  /* is this necessary still? */
                   4440:                                        if(ERROR_VALUE == ENOTSOCK || ERROR_VALUE == EINVAL) {
                   4441:                                lprintf(LOG_NOTICE,"%04d SMTP socket closed while listening"
                   4442:                                                        ,server_socket);
                   4443:                                                break;
                   4444:                                        }
                   4445: #endif
                   4446:                                        lprintf(LOG_WARNING,"%04d SMTP !ERROR %d accepting connection"
                   4447:                                                ,server_socket, ERROR_VALUE);
                   4448: #ifdef _WIN32
                   4449:                                        if(WSAGetLastError()==WSAENOBUFS)       /* recycle (re-init WinSock) on this error */
                   4450:                                                break;
                   4451: #endif
                   4452:                                        continue;
                   4453:                                }
                   4454:                                if(startup->socket_open!=NULL)
                   4455:                                        startup->socket_open(startup->cbdata,TRUE);
                   4456:                                sockets++;
                   4457: 
                   4458:                                if(trashcan(&scfg,inet_ntoa(client_addr.sin_addr),"ip-silent")) {
                   4459:                                        mail_close_socket(client_socket);
                   4460:                                        continue;
                   4461:                                }
                   4462: 
                   4463:                                if(active_clients>=startup->max_clients) {
                   4464:                                        lprintf(LOG_WARNING,"%04d SMTP !MAXIMUM CLIENTS (%u) reached, access denied"
                   4465:                                                ,client_socket, startup->max_clients);
                   4466:                                        sockprintf(client_socket,"421 Maximum active clients reached, please try again later.");
                   4467:                                        mswait(3000);
                   4468:                                        mail_close_socket(client_socket);
                   4469:                                        continue;
                   4470:                                }
                   4471: 
                   4472:                                l=1;
                   4473: 
                   4474:                                if((i=ioctlsocket(client_socket, FIONBIO, &l))!=0) {
                   4475:                                        lprintf(LOG_ERR,"%04d SMTP !ERROR %d (%d) disabling blocking on socket"
                   4476:                                                ,client_socket, i, ERROR_VALUE);
                   4477:                                        mail_close_socket(client_socket);
                   4478:                                        continue;
                   4479:                                }
                   4480: 
                   4481:                                if((smtp=malloc(sizeof(smtp_t)))==NULL) {
                   4482:                                        lprintf(LOG_CRIT,"%04d SMTP !ERROR allocating %u bytes of memory for smtp_t"
                   4483:                                                ,client_socket, sizeof(smtp_t));
                   4484:                                        mail_close_socket(client_socket);
                   4485:                                        continue;
                   4486:                                }
                   4487: 
                   4488:                                smtp->socket=client_socket;
                   4489:                                smtp->client_addr=client_addr;
                   4490:                                _beginthread (smtp_thread, 0, smtp);
                   4491:                                served++;
                   4492:                        }
                   4493: 
                   4494:                        if(pop3_socket!=INVALID_SOCKET
                   4495:                                && FD_ISSET(pop3_socket,&socket_set)) {
                   4496: 
                   4497:                                client_addr_len = sizeof(client_addr);
                   4498:                                client_socket = accept(pop3_socket, (struct sockaddr *)&client_addr
                   4499:                                ,&client_addr_len);
                   4500: 
                   4501:                                if(client_socket == INVALID_SOCKET)
                   4502:                                {
                   4503: #if 0  /* is this necessary still? */
                   4504:                                        if(ERROR_VALUE == ENOTSOCK || ERROR_VALUE == EINVAL) {
                   4505:                                lprintf(LOG_NOTICE,"%04d POP3 socket closed while listening",pop3_socket);
                   4506:                                                break;
                   4507:                                        }
                   4508: #endif
                   4509:                                        lprintf(LOG_WARNING,"%04d POP3 !ERROR %d accepting connection"
                   4510:                                                ,pop3_socket, ERROR_VALUE);
                   4511: #ifdef _WIN32
                   4512:                                        if(WSAGetLastError()==WSAENOBUFS)       /* recycle (re-init WinSock) on this error */
                   4513:                                                break;
                   4514: #endif
                   4515:                                        continue;
                   4516:                                }
                   4517:                                if(startup->socket_open!=NULL)
                   4518:                                        startup->socket_open(startup->cbdata,TRUE);
                   4519:                                sockets++;
                   4520: 
                   4521:                                if(trashcan(&scfg,inet_ntoa(client_addr.sin_addr),"ip-silent")) {
                   4522:                                        mail_close_socket(client_socket);
                   4523:                                        continue;
                   4524:                                }
                   4525: 
                   4526:                                if(active_clients>=startup->max_clients) {
                   4527:                                        lprintf(LOG_WARNING,"%04d POP3 !MAXIMUM CLIENTS (%u) reached, access denied"
                   4528:                                                ,client_socket, startup->max_clients);
                   4529:                                        sockprintf(client_socket,"-ERR Maximum active clients reached, please try again later.");
                   4530:                                        mswait(3000);
                   4531:                                        mail_close_socket(client_socket);
                   4532:                                        continue;
                   4533:                                }
                   4534: 
                   4535: 
                   4536:                                l=1;
                   4537: 
                   4538:                                if((i=ioctlsocket(client_socket, FIONBIO, &l))!=0) {
                   4539:                                        lprintf(LOG_ERR,"%04d POP3 !ERROR %d (%d) disabling blocking on socket"
                   4540:                                                ,client_socket, i, ERROR_VALUE);
                   4541:                                        sockprintf(client_socket,"-ERR System error, please try again later.");
                   4542:                                        mswait(3000);
                   4543:                                        mail_close_socket(client_socket);
                   4544:                                        continue;
                   4545:                                }
                   4546: 
                   4547:                                if((pop3=malloc(sizeof(pop3_t)))==NULL) {
                   4548:                                        lprintf(LOG_CRIT,"%04d POP3 !ERROR allocating %u bytes of memory for pop3_t"
                   4549:                                                ,client_socket,sizeof(pop3_t));
                   4550:                                        sockprintf(client_socket,"-ERR System error, please try again later.");
                   4551:                                        mswait(3000);
                   4552:                                        mail_close_socket(client_socket);
                   4553:                                        continue;
                   4554:                                }
                   4555: 
                   4556:                                pop3->socket=client_socket;
                   4557:                                pop3->client_addr=client_addr;
                   4558: 
                   4559:                                _beginthread (pop3_thread, 0, pop3);
                   4560:                                served++;
                   4561:                        }
                   4562:                }
                   4563: 
                   4564:                if(active_clients) {
                   4565:                        lprintf(LOG_DEBUG,"%04d Waiting for %d active clients to disconnect..."
                   4566:                                ,server_socket, active_clients);
                   4567:                        start=time(NULL);
                   4568:                        while(active_clients) {
                   4569:                                if(time(NULL)-start>startup->max_inactivity) {
                   4570:                                        lprintf(LOG_WARNING,"%04d !TIMEOUT waiting for %d active clients"
                   4571:                                                ,server_socket, active_clients);
                   4572:                                        break;
                   4573:                                }
                   4574:                                mswait(100);
                   4575:                        }
                   4576:                }
                   4577: 
                   4578:                if(sendmail_running) {
                   4579:                        terminate_sendmail=TRUE;
                   4580:                        sem_post(&sendmail_wakeup_sem);
                   4581:                        mswait(100);
                   4582:                }
                   4583:                if(sendmail_running) {
                   4584:                        lprintf(LOG_DEBUG,"%04d Waiting for SendMail thread to terminate..."
                   4585:                                ,server_socket);
                   4586:                        start=time(NULL);
                   4587:                        while(sendmail_running) {
                   4588:                                if(time(NULL)-start>TIMEOUT_THREAD_WAIT) {
                   4589:                                        lprintf(LOG_WARNING,"%04d !TIMEOUT waiting for sendmail thread to terminate"
                   4590:                                                ,server_socket);
                   4591:                                        break;
                   4592:                                }
                   4593:                                mswait(500);
                   4594:                        }
                   4595:                }
                   4596:                if(!sendmail_running) {
                   4597:                        while(sem_destroy(&sendmail_wakeup_sem)==-1 && errno==EBUSY) {
                   4598:                                mswait(1);
                   4599:                                sem_post(&sendmail_wakeup_sem);
                   4600:                        }
                   4601:                }
                   4602: 
                   4603:                cleanup(0);
                   4604: 
                   4605:                if(!terminate_server) {
                   4606:                        lprintf(LOG_INFO,"Recycling server...");
                   4607:                        mswait(2000);
                   4608:                        if(startup->recycle!=NULL)
                   4609:                                startup->recycle(startup->cbdata);
                   4610:                }
                   4611: 
                   4612:        } while(!terminate_server);
                   4613: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.