/***************************************************************************** POPular -- A POP3 server and proxy for large mail systems $Id: popular.h,v 1.60 2002/11/28 13:56:03 sqrt Exp $ http://www.remote.org/jochen/mail/popular/ ****************************************************************************** Copyright (C) 1999-2002 Jochen Topf This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA *****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef USE_TLS # include # include # include #endif #ifdef USE_READLINE # include # include #endif #ifndef HAVE_STRLCAT # include "../lib/strl.h" #endif #ifdef HAVE_GETOPT # include #else # include "../lib/getopt.h" #endif #include "pconfig.h" extern int debug; #define PP_FLAGS_M 1 #define max(a,b) ((a) > (b) ? (a) : (b)) #define min(a,b) ((a) < (b) ? (a) : (b)) /***************************************************************************** Results of a mail check from pcheckd. *****************************************************************************/ typedef enum { mcrMail = 0, mcrEmpty = 1, mcrTimeout = 2, mcrLoadTooHigh = 3, mcrMaxSession = 4, mcrError = -1 } mailcheck_result_t; /***************************************************************************** The different types of config parameters. *****************************************************************************/ typedef enum { ctNone = 0, /* end-of-list designator */ ctInt, /* integer value */ ctStr, /* string */ ctFile, /* file name */ ctDir, /* directory name */ ctId, /* some kind of id */ ctBool, /* boolean (0=no=off=false, 1=yes=on=true) */ ctTime, /* a time interval (ie. 10h3m4s) */ ctIgn /* unsupported in this configuration */ } config_type_t; /***************************************************************************** Format of a mail. *****************************************************************************/ typedef enum { mfLF = 0, /* linefeed on end-of-line */ mfCRLF, /* carriage return + linefeed on end-of-line */ mfNET, /* like mfCRLF plus dot stuffing */ } mail_format_t; /***************************************************************************** These are the different kinds of protocols that the POPular proxy supports (or might at some point support). *****************************************************************************/ typedef enum { ptPOP3 = 0, /* POP3 (RFC 1939) */ ptIMAP4, /* IMAP4 */ ptXPOP, /* XPOP (see POPular documentation) */ ptCXPOP, /* Check and XPOP (see POPular doc) */ ptPOP3TLS, /* POP3 over TLS */ ptIMAP4TLS, /* IMAP4 over TLS */ ptPOP3STLS, /* POP3 with STLS */ } protocol_t; struct protocol_info { protocol_t type; /* type (see above) */ char *name; /* descriptive name */ int tls; /* does this protocol use TLS? */ int port; /* default port for this protocol */ int support_client_side; /* protocol supported on client connection */ int support_backend_side; /* protocol supported on backend connection */ }; /***************************************************************************** Different kind of states a proxy or server session can be in. *****************************************************************************/ typedef enum { sstFree = 0, /* proxy and backend: slot free */ sstNew, /* proxy and backend: new connection */ sstIdle, /* backend: idle */ sstRead, /* backend: reading mail */ sstDone, /* proxy: closing down */ sstAuthPhase, /* proxy: authenticating user */ sstVirtServDisabled, /* proxy: virt server is disabled */ sstVirtServFake, /* proxy: virt server is to be faked */ sstCheck, /* proxy: checking for mails in mailbox */ sstConnecting, /* proxy: connecting to backend */ sstBackendUnreachable, /* proxy: backend unreachable */ sstBackendDisabled, /* proxy: backend disabled */ sstBackendFake, /* proxy: backend is to be faked */ sstProxy, /* proxy: transfering data back and forth */ sstMailboxEmpty, /* proxy: mailbox is empty */ sstUnknownBackend, /* proxy: unknown backend */ sstConnQuit, /* backend: connection properly closed */ sstConnBroken, /* backend: connection not properly closed */ } session_state_t; struct session_state_info { session_state_t type; /* type (see above) */ char *name; /* descriptive name */ }; /***************************************************************************** States a virtual server can be in. *****************************************************************************/ typedef enum { vsstFree = 0, /* this virtual server slot is unused */ vsstOffline, /* virtual server doesn't listen on port */ vsstDisabled, /* server listens, but sends error msg on */ /* connect */ vsstFake, /* server listens, all connections are faked */ vsstOnline /* virtual server is online */ } virt_serv_state_t; struct virt_serv_state_info { virt_serv_state_t type; /* type (see above) */ char *name; /* descriptive name */ int listen; /* listen on port in this state ? */ }; /***************************************************************************** States a backend can be in. *****************************************************************************/ typedef enum { bstFree = 0, /* this backend slot is unused */ bstOffline, /* backend is offline, send error msg */ bstFake, /* backend is offline, fake connection */ bstOnline /* backend is online */ } backend_state_t; struct backend_state_info { backend_state_t type; /* type (see above) */ char *name; /* descriptive name */ }; /***************************************************************************** Capability types for virtual servers. *****************************************************************************/ typedef enum { capa_error, capa_none, capa_default, capa_user } capa_t; /***************************************************************************** STARTTLS types for virtual servers. *****************************************************************************/ typedef enum { starttls_off, starttls_optional, starttls_force } starttls_t; /***************************************************************************** Description of a virtual server. *****************************************************************************/ struct virt_serv { char id[MAXLEN_ID+1]; protocol_t prot; struct sockaddr_in local_addr; char namespace[MAXLEN_ID+1]; virt_serv_state_t state; capa_t capa_type; starttls_t starttls_type; struct capa *capa_ptr; char banner_ok[MAXLEN_BANNER+1]; char banner_err[MAXLEN_BANNER+1]; int fd; /* file descriptor for listen */ #if USE_TLS SSL_CTX *ssl_ctx; #endif }; /***************************************************************************** Description of a backend. *****************************************************************************/ struct backend { char id[MAXLEN_ID+1]; protocol_t prot; struct sockaddr_in backend_addr; backend_state_t state; }; /***************************************************************************** struct proxy_session *****************************************************************************/ struct proxy_session { session_state_t state; /* state of this session */ pid_t pid; /* process id of child process handling this session */ time_t starttime; /* start time of this session */ time_t statetime; /* time when the server switched into the current state */ long mailcheck_time; /* time in usecs for mail check */ int mailcheck_retry; /* number of retries for mail check */ struct sockaddr_in sin_client_remote; /* remote side of conn. to client */ struct sockaddr_in sin_client_local; /* local side of conn. to client */ struct sockaddr_in sin_backend_remote; /* remote side of conn. to backend */ struct sockaddr_in sin_backend_local; /* local side of conn. to backend */ int fd_client; /* file descriptor to client */ struct io_ctx *ioc_client; /* IO context to client */ struct io_ctx *ioc_backend; /* IO context to backend */ struct virt_serv vs; /* virtual server for this session */ struct backend backend; /* backend for this session */ char namespace[MAXLEN_ID+1]; /* namespace for this session */ char username[MAXLEN_USERNAME+1]; /* username sent by client */ char password[MAXLEN_PASSWORD+1]; /* password sent by client */ char mailbox[MAXLEN_MAILBOX+1]; /* name of mailbox for backend */ char id[MAXLEN_SESSION_ID+1]; /* session id */ unsigned long bytesin; /* bytes from client to backend */ unsigned long bytesout; /* bytes from backend to client */ }; /***************************************************************************** struct backend_session *****************************************************************************/ struct backend_session { session_state_t state; /* state of this session */ pid_t pid; /* process id of child process handling this session */ time_t starttime; /* start time */ time_t statetime; /* time when the server switched into the current state */ struct sockaddr_in sin_proxy; /* remote side of conn. to proxy */ char username[MAXLEN_USERNAME+1]; /* username sent by client */ char mailbox[MAXLEN_MAILBOX+1]; /* name of mailbox for backend */ char id[MAXLEN_SESSION_ID+1]; /* session id */ char flags[MAXLEN_FLAGS+1]; /* flags for this session */ unsigned long msgnum; /* number of mails in mailbox */ unsigned long msgnew; /* number of new mails in mailbox */ unsigned long msgread; /* number of messages read */ unsigned long msgdel; /* number of messages deleted */ }; /***************************************************************************** struct capa *****************************************************************************/ struct capa { struct capa *next; /* next capa struct in linked list */ char name[MAXLEN_ID+1]; /* name of this capability list */ char text[MAXLEN_CAPA+1]; /* text of capabilities */ }; struct pserv_capa { capa_t capa_type; char name[MAXLEN_ID+1]; /* name of this capability list */ char text[MAXLEN_CAPA+1]; /* text of capabilities */ }; /***************************************************************************** *****************************************************************************/ struct auth_request { char *user; char *pass; char *peer; char *namespace; }; struct auth_result_data { int flags; char backend[MAXLEN_ID]; char user[MAXLEN_USERNAME]; char pass[MAXLEN_PASSWORD]; }; /***************************************************************************** struct configdesc *****************************************************************************/ struct configdesc { char *tag; int readwrite; config_type_t type; void *ptr; int min, max, def; char *defstr; }; /***************************************************************************** struct pproxyconfig All the config options for the pop proxy are saved in here. *****************************************************************************/ struct pproxyconfig { int allowsslv2; int authtimeout; int backlog; char capadir[MAX_FILE_LEN]; int checkport; int checktimeout; char defaultns[MAXLEN_ID+1]; char fallback[MAXLEN_ID+1]; char id[20]; int idletimeout; char logfile[80]; int maxlocalload; int maxsession; char pdmdir[MAX_FILE_LEN]; pid_t pid; int proxytimeout; char rundir[MAX_FILE_LEN]; int sessionlimit; int sessiontimeout; char sidprefix[32]; char tlsdir[MAX_FILE_LEN]; char version[20]; }; /***************************************************************************** struct pservconfig All the config options for the pop server are saved in here. *****************************************************************************/ struct pservconfig { int backlog; char capadir[MAX_FILE_LEN]; char id[20]; int idletimeout; char localip[16]; int logeachmsg; char logfile[80]; int maxlocalload; int maxsession; pid_t pid; char popdir[MAX_FILE_LEN]; char rundir[MAX_FILE_LEN]; int servport; int sessionlimit; int sessiontimeout; int statusheader; char version[20]; }; /***************************************************************************** struct shmem_desc *****************************************************************************/ struct shmem_desc { char magic[8]; /* magic 'POPULAR\0' */ char type[8]; /* type 'PROXY\0' oder 'SERVER\0' */ int version; long starttime; }; /***************************************************************************** struct shmem_proxy_stat *****************************************************************************/ struct shmem_proxy_stat { unsigned long connections; /* number of client connections */ unsigned long bytesin; /* bytes from client to backend */ unsigned long bytesout; /* bytes from backend to client */ unsigned long mailcheck_time; /* accumulated time for all mail checks */ unsigned long mailcheck_retry[MAILCHECK_MAX_REQUESTS+1]; }; /***************************************************************************** struct shmem_proxy *****************************************************************************/ struct shmem_proxy { char magic[8]; /* magic string 'POPULAR\0' */ char type[8]; /* magic string 'PROXY\0\0\0' */ int version; long starttime; int max_virt_serv; int max_backend; int max_sessions, n_sessions, used_sessions; struct shmem_proxy_stat stat; struct proxy_session session[MAX_SESSION]; }; /***************************************************************************** struct shmem_backend_stat *****************************************************************************/ struct shmem_backend_stat { unsigned long connections; /* number of connections from proxy */ unsigned long bytesin; /* bytes from proxy to backend */ unsigned long bytesout; /* bytes from backend to proxy */ unsigned long msgread; /* number of messages read */ unsigned long msgdel; /* number of messages deleted */ unsigned long connquit; /* number of properly closed connections */ unsigned long connbroken; /* number of not properly closed connections */ }; /***************************************************************************** struct shmem_backend *****************************************************************************/ struct shmem_backend { char magic[8]; /* magic string 'POPULAR\0' */ char type[8]; /* magic string 'SERVER\0\0' */ int version; long starttime; struct pservconfig conf; struct shmem_backend_stat stat; int max_sessions, n_sessions, used_sessions; struct backend_session session[MAX_SESSION]; }; /***************************************************************************** for shutdown *****************************************************************************/ #define SHUTDOWN_SERVER 1 #define SHUTDOWN_CHILDREN 2 #define SHUTDOWN_DELAYED 4 /***************************************************************************** for debug *****************************************************************************/ #define DG_MAIN 0x0001 #define DG_AUTH 0x0002 #define DG_PASS 0x0004 #define DG_POP 0x0008 #define DG_CTRL 0x0010 #define DG_NET 0x0020 #define DG_RINGD 0x0040 #define DG_TLS 0x0080 #define DG_IO 0x0100 #define DG_ALL 0x01ff struct debug_info { int type; char *name; }; /***************************************************************************** Debugging Macros Use like this: DEBUG0(DG_MISC, "main", "misc"); DEBUGX(DG_NET, "main", "net %d", 1); DEBUGX(DG_AUTH, "main", "auth %d %s", 1, "xx"); *****************************************************************************/ #define DEBUG0(type, func, text) \ if (debug & (type)) do { \ xlog_printf(xlog_dbg, 0x0000, #type ":" func ":" __FILE__ ":%d " text, __LINE__); \ } while (0) /* this isn't supported by older gccs :-( #define DEBUGX(type, func, text, ...) \ if (debug & (type)) do { \ xlog_printf(xlog_dbg, 0x0000, #type ":" func ":" __FILE__ ":%d " text, __LINE__, __VA_ARGS__); \ } while (0) */ #define DEBUG1(type, func, text, a1) \ if (debug & (type)) do { \ xlog_printf(xlog_dbg, 0x0000, #type ":" func ":" __FILE__ ":%d " text, __LINE__, (a1)); \ } while (0) #define DEBUG2(type, func, text, a1, a2) \ if (debug & (type)) do { \ xlog_printf(xlog_dbg, 0x0000, #type ":" func ":" __FILE__ ":%d " text, __LINE__, (a1), (a2)); \ } while (0) #define DEBUG3(type, func, text, a1, a2, a3) \ if (debug & (type)) do { \ xlog_printf(xlog_dbg, 0x0000, #type ":" func ":" __FILE__ ":%d " text, __LINE__, (a1), (a2), (a3)); \ } while (0) #define DEBUG4(type, func, text, a1, a2, a3, a4) \ if (debug & (type)) do { \ xlog_printf(xlog_dbg, 0x0000, #type ":" func ":" __FILE__ ":%d " text, __LINE__, (a1), (a2), (a3), (a4)); \ } while (0) #define DEBUG5(type, func, text, a1, a2, a3, a4, a5) \ if (debug & (type)) do { \ xlog_printf(xlog_dbg, 0x0000, #type ":" func ":" __FILE__ ":%d " text, __LINE__, (a1), (a2), (a3), (a4), (a5)); \ } while (0) #define DEBUG6(type, func, text, a1, a2, a3, a4, a5, a6) \ if (debug & (type)) do { \ xlog_printf(xlog_dbg, 0x0000, #type ":" func ":" __FILE__ ":%d " text, __LINE__, (a1), (a2), (a3), (a4), (a5), (a6)); \ } while (0) /***************************************************************************** *****************************************************************************/ #include "util.h" #include "io.h" #include "info.h" #include "pdm.h" #include "pop3.h" #include "xlog.h" #include "sig.h" #include "uds.h" #include "mailbox.h" #include "smtp_after_pop.h" /** THE END *****************************************************************/