~ubuntu-branches/ubuntu/utopic/rmilter/utopic

« back to all changes in this revision

Viewing changes to src/cfg_file.c

  • Committer: Package Import Robot
  • Author(s): Mikhail Gusarov
  • Date: 2014-03-10 00:55:10 UTC
  • Revision ID: package-import@ubuntu.com-20140310005510-mnoc6rsyn4ztnwtx
Tags: 1.6.1
Initial upload (Closes: #741161)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2007-2012, Vsevolod Stakhov
 
3
 * All rights reserved.
 
4
 
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions are met:
 
7
 * Redistributions of source code must retain the above copyright notice, this
 
8
 * list of conditions and the following disclaimer. Redistributions in binary form
 
9
 * must reproduce the above copyright notice, this list of conditions and the
 
10
 * following disclaimer in the documentation and/or other materials provided with
 
11
 * the distribution. Neither the name of the author nor the names of its
 
12
 * contributors may be used to endorse or promote products derived from this
 
13
 * software without specific prior written permission.
 
14
 
 
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
17
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
18
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
21
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 
22
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 
23
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
24
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
25
 */
 
26
 
 
27
#include "config.h"
 
28
 
 
29
#include "pcre.h"
 
30
#include "cfg_file.h"
 
31
#include "spf.h"
 
32
#include "rmilter.h"
 
33
 
 
34
extern int yylineno;
 
35
extern char *yytext;
 
36
 
 
37
void
 
38
parse_err (const char *fmt, ...)
 
39
{
 
40
        va_list aq;
 
41
        char logbuf[BUFSIZ], readbuf[32];
 
42
        int r;
 
43
        
 
44
        va_start (aq, fmt);
 
45
        rmilter_strlcpy (readbuf, yytext, sizeof (readbuf));
 
46
 
 
47
        r = snprintf (logbuf, sizeof (logbuf), "config file parse error! line: %d, text: %s, reason: ", yylineno, readbuf);
 
48
        r += vsnprintf (logbuf + r, sizeof (logbuf) - r, fmt, aq);
 
49
 
 
50
        va_end (aq);
 
51
        fprintf (stderr,"%s\n", logbuf);
 
52
        syslog (LOG_ERR, "%s", logbuf);
 
53
}
 
54
 
 
55
void
 
56
parse_warn (const char *fmt, ...)
 
57
{
 
58
        va_list aq;
 
59
        char logbuf[BUFSIZ], readbuf[32];
 
60
        int r;
 
61
        
 
62
        va_start (aq, fmt);
 
63
        rmilter_strlcpy (readbuf, yytext, sizeof (readbuf));
 
64
 
 
65
        r = snprintf (logbuf, sizeof (logbuf), "config file parse warning! line: %d, text: %s, reason: ", yylineno, readbuf);
 
66
        r += vsnprintf (logbuf + r, sizeof (logbuf) - r, fmt, aq);
 
67
 
 
68
        va_end (aq);
 
69
        syslog (LOG_ERR, "%s", logbuf);
 
70
}
 
71
 
 
72
 
 
73
static size_t
 
74
copy_regexp (char **dst, const char *src)
 
75
{
 
76
        size_t len;
 
77
        if (!src || *src == '\0') return 0;
 
78
 
 
79
        len = strlen (src);
 
80
 
 
81
        /* Skip slashes */
 
82
        if (*src == '/') {
 
83
                src++;
 
84
                len--;
 
85
        }
 
86
        if (src[len - 1] == '/') {
 
87
                len--;
 
88
        }
 
89
 
 
90
        *dst = malloc (len + 1);
 
91
        if (!*dst) return 0;
 
92
 
 
93
        return rmilter_strlcpy (*dst, src, len + 1);
 
94
}
 
95
 
 
96
int
 
97
add_memcached_server (struct config_file *cf, char *str, char *str2, int type)
 
98
{
 
99
        char *cur_tok, *err_str;
 
100
        struct memcached_server *mc = NULL;
 
101
        struct hostent *he;
 
102
        uint16_t port;
 
103
 
 
104
        if (str == NULL) return 0;
 
105
 
 
106
        if (type == MEMCACHED_SERVER_GREY) {
 
107
                if(cf->memcached_servers_grey_num == MAX_MEMCACHED_SERVERS) {
 
108
                        yywarn ("yyparse: maximum number of memcached servers is reached %d", MAX_MEMCACHED_SERVERS);
 
109
                        return 0;
 
110
                }
 
111
        
 
112
                mc = &cf->memcached_servers_grey[cf->memcached_servers_grey_num];
 
113
        }
 
114
        else if (type == MEMCACHED_SERVER_WHITE) {
 
115
                if(cf->memcached_servers_white_num == MAX_MEMCACHED_SERVERS) {
 
116
                        yywarn ("yyparse: maximum number of whitelist memcached servers is reached %d", MAX_MEMCACHED_SERVERS);
 
117
                        return 0;
 
118
                }
 
119
        
 
120
                mc = &cf->memcached_servers_white[cf->memcached_servers_white_num];
 
121
        }
 
122
        else if (type == MEMCACHED_SERVER_LIMITS) {
 
123
                if(cf->memcached_servers_limits_num == MAX_MEMCACHED_SERVERS) {
 
124
                        yywarn ("yyparse: maximum number of limits memcached servers is reached %d", MAX_MEMCACHED_SERVERS);
 
125
                        return 0;
 
126
                }
 
127
        
 
128
                mc = &cf->memcached_servers_limits[cf->memcached_servers_limits_num];
 
129
        }
 
130
        else if (type == MEMCACHED_SERVER_ID) {
 
131
                if(cf->memcached_servers_id_num == MAX_MEMCACHED_SERVERS) {
 
132
                        yywarn ("yyparse: maximum number of id memcached servers is reached %d", MAX_MEMCACHED_SERVERS);
 
133
                        return 0;
 
134
                }
 
135
        
 
136
                mc = &cf->memcached_servers_id[cf->memcached_servers_id_num];
 
137
        }
 
138
        if (mc == NULL) return 0;
 
139
 
 
140
        cur_tok = strsep (&str, ":");
 
141
 
 
142
        if (cur_tok == NULL || *cur_tok == '\0') return 0;
 
143
 
 
144
        /* cur_tok - server name, str - server port */
 
145
        if (str == NULL) {
 
146
                port = htons(DEFAULT_MEMCACHED_PORT);
 
147
        }
 
148
        else {
 
149
                port = htons ((uint16_t)strtoul (str, &err_str, 10));
 
150
                if (*err_str != '\0') {
 
151
                        return 0;
 
152
                }
 
153
        }
 
154
 
 
155
        if (!inet_aton (cur_tok, &mc->addr[0])) {
 
156
                /* Try to call gethostbyname */
 
157
                he = gethostbyname (cur_tok);
 
158
                if (he == NULL) {
 
159
                        return 0;
 
160
                }
 
161
                else {
 
162
                        memcpy((char *)&mc->addr[0], he->h_addr, sizeof(struct in_addr));
 
163
                }
 
164
        }
 
165
        mc->port[0] = port;
 
166
 
 
167
        if (str2 == NULL) {
 
168
                mc->num = 1;
 
169
        }
 
170
        else {
 
171
                mc->num = 2;
 
172
                cur_tok = strsep (&str2, ":");
 
173
 
 
174
                if (cur_tok == NULL || *cur_tok == '\0') return 0;
 
175
 
 
176
                /* cur_tok - server name, str - server port */
 
177
                if (str2 == NULL) {
 
178
                        port = htons(DEFAULT_MEMCACHED_PORT);
 
179
                }
 
180
                else {
 
181
                        port = htons ((uint16_t)strtoul (str2, &err_str, 10));
 
182
                        if (*err_str != '\0') {
 
183
                                return 0;
 
184
                        }
 
185
                }
 
186
 
 
187
                if (!inet_aton (cur_tok, &mc->addr[1])) {
 
188
                        /* Try to call gethostbyname */
 
189
                        he = gethostbyname (cur_tok);
 
190
                        if (he == NULL) {
 
191
                                return 0;
 
192
                        }
 
193
                        else {
 
194
                                memcpy((char *)&mc->addr[1], he->h_addr, sizeof(struct in_addr));
 
195
                        }
 
196
                }
 
197
                mc->port[1] = port;
 
198
        }
 
199
        
 
200
        mc->alive[0] = 1;
 
201
        mc->alive[1] = 1;
 
202
 
 
203
        if (type == MEMCACHED_SERVER_GREY) {
 
204
                cf->memcached_servers_grey_num++;
 
205
        }
 
206
        else if (type == MEMCACHED_SERVER_WHITE) {
 
207
                cf->memcached_servers_white_num++;
 
208
        }
 
209
        else if (type == MEMCACHED_SERVER_LIMITS) {
 
210
                cf->memcached_servers_limits_num++;
 
211
        }
 
212
        else if (type == MEMCACHED_SERVER_ID) {
 
213
                cf->memcached_servers_id_num++;
 
214
        }
 
215
 
 
216
        return 1;
 
217
}
 
218
 
 
219
int
 
220
add_clamav_server (struct config_file *cf, char *str)
 
221
{
 
222
        char *cur_tok, *err_str;
 
223
        struct clamav_server *srv;
 
224
        struct hostent *he;
 
225
 
 
226
        if (str == NULL) return 0;
 
227
        
 
228
        cur_tok = strsep (&str, ":");
 
229
        
 
230
        if (cur_tok == NULL || *cur_tok == '\0') return 0;
 
231
 
 
232
        if (cf->clamav_servers_num == MAX_CLAMAV_SERVERS) {
 
233
                yywarn ("yyparse: maximum number of clamav servers is reached %d", MAX_CLAMAV_SERVERS);
 
234
        }
 
235
 
 
236
        srv = &cf->clamav_servers[cf->clamav_servers_num];
 
237
 
 
238
        if (srv == NULL) return 0;
 
239
 
 
240
        if (cur_tok[0] == '/' || cur_tok[0] == '.') {
 
241
                srv->sock.unix_path = strdup (cur_tok);
 
242
                srv->sock_type = AF_UNIX;
 
243
                srv->name = srv->sock.unix_path;
 
244
                if (str != NULL && *str != '\0') {
 
245
                        srv->up.priority = strtoul (str, &err_str, 10);
 
246
                        if (*err_str != '\0') {
 
247
                                return 0;
 
248
                        }
 
249
                        cf->weighted_clamav = 1;
 
250
                }
 
251
 
 
252
                cf->clamav_servers_num++;
 
253
                return 1;
 
254
 
 
255
        } else {
 
256
                if (str == '\0') {
 
257
                        srv->sock.inet.port = htons (DEFAULT_CLAMAV_PORT);
 
258
                }
 
259
                else {
 
260
                        srv->sock.inet.port = htons ((uint16_t)strtoul (str, &err_str, 10));
 
261
                        if (*err_str != '\0') {
 
262
                                return 0;
 
263
                        }
 
264
 
 
265
                }
 
266
 
 
267
                if (!inet_aton (cur_tok, &srv->sock.inet.addr)) {
 
268
                        /* Try to call gethostbyname */
 
269
                        he = gethostbyname (cur_tok);
 
270
                        if (he == NULL) {
 
271
                                return 0;
 
272
                        }
 
273
                        else {
 
274
                                srv->name = strdup (cur_tok);
 
275
                                memcpy((char *)&srv->sock.inet.addr, he->h_addr, sizeof(struct in_addr));
 
276
                        }
 
277
                }
 
278
                /* Try to parse priority */
 
279
                cur_tok = strsep (&str, ":");
 
280
                if (str != NULL && *str != '\0') {
 
281
                        srv->up.priority = strtoul (str, &err_str, 10);
 
282
                        if (*err_str != '\0') {
 
283
                                return 0;
 
284
                        }
 
285
                        cf->weighted_clamav = 1;
 
286
                }
 
287
 
 
288
                srv->sock_type = AF_INET;
 
289
                cf->clamav_servers_num++;
 
290
                return 1;
 
291
        }
 
292
 
 
293
        return 0;
 
294
}
 
295
 
 
296
int
 
297
add_spamd_server (struct config_file *cf, char *str, int is_extra)
 
298
{
 
299
        char *cur_tok, *err_str;
 
300
        struct spamd_server *srv;
 
301
        struct hostent *he;
 
302
 
 
303
        if (str == NULL) return 0;
 
304
        
 
305
        if (is_extra) {
 
306
                if (cf->extra_spamd_servers_num == MAX_SPAMD_SERVERS) {
 
307
                        yywarn ("yyparse: maximum number of spamd servers is reached %d", MAX_SPAMD_SERVERS);
 
308
                        return -1;
 
309
                }
 
310
        }
 
311
        else {
 
312
                if (cf->spamd_servers_num == MAX_SPAMD_SERVERS) {
 
313
                        yywarn ("yyparse: maximum number of spamd servers is reached %d", MAX_SPAMD_SERVERS);
 
314
                        return -1;
 
315
                }
 
316
        }
 
317
 
 
318
        if (is_extra) {
 
319
                srv = &cf->extra_spamd_servers[cf->extra_spamd_servers_num];
 
320
        }
 
321
        else {
 
322
                srv = &cf->spamd_servers[cf->spamd_servers_num];
 
323
        }
 
324
 
 
325
        if (*str == 'r' && *(str + 1) == ':') {
 
326
                srv->type = SPAMD_RSPAMD;
 
327
                str += 2;
 
328
        }
 
329
        else {
 
330
                srv->type = SPAMD_SPAMASSASSIN;
 
331
        }
 
332
 
 
333
 
 
334
        cur_tok = strsep (&str, ":");
 
335
        
 
336
        if (cur_tok == NULL || *cur_tok == '\0') return 0;
 
337
 
 
338
        if (cur_tok[0] == '/' || cur_tok[0] == '.') {
 
339
                srv->sock.unix_path = strdup (cur_tok);
 
340
                srv->sock_type = AF_UNIX;
 
341
                srv->name = srv->sock.unix_path;
 
342
 
 
343
                if (is_extra) {
 
344
                        cf->extra_spamd_servers_num++;
 
345
                }
 
346
                else {
 
347
                        cf->spamd_servers_num++;
 
348
                }
 
349
                return 1;
 
350
 
 
351
        } else {
 
352
                if (str == '\0') {
 
353
                        srv->sock.inet.port = htons (DEFAULT_SPAMD_PORT);
 
354
                }
 
355
                else {
 
356
                        srv->sock.inet.port = htons ((uint16_t)strtoul (str, &err_str, 10));
 
357
                        if (*err_str != '\0') {
 
358
                                return 0;
 
359
                        }
 
360
                }
 
361
 
 
362
                if (!inet_aton (cur_tok, &srv->sock.inet.addr)) {
 
363
                        /* Try to call gethostbyname */
 
364
                        he = gethostbyname (cur_tok);
 
365
                        if (he == NULL) {
 
366
                                return 0;
 
367
                        }
 
368
                        else {
 
369
                                memcpy((char *)&srv->sock.inet.addr, he->h_addr, sizeof(struct in_addr));
 
370
                        }
 
371
                }
 
372
                srv->name = strdup (cur_tok);
 
373
 
 
374
                srv->sock_type = AF_INET;
 
375
                if (is_extra) {
 
376
                        cf->extra_spamd_servers_num++;
 
377
                }
 
378
                else {
 
379
                        cf->spamd_servers_num++;
 
380
                }
 
381
                return 1;
 
382
        }
 
383
 
 
384
        return 0;
 
385
}
 
386
 
 
387
int
 
388
add_beanstalk_server (struct config_file *cf, char *str, int type)
 
389
{
 
390
        char *cur_tok, *err_str;
 
391
        struct beanstalk_server *srv;
 
392
        struct hostent *he;
 
393
 
 
394
        if (str == NULL) return 0;
 
395
        
 
396
        cur_tok = strsep (&str, ":");
 
397
        
 
398
        if (cur_tok == NULL || *cur_tok == '\0') return 0;
 
399
        
 
400
        if (type == 1) {
 
401
                cf->copy_server = malloc (sizeof (struct beanstalk_server));
 
402
                srv = cf->copy_server;
 
403
        }
 
404
        else if (type == 2) {
 
405
                cf->spam_server = malloc (sizeof (struct beanstalk_server));
 
406
                srv = cf->spam_server;
 
407
        }
 
408
        else {
 
409
                if (cf->beanstalk_servers_num == MAX_BEANSTALK_SERVERS) {
 
410
                        yywarn ("yyparse: maximum number of beanstalk servers is reached %d", MAX_BEANSTALK_SERVERS);
 
411
                }
 
412
 
 
413
                srv = &cf->beanstalk_servers[cf->beanstalk_servers_num];
 
414
        }
 
415
 
 
416
        if (srv == NULL) return 0;
 
417
 
 
418
        if (str == '\0') {
 
419
                srv->port = htons (DEFAULT_BEANSTALK_PORT);
 
420
        }
 
421
        else {
 
422
                srv->port = htons ((uint16_t)strtoul (str, &err_str, 10));
 
423
                if (*err_str != '\0') {
 
424
                        return 0;
 
425
                }
 
426
        }
 
427
 
 
428
        if (!inet_aton (cur_tok, &srv->addr)) {
 
429
                /* Try to call gethostbyname */
 
430
                he = gethostbyname (cur_tok);
 
431
                if (he == NULL) {
 
432
                        return 0;
 
433
                }
 
434
                else {
 
435
                        srv->name = strdup (cur_tok);
 
436
                        memcpy((char *)&srv->addr, he->h_addr, sizeof(struct in_addr));
 
437
                }
 
438
                if (type == 0) {
 
439
                        cf->beanstalk_servers_num ++;
 
440
                }
 
441
                return 1;
 
442
        }
 
443
        else {
 
444
                srv->name = strdup (cur_tok);
 
445
                if (type == 0) {
 
446
                        cf->beanstalk_servers_num ++;
 
447
                }
 
448
                return 1;       
 
449
        }
 
450
 
 
451
 
 
452
        return 0;
 
453
}
 
454
 
 
455
struct action *
 
456
create_action (enum action_type type, const char *message)
 
457
{
 
458
        struct action *new;
 
459
        size_t len = strlen (message);
 
460
 
 
461
        if (message == NULL) return NULL;
 
462
 
 
463
        new = (struct action *)malloc (sizeof (struct action)); 
 
464
 
 
465
        if (new == NULL) return NULL;
 
466
 
 
467
        new->type = type;
 
468
        /* Trim quotes */
 
469
        if (*message == '"') {
 
470
                message++;
 
471
                len--;
 
472
        }
 
473
        if (message[len - 1] == '"') {
 
474
                len--;
 
475
        }
 
476
 
 
477
        new->message = (char *)malloc (len + 1);
 
478
 
 
479
        if (new->message == NULL) return NULL;
 
480
 
 
481
        rmilter_strlcpy (new->message, message, len + 1);
 
482
 
 
483
        return new;
 
484
}
 
485
 
 
486
struct condition *
 
487
create_cond (enum condition_type type, const char *arg1, const char *arg2)
 
488
{
 
489
        struct condition *new;
 
490
        int offset;
 
491
        const char *read_err;
 
492
 
 
493
        new = (struct condition *)malloc (sizeof (struct condition));
 
494
        bzero (new, sizeof (struct condition));
 
495
        
 
496
        if (new == NULL) return NULL;
 
497
 
 
498
        if (arg1 == NULL || *arg1 == '\0') {
 
499
                new->args[0].empty = 1;
 
500
        }
 
501
        else {
 
502
                if (!copy_regexp (&new->args[0].src, arg1)) {
 
503
                        new->args[0].empty = 1;
 
504
                }
 
505
                else {
 
506
                        new->args[0].re = pcre_compile (new->args[0].src, 0, &read_err, &offset, NULL);
 
507
                        if (new->args[0].re == NULL) {
 
508
                                new->args[0].empty = 1;
 
509
                        }
 
510
                }
 
511
        }
 
512
        if (arg2 == NULL || *arg2 == '\0') {
 
513
                new->args[1].empty = 1;
 
514
        }
 
515
        else {
 
516
                if (!copy_regexp (&new->args[1].src, arg2)) {
 
517
                        new->args[1].empty = 1;
 
518
                }
 
519
                else {
 
520
                        new->args[1].re = pcre_compile (new->args[1].src, 0, &read_err, &offset, NULL);
 
521
                        if (new->args[1].re == NULL) {
 
522
                                new->args[1].empty = 1;
 
523
                        }
 
524
                }
 
525
        }
 
526
 
 
527
        new->type = type;
 
528
 
 
529
        return new;
 
530
}
 
531
 
 
532
int
 
533
add_spf_domain (struct config_file *cfg, char *domain)
 
534
{
 
535
        if (!domain) return 0;
 
536
 
 
537
        if (cfg->spf_domains_num > MAX_SPF_DOMAINS) {
 
538
                return 0;
 
539
        }
 
540
 
 
541
        cfg->spf_domains[cfg->spf_domains_num] = domain;
 
542
        cfg->spf_domains_num ++;
 
543
 
 
544
        return 1;
 
545
}
 
546
 
 
547
int
 
548
add_ip_radix (radix_tree_t *tree, char *ipnet)
 
549
{
 
550
        uint32_t mask = 0xFFFFFFFF;
 
551
        uint32_t ip;
 
552
        char *token;
 
553
        struct in_addr ina;
 
554
        int k;
 
555
 
 
556
        token = strsep (&ipnet, "/");
 
557
 
 
558
        if (ipnet != NULL) {
 
559
                k = atoi (ipnet);
 
560
                if (k > 32 || k < 0) {
 
561
                        yywarn ("add_ip_radix: invalid netmask value: %d", k);
 
562
                        k = 32;
 
563
                }
 
564
                k = 32 - k;
 
565
                mask = mask << k;
 
566
        }
 
567
 
 
568
        if (inet_aton (token, &ina) == 0) {
 
569
                yyerror ("add_ip_radix: invalid ip address: %s", token);
 
570
                return 0;
 
571
        }
 
572
 
 
573
        ip = ntohl((uint32_t)ina.s_addr);
 
574
        k = radix32tree_insert (tree, ip, mask, 1);
 
575
        if (k == -1) {
 
576
                yyerror ("add_ip_radix: cannot insert ip to tree: %s, mask %X", inet_ntoa (ina), mask);
 
577
                return 0;
 
578
        }
 
579
        else if (k == 1) {
 
580
                yywarn ("add_ip_radix: ip %s, mask %X, value already exists", inet_ntoa (ina), mask);
 
581
        }
 
582
 
 
583
        return 1;
 
584
}
 
585
 
 
586
static void
 
587
add_hashed_header (const char *name, struct dkim_hash_entry **hash)
 
588
{
 
589
        struct dkim_hash_entry *new;
 
590
 
 
591
        new = malloc (sizeof (struct dkim_hash_entry));
 
592
        new->name = strdup (name);
 
593
        HASH_ADD_KEYPTR (hh, *hash, new->name, strlen (new->name), new);
 
594
}
 
595
 
 
596
void
 
597
init_defaults (struct config_file *cfg)
 
598
{
 
599
        LIST_INIT (&cfg->rules);
 
600
        cfg->wlist_rcpt_global = NULL;
 
601
        cfg->wlist_rcpt_limit = NULL;
 
602
        LIST_INIT (&cfg->bounce_addrs);
 
603
 
 
604
        cfg->clamav_connect_timeout = DEFAULT_CLAMAV_CONNECT_TIMEOUT;
 
605
        cfg->clamav_port_timeout = DEFAULT_CLAMAV_PORT_TIMEOUT;
 
606
        cfg->clamav_results_timeout = DEFAULT_CLAMAV_RESULTS_TIMEOUT;
 
607
        cfg->memcached_connect_timeout = DEFAULT_MEMCACHED_CONNECT_TIMEOUT;
 
608
        cfg->beanstalk_connect_timeout = DEFAULT_MEMCACHED_CONNECT_TIMEOUT;
 
609
        cfg->spamd_connect_timeout = DEFAULT_SPAMD_CONNECT_TIMEOUT;
 
610
        cfg->spamd_results_timeout = DEFAULT_SPAMD_RESULTS_TIMEOUT;
 
611
 
 
612
        cfg->clamav_error_time = DEFAULT_UPSTREAM_ERROR_TIME;
 
613
        cfg->clamav_dead_time = DEFAULT_UPSTREAM_DEAD_TIME;
 
614
        cfg->clamav_maxerrors = DEFAULT_UPSTREAM_MAXERRORS;
 
615
 
 
616
        cfg->spamd_error_time = DEFAULT_UPSTREAM_ERROR_TIME;
 
617
        cfg->spamd_dead_time = DEFAULT_UPSTREAM_DEAD_TIME;
 
618
        cfg->spamd_maxerrors = DEFAULT_UPSTREAM_MAXERRORS;
 
619
        cfg->spamd_reject_message = strdup (DEFAUL_SPAMD_REJECT);
 
620
        cfg->rspamd_metric = strdup (DEFAULT_RSPAMD_METRIC);
 
621
        cfg->spam_header = strdup (DEFAULT_SPAM_HEADER);
 
622
        cfg->spam_header_value = strdup (DEFAULT_SPAM_HEADER_VALUE);
 
623
 
 
624
        cfg->memcached_error_time = DEFAULT_UPSTREAM_ERROR_TIME;
 
625
        cfg->memcached_dead_time = DEFAULT_UPSTREAM_DEAD_TIME;
 
626
        cfg->memcached_maxerrors = DEFAULT_UPSTREAM_MAXERRORS;
 
627
        cfg->memcached_protocol = UDP_TEXT;
 
628
 
 
629
        cfg->beanstalk_error_time = DEFAULT_UPSTREAM_ERROR_TIME;
 
630
        cfg->beanstalk_dead_time = DEFAULT_UPSTREAM_DEAD_TIME;
 
631
        cfg->beanstalk_maxerrors = DEFAULT_UPSTREAM_MAXERRORS;
 
632
        cfg->beanstalk_protocol = BEANSTALK_TCP_TEXT;
 
633
        cfg->beanstalk_lifetime = DEFAULT_BEANSTALK_LIFETIME;
 
634
        cfg->copy_server = NULL;
 
635
        cfg->spam_server = NULL;
 
636
        
 
637
        cfg->grey_whitelist_tree = radix_tree_create ();
 
638
        cfg->limit_whitelist_tree = radix_tree_create ();
 
639
        cfg->spamd_whitelist = radix_tree_create ();
 
640
        cfg->greylisted_message = strdup (DEFAULT_GREYLISTED_MESSAGE);
 
641
 
 
642
        cfg->spf_domains = (char **) calloc (MAX_SPF_DOMAINS, sizeof (char *));
 
643
        cfg->awl_enable = 0;
 
644
        cfg->beanstalk_copy_prob = 100.0;
 
645
 
 
646
        cfg->spamd_soft_fail = 1;
 
647
        cfg->spamd_greylist = 1;
 
648
 
 
649
        cfg->dkim_auth_only = 1;
 
650
 
 
651
#if 0
 
652
        /* Init static defaults */
 
653
        white_from_abuse.addr = "abuse";
 
654
        white_from_abuse.len = sizeof ("abuse") - 1;
 
655
        white_from_postmaster.addr = "postmaster";
 
656
        white_from_postmaster.len = sizeof ("postmaster") - 1;
 
657
        LIST_INSERT_HEAD (&cfg->whitelist_static, &white_from_abuse, next);
 
658
        LIST_INSERT_HEAD (&cfg->whitelist_static, &white_from_postmaster, next);
 
659
#endif
 
660
 
 
661
#ifdef WITH_DKIM
 
662
        cfg->dkim_lib = dkim_init (NULL, NULL);
 
663
        /* Add recommended by rfc headers */
 
664
        add_hashed_header ("from", &cfg->headers);
 
665
        add_hashed_header ("sender", &cfg->headers);
 
666
        add_hashed_header ("reply-to", &cfg->headers);
 
667
        add_hashed_header ("subject", &cfg->headers);
 
668
        add_hashed_header ("date", &cfg->headers);
 
669
        add_hashed_header ("message-id", &cfg->headers);
 
670
        add_hashed_header ("to", &cfg->headers);
 
671
        add_hashed_header ("cc", &cfg->headers);
 
672
        add_hashed_header ("date", &cfg->headers);
 
673
        add_hashed_header ("mime-version", &cfg->headers);
 
674
        add_hashed_header ("content-type", &cfg->headers);
 
675
        add_hashed_header ("content-transfer-encoding", &cfg->headers);
 
676
        add_hashed_header ("resent-to", &cfg->headers);
 
677
        add_hashed_header ("resent-cc", &cfg->headers);
 
678
        add_hashed_header ("resent-from", &cfg->headers);
 
679
        add_hashed_header ("resent-sender", &cfg->headers);
 
680
        add_hashed_header ("resent-message-id", &cfg->headers);
 
681
        add_hashed_header ("in-reply-to", &cfg->headers);
 
682
        add_hashed_header ("references", &cfg->headers);
 
683
        add_hashed_header ("list-id", &cfg->headers);
 
684
        add_hashed_header ("list-owner", &cfg->headers);
 
685
        add_hashed_header ("list-unsubscribe", &cfg->headers);
 
686
        add_hashed_header ("list-subscribe", &cfg->headers);
 
687
        add_hashed_header ("list-post", &cfg->headers);
 
688
        /* TODO: make it configurable */
 
689
#endif
 
690
}
 
691
 
 
692
void
 
693
free_config (struct config_file *cfg)
 
694
{
 
695
        unsigned int i;
 
696
        struct rule *cur, *tmp_rule;
 
697
        struct condition *cond, *tmp_cond;
 
698
        struct addr_list_entry *addr_cur, *addr_tmp;
 
699
        struct whitelisted_rcpt_entry *rcpt_cur, *rcpt_tmp;
 
700
 
 
701
        if (cfg->pid_file) {
 
702
                free (cfg->pid_file);
 
703
        }
 
704
        if (cfg->temp_dir) {
 
705
                free (cfg->temp_dir);
 
706
        }
 
707
        if (cfg->sock_cred) {
 
708
                free (cfg->sock_cred);
 
709
        }
 
710
 
 
711
        if (cfg->spf_domains) {
 
712
                for (i = 0; i < MAX_SPF_DOMAINS; i++) {
 
713
                        free (cfg->spf_domains[i]);
 
714
                }
 
715
                free (cfg->spf_domains);
 
716
        }
 
717
 
 
718
        if (cfg->special_mid_re) {
 
719
                pcre_free (cfg->special_mid_re);
 
720
        }
 
721
        
 
722
        for (i = 0; i < cfg->clamav_servers_num; i++) {
 
723
                free (cfg->clamav_servers[i].name);
 
724
        }
 
725
        for (i = 0; i < cfg->spamd_servers_num; i++) {
 
726
                free (cfg->spamd_servers[i].name);
 
727
        }
 
728
        /* Free rules list */
 
729
        LIST_FOREACH_SAFE (cur, &cfg->rules, next, tmp_rule) {
 
730
                LIST_FOREACH_SAFE (cond, cur->conditions, next, tmp_cond) {
 
731
                        if (!cond->args[0].empty) {
 
732
                                if (cond->args[0].re != NULL) {
 
733
                                        pcre_free (cond->args[0].re);
 
734
                                }
 
735
                                if (cond->args[0].src != NULL) {
 
736
                                        free (cond->args[0].src);
 
737
                                }
 
738
                        }
 
739
                        if (!cond->args[1].empty) {
 
740
                                if (cond->args[1].re != NULL) {
 
741
                                        pcre_free (cond->args[1].re);
 
742
                                }
 
743
                                if (cond->args[1].src != NULL) {
 
744
                                        free (cond->args[1].src);
 
745
                                }
 
746
                        }
 
747
                        LIST_REMOVE (cond, next);
 
748
                        free (cond);
 
749
                }
 
750
                if (cur->act->message) {
 
751
                        free (cur->act->message);
 
752
                }
 
753
                free (cur->act);
 
754
                LIST_REMOVE (cur, next);
 
755
                free (cur);
 
756
        }
 
757
        /* Free whitelists and bounce list*/
 
758
        HASH_ITER (hh, cfg->wlist_rcpt_global, rcpt_cur, rcpt_tmp) {
 
759
                HASH_DEL (cfg->wlist_rcpt_global, rcpt_cur);
 
760
                free (rcpt_cur->rcpt);
 
761
                free (rcpt_cur);
 
762
        }
 
763
        HASH_ITER (hh, cfg->wlist_rcpt_limit, rcpt_cur, rcpt_tmp) {
 
764
                HASH_DEL (cfg->wlist_rcpt_limit, rcpt_cur);
 
765
                free (rcpt_cur->rcpt);
 
766
                free (rcpt_cur);
 
767
        }
 
768
        LIST_FOREACH_SAFE (addr_cur, &cfg->bounce_addrs, next, addr_tmp) {
 
769
                if (addr_cur->addr) {
 
770
                        free (addr_cur->addr);
 
771
                }
 
772
                LIST_REMOVE (addr_cur, next);
 
773
                free (addr_cur);
 
774
        }
 
775
 
 
776
        radix_tree_free (cfg->grey_whitelist_tree);
 
777
        free (cfg->grey_whitelist_tree);
 
778
        
 
779
        radix_tree_free (cfg->spamd_whitelist);
 
780
        free (cfg->spamd_whitelist);
 
781
 
 
782
        radix_tree_free (cfg->limit_whitelist_tree);
 
783
        free (cfg->limit_whitelist_tree);
 
784
        
 
785
        if (cfg->spamd_reject_message) {
 
786
                free (cfg->spamd_reject_message);
 
787
        }
 
788
        if (cfg->rspamd_metric) {
 
789
                free (cfg->rspamd_metric);
 
790
        }
 
791
        if (cfg->spam_header) {
 
792
                free (cfg->spam_header);
 
793
        }
 
794
        if (cfg->spam_header_value) {
 
795
                free (cfg->spam_header_value);
 
796
        }
 
797
        if (cfg->id_prefix) {
 
798
                free (cfg->id_prefix);
 
799
        }
 
800
        if (cfg->grey_prefix) {
 
801
                free (cfg->grey_prefix);
 
802
        }
 
803
        if (cfg->white_prefix) {
 
804
                free (cfg->white_prefix);
 
805
        }
 
806
        if (cfg->copy_server) {
 
807
                free (cfg->copy_server);
 
808
        }
 
809
        if (cfg->spam_server) {
 
810
                free (cfg->spam_server);
 
811
        }
 
812
        if (cfg->greylisted_message) {
 
813
                free (cfg->greylisted_message);
 
814
        }
 
815
 
 
816
        if (cfg->awl_enable && cfg->awl_hash != NULL) {
 
817
                free (cfg->awl_hash->pool);
 
818
                free (cfg->awl_hash);
 
819
        }
 
820
 
 
821
 
 
822
#ifdef WITH_DKIM
 
823
        struct dkim_hash_entry *curh, *tmph;
 
824
        struct dkim_domain_entry *curd, *tmpd;
 
825
 
 
826
        if (cfg->dkim_lib) {
 
827
                dkim_close (cfg->dkim_lib);
 
828
        }
 
829
        HASH_ITER (hh, cfg->headers, curh, tmph) {
 
830
                HASH_DEL (cfg->headers, curh);  /* delete; users advances to next */
 
831
                free (curh->name);
 
832
                free (curh);
 
833
        }
 
834
        HASH_ITER (hh, cfg->dkim_domains, curd, tmpd) {
 
835
                HASH_DEL (cfg->dkim_domains, curd);  /* delete; users advances to next */
 
836
                if (curd->key != MAP_FAILED && curd->key != NULL) {
 
837
                        munmap (curd->key, curd->keylen);
 
838
                }
 
839
                if (curd->domain) {
 
840
                        free (curd->domain);
 
841
                }
 
842
                if (curd->selector) {
 
843
                        free (curd->selector);
 
844
                }
 
845
                if (curd->keyfile) {
 
846
                        free (curd->keyfile);
 
847
                }
 
848
                free (curd);
 
849
        }
 
850
#endif
 
851
}
 
852
 
 
853
void
 
854
add_rcpt_whitelist (struct config_file *cfg, const char *rcpt, int is_global)
 
855
{
 
856
        struct whitelisted_rcpt_entry *t;
 
857
        t = (struct whitelisted_rcpt_entry *)malloc (sizeof (struct whitelisted_rcpt_entry));
 
858
        if (*rcpt == '@') {
 
859
                t->type = WLIST_RCPT_DOMAIN;
 
860
                rcpt ++;
 
861
        }
 
862
        else if (strchr (rcpt, '@') != NULL) {
 
863
                t->type = WLIST_RCPT_USERDOMAIN;
 
864
        }
 
865
        else {
 
866
                t->type = WLIST_RCPT_USER;
 
867
        }
 
868
        t->rcpt = strdup (rcpt);
 
869
        t->len = strlen (t->rcpt);
 
870
        if (is_global) {
 
871
                HASH_ADD_KEYPTR (hh, cfg->wlist_rcpt_global, t->rcpt, t->len, t);
 
872
        }
 
873
        else {
 
874
                HASH_ADD_KEYPTR (hh, cfg->wlist_rcpt_limit, t->rcpt, t->len, t);
 
875
        }
 
876
}
 
877
 
 
878
int
 
879
is_whitelisted_rcpt (struct config_file *cfg, const char *str, int is_global)
 
880
{
 
881
        int len;
 
882
        struct whitelisted_rcpt_entry *entry, *list;
 
883
        char rcptbuf[ADDRLEN + 1], *domain;
 
884
 
 
885
        if (*str == '<') {
 
886
                str ++;
 
887
        }
 
888
 
 
889
        len = strcspn (str, ">");
 
890
        rmilter_strlcpy (rcptbuf, str, MIN (len + 1, sizeof (rcptbuf)));
 
891
        if (len > 0) {
 
892
                if (is_global) {
 
893
                        list = cfg->wlist_rcpt_global;
 
894
                }
 
895
                else {
 
896
                        list = cfg->wlist_rcpt_limit;
 
897
                }
 
898
                /* Initially search for userdomain */
 
899
                HASH_FIND_STR (list, rcptbuf, entry, strncasecmp);
 
900
                if (entry != NULL && entry->type == WLIST_RCPT_USERDOMAIN) {
 
901
                        return 1;
 
902
                }
 
903
                domain = strchr (rcptbuf, '@');
 
904
                if (domain == NULL && entry != NULL && entry->type == WLIST_RCPT_USER) {
 
905
                        return 1;
 
906
                }
 
907
                /* Search for user */
 
908
                if (domain != NULL) {
 
909
                        *domain = '\0';
 
910
                }
 
911
                HASH_FIND_STR (list, rcptbuf, entry, strncasecmp);
 
912
                if (entry != NULL && entry->type == WLIST_RCPT_USER) {
 
913
                        return 1;
 
914
                }
 
915
                if (domain != NULL) {
 
916
                        /* Search for domain */
 
917
                        domain ++;
 
918
                        HASH_FIND_STR (list, domain, entry, strncasecmp);
 
919
                        if (entry != NULL && entry->type == WLIST_RCPT_DOMAIN) {
 
920
                                return 1;
 
921
                        }
 
922
                }
 
923
        }
 
924
 
 
925
        return 0;
 
926
}
 
927
 
 
928
/*
 
929
 * vi:ts=4
 
930
 */