comparison src/conf.c @ 10:26e34ae9a3e3

changed indention and line wrapping to a more consistent style
author meillo@marmaro.de
date Mon, 27 Oct 2008 16:23:10 +0100
parents 08114f7dcc23
children 49dab67fe461
comparison
equal deleted inserted replaced
9:31cc8a89cb74 10:26e34ae9a3e3
21 #include "pwd.h" 21 #include "pwd.h"
22 #include "grp.h" 22 #include "grp.h"
23 23
24 masqmail_conf conf; 24 masqmail_conf conf;
25 25
26 void init_conf() 26 void
27 { 27 init_conf()
28 struct passwd *passwd; 28 {
29 struct group *group; 29 struct passwd *passwd;
30 30 struct group *group;
31 memset(&conf, 0, sizeof(masqmail_conf)); 31
32 32 memset(&conf, 0, sizeof(masqmail_conf));
33 conf.orig_uid = getuid(); 33
34 conf.orig_gid = getgid(); 34 conf.orig_uid = getuid();
35 35 conf.orig_gid = getgid();
36 if((passwd = getpwnam(DEF_MAIL_USER))) 36
37 conf.mail_uid = passwd->pw_uid; 37 if ((passwd = getpwnam(DEF_MAIL_USER)))
38 else{ 38 conf.mail_uid = passwd->pw_uid;
39 fprintf(stderr, "user %s not found! (terminating)\n", DEF_MAIL_USER); 39 else {
40 exit(EXIT_FAILURE); 40 fprintf(stderr, "user %s not found! (terminating)\n", DEF_MAIL_USER);
41 } 41 exit(EXIT_FAILURE);
42 if((group = getgrnam(DEF_MAIL_GROUP))) 42 }
43 conf.mail_gid = group->gr_gid; 43 if ((group = getgrnam(DEF_MAIL_GROUP)))
44 else{ 44 conf.mail_gid = group->gr_gid;
45 fprintf(stderr, "group %s not found! (terminating)\n", DEF_MAIL_GROUP); 45 else {
46 exit(EXIT_FAILURE); 46 fprintf(stderr, "group %s not found! (terminating)\n", DEF_MAIL_GROUP);
47 } 47 exit(EXIT_FAILURE);
48 } 48 }
49 49 }
50 static gchar *true_strings[] = 50
51 { 51 static gchar* true_strings[] = {
52 "yes", "on", "true", NULL 52 "yes", "on", "true", NULL
53 }; 53 };
54 54
55 static gchar *false_strings[] = 55 static gchar *false_strings[] = {
56 { 56 "no", "off", "false", NULL
57 "no", "off", "false", NULL
58 }; 57 };
59 58
60 static 59 static gboolean
61 gboolean parse_boolean(gchar *rval) 60 parse_boolean(gchar * rval)
62 { 61 {
63 gchar **str; 62 gchar **str;
64 63
65 DEBUG(6) fprintf(stderr, "parse_boolean: %s\n", rval); 64 DEBUG(6) fprintf(stderr, "parse_boolean: %s\n", rval);
66 65
67 str = true_strings; 66 str = true_strings;
68 while(*str){ 67 while (*str) {
69 if(strncasecmp(*str, rval, strlen(*str)) == 0) 68 if (strncasecmp(*str, rval, strlen(*str)) == 0)
70 return TRUE; 69 return TRUE;
71 str++; 70 str++;
72 } 71 }
73 72
74 str = false_strings; 73 str = false_strings;
75 while(*str){ 74 while (*str) {
76 if(strncasecmp(*str, rval, strlen(*str)) == 0) 75 if (strncasecmp(*str, rval, strlen(*str)) == 0)
77 return FALSE; 76 return FALSE;
78 str++; 77 str++;
79 } 78 }
80 79
81 fprintf(stderr, "cannot parse value '%s'\n", rval); 80 fprintf(stderr, "cannot parse value '%s'\n", rval);
82 exit(EXIT_FAILURE); 81 exit(EXIT_FAILURE);
83 } 82 }
84 83
85 /* make a list from each line in a file */ 84 /* make a list from each line in a file */
86 static 85 static GList*
87 GList *parse_list_file(gchar *fname) 86 parse_list_file(gchar * fname)
88 { 87 {
89 GList *list = NULL; 88 GList *list = NULL;
90 FILE *fptr; 89 FILE *fptr;
91 90
92 if((fptr = fopen(fname, "rt"))){ 91 if ((fptr = fopen(fname, "rt"))) {
93 gchar buf[256]; 92 gchar buf[256];
94 93
95 while(!feof(fptr)){ 94 while (!feof(fptr)) {
96 fgets(buf, 255, fptr); 95 fgets(buf, 255, fptr);
97 if(buf[0] && (buf[0] != '#') && (buf[0] != '\n')){ 96 if (buf[0] && (buf[0] != '#') && (buf[0] != '\n')) {
98 g_strchomp(buf); 97 g_strchomp(buf);
99 list = g_list_append(list, g_strdup(buf)); 98 list = g_list_append(list, g_strdup(buf));
100 } 99 }
101 } 100 }
102 fclose(fptr); 101 fclose(fptr);
103 }else{ 102 } else {
104 logwrite(LOG_ALERT, "could not open %s for reading: %s\n", fname, strerror(errno)); 103 logwrite(LOG_ALERT, "could not open %s for reading: %s\n", fname, strerror(errno));
105 exit(EXIT_FAILURE); 104 exit(EXIT_FAILURE);
106 } 105 }
107 106
108 return list; 107 return list;
109 } 108 }
110 109
111 /* given a semicolon separated string, this function 110 /* given a semicolon separated string, this function
112 makes a GList out of it. 111 makes a GList out of it.
113 */ 112 */
114 GList *parse_list(gchar *line, gboolean read_file) 113 GList*
115 { 114 parse_list(gchar * line, gboolean read_file)
116 GList *list = NULL; 115 {
117 gchar buf[256]; 116 GList *list = NULL;
118 gchar *p, *q; 117 gchar buf[256];
119 118 gchar *p, *q;
120 DEBUG(6) fprintf(stderr, "parsing list %s\n", line); 119
121 120 DEBUG(6) fprintf(stderr, "parsing list %s\n", line);
122 p = line; 121
123 while(*p != 0){ 122 p = line;
124 q = buf; 123 while (*p != 0) {
125 124 q = buf;
126 while(*p && (*p != ';') && (q < buf+255)) 125
127 *(q++) = *(p++); 126 while (*p && (*p != ';') && (q < buf + 255))
128 *q = 0; 127 *(q++) = *(p++);
129 128 *q = 0;
130 if((buf[0] == '/') && (read_file)) 129
131 /* item is a filename, include its contents */ 130 if ((buf[0] == '/') && (read_file))
132 list = g_list_concat(list, parse_list_file(buf)); 131 /* item is a filename, include its contents */
133 else 132 list = g_list_concat(list, parse_list_file(buf));
134 /* just a normal item */ 133 else
135 list = g_list_append(list, g_strdup(buf)); 134 /* just a normal item */
136 135 list = g_list_append(list, g_strdup(buf));
137 DEBUG(6) printf("item = %s\n", buf); 136
138 137 DEBUG(6) printf("item = %s\n", buf);
139 if(*p) p++; 138
140 } 139 if (*p)
141 return list; 140 p++;
142 } 141 }
143 142 return list;
144 static 143 }
145 GList *parse_address_list(gchar *line, gboolean read_file) 144
146 { 145 static GList*
147 GList *plain_list = parse_list(line, read_file); 146 parse_address_list(gchar * line, gboolean read_file)
148 GList *node; 147 {
149 GList *list = NULL; 148 GList *plain_list = parse_list(line, read_file);
150 149 GList *node;
151 foreach(plain_list, node){ 150 GList *list = NULL;
152 gchar *item = (gchar *)(node->data); 151
153 address *addr = create_address(item, TRUE); 152 foreach(plain_list, node) {
154 if(addr) 153 gchar *item = (gchar *) (node->data);
155 list = g_list_append(list, addr); 154 address *addr = create_address(item, TRUE);
156 g_free(item); 155 if (addr)
157 } 156 list = g_list_append(list, addr);
158 g_list_free(plain_list); 157 g_free(item);
159 158 }
160 return list; 159 g_list_free(plain_list);
161 } 160
162 161 return list;
163 static 162 }
164 GList *parse_resolve_list(gchar *line) 163
165 { 164 static GList*
166 GList *list; 165 parse_resolve_list(gchar * line)
167 GList *list_node; 166 {
168 GList *res_list = NULL; 167 GList *list;
169 168 GList *list_node;
170 list = parse_list(line, FALSE); 169 GList *res_list = NULL;
171 if(list){ 170
172 foreach(list, list_node){ 171 list = parse_list(line, FALSE);
173 gchar *item = (gchar *)(list_node->data); 172 if (list) {
174 if(strcmp(item, "byname") == 0){ 173 foreach(list, list_node) {
175 res_list = g_list_append(res_list, resolve_byname); 174 gchar *item = (gchar *) (list_node->data);
175 if (strcmp(item, "byname") == 0) {
176 res_list = g_list_append(res_list, resolve_byname);
176 #ifdef ENABLE_RESOLVER 177 #ifdef ENABLE_RESOLVER
177 }else if(strcmp(item, "dns_a") == 0){ 178 } else if (strcmp(item, "dns_a") == 0) {
178 res_list = g_list_append(res_list, resolve_dns_a); 179 res_list = g_list_append(res_list, resolve_dns_a);
179 }else if(strcmp(item, "dns_mx") == 0){ 180 } else if (strcmp(item, "dns_mx") == 0) {
180 res_list = g_list_append(res_list, resolve_dns_mx); 181 res_list = g_list_append(res_list, resolve_dns_mx);
181 #endif 182 #endif
182 }else{ 183 } else {
183 logwrite(LOG_ALERT, "unknown resolver %s\n", item); 184 logwrite(LOG_ALERT, "unknown resolver %s\n", item);
184 exit(EXIT_FAILURE); 185 exit(EXIT_FAILURE);
185 } 186 }
186 g_free(item); 187 g_free(item);
187 } 188 }
188 g_list_free(list); 189 g_list_free(list);
189 } 190 }
190 return res_list; 191 return res_list;
191 } 192 }
192 193
193 static 194 static interface*
194 interface *parse_interface(gchar *line, gint def_port) 195 parse_interface(gchar * line, gint def_port)
195 { 196 {
196 gchar buf[256]; 197 gchar buf[256];
197 gchar *p, *q; 198 gchar *p, *q;
198 interface *iface; 199 interface *iface;
199 200
200 DEBUG(6) fprintf(stderr, "parse_interface: %s\n", line); 201 DEBUG(6) fprintf(stderr, "parse_interface: %s\n", line);
201 202
202 p = line; 203 p = line;
203 q = buf; 204 q = buf;
204 while((*p != 0) && (*p != ':') && (q < buf+255)) 205 while ((*p != 0) && (*p != ':') && (q < buf + 255))
205 *(q++) = *(p++); 206 *(q++) = *(p++);
206 *q = 0; 207 *q = 0;
207 208
208 iface = g_malloc(sizeof(interface)); 209 iface = g_malloc(sizeof(interface));
209 iface->address = g_strdup(buf); 210 iface->address = g_strdup(buf);
210 211
211 if(*p){ 212 if (*p) {
212 p++; 213 p++;
213 iface->port = atoi(p); 214 iface->port = atoi(p);
214 }else 215 } else
215 iface->port = def_port; 216 iface->port = def_port;
216 217
217 return iface; 218 return iface;
218 } 219 }
219 220
220 #ifdef ENABLE_IDENT /* so far used for that only */ 221 #ifdef ENABLE_IDENT /* so far used for that only */
221 static 222 static struct in_addr*
222 struct in_addr *parse_network(gchar *line, gint def_port) 223 parse_network(gchar * line, gint def_port)
223 { 224 {
224 gchar buf[256]; 225 gchar buf[256];
225 gchar *p, *q; 226 gchar *p, *q;
226 struct in_addr addr, mask_addr, net_addr, *p_net_addr; 227 struct in_addr addr, mask_addr, net_addr, *p_net_addr;
227 guint n; 228 guint n;
228 229
229 DEBUG(6) fprintf(stderr, "parse_network: %s\n", line); 230 DEBUG(6) fprintf(stderr, "parse_network: %s\n", line);
230 231
231 p = line; 232 p = line;
232 q = buf; 233 q = buf;
233 while((*p != 0) && (*p != '/') && (q < buf+255)) 234 while ((*p != 0) && (*p != '/') && (q < buf + 255))
234 *(q++) = *(p++); 235 *(q++) = *(p++);
235 *q = 0; 236 *q = 0;
236 237
237 if((addr.s_addr = inet_addr(buf)) != INADDR_NONE){ 238 if ((addr.s_addr = inet_addr(buf)) != INADDR_NONE) {
238 if(*p){ 239 if (*p) {
239 guint i; 240 guint i;
240 p++; 241 p++;
241 i = atoi(p); 242 i = atoi(p);
242 if((i >= 0) && (i <= 32)) 243 if ((i >= 0) && (i <= 32))
243 n = i ? ~((1 << (32 - i)) - 1) : 0; 244 n = i ? ~((1 << (32 - i)) - 1) : 0;
244 else{ 245 else {
245 fprintf(stderr, "'%d' is not a valid net mask (must be >= 0 and <= 32)\n", i); 246 fprintf(stderr, "'%d' is not a valid net mask (must be >= 0 and <= 32)\n", i);
246 exit(EXIT_FAILURE); 247 exit(EXIT_FAILURE);
247 } 248 }
248 }else 249 } else
249 n = 0; 250 n = 0;
250 251
251 mask_addr.s_addr = htonl(n); 252 mask_addr.s_addr = htonl(n);
252 net_addr.s_addr = mask_addr.s_addr & addr.s_addr; 253 net_addr.s_addr = mask_addr.s_addr & addr.s_addr;
253 }else{ 254 } else {
254 fprintf(stderr, "'%s' is not a valid address (must be ip)\n", buf); 255 fprintf(stderr, "'%s' is not a valid address (must be ip)\n", buf);
255 exit(EXIT_FAILURE); 256 exit(EXIT_FAILURE);
256 } 257 }
257 258
258 p_net_addr = g_malloc(sizeof(struct in_addr)); 259 p_net_addr = g_malloc(sizeof(struct in_addr));
259 p_net_addr->s_addr = net_addr.s_addr; 260 p_net_addr->s_addr = net_addr.s_addr;
260 return p_net_addr; 261 return p_net_addr;
261 } 262 }
262 #endif 263 #endif
263 264
264 static 265 static gboolean
265 gboolean eat_comments(FILE *in) 266 eat_comments(FILE * in)
266 { 267 {
267 gint c; 268 gint c;
268 269
269 for(c = fgetc(in); (c == '#' || isspace(c)) && c != EOF; c = fgetc(in)){ 270 for (c = fgetc(in); (c == '#' || isspace(c)) && c != EOF;
270 if(c == '#'){ 271 c = fgetc(in)) {
271 gint c; 272 if (c == '#') {
272 for(c = fgetc(in); (c != '\n') && (c != EOF); c = fgetc(in)); 273 gint c;
273 } 274 for (c = fgetc(in); (c != '\n') && (c != EOF); c = fgetc(in));
274 } 275 }
275 if(c == EOF) return FALSE; 276 }
276 ungetc(c, in); 277 if (c == EOF)
277 return TRUE; 278 return FALSE;
279 ungetc(c, in);
280 return TRUE;
278 } 281 }
279 282
280 /* after parsing, eat trailing character until LF */ 283 /* after parsing, eat trailing character until LF */
281 static 284 static gboolean
282 gboolean eat_line_trailing(FILE *in) 285 eat_line_trailing(FILE * in)
283 { 286 {
284 gint c; 287 gint c;
285 288
286 for(c = fgetc(in); c != EOF && c != '\n'; c = fgetc(in)); 289 for (c = fgetc(in); c != EOF && c != '\n'; c = fgetc(in));
287 if(c == EOF) return FALSE; 290 if (c == EOF)
288 return TRUE; 291 return FALSE;
289 }
290
291 static
292 gboolean eat_spaces(FILE *in)
293 {
294 gint c;
295
296 for(c = fgetc(in); c != EOF && isspace(c); c = fgetc(in));
297 if(c == EOF) return FALSE;
298 ungetc(c, in);
299 return TRUE;
300 }
301
302 static
303 gboolean read_lval(FILE *in, gchar *buf, gint size)
304 {
305 gint c;
306 gchar *ptr = buf;
307
308 DEBUG(6) fprintf(stderr, "read_lval()\n");
309
310 if(!eat_spaces(in)) return FALSE;
311
312 c = fgetc(in);
313 DEBUG(6) fprintf(stderr, "read_lval() 2\n");
314 while((isalnum(c) || c == '_' || c == '-' || c == '.')
315 && (ptr < buf+size-1)
316 && (c != EOF)
317 ){
318 *ptr = c; ptr++;
319 c = fgetc(in);
320 }
321 *ptr = 0;
322 ungetc(c, in);
323
324 if(c == EOF){
325 fprintf(stderr, "unexpected EOF after %s\n", buf);
326 return FALSE;
327 }else if(ptr >= buf+size-1){
328 fprintf(stderr, "lval too long\n");
329 }
330
331 eat_spaces(in);
332
333 DEBUG(6) fprintf(stderr, "lval = %s\n", buf);
334
335 return buf[0] != 0;
336 }
337
338 static
339 gboolean read_rval(FILE *in, gchar *buf, gint size)
340 {
341 gint c;
342 gchar *ptr = buf;
343
344 DEBUG(6) fprintf(stderr, "read_rval()\n");
345
346 if(!eat_spaces(in)) return FALSE;
347
348 c = fgetc(in);
349 if(c != '\"'){
350 while((isalnum(c) || c == '_' || c == '-' || c == '.' || c == '/' || c == '@' || c == ';')
351 && (ptr < buf+size-1)
352 && (c != EOF)
353 ){
354 *ptr = c; ptr++;
355 c = fgetc(in);
356 }
357 *ptr = 0;
358 ungetc(c, in);
359 }else{
360 gboolean escape = FALSE;
361 c = fgetc(in);
362 while(((c != '\"') || escape) && (ptr < buf+size-1)){
363 if(c != '\n'){ /* ignore line breaks */
364 if((c == '\\') && (!escape)){
365 escape = TRUE;
366 }else{
367 *ptr = c; ptr++;
368 escape = FALSE;
369 }
370 }
371 c = fgetc(in);
372 }
373 *ptr = 0;
374 }
375
376 eat_line_trailing(in);
377
378 DEBUG(6) fprintf(stderr, "rval = %s\n", buf);
379
380 return TRUE;
381 }
382
383 static
384 gboolean read_statement(FILE *in,
385 gchar *lval, gint lsize,
386 gchar *rval, gint rsize)
387 {
388 gint c;
389
390 DEBUG(6) fprintf(stderr, "read_statement()\n");
391
392 /* eat comments and empty lines: */
393 if(!eat_comments(in)) return FALSE;
394
395 DEBUG(6) fprintf(stderr, "read_statement() 1\n");
396
397 if(read_lval(in, lval, lsize)){
398 DEBUG(6) fprintf(stderr, "lval = %s\n", lval);
399 if((c = fgetc(in) == '=')){
400 if(read_rval(in, rval, rsize)){
401 DEBUG(6) fprintf(stderr, "rval = %s\n", rval);
402 return TRUE; 292 return TRUE;
403 } 293 }
404 }else{ 294
405 fprintf(stderr, "'=' expected after %s, char was '%c'\n", lval, c); 295 static gboolean
406 } 296 eat_spaces(FILE * in)
407 } 297 {
408 return FALSE; 298 gint c;
409 } 299
410 300 for (c = fgetc(in); c != EOF && isspace(c); c = fgetc(in));
411 gboolean read_conf(gchar *filename) 301 if (c == EOF)
412 { 302 return FALSE;
413 FILE *in; 303 ungetc(c, in);
414 304 return TRUE;
415 conf.log_max_pri = 7; 305 }
416 306
417 conf.remote_port = 25; 307 static gboolean
418 308 read_lval(FILE * in, gchar * buf, gint size)
419 conf.do_relay = TRUE; 309 {
420 310 gint c;
421 conf.alias_local_cmp = strcmp; 311 gchar *ptr = buf;
422 312
423 conf.max_defer_time = 86400*4; /* 4 days */ 313 DEBUG(6) fprintf(stderr, "read_lval()\n");
424 314
425 if((in = fopen(filename, "r"))){ 315 if (!eat_spaces(in))
426 gchar lval[256], rval[2048]; 316 return FALSE;
427 while(read_statement(in, lval, 256, rval, 2048)){ 317
428 if(strcmp(lval, "debug_level") == 0) 318 c = fgetc(in);
429 conf.debug_level = atoi(rval); 319 DEBUG(6) fprintf(stderr, "read_lval() 2\n");
430 else if(strcmp(lval, "run_as_user") == 0){ 320 while ((isalnum(c) || c == '_' || c == '-' || c == '.')
431 if(!conf.run_as_user) /* you should not be able 321 && (ptr < buf + size - 1)
432 to reset that flag */ 322 && (c != EOF)) {
433 conf.run_as_user = parse_boolean(rval); 323 *ptr = c;
434 }else if(strcmp(lval, "use_syslog") == 0) 324 ptr++;
435 conf.use_syslog = parse_boolean(rval); 325 c = fgetc(in);
436 else if(strcmp(lval, "mail_dir") == 0) 326 }
437 conf.mail_dir = g_strdup(rval); 327 *ptr = 0;
438 else if(strcmp(lval, "lock_dir") == 0) 328 ungetc(c, in);
439 conf.lock_dir = g_strdup(rval); 329
440 else if(strcmp(lval, "spool_dir") == 0) 330 if (c == EOF) {
441 conf.spool_dir = g_strdup(rval); 331 fprintf(stderr, "unexpected EOF after %s\n", buf);
442 else if(strcmp(lval, "log_dir") == 0) 332 return FALSE;
443 conf.log_dir = g_strdup(rval); 333 } else if (ptr >= buf + size - 1) {
444 else if(strcmp(lval, "host_name") == 0){ 334 fprintf(stderr, "lval too long\n");
445 if(rval[0] != '/') 335 }
446 conf.host_name = g_strdup(rval); 336
447 else{ 337 eat_spaces(in);
448 char buf[256]; 338
449 FILE *fptr = fopen(rval, "rt"); 339 DEBUG(6) fprintf(stderr, "lval = %s\n", buf);
450 if(fptr){ 340
451 fgets(buf, 255, fptr); 341 return buf[0] != 0;
452 g_strchomp(buf); 342 }
453 conf.host_name = g_strdup(buf); 343
454 fclose(fptr); 344 static gboolean
455 }else{ 345 read_rval(FILE * in, gchar * buf, gint size)
456 fprintf(stderr, "could not open %s: %s\n", rval, strerror(errno)); 346 {
457 return FALSE; 347 gint c;
458 } 348 gchar *ptr = buf;
459 } 349
460 } 350 DEBUG(6) fprintf(stderr, "read_rval()\n");
461 else if(strcmp(lval, "remote_port") == 0){ 351
462 fprintf(stderr, 352 if (!eat_spaces(in))
463 "the remote_port option is now deprecated. Use 'mail_host' in the\n" 353 return FALSE;
464 "route configuration instead. See man masqmail.route\n"); 354
465 conf.remote_port = atoi(rval); 355 c = fgetc(in);
466 }else if(strcmp(lval, "local_hosts") == 0) 356 if (c != '\"') {
467 conf.local_hosts = parse_list(rval, FALSE); 357 while ((isalnum(c) || c == '_' || c == '-' || c == '.' || c == '/'
468 else if(strcmp(lval, "local_addresses") == 0) 358 || c == '@' || c == ';')
469 conf.local_addresses = parse_list(rval, TRUE); 359 && (ptr < buf + size - 1)
470 else if(strcmp(lval, "not_local_addresses") == 0) 360 && (c != EOF)) {
471 conf.not_local_addresses = parse_list(rval, TRUE); 361 *ptr = c;
472 else if(strcmp(lval, "local_nets") == 0) 362 ptr++;
473 conf.local_nets = parse_list(rval, FALSE); 363 c = fgetc(in);
474 else if(strcmp(lval, "do_save_envelope_to") == 0) 364 }
475 conf.do_save_envelope_to = parse_boolean(rval); 365 *ptr = 0;
476 else if(strcmp(lval, "defer_all") == 0) 366 ungetc(c, in);
477 conf.defer_all = parse_boolean(rval); 367 } else {
478 else if(strcmp(lval, "do_relay") == 0) 368 gboolean escape = FALSE;
479 conf.do_relay = parse_boolean(rval); 369 c = fgetc(in);
480 else if(strcmp(lval, "alias_file") == 0){ 370 while (((c != '\"') || escape) && (ptr < buf + size - 1)) {
481 conf.alias_file = g_strdup(rval); 371 if (c != '\n') { /* ignore line breaks */
482 }else if(strcmp(lval, "alias_local_caseless") == 0){ 372 if ((c == '\\') && (!escape)) {
483 conf.alias_local_cmp = parse_boolean(rval) ? strcasecmp : strcmp; 373 escape = TRUE;
484 }else if(strcmp(lval, "mbox_default") == 0){ 374 } else {
485 conf.mbox_default = g_strdup(rval); 375 *ptr = c;
486 }else if(strcmp(lval, "mbox_users") == 0){ 376 ptr++;
487 conf.mbox_users = parse_list(rval, TRUE); 377 escape = FALSE;
488 }else if(strcmp(lval, "mda_users") == 0){ 378 }
489 conf.mda_users = parse_list(rval, TRUE); 379 }
490 }else if(strcmp(lval, "maildir_users") == 0){ 380 c = fgetc(in);
491 conf.maildir_users = parse_list(rval, TRUE); 381 }
492 }else if(strcmp(lval, "mda") == 0){ 382 *ptr = 0;
493 conf.mda = g_strdup(rval); 383 }
494 }else if(strcmp(lval, "mda_fromline") == 0){ 384
495 conf.mda_fromline = parse_boolean(rval); 385 eat_line_trailing(in);
496 }else if(strcmp(lval, "mda_fromhack") == 0){ 386
497 conf.mda_fromhack = parse_boolean(rval); 387 DEBUG(6) fprintf(stderr, "rval = %s\n", buf);
498 }else if(strcmp(lval, "pipe_fromline") == 0){ 388
499 conf.pipe_fromline = parse_boolean(rval); 389 return TRUE;
500 }else if(strcmp(lval, "pipe_fromhack") == 0){ 390 }
501 conf.pipe_fromhack = parse_boolean(rval); 391
502 }else if(strcmp(lval, "listen_addresses") == 0){ 392 static gboolean
393 read_statement(FILE * in, gchar * lval, gint lsize, gchar * rval, gint rsize)
394 {
395 gint c;
396
397 DEBUG(6) fprintf(stderr, "read_statement()\n");
398
399 /* eat comments and empty lines: */
400 if (!eat_comments(in))
401 return FALSE;
402
403 DEBUG(6) fprintf(stderr, "read_statement() 1\n");
404
405 if (read_lval(in, lval, lsize)) {
406 DEBUG(6) fprintf(stderr, "lval = %s\n", lval);
407 if ((c = fgetc(in) == '=')) {
408 if (read_rval(in, rval, rsize)) {
409 DEBUG(6) fprintf(stderr, "rval = %s\n", rval);
410 return TRUE;
411 }
412 } else {
413 fprintf(stderr, "'=' expected after %s, char was '%c'\n", lval,
414 c);
415 }
416 }
417 return FALSE;
418 }
419
420 gboolean
421 read_conf(gchar * filename)
422 {
423 FILE *in;
424
425 conf.log_max_pri = 7;
426 conf.remote_port = 25;
427 conf.do_relay = TRUE;
428 conf.alias_local_cmp = strcmp;
429 conf.max_defer_time = 86400 * 4; /* 4 days */
430
431 if ((in = fopen(filename, "r"))) {
432 gchar lval[256], rval[2048];
433 while (read_statement(in, lval, 256, rval, 2048)) {
434 if (strcmp(lval, "debug_level") == 0)
435 conf.debug_level = atoi(rval);
436 else if (strcmp(lval, "run_as_user") == 0) {
437 if (!conf.run_as_user) /* you should not be able to reset that flag */
438 conf.run_as_user = parse_boolean(rval);
439 } else if (strcmp(lval, "use_syslog") == 0)
440 conf.use_syslog = parse_boolean(rval);
441 else if (strcmp(lval, "mail_dir") == 0)
442 conf.mail_dir = g_strdup(rval);
443 else if (strcmp(lval, "lock_dir") == 0)
444 conf.lock_dir = g_strdup(rval);
445 else if (strcmp(lval, "spool_dir") == 0)
446 conf.spool_dir = g_strdup(rval);
447 else if (strcmp(lval, "log_dir") == 0)
448 conf.log_dir = g_strdup(rval);
449 else if (strcmp(lval, "host_name") == 0) {
450 if (rval[0] != '/')
451 conf.host_name = g_strdup(rval);
452 else {
453 char buf[256];
454 FILE *fptr = fopen(rval, "rt");
455 if (fptr) {
456 fgets(buf, 255, fptr);
457 g_strchomp(buf);
458 conf.host_name = g_strdup(buf);
459 fclose(fptr);
460 } else {
461 fprintf(stderr, "could not open %s: %s\n", rval,
462 strerror(errno));
463 return FALSE;
464 }
465 }
466 } else if (strcmp(lval, "remote_port") == 0) {
467 fprintf(stderr, "the remote_port option is now deprecated. Use 'mail_host' in the\n"
468 "route configuration instead. See man masqmail.route\n");
469 conf.remote_port = atoi(rval);
470 } else if (strcmp(lval, "local_hosts") == 0)
471 conf.local_hosts = parse_list(rval, FALSE);
472 else if (strcmp(lval, "local_addresses") == 0)
473 conf.local_addresses = parse_list(rval, TRUE);
474 else if (strcmp(lval, "not_local_addresses") == 0)
475 conf.not_local_addresses = parse_list(rval, TRUE);
476 else if (strcmp(lval, "local_nets") == 0)
477 conf.local_nets = parse_list(rval, FALSE);
478 else if (strcmp(lval, "do_save_envelope_to") == 0)
479 conf.do_save_envelope_to = parse_boolean(rval);
480 else if (strcmp(lval, "defer_all") == 0)
481 conf.defer_all = parse_boolean(rval);
482 else if (strcmp(lval, "do_relay") == 0)
483 conf.do_relay = parse_boolean(rval);
484 else if (strcmp(lval, "alias_file") == 0) {
485 conf.alias_file = g_strdup(rval);
486 } else if (strcmp(lval, "alias_local_caseless") == 0) {
487 conf.alias_local_cmp = parse_boolean(rval) ? strcasecmp : strcmp;
488 } else if (strcmp(lval, "mbox_default") == 0) {
489 conf.mbox_default = g_strdup(rval);
490 } else if (strcmp(lval, "mbox_users") == 0) {
491 conf.mbox_users = parse_list(rval, TRUE);
492 } else if (strcmp(lval, "mda_users") == 0) {
493 conf.mda_users = parse_list(rval, TRUE);
494 } else if (strcmp(lval, "maildir_users") == 0) {
495 conf.maildir_users = parse_list(rval, TRUE);
496 } else if (strcmp(lval, "mda") == 0) {
497 conf.mda = g_strdup(rval);
498 } else if (strcmp(lval, "mda_fromline") == 0) {
499 conf.mda_fromline = parse_boolean(rval);
500 } else if (strcmp(lval, "mda_fromhack") == 0) {
501 conf.mda_fromhack = parse_boolean(rval);
502 } else if (strcmp(lval, "pipe_fromline") == 0) {
503 conf.pipe_fromline = parse_boolean(rval);
504 } else if (strcmp(lval, "pipe_fromhack") == 0) {
505 conf.pipe_fromhack = parse_boolean(rval);
506 } else if (strcmp(lval, "listen_addresses") == 0) {
507 GList *node;
508 GList *tmp_list = parse_list(rval, FALSE);
509
510 conf.listen_addresses = NULL;
511 foreach(tmp_list, node) {
512 conf.listen_addresses = g_list_append(conf.listen_addresses, parse_interface((gchar *) (node-> data), 25));
513 g_free(node->data);
514 }
515 g_list_free(tmp_list);
516 } else if (strcmp(lval, "ident_trusted_nets") == 0) {
517 #ifdef ENABLE_IDENT
518 GList *node;
519 GList *tmp_list = parse_list(rval, FALSE);
520
521 conf.ident_trusted_nets = NULL;
522 foreach(tmp_list, node) {
523 conf.ident_trusted_nets = g_list_append(conf.ident_trusted_nets, parse_network((gchar *) (node->data), 25));
524 g_free(node->data);
525 }
526 g_list_free(tmp_list);
527 #else
528 fprintf(stderr, "%s ignored: not compiled with ident support\n", lval);
529 #endif
530 } else if ((strncmp(lval, "connect_route.", 14) == 0)
531 || (strncmp(lval, "online_routes.", 14) == 0)) {
532 GList *file_list = parse_list(rval, FALSE);
533 table_pair *pair = create_pair(&(lval[14]), file_list);
534 conf.connect_routes = g_list_append(conf.connect_routes, pair);
535 } else if (strcmp(lval, "local_net_route") == 0) {
536 conf.local_net_routes = parse_list(rval, FALSE);
537 } else if (strcmp(lval, "online_detect") == 0)
538 conf.online_detect = g_strdup(rval);
539 else if (strcmp(lval, "online_file") == 0)
540 conf.online_file = g_strdup(rval);
541 else if (strcmp(lval, "online_pipe") == 0)
542 conf.online_pipe = g_strdup(rval);
543 else if (strcmp(lval, "mserver_iface") == 0)
544 conf.mserver_iface = parse_interface(rval, 224);
545 else if (strcmp(lval, "do_queue") == 0)
546 conf.do_queue = parse_boolean(rval);
547 else if (strncmp(lval, "get.", 4) == 0) {
548 #ifdef ENABLE_POP3
549 table_pair *pair = create_pair_string(&(lval[4]), rval);
550 conf.get_names = g_list_append(conf.get_names, pair);
551 #else
552 fprintf(stderr, "get.<name> ignored: not compiled with pop support\n");
553 #endif
554 } else if (strncmp(lval, "online_gets.", 12) == 0) {
555 #ifdef ENABLE_POP3
556 GList *file_list = parse_list(rval, FALSE);
557 table_pair *pair = create_pair(&(lval[12]), file_list);
558 conf.online_gets = g_list_append(conf.online_gets, pair);
559 #else
560 fprintf(stderr, "online_gets.<name> ignored: not compiled with pop support\n");
561 #endif
562 } else if (strcmp(lval, "errmsg_file") == 0)
563 conf.errmsg_file = g_strdup(rval);
564 else if (strcmp(lval, "warnmsg_file") == 0)
565 conf.warnmsg_file = g_strdup(rval);
566 else if (strcmp(lval, "warn_intervals") == 0)
567 conf.warn_intervals = parse_list(rval, FALSE);
568 else if (strcmp(lval, "max_defer_time") == 0) {
569 gint dummy;
570 gint ival = time_interval(rval, &dummy);
571 if (ival < 0)
572 fprintf(stderr, "invalid time interval for 'max_defer_time': %s\n", rval);
573 else
574 conf.max_defer_time = ival;
575 } else if (strcmp(lval, "log_user") == 0)
576 conf.log_user = g_strdup(rval);
577
578 else
579 fprintf(stderr, "var '%s' not (yet) known, ignored\n", lval);
580 }
581 fclose(in);
582
583 if (conf.errmsg_file == NULL)
584 conf.errmsg_file = g_strdup(DATA_DIR "/tpl/failmsg.tpl");
585 if (conf.warnmsg_file == NULL)
586 conf.warnmsg_file = g_strdup(DATA_DIR "/tpl/warnmsg.tpl");
587
588 if (conf.lock_dir == NULL)
589 conf.lock_dir = g_strdup_printf("%s/lock/", conf.spool_dir);
590
591 if (conf.mbox_default == NULL)
592 conf.mbox_default = g_strdup("mbox");
593
594 if (conf.warn_intervals == NULL)
595 conf.warn_intervals = parse_list("1h;4h;8h;1d;2d;3d", FALSE);
596
597 return TRUE;
598 } else
599 fprintf(stderr, "could not open config file %s: %s\n", filename, strerror(errno));
600 return FALSE;
601 }
602
603 connect_route*
604 read_route(gchar * filename, gboolean is_local_net)
605 {
606 gboolean ok = FALSE;
607 FILE *in;
608
609 connect_route *route = g_malloc(sizeof(connect_route));
610 memset(route, 0, sizeof(connect_route));
611
612 DEBUG(5) debugf("read_route, filename = %s\n", filename);
613
614 route->filename = g_strdup(filename);
615 route->name = g_strdup(filename); /* quick hack */
616
617 route->protocol = g_strdup("smtp");
618 route->expand_h_sender_address = TRUE;
619
620 route->is_local_net = is_local_net;
621
622 route->do_pipelining = TRUE;
623
624 if ((in = fopen(route->filename, "r"))) {
625 gchar lval[256], rval[2048];
626 while (read_statement(in, lval, 256, rval, 2048)) {
627 if (strcmp(lval, "protocol") == 0)
628 route->protocol = g_strdup(rval);
629 else if (strcmp(lval, "mail_host") == 0)
630 route->mail_host = parse_interface(rval, conf.remote_port);
631 else if (strcmp(lval, "helo_name") == 0)
632 route->helo_name = g_strdup(rval);
633 else if (strcmp(lval, "wrapper") == 0)
634 route->wrapper = g_strdup(rval);
635 else if (strcmp(lval, "connect_error_fail") == 0)
636 route->connect_error_fail = parse_boolean(rval);
637 else if (strcmp(lval, "do_correct_helo") == 0)
638 route->do_correct_helo = parse_boolean(rval);
639 else if (strcmp(lval, "do_pipelining") == 0)
640 route->do_pipelining = parse_boolean(rval);
641 else if (strcmp(lval, "allowed_return_paths") == 0)
642 route->allowed_return_paths = parse_address_list(rval, TRUE);
643 else if (strcmp(lval, "allowed_mail_locals") == 0)
644 route->allowed_mail_locals = parse_list(rval, TRUE);
645 else if (strcmp(lval, "not_allowed_return_paths") == 0)
646 route->not_allowed_return_paths = parse_address_list(rval, TRUE);
647 else if (strcmp(lval, "not_allowed_mail_locals") == 0)
648 route->not_allowed_mail_locals = parse_list(rval, TRUE);
649 else if (strcmp(lval, "allowed_rcpt_domains") == 0)
650 route->allowed_rcpt_domains = parse_list(rval, TRUE);
651 else if (strcmp(lval, "not_allowed_rcpt_domains") == 0)
652 route->not_allowed_rcpt_domains = parse_list(rval, TRUE);
653 else if (strcmp(lval, "set_h_from_domain") == 0)
654 route->set_h_from_domain = g_strdup(rval);
655 else if (strcmp(lval, "set_h_reply_to_domain") == 0)
656 route->set_h_reply_to_domain = g_strdup(rval);
657 else if (strcmp(lval, "set_return_path_domain") == 0)
658 route->set_return_path_domain = g_strdup(rval);
659 else if (strcmp(lval, "map_return_path_addresses") == 0) {
660 GList *node, *list;
661
662 list = parse_list(rval, TRUE);
663 foreach(list, node) {
664 gchar *item = (gchar *) (node->data);
665 table_pair *pair = parse_table_pair(item, ':');
666 address *addr = create_address((gchar *) (pair->value), TRUE);
667 g_free(pair->value);
668 pair->value = (gpointer *) addr;
669 route->map_return_path_addresses = g_list_append(route->map_return_path_addresses, pair);
670 g_free(item);
671 }
672 g_list_free(list);
673 } else if (strcmp(lval, "map_h_from_addresses") == 0) {
674 GList *list, *node;
675
676 list = parse_list(rval, TRUE);
677 foreach(list, node) {
678 gchar *item = (gchar *) (node->data);
679 table_pair *pair = parse_table_pair(item, ':');
680 route->map_h_from_addresses = g_list_append(route->map_h_from_addresses, pair);
681 g_free(item);
682 }
683 g_list_free(list);
684 } else if (strcmp(lval, "map_h_reply_to_addresses") == 0) {
685 GList *list, *node;
686
687 list = parse_list(rval, TRUE);
688 foreach(list, node) {
689 gchar *item = (gchar *) (node->data);
690 table_pair *pair = parse_table_pair(item, ':');
691 route->map_h_reply_to_addresses = g_list_append(route->map_h_reply_to_addresses, pair);
692 g_free(item);
693 }
694 g_list_free(list);
695 } else if (strcmp(lval, "map_h_mail_followup_to_addresses") == 0) {
696 GList *list, *node;
697
698 list = parse_list(rval, TRUE);
699 foreach(list, node) {
700 gchar *item = (gchar *) (node->data);
701 table_pair *pair = parse_table_pair(item, ':');
702 route->map_h_mail_followup_to_addresses = g_list_append(route->map_h_mail_followup_to_addresses, pair);
703 g_free(item);
704 }
705 g_list_free(list);
706 } else if (strcmp(lval, "expand_h_sender_domain") == 0) {
707 route->expand_h_sender_domain = parse_boolean(rval);
708 } else if (strcmp(lval, "expand_h_sender_address") == 0) {
709 route->expand_h_sender_address = parse_boolean(rval);
710 } else if (strcmp(lval, "resolve_list") == 0)
711 route->resolve_list = parse_resolve_list(rval);
712 else if (strcmp(lval, "do_ssl") == 0) {
713 /* we ignore this. This option is used by sqilconf */
714 ;
715 }
716 #ifdef ENABLE_AUTH
717 else if (strcmp(lval, "auth_name") == 0) {
718 route->auth_name = g_strdup(rval);
719 } else if (strcmp(lval, "auth_login") == 0) {
720 route->auth_login = g_strdup(rval);
721 } else if (strcmp(lval, "auth_secret") == 0) {
722 route->auth_secret = g_strdup(rval);
723 }
724 #else
725 else if ((strcmp(lval, "auth_name") == 0)
726 || (strcmp(lval, "auth_login") == 0)
727 || (strcmp(lval, "auth_secret") == 0)) {
728 logwrite(LOG_WARNING, "%s ignored: not compiled with auth support.\n", lval);
729 }
730 #endif
731 else if (strcmp(lval, "pop3_login") == 0) {
732 #ifdef ENABLE_POP3
733 route->pop3_login = g_strdup(rval);
734 #else
735 logwrite(LOG_WARNING, "pop3_login ignored: not compiled with pop support.\n");
736 #endif
737 } else if (strcmp(lval, "pipe") == 0) {
738 route->pipe = g_strdup(rval);
739 } else if (strcmp(lval, "pipe_fromline") == 0) {
740 route->pipe_fromline = parse_boolean(rval);
741 } else if (strcmp(lval, "pipe_fromhack") == 0) {
742 route->pipe_fromhack = parse_boolean(rval);
743 } else if (strcmp(lval, "last_route") == 0) {
744 route->last_route = parse_boolean(rval);
745 } else
746 logwrite(LOG_WARNING, "var '%s' not (yet) known, ignored\n", lval);
747 }
748
749 if (route->resolve_list == NULL) {
750 if (is_local_net) {
751 route->resolve_list = g_list_append(NULL, resolve_byname);
752 } else {
753 #ifdef ENABLE_RESOLVER
754 route->resolve_list = g_list_append(route->resolve_list, resolve_dns_mx);
755 route->resolve_list = g_list_append(route->resolve_list, resolve_dns_a);
756 #endif
757 route->resolve_list = g_list_append(route->resolve_list, resolve_byname);
758 }
759 }
760 fclose(in);
761 ok = TRUE;
762
763 /* warn user about misconfigurations: */
764 if ((route->map_h_from_addresses != NULL)
765 && (route->set_h_from_domain != NULL)) {
766 logwrite(LOG_WARNING, "'map_h_from_addresses' overrides 'set_h_from_domain'\n");
767 g_free(route->set_h_from_domain);
768 route->set_h_from_domain = NULL;
769 }
770 if ((route->map_h_reply_to_addresses != NULL)
771 && (route->set_h_reply_to_domain != NULL)) {
772 logwrite(LOG_WARNING, "'map_h_reply_to_addresses' overrides 'set_h_reply_to_domain'\n");
773 g_free(route->set_h_reply_to_domain);
774 route->set_h_reply_to_domain = NULL;
775 }
776 } else {
777 logwrite(LOG_ALERT, "could not open route file %s: %s\n", route->filename, strerror(errno));
778 }
779
780 if (!ok) {
781 g_free(route);
782 route = NULL;
783 }
784
785 return route;
786 }
787
788 static void
789 _g_list_free_all(GList * list)
790 {
503 GList *node; 791 GList *node;
504 GList *tmp_list = parse_list(rval, FALSE); 792 if (list) {
505 793 foreach(list, node)
506 conf.listen_addresses = NULL; 794 g_free(node->data);
507 foreach(tmp_list, node){ 795 g_list_free(list);
508 conf.listen_addresses = 796 }
509 g_list_append(conf.listen_addresses, 797 }
510 parse_interface((gchar *)(node->data), 25)); 798
511 g_free(node->data); 799 void
512 } 800 destroy_route(connect_route * r)
513 g_list_free(tmp_list); 801 {
514 } 802 if (r->filename)
515 else if(strcmp(lval, "ident_trusted_nets") == 0){ 803 g_free(r->filename);
516 #ifdef ENABLE_IDENT 804 if (r->protocol)
805 g_free(r->protocol);
806 if (r->mail_host) {
807 g_free(r->mail_host->address);
808 g_free(r->mail_host);
809 }
810 if (r->wrapper)
811 g_free(r->wrapper);
812 if (r->helo_name)
813 g_free(r->helo_name);
814 _g_list_free_all(r->allowed_mail_locals);
815 _g_list_free_all(r->not_allowed_mail_locals);
816 _g_list_free_all(r->allowed_rcpt_domains);
817 _g_list_free_all(r->not_allowed_rcpt_domains);
818 if (r->set_h_from_domain)
819 g_free(r->set_h_from_domain);
820 if (r->set_h_reply_to_domain)
821 g_free(r->set_h_reply_to_domain);
822 if (r->set_return_path_domain)
823 g_free(r->set_return_path_domain);
824 if (r->map_h_reply_to_addresses)
825 destroy_table(r->map_h_reply_to_addresses);
826 if (r->resolve_list)
827 g_list_free(r->resolve_list);
828 #ifdef ENABLE_AUTH
829 if (r->auth_name)
830 g_free(r->auth_name);
831 if (r->auth_login)
832 g_free(r->auth_login);
833 if (r->auth_secret)
834 g_free(r->auth_secret);
835 #endif
836 #ifdef ENABLE_POP3
837 if (r->pop3_login)
838 g_free(r->pop3_login);
839 #endif
840 if (r->pipe)
841 g_free(r->pipe);
842 g_free(r);
843 }
844
845 GList*
846 read_route_list(GList * rf_list, gboolean is_local_net)
847 {
848 GList *list = NULL;
517 GList *node; 849 GList *node;
518 GList *tmp_list = parse_list(rval, FALSE); 850 uid_t saved_uid, saved_gid;
519 851
520 conf.ident_trusted_nets = NULL; 852 if (!conf.run_as_user) {
521 foreach(tmp_list, node){ 853 set_euidgid(0, 0, &saved_uid, &saved_gid);
522 conf.ident_trusted_nets = 854 }
523 g_list_append(conf.ident_trusted_nets, 855
524 parse_network((gchar *)(node->data), 25)); 856 foreach(rf_list, node) {
525 g_free(node->data); 857 gchar *fname = (gchar *) (node->data);
526 } 858 connect_route *route = read_route(fname, is_local_net);
527 g_list_free(tmp_list); 859 if (route)
528 #else 860 list = g_list_append(list, route);
529 fprintf(stderr, "%s ignored: not compiled with ident support\n", lval); 861 else
530 #endif 862 logwrite(LOG_ALERT, "could not read route configuration %s\n", fname);
531 } 863 }
532 else if((strncmp(lval, "connect_route.", 14) == 0) || 864
533 (strncmp(lval, "online_routes.", 14) == 0)){ 865 /* set uid and gid back */
534 GList *file_list = parse_list(rval, FALSE); 866 if (!conf.run_as_user) {
535 table_pair *pair = create_pair(&(lval[14]), file_list); 867 set_euidgid(saved_uid, saved_gid, NULL, NULL);
536 conf.connect_routes = g_list_append(conf.connect_routes, pair); 868 }
537 } 869
538 else if(strcmp(lval, "local_net_route") == 0){ 870 return list;
539 conf.local_net_routes = parse_list(rval, FALSE); 871 }
540 } 872
541 else if(strcmp(lval, "online_detect") == 0) 873 void
542 conf.online_detect = g_strdup(rval); 874 destroy_route_list(GList * list)
543 else if(strcmp(lval, "online_file") == 0) 875 {
544 conf.online_file = g_strdup(rval); 876 GList *node;
545 else if(strcmp(lval, "online_pipe") == 0) 877
546 conf.online_pipe = g_strdup(rval); 878 foreach(list, node) {
547 else if(strcmp(lval, "mserver_iface") == 0) 879 connect_route *route = (connect_route *) (node->data);
548 conf.mserver_iface = parse_interface(rval, 224); 880 destroy_route(route);
549 else if(strcmp(lval, "do_queue") == 0) 881 }
550 conf.do_queue = parse_boolean(rval); 882 g_list_free(list);
551 else if(strncmp(lval, "get.", 4) == 0){ 883 }
884
552 #ifdef ENABLE_POP3 885 #ifdef ENABLE_POP3
553 table_pair *pair = create_pair_string(&(lval[4]), rval); 886
554 conf.get_names = g_list_append(conf.get_names, pair); 887 get_conf*
555 #else 888 read_get_conf(gchar * filename)
556 fprintf(stderr, "get.<name> ignored: not compiled with pop support\n"); 889 {
557 #endif 890 FILE *in;
558 } 891
559 else if(strncmp(lval, "online_gets.", 12) == 0){ 892 get_conf *gc = g_malloc(sizeof(get_conf));
560 #ifdef ENABLE_POP3 893 memset(gc, 0, sizeof(get_conf));
561 GList *file_list = parse_list(rval, FALSE); 894
562 table_pair *pair = create_pair(&(lval[12]), file_list); 895 gc->server_port = 110;
563 conf.online_gets = g_list_append(conf.online_gets, pair); 896
564 #else 897 if ((in = fopen(filename, "r"))) {
565 fprintf(stderr, "online_gets.<name> ignored: not compiled with pop support\n"); 898 gchar lval[256], rval[2048];
566 #endif 899 while (read_statement(in, lval, 256, rval, 2048)) {
567 } 900 if (strcmp(lval, "protocol") == 0)
568 else if(strcmp(lval, "errmsg_file") == 0) 901 gc->protocol = g_strdup(rval);
569 conf.errmsg_file = g_strdup(rval); 902 else if (strcmp(lval, "server") == 0)
570 else if(strcmp(lval, "warnmsg_file") == 0) 903 gc->server_name = g_strdup(rval);
571 conf.warnmsg_file = g_strdup(rval); 904 else if (strcmp(lval, "port") == 0)
572 else if(strcmp(lval, "warn_intervals") == 0) 905 gc->server_port = atoi(rval);
573 conf.warn_intervals = parse_list(rval, FALSE); 906 else if (strcmp(lval, "wrapper") == 0)
574 else if(strcmp(lval, "max_defer_time") == 0){ 907 gc->wrapper = g_strdup(rval);
575 gint dummy; 908 else if (strcmp(lval, "user") == 0)
576 gint ival = time_interval(rval, &dummy); 909 gc->login_user = g_strdup(rval);
577 if(ival < 0) 910 else if (strcmp(lval, "pass") == 0)
578 fprintf(stderr, "invalid time interval for 'max_defer_time': %s\n", rval); 911 gc->login_pass = g_strdup(rval);
579 else 912 else if (strcmp(lval, "address") == 0)
580 conf.max_defer_time = ival; 913 gc->address = create_address_qualified(rval, TRUE, conf.host_name);
581 }else if(strcmp(lval, "log_user") == 0) 914 else if (strcmp(lval, "return_path") == 0)
582 conf.log_user = g_strdup(rval); 915 gc->return_path = create_address_qualified(rval, TRUE, conf.host_name);
583 916 else if (strcmp(lval, "do_ssl") == 0)
584 else 917 /* we ignore this. This option is used by sqilconf */
585 fprintf(stderr, "var '%s' not (yet) known, ignored\n", lval); 918 ;
586 } 919 else if (strcmp(lval, "do_keep") == 0)
587 fclose(in); 920 gc->do_keep = parse_boolean(rval);
588 921 else if (strcmp(lval, "do_uidl") == 0)
589 if(conf.errmsg_file == NULL) 922 gc->do_uidl = parse_boolean(rval);
590 conf.errmsg_file = g_strdup(DATA_DIR"/tpl/failmsg.tpl"); 923 else if (strcmp(lval, "do_uidl_dele") == 0)
591 if(conf.warnmsg_file == NULL) 924 gc->do_uidl_dele = parse_boolean(rval);
592 conf.warnmsg_file = g_strdup(DATA_DIR"/tpl/warnmsg.tpl"); 925 else if (strcmp(lval, "max_size") == 0)
593 926 gc->max_size = atoi(rval);
594 if(conf.lock_dir == NULL) 927 else if (strcmp(lval, "max_size_delete") == 0)
595 conf.lock_dir = g_strdup_printf("%s/lock/", conf.spool_dir); 928 gc->max_size = parse_boolean(rval);
596 929 else if (strcmp(lval, "max_count") == 0)
597 if(conf.mbox_default == NULL) 930 gc->max_count = atoi(rval);
598 conf.mbox_default = g_strdup("mbox"); 931 else if (strcmp(lval, "resolve_list") == 0)
599 932 gc->resolve_list = parse_resolve_list(rval);
600 if(conf.warn_intervals == NULL) 933 else
601 conf.warn_intervals = parse_list("1h;4h;8h;1d;2d;3d", FALSE); 934 logwrite(LOG_WARNING, "var '%s' not (yet) known, ignored\n", lval);
602 935 }
603 return TRUE; 936 fclose(in);
604 }else 937
605 fprintf(stderr, "could not open config file %s: %s\n", filename, strerror(errno)); 938 if (gc->resolve_list == NULL) {
606 return FALSE;
607 }
608
609 connect_route *read_route(gchar *filename, gboolean is_local_net)
610 {
611 gboolean ok = FALSE;
612 FILE *in;
613
614 connect_route *route = g_malloc(sizeof(connect_route));
615 memset(route, 0, sizeof(connect_route));
616
617 DEBUG(5) debugf("read_route, filename = %s\n", filename);
618
619 route->filename = g_strdup(filename);
620 route->name = g_strdup(filename); /* quick hack */
621
622 route->protocol = g_strdup("smtp");
623 route->expand_h_sender_address = TRUE;
624
625 route->is_local_net = is_local_net;
626
627 route->do_pipelining = TRUE;
628
629 if((in = fopen(route->filename, "r"))){
630 gchar lval[256], rval[2048];
631 while(read_statement(in, lval, 256, rval, 2048)){
632 if(strcmp(lval, "protocol") == 0)
633 route->protocol = g_strdup(rval);
634 else if(strcmp(lval, "mail_host") == 0)
635 route->mail_host = parse_interface(rval, conf.remote_port);
636 else if(strcmp(lval, "helo_name") == 0)
637 route->helo_name = g_strdup(rval);
638 else if(strcmp(lval, "wrapper") == 0)
639 route->wrapper = g_strdup(rval);
640 else if(strcmp(lval, "connect_error_fail") == 0)
641 route->connect_error_fail = parse_boolean(rval);
642 else if(strcmp(lval, "do_correct_helo") == 0)
643 route->do_correct_helo = parse_boolean(rval);
644 else if(strcmp(lval, "do_pipelining") == 0)
645 route->do_pipelining = parse_boolean(rval);
646 else if(strcmp(lval, "allowed_return_paths") == 0)
647 route->allowed_return_paths = parse_address_list(rval, TRUE);
648 else if(strcmp(lval, "allowed_mail_locals") == 0)
649 route->allowed_mail_locals = parse_list(rval, TRUE);
650 else if(strcmp(lval, "not_allowed_return_paths") == 0)
651 route->not_allowed_return_paths = parse_address_list(rval, TRUE);
652 else if(strcmp(lval, "not_allowed_mail_locals") == 0)
653 route->not_allowed_mail_locals = parse_list(rval, TRUE);
654 else if(strcmp(lval, "allowed_rcpt_domains") == 0)
655 route->allowed_rcpt_domains = parse_list(rval, TRUE);
656 else if(strcmp(lval, "not_allowed_rcpt_domains") == 0)
657 route->not_allowed_rcpt_domains = parse_list(rval, TRUE);
658 else if(strcmp(lval, "set_h_from_domain") == 0)
659 route->set_h_from_domain = g_strdup(rval);
660 else if(strcmp(lval, "set_h_reply_to_domain") == 0)
661 route->set_h_reply_to_domain = g_strdup(rval);
662 else if(strcmp(lval, "set_return_path_domain") == 0)
663 route->set_return_path_domain = g_strdup(rval);
664 else if(strcmp(lval, "map_return_path_addresses") == 0){
665 GList *node, *list;
666
667 list = parse_list(rval, TRUE);
668 foreach(list, node){
669 gchar *item = (gchar *)(node->data);
670 table_pair *pair = parse_table_pair(item, ':');
671 address *addr = create_address((gchar *)(pair->value), TRUE);
672 g_free(pair->value);
673 pair->value = (gpointer *)addr;
674 route->map_return_path_addresses =
675 g_list_append(route->map_return_path_addresses, pair);
676 g_free(item);
677 }
678 g_list_free(list);
679 }
680 else if(strcmp(lval, "map_h_from_addresses") == 0){
681 GList *list, *node;
682
683 list = parse_list(rval, TRUE);
684 foreach(list, node){
685 gchar *item = (gchar *)(node->data);
686 table_pair *pair = parse_table_pair(item, ':');
687 route->map_h_from_addresses =
688 g_list_append(route->map_h_from_addresses, pair);
689 g_free(item);
690 }
691 g_list_free(list);
692 }
693 else if(strcmp(lval, "map_h_reply_to_addresses") == 0){
694 GList *list, *node;
695
696 list = parse_list(rval, TRUE);
697 foreach(list, node){
698 gchar *item = (gchar *)(node->data);
699 table_pair *pair = parse_table_pair(item, ':');
700 route->map_h_reply_to_addresses =
701 g_list_append(route->map_h_reply_to_addresses, pair);
702 g_free(item);
703 }
704 g_list_free(list);
705 }
706 else if(strcmp(lval, "map_h_mail_followup_to_addresses") == 0){
707 GList *list, *node;
708
709 list = parse_list(rval, TRUE);
710 foreach(list, node){
711 gchar *item = (gchar *)(node->data);
712 table_pair *pair = parse_table_pair(item, ':');
713 route->map_h_mail_followup_to_addresses =
714 g_list_append(route->map_h_mail_followup_to_addresses, pair);
715 g_free(item);
716 }
717 g_list_free(list);
718 }
719 else if(strcmp(lval, "expand_h_sender_domain") == 0){
720 route->expand_h_sender_domain = parse_boolean(rval);
721 }
722 else if(strcmp(lval, "expand_h_sender_address") == 0){
723 route->expand_h_sender_address = parse_boolean(rval);
724 }
725 else if(strcmp(lval, "resolve_list") == 0)
726 route->resolve_list = parse_resolve_list(rval);
727 else if(strcmp(lval, "do_ssl") == 0){
728 /* we ignore this. This option is used by sqilconf */
729 ;
730 }
731 #ifdef ENABLE_AUTH
732 else if(strcmp(lval, "auth_name") == 0){
733 route->auth_name = g_strdup(rval);
734 }
735 else if(strcmp(lval, "auth_login") == 0){
736 route->auth_login = g_strdup(rval);
737 }
738 else if(strcmp(lval, "auth_secret") == 0){
739 route->auth_secret = g_strdup(rval);
740 }
741 #else
742 else if((strcmp(lval, "auth_name") == 0) ||
743 (strcmp(lval, "auth_login") == 0) ||
744 (strcmp(lval, "auth_secret") == 0)){
745 logwrite(LOG_WARNING, "%s ignored: not compiled with auth support.\n", lval);
746 }
747 #endif
748 else if(strcmp(lval, "pop3_login") == 0){
749 #ifdef ENABLE_POP3
750 route->pop3_login = g_strdup(rval);
751 #else
752 logwrite(LOG_WARNING, "pop3_login ignored: not compiled with pop support.\n");
753 #endif
754 }
755 else if(strcmp(lval, "pipe") == 0){
756 route->pipe = g_strdup(rval);
757 }
758 else if(strcmp(lval, "pipe_fromline") == 0){
759 route->pipe_fromline = parse_boolean(rval);
760 }
761 else if(strcmp(lval, "pipe_fromhack") == 0){
762 route->pipe_fromhack = parse_boolean(rval);
763 }
764 else if(strcmp(lval, "last_route") == 0){
765 route->last_route = parse_boolean(rval);
766 }
767 else
768 logwrite(LOG_WARNING, "var '%s' not (yet) known, ignored\n", lval);
769 }
770
771 if(route->resolve_list == NULL){
772 if(is_local_net){
773 route->resolve_list =
774 g_list_append(NULL, resolve_byname);
775 }else{
776 #ifdef ENABLE_RESOLVER 939 #ifdef ENABLE_RESOLVER
777 route->resolve_list = 940 gc->resolve_list = g_list_append(NULL, resolve_dns_a);
778 g_list_append(route->resolve_list, resolve_dns_mx); 941 #endif
779 route->resolve_list = 942 gc->resolve_list = g_list_append(NULL, resolve_byname);
780 g_list_append(route->resolve_list, resolve_dns_a); 943 }
781 #endif 944
782 route->resolve_list = 945 if (gc->protocol == NULL)
783 g_list_append(route->resolve_list, resolve_byname); 946 gc->protocol = g_strdup("pop3");
784 } 947 return gc;
785 } 948 }
786 fclose(in); 949 logwrite(LOG_ALERT, "could not open get file %s: %s\n", filename, strerror(errno));
787 ok = TRUE; 950
788 951 g_free(gc);
789 /* warn user about misconfigurations: */ 952 return NULL;
790 if((route->map_h_from_addresses != NULL) && (route->set_h_from_domain != NULL)){ 953 }
791 logwrite(LOG_WARNING, "'map_h_from_addresses' overrides 'set_h_from_domain'\n"); 954
792 g_free(route->set_h_from_domain); 955 void
793 route->set_h_from_domain = NULL; 956 destroy_get_conf(get_conf * gc)
794 } 957 {
795 if((route->map_h_reply_to_addresses != NULL) && (route->set_h_reply_to_domain != NULL)){ 958 if (gc->protocol)
796 logwrite(LOG_WARNING, "'map_h_reply_to_addresses' overrides 'set_h_reply_to_domain'\n"); 959 g_free(gc->protocol);
797 g_free(route->set_h_reply_to_domain); 960 if (gc->server_name)
798 route->set_h_reply_to_domain = NULL; 961 g_free(gc->server_name);
799 } 962 if (gc->login_user)
800 }else{ 963 g_free(gc->login_user);
801 logwrite(LOG_ALERT, "could not open route file %s: %s\n", 964 if (gc->login_pass)
802 route->filename, strerror(errno)); 965 g_free(gc->login_pass);
803 } 966 if (gc->wrapper)
804 967 g_free(gc->wrapper);
805 if(!ok){ 968 if (gc->address)
806 g_free(route); 969 destroy_address(gc->address);
807 route = NULL; 970 if (gc->return_path)
808 } 971 destroy_address(gc->return_path);
809 972 if (gc->resolve_list)
810 return route; 973 g_list_free(gc->resolve_list);
811 } 974 g_free(gc);
812 975 }
813 static 976
814 void _g_list_free_all(GList *list) 977 #endif
815 { 978
816 GList *node; 979 connect_route*
817 if(list){ 980 create_local_route()
818 foreach(list, node) 981 {
819 g_free(node->data); 982 connect_route *route;
820 g_list_free(list); 983
821 } 984 route = g_malloc(sizeof(connect_route));
822 } 985 if (route) {
823 986 memset(route, 0, sizeof(connect_route));
824 void destroy_route(connect_route *r) 987 route->protocol = g_strdup("smtp");
825 { 988 route->is_local_net = TRUE;
826 if(r->filename) g_free(r->filename); 989 route->name = g_strdup("local_net (default)");
827 if(r->protocol) g_free(r->protocol); 990 route->expand_h_sender_address = TRUE;
828 if(r->mail_host){ 991 route->resolve_list = g_list_append(NULL, resolve_byname);
829 g_free(r->mail_host->address); 992 route->connect_error_fail = TRUE;
830 g_free(r->mail_host); 993 }
831 } 994 return route;
832 if(r->wrapper) g_free(r->wrapper); 995 }
833 if(r->helo_name) g_free(r->helo_name);
834 _g_list_free_all(r->allowed_mail_locals);
835 _g_list_free_all(r->not_allowed_mail_locals);
836 _g_list_free_all(r->allowed_rcpt_domains);
837 _g_list_free_all(r->not_allowed_rcpt_domains);
838 if(r->set_h_from_domain) g_free(r->set_h_from_domain);
839 if(r->set_h_reply_to_domain) g_free(r->set_h_reply_to_domain);
840 if(r->set_return_path_domain) g_free(r->set_return_path_domain);
841 if(r->map_h_reply_to_addresses) destroy_table(r->map_h_reply_to_addresses);
842 if(r->resolve_list) g_list_free(r->resolve_list);
843 #ifdef ENABLE_AUTH
844 if(r->auth_name) g_free(r->auth_name);
845 if(r->auth_login) g_free(r->auth_login);
846 if(r->auth_secret) g_free(r->auth_secret);
847 #endif
848 #ifdef ENABLE_POP3
849 if(r->pop3_login) g_free(r->pop3_login);
850 #endif
851 if(r->pipe) g_free(r->pipe);
852 g_free(r);
853 }
854
855 GList *read_route_list(GList *rf_list, gboolean is_local_net)
856 {
857 GList *list = NULL;
858 GList *node;
859 uid_t saved_uid, saved_gid;
860
861 if(!conf.run_as_user){
862 set_euidgid(0, 0, &saved_uid, &saved_gid);
863 }
864
865 foreach(rf_list, node){
866 gchar *fname = (gchar *)(node->data);
867 connect_route *route = read_route(fname, is_local_net);
868 if(route)
869 list = g_list_append(list, route);
870 else
871 logwrite(LOG_ALERT, "could not read route configuration %s\n", fname);
872 }
873
874 /* set uid and gid back */
875 if(!conf.run_as_user){
876 set_euidgid(saved_uid, saved_gid, NULL, NULL);
877 }
878
879 return list;
880 }
881
882 void destroy_route_list(GList *list)
883 {
884 GList *node;
885
886 foreach(list, node){
887 connect_route *route = (connect_route *)(node->data);
888 destroy_route(route);
889 }
890 g_list_free(list);
891 }
892
893 #ifdef ENABLE_POP3
894
895 get_conf *read_get_conf(gchar *filename)
896 {
897 FILE *in;
898
899 get_conf *gc = g_malloc(sizeof(get_conf));
900 memset(gc, 0, sizeof(get_conf));
901
902 gc->server_port = 110;
903
904 if((in = fopen(filename, "r"))){
905 gchar lval[256], rval[2048];
906 while(read_statement(in, lval, 256, rval, 2048)){
907 if(strcmp(lval, "protocol") == 0)
908 gc->protocol = g_strdup(rval);
909 else if(strcmp(lval, "server") == 0)
910 gc->server_name = g_strdup(rval);
911 else if(strcmp(lval, "port") == 0)
912 gc->server_port = atoi(rval);
913 else if(strcmp(lval, "wrapper") == 0)
914 gc->wrapper = g_strdup(rval);
915 else if(strcmp(lval, "user") == 0)
916 gc->login_user = g_strdup(rval);
917 else if(strcmp(lval, "pass") == 0)
918 gc->login_pass = g_strdup(rval);
919 else if(strcmp(lval, "address") == 0)
920 gc->address = create_address_qualified(rval, TRUE, conf.host_name);
921 else if(strcmp(lval, "return_path") == 0)
922 gc->return_path = create_address_qualified(rval, TRUE, conf.host_name);
923 else if(strcmp(lval, "do_ssl") == 0)
924 /* we ignore this. This option is used by sqilconf */
925 ;
926 else if(strcmp(lval, "do_keep") == 0)
927 gc->do_keep = parse_boolean(rval);
928 else if(strcmp(lval, "do_uidl") == 0)
929 gc->do_uidl = parse_boolean(rval);
930 else if(strcmp(lval, "do_uidl_dele") == 0)
931 gc->do_uidl_dele = parse_boolean(rval);
932 else if(strcmp(lval, "max_size") == 0)
933 gc->max_size = atoi(rval);
934 else if(strcmp(lval, "max_size_delete") == 0)
935 gc->max_size = parse_boolean(rval);
936 else if(strcmp(lval, "max_count") == 0)
937 gc->max_count = atoi(rval);
938 else if(strcmp(lval, "resolve_list") == 0)
939 gc->resolve_list = parse_resolve_list(rval);
940 else
941 logwrite(LOG_WARNING, "var '%s' not (yet) known, ignored\n", lval);
942 }
943 fclose(in);
944
945 if(gc->resolve_list == NULL){
946 #ifdef ENABLE_RESOLVER
947 gc->resolve_list =
948 g_list_append(NULL, resolve_dns_a);
949 #endif
950 gc->resolve_list =
951 g_list_append(NULL, resolve_byname);
952 }
953
954 if(gc->protocol == NULL)
955 gc->protocol = g_strdup("pop3");
956 return gc;
957 }
958 logwrite(LOG_ALERT, "could not open get file %s: %s\n", filename, strerror(errno));
959
960 g_free(gc);
961 return NULL;
962 }
963
964 void destroy_get_conf(get_conf *gc)
965 {
966 if(gc->protocol) g_free(gc->protocol);
967 if(gc->server_name) g_free(gc->server_name);
968 if(gc->login_user) g_free(gc->login_user);
969 if(gc->login_pass) g_free(gc->login_pass);
970 if(gc->wrapper) g_free(gc->wrapper);
971 if(gc->address) destroy_address(gc->address);
972 if(gc->return_path) destroy_address(gc->return_path);
973 if(gc->resolve_list) g_list_free(gc->resolve_list);
974 g_free(gc);
975 }
976
977 #endif
978
979 connect_route *create_local_route()
980 {
981 connect_route *route;
982
983 route = g_malloc(sizeof(connect_route));
984 if(route){
985 memset(route, 0, sizeof(connect_route));
986 route->protocol = g_strdup("smtp");
987 route->is_local_net = TRUE;
988 route->name = g_strdup("local_net (default)");
989 route->expand_h_sender_address = TRUE;
990 route->resolve_list =
991 g_list_append(NULL, resolve_byname);
992 route->connect_error_fail = TRUE;
993 }
994 return route;
995 }