1 /*
2 **
3 ** Copyright (c) 2010-2017 The SquirrelMail Project Team
4 ** Copyright (c) 2002-2010 Dave McMurtrie
5 **
6 ** Licensed under the GNU GPL. For full terms see the file COPYING.
7 **
8 ** This file is part of SquirrelMail IMAP Proxy.
9 **
10 **  Facility:
11 **
12 **	imapproxy.h
13 **
14 **  Abstract:
15 **
16 **	Common definitions and function prototypes for the IMAP proxy server.
17 **
18 **  Authors:
19 **
20 **      Dave McMurtrie <davemcmurtrie@hotmail.com>
21 **
22 **  Version:
23 **
24 **      $Id: imapproxy.h 14647 2017-01-27 20:53:57Z pdontthink $
25 **
26 **  Modification History:
27 **
28 **      $Log$
29 **
30 **      Revision 1.30  2009/10/16 14:35:17  dave64
31 **      Applied patch by Jose Luis Tallon to improve server connect retry logic.
32 **
33 **      Revision 1.29  2009/10/16 14:29:21  dave64
34 **      Applied patch by Jose Luis Tallon to allow for default config options.
35 **
36 **      Revision 1.28  2008/10/20 13:22:19  dave64
37 **      Applied patch by Michael M. Slusarz to support XPROXYREUSE.
38 **
39 **      Revision 1.27  2007/11/15 11:11:46  dave64
40 **      Added pidfile support patch by Jose Luis Tallón.
41 **
42 **      Revision 1.26  2007/05/31 12:07:41  dave64
43 **      Applied ipv6 patch by Antonio Querubin.
44 **
45 **      Revision 1.25  2007/05/31 11:46:00  dave64
46 **      Applied OpenSSL threads patch by Jan Grant.
47 **
48 **      Revision 1.24  2005/07/06 11:51:25  dgm
49 **      Added enable_admin_commands to struct ProxyConfig
50 **
51 **      Revision 1.23  2005/06/15 12:13:40  dgm
52 **      Changed all long int values to int.  Changed logouttime in
53 **      IMAPConnectionContext to time_t.  Added atoui function
54 **      prototype.  Patch by Dave Steinberg and Jarno Huuskonen to
55 **      allow chroot.
56 **
57 **      Revision 1.22  2005/01/12 17:51:19  dgm
58 **      Applied patch by David Lancaster to provide force_tls
59 **      config option.
60 **
61 **      Revision 1.21  2005/01/12 16:50:59  dgm
62 **      cache_size and cache_expiration_time in struct ProxyConfig now
63 **      declared as unsigned int instead of unsigned long.
64 **
65 **      Revision 1.20  2004/11/10 15:35:13  dgm
66 **      Changed LiteralBytesRemaining from signed long to unsigned long.
67 **
68 **      Revision 1.19  2004/10/11 18:00:42  dgm
69 **      Added foreground_mode configuration option.
70 **
71 **      Revision 1.18  2004/03/11 15:17:58  dgm
72 **      SELECT_BUF_SIZE size changed from 1024 to BUFSIZE which is
73 **      currently 4096
74 **
75 **      Revision 1.17  2004/02/24 15:21:01  dgm
76 **      Added support for SELECT caching.
77 **
78 **      Revision 1.16  2003/11/14 15:06:14  dgm
79 **      Patch by Geoffrey Hort <g.hort@unsw.edu.au> to include listen_address
80 **      config option.  Also, I changed the default buffer size from
81 **      1024 to 4096.
82 **
83 **      Revision 1.15  2003/10/09 15:05:01  dgm
84 **      Added tcp keepalive support.
85 **
86 **      Revision 1.14  2003/07/14 16:41:18  dgm
87 **      Applied patch by William Yodlowsky <wyodlows@andromeda.rutgers.edu> to
88 **      allow TLS to work on machines without /dev/random.
89 **
90 **      Revision 1.13  2003/05/20 19:18:00  dgm
91 **      Comment changes only.
92 **
93 **      Revision 1.12  2003/05/15 12:30:39  dgm
94 **      include netinet/in.h
95 **
96 **      Revision 1.11  2003/05/13 11:38:53  dgm
97 **      Patches by Ken Murchison <ken@oceana.com> to clean up build process.
98 **
99 **      Revision 1.10  2003/05/06 12:09:12  dgm
100 **      Applied patches by Ken Murchison <ken@oceana.com> to add SSL
101 **      support and remove old base64 functions.
102 **
103 **      Revision 1.9  2003/04/16 12:19:29  dgm
104 **      Added support for syslog configuration.
105 **      Added base64 routine prototypes that I previously forgot.
106 **
107 **      Revision 1.8  2003/03/19 13:24:50  dgm
108 **      Applied patch by Devrim Seral  <devrim@gazi.edu.tr> to allow
109 **      the default configfile to be configurable via a configure script.
110 **      (Lots of configures in that sentence, huh?)
111 **
112 **      Revision 1.7  2003/02/20 12:40:08  dgm
113 **      Added UNSELECT support.
114 **
115 **      Revision 1.6  2003/02/19 13:03:35  dgm
116 **      Added LITERAL_PASSWORD and NON_LITERAL_PASSWORD definitions.
117 **
118 **      Revision 1.5  2003/01/22 15:33:53  dgm
119 **      Changed Get_Server_sd() function prototype to reflect the addition of
120 **      the literal password flag.
121 **
122 **      Revision 1.4  2002/12/19 21:41:32  dgm
123 **      Added support for global configuration.
124 **
125 **      Revision 1.3  2002/08/30 13:21:42  dgm
126 **      Added total client logins counter to IMAPCounter struct
127 **
128 **      Revision 1.2  2002/08/29 16:33:46  dgm
129 **      Added CountTime field to struct IMAPCounter.
130 **      Removed #define for max number of open file descriptors since
131 **      we now determine rlimit dynamically instead.
132 **      Added POLL_TIMEOUT stuff.
133 **
134 **      Revision 1.1  2002/07/03 11:21:12  dgm
135 **      Initial revision
136 **
137 */
138 
139 
140 #ifndef __IMAPPROXY_H
141 #define __IMAPPROXY_H
142 
143 #include <netdb.h>
144 #include <pthread.h>
145 #include <netinet/in.h>
146 #include <time.h>
147 #include "config.h"
148 
149 #if HAVE_LIBSSL
150 #include <openssl/ssl.h>
151 #include <openssl/md5.h>
152 #include <openssl/rand.h>
153 #include <limits.h>
154 #endif
155 
156 #ifndef PR_SET_NO_NEW_PRIVS
157 #define PR_SET_NO_NEW_PRIVS 38
158 #endif
159 
160 
161 /*
162  * Common definitions
163  */
164 #define PGM                     "in.imapproxyd"
165 #define IMAP_UNTAGGED_OK        "* OK "           /* untagged OK response    */
166 #define IMAP_TAGGED_OK          "1 OK "           /* tagged OK response      */
167 #define BUFSIZE                 8192              /* default buffer size     */
168 #define MAX_CONN_BACKLOG        5                 /* tcp connection backlog  */
169 #define MAXTAGLEN               256               /* max IMAP tag length     */
170 #define MAXMAILBOXNAME          512               /* max mailbox name length */
171 #define MAXUSERNAMELEN          256               /* max username length     */
172 #define MAXPASSWDLEN            8192              /* max passwd length       */
173 #define POLL_TIMEOUT_MINUTES    30                /* Poll timeout in minutes */
174 #define POLL_TIMEOUT            (POLL_TIMEOUT_MINUTES * 60000)
175 #define SELECT_BUF_SIZE         BUFSIZE           /* max length of a SELECT  */
176 						  /* string we can cache     */
177 #define SELECT_CACHE_EXP        10                /* # of seconds before we  */
178                                                   /* expire a SELECT cache   */
179 #define SELECT_STATUS_BUF_SIZE  256               /* size of select status   */
180 
181 #ifndef DEFAULT_CONFIG_FILE
182 #define DEFAULT_CONFIG_FILE     "/etc/imapproxy.conf"
183 #endif
184 #ifndef DEFAULT_PID_FILE
185 #define DEFAULT_PID_FILE       "/var/run/imapproxy.pid"
186 #endif
187 
188 #define LITERAL_PASSWORD        1
189 #define NON_LITERAL_PASSWORD    0
190 #define UNSELECT_SUPPORTED      1
191 #define UNSELECT_NOT_SUPPORTED  0
192 #define STARTTLS_SUPPORTED      1
193 #define STARTTLS_NOT_SUPPORTED  0
194 #define LOGIN_DISABLED          1
195 #define LOGIN_NOT_DISABLED      0
196 
197 
198 #define DEFAULT_SERVER_CONNECT_RETRIES	10
199 #define DEFAULT_SERVER_CONNECT_DELAY	5
200 
201 /*
202  * One IMAPServerDescriptor will be globally allocated such that each thread
203  * can save the time of doing host lookups, service lookups, and filling
204  * in the sockaddr_storage struct.
205  */
206 struct IMAPServerDescriptor
207 {
208     struct addrinfo *airesults; /* IMAP server info (top of addrinfo
209 				   list from getaddrinfo() */
210     struct addrinfo *srv;	/* IMAP server active socket info */
211 };
212 
213 
214 /*
215  * IMAPSelectCaches provide for caching of SELECT output from an IMAP server
216  */
217 struct IMAPSelectCache
218 {
219     time_t ISCTime;
220     char MailboxName[ MAXMAILBOXNAME ];
221     char SelectString[ SELECT_BUF_SIZE ];
222     char SelectStatus[ SELECT_STATUS_BUF_SIZE ];
223 };
224 
225 
226 /*
227  * IMAPConnectionDescriptors contain the info needed to communicate on an
228  * IMAP connection.
229  */
230 struct IMAPConnectionDescriptor
231 {
232     int sd;                          /* socket descriptor                    */
233 #if HAVE_LIBSSL
234     SSL *tls;                        /* TLS connection context               */
235 #endif
236     struct IMAPSelectCache ISC;      /* Cached SELECT data                   */
237     struct IMAPConnectionContext *ICC; /* backreference the ICC */
238     unsigned int reused;             /* Was the connection reused?           */
239 };
240 
241 
242 /*
243  * IMAPTransactionDescriptors facilitate multi-line buffered reads from
244  * IMAP servers and clients.
245  */
246 struct IMAPTransactionDescriptor
247 {
248     struct IMAPConnectionDescriptor *conn;
249     char ReadBuf[ BUFSIZE ];         /* Read Buffer                          */
250     unsigned int BytesInReadBuffer;  /* bytes left in read buffer            */
251     unsigned int ReadBytesProcessed; /* bytes already processed in read buf  */
252     unsigned int LiteralBytesRemaining; /* num of bytes left as literal     */
253     unsigned char NonSyncLiteral;    /* rfc2088 alert flag                   */
254     unsigned char MoreData;          /* flag to tell caller "more data"      */
255     unsigned char TraceOn;           /* trace this transaction?              */
256 };
257 
258 
259 /*
260  * IMAPConnectionContext structures are used to cache connection info on
261  * a per-user basis.
262  */
263 struct IMAPConnectionContext
264 {
265     struct IMAPConnectionDescriptor *server_conn;
266     char username[MAXUSERNAMELEN];      /* username connected on this sd     */
267     char hashedpw[16];                  /* md5 hash copy of password         */
268     time_t logouttime;                  /* time the user logged out last     */
269     struct IMAPConnectionContext *next; /* linked list next pointer          */
270 };
271 
272 
273 /*
274  * One ProxyConfig structure will be used globally to keep track of
275  * configurable options.  All of these options are set by reading values
276  * from the global config file except for support_unselect.  That's set
277  * based on the CAPABILITY string from the real IMAP server.
278  */
279 struct ProxyConfig
280 {
281     char *listen_port;         	              /* port we bind to */
282     char *listen_addr;                        /* address we bind to */
283     char *server_hostname;                    /* server we proxy to */
284     char *server_port;                        /* port we proxy to */
285     unsigned int server_connect_retries;      /* connect retries to IMAP server */
286     unsigned int server_connect_delay;	      /* delay between connection retry rounds */
287     unsigned int cache_size;                  /* number of cache slots */
288     unsigned int cache_expiration_time;       /* cache exp time in seconds */
289     unsigned int send_tcp_keepalives;         /* flag to send keepalives */
290     unsigned int enable_select_cache;         /* flag to enable select cache */
291     unsigned int foreground_mode;             /* flag to enable fg mode */
292     char *proc_username;                      /* username to run as */
293     char *proc_groupname;                     /* groupname to run as */
294     char *stat_filename;                      /* mmap()ed stat filename */
295     char *protocol_log_filename;              /* global trace filename */
296     char *syslog_facility;                    /* syslog log facility */
297     char *syslog_prioritymask;                /* syslog priority mask */
298     char *tls_ca_file;                        /* file with CA certs */
299     char *tls_ca_path;                        /* path to directory CA certs */
300     char *tls_cert_file;                      /* file with client cert */
301     char *tls_key_file;                       /* file with client priv key */
302     char *tls_ciphers;                        /* TLS Cipher suite */
303     unsigned int tls_verify_server;           /* flag to require server cert validation */
304     unsigned int tls_no_tlsv1;                /* flag to disable TLSv1 */
305     unsigned int tls_no_tlsv1_1;              /* flag to disable TLSv1.1 */
306     unsigned int tls_no_tlsv1_2;              /* flag to disable TLSv1.2 */
307     unsigned int force_tls;                   /* flag to force TLS */
308     unsigned int enable_admin_commands;       /* flag to enable admin cmds */
309     unsigned char support_unselect;           /* unselect support flag */
310     unsigned char support_starttls;           /* starttls support flag */
311     unsigned char login_disabled;             /* login disabled flag */
312     char *chroot_directory;                   /* chroot(2) into this dir */
313     char *preauth_command;                    /* arbitrary pre-authentication command */
314     char *auth_sasl_plain_username;           /* authentication username under SASL PLAIN */
315     char *auth_sasl_plain_password;           /* authentication password under SASL PLAIN */
316     char *auth_shared_secret;                 /* REQUIRED shared secret in leiu of a user password when using LOGIN command with SASL PLAIN authentication */
317     unsigned int ipversion;                   /* limit DNS requests to AF_INET or AF_INET6 */
318     unsigned int dnsrr;                       /* cycle through all DNS entries we got */
319 };
320 
321 
322 /*
323  * One IMAPCounter structure will be used globally to keep track of
324  * several different things that we want to keep a count of, purely for
325  * diagnostic, or usage tracking purposes.
326  *
327  * IMPORTANT NOTE: No attempt is made to guarantee that these counters
328  * will be completely accurate.  No mutex is ever taken out when these
329  * counters are updated.  This was done for performance -- these numbers
330  * aren't considered important enough to waste time locking a mutex to
331  * guarantee their accuracy.
332  */
333 struct IMAPCounter
334 {
335     time_t StartTime;
336     time_t CountTime;
337     unsigned int CurrentClientConnections;
338     unsigned int PeakClientConnections;
339     unsigned int InUseServerConnections;
340     unsigned int PeakInUseServerConnections;
341     unsigned int RetainedServerConnections;
342     unsigned int PeakRetainedServerConnections;
343     unsigned int TotalClientConnectionsAccepted;
344     unsigned int TotalClientLogins;
345     unsigned int TotalServerConnectionsCreated;
346     unsigned int TotalServerConnectionsReused;
347     unsigned int TotalSelectCommands;
348     unsigned int SelectCacheHits;
349     unsigned int SelectCacheMisses;
350 };
351 
352 
353 
354 typedef struct IMAPServerDescriptor ISD_Struct;
355 typedef struct IMAPTransactionDescriptor ITD_Struct;
356 typedef struct IMAPConnectionDescriptor ICD_Struct;
357 typedef struct IMAPConnectionContext ICC_Struct;
358 typedef struct IMAPCounter IMAPCounter_Struct;
359 typedef struct ProxyConfig ProxyConfig_Struct;
360 typedef struct IMAPSelectCache ISC_Struct;
361 
362 /*
363  * Function prototypes for external entry points.
364  */
365 extern int IMAP_Write( ICD_Struct *, const void *, int );
366 extern int IMAP_Read( ICD_Struct *, void *, int );
367 extern int IMAP_Line_Read( ITD_Struct * );
368 extern int IMAP_Literal_Read( ITD_Struct * );
369 extern void HandleRequest( int );
370 extern char *memtok( char *, char *, char ** );
371 extern int imparse_isatom( const char * );
372 extern ICD_Struct *Get_Server_conn( char *, char *, const char *, const char *, unsigned char, char *, char * );
373 extern void ICC_Logout( ICC_Struct * );
374 extern void ICC_Recycle( unsigned int );
375 extern void ICC_Recycle_Loop( void );
376 extern void LockMutex( pthread_mutex_t * );
377 extern void UnLockMutex( pthread_mutex_t * );
378 extern void SetDefaultConfigValues(ProxyConfig_Struct *);
379 extern void SetConfigOptions( char * );
380 extern void SetLogOptions( void );
381 extern int Handle_Select_Command( ITD_Struct *, ITD_Struct *, ISC_Struct *, char *, int );
382 extern unsigned int Is_Safe_Command( char *Command );
383 extern void Invalidate_Cache_Entry( ISC_Struct * );
384 extern int atoui( const char *, unsigned int * );
385 
386 
387 #ifndef MD5_DIGEST_LENGTH
388 #define MD5_DIGEST_LENGTH 16	/* When would it ever be different? */
389 #endif
390 extern void ssl_thread_setup(const char * fn);
391 
392 
393 #endif /* __IMAPPROXY_H */
394 
395