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

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

unix.superglobalmegacorp.com

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