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

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

unix.superglobalmegacorp.com

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