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

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

unix.superglobalmegacorp.com

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