policyd.h 8.95 KB
Newer Older
Nigel Kukard's avatar
Nigel Kukard committed
1
2
3
4
5
6
7
/*
 *
 *
 *                           Policy Daemon
 *
 *  policy daemon is used in conjuction with postfix to combat spam.
 *
8
 *  Copyright (C) 2007 Nigel Kukard <nkukard@lbsd.net>
Nigel Kukard's avatar
Nigel Kukard committed
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 *  Copyright (C) 2004 Cami Sardinha (cami@mweb.co.za)
 *
 *
 *  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
 *
 *
 *
 */

/* INCLUDES */
#include <ctype.h>
#include <strings.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <sys/signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <syslog.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <netdb.h>
#include <fcntl.h>
#include <stdio.h>
#include <mysql.h>
#include <setjmp.h>
/* Do not generate SIGPIPE */
#if defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__)
  #ifndef MSG_NOSIGNAL
    #define MSG_NOSIGNAL SO_NOSIGPIPE
  #endif
#endif

/* CONFIGS */
#define PROJECT         "policyd"
63
#define VERSION         "v1.81a"
Nigel Kukard's avatar
Nigel Kukard committed
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224

/* Miscellaneous constants */
#define LISTENQ         1023    /* 2nd argument to listen() */
#define MAXLINE         1023    /* max text line length */
#define BUFFSIZE        8191    /* buffer size for reads and writes */
#define BUFSIZE         4095 
#ifndef MAXFDS
  #define MAXFDS        1023    /* max file descriptors   */
#endif

#define POSTFIX_X_HEADER        "action=prepend X-Greylist: Passed"
#define POSTFIX_GOOD            "action=dunno\n\n"
#define POSTFIX_GREYLIST        "action=defer_if_permit Policy Rejection-"
#define POSTFIX_BAD_SIZE        "action=reject Policy Rejection-"
#define POSTFIX_SPAMTRAP        "action=reject Policy Rejection-"
#define POSTFIX_BLACKLIST_PERM  "action=reject Policy Rejection-"
#define POSTFIX_BLACKLIST_TEMP  "action=defer_if_permit Policy Rejection-"
#define POSTFIX_MODULE_FAILURE  "action=defer_if_permit Policy Rejection- Invalid data\n\n"
#define POSTFIX_QUOTA_EXCEEDED_PERM  "action=reject Policy Rejection-"
#define POSTFIX_QUOTA_EXCEEDED_TEMP  "action=defer_if_permit Policy Rejection-"


/* MySQL VARIABLES */
char *MYSQLHOST;
char *MYSQLUSER;
char *MYSQLPASS;
char *MYSQLDBASE;
char *MYSQLOPT;
 int MYSQLPORT;

 
/* GLOBAL OPTARGS */
 char *configpath;
 int DEBUG;
 int DAEMON;
 int FAILSAFE;
 int TRIPLET_TIME;
 int TRIPLET_AUTH_TIMEOUT;
 int TRIPLET_UNAUTH_TIMEOUT;
 int OPTINOUT;
 int OPTINOUTALL;
 int TRAINING_MODE;
 int TRAINING_POLICY_TIMEOUT;
 int AUTO_WHITE_LISTING;
 int AUTO_WHITELIST_NUMBER;
 int AUTO_BLACKLIST_NUMBER;
 int AUTO_WHITELIST_EXPIRE;
 int AUTO_BLACKLIST_EXPIRE;
 int AUTO_WHITELIST_NETBLOCK;
 int SPAMTRAP_AUTO_EXPIRE;
 int WHITELISTING;
 int WHITELISTNULL;
 int WHITELISTSENDER;
 int WHITELISTDNSNAME;
 int BLACKLIST_TEMP_REJECT;
 int BLACKLISTING;
 int BLACKLIST_TIMEOUT;
 int BLACKLIST_NETBLOCK;
 int BLACKLIST_HELO;
 int BLACKLIST_HELO_AUTO_EXPIRE;
 int BLACKLISTSENDER;
 int BLACKLISTDNSNAME;
 int AUTO_BLACK_LISTING;
 int GREYLISTING;
 int SPAMTRAPPING;
 int HELO_CHECK;
 int HELO_MAX_COUNT;
 int HELO_BLACKLIST_AUTO_EXPIRE;
 int HELO_AUTO_EXPIRE;
 int GREYLIST_X_HEADER;
 unsigned int GREYLIST_HOSTADDR;
 int BINDPORT;
 int QUOTA_EXCEEDED_TEMP_REJECT;
 int SENDERTHROTTLE;
 int SENDER_THROTTLE_SASL;
 int SENDER_THROTTLE_HOST;
 int SENDERMSGLIMIT;
 int SENDERRCPTLIMIT;
 int SENDERTIMELIMIT;
 int SENDERQUOTALIMIT;
 int SENDERMSGSIZE;
 int SENDER_INACTIVE_EXPIRE;
 int SENDER_THROTTLE_AUTOBLACKLIST;
 int SENDER_THROTTLE_AUTOBLACKLIST_NUMBER;
 int SENDER_THROTTLE_AUTOBLACKLIST_EXPIRE;

 int RECIPIENTTHROTTLE;
 int RECIPIENTMSGLIMIT;
 int RECIPIENTTIMELIMIT;
 int RECIPIENT_INACTIVE_EXPIRE;
 int SYSLOG_FACILITY;
 int DATABASE_KEEPALIVE;
 int count;
 uid_t UID;
 gid_t GID;
 char *BINDHOST;
 char *CONN_ACL;
 char *CHROOT;
 char *PIDFILE;
 char *postfix_greylist;
 char *postfix_bad_size;
 char *postfix_spamtrap;
 char *postfix_blacklist;
 char *postfix_sender_quota_exceeded;
 char *postfix_recipient_quota_exceeded;

 
/* GLOBAL VARIABLES/ARRAYS */
 MYSQL * volatile mysql;
unsigned long int rcpt_count;           /* total mails processed */
unsigned long int mysql_failure_count;  /* total mysql queries   */
unsigned long int last_mail_time;       /* seconds since epoch   */
unsigned long int last_mysql_failure;   /* seconds since epoch   */
unsigned long int mysql_timeout;        /* mysql query timeout   */
       sigjmp_buf sjmp;

  int msock;                            /* master server socket  */
  int ssock;                            /* slave server socket   */
  int         mysql_array[MAXFDS][10];
  int      mysql_optarray[MAXFDS][1];
  
  char    mysqlchar_array[MAXFDS][20][64];
  char         host_array[MAXFDS][20][64];
  char       policy_array[MAXFDS][20][64];
  char      triplet_array[MAXFDS][20][64];

  char   mysqlquery_array[MAXFDS][512];
  char    xgreylist_array[MAXFDS][128];
  char      extract_array[MAXFDS][64];
  char   extract_ip_array[MAXFDS][64];
  char  extract_host_addr[MAXFDS][64];
  char        return_code[MAXFDS][64];
  char extract_array_conf[MAXFDS][64];
  
  unsigned int i[MAXFDS], instance_inc[MAXFDS], t;
  unsigned int tcount[MAXFDS], tquota[MAXFDS], trcpt[MAXFDS];
  char      tattrib_array[MAXFDS][1];
  int x[MAXFDS], y[MAXFDS];
  struct timeval timevalue;     /* gettimeofday() */
  unsigned int timenow;
  FILE *fd_config, *pidfile;
  int  action_array[MAXFDS];
  char confbuf[256];
  char buf[MAXFDS][MAXLINE];
  unsigned int buf_size[MAXFDS];
  unsigned int buf_counter[MAXFDS];


/*  PROTOTYPES */

  // sockets
  int w_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
  int w_socket(int family, int type, int protocol);
  int w_accept(unsigned int fd, struct sockaddr *sa, socklen_t *salenptr);
   void buf_write(unsigned int fd, const char *ptr, size_t nbytes);
  int socktimeout(unsigned int fd, unsigned int sec);
  int daemonize(int nochdir, int noclose);
  int w_tcp_conn_acl (const char *host);
  int    cidr_ip_match (unsigned long ip, char *range);
  pid_t w_fork(void);
const char *w_inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
225
 ssize_t w_read(unsigned int fd, char *ptr, size_t max_size);
Nigel Kukard's avatar
Nigel Kukard committed
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
 ssize_t w_write(unsigned int fd, const void *vbuf);
 ssize_t f_write(unsigned int volatile fd, const void *vptr, size_t n);
 void w_close(unsigned int fd);
 void w_bind(unsigned int fd, const struct sockaddr *sa, socklen_t salen);
 void w_listen(unsigned int fd, unsigned int backlog);
 void sigalrm_handler (void);

  // functions
  void chk_pol(unsigned int fd);
  int bindsock(unsigned int port, unsigned int qlen);
  int greylist_check(unsigned int fd);
  int spamtrap_check(unsigned int fd);
  int throttle_check(unsigned int fd);
  int throttle_host(unsigned int fd);
  int throttle_from(unsigned int fd);
  int throttle_sasl(unsigned int fd);
  int throttle_rcpt(unsigned int fd);
  int helo_check(unsigned int fd);
  int module_info_check(unsigned int fd);
  int blacklist_helo_check(unsigned int fd);
  int gettime(void);
  int db_failure(unsigned int fd, char *module);
  int whitelist_check(unsigned int fd);
  int whitelist_sender_check(unsigned int fd);
  int whitelist_dnsname_check(unsigned int fd);
  int blacklist_sender_check(unsigned int fd);
  int blacklist_dnsname_check(unsigned int fd);
  void policy_reply(unsigned int fd, int code, int status);
  int blacklist_check(unsigned int fd);
  int extract_seconds(char *token);
  int parse_syslog_priority (char *str);
  int database_probe(unsigned int fd);
  int w_string_strip(void *str, char *token);
 void drop_privs(void);
 void read_conf(unsigned int prog);
 void logmessage(const char *fmt, ...);
 void usage(char *usag);
 void clear_var(unsigned int fd);
 void parse_buf(unsigned int fd, char *buf);
 void fold();
 void extract (unsigned int fd, char *token, unsigned int startlen);
 void extract_ip(unsigned int fd, char *token);
 void extract_ipfill(unsigned int fd, char *token);
 void extract_conf(unsigned int fd, char *token, unsigned int startlen);
 void syslog_token_set (char *token, int *value);
 char *strip_space (char *str);
  
 
  // mysql
 int db_doquery(unsigned int volatile fd);
 int db_optquery(unsigned int volatile fd);
 int db_charquery(unsigned int volatile fd);
 int db_printquery(unsigned int volatile fd);
 int db_deletequery(unsigned int volatile fd);
 int w_mysql_query(unsigned int volatile fd, const char *function);
MYSQL *db_connect(const char *dbname);



/* EOF */