masqmail

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