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