masqmail-0.2
diff src/conf.c @ 0:08114f7dcc23
this is masqmail-0.2.21 from oliver kurth
author | meillo@marmaro.de |
---|---|
date | Fri, 26 Sep 2008 17:05:23 +0200 |
parents | |
children | 26e34ae9a3e3 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/conf.c Fri Sep 26 17:05:23 2008 +0200 1.3 @@ -0,0 +1,995 @@ 1.4 +/* MasqMail 1.5 + Copyright (C) 1999-2001 Oliver Kurth 1.6 + 1.7 + This program is free software; you can redistribute it and/or modify 1.8 + it under the terms of the GNU General Public License as published by 1.9 + the Free Software Foundation; either version 2 of the License, or 1.10 + (at your option) any later version. 1.11 + 1.12 + This program is distributed in the hope that it will be useful, 1.13 + but WITHOUT ANY WARRANTY; without even the implied warranty of 1.14 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.15 + GNU General Public License for more details. 1.16 + 1.17 + You should have received a copy of the GNU General Public License 1.18 + along with this program; if not, write to the Free Software 1.19 + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 1.20 +*/ 1.21 + 1.22 +#include "masqmail.h" 1.23 + 1.24 +#include "pwd.h" 1.25 +#include "grp.h" 1.26 + 1.27 +masqmail_conf conf; 1.28 + 1.29 +void init_conf() 1.30 +{ 1.31 + struct passwd *passwd; 1.32 + struct group *group; 1.33 + 1.34 + memset(&conf, 0, sizeof(masqmail_conf)); 1.35 + 1.36 + conf.orig_uid = getuid(); 1.37 + conf.orig_gid = getgid(); 1.38 + 1.39 + if((passwd = getpwnam(DEF_MAIL_USER))) 1.40 + conf.mail_uid = passwd->pw_uid; 1.41 + else{ 1.42 + fprintf(stderr, "user %s not found! (terminating)\n", DEF_MAIL_USER); 1.43 + exit(EXIT_FAILURE); 1.44 + } 1.45 + if((group = getgrnam(DEF_MAIL_GROUP))) 1.46 + conf.mail_gid = group->gr_gid; 1.47 + else{ 1.48 + fprintf(stderr, "group %s not found! (terminating)\n", DEF_MAIL_GROUP); 1.49 + exit(EXIT_FAILURE); 1.50 + } 1.51 +} 1.52 + 1.53 +static gchar *true_strings[] = 1.54 +{ 1.55 + "yes", "on", "true", NULL 1.56 +}; 1.57 + 1.58 +static gchar *false_strings[] = 1.59 +{ 1.60 + "no", "off", "false", NULL 1.61 +}; 1.62 + 1.63 +static 1.64 +gboolean parse_boolean(gchar *rval) 1.65 +{ 1.66 + gchar **str; 1.67 + 1.68 + DEBUG(6) fprintf(stderr, "parse_boolean: %s\n", rval); 1.69 + 1.70 + str = true_strings; 1.71 + while(*str){ 1.72 + if(strncasecmp(*str, rval, strlen(*str)) == 0) 1.73 + return TRUE; 1.74 + str++; 1.75 + } 1.76 + 1.77 + str = false_strings; 1.78 + while(*str){ 1.79 + if(strncasecmp(*str, rval, strlen(*str)) == 0) 1.80 + return FALSE; 1.81 + str++; 1.82 + } 1.83 + 1.84 + fprintf(stderr, "cannot parse value '%s'\n", rval); 1.85 + exit(EXIT_FAILURE); 1.86 +} 1.87 + 1.88 +/* make a list from each line in a file */ 1.89 +static 1.90 +GList *parse_list_file(gchar *fname) 1.91 +{ 1.92 + GList *list = NULL; 1.93 + FILE *fptr; 1.94 + 1.95 + if((fptr = fopen(fname, "rt"))){ 1.96 + gchar buf[256]; 1.97 + 1.98 + while(!feof(fptr)){ 1.99 + fgets(buf, 255, fptr); 1.100 + if(buf[0] && (buf[0] != '#') && (buf[0] != '\n')){ 1.101 + g_strchomp(buf); 1.102 + list = g_list_append(list, g_strdup(buf)); 1.103 + } 1.104 + } 1.105 + fclose(fptr); 1.106 + }else{ 1.107 + logwrite(LOG_ALERT, "could not open %s for reading: %s\n", fname, strerror(errno)); 1.108 + exit(EXIT_FAILURE); 1.109 + } 1.110 + 1.111 + return list; 1.112 +} 1.113 + 1.114 +/* given a semicolon separated string, this function 1.115 + makes a GList out of it. 1.116 +*/ 1.117 +GList *parse_list(gchar *line, gboolean read_file) 1.118 +{ 1.119 + GList *list = NULL; 1.120 + gchar buf[256]; 1.121 + gchar *p, *q; 1.122 + 1.123 + DEBUG(6) fprintf(stderr, "parsing list %s\n", line); 1.124 + 1.125 + p = line; 1.126 + while(*p != 0){ 1.127 + q = buf; 1.128 + 1.129 + while(*p && (*p != ';') && (q < buf+255)) 1.130 + *(q++) = *(p++); 1.131 + *q = 0; 1.132 + 1.133 + if((buf[0] == '/') && (read_file)) 1.134 + /* item is a filename, include its contents */ 1.135 + list = g_list_concat(list, parse_list_file(buf)); 1.136 + else 1.137 + /* just a normal item */ 1.138 + list = g_list_append(list, g_strdup(buf)); 1.139 + 1.140 + DEBUG(6) printf("item = %s\n", buf); 1.141 + 1.142 + if(*p) p++; 1.143 + } 1.144 + return list; 1.145 +} 1.146 + 1.147 +static 1.148 +GList *parse_address_list(gchar *line, gboolean read_file) 1.149 +{ 1.150 + GList *plain_list = parse_list(line, read_file); 1.151 + GList *node; 1.152 + GList *list = NULL; 1.153 + 1.154 + foreach(plain_list, node){ 1.155 + gchar *item = (gchar *)(node->data); 1.156 + address *addr = create_address(item, TRUE); 1.157 + if(addr) 1.158 + list = g_list_append(list, addr); 1.159 + g_free(item); 1.160 + } 1.161 + g_list_free(plain_list); 1.162 + 1.163 + return list; 1.164 +} 1.165 + 1.166 +static 1.167 +GList *parse_resolve_list(gchar *line) 1.168 +{ 1.169 + GList *list; 1.170 + GList *list_node; 1.171 + GList *res_list = NULL; 1.172 + 1.173 + list = parse_list(line, FALSE); 1.174 + if(list){ 1.175 + foreach(list, list_node){ 1.176 + gchar *item = (gchar *)(list_node->data); 1.177 + if(strcmp(item, "byname") == 0){ 1.178 + res_list = g_list_append(res_list, resolve_byname); 1.179 +#ifdef ENABLE_RESOLVER 1.180 + }else if(strcmp(item, "dns_a") == 0){ 1.181 + res_list = g_list_append(res_list, resolve_dns_a); 1.182 + }else if(strcmp(item, "dns_mx") == 0){ 1.183 + res_list = g_list_append(res_list, resolve_dns_mx); 1.184 +#endif 1.185 + }else{ 1.186 + logwrite(LOG_ALERT, "unknown resolver %s\n", item); 1.187 + exit(EXIT_FAILURE); 1.188 + } 1.189 + g_free(item); 1.190 + } 1.191 + g_list_free(list); 1.192 + } 1.193 + return res_list; 1.194 +} 1.195 + 1.196 +static 1.197 +interface *parse_interface(gchar *line, gint def_port) 1.198 +{ 1.199 + gchar buf[256]; 1.200 + gchar *p, *q; 1.201 + interface *iface; 1.202 + 1.203 + DEBUG(6) fprintf(stderr, "parse_interface: %s\n", line); 1.204 + 1.205 + p = line; 1.206 + q = buf; 1.207 + while((*p != 0) && (*p != ':') && (q < buf+255)) 1.208 + *(q++) = *(p++); 1.209 + *q = 0; 1.210 + 1.211 + iface = g_malloc(sizeof(interface)); 1.212 + iface->address = g_strdup(buf); 1.213 + 1.214 + if(*p){ 1.215 + p++; 1.216 + iface->port = atoi(p); 1.217 + }else 1.218 + iface->port = def_port; 1.219 + 1.220 + return iface; 1.221 +} 1.222 + 1.223 +#ifdef ENABLE_IDENT /* so far used for that only */ 1.224 +static 1.225 +struct in_addr *parse_network(gchar *line, gint def_port) 1.226 +{ 1.227 + gchar buf[256]; 1.228 + gchar *p, *q; 1.229 + struct in_addr addr, mask_addr, net_addr, *p_net_addr; 1.230 + guint n; 1.231 + 1.232 + DEBUG(6) fprintf(stderr, "parse_network: %s\n", line); 1.233 + 1.234 + p = line; 1.235 + q = buf; 1.236 + while((*p != 0) && (*p != '/') && (q < buf+255)) 1.237 + *(q++) = *(p++); 1.238 + *q = 0; 1.239 + 1.240 + if((addr.s_addr = inet_addr(buf)) != INADDR_NONE){ 1.241 + if(*p){ 1.242 + guint i; 1.243 + p++; 1.244 + i = atoi(p); 1.245 + if((i >= 0) && (i <= 32)) 1.246 + n = i ? ~((1 << (32 - i)) - 1) : 0; 1.247 + else{ 1.248 + fprintf(stderr, "'%d' is not a valid net mask (must be >= 0 and <= 32)\n", i); 1.249 + exit(EXIT_FAILURE); 1.250 + } 1.251 + }else 1.252 + n = 0; 1.253 + 1.254 + mask_addr.s_addr = htonl(n); 1.255 + net_addr.s_addr = mask_addr.s_addr & addr.s_addr; 1.256 + }else{ 1.257 + fprintf(stderr, "'%s' is not a valid address (must be ip)\n", buf); 1.258 + exit(EXIT_FAILURE); 1.259 + } 1.260 + 1.261 + p_net_addr = g_malloc(sizeof(struct in_addr)); 1.262 + p_net_addr->s_addr = net_addr.s_addr; 1.263 + return p_net_addr; 1.264 +} 1.265 +#endif 1.266 + 1.267 +static 1.268 +gboolean eat_comments(FILE *in) 1.269 +{ 1.270 + gint c; 1.271 + 1.272 + for(c = fgetc(in); (c == '#' || isspace(c)) && c != EOF; c = fgetc(in)){ 1.273 + if(c == '#'){ 1.274 + gint c; 1.275 + for(c = fgetc(in); (c != '\n') && (c != EOF); c = fgetc(in)); 1.276 + } 1.277 + } 1.278 + if(c == EOF) return FALSE; 1.279 + ungetc(c, in); 1.280 + return TRUE; 1.281 +} 1.282 + 1.283 +/* after parsing, eat trailing character until LF */ 1.284 +static 1.285 +gboolean eat_line_trailing(FILE *in) 1.286 +{ 1.287 + gint c; 1.288 + 1.289 + for(c = fgetc(in); c != EOF && c != '\n'; c = fgetc(in)); 1.290 + if(c == EOF) return FALSE; 1.291 + return TRUE; 1.292 +} 1.293 + 1.294 +static 1.295 +gboolean eat_spaces(FILE *in) 1.296 +{ 1.297 + gint c; 1.298 + 1.299 + for(c = fgetc(in); c != EOF && isspace(c); c = fgetc(in)); 1.300 + if(c == EOF) return FALSE; 1.301 + ungetc(c, in); 1.302 + return TRUE; 1.303 +} 1.304 + 1.305 +static 1.306 +gboolean read_lval(FILE *in, gchar *buf, gint size) 1.307 +{ 1.308 + gint c; 1.309 + gchar *ptr = buf; 1.310 + 1.311 + DEBUG(6) fprintf(stderr, "read_lval()\n"); 1.312 + 1.313 + if(!eat_spaces(in)) return FALSE; 1.314 + 1.315 + c = fgetc(in); 1.316 + DEBUG(6) fprintf(stderr, "read_lval() 2\n"); 1.317 + while((isalnum(c) || c == '_' || c == '-' || c == '.') 1.318 + && (ptr < buf+size-1) 1.319 + && (c != EOF) 1.320 + ){ 1.321 + *ptr = c; ptr++; 1.322 + c = fgetc(in); 1.323 + } 1.324 + *ptr = 0; 1.325 + ungetc(c, in); 1.326 + 1.327 + if(c == EOF){ 1.328 + fprintf(stderr, "unexpected EOF after %s\n", buf); 1.329 + return FALSE; 1.330 + }else if(ptr >= buf+size-1){ 1.331 + fprintf(stderr, "lval too long\n"); 1.332 + } 1.333 + 1.334 + eat_spaces(in); 1.335 + 1.336 + DEBUG(6) fprintf(stderr, "lval = %s\n", buf); 1.337 + 1.338 + return buf[0] != 0; 1.339 +} 1.340 + 1.341 +static 1.342 +gboolean read_rval(FILE *in, gchar *buf, gint size) 1.343 +{ 1.344 + gint c; 1.345 + gchar *ptr = buf; 1.346 + 1.347 + DEBUG(6) fprintf(stderr, "read_rval()\n"); 1.348 + 1.349 + if(!eat_spaces(in)) return FALSE; 1.350 + 1.351 + c = fgetc(in); 1.352 + if(c != '\"'){ 1.353 + while((isalnum(c) || c == '_' || c == '-' || c == '.' || c == '/' || c == '@' || c == ';') 1.354 + && (ptr < buf+size-1) 1.355 + && (c != EOF) 1.356 + ){ 1.357 + *ptr = c; ptr++; 1.358 + c = fgetc(in); 1.359 + } 1.360 + *ptr = 0; 1.361 + ungetc(c, in); 1.362 + }else{ 1.363 + gboolean escape = FALSE; 1.364 + c = fgetc(in); 1.365 + while(((c != '\"') || escape) && (ptr < buf+size-1)){ 1.366 + if(c != '\n'){ /* ignore line breaks */ 1.367 + if((c == '\\') && (!escape)){ 1.368 + escape = TRUE; 1.369 + }else{ 1.370 + *ptr = c; ptr++; 1.371 + escape = FALSE; 1.372 + } 1.373 + } 1.374 + c = fgetc(in); 1.375 + } 1.376 + *ptr = 0; 1.377 + } 1.378 + 1.379 + eat_line_trailing(in); 1.380 + 1.381 + DEBUG(6) fprintf(stderr, "rval = %s\n", buf); 1.382 + 1.383 + return TRUE; 1.384 +} 1.385 + 1.386 +static 1.387 +gboolean read_statement(FILE *in, 1.388 + gchar *lval, gint lsize, 1.389 + gchar *rval, gint rsize) 1.390 +{ 1.391 + gint c; 1.392 + 1.393 + DEBUG(6) fprintf(stderr, "read_statement()\n"); 1.394 + 1.395 + /* eat comments and empty lines: */ 1.396 + if(!eat_comments(in)) return FALSE; 1.397 + 1.398 + DEBUG(6) fprintf(stderr, "read_statement() 1\n"); 1.399 + 1.400 + if(read_lval(in, lval, lsize)){ 1.401 + DEBUG(6) fprintf(stderr, "lval = %s\n", lval); 1.402 + if((c = fgetc(in) == '=')){ 1.403 + if(read_rval(in, rval, rsize)){ 1.404 + DEBUG(6) fprintf(stderr, "rval = %s\n", rval); 1.405 + return TRUE; 1.406 + } 1.407 + }else{ 1.408 + fprintf(stderr, "'=' expected after %s, char was '%c'\n", lval, c); 1.409 + } 1.410 + } 1.411 + return FALSE; 1.412 +} 1.413 + 1.414 +gboolean read_conf(gchar *filename) 1.415 +{ 1.416 + FILE *in; 1.417 + 1.418 + conf.log_max_pri = 7; 1.419 + 1.420 + conf.remote_port = 25; 1.421 + 1.422 + conf.do_relay = TRUE; 1.423 + 1.424 + conf.alias_local_cmp = strcmp; 1.425 + 1.426 + conf.max_defer_time = 86400*4; /* 4 days */ 1.427 + 1.428 + if((in = fopen(filename, "r"))){ 1.429 + gchar lval[256], rval[2048]; 1.430 + while(read_statement(in, lval, 256, rval, 2048)){ 1.431 + if(strcmp(lval, "debug_level") == 0) 1.432 + conf.debug_level = atoi(rval); 1.433 + else if(strcmp(lval, "run_as_user") == 0){ 1.434 + if(!conf.run_as_user) /* you should not be able 1.435 + to reset that flag */ 1.436 + conf.run_as_user = parse_boolean(rval); 1.437 + }else if(strcmp(lval, "use_syslog") == 0) 1.438 + conf.use_syslog = parse_boolean(rval); 1.439 + else if(strcmp(lval, "mail_dir") == 0) 1.440 + conf.mail_dir = g_strdup(rval); 1.441 + else if(strcmp(lval, "lock_dir") == 0) 1.442 + conf.lock_dir = g_strdup(rval); 1.443 + else if(strcmp(lval, "spool_dir") == 0) 1.444 + conf.spool_dir = g_strdup(rval); 1.445 + else if(strcmp(lval, "log_dir") == 0) 1.446 + conf.log_dir = g_strdup(rval); 1.447 + else if(strcmp(lval, "host_name") == 0){ 1.448 + if(rval[0] != '/') 1.449 + conf.host_name = g_strdup(rval); 1.450 + else{ 1.451 + char buf[256]; 1.452 + FILE *fptr = fopen(rval, "rt"); 1.453 + if(fptr){ 1.454 + fgets(buf, 255, fptr); 1.455 + g_strchomp(buf); 1.456 + conf.host_name = g_strdup(buf); 1.457 + fclose(fptr); 1.458 + }else{ 1.459 + fprintf(stderr, "could not open %s: %s\n", rval, strerror(errno)); 1.460 + return FALSE; 1.461 + } 1.462 + } 1.463 + } 1.464 + else if(strcmp(lval, "remote_port") == 0){ 1.465 + fprintf(stderr, 1.466 + "the remote_port option is now deprecated. Use 'mail_host' in the\n" 1.467 + "route configuration instead. See man masqmail.route\n"); 1.468 + conf.remote_port = atoi(rval); 1.469 + }else if(strcmp(lval, "local_hosts") == 0) 1.470 + conf.local_hosts = parse_list(rval, FALSE); 1.471 + else if(strcmp(lval, "local_addresses") == 0) 1.472 + conf.local_addresses = parse_list(rval, TRUE); 1.473 + else if(strcmp(lval, "not_local_addresses") == 0) 1.474 + conf.not_local_addresses = parse_list(rval, TRUE); 1.475 + else if(strcmp(lval, "local_nets") == 0) 1.476 + conf.local_nets = parse_list(rval, FALSE); 1.477 + else if(strcmp(lval, "do_save_envelope_to") == 0) 1.478 + conf.do_save_envelope_to = parse_boolean(rval); 1.479 + else if(strcmp(lval, "defer_all") == 0) 1.480 + conf.defer_all = parse_boolean(rval); 1.481 + else if(strcmp(lval, "do_relay") == 0) 1.482 + conf.do_relay = parse_boolean(rval); 1.483 + else if(strcmp(lval, "alias_file") == 0){ 1.484 + conf.alias_file = g_strdup(rval); 1.485 + }else if(strcmp(lval, "alias_local_caseless") == 0){ 1.486 + conf.alias_local_cmp = parse_boolean(rval) ? strcasecmp : strcmp; 1.487 + }else if(strcmp(lval, "mbox_default") == 0){ 1.488 + conf.mbox_default = g_strdup(rval); 1.489 + }else if(strcmp(lval, "mbox_users") == 0){ 1.490 + conf.mbox_users = parse_list(rval, TRUE); 1.491 + }else if(strcmp(lval, "mda_users") == 0){ 1.492 + conf.mda_users = parse_list(rval, TRUE); 1.493 + }else if(strcmp(lval, "maildir_users") == 0){ 1.494 + conf.maildir_users = parse_list(rval, TRUE); 1.495 + }else if(strcmp(lval, "mda") == 0){ 1.496 + conf.mda = g_strdup(rval); 1.497 + }else if(strcmp(lval, "mda_fromline") == 0){ 1.498 + conf.mda_fromline = parse_boolean(rval); 1.499 + }else if(strcmp(lval, "mda_fromhack") == 0){ 1.500 + conf.mda_fromhack = parse_boolean(rval); 1.501 + }else if(strcmp(lval, "pipe_fromline") == 0){ 1.502 + conf.pipe_fromline = parse_boolean(rval); 1.503 + }else if(strcmp(lval, "pipe_fromhack") == 0){ 1.504 + conf.pipe_fromhack = parse_boolean(rval); 1.505 + }else if(strcmp(lval, "listen_addresses") == 0){ 1.506 + GList *node; 1.507 + GList *tmp_list = parse_list(rval, FALSE); 1.508 + 1.509 + conf.listen_addresses = NULL; 1.510 + foreach(tmp_list, node){ 1.511 + conf.listen_addresses = 1.512 + g_list_append(conf.listen_addresses, 1.513 + parse_interface((gchar *)(node->data), 25)); 1.514 + g_free(node->data); 1.515 + } 1.516 + g_list_free(tmp_list); 1.517 + } 1.518 + else if(strcmp(lval, "ident_trusted_nets") == 0){ 1.519 +#ifdef ENABLE_IDENT 1.520 + GList *node; 1.521 + GList *tmp_list = parse_list(rval, FALSE); 1.522 + 1.523 + conf.ident_trusted_nets = NULL; 1.524 + foreach(tmp_list, node){ 1.525 + conf.ident_trusted_nets = 1.526 + g_list_append(conf.ident_trusted_nets, 1.527 + parse_network((gchar *)(node->data), 25)); 1.528 + g_free(node->data); 1.529 + } 1.530 + g_list_free(tmp_list); 1.531 +#else 1.532 + fprintf(stderr, "%s ignored: not compiled with ident support\n", lval); 1.533 +#endif 1.534 + } 1.535 + else if((strncmp(lval, "connect_route.", 14) == 0) || 1.536 + (strncmp(lval, "online_routes.", 14) == 0)){ 1.537 + GList *file_list = parse_list(rval, FALSE); 1.538 + table_pair *pair = create_pair(&(lval[14]), file_list); 1.539 + conf.connect_routes = g_list_append(conf.connect_routes, pair); 1.540 + } 1.541 + else if(strcmp(lval, "local_net_route") == 0){ 1.542 + conf.local_net_routes = parse_list(rval, FALSE); 1.543 + } 1.544 + else if(strcmp(lval, "online_detect") == 0) 1.545 + conf.online_detect = g_strdup(rval); 1.546 + else if(strcmp(lval, "online_file") == 0) 1.547 + conf.online_file = g_strdup(rval); 1.548 + else if(strcmp(lval, "online_pipe") == 0) 1.549 + conf.online_pipe = g_strdup(rval); 1.550 + else if(strcmp(lval, "mserver_iface") == 0) 1.551 + conf.mserver_iface = parse_interface(rval, 224); 1.552 + else if(strcmp(lval, "do_queue") == 0) 1.553 + conf.do_queue = parse_boolean(rval); 1.554 + else if(strncmp(lval, "get.", 4) == 0){ 1.555 +#ifdef ENABLE_POP3 1.556 + table_pair *pair = create_pair_string(&(lval[4]), rval); 1.557 + conf.get_names = g_list_append(conf.get_names, pair); 1.558 +#else 1.559 + fprintf(stderr, "get.<name> ignored: not compiled with pop support\n"); 1.560 +#endif 1.561 + } 1.562 + else if(strncmp(lval, "online_gets.", 12) == 0){ 1.563 +#ifdef ENABLE_POP3 1.564 + GList *file_list = parse_list(rval, FALSE); 1.565 + table_pair *pair = create_pair(&(lval[12]), file_list); 1.566 + conf.online_gets = g_list_append(conf.online_gets, pair); 1.567 +#else 1.568 + fprintf(stderr, "online_gets.<name> ignored: not compiled with pop support\n"); 1.569 +#endif 1.570 + } 1.571 + else if(strcmp(lval, "errmsg_file") == 0) 1.572 + conf.errmsg_file = g_strdup(rval); 1.573 + else if(strcmp(lval, "warnmsg_file") == 0) 1.574 + conf.warnmsg_file = g_strdup(rval); 1.575 + else if(strcmp(lval, "warn_intervals") == 0) 1.576 + conf.warn_intervals = parse_list(rval, FALSE); 1.577 + else if(strcmp(lval, "max_defer_time") == 0){ 1.578 + gint dummy; 1.579 + gint ival = time_interval(rval, &dummy); 1.580 + if(ival < 0) 1.581 + fprintf(stderr, "invalid time interval for 'max_defer_time': %s\n", rval); 1.582 + else 1.583 + conf.max_defer_time = ival; 1.584 + }else if(strcmp(lval, "log_user") == 0) 1.585 + conf.log_user = g_strdup(rval); 1.586 + 1.587 + else 1.588 + fprintf(stderr, "var '%s' not (yet) known, ignored\n", lval); 1.589 + } 1.590 + fclose(in); 1.591 + 1.592 + if(conf.errmsg_file == NULL) 1.593 + conf.errmsg_file = g_strdup(DATA_DIR"/tpl/failmsg.tpl"); 1.594 + if(conf.warnmsg_file == NULL) 1.595 + conf.warnmsg_file = g_strdup(DATA_DIR"/tpl/warnmsg.tpl"); 1.596 + 1.597 + if(conf.lock_dir == NULL) 1.598 + conf.lock_dir = g_strdup_printf("%s/lock/", conf.spool_dir); 1.599 + 1.600 + if(conf.mbox_default == NULL) 1.601 + conf.mbox_default = g_strdup("mbox"); 1.602 + 1.603 + if(conf.warn_intervals == NULL) 1.604 + conf.warn_intervals = parse_list("1h;4h;8h;1d;2d;3d", FALSE); 1.605 + 1.606 + return TRUE; 1.607 + }else 1.608 + fprintf(stderr, "could not open config file %s: %s\n", filename, strerror(errno)); 1.609 + return FALSE; 1.610 +} 1.611 + 1.612 +connect_route *read_route(gchar *filename, gboolean is_local_net) 1.613 +{ 1.614 + gboolean ok = FALSE; 1.615 + FILE *in; 1.616 + 1.617 + connect_route *route = g_malloc(sizeof(connect_route)); 1.618 + memset(route, 0, sizeof(connect_route)); 1.619 + 1.620 + DEBUG(5) debugf("read_route, filename = %s\n", filename); 1.621 + 1.622 + route->filename = g_strdup(filename); 1.623 + route->name = g_strdup(filename); /* quick hack */ 1.624 + 1.625 + route->protocol = g_strdup("smtp"); 1.626 + route->expand_h_sender_address = TRUE; 1.627 + 1.628 + route->is_local_net = is_local_net; 1.629 + 1.630 + route->do_pipelining = TRUE; 1.631 + 1.632 + if((in = fopen(route->filename, "r"))){ 1.633 + gchar lval[256], rval[2048]; 1.634 + while(read_statement(in, lval, 256, rval, 2048)){ 1.635 + if(strcmp(lval, "protocol") == 0) 1.636 + route->protocol = g_strdup(rval); 1.637 + else if(strcmp(lval, "mail_host") == 0) 1.638 + route->mail_host = parse_interface(rval, conf.remote_port); 1.639 + else if(strcmp(lval, "helo_name") == 0) 1.640 + route->helo_name = g_strdup(rval); 1.641 + else if(strcmp(lval, "wrapper") == 0) 1.642 + route->wrapper = g_strdup(rval); 1.643 + else if(strcmp(lval, "connect_error_fail") == 0) 1.644 + route->connect_error_fail = parse_boolean(rval); 1.645 + else if(strcmp(lval, "do_correct_helo") == 0) 1.646 + route->do_correct_helo = parse_boolean(rval); 1.647 + else if(strcmp(lval, "do_pipelining") == 0) 1.648 + route->do_pipelining = parse_boolean(rval); 1.649 + else if(strcmp(lval, "allowed_return_paths") == 0) 1.650 + route->allowed_return_paths = parse_address_list(rval, TRUE); 1.651 + else if(strcmp(lval, "allowed_mail_locals") == 0) 1.652 + route->allowed_mail_locals = parse_list(rval, TRUE); 1.653 + else if(strcmp(lval, "not_allowed_return_paths") == 0) 1.654 + route->not_allowed_return_paths = parse_address_list(rval, TRUE); 1.655 + else if(strcmp(lval, "not_allowed_mail_locals") == 0) 1.656 + route->not_allowed_mail_locals = parse_list(rval, TRUE); 1.657 + else if(strcmp(lval, "allowed_rcpt_domains") == 0) 1.658 + route->allowed_rcpt_domains = parse_list(rval, TRUE); 1.659 + else if(strcmp(lval, "not_allowed_rcpt_domains") == 0) 1.660 + route->not_allowed_rcpt_domains = parse_list(rval, TRUE); 1.661 + else if(strcmp(lval, "set_h_from_domain") == 0) 1.662 + route->set_h_from_domain = g_strdup(rval); 1.663 + else if(strcmp(lval, "set_h_reply_to_domain") == 0) 1.664 + route->set_h_reply_to_domain = g_strdup(rval); 1.665 + else if(strcmp(lval, "set_return_path_domain") == 0) 1.666 + route->set_return_path_domain = g_strdup(rval); 1.667 + else if(strcmp(lval, "map_return_path_addresses") == 0){ 1.668 + GList *node, *list; 1.669 + 1.670 + list = parse_list(rval, TRUE); 1.671 + foreach(list, node){ 1.672 + gchar *item = (gchar *)(node->data); 1.673 + table_pair *pair = parse_table_pair(item, ':'); 1.674 + address *addr = create_address((gchar *)(pair->value), TRUE); 1.675 + g_free(pair->value); 1.676 + pair->value = (gpointer *)addr; 1.677 + route->map_return_path_addresses = 1.678 + g_list_append(route->map_return_path_addresses, pair); 1.679 + g_free(item); 1.680 + } 1.681 + g_list_free(list); 1.682 + } 1.683 + else if(strcmp(lval, "map_h_from_addresses") == 0){ 1.684 + GList *list, *node; 1.685 + 1.686 + list = parse_list(rval, TRUE); 1.687 + foreach(list, node){ 1.688 + gchar *item = (gchar *)(node->data); 1.689 + table_pair *pair = parse_table_pair(item, ':'); 1.690 + route->map_h_from_addresses = 1.691 + g_list_append(route->map_h_from_addresses, pair); 1.692 + g_free(item); 1.693 + } 1.694 + g_list_free(list); 1.695 + } 1.696 + else if(strcmp(lval, "map_h_reply_to_addresses") == 0){ 1.697 + GList *list, *node; 1.698 + 1.699 + list = parse_list(rval, TRUE); 1.700 + foreach(list, node){ 1.701 + gchar *item = (gchar *)(node->data); 1.702 + table_pair *pair = parse_table_pair(item, ':'); 1.703 + route->map_h_reply_to_addresses = 1.704 + g_list_append(route->map_h_reply_to_addresses, pair); 1.705 + g_free(item); 1.706 + } 1.707 + g_list_free(list); 1.708 + } 1.709 + else if(strcmp(lval, "map_h_mail_followup_to_addresses") == 0){ 1.710 + GList *list, *node; 1.711 + 1.712 + list = parse_list(rval, TRUE); 1.713 + foreach(list, node){ 1.714 + gchar *item = (gchar *)(node->data); 1.715 + table_pair *pair = parse_table_pair(item, ':'); 1.716 + route->map_h_mail_followup_to_addresses = 1.717 + g_list_append(route->map_h_mail_followup_to_addresses, pair); 1.718 + g_free(item); 1.719 + } 1.720 + g_list_free(list); 1.721 + } 1.722 + else if(strcmp(lval, "expand_h_sender_domain") == 0){ 1.723 + route->expand_h_sender_domain = parse_boolean(rval); 1.724 + } 1.725 + else if(strcmp(lval, "expand_h_sender_address") == 0){ 1.726 + route->expand_h_sender_address = parse_boolean(rval); 1.727 + } 1.728 + else if(strcmp(lval, "resolve_list") == 0) 1.729 + route->resolve_list = parse_resolve_list(rval); 1.730 + else if(strcmp(lval, "do_ssl") == 0){ 1.731 + /* we ignore this. This option is used by sqilconf */ 1.732 + ; 1.733 + } 1.734 +#ifdef ENABLE_AUTH 1.735 + else if(strcmp(lval, "auth_name") == 0){ 1.736 + route->auth_name = g_strdup(rval); 1.737 + } 1.738 + else if(strcmp(lval, "auth_login") == 0){ 1.739 + route->auth_login = g_strdup(rval); 1.740 + } 1.741 + else if(strcmp(lval, "auth_secret") == 0){ 1.742 + route->auth_secret = g_strdup(rval); 1.743 + } 1.744 +#else 1.745 + else if((strcmp(lval, "auth_name") == 0) || 1.746 + (strcmp(lval, "auth_login") == 0) || 1.747 + (strcmp(lval, "auth_secret") == 0)){ 1.748 + logwrite(LOG_WARNING, "%s ignored: not compiled with auth support.\n", lval); 1.749 + } 1.750 +#endif 1.751 + else if(strcmp(lval, "pop3_login") == 0){ 1.752 +#ifdef ENABLE_POP3 1.753 + route->pop3_login = g_strdup(rval); 1.754 +#else 1.755 + logwrite(LOG_WARNING, "pop3_login ignored: not compiled with pop support.\n"); 1.756 +#endif 1.757 + } 1.758 + else if(strcmp(lval, "pipe") == 0){ 1.759 + route->pipe = g_strdup(rval); 1.760 + } 1.761 + else if(strcmp(lval, "pipe_fromline") == 0){ 1.762 + route->pipe_fromline = parse_boolean(rval); 1.763 + } 1.764 + else if(strcmp(lval, "pipe_fromhack") == 0){ 1.765 + route->pipe_fromhack = parse_boolean(rval); 1.766 + } 1.767 + else if(strcmp(lval, "last_route") == 0){ 1.768 + route->last_route = parse_boolean(rval); 1.769 + } 1.770 + else 1.771 + logwrite(LOG_WARNING, "var '%s' not (yet) known, ignored\n", lval); 1.772 + } 1.773 + 1.774 + if(route->resolve_list == NULL){ 1.775 + if(is_local_net){ 1.776 + route->resolve_list = 1.777 + g_list_append(NULL, resolve_byname); 1.778 + }else{ 1.779 +#ifdef ENABLE_RESOLVER 1.780 + route->resolve_list = 1.781 + g_list_append(route->resolve_list, resolve_dns_mx); 1.782 + route->resolve_list = 1.783 + g_list_append(route->resolve_list, resolve_dns_a); 1.784 +#endif 1.785 + route->resolve_list = 1.786 + g_list_append(route->resolve_list, resolve_byname); 1.787 + } 1.788 + } 1.789 + fclose(in); 1.790 + ok = TRUE; 1.791 + 1.792 + /* warn user about misconfigurations: */ 1.793 + if((route->map_h_from_addresses != NULL) && (route->set_h_from_domain != NULL)){ 1.794 + logwrite(LOG_WARNING, "'map_h_from_addresses' overrides 'set_h_from_domain'\n"); 1.795 + g_free(route->set_h_from_domain); 1.796 + route->set_h_from_domain = NULL; 1.797 + } 1.798 + if((route->map_h_reply_to_addresses != NULL) && (route->set_h_reply_to_domain != NULL)){ 1.799 + logwrite(LOG_WARNING, "'map_h_reply_to_addresses' overrides 'set_h_reply_to_domain'\n"); 1.800 + g_free(route->set_h_reply_to_domain); 1.801 + route->set_h_reply_to_domain = NULL; 1.802 + } 1.803 + }else{ 1.804 + logwrite(LOG_ALERT, "could not open route file %s: %s\n", 1.805 + route->filename, strerror(errno)); 1.806 + } 1.807 + 1.808 + if(!ok){ 1.809 + g_free(route); 1.810 + route = NULL; 1.811 + } 1.812 + 1.813 + return route; 1.814 +} 1.815 + 1.816 +static 1.817 +void _g_list_free_all(GList *list) 1.818 +{ 1.819 + GList *node; 1.820 + if(list){ 1.821 + foreach(list, node) 1.822 + g_free(node->data); 1.823 + g_list_free(list); 1.824 + } 1.825 +} 1.826 + 1.827 +void destroy_route(connect_route *r) 1.828 +{ 1.829 + if(r->filename) g_free(r->filename); 1.830 + if(r->protocol) g_free(r->protocol); 1.831 + if(r->mail_host){ 1.832 + g_free(r->mail_host->address); 1.833 + g_free(r->mail_host); 1.834 + } 1.835 + if(r->wrapper) g_free(r->wrapper); 1.836 + if(r->helo_name) g_free(r->helo_name); 1.837 + _g_list_free_all(r->allowed_mail_locals); 1.838 + _g_list_free_all(r->not_allowed_mail_locals); 1.839 + _g_list_free_all(r->allowed_rcpt_domains); 1.840 + _g_list_free_all(r->not_allowed_rcpt_domains); 1.841 + if(r->set_h_from_domain) g_free(r->set_h_from_domain); 1.842 + if(r->set_h_reply_to_domain) g_free(r->set_h_reply_to_domain); 1.843 + if(r->set_return_path_domain) g_free(r->set_return_path_domain); 1.844 + if(r->map_h_reply_to_addresses) destroy_table(r->map_h_reply_to_addresses); 1.845 + if(r->resolve_list) g_list_free(r->resolve_list); 1.846 +#ifdef ENABLE_AUTH 1.847 + if(r->auth_name) g_free(r->auth_name); 1.848 + if(r->auth_login) g_free(r->auth_login); 1.849 + if(r->auth_secret) g_free(r->auth_secret); 1.850 +#endif 1.851 +#ifdef ENABLE_POP3 1.852 + if(r->pop3_login) g_free(r->pop3_login); 1.853 +#endif 1.854 + if(r->pipe) g_free(r->pipe); 1.855 + g_free(r); 1.856 +} 1.857 + 1.858 +GList *read_route_list(GList *rf_list, gboolean is_local_net) 1.859 +{ 1.860 + GList *list = NULL; 1.861 + GList *node; 1.862 + uid_t saved_uid, saved_gid; 1.863 + 1.864 + if(!conf.run_as_user){ 1.865 + set_euidgid(0, 0, &saved_uid, &saved_gid); 1.866 + } 1.867 + 1.868 + foreach(rf_list, node){ 1.869 + gchar *fname = (gchar *)(node->data); 1.870 + connect_route *route = read_route(fname, is_local_net); 1.871 + if(route) 1.872 + list = g_list_append(list, route); 1.873 + else 1.874 + logwrite(LOG_ALERT, "could not read route configuration %s\n", fname); 1.875 + } 1.876 + 1.877 + /* set uid and gid back */ 1.878 + if(!conf.run_as_user){ 1.879 + set_euidgid(saved_uid, saved_gid, NULL, NULL); 1.880 + } 1.881 + 1.882 + return list; 1.883 +} 1.884 + 1.885 +void destroy_route_list(GList *list) 1.886 +{ 1.887 + GList *node; 1.888 + 1.889 + foreach(list, node){ 1.890 + connect_route *route = (connect_route *)(node->data); 1.891 + destroy_route(route); 1.892 + } 1.893 + g_list_free(list); 1.894 +} 1.895 + 1.896 +#ifdef ENABLE_POP3 1.897 + 1.898 +get_conf *read_get_conf(gchar *filename) 1.899 +{ 1.900 + FILE *in; 1.901 + 1.902 + get_conf *gc = g_malloc(sizeof(get_conf)); 1.903 + memset(gc, 0, sizeof(get_conf)); 1.904 + 1.905 + gc->server_port = 110; 1.906 + 1.907 + if((in = fopen(filename, "r"))){ 1.908 + gchar lval[256], rval[2048]; 1.909 + while(read_statement(in, lval, 256, rval, 2048)){ 1.910 + if(strcmp(lval, "protocol") == 0) 1.911 + gc->protocol = g_strdup(rval); 1.912 + else if(strcmp(lval, "server") == 0) 1.913 + gc->server_name = g_strdup(rval); 1.914 + else if(strcmp(lval, "port") == 0) 1.915 + gc->server_port = atoi(rval); 1.916 + else if(strcmp(lval, "wrapper") == 0) 1.917 + gc->wrapper = g_strdup(rval); 1.918 + else if(strcmp(lval, "user") == 0) 1.919 + gc->login_user = g_strdup(rval); 1.920 + else if(strcmp(lval, "pass") == 0) 1.921 + gc->login_pass = g_strdup(rval); 1.922 + else if(strcmp(lval, "address") == 0) 1.923 + gc->address = create_address_qualified(rval, TRUE, conf.host_name); 1.924 + else if(strcmp(lval, "return_path") == 0) 1.925 + gc->return_path = create_address_qualified(rval, TRUE, conf.host_name); 1.926 + else if(strcmp(lval, "do_ssl") == 0) 1.927 + /* we ignore this. This option is used by sqilconf */ 1.928 + ; 1.929 + else if(strcmp(lval, "do_keep") == 0) 1.930 + gc->do_keep = parse_boolean(rval); 1.931 + else if(strcmp(lval, "do_uidl") == 0) 1.932 + gc->do_uidl = parse_boolean(rval); 1.933 + else if(strcmp(lval, "do_uidl_dele") == 0) 1.934 + gc->do_uidl_dele = parse_boolean(rval); 1.935 + else if(strcmp(lval, "max_size") == 0) 1.936 + gc->max_size = atoi(rval); 1.937 + else if(strcmp(lval, "max_size_delete") == 0) 1.938 + gc->max_size = parse_boolean(rval); 1.939 + else if(strcmp(lval, "max_count") == 0) 1.940 + gc->max_count = atoi(rval); 1.941 + else if(strcmp(lval, "resolve_list") == 0) 1.942 + gc->resolve_list = parse_resolve_list(rval); 1.943 + else 1.944 + logwrite(LOG_WARNING, "var '%s' not (yet) known, ignored\n", lval); 1.945 + } 1.946 + fclose(in); 1.947 + 1.948 + if(gc->resolve_list == NULL){ 1.949 +#ifdef ENABLE_RESOLVER 1.950 + gc->resolve_list = 1.951 + g_list_append(NULL, resolve_dns_a); 1.952 +#endif 1.953 + gc->resolve_list = 1.954 + g_list_append(NULL, resolve_byname); 1.955 + } 1.956 + 1.957 + if(gc->protocol == NULL) 1.958 + gc->protocol = g_strdup("pop3"); 1.959 + return gc; 1.960 + } 1.961 + logwrite(LOG_ALERT, "could not open get file %s: %s\n", filename, strerror(errno)); 1.962 + 1.963 + g_free(gc); 1.964 + return NULL; 1.965 +} 1.966 + 1.967 +void destroy_get_conf(get_conf *gc) 1.968 +{ 1.969 + if(gc->protocol) g_free(gc->protocol); 1.970 + if(gc->server_name) g_free(gc->server_name); 1.971 + if(gc->login_user) g_free(gc->login_user); 1.972 + if(gc->login_pass) g_free(gc->login_pass); 1.973 + if(gc->wrapper) g_free(gc->wrapper); 1.974 + if(gc->address) destroy_address(gc->address); 1.975 + if(gc->return_path) destroy_address(gc->return_path); 1.976 + if(gc->resolve_list) g_list_free(gc->resolve_list); 1.977 + g_free(gc); 1.978 +} 1.979 + 1.980 +#endif 1.981 + 1.982 +connect_route *create_local_route() 1.983 +{ 1.984 + connect_route *route; 1.985 + 1.986 + route = g_malloc(sizeof(connect_route)); 1.987 + if(route){ 1.988 + memset(route, 0, sizeof(connect_route)); 1.989 + route->protocol = g_strdup("smtp"); 1.990 + route->is_local_net = TRUE; 1.991 + route->name = g_strdup("local_net (default)"); 1.992 + route->expand_h_sender_address = TRUE; 1.993 + route->resolve_list = 1.994 + g_list_append(NULL, resolve_byname); 1.995 + route->connect_error_fail = TRUE; 1.996 + } 1.997 + return route; 1.998 +}