1 /*
2  *
3  *
4  *                           Policy Daemon
5  *
6  *  policy daemon is used in conjuction with postfix to combat spam.
7  *
8  *  Copyright (C) 2007 Nigel Kukard <nkukard@lbsd.net>
9  *  Copyright (C) 2004 Cami Sardinha (cami@mweb.co.za)
10  *
11  *
12  *  This program is free software; you can redistribute it and/or modify it
13  *  under the terms of the  GNU General  Public License as published by the
14  *  Free Software Foundation;  either version 2 of the License, or (at your
15  *  option) any later version.
16  *
17  *  This program  is  distributed  in the hope that  it will be useful, but
18  *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19  *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20  *  for more details.
21  *
22  *  You should have received a copy of the GNU General Public License along
23  *  with this program; if not, write to the Free Software Foundation Inc.,
24  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  *
26  *
27  *
28  */
29 
30 /* INCLUDES */
31 #include <ctype.h>
32 #include <strings.h>
33 #include <sys/types.h>
34 #include <unistd.h>
35 #include <sys/time.h>
36 #include <sys/resource.h>
37 #include <netinet/in.h>
38 #include <sys/signal.h>
39 #include <sys/socket.h>
40 #include <arpa/inet.h>
41 #include <sys/wait.h>
42 #include <sys/stat.h>
43 #include <syslog.h>
44 #include <signal.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <stdarg.h>
48 #include <errno.h>
49 #include <netdb.h>
50 #include <fcntl.h>
51 #include <stdio.h>
52 #include <mysql.h>
53 #include <setjmp.h>
54 
55 /* SIGPIPE quirks */
56 #ifndef MSG_NOSIGNAL
57   /* Operating systems which have SO_NOSIGPIPE but not MSG_NOSIGNAL */
58   #if defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__APPLE__)
59     #define MSG_NOSIGNAL SO_NOSIGPIPE
60   /* Some versions of NetBSD dont have SO_NOSIGPIPE, check if we can use it or define as 0 */
61   #elif defined(__NetBSD__)
62     #ifdef SO_NOSIGPIPE
63       #define MSG_NOSIGNAL SO_NOSIGPIPE
64     #else
65       #define MSG_NOSIGNAL 0
66     #endif
67   #else
68     #error Your OS doesnt support MSG_NOSIGNAL or SO_NOSIGPIPE, please report to policyd-devel@lists.sf.net
69   #endif
70 #endif
71 
72 /* CONFIGS */
73 #define PROJECT         "policyd"
74 #define VERSION         "v1.82"
75 
76 /* Miscellaneous constants */
77 #define LISTENQ         1023    /* 2nd argument to listen() */
78 #define MAXLINE         1023    /* max text line length */
79 #define BUFFSIZE        8191    /* buffer size for reads and writes */
80 #define BUFSIZE         4095
81 #ifndef MAXFDS
82   #define MAXFDS        1023    /* max file descriptors   */
83 #endif
84 
85 #define POSTFIX_X_HEADER        "action=prepend X-Greylist: Passed"
86 #define POSTFIX_GOOD            "action=dunno\n\n"
87 #define POSTFIX_GREYLIST        "action=defer_if_permit Policy Rejection-"
88 #define POSTFIX_BAD_SIZE        "action=reject Policy Rejection-"
89 #define POSTFIX_SPAMTRAP        "action=reject Policy Rejection-"
90 #define POSTFIX_BLACKLIST_PERM  "action=reject Policy Rejection-"
91 #define POSTFIX_BLACKLIST_TEMP  "action=defer_if_permit Policy Rejection-"
92 #define POSTFIX_MODULE_FAILURE  "action=defer_if_permit Policy Rejection- Invalid data\n\n"
93 #define POSTFIX_QUOTA_EXCEEDED_PERM  "action=reject Policy Rejection-"
94 #define POSTFIX_QUOTA_EXCEEDED_TEMP  "action=defer_if_permit Policy Rejection-"
95 
96 
97 /* MySQL VARIABLES */
98 char *MYSQLHOST;
99 char *MYSQLUSER;
100 char *MYSQLPASS;
101 char *MYSQLDBASE;
102 char *MYSQLOPT;
103  int MYSQLPORT;
104 
105 
106 /* GLOBAL OPTARGS */
107  char *configpath;
108  int DEBUG;
109  int DAEMON;
110  int FAILSAFE;
111  int TRIPLET_TIME;
112  int TRIPLET_AUTH_TIMEOUT;
113  int TRIPLET_UNAUTH_TIMEOUT;
114  int OPTINOUT;
115  int OPTINOUTALL;
116  int TRAINING_MODE;
117  int TRAINING_POLICY_TIMEOUT;
118  int AUTO_WHITE_LISTING;
119  int AUTO_WHITELIST_NUMBER;
120  int AUTO_BLACKLIST_NUMBER;
121  int AUTO_WHITELIST_EXPIRE;
122  int AUTO_BLACKLIST_EXPIRE;
123  int AUTO_WHITELIST_NETBLOCK;
124  int SPAMTRAP_AUTO_EXPIRE;
125  int WHITELISTING;
126  int WHITELISTNULL;
127  int WHITELISTSENDER;
128  int WHITELISTDNSNAME;
129  int BLACKLIST_TEMP_REJECT;
130  int BLACKLISTING;
131  int BLACKLIST_TIMEOUT;
132  int BLACKLIST_NETBLOCK;
133  int BLACKLIST_HELO;
134  int BLACKLIST_HELO_AUTO_EXPIRE;
135  int BLACKLISTSENDER;
136  int BLACKLISTDNSNAME;
137  int AUTO_BLACK_LISTING;
138  int GREYLISTING;
139  int SPAMTRAPPING;
140  int HELO_CHECK;
141  int HELO_MAX_COUNT;
142  int HELO_BLACKLIST_AUTO_EXPIRE;
143  int HELO_AUTO_EXPIRE;
144  int GREYLIST_X_HEADER;
145  unsigned int GREYLIST_HOSTADDR;
146  int BINDPORT;
147  int QUOTA_EXCEEDED_TEMP_REJECT;
148  int SENDERTHROTTLE;
149  int SENDER_THROTTLE_SASL;
150  int SENDER_THROTTLE_HOST;
151  int SENDERMSGLIMIT;
152  int SENDERRCPTLIMIT;
153  int SENDERTIMELIMIT;
154  int SENDERQUOTALIMIT;
155  int SENDERMSGSIZE;
156  int SENDER_INACTIVE_EXPIRE;
157  int SENDER_THROTTLE_AUTOBLACKLIST;
158  int SENDER_THROTTLE_AUTOBLACKLIST_NUMBER;
159  int SENDER_THROTTLE_AUTOBLACKLIST_EXPIRE;
160 
161  int RECIPIENTTHROTTLE;
162  int RECIPIENTMSGLIMIT;
163  int RECIPIENTTIMELIMIT;
164  int RECIPIENT_INACTIVE_EXPIRE;
165  int SYSLOG_FACILITY;
166  int DATABASE_KEEPALIVE;
167  int count;
168  uid_t UID;
169  gid_t GID;
170  char *BINDHOST;
171  char *CONN_ACL;
172  char *CHROOT;
173  char *PIDFILE;
174  char *postfix_greylist;
175  char *postfix_bad_size;
176  char *postfix_spamtrap;
177  char *postfix_blacklist;
178  char *postfix_sender_quota_exceeded;
179  char *postfix_recipient_quota_exceeded;
180 
181 
182 /* GLOBAL VARIABLES/ARRAYS */
183  MYSQL * volatile mysql;
184 unsigned long int rcpt_count;           /* total mails processed */
185 unsigned long int mysql_failure_count;  /* total mysql queries   */
186 unsigned long int last_mail_time;       /* seconds since epoch   */
187 unsigned long int last_mysql_failure;   /* seconds since epoch   */
188 unsigned long int mysql_timeout;        /* mysql query timeout   */
189        sigjmp_buf sjmp;
190 
191   int msock;                            /* master server socket  */
192   int ssock;                            /* slave server socket   */
193   int         mysql_array[MAXFDS][10];
194   int      mysql_optarray[MAXFDS][1];
195 
196   char    mysqlchar_array[MAXFDS][20][64];
197   char         host_array[MAXFDS][20][64];
198   char       policy_array[MAXFDS][20][64];
199   char      triplet_array[MAXFDS][20][64];
200 
201   char   mysqlquery_array[MAXFDS][512];
202   char    xgreylist_array[MAXFDS][128];
203   char      extract_array[MAXFDS][64];
204   char   extract_ip_array[MAXFDS][64];
205   char  extract_host_addr[MAXFDS][64];
206   char        return_code[MAXFDS][64];
207   char extract_array_conf[MAXFDS][64];
208 
209   unsigned int i[MAXFDS], instance_inc[MAXFDS], t;
210   unsigned int tcount[MAXFDS], tquota[MAXFDS], trcpt[MAXFDS];
211   char      tattrib_array[MAXFDS][1];
212   int x[MAXFDS], y[MAXFDS];
213   struct timeval timevalue;     /* gettimeofday() */
214   unsigned int timenow;
215   FILE *fd_config, *pidfile;
216   int  action_array[MAXFDS];
217   char confbuf[256];
218   char buf[MAXFDS][MAXLINE];
219   unsigned int buf_size[MAXFDS];
220   unsigned int buf_counter[MAXFDS];
221 
222 
223 /*  PROTOTYPES */
224 
225   // sockets
226   int w_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
227   int w_socket(int family, int type, int protocol);
228   int w_accept(unsigned int fd, struct sockaddr *sa, socklen_t *salenptr);
229    void buf_write(unsigned int fd, const char *ptr, size_t nbytes);
230   int socktimeout(unsigned int fd, unsigned int sec);
231   int daemonize(int nochdir, int noclose);
232   int w_tcp_conn_acl (const char *host);
233   int    cidr_ip_match (unsigned long ip, char *range);
234   pid_t w_fork(void);
235 const char *w_inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
236  ssize_t w_read(unsigned int fd, char *ptr, size_t max_size);
237  ssize_t w_write(unsigned int fd, const void *vbuf);
238  ssize_t f_write(unsigned int volatile fd, const void *vptr, size_t n);
239  void w_close(unsigned int fd);
240  void w_bind(unsigned int fd, const struct sockaddr *sa, socklen_t salen);
241  void w_listen(unsigned int fd, unsigned int backlog);
242  void sigalrm_handler (void);
243 
244   // functions
245   void chk_pol(unsigned int fd);
246   int bindsock(unsigned int port, unsigned int qlen);
247   int greylist_check(unsigned int fd);
248   int spamtrap_check(unsigned int fd);
249   int throttle_check(unsigned int fd);
250   int throttle_host(unsigned int fd);
251   int throttle_from(unsigned int fd);
252   int throttle_sasl(unsigned int fd);
253   int throttle_rcpt(unsigned int fd);
254   int helo_check(unsigned int fd);
255   int module_info_check(unsigned int fd);
256   int blacklist_helo_check(unsigned int fd);
257   int gettime(void);
258   int db_failure(unsigned int fd, char *module);
259   int whitelist_check(unsigned int fd);
260   int whitelist_sender_check(unsigned int fd);
261   int whitelist_dnsname_check(unsigned int fd);
262   int blacklist_sender_check(unsigned int fd);
263   int blacklist_dnsname_check(unsigned int fd);
264   void policy_reply(unsigned int fd, int code, int status);
265   int blacklist_check(unsigned int fd);
266   int extract_seconds(char *token);
267   int parse_syslog_priority (char *str);
268   int database_probe(unsigned int fd);
269   int w_string_strip(void *str, char *token);
270  void drop_privs(void);
271  void read_conf(unsigned int prog);
272  void logmessage(const char *fmt, ...);
273  void usage(char *usag);
274  void clear_var(unsigned int fd);
275  void parse_buf(unsigned int fd, char *buf);
276  void fold();
277  void extract (unsigned int fd, char *token, unsigned int startlen);
278  void extract_ip(unsigned int fd, char *token);
279  void extract_ipfill(unsigned int fd, char *token);
280  void extract_conf(unsigned int fd, char *token, unsigned int startlen);
281  void syslog_token_set (char *token, int *value);
282  char *strip_space (char *str);
283 
284 
285   // mysql
286  int db_doquery(unsigned int volatile fd);
287  int db_optquery(unsigned int volatile fd);
288  int db_charquery(unsigned int volatile fd);
289  int db_printquery(unsigned int volatile fd);
290  int db_deletequery(unsigned int volatile fd);
291  int w_mysql_query(unsigned int volatile fd, const char *function);
292 MYSQL *db_connect(const char *dbname);
293 
294 
295 
296 /* EOF */
297