masqmail

view src/conf.c @ 378:5781ba87df95

Removed ident. This had been discussed on the mailing list in Oct 2011. Ident is hardly useful in typical setups for masqmail. Probably Oliver had used it in his setup; that would make sense. Now, I know of nobody who needs it.
author markus schnalke <meillo@marmaro.de>
date Sat, 14 Jan 2012 21:36:58 +0100
parents b27f66555ba8
children a408411ff8df
line source
1 /*
2 ** MasqMail
3 ** Copyright (C) 1999-2001 Oliver Kurth
4 ** Copyright (C) 2010 markus schnalke <meillo@marmaro.de>
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
21 #include <pwd.h>
22 #include <grp.h>
24 #include "masqmail.h"
26 masqmail_conf conf;
28 void
29 init_conf()
30 {
31 struct passwd *passwd;
32 struct group *group;
34 memset(&conf, 0, sizeof(masqmail_conf));
36 conf.orig_uid = getuid();
37 conf.orig_gid = getgid();
39 if ((passwd = getpwnam(DEF_MAIL_USER)))
40 conf.mail_uid = passwd->pw_uid;
41 else {
42 fprintf(stderr, "user %s not found! (terminating)\n", DEF_MAIL_USER);
43 exit(1);
44 }
45 if ((group = getgrnam(DEF_MAIL_GROUP)))
46 conf.mail_gid = group->gr_gid;
47 else {
48 fprintf(stderr, "group %s not found! (terminating)\n", DEF_MAIL_GROUP);
49 exit(1);
50 }
51 }
53 static gchar *true_strings[] = {
54 "yes", "on", "true", NULL
55 };
57 static gchar *false_strings[] = {
58 "no", "off", "false", NULL
59 };
61 static gboolean
62 parse_boolean(gchar *rval)
63 {
64 gchar **str;
66 DEBUG(9) fprintf(stderr, "parse_boolean: %s\n", rval);
68 str = true_strings;
69 while (*str) {
70 if (strncasecmp(*str, rval, strlen(*str)) == 0)
71 return TRUE;
72 str++;
73 }
75 str = false_strings;
76 while (*str) {
77 if (strncasecmp(*str, rval, strlen(*str)) == 0)
78 return FALSE;
79 str++;
80 }
82 fprintf(stderr, "cannot parse value '%s'\n", rval);
83 exit(1);
84 }
86 /* make a list from each line in a file */
87 static GList*
88 parse_list_file(gchar *fname)
89 {
90 GList *list = NULL;
91 FILE *fptr;
93 if ((fptr = fopen(fname, "rt")) == NULL) {
94 logwrite(LOG_ALERT, "could not open %s for reading: %s\n", fname, strerror(errno));
95 exit(1);
96 }
98 gchar buf[256];
100 while (!feof(fptr)) {
101 fgets(buf, 255, fptr);
102 if (buf[0] && (buf[0] != '#') && (buf[0] != '\n')) {
103 g_strchomp(buf);
104 DEBUG(9) fprintf(stderr,"parse_list_file: item = %s\n", buf);
105 list = g_list_append(list, g_strdup(buf));
106 }
107 }
108 fclose(fptr);
110 return list;
111 }
113 /* given a semicolon separated string, this function makes a GList out of it. */
114 GList*
115 parse_list(gchar *line, gboolean read_file)
116 {
117 GList *list = NULL;
118 gchar buf[256];
119 gchar *p, *q;
121 DEBUG(9) fprintf(stderr, "parsing list %s, file?:%d\n", line, read_file);
123 p = line;
124 while (*p != '\0') {
125 q = buf;
127 while (*p && (*p != ';') && (q < buf + 255))
128 *(q++) = *(p++);
129 *q = '\0';
131 if ((buf[0] == '/') && (read_file))
132 /* item is a filename, include its contents */
133 list = g_list_concat(list, parse_list_file(buf));
134 else
135 /* just a normal item */
136 list = g_list_append(list, g_strdup(buf));
138 DEBUG(9) fprintf(stderr, "item = %s\n", buf);
140 if (*p)
141 p++;
142 }
143 return list;
144 }
146 /*
147 ** Split the addrs at '@' into local_part and domain. Without an '@'
148 ** everything is local_part. Create address structs, which are put into a
149 ** list and returned. This funktion is used for lists of addrs containing
150 ** globbing chars (* and ?). We don't need valid RFC821 addresses here,
151 ** just patterns to match against.
152 */
153 static GList*
154 parse_address_glob_list(gchar *line, gboolean read_file)
155 {
156 GList *plain_list = parse_list(line, read_file);
157 GList *node;
158 GList *list = NULL;
160 foreach(plain_list, node) {
161 gchar *item = (gchar *) (node->data);
162 char *at;
163 char *p;
164 address *addr = calloc(1, sizeof(address));
166 for (p=item+strlen(item)-1; isspace(*p) || *p=='>'; p--) {
167 *p = '\0';
168 }
169 for (p=item; isspace(*p) || *p=='<'; p++) {
170 }
172 addr->address = strdup(p);
173 at = strrchr(p, '@');
174 if (at) {
175 *at = '\0';
176 addr->local_part = strdup(p);
177 addr->domain = strdup(at+1);
178 } else {
179 addr->local_part = strdup(p);
180 /* No `@', thus any domain is okay. */
181 addr->domain = "*";
182 }
183 list = g_list_append(list, addr);
184 DEBUG(6) debugf("parse_address_glob_list: read pattern `%s' `%s'\n",
185 addr->local_part, addr->domain);
186 g_free(item);
187 }
188 g_list_free(plain_list);
189 return list;
190 }
192 static GList*
193 parse_resolve_list(gchar *line)
194 {
195 GList *list;
196 GList *list_node;
197 GList *res_list = NULL;
199 list = parse_list(line, FALSE);
200 if (!list) {
201 return NULL;
202 }
204 foreach(list, list_node) {
205 gchar *item = (gchar *) (list_node->data);
206 if (strcmp(item, "byname") == 0) {
207 res_list = g_list_append(res_list, resolve_byname);
208 #ifdef ENABLE_RESOLVER
209 } else if (strcmp(item, "dns_a") == 0) {
210 res_list = g_list_append(res_list, resolve_dns_a);
211 } else if (strcmp(item, "dns_mx") == 0) {
212 res_list = g_list_append(res_list, resolve_dns_mx);
213 #endif
214 } else {
215 logwrite(LOG_ALERT, "unknown resolver %s\n", item);
216 exit(1);
217 }
218 g_free(item);
219 }
220 g_list_free(list);
221 return res_list;
222 }
224 static interface*
225 parse_interface(gchar *line, gint def_port)
226 {
227 gchar buf[256];
228 gchar *p, *q;
229 interface *iface;
231 DEBUG(9) fprintf(stderr, "parse_interface: %s\n", line);
233 p = line;
234 q = buf;
235 while ((*p != '\0') && (*p != ':') && (q < buf + 255))
236 *(q++) = *(p++);
237 *q = '\0';
239 iface = g_malloc(sizeof(interface));
240 iface->address = g_strdup(buf);
242 if (*p) {
243 p++;
244 iface->port = atoi(p);
245 } else
246 iface->port = def_port;
247 DEBUG(9) fprintf(stderr,"rval=%s, address:port=%s:%i\n",line, iface->address, iface->port);
249 return iface;
250 }
252 static gboolean
253 eat_comments(FILE *in)
254 {
255 gint c;
257 for (c = fgetc(in); (c == '#' || isspace(c)) && c != EOF;
258 c = fgetc(in)) {
259 if (c == '#') {
260 gint c;
261 for (c = fgetc(in); (c != '\n') && (c != EOF); c = fgetc(in));
262 }
263 }
264 if (c == EOF)
265 return FALSE;
266 ungetc(c, in);
267 return TRUE;
268 }
270 /* after parsing, eat trailing character until LF */
271 static gboolean
272 eat_line_trailing(FILE *in)
273 {
274 gint c;
276 for (c = fgetc(in); c != EOF && c != '\n'; c = fgetc(in));
277 if (c == EOF)
278 return FALSE;
279 return TRUE;
280 }
282 static gboolean
283 eat_spaces(FILE *in)
284 {
285 gint c;
287 for (c = fgetc(in); c != EOF && isspace(c); c = fgetc(in)) {
288 /* empty */
289 }
290 if (c == EOF)
291 return FALSE;
292 ungetc(c, in);
293 return TRUE;
294 }
296 static gboolean
297 read_lval(FILE *in, gchar *buf, gint size)
298 {
299 gint c;
300 gchar *ptr = buf;
302 DEBUG(9) fprintf(stderr, "read_lval()\n");
304 if (!eat_spaces(in))
305 return FALSE;
307 c = fgetc(in);
308 DEBUG(9) fprintf(stderr, "read_lval() 2\n");
309 while ((isalnum(c) || c == '_' || c == '-' || c == '.')
310 && (ptr < buf + size - 1)
311 && (c != EOF)) {
312 *ptr = c;
313 ptr++;
314 c = fgetc(in);
315 }
316 *ptr = '\0';
317 ungetc(c, in);
319 if (c == EOF) {
320 fprintf(stderr, "unexpected EOF after %s\n", buf);
321 return FALSE;
322 } else if (ptr >= buf + size - 1) {
323 fprintf(stderr, "lval too long\n");
324 }
326 eat_spaces(in);
328 DEBUG(9) fprintf(stderr, "lval = %s\n", buf);
330 return buf[0] != '\0';
331 }
333 static gboolean
334 read_rval(FILE *in, gchar *buf, gint size)
335 {
336 gint c;
337 gchar *ptr = buf;
339 DEBUG(9) fprintf(stderr, "read_rval()\n");
341 if (!eat_spaces(in))
342 return FALSE;
344 c = fgetc(in);
345 if (c != '\"') {
346 while ((isalnum(c) || c == '_' || c == '-' || c == '.'
347 || c == '/' || c == '@' || c == ';' || c == ':')
348 && (ptr < buf + size - 1)
349 && (c != EOF)) {
350 *ptr = c;
351 ptr++;
352 c = fgetc(in);
353 }
354 *ptr = '\0';
355 ungetc(c, in);
356 } else {
357 gboolean escape = FALSE;
358 c = fgetc(in);
359 while (((c != '\"') || escape) && (ptr < buf + size - 1)) {
360 if (c != '\n') { /* ignore line breaks */
361 if ((c == '\\') && (!escape)) {
362 escape = TRUE;
363 } else {
364 *ptr = c;
365 ptr++;
366 escape = FALSE;
367 }
368 }
369 c = fgetc(in);
370 }
371 *ptr = '\0';
372 }
374 eat_line_trailing(in);
376 DEBUG(9) fprintf(stderr, "rval = %s\n", buf);
378 return TRUE;
379 }
381 static gboolean
382 read_statement(FILE *in, gchar *lval, gint lsize, gchar *rval, gint rsize)
383 {
384 gint c;
386 DEBUG(9) fprintf(stderr, "read_statement()\n");
388 /* eat comments and empty lines: */
389 if (!eat_comments(in))
390 return FALSE;
392 if (!read_lval(in, lval, lsize)) {
393 return FALSE;
394 }
396 DEBUG(9) fprintf(stderr, " lval = %s\n", lval);
397 if ((c = fgetc(in) == '=')) {
398 if (read_rval(in, rval, rsize)) {
399 DEBUG(9) fprintf(stderr, " rval = %s\n", rval);
400 return TRUE;
401 }
402 } else {
403 DEBUG(9) fprintf(stderr," '=' expected after %s, char was '%c'\n", lval, c);
404 fprintf(stderr, "'=' expected after %s, char was '%c'\n", lval, c);
405 }
406 return FALSE;
407 }
409 gboolean
410 read_conf(gchar *filename)
411 {
412 FILE *in;
414 conf.log_max_pri = 7;
415 conf.do_relay = TRUE;
416 conf.localpartcmp = strcmp;
417 conf.max_defer_time = 86400 * 4; /* 4 days */
418 conf.max_msg_size = 0; /* no limit on msg size */
419 conf.spool_dir = SPOOL_DIR;
420 conf.mail_dir = "/var/mail";
421 conf.listen_addresses = g_list_append(NULL, parse_interface("localhost", 25));
423 if ((in = fopen(filename, "r")) == NULL) {
424 logwrite(LOG_ALERT, "could not open config file %s: %s\n", filename, strerror(errno));
425 return FALSE;
426 }
428 gchar lval[256], rval[2048];
429 while (read_statement(in, lval, 256, rval, 2048)) {
430 DEBUG(9) fprintf(stderr,"read_conf(): lval=%s\n", lval);
431 if (strcmp(lval, "debug_level") == 0)
432 conf.debug_level = atoi(rval);
433 else if (strcmp(lval, "run_as_user") == 0) {
434 if (!conf.run_as_user) /* you should not be able to reset that flag */
435 conf.run_as_user = parse_boolean(rval);
436 } else if (strcmp(lval, "use_syslog") == 0)
437 conf.use_syslog = parse_boolean(rval);
438 else if (strcmp(lval, "mail_dir") == 0)
439 conf.mail_dir = g_strdup(rval);
440 else if (strcmp(lval, "lock_dir") == 0)
441 conf.lock_dir = g_strdup(rval);
442 else if (strcmp(lval, "spool_dir") == 0)
443 conf.spool_dir = g_strdup(rval);
444 else if (strcmp(lval, "log_dir") == 0)
445 conf.log_dir = g_strdup(rval);
446 else if (strcmp(lval, "host_name") == 0) {
447 if (rval[0] != '/')
448 conf.host_name = g_strdup(rval);
449 else {
450 char buf[256];
451 FILE *fptr = fopen(rval, "rt");
452 if (!fptr) {
453 logwrite(LOG_ALERT, "could not open %s: %s\n", rval, strerror(errno));
454 return FALSE;
455 }
456 fgets(buf, 255, fptr);
457 g_strchomp(buf);
458 conf.host_name = g_strdup(buf);
459 fclose(fptr);
460 }
461 } else if (strcmp(lval, "local_hosts") == 0)
462 conf.local_hosts = parse_list(rval, FALSE);
463 else if (strcmp(lval, "local_addresses") == 0)
464 conf.local_addresses = parse_list(rval, TRUE);
465 else if (strcmp(lval, "not_local_addresses") == 0)
466 conf.not_local_addresses = parse_list(rval, TRUE);
467 else if (strcmp(lval, "do_save_envelope_to") == 0)
468 conf.do_save_envelope_to = parse_boolean(rval);
469 else if (strcmp(lval, "defer_all") == 0)
470 conf.defer_all = parse_boolean(rval);
471 else if (strcmp(lval, "do_relay") == 0)
472 conf.do_relay = parse_boolean(rval);
473 else if (strcmp(lval, "alias_file") == 0) {
474 conf.alias_file = g_strdup(rval);
475 } else if (strcmp(lval, "caseless_matching") == 0) {
476 conf.localpartcmp = parse_boolean(rval) ? strcasecmp : strcmp;
477 } else if (strcmp(lval, "mbox_default") == 0) {
478 conf.mbox_default = g_strdup(rval);
479 } else if (strcmp(lval, "mbox_users") == 0) {
480 conf.mbox_users = parse_list(rval, TRUE);
481 } else if (strcmp(lval, "mda_users") == 0) {
482 conf.mda_users = parse_list(rval, TRUE);
483 } else if (strcmp(lval, "mda") == 0) {
484 conf.mda = g_strdup(rval);
485 } else if (strcmp(lval, "mda_fromline") == 0) {
486 conf.mda_fromline = parse_boolean(rval);
487 } else if (strcmp(lval, "mda_fromhack") == 0) {
488 conf.mda_fromhack = parse_boolean(rval);
489 } else if (strcmp(lval, "pipe_fromline") == 0) {
490 conf.pipe_fromline = parse_boolean(rval);
491 } else if (strcmp(lval, "pipe_fromhack") == 0) {
492 conf.pipe_fromhack = parse_boolean(rval);
493 } else if (strcmp(lval, "listen_addresses") == 0) {
494 GList *node;
495 GList *tmp_list = parse_list(rval, FALSE);
497 conf.listen_addresses = NULL;
498 foreach(tmp_list, node) {
499 conf.listen_addresses = g_list_append(conf.listen_addresses, parse_interface((gchar *) (node-> data), 25));
500 g_free(node->data);
501 }
502 g_list_free(tmp_list);
503 } else if (strncmp(lval, "query_routes.", 13) == 0) {
504 GList *file_list = parse_list(rval, FALSE);
505 table_pair *pair = create_pair(lval+13, file_list);
506 conf.query_routes = g_list_append(conf.query_routes, pair);
507 } else if (strcmp(lval, "permanent_routes") == 0) {
508 conf.perma_routes = parse_list(rval, FALSE);
509 } else if (strcmp(lval, "online_query") == 0)
510 conf.online_query = g_strdup(rval);
511 else if (strcmp(lval, "do_queue") == 0)
512 conf.do_queue = parse_boolean(rval);
513 else if (strcmp(lval, "errmsg_file") == 0)
514 conf.errmsg_file = g_strdup(rval);
515 else if (strcmp(lval, "warnmsg_file") == 0)
516 conf.warnmsg_file = g_strdup(rval);
517 else if (strcmp(lval, "warn_intervals") == 0)
518 conf.warn_intervals = parse_list(rval, FALSE);
519 else if (strcmp(lval, "max_defer_time") == 0) {
520 gint ival = time_interval(rval);
521 if (ival < 0)
522 logwrite(LOG_WARNING, "invalid time interval for 'max_defer_time': %s\n", rval);
523 else
524 conf.max_defer_time = ival;
525 } else if (strcmp(lval, "log_user") == 0)
526 conf.log_user = g_strdup(rval);
527 else if(strcmp(lval, "max_msg_size") == 0) {
528 conf.max_msg_size = atol(rval);
529 DEBUG(9) fprintf(stderr,"rval=%s, conf.max_msg_size=%ld\n",
530 rval, conf.max_msg_size);
531 }
532 else
533 logwrite(LOG_WARNING, "var '%s' not (yet) known, ignored\n", lval);
534 }
535 fclose(in);
537 if (!conf.host_name) {
538 logwrite(LOG_ALERT, "`host_name' MUST be set in masqmail.conf. See man page\n");
539 return FALSE;
540 }
542 if (conf.errmsg_file == NULL)
543 conf.errmsg_file = g_strdup(DATA_DIR "/tpl/failmsg.tpl");
544 if (conf.warnmsg_file == NULL)
545 conf.warnmsg_file = g_strdup(DATA_DIR "/tpl/warnmsg.tpl");
547 if (conf.lock_dir == NULL)
548 conf.lock_dir = g_strdup_printf("%s/lock/", conf.spool_dir);
550 if (conf.mbox_default == NULL)
551 conf.mbox_default = g_strdup("mbox");
553 if (conf.warn_intervals == NULL)
554 conf.warn_intervals = parse_list("1h;4h;8h;1d;2d;3d", FALSE);
556 if (!conf.local_hosts) {
557 char *shortname = strdup(conf.host_name);
558 char *p = strchr(shortname, '.');
559 if (p) {
560 *p = '\0';
561 }
562 /* we don't care if shortname and conf.host_name are the same */
563 char *local_hosts_str = g_strdup_printf("localhost;%s;%s", shortname, conf.host_name);
564 conf.local_hosts = parse_list(local_hosts_str, FALSE);
565 free(shortname);
566 free(local_hosts_str);
567 }
570 return TRUE;
571 }
573 connect_route*
574 read_route(gchar *filename, gboolean is_perma)
575 {
576 gboolean ok = FALSE;
577 FILE *in;
579 connect_route *route = g_malloc(sizeof(connect_route));
580 memset(route, 0, sizeof(connect_route));
582 DEBUG(5) debugf("read_route, filename = %s\n", filename);
584 route->filename = g_strdup(filename);
585 route->name = route->filename; /* quick hack */
587 route->expand_h_sender_address = TRUE;
589 route->is_perma = is_perma;
591 route->do_pipelining = TRUE;
593 if ((in = fopen(route->filename, "r")) == NULL) {
594 logwrite(LOG_ALERT, "could not open route file %s: %s\n", route->filename, strerror(errno));
595 g_free(route);
596 return NULL;
597 }
599 gchar lval[256], rval[2048];
600 while (read_statement(in, lval, 256, rval, 2048)) {
601 if (strcmp(lval, "mail_host") == 0)
602 route->mail_host = parse_interface(rval, 25);
603 else if (strcmp(lval, "helo_name") == 0)
604 route->helo_name = g_strdup(rval);
605 else if (strcmp(lval, "wrapper") == 0)
606 route->wrapper = g_strdup(rval);
607 else if (strcmp(lval, "connect_error_fail") == 0)
608 route->connect_error_fail = parse_boolean(rval);
609 else if (strcmp(lval, "do_correct_helo") == 0)
610 route->do_correct_helo = parse_boolean(rval);
611 else if (strcmp(lval, "instant_helo") == 0)
612 route->instant_helo = parse_boolean(rval);
613 else if (strcmp(lval, "do_pipelining") == 0)
614 route->do_pipelining = parse_boolean(rval);
616 else if (strcmp(lval, "allowed_senders") == 0)
617 route->allowed_senders = parse_address_glob_list(rval, TRUE);
618 else if (strcmp(lval, "denied_senders") == 0)
619 route->denied_senders = parse_address_glob_list(rval, TRUE);
620 else if (strcmp(lval, "allowed_recipients") == 0)
621 route->allowed_recipients = parse_address_glob_list(rval, TRUE);
622 else if (strcmp(lval, "denied_recipients") == 0)
623 route->denied_recipients = parse_address_glob_list(rval, TRUE);
625 else if (strcmp(lval, "set_h_from_domain") == 0)
626 route->set_h_from_domain = g_strdup(rval);
627 else if (strcmp(lval, "set_h_reply_to_domain") == 0)
628 route->set_h_reply_to_domain = g_strdup(rval);
629 else if (strcmp(lval, "set_return_path_domain") == 0)
630 route->set_return_path_domain = g_strdup(rval);
631 else if (strcmp(lval, "map_return_path_addresses") == 0) {
632 GList *node, *list;
634 list = parse_list(rval, TRUE);
635 foreach(list, node) {
636 gchar *item = (gchar *) (node->data);
637 table_pair *pair = parse_table_pair(item, ':');
638 address *addr = create_address((gchar *) (pair->value), TRUE);
639 g_free(pair->value);
640 pair->value = (gpointer *) addr;
641 route->map_return_path_addresses = g_list_append(route->map_return_path_addresses, pair);
642 g_free(item);
643 }
644 g_list_free(list);
645 } else if (strcmp(lval, "map_h_from_addresses") == 0) {
646 GList *list, *node;
648 list = parse_list(rval, TRUE);
649 foreach(list, node) {
650 gchar *item = (gchar *) (node->data);
651 table_pair *pair = parse_table_pair(item, ':');
652 route->map_h_from_addresses = g_list_append(route->map_h_from_addresses, pair);
653 g_free(item);
654 }
655 g_list_free(list);
656 } else if (strcmp(lval, "map_h_reply_to_addresses") == 0) {
657 GList *list, *node;
659 list = parse_list(rval, TRUE);
660 foreach(list, node) {
661 gchar *item = (gchar *) (node->data);
662 table_pair *pair = parse_table_pair(item, ':');
663 route->map_h_reply_to_addresses = g_list_append(route->map_h_reply_to_addresses, pair);
664 g_free(item);
665 }
666 g_list_free(list);
667 } else if (strcmp(lval, "map_h_mail_followup_to_addresses") == 0) {
668 GList *list, *node;
670 list = parse_list(rval, TRUE);
671 foreach(list, node) {
672 gchar *item = (gchar *) (node->data);
673 table_pair *pair = parse_table_pair(item, ':');
674 route->map_h_mail_followup_to_addresses = g_list_append(route->map_h_mail_followup_to_addresses, pair);
675 g_free(item);
676 }
677 g_list_free(list);
678 } else if (strcmp(lval, "expand_h_sender_domain") == 0) {
679 route->expand_h_sender_domain = parse_boolean(rval);
680 } else if (strcmp(lval, "expand_h_sender_address") == 0) {
681 route->expand_h_sender_address = parse_boolean(rval);
682 } else if (strcmp(lval, "resolve_list") == 0)
683 route->resolve_list = parse_resolve_list(rval);
684 else if (strcmp(lval, "do_ssl") == 0) {
685 /* we ignore this. This option is used by sqilconf */
686 ;
687 }
688 #ifdef ENABLE_AUTH
689 else if (strcmp(lval, "auth_name") == 0) {
690 route->auth_name = g_strdup(rval);
691 } else if (strcmp(lval, "auth_login") == 0) {
692 route->auth_login = g_strdup(rval);
693 } else if (strcmp(lval, "auth_secret") == 0) {
694 route->auth_secret = g_strdup(rval);
695 }
696 #else
697 else if ((strcmp(lval, "auth_name") == 0)
698 || (strcmp(lval, "auth_login") == 0)
699 || (strcmp(lval, "auth_secret") == 0)) {
700 logwrite(LOG_WARNING, "%s ignored: not compiled with auth support.\n", lval);
701 }
702 #endif
703 else if (strcmp(lval, "pipe") == 0) {
704 route->pipe = g_strdup(rval);
705 } else if (strcmp(lval, "pipe_fromline") == 0) {
706 route->pipe_fromline = parse_boolean(rval);
707 } else if (strcmp(lval, "pipe_fromhack") == 0) {
708 route->pipe_fromhack = parse_boolean(rval);
709 } else if (strcmp(lval, "last_route") == 0) {
710 route->last_route = parse_boolean(rval);
711 } else
712 logwrite(LOG_WARNING, "var '%s' not (yet) known, ignored\n", lval);
713 }
715 if (!route->resolve_list) {
716 #ifdef ENABLE_RESOLVER
717 route->resolve_list = g_list_append(route->resolve_list, resolve_dns_mx);
718 route->resolve_list = g_list_append(route->resolve_list, resolve_dns_a);
719 #endif
720 route->resolve_list = g_list_append(route->resolve_list, resolve_byname);
721 }
722 fclose(in);
723 ok = TRUE;
725 /* warn user about misconfigurations: */
726 if ((route->map_h_from_addresses != NULL) && (route->set_h_from_domain != NULL)) {
727 logwrite(LOG_WARNING, "'map_h_from_addresses' overrides 'set_h_from_domain'\n");
728 g_free(route->set_h_from_domain);
729 route->set_h_from_domain = NULL;
730 }
731 if ((route->map_h_reply_to_addresses != NULL) && (route->set_h_reply_to_domain != NULL)) {
732 logwrite(LOG_WARNING, "'map_h_reply_to_addresses' overrides 'set_h_reply_to_domain'\n");
733 g_free(route->set_h_reply_to_domain);
734 route->set_h_reply_to_domain = NULL;
735 }
737 if (!ok) {
738 g_free(route);
739 route = NULL;
740 }
742 return route;
743 }
745 static void
746 _g_list_free_all(GList *list)
747 {
748 GList *node;
749 if (list) {
750 foreach(list, node)
751 g_free(node->data);
752 g_list_free(list);
753 }
754 }
756 void
757 destroy_route(connect_route *r)
758 {
759 if (r->filename)
760 g_free(r->filename);
761 if (r->mail_host) {
762 g_free(r->mail_host->address);
763 g_free(r->mail_host);
764 }
765 if (r->wrapper)
766 g_free(r->wrapper);
767 if (r->helo_name)
768 g_free(r->helo_name);
769 _g_list_free_all(r->allowed_senders);
770 _g_list_free_all(r->denied_senders);
771 _g_list_free_all(r->allowed_recipients);
772 _g_list_free_all(r->denied_recipients);
773 if (r->set_h_from_domain)
774 g_free(r->set_h_from_domain);
775 if (r->set_h_reply_to_domain)
776 g_free(r->set_h_reply_to_domain);
777 if (r->set_return_path_domain)
778 g_free(r->set_return_path_domain);
779 if (r->map_h_reply_to_addresses)
780 destroy_table(r->map_h_reply_to_addresses);
781 if (r->resolve_list)
782 g_list_free(r->resolve_list);
783 #ifdef ENABLE_AUTH
784 if (r->auth_name)
785 g_free(r->auth_name);
786 if (r->auth_login)
787 g_free(r->auth_login);
788 if (r->auth_secret)
789 g_free(r->auth_secret);
790 #endif
791 if (r->pipe)
792 g_free(r->pipe);
793 g_free(r);
794 }
796 GList*
797 read_route_list(GList *rf_list, gboolean is_perma)
798 {
799 GList *list = NULL;
800 GList *node;
801 uid_t saved_uid, saved_gid;
803 if (!conf.run_as_user) {
804 set_euidgid(0, 0, &saved_uid, &saved_gid);
805 }
807 foreach(rf_list, node) {
808 gchar *fname = (gchar *) (node->data);
809 connect_route *route = read_route(fname, is_perma);
810 if (route)
811 list = g_list_append(list, route);
812 else
813 logwrite(LOG_ALERT, "could not read route configuration %s\n", fname);
814 }
816 /* set uid and gid back */
817 if (!conf.run_as_user) {
818 set_euidgid(saved_uid, saved_gid, NULL, NULL);
819 }
821 return list;
822 }
824 void
825 destroy_route_list(GList *list)
826 {
827 GList *node;
829 foreach(list, node) {
830 connect_route *route = (connect_route *) (node->data);
831 destroy_route(route);
832 }
833 g_list_free(list);
834 }