1 #include "policyd.h"
2 
3 /*
4  *
5  *
6  *                           Policy Daemon
7  *
8  *  policy daemon is used in conjuction with postfix to combat spam.
9  *
10  *  Copyright (C) 2004 Cami Sardinha (cami@mweb.co.za)
11  *
12  *
13  *  This program is free software; you can redistribute it and/or modify it
14  *  under the terms of the  GNU General  Public License as published by the
15  *  Free Software Foundation;  either version 2 of the License, or (at your
16  *  option) any later version.
17  *
18  *  This program  is  distributed  in the hope that  it will be useful, but
19  *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20  *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  *  for more details.
22  *
23  *  You should have received a copy of the GNU General Public License along
24  *  with this program; if not, write to the Free Software Foundation Inc.,
25  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  *
27  *
28  *
29  */
30 
31 /*
32  * function: read_conf
33  *  purpose: read config options from file and store memory
34  */
35 void
read_conf(unsigned int prog)36 read_conf(unsigned int prog)
37 {
38 
39   memset(confbuf, 0x00, 256);
40 
41   /* file should exist */
42   if((fd_config=freopen(configpath, "r", stdin)) == NULL)
43   {
44     fprintf(stderr, "fopen(): %s: %s\n", strerror(errno), configpath);
45     exit(-1);
46   }
47 
48   /* cycle through file, grab config options */
49   while(fgets(confbuf, 256, fd_config) != NULL)
50   {
51     memset(extract_array[0], 0x00, 256);
52 
53     /* SYSLOG FACILITY */
54     if(strncmp(confbuf, "SYSLOG_FACILITY=", 16) == 0)
55     {
56       extract(0, confbuf, 15);
57       SYSLOG_FACILITY=parse_syslog_priority(extract_array[0]);
58     }
59 
60     /* DAEMON MODE */
61     if(strncmp(confbuf, "DAEMON=", 7) == 0)
62     {
63       extract(0, confbuf, 6);
64       DAEMON=atol(extract_array[0]);
65     }
66 
67     /* CHROOT */
68     if(strncmp(confbuf, "CHROOT=", 7) == 0)
69     {
70       extract(0, confbuf, 6);
71       if((CHROOT=malloc(strlen(extract_array[0])+1)) != NULL)
72         strcpy(CHROOT, extract_array[0]);
73       else {
74         logmessage("malloc(): %s\n", strerror(errno));
75         exit(-1);
76       }
77     }
78 
79     /* UID */
80     if(strncmp(confbuf, "UID=", 4) == 0)
81     {
82       extract(0, confbuf, 3);
83       UID=atol(extract_array[0]);
84     }
85 
86     /* GID */
87     if(strncmp(confbuf, "GID=", 4) == 0)
88     {
89       extract(0, confbuf, 3);
90       GID=atol(extract_array[0]);
91     }
92 
93     /* DEBUG MODE */
94     if(strncmp(confbuf, "DEBUG=", 6) == 0)
95     {
96       extract(0, confbuf, 5);
97       DEBUG=atol(extract_array[0]);
98     }
99 
100     /* PORT TO BIND TO */
101     if(strncmp(confbuf, "BINDPORT=", 9) == 0)
102     {
103       extract(0, confbuf, 8);
104       BINDPORT=atol(extract_array[0]);
105     }
106 
107     /* HOST TO BIND TO */
108     if(strncmp(confbuf, "BINDHOST=", 9) == 0)
109     {
110       extract(0, confbuf, 8);
111       if((BINDHOST=malloc(strlen(extract_array[0])+1)) != NULL)
112         strcpy(BINDHOST,extract_array[0]);
113       else {
114         logmessage("malloc(): %s\n", strerror(errno));
115         exit(-1);
116       }
117     }
118 
119     /* CONNECTION ACL */
120     if(strncmp(confbuf, "CONN_ACL=", 9) == 0)
121     {
122       extract(0, confbuf, 8);
123       if((CONN_ACL=malloc(strlen(extract_array[0])+1)) != NULL)
124         strcpy(CONN_ACL,extract_array[0]);
125       else {
126         logmessage("malloc(): %s\n", strerror(errno));
127         exit(-1);
128       }
129     }
130 
131     /* PID TO WRITE TO */
132     if(strncmp(confbuf, "PIDFILE=", 8) == 0)
133     {
134       extract(0, confbuf, 7);
135       if((PIDFILE=malloc(strlen(extract_array[0])+1)) != NULL)
136         strcpy(PIDFILE,extract_array[0]);
137       else {
138         logmessage("malloc(): %s\n", strerror(errno));
139         exit(-1);
140       }
141     }
142 
143     /* GREYLISTING */
144     if(strncmp(confbuf, "GREYLISTING=", 12) == 0)
145     {
146       extract(0, confbuf, 11);
147       GREYLISTING=atol(extract_array[0]);
148     }
149 
150     /* GREYLIST_HOSTADDR */
151     if(strncmp(confbuf, "GREYLIST_HOSTADDR=", 18) == 0)
152     {
153       extract(0, confbuf, 17);
154       GREYLIST_HOSTADDR=atol(extract_array[0]);
155     }
156 
157     /* TRAINING_MODE */
158     if(strncmp(confbuf, "TRAINING_MODE=", 14) == 0)
159     {
160       extract(0, confbuf, 13);
161       TRAINING_MODE=atol(extract_array[0]);
162     }
163 
164     /* TRAINING_POLICY_TIMEOUT */
165     if(strncmp(confbuf, "TRAINING_POLICY_TIMEOUT=", 24) == 0)
166     {
167       extract(0, confbuf, 23);
168       TRAINING_POLICY_TIMEOUT=extract_seconds(extract_array[0]);
169     }
170 
171     /* GREYLIST_X_HEADER */
172     if(strncmp(confbuf, "GREYLIST_X_HEADER=", 18) == 0)
173     {
174       extract(0, confbuf, 17);
175       GREYLIST_X_HEADER=atol(extract_array[0]);
176     }
177 
178     /* WHITELISTING */
179     if(strncmp(confbuf, "WHITELISTING=", 13) == 0)
180     {
181       extract(0, confbuf, 12);
182       WHITELISTING=atol(extract_array[0]);
183     }
184 
185     /* AUTO_WHITELIST_EXPIRE */
186     if(strncmp(confbuf, "AUTO_WHITELIST_EXPIRE=", 22) == 0)
187     {
188       extract(0, confbuf, 21);
189       AUTO_WHITELIST_EXPIRE=extract_seconds(extract_array[0]);
190     }
191 
192     /* AUTO_BLACKLIST_EXPIRE */
193     if(strncmp(confbuf, "AUTO_BLACKLIST_EXPIRE=", 22) == 0)
194     {
195       extract(0, confbuf, 21);
196       AUTO_BLACKLIST_EXPIRE=extract_seconds(extract_array[0]);
197     }
198 
199     /* AUTO_WHITELIST_NETBLOCK */
200     if(strncmp(confbuf, "AUTO_WHITELIST_NETBLOCK=", 24) == 0)
201     {
202       extract(0, confbuf, 23);
203       AUTO_WHITELIST_NETBLOCK=atol(extract_array[0]);
204     }
205 
206     /* AUTO_WHITELIST_NUMBER */
207     if(strncmp(confbuf, "AUTO_WHITELIST_NUMBER=", 22) == 0)
208     {
209       extract(0, confbuf, 21);
210       AUTO_WHITELIST_NUMBER=atol(extract_array[0]);
211     }
212 
213     /* AUTO_BLACKLIST_NUMBER */
214     if(strncmp(confbuf, "AUTO_BLACKLIST_NUMBER=", 22) == 0)
215     {
216       extract(0, confbuf, 21);
217       AUTO_BLACKLIST_NUMBER=atol(extract_array[0]);
218     }
219 
220     /* AUTO_WHITE_LISTING */
221     if(strncmp(confbuf, "AUTO_WHITE_LISTING=", 19) == 0)
222     {
223       extract(0, confbuf, 18);
224       AUTO_WHITE_LISTING=atol(extract_array[0]);
225     }
226 
227     /* SPAMTRAP_AUTO_EXPIRE */
228     if(strncmp(confbuf, "SPAMTRAP_AUTO_EXPIRE=", 21) == 0)
229     {
230       extract(0, confbuf, 20);
231       SPAMTRAP_AUTO_EXPIRE=extract_seconds(extract_array[0]);
232     }
233 
234     /* HELO CHECK */
235     if(strncmp(confbuf, "HELO_CHECK=", 11) == 0)
236     {
237       extract(0, confbuf, 10);
238       HELO_CHECK=atol(extract_array[0]);
239     }
240 
241     /* HELO_MAX_COUNT */
242     if(strncmp(confbuf, "HELO_MAX_COUNT=", 15) == 0)
243     {
244       extract(0, confbuf, 14);
245       HELO_MAX_COUNT=atol(extract_array[0]);
246     }
247 
248     /* HELO_BLACKLIST_AUTO_EXPIRE */
249     if(strncmp(confbuf, "HELO_BLACKLIST_AUTO_EXPIRE=", 27) == 0)
250     {
251       extract(0, confbuf, 26);
252       HELO_BLACKLIST_AUTO_EXPIRE=extract_seconds(extract_array[0]);
253     }
254 
255     /* HELO_AUTO_EXPIRE */
256     if(strncmp(confbuf, "HELO_AUTO_EXPIRE=", 17) == 0)
257     {
258       extract(0, confbuf, 16);
259       HELO_AUTO_EXPIRE=extract_seconds(extract_array[0]);
260     }
261 
262     /* BLACKLISTING */
263     if(strncmp(confbuf, "BLACKLISTING=", 13) == 0)
264     {
265       extract(0, confbuf, 12);
266       BLACKLISTING=atol(extract_array[0]);
267     }
268 
269     /* AUTO_BLACK_LISTING */
270     if(strncmp(confbuf, "AUTO_BLACK_LISTING=", 19) == 0)
271     {
272       extract(0, confbuf, 18);
273       AUTO_BLACK_LISTING=atol(extract_array[0]);
274     }
275 
276     /* BLACKLIST_HELO */
277     if(strncmp(confbuf, "BLACKLIST_HELO=", 15) == 0)
278     {
279       extract(0, confbuf, 14);
280       BLACKLIST_HELO=atol(extract_array[0]);
281     }
282 
283     /* BLACKLIST_HELO_AUTO_EXPIRE */
284     if(strncmp(confbuf, "BLACKLIST_HELO_AUTO_EXPIRE=", 27) == 0)
285     {
286       extract(0, confbuf, 26);
287       BLACKLIST_HELO_AUTO_EXPIRE=extract_seconds(extract_array[0]);
288     }
289 
290     /* SPAMTRAPPING */
291     if(strncmp(confbuf, "SPAMTRAPPING=", 13) == 0)
292     {
293       extract(0, confbuf, 12);
294       SPAMTRAPPING=atol(extract_array[0]);
295     }
296 
297     /* BLACKLIST_TEMP_REJECT */
298     if(strncmp(confbuf, "BLACKLIST_TEMP_REJECT=", 22) == 0)
299     {
300       extract(0, confbuf, 21);
301       BLACKLIST_TEMP_REJECT=atol(extract_array[0]);
302     }
303 
304     /* BLACKLIST_TIMEOUT */
305     if(strncmp(confbuf, "BLACKLIST_TIMEOUT=", 18) == 0)
306     {
307       extract(0, confbuf, 17);
308       BLACKLIST_TIMEOUT=extract_seconds(extract_array[0]);
309     }
310 
311     /* BLACKLIST_NETBLOCK */
312     if(strncmp(confbuf, "BLACKLIST_NETBLOCK=", 19) == 0)
313     {
314       extract(0, confbuf, 18);
315       BLACKLIST_NETBLOCK=atol(extract_array[0]);
316     }
317 
318     /* BLACKLIST SENDER */
319     if(strncmp(confbuf, "BLACKLISTSENDER=", 16) == 0)
320     {
321       extract(0, confbuf, 15);
322       BLACKLISTSENDER=atol(extract_array[0]);
323     }
324 
325     /* BLACKLIST DNS NAME */
326     if(strncmp(confbuf, "BLACKLISTDNSNAME=", 17) == 0)
327     {
328       extract(0, confbuf, 16);
329       BLACKLISTDNSNAME=atol(extract_array[0]);
330     }
331 
332     /* WHITELIST NULL SENDER */
333     if(strncmp(confbuf, "WHITELISTNULL=", 14) == 0)
334     {
335       extract(0, confbuf, 13);
336       WHITELISTNULL=atol(extract_array[0]);
337     }
338 
339     /* WHITELIST SENDER */
340     if(strncmp(confbuf, "WHITELISTSENDER=", 16) == 0)
341     {
342       extract(0, confbuf, 15);
343       WHITELISTSENDER=atol(extract_array[0]);
344     }
345 
346     /* WHITELIST DNS NAME */
347     if(strncmp(confbuf, "WHITELISTDNSNAME=", 17) == 0)
348     {
349       extract(0, confbuf, 16);
350       WHITELISTDNSNAME=atol(extract_array[0]);
351     }
352 
353     /* SENDERTHROTTLE */
354     if(strncmp(confbuf, "SENDERTHROTTLE=", 15) == 0)
355     {
356       extract(0, confbuf, 14);
357       SENDERTHROTTLE=atol(extract_array[0]);
358     }
359 
360     /* SENDER_THROTTLE_SASL */
361     if(strncmp(confbuf, "SENDER_THROTTLE_SASL=", 21) == 0)
362     {
363       extract(0, confbuf, 20);
364       SENDER_THROTTLE_SASL=atol(extract_array[0]);
365     }
366 
367     /* SENDER_THROTTLE_HOST */
368     if(strncmp(confbuf, "SENDER_THROTTLE_HOST=", 21) == 0)
369     {
370       extract(0, confbuf, 20);
371       SENDER_THROTTLE_HOST=atol(extract_array[0]);
372     }
373 
374     /* MAXIMUM SENDER MESSAGE LIMIT */
375     if(strncmp(confbuf, "SENDERMSGLIMIT=", 15) == 0)
376     {
377       extract(0, confbuf, 14);
378       SENDERMSGLIMIT=atol(extract_array[0]);
379     }
380 
381     /* MAXIMUM SENDER RCPT LIMIT */
382     if(strncmp(confbuf, "SENDERRCPTLIMIT=", 16) == 0)
383     {
384       extract(0, confbuf, 15);
385       SENDERRCPTLIMIT=atol(extract_array[0]);
386     }
387 
388     /* MAX SENDER VOLUME/QUOTA SENDER TIME LIMIT */
389     if(strncmp(confbuf, "SENDERQUOTALIMIT=", 17) == 0)
390     {
391       extract(0, confbuf, 16);
392       SENDERQUOTALIMIT=atol(extract_array[0]);
393     }
394 
395     /* MAX MAIL SIZE PER SENDER */
396     if(strncmp(confbuf, "SENDERMSGSIZE=", 14) == 0)
397     {
398       extract(0, confbuf, 13);
399       SENDERMSGSIZE=atol(extract_array[0]);
400     }
401 
402     /* MAX SENDER TIME LIMIT */
403     if(strncmp(confbuf, "SENDERTIMELIMIT=", 16) == 0)
404     {
405       extract(0, confbuf, 15);
406       SENDERTIMELIMIT=extract_seconds(extract_array[0]);
407     }
408 
409     /* INACTIVE SENDER EXPIRATION TIME LIMIT */
410     if(strncmp(confbuf, "SENDER_INACTIVE_EXPIRE=", 23) == 0)
411     {
412       extract(0, confbuf, 22);
413       SENDER_INACTIVE_EXPIRE=extract_seconds(extract_array[0]);
414     }
415 
416     /* SENDER_THROTTLE_AUTOBLACKLIST */
417     if(strncmp(confbuf, "SENDER_THROTTLE_AUTOBLACKLIST=", 30) == 0)
418     {
419       extract(0, confbuf, 29);
420       SENDER_THROTTLE_AUTOBLACKLIST=atol(extract_array[0]);
421     }
422 
423     /* SENDER_THROTTLE_AUTOBLACKLIST_NUMBER */
424     if(strncmp(confbuf, "SENDER_THROTTLE_AUTOBLACKLIST_NUMBER=", 37) == 0)
425     {
426       extract(0, confbuf, 36);
427       SENDER_THROTTLE_AUTOBLACKLIST_NUMBER=atol(extract_array[0]);
428     }
429 
430     /* SENDER_THROTTLE_AUTOBLACKLIST_EXPIRE */
431     if(strncmp(confbuf, "SENDER_THROTTLE_AUTOBLACKLIST_EXPIRE=", 37) == 0)
432     {
433       extract(0, confbuf, 36);
434       SENDER_THROTTLE_AUTOBLACKLIST_EXPIRE=extract_seconds(extract_array[0]);
435     }
436 
437 
438     /* RECIPIENTTHROTTLE */
439     if(strncmp(confbuf, "RECIPIENTTHROTTLE=", 18) == 0)
440     {
441       extract(0, confbuf, 17);
442       RECIPIENTTHROTTLE=atol(extract_array[0]);
443     }
444 
445     /* MAX RECIPIENT MESSAGES LIMIT */
446     if(strncmp(confbuf, "RECIPIENTMSGLIMIT=", 18) == 0)
447     {
448       extract(0, confbuf, 17);
449       RECIPIENTMSGLIMIT=atol(extract_array[0]);
450     }
451 
452     /* MAX RECIPIENT TIME LIMIT */
453     if(strncmp(confbuf, "RECIPIENTTIMELIMIT=", 19) == 0)
454     {
455       extract(0, confbuf, 18);
456       RECIPIENTTIMELIMIT=extract_seconds(extract_array[0]);
457     }
458 
459     /* INACTIVE RECIPIENT EXPIRATION TIME LIMIT */
460     if(strncmp(confbuf, "RECIPIENT_INACTIVE_EXPIRE=", 26) == 0)
461     {
462       extract(0, confbuf, 25);
463       RECIPIENT_INACTIVE_EXPIRE=extract_seconds(extract_array[0]);
464     }
465 
466     /* TRIPLET TIMEOUT */
467     if(strncmp(confbuf, "TRIPLET_TIME=", 13) == 0)
468     {
469       extract(0, confbuf, 12);
470       TRIPLET_TIME=extract_seconds(extract_array[0]);
471     }
472 
473     /* TRIPLET_AUTH_TIMEOUT */
474     if(strncmp(confbuf, "TRIPLET_AUTH_TIMEOUT=", 21) == 0)
475     {
476       extract(0, confbuf, 20);
477       TRIPLET_AUTH_TIMEOUT=extract_seconds(extract_array[0]);
478     }
479 
480     /* TRIPLET_UNAUTH_TIMEOUT */
481     if(strncmp(confbuf, "TRIPLET_UNAUTH_TIMEOUT=", 23) == 0)
482     {
483       extract(0, confbuf, 22);
484       TRIPLET_UNAUTH_TIMEOUT=extract_seconds(extract_array[0]);
485     }
486 
487     /* OPT-IN / OPT-OUT */
488     if(strncmp(confbuf, "OPTINOUT=", 9) == 0)
489     {
490       extract(0, confbuf, 8);
491       OPTINOUT=atol(extract_array[0]);
492     }
493 
494     /* OPT-IN / OPT-OUT */
495     if(strncmp(confbuf, "OPTINOUTALL=", 12) == 0)
496     {
497       extract(0, confbuf, 11);
498       OPTINOUTALL=atol(extract_array[0]);
499     }
500 
501     /* FAILOVER MODE */
502     if(strncmp(confbuf, "FAILSAFE=", 9) == 0)
503     {
504       extract(0, confbuf, 8);
505       FAILSAFE=atol(extract_array[0]);
506     }
507 
508     /* DATABASE_KEEPALIVE */
509     if(strncmp(confbuf, "DATABASE_KEEPALIVE=", 19) == 0)
510     {
511       extract(0, confbuf, 18);
512       DATABASE_KEEPALIVE=atol(extract_array[0]);
513     }
514 
515     /* MYSQL HOST */
516     if(strncmp(confbuf, "MYSQLHOST=", 10) == 0)
517     {
518       extract_conf(0, confbuf, 9);
519       if((MYSQLHOST=malloc(strlen(extract_array_conf[0])+1)) != NULL)
520         strcpy(MYSQLHOST, extract_array_conf[0]);
521       else {
522         logmessage("malloc(): %s\n", strerror(errno));
523         exit(-1);
524       }
525     }
526 
527     /* MYSQL DATABASE */
528     if(strncmp(confbuf, "MYSQLDBASE=", 11) == 0)
529     {
530       extract_conf(0, confbuf, 10);
531       if((MYSQLDBASE=malloc(strlen(extract_array_conf[0])+1)) != NULL)
532         strcpy(MYSQLDBASE, extract_array_conf[0]);
533       else {
534         logmessage("malloc(): %s\n", strerror(errno));
535         exit(-1);
536       }
537     }
538 
539     /* MYSQL USER */
540     if(strncmp(confbuf, "MYSQLUSER=", 10) == 0)
541     {
542       extract_conf(0, confbuf, 9);
543       if((MYSQLUSER=malloc(strlen(extract_array_conf[0])+1)) != NULL)
544         strcpy(MYSQLUSER, extract_array_conf[0]);
545       else {
546         logmessage("malloc(): %s\n", strerror(errno));
547         exit(-1);
548       }
549     }
550 
551     /* MYSQL PASS */
552     if(strncmp(confbuf, "MYSQLPASS=", 10) == 0)
553     {
554       extract_conf(0, confbuf, 9);
555       if((MYSQLPASS=malloc(strlen(extract_array_conf[0])+1)) != NULL)
556         strcpy(MYSQLPASS, extract_array_conf[0]);
557       else {
558         logmessage("malloc(): %s\n", strerror(errno));
559         exit(-1);
560       }
561     }
562 
563     /* MYSQL OPTIONS */
564     if(strncmp(confbuf, "MYSQLOPT=", 9) == 0)
565     {
566       extract_conf(0, confbuf, 8);
567       if((MYSQLOPT=malloc(strlen(extract_array_conf[0])+1)) != NULL)
568         strcpy(MYSQLOPT, extract_array_conf[0]);
569       else {
570         logmessage("malloc(): %s\n", strerror(errno));
571         exit(-1);
572       }
573     }
574 
575     /* MYSQL PORT */
576     if(strncmp(confbuf, "MYSQLPORT=", 10) == 0)
577     {
578       extract(0, confbuf, 9);
579       MYSQLPORT=atol(extract_array[0]);
580     }
581 
582     /* GREYLIST_REJECTION */
583     if(strncmp(confbuf, "GREYLIST_REJECTION=", 19) == 0)
584     {
585       extract_conf(0, confbuf, 18);
586       if((postfix_greylist=malloc(512)) != NULL)
587         snprintf(postfix_greylist, 512, "%s %s\n\n", POSTFIX_GREYLIST, extract_array_conf[0]);
588       else {
589         logmessage("malloc(): %s\n", strerror(errno));
590         exit(-1);
591       }
592     }
593 
594     /* BLACKLIST_REJECTION */
595     if(strncmp(confbuf, "BLACKLIST_REJECTION=", 20) == 0)
596     {
597       extract_conf(0, confbuf, 19);
598       if((postfix_blacklist=malloc(512)) != NULL)
599       {
600         if(BLACKLIST_TEMP_REJECT==1)
601           snprintf(postfix_blacklist, 512, "%s %s\n\n", POSTFIX_BLACKLIST_TEMP, extract_array_conf[0]);
602         else
603           snprintf(postfix_blacklist, 512, "%s %s\n\n", POSTFIX_BLACKLIST_PERM, extract_array_conf[0]);
604       }
605       else {
606         logmessage("malloc(): %s\n", strerror(errno));
607         exit(-1);
608       }
609     }
610 
611     /* THROTTLE BAD SIZE */
612     if(strncmp(confbuf, "SENDER_SIZE_REJECTION=", 22) == 0)
613     {
614       extract_conf(0, confbuf, 21);
615       if((postfix_bad_size=malloc(512)) != NULL)
616         snprintf(postfix_bad_size, 512, "%s %s\n\n", POSTFIX_BAD_SIZE, extract_array_conf[0]);
617       else {
618         logmessage("malloc(): %s\n", strerror(errno));
619         exit(-1);
620       }
621     }
622 
623     /* SPAMTRAP */
624     if(strncmp(confbuf, "SPAMTRAP_REJECTION=", 19) == 0)
625     {
626       extract_conf(0, confbuf, 18);
627       if((postfix_spamtrap=malloc(512)) != NULL)
628         snprintf(postfix_spamtrap, 512, "%s %s\n\n", POSTFIX_SPAMTRAP, extract_array_conf[0]);
629       else {
630         logmessage("malloc(): %s\n", strerror(errno));
631         exit(-1);
632       }
633     }
634 
635     /* MAX SENDER QUOTA EXCEEDED */
636     if(strncmp(confbuf, "SENDER_QUOTA_REJECTION=", 23) == 0)
637     {
638       extract_conf(0, confbuf, 22);
639       if((postfix_sender_quota_exceeded=malloc(512)) != NULL)
640       {
641         if(QUOTA_EXCEEDED_TEMP_REJECT==1)
642           snprintf(postfix_sender_quota_exceeded, 512, "%s %s\n\n", POSTFIX_QUOTA_EXCEEDED_TEMP, extract_array_conf[0]);
643         else
644           snprintf(postfix_sender_quota_exceeded, 512, "%s %s\n\n", POSTFIX_QUOTA_EXCEEDED_PERM, extract_array_conf[0]);
645       }
646       else {
647         logmessage("malloc(): %s\n", strerror(errno));
648         exit(-1);
649       }
650     }
651 
652     /* MAX RECIPIENT QUOTA EXCEEDED */
653     if(strncmp(confbuf, "RECIPIENT_QUOTA_REJECTION=", 26) == 0)    {
654       extract_conf(0, confbuf, 25);
655       if((postfix_recipient_quota_exceeded=malloc(512)) != NULL)
656       {
657         if(QUOTA_EXCEEDED_TEMP_REJECT==1)
658           snprintf(postfix_recipient_quota_exceeded, 512, "%s %s\n\n", POSTFIX_QUOTA_EXCEEDED_TEMP, extract_array_conf[0]);
659         else
660           snprintf(postfix_recipient_quota_exceeded, 512, "%s %s\n\n", POSTFIX_QUOTA_EXCEEDED_PERM, extract_array_conf[0]);
661       }
662       else {
663         logmessage("malloc(): %s\n", strerror(errno));
664         exit(-1);
665       }
666     }
667 
668     /* QUOTA_EXCEEDED_TEMP_REJECT */
669     if(strncmp(confbuf, "QUOTA_EXCEEDED_TEMP_REJECT=", 27) == 0)
670     {
671       extract(0, confbuf, 26);
672       QUOTA_EXCEEDED_TEMP_REJECT=atol(extract_array[0]);
673     }
674 
675     memset(confbuf, 0x00, 256);
676   }
677 
678   /* backward compatible with old configs */
679   if(!SYSLOG_FACILITY)
680     SYSLOG_FACILITY=LOG_MAIL|LOG_INFO;
681 
682   /* close config file when we're done */
683   if(fclose(fd_config) != 0)
684   {
685     logmessage("fclose(): %s: %s\n", configpath, strerror(errno));
686     exit(-1);
687   }
688 
689   /* background policyd */
690   if(DAEMON)
691   {
692 
693     /* dont let cleanup run in the background */
694     if(prog == 0)
695     {
696       if(daemonize(0,0) == -1)
697       {
698         fprintf(stderr, "daemon(): %s\n", strerror(errno));
699         exit(-1);
700       }
701     }
702   }
703 
704   /* dump all debugging info */
705   if(DEBUG > 0)
706   {
707     logmessage(" ---- DAEMON CONFIG ----\n");
708     logmessage("config: version> %s\n", VERSION);
709     logmessage("config: debug> %d\n", DEBUG);
710     logmessage("config: daemon mode> %d\n", DAEMON);
711     logmessage("config: bindhost> %s\n", BINDHOST);
712     logmessage("config: bindport> %d\n", BINDPORT);
713     logmessage("config: pidfile> %s\n", PIDFILE);
714     logmessage("config: syslog> %d\n", SYSLOG_FACILITY);
715     logmessage("config: chroot> %s\n", CHROOT);
716     logmessage("config: uid> %d\n", UID);
717     logmessage("config: gid> %d\n", GID);
718     logmessage("config: conn acl> %s\n", CONN_ACL);
719     logmessage("\n");
720 
721     logmessage(" ---- DATABASE CONFIG ----\n");
722     logmessage("config: host> %s\n", MYSQLHOST);
723     logmessage("config: user> %s\n", MYSQLUSER);
724     logmessage("config: pass> %s\n", MYSQLPASS);
725     logmessage("config: database> %s\n", MYSQLDBASE);
726     logmessage("config: options> %s\n", MYSQLOPT);
727     logmessage("config: failsafe> %d\n", FAILSAFE);
728     logmessage("config: keep alive> %d\n", DATABASE_KEEPALIVE);
729     logmessage("config: version> %d\n", MYSQL_VERSION_ID);
730     logmessage("\n");
731 
732     logmessage(" ---- WHITELISTING ----\n");
733     logmessage("config: whitelisting> %d\n", WHITELISTING);
734     logmessage("config: whitelistnullsender> %d\n", WHITELISTNULL);
735     logmessage("config: whitelistsender> %d\n", WHITELISTSENDER);
736     logmessage("config: whitelistdnsname> %d\n", WHITELISTDNSNAME);
737     logmessage("config: autowhitelisting> %d\n", AUTO_WHITE_LISTING);
738     logmessage("config: autowhitelist_number> %d\n", AUTO_WHITELIST_NUMBER);
739     logmessage("config: autowhitelist_netblock> %d\n", AUTO_WHITELIST_NETBLOCK);
740     logmessage("config: autowhitelist_expire> %d\n", AUTO_WHITELIST_EXPIRE);
741     logmessage("\n");
742 
743     logmessage(" ---- BLACKLISTING ----\n");
744     logmessage("config: blacklisting> %d\n", BLACKLISTING);
745     logmessage("config: blacklisting_temp_reject> %d\n", BLACKLIST_TEMP_REJECT);
746     logmessage("config: blacklisting_netblock> %d\n", BLACKLIST_NETBLOCK);
747     logmessage("config: postfix_blacklist> %s\n", postfix_blacklist);
748     logmessage("config: autoblacklisting> %d\n", AUTO_BLACK_LISTING);
749     logmessage("config: autoblacklist_number> %d\n", AUTO_BLACKLIST_NUMBER);
750     logmessage("config: autoblacklist_expire> %d\n", AUTO_BLACKLIST_EXPIRE);
751     logmessage("config: blacklist_rejection> %s\n", postfix_blacklist);
752     logmessage("\n");
753 
754     logmessage(" ---- HELO (HRP) ----\n");
755     logmessage("config: helo> %d\n", HELO_CHECK);
756     logmessage("config: helo_max_count> %d\n", HELO_MAX_COUNT);
757     logmessage("config: helo_blacklist_auto_expire> %d\n", HELO_BLACKLIST_AUTO_EXPIRE);
758     logmessage("config: helo_auto_expire> %d\n", HELO_AUTO_EXPIRE);
759     logmessage("\n");
760 
761     logmessage(" ---- SPAMTRAP CONFIG ----\n");
762     logmessage("config: spamtrap> %d\n", SPAMTRAPPING);
763     logmessage("config: postfix_spamtrap> %s\n", postfix_spamtrap);
764     logmessage("config: spamtrapauto_expire> %d\n", SPAMTRAP_AUTO_EXPIRE);
765     logmessage("\n");
766 
767     logmessage(" ---- GREYLISTING CONFIG ----\n");
768     logmessage("config: greylisting> %d\n", GREYLISTING);
769     logmessage("config: greylist_hostaddr> %d\n", GREYLIST_HOSTADDR);
770     logmessage("config: postfix_greylist> %s\n", postfix_greylist);
771     logmessage("config: greylist_x_header> %d\n", GREYLIST_X_HEADER);
772     logmessage("config: trainingmode> %d\n", TRAINING_MODE);
773     logmessage("config: training_policyd_timeout> %d\n", TRAINING_POLICY_TIMEOUT);
774     logmessage("config: triplet timeout> %d\n", TRIPLET_TIME);
775     logmessage("config: optin/optout> %d\n", OPTINOUT);
776     logmessage("config: optin all in> %d\n", OPTINOUTALL);
777     logmessage("config: triplet auth timeout> %d\n", TRIPLET_AUTH_TIMEOUT);
778     logmessage("config: triplet unauth timeout> %d\n", TRIPLET_UNAUTH_TIMEOUT);
779     logmessage("\n");
780 
781     logmessage(" ---- SENDER THROTTLE CONFIG ----\n");
782     logmessage("config: sender throttle> %d\n", SENDERTHROTTLE);
783     logmessage("config: sender throttle sasl> %d\n", SENDER_THROTTLE_SASL);
784     logmessage("config: sender throttle host> %d\n", SENDER_THROTTLE_HOST);
785     logmessage("config: postfix_sender_quota_exceeded> %s\n", postfix_sender_quota_exceeded);
786     logmessage("config: quota_exceeded_temp_reject> %d\n", QUOTA_EXCEEDED_TEMP_REJECT);
787     logmessage("config: postfix_bad_size> %s\n", postfix_bad_size);
788     logmessage("config: sender msglimit> %d\n", SENDERMSGLIMIT);
789     logmessage("config: sender quotalimit> %d\n", SENDERQUOTALIMIT);
790     logmessage("config: sender timelimit> %d\n", SENDERTIMELIMIT);
791     logmessage("config: sender msgsize> %d\n", SENDERMSGSIZE);
792     logmessage("config: sender expire inactive> %d\n", SENDER_INACTIVE_EXPIRE);
793     logmessage("config: sender throttle autoblacklisting> %d\n", SENDER_THROTTLE_AUTOBLACKLIST);
794     logmessage("config: sender throttle autoblacklist number> %d\n", SENDER_THROTTLE_AUTOBLACKLIST_NUMBER);
795     logmessage("config: sender throttle autoblacklist expire> %d\n", SENDER_THROTTLE_AUTOBLACKLIST_EXPIRE);
796     logmessage("\n");
797 
798     logmessage(" ---- RECIPIENT THROTTLE CONFIG ----\n");
799     logmessage("config: recipient throttle> %d\n", RECIPIENTTHROTTLE);
800     logmessage("config: recipient msglimit> %d\n", RECIPIENTMSGLIMIT);
801     logmessage("config: recipient timelimit> %d\n", RECIPIENTTIMELIMIT);
802     logmessage("config: recipient expire inactive> %d\n", RECIPIENT_INACTIVE_EXPIRE);
803     logmessage("config: postfix_recipient_quota_exceeded> %s\n", postfix_recipient_quota_exceeded);
804     logmessage("config: quota_exceeded_temp_reject> %d\n", QUOTA_EXCEEDED_TEMP_REJECT);
805     logmessage("\n");
806   }
807 
808   if((SENDER_THROTTLE_HOST) && (SENDER_THROTTLE_SASL))
809   {
810     logmessage("FATAL: you may NOT have SENDER_THROTTLE_HOST and SENDER_THROTTLE_SASL enabled\n");
811     exit (-1);
812   }
813 
814   /* quick acl check */
815   if((!CONN_ACL) || (!strlen(CONN_ACL)))
816   {
817     logmessage("FATAL: you did not upgrade correctly or have broken something. "
818                "Please read the Changelog.txt. You're missing the CONN_ACL setting\n");
819     exit (-1);
820   }
821 }
822 
823 
824 
825 /*
826  * function: w_string_strip
827  *  purpose:
828  *   return:
829  */
830 int
w_string_strip(void * str,char * token)831 w_string_strip(void *str, char *token)
832 {
833   char	*ptr;
834   ptr	 = strtok(str, token);
835 
836   if(ptr != NULL)
837   {
838     return (1); /* found */
839   } else {
840     return (0); /* not found */
841   }
842 }
843 
844 
845 
846 /*
847  * function: logmessage
848  *  purpose: log messages to syslog or stdout/stderr
849  *   return: nada
850  */
851 void
logmessage(const char * fmt,...)852 logmessage(const char *fmt, ...)
853 {
854   va_list ap;
855   va_start(ap, fmt);
856 
857   if(DAEMON == 0)
858   {
859     vfprintf(stdout, fmt, ap);
860     fflush(stdout);
861   }
862   else
863     vsyslog(SYSLOG_FACILITY, fmt, ap);
864 
865   va_end(ap);
866 }
867 
868 
869 
870 
871 /*
872  * function: usage
873  *  purpose: print out usage information
874  *   return: nada
875  */
876 void
usage(char * usag)877 usage(char *usag)
878 {
879   logmessage("policyd %s\n", VERSION);
880   logmessage("usage: %s -c /path/to/policyd.conf\n", usag);
881   exit(-1);
882 }
883 
884 
885 
886 
887 /*
888  * function: extract_seconds
889  *  purpose: convert token to seconds
890  *   return: seconds
891  */
892 int
extract_seconds(char * token)893 extract_seconds(char *token)
894 {
895            char tmp[32];
896   unsigned  int multiplier=0;
897 
898   /* allow values of 0 */
899   if((isdigit(token[0]) != 0) && (atol(token) == 0))
900     return 0;
901 
902   memset(tmp, 0x00, 32);
903   switch(token[strlen(token) - 1])
904   {
905 
906     case 's':
907       multiplier = 1;
908       break;
909 
910     case 'm':
911       multiplier = 60;
912       break;
913 
914     case 'h':
915       multiplier = 60 * 60;
916       break;
917 
918     case 'd':
919       multiplier = 60 * 60 * 24;
920       break;
921 
922     case 'w':
923       multiplier = 60 * 60 * 24 * 7;
924       break;
925 
926     case 'M':
927       multiplier = 60 * 60 * 24 * 31 ;
928       break;
929 
930     case 'Y':
931       multiplier = 60 * 60 * 24 * 31 * 12;
932       break;
933 
934     default:
935       logmessage("fatal: invalid time unit: %s\n", token);
936       exit(-1);
937   }
938 
939   strncpy(tmp, token, sizeof(tmp) - 2);
940   return (atol(tmp) * multiplier);
941 }
942 
943 
944 
945 
946 /*
947  * function: extract
948  *  purpose: extract policy variable
949  *   return: policy variable (into an array)
950  */
951 void
extract(unsigned int fd,char * token,unsigned int startlen)952 extract(unsigned int fd, char *token, unsigned int startlen)
953 {
954   unsigned int y, clen=startlen, tlen;
955 
956   memset(extract_array[fd], 0x00, 64);
957   tlen=strlen(token);
958 
959   for( ; clen <= tlen && clen <= 63 ; clen++) {
960     if(token[clen]=='=') {
961       for(clen++,y=0; clen<=tlen&&clen<=63;clen++) {
962         /* we only want characters [A-Z][a-z][0-9]/@ and . */
963         if((isalnum(token[clen]) != 0)
964                 || (token[clen] == '@')
965                 || (token[clen] == '|')
966                 || (token[clen] == '.')
967                 || (token[clen] == '_')
968                 || (token[clen] == '-')
969                 || (token[clen] == ' ')
970                 || (token[clen] == '/')) {
971           extract_array[fd][y]=token[clen]; y++;
972         }
973       }
974     }
975   }
976 }
977 
978 
979 
980 
981 /*
982  * function: extract_conf
983  *  purpose: extract policy variable
984  *   return: policy variable (into an array)
985  */
986 void
extract_conf(unsigned int fd,char * token,unsigned int startlen)987 extract_conf(unsigned int fd, char *token, unsigned int startlen)
988 {
989   unsigned int y, clen=startlen, tlen;
990 
991   memset(extract_array_conf[fd], 0x00, 512);
992   tlen=strlen(token);
993 
994   for( ; clen <= tlen && clen <= 511 ; clen++) {
995     if(token[clen]=='=') {
996       for(clen++,y=0; clen<=tlen&&clen<=511;clen++) {
997         /* we only want characters [A-Z][a-z][0-9]/@ and . */
998         if((isalnum(token[clen]) != 0) || isascii(token[clen] != 0)) {
999 	  if((token[clen] != '"') && (token[clen] != '\n')) {
1000           extract_array_conf[fd][y]=token[clen]; y++; }
1001         }
1002       }
1003     }
1004   }
1005 }
1006 
1007 
1008 
1009 
1010 
1011 /*
1012  * function: extract_ip
1013  *  purpose: extract ip address from policy variable
1014  *   return: policy variable (into an array)
1015  */
1016 void
extract_ip(unsigned int fd,char * token)1017 extract_ip(unsigned int fd, char *token)
1018 {
1019   unsigned int x=15, y=0, z=0, len;
1020 
1021   memset(extract_ip_array[fd], 0x00, 64);
1022   len=strlen(token);
1023 
1024   for(x=15,z=0,y=0;x<len||x<64;x++) {
1025     if(token[x] == '\n') break;
1026 
1027     /* we only want characters [0-9] and . */
1028     if((isdigit(token[x]) != 0) || (token[x] == '.'))
1029     {
1030       if(token[x] == '.') z++;
1031       if(z == GREYLIST_HOSTADDR) break;
1032       extract_ip_array[fd][y]=token[x]; y++;
1033     }
1034   }
1035 }
1036 
1037 
1038 
1039 
1040 /*
1041  * function: extract_ip_array
1042  *  purpose: extract ip address from policy variable
1043  *   return: policy variable (into an array)
1044  */
1045 void
extract_ipfill(unsigned int fd,char * token)1046 extract_ipfill(unsigned int fd, char *token)
1047 {
1048   unsigned int x=15, y=0, z=0, len, w=5;
1049 
1050   memset(extract_ip_array[fd], 0x00, 64);
1051   len=strlen(token);
1052 
1053   for(x=15,z=0,y=0;x<len||x<64;x++) {
1054     if(token[x] == '\n') break;
1055 
1056     /* we only want characters [0-9] and . */
1057     if((isdigit(token[x]) != 0) || (token[x] == '.'))
1058     {
1059       if(token[x] == '.')
1060       {
1061         if(z == 0)
1062            snprintf(host_array[fd][w], 64, "%s.%%.%%.%%", extract_ip_array[fd]);
1063 
1064         if(z == 1)
1065            snprintf(host_array[fd][w], 64, "%s.%%.%%", extract_ip_array[fd]);
1066 
1067         if(z == 2)
1068            snprintf(host_array[fd][w], 64, "%s.%%", extract_ip_array[fd]);
1069 
1070         z++; w--;
1071       }
1072 
1073       if(z == GREYLIST_HOSTADDR)
1074         break;
1075       extract_ip_array[fd][y]=token[x];
1076       y++;
1077     }
1078   }
1079 }
1080 
1081 
1082 
1083 
1084 /*
1085  *  function: fold
1086  *   purpose: shut down all open connections and close policyd gracefully
1087  *    return: nada
1088  */
1089 void
fold()1090 fold()
1091 {
1092   logmessage("shutting down..\n");
1093   shutdown(msock, SHUT_RDWR);
1094   shutdown(ssock, SHUT_RDWR);
1095   exit(0);
1096 }
1097 
1098 
1099 
1100 
1101 /*
1102  * function: gettime
1103  *  purpose: get current time
1104  *   return: return current time
1105  */
1106 int
gettime(void)1107 gettime(void)
1108 {
1109   /* get current time */
1110   if(gettimeofday(&timevalue, NULL) != 0)
1111   {
1112     logmessage("gettimeofday(): %s\n", strerror(errno));
1113     exit(-1);
1114   }
1115 
1116   return (timevalue.tv_sec);
1117 }
1118 
1119 
1120 
1121 
1122 /*
1123  * function: drop_privs
1124  *  purpose: drop privledges
1125  *   return: nada
1126  */
1127 void
drop_privs(void)1128 drop_privs(void)
1129 {
1130   /*
1131    * 1) quick sanity check
1132    * 2) ensure backward compatibility with old configs
1133    */
1134   if(PIDFILE)
1135   {
1136     /* write to pid file */
1137     if((pidfile=fopen(PIDFILE, "w")) == NULL)
1138     {
1139       fprintf(stderr, "fopen(): %s: %s\n", strerror(errno), PIDFILE);
1140       exit(-1);
1141     }
1142     fprintf(pidfile, "%d\n", (unsigned int)getpid());
1143 
1144     /* we're done, clean up */
1145     if(fclose(pidfile) != 0)
1146     {
1147       logmessage("fclose(): %s: %s\n", PIDFILE, strerror(errno));
1148       exit(-1);
1149     }
1150   }
1151 
1152   /* change root */
1153   if(chdir(CHROOT) == -1)
1154   {
1155     logmessage("chdir(): %s\n", strerror(errno));
1156     exit(-1);
1157   }
1158 
1159   /* chroot */
1160   if(chroot(".") == -1)
1161   {
1162     logmessage("chroot(): %s\n", strerror(errno));
1163     exit(-1);
1164   }
1165 
1166   /* change gid */
1167   if(setgid(GID) == -1)
1168   {
1169     logmessage("setgid(): %s\n", strerror(errno));
1170     exit(-1);
1171   }
1172 
1173   /* change uid */
1174   if(setuid(UID) == -1)
1175   {
1176     logmessage("setuid(): %s\n", strerror(errno));
1177     exit(-1);
1178   }
1179 
1180 }
1181 
1182 
1183 
1184 
1185 /*
1186  * function: policy_reply
1187  *  purpose: reply/talk to Postfix
1188  *   return: 0=sucessfull write(), 1=failed write()
1189  */
1190 void
policy_reply(unsigned int fd,int code,int status)1191 policy_reply(unsigned int fd, int code, int status)
1192 {
1193   /* keep gcc quiet for now */
1194   status = 0;
1195 
1196 
1197   switch (code)
1198   {
1199     /* accept: always allow */
1200     case 0:
1201       /* dump greylisting information into mail? */
1202       if((GREYLISTING==1) && (GREYLIST_X_HEADER==1))
1203       {
1204 
1205         /* whitelisted */
1206         snprintf(xgreylist_array[fd], 128, "%s host: %s\n\n",
1207         POSTFIX_X_HEADER, host_array[fd][2]);
1208 
1209         /* if not whitelisted, greylist.c already filled in all the details */
1210         buf_write(fd, xgreylist_array[fd], strlen(xgreylist_array[fd]));
1211       } else {
1212     	buf_write(fd, POSTFIX_GOOD, strlen(POSTFIX_GOOD));
1213       }
1214 
1215     break;
1216 
1217   /* reject: greylisting */
1218   case -1:
1219     buf_write(fd, postfix_greylist, strlen(postfix_greylist));
1220     break;
1221 
1222   /* reject: blacklisted */
1223   case -2:
1224     buf_write(fd, postfix_blacklist, strlen(postfix_blacklist));
1225     break;
1226 
1227   /* reject: message size too big */
1228   case -3:
1229     buf_write(fd, postfix_bad_size, strlen(postfix_bad_size));
1230     break;
1231 
1232   /* reject: spam trap address */
1233   case -4:
1234     buf_write(fd, postfix_spamtrap, strlen(postfix_spamtrap));
1235     break;
1236 
1237   /* reject: max sender quota exceeded */
1238   case -5:
1239     buf_write(fd, postfix_sender_quota_exceeded, strlen(postfix_sender_quota_exceeded));
1240     break;
1241 
1242   /* reject: helo checking */
1243   case -6:
1244     buf_write(fd, postfix_blacklist, strlen(postfix_blacklist));
1245     break;
1246 
1247   /* reject: max recipient quota exceeded */
1248   case -7:
1249     buf_write(fd, postfix_recipient_quota_exceeded, strlen(postfix_recipient_quota_exceeded));
1250     break;
1251 
1252   /* reject: max recipient quota exceeded */
1253   case -8:
1254     buf_write(fd, POSTFIX_MODULE_FAILURE, strlen(POSTFIX_MODULE_FAILURE));
1255     break;
1256 
1257   /* something bad happened */
1258   default:
1259     logmessage("WARNING: policy_reply called with unknown code\n");
1260     buf_write(fd, POSTFIX_MODULE_FAILURE, strlen(POSTFIX_MODULE_FAILURE));
1261     break;
1262   }
1263 }
1264 
1265 
1266 
1267 
1268 /*
1269  * function: db_failure
1270  *  purpose: handle database failures so policyd isnt a single point of failure.
1271  *   return: -20 for failures (talk to Postfix first)
1272  */
1273 int
db_failure(unsigned int fd,char * module)1274 db_failure(unsigned int fd, char *module)
1275 {
1276 
1277   if(FAILSAFE==1)
1278   {
1279     /* do not fail */
1280     logmessage("rcpt=%lu, %s=bypass, host=%s (%s), from=%s, to=%s, size=%s\n",
1281       rcpt_count,               /* recipient count      */
1282       module,                   /* module name          */
1283       host_array[fd][2],        /* host                 */
1284       host_array[fd][0],        /* hostname             */
1285       triplet_array[fd][1],     /* from                 */
1286       triplet_array[fd][2],     /* rcpt                 */
1287       triplet_array[fd][3]      /* size                 */
1288     );
1289 
1290     mysql_failure_count++;
1291     policy_reply(fd, 0, 0);
1292     return (-20);
1293   }
1294 
1295   if(FAILSAFE==0)
1296   {
1297     /* fail as requested */
1298     logmessage("rcpt=%lu, %s=failed, host=%s (%s), from=%s, to=%s, size=%s\n",
1299       rcpt_count,               /* recipient count      */
1300       module,                   /* module name          */
1301       host_array[fd][2],        /* host                 */
1302       host_array[fd][0],        /* hostname             */
1303       triplet_array[fd][1],     /* from                 */
1304       triplet_array[fd][2],     /* rcpt                 */
1305       triplet_array[fd][3]      /* size                 */
1306     );
1307 
1308     policy_reply(fd, -1, 0);
1309     return (-20);
1310   }
1311 
1312   return (0); /* not reached */
1313 }
1314 
1315 
1316 void
sigalrm_handler(void)1317 sigalrm_handler (void)
1318 {
1319   alarm (0);                      /* reset alarm timer */
1320   siglongjmp (sjmp, 1);           /* jump back */
1321 }
1322 
1323 
1324 
1325 /* EOF */
1326