file permissions and client buffer overflow fix
[fwknop.git] / server / config_init.c
1 /*
2  ******************************************************************************
3  *
4  * File:    config_init.c
5  *
6  * Author:  Damien Stuart
7  *
8  * Purpose: Command-line and config file processing for fwknop server.
9  *
10  * Copyright 2010 Damien Stuart (dstuart@dstuart.org)
11  *
12  *  License (GNU Public License):
13  *
14  *  This program is free software; you can redistribute it and/or
15  *  modify it under the terms of the GNU General Public License
16  *  as published by the Free Software Foundation; either version 2
17  *  of the License, or (at your option) any later version.
18  *
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software
26  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
27  *  USA
28  *
29  ******************************************************************************
30 */
31 #include "fwknopd_common.h"
32 #include "config_init.h"
33 #include "access.h"
34 #include "cmd_opts.h"
35 #include "utils.h"
36 #include "log_msg.h"
37
38 /* Check to see if an integer variable has a value that is within a
39  * specific range
40 */
41 static void
42 range_check(fko_srv_options_t *opts, char *var, char *val, int low, int high)
43 {
44     if (low > atoi(val) || high < atoi(val))
45     {
46         fprintf(stderr, "[*] var %s value '%s' not in the range %d-%d\n",
47             var, val, low, high);
48         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
49     }
50     return;
51 }
52
53 /* Take an index and a string value. malloc the space for the value
54  * and assign it to the array at the specified index.
55 */
56 static void
57 set_config_entry(fko_srv_options_t *opts, const int var_ndx, const char *value)
58 {
59     int space_needed;
60
61     /* Sanity check the index value.
62     */
63     if(var_ndx < 0 || var_ndx >= NUMBER_OF_CONFIG_ENTRIES)
64     {
65         fprintf(stderr, "Index value of %i is not valid\n", var_ndx);
66         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
67     }
68
69     /* If this particular entry was already set (i.e. not NULL), then
70      * assume it needs to be freed first.
71     */
72     if(opts->config[var_ndx] != NULL)
73         free(opts->config[var_ndx]);
74
75     /* If we are setting it to NULL, do it and be done.
76     */
77     if(value == NULL)
78     {
79         opts->config[var_ndx] = NULL;
80         return;
81     }
82
83     /* Otherwise, make the space we need and set it.
84     */
85     space_needed = strlen(value) + 1;
86
87     opts->config[var_ndx] = malloc(space_needed);
88
89     if(opts->config[var_ndx] == NULL)
90     {
91         fprintf(stderr, "*Fatal memory allocation error!\n");
92         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
93     }
94
95     strlcpy(opts->config[var_ndx], value, space_needed);
96
97     return;
98 }
99
100 /* Given a config parameter name, return its index or -1 if not found.
101 */
102 static int
103 config_entry_index(const fko_srv_options_t *opts, const char *var)
104 {
105     int i;
106
107     for(i=0; i<NUMBER_OF_CONFIG_ENTRIES; i++)
108         if(opts->config[i] != NULL && CONF_VAR_IS(var, config_map[i]))
109             return(i);
110
111     return(-1);
112 }
113
114 /* Free the config memory
115 */
116 void
117 free_configs(fko_srv_options_t *opts)
118 {
119     int i;
120
121     free_acc_stanzas(opts);
122
123     for(i=0; i<NUMBER_OF_CONFIG_ENTRIES; i++)
124         if(opts->config[i] != NULL)
125             free(opts->config[i]);
126 }
127
128 static void
129 validate_int_var_ranges(fko_srv_options_t *opts)
130 {
131     range_check(opts, "PCAP_LOOP_SLEEP", opts->config[CONF_PCAP_LOOP_SLEEP],
132         1, RCHK_MAX_PCAP_LOOP_SLEEP);
133     range_check(opts, "MAX_SPA_PACKET_AGE", opts->config[CONF_MAX_SPA_PACKET_AGE],
134         1, RCHK_MAX_SPA_PACKET_AGE);
135     range_check(opts, "MAX_SNIFF_BYTES", opts->config[CONF_MAX_SNIFF_BYTES],
136         1, RCHK_MAX_SNIFF_BYTES);
137     range_check(opts, "TCPSERV_PORT", opts->config[CONF_TCPSERV_PORT],
138         1, RCHK_MAX_TCPSERV_PORT);
139
140 #if FIREWALL_IPFW
141     range_check(opts, "IPFW_START_RULE_NUM", opts->config[CONF_IPFW_START_RULE_NUM],
142         0, RCHK_MAX_IPFW_START_RULE_NUM);
143     range_check(opts, "IPFW_MAX_RULES", opts->config[CONF_IPFW_MAX_RULES],
144         1, RCHK_MAX_IPFW_MAX_RULES);
145     range_check(opts, "IPFW_ACTIVE_SET_NUM", opts->config[CONF_IPFW_ACTIVE_SET_NUM],
146         0, RCHK_MAX_IPFW_SET_NUM);
147     range_check(opts, "IPFW_EXPIRE_SET_NUM", opts->config[CONF_IPFW_EXPIRE_SET_NUM],
148         0, RCHK_MAX_IPFW_SET_NUM);
149     range_check(opts, "IPFW_EXPIRE_PURGE_INTERVAL",
150         opts->config[CONF_IPFW_EXPIRE_PURGE_INTERVAL],
151         1, RCHK_MAX_IPFW_PURGE_INTERVAL);
152
153     /* Make sure the active and expire sets are not identical whenever
154      * they are non-zero
155     */
156     if((atoi(opts->config[CONF_IPFW_ACTIVE_SET_NUM]) > 0
157             && atoi(opts->config[CONF_IPFW_EXPIRE_SET_NUM]) > 0)
158             && atoi(opts->config[CONF_IPFW_ACTIVE_SET_NUM])
159                 == atoi(opts->config[CONF_IPFW_EXPIRE_SET_NUM]))
160     {
161         fprintf(stderr,
162                 "[*] Cannot set identical ipfw active and expire sets.\n");
163         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
164     }
165
166 #elif FIREWALL_PF
167     range_check(opts, "PF_EXPIRE_INTERVAL", opts->config[CONF_PF_EXPIRE_INTERVAL],
168         1, RCHK_MAX_PF_EXPIRE_INTERVAL);
169
170 #endif /* FIREWALL type */
171
172     return;
173 }
174
175 /* Parse the config file...
176 */
177 static void
178 parse_config_file(fko_srv_options_t *opts, const char *config_file)
179 {
180     FILE           *cfile_ptr;
181     unsigned int    numLines = 0;
182     unsigned int    i, good_ent;
183     int             cndx;
184
185     char            conf_line_buf[MAX_LINE_LEN] = {0};
186     char            var[MAX_LINE_LEN]  = {0};
187     char            val[MAX_LINE_LEN]  = {0};
188     char            tmp1[MAX_LINE_LEN] = {0};
189     char            tmp2[MAX_LINE_LEN] = {0};
190
191     struct stat     st;
192
193     /* First see if the config file exists.  If it doesn't, complain
194      * and go on with program defaults.
195     */
196     if(stat(config_file, &st) != 0)
197     {
198         fprintf(stderr, "[*] Config file: '%s' was not found.\n",
199             config_file);
200         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
201     }
202
203     verify_file_perms_ownership(config_file);
204
205     if ((cfile_ptr = fopen(config_file, "r")) == NULL)
206     {
207         fprintf(stderr, "[*] Could not open config file: %s\n",
208             config_file);
209         perror(NULL);
210
211         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
212     }
213
214     while ((fgets(conf_line_buf, MAX_LINE_LEN, cfile_ptr)) != NULL)
215     {
216         numLines++;
217         conf_line_buf[MAX_LINE_LEN-1] = '\0';
218
219         /* Get past comments and empty lines (note: we only look at the
220          * first character.
221         */
222         if(IS_EMPTY_LINE(conf_line_buf[0]))
223             continue;
224
225         if(sscanf(conf_line_buf, "%s %[^;\n\r]", var, val) != 2)
226         {
227             fprintf(stderr,
228                 "*Invalid config file entry in %s at line %i.\n - '%s'",
229                 config_file, numLines, conf_line_buf
230             );
231             continue;
232         }
233
234         /*
235         fprintf(stderr,
236             "CONF FILE: %s, LINE: %s\tVar: %s, Val: '%s'\n",
237             config_file, conf_line_buf, var, val
238         );
239         */
240
241         good_ent = 0;
242         for(i=0; i<NUMBER_OF_CONFIG_ENTRIES; i++)
243         {
244             if(CONF_VAR_IS(config_map[i], var))
245             {
246                 /* First check to see if we need to do a varable expansion
247                  * on this value.  Note: this only supports one expansion and
248                  * only if the value starts with the variable.
249                 */
250                 if(*val == '$')
251                 {
252                     if(sscanf((val+1), "%[A-Z_]%s", tmp1, tmp2))
253                     {
254                         if((cndx = config_entry_index(opts, tmp1)) >= 0)
255                         {
256                             strlcpy(val, opts->config[cndx], MAX_LINE_LEN);
257                             strlcat(val, tmp2, MAX_LINE_LEN);
258                         }
259                     }
260                 }
261
262                 set_config_entry(opts, i, val);
263                 good_ent++;
264                 break;
265             }
266         }
267
268         if(good_ent == 0)
269             fprintf(stderr,
270                 "*Ignoring unknown configuration parameter: '%s' in %s\n",
271                 var, config_file
272             );
273     }
274
275     fclose(cfile_ptr);
276
277     return;
278 }
279
280 /* Set defaults, and do sanity and bounds checks for the various options.
281 */
282 static void
283 validate_options(fko_srv_options_t *opts)
284 {
285     char tmp_path[MAX_PATH_LEN];
286
287     /* If no conf dir is set in the config file, use the default.
288     */
289     if(opts->config[CONF_FWKNOP_CONF_DIR] == NULL)
290         set_config_entry(opts, CONF_FWKNOP_CONF_DIR, DEF_CONF_DIR);
291
292     /* If no access.conf path was specified on the command line or set in
293      * the config file, use the default.
294     */
295     if(opts->config[CONF_ACCESS_FILE] == NULL)
296         set_config_entry(opts, CONF_ACCESS_FILE, DEF_ACCESS_FILE);
297
298     /* If the pid and digest cache files where not set in the config file or
299      * via command-line, then grab the defaults. Start with RUN_DIR as the
300      * files may depend on that.
301     */
302     if(opts->config[CONF_FWKNOP_RUN_DIR] == NULL)
303         set_config_entry(opts, CONF_FWKNOP_RUN_DIR, DEF_RUN_DIR);
304
305     if(opts->config[CONF_FWKNOP_PID_FILE] == NULL)
306     {
307         strlcpy(tmp_path, opts->config[CONF_FWKNOP_RUN_DIR], MAX_PATH_LEN);
308
309         if(tmp_path[strlen(tmp_path)-1] != '/')
310             strlcat(tmp_path, "/", MAX_PATH_LEN);
311
312         strlcat(tmp_path, DEF_PID_FILENAME, MAX_PATH_LEN);
313
314         set_config_entry(opts, CONF_FWKNOP_PID_FILE, tmp_path);
315     }
316
317 #if USE_FILE_CACHE
318     if(opts->config[CONF_DIGEST_FILE] == NULL)
319 #else
320     if(opts->config[CONF_DIGEST_DB_FILE] == NULL)
321 #endif
322     {
323         strlcpy(tmp_path, opts->config[CONF_FWKNOP_RUN_DIR], MAX_PATH_LEN);
324
325         if(tmp_path[strlen(tmp_path)-1] != '/')
326             strlcat(tmp_path, "/", MAX_PATH_LEN);
327
328
329 #if USE_FILE_CACHE
330         strlcat(tmp_path, DEF_DIGEST_CACHE_FILENAME, MAX_PATH_LEN);
331         set_config_entry(opts, CONF_DIGEST_FILE, tmp_path);
332 #else
333         strlcat(tmp_path, DEF_DIGEST_CACHE_DB_FILENAME, MAX_PATH_LEN);
334         set_config_entry(opts, CONF_DIGEST_DB_FILE, tmp_path);
335 #endif
336     }
337
338     /* Set remaining require CONF_ vars if they are not already set.  */
339
340     /* PCAP capture interface.
341     */
342     if(opts->config[CONF_PCAP_INTF] == NULL)
343         set_config_entry(opts, CONF_PCAP_INTF, DEF_INTERFACE);
344
345     /* PCAP Promiscuous mode.
346     */
347     if(opts->config[CONF_ENABLE_PCAP_PROMISC] == NULL)
348         set_config_entry(opts, CONF_ENABLE_PCAP_PROMISC,
349             DEF_ENABLE_PCAP_PROMISC);
350
351     /* The packet count argument to pcap_dispatch()
352     */
353     if(opts->config[CONF_PCAP_DISPATCH_COUNT] == NULL)
354         set_config_entry(opts, CONF_PCAP_DISPATCH_COUNT,
355             DEF_PCAP_DISPATCH_COUNT);
356
357     /* Microseconds to sleep between pcap loop iterations
358     */
359     if(opts->config[CONF_PCAP_LOOP_SLEEP] == NULL)
360         set_config_entry(opts, CONF_PCAP_LOOP_SLEEP,
361             DEF_PCAP_LOOP_SLEEP);
362
363     /* PCAP Filter.
364     */
365     if(opts->config[CONF_PCAP_FILTER] == NULL)
366         set_config_entry(opts, CONF_PCAP_FILTER, DEF_PCAP_FILTER);
367
368     /* Enable SPA packet aging.
369     */
370     if(opts->config[CONF_ENABLE_SPA_PACKET_AGING] == NULL)
371         set_config_entry(opts, CONF_ENABLE_SPA_PACKET_AGING,
372             DEF_ENABLE_SPA_PACKET_AGING);
373
374     /* SPA packet age.
375     */
376     if(opts->config[CONF_MAX_SPA_PACKET_AGE] == NULL)
377         set_config_entry(opts, CONF_MAX_SPA_PACKET_AGE,
378             DEF_MAX_SPA_PACKET_AGE);
379
380
381     /* Enable digest persistence.
382     */
383     if(opts->config[CONF_ENABLE_DIGEST_PERSISTENCE] == NULL)
384         set_config_entry(opts, CONF_ENABLE_DIGEST_PERSISTENCE,
385             DEF_ENABLE_DIGEST_PERSISTENCE);
386
387     /* Max sniff bytes.
388     */
389     if(opts->config[CONF_MAX_SNIFF_BYTES] == NULL)
390         set_config_entry(opts, CONF_MAX_SNIFF_BYTES, DEF_MAX_SNIFF_BYTES);
391
392 #if FIREWALL_IPTABLES
393     /* Enable IPT forwarding.
394     */
395     if(opts->config[CONF_ENABLE_IPT_FORWARDING] == NULL)
396         set_config_entry(opts, CONF_ENABLE_IPT_FORWARDING,
397             DEF_ENABLE_IPT_FORWARDING);
398
399     /* Enable IPT local NAT.
400     */
401     if(opts->config[CONF_ENABLE_IPT_LOCAL_NAT] == NULL)
402         set_config_entry(opts, CONF_ENABLE_IPT_LOCAL_NAT,
403             DEF_ENABLE_IPT_LOCAL_NAT);
404
405     /* Enable IPT SNAT.
406     */
407     if(opts->config[CONF_ENABLE_IPT_SNAT] == NULL)
408         set_config_entry(opts, CONF_ENABLE_IPT_SNAT,
409             DEF_ENABLE_IPT_SNAT);
410
411     /* Enable IPT OUTPUT.
412     */
413     if(opts->config[CONF_ENABLE_IPT_OUTPUT] == NULL)
414         set_config_entry(opts, CONF_ENABLE_IPT_OUTPUT,
415             DEF_ENABLE_IPT_OUTPUT);
416
417     /* Flush IPT at init.
418     */
419     if(opts->config[CONF_FLUSH_IPT_AT_INIT] == NULL)
420         set_config_entry(opts, CONF_FLUSH_IPT_AT_INIT, DEF_FLUSH_IPT_AT_INIT);
421
422     /* Flush IPT at exit.
423     */
424     if(opts->config[CONF_FLUSH_IPT_AT_EXIT] == NULL)
425         set_config_entry(opts, CONF_FLUSH_IPT_AT_EXIT, DEF_FLUSH_IPT_AT_EXIT);
426
427     /* IPT input access.
428     */
429     if(opts->config[CONF_IPT_INPUT_ACCESS] == NULL)
430         set_config_entry(opts, CONF_IPT_INPUT_ACCESS,
431             DEF_IPT_INPUT_ACCESS);
432
433     /* IPT output access.
434     */
435     if(opts->config[CONF_IPT_OUTPUT_ACCESS] == NULL)
436         set_config_entry(opts, CONF_IPT_OUTPUT_ACCESS,
437             DEF_IPT_OUTPUT_ACCESS);
438
439     /* IPT forward access.
440     */
441     if(opts->config[CONF_IPT_FORWARD_ACCESS] == NULL)
442         set_config_entry(opts, CONF_IPT_FORWARD_ACCESS,
443             DEF_IPT_FORWARD_ACCESS);
444
445     /* IPT dnat access.
446     */
447     if(opts->config[CONF_IPT_DNAT_ACCESS] == NULL)
448         set_config_entry(opts, CONF_IPT_DNAT_ACCESS,
449             DEF_IPT_DNAT_ACCESS);
450
451     /* IPT snat access.
452     */
453     if(opts->config[CONF_IPT_SNAT_ACCESS] == NULL)
454         set_config_entry(opts, CONF_IPT_SNAT_ACCESS,
455             DEF_IPT_SNAT_ACCESS);
456
457     /* IPT masquerade access.
458     */
459     if(opts->config[CONF_IPT_MASQUERADE_ACCESS] == NULL)
460         set_config_entry(opts, CONF_IPT_MASQUERADE_ACCESS,
461             DEF_IPT_MASQUERADE_ACCESS);
462
463     /* Check for the iptables 'comment' match at init time
464     */
465     if(opts->config[CONF_ENABLE_IPT_COMMENT_CHECK] == NULL)
466         set_config_entry(opts, CONF_ENABLE_IPT_COMMENT_CHECK,
467             DEF_ENABLE_IPT_COMMENT_CHECK);
468
469 #elif FIREWALL_IPFW
470
471     /* Flush ipfw rules at init.
472     */
473     if(opts->config[CONF_FLUSH_IPFW_AT_INIT] == NULL)
474         set_config_entry(opts, CONF_FLUSH_IPFW_AT_INIT, DEF_FLUSH_IPFW_AT_INIT);
475
476     /* Flush ipfw rules at exit.
477     */
478     if(opts->config[CONF_FLUSH_IPFW_AT_EXIT] == NULL)
479         set_config_entry(opts, CONF_FLUSH_IPFW_AT_EXIT, DEF_FLUSH_IPFW_AT_EXIT);
480
481     /* Set IPFW start rule number.
482     */
483     if(opts->config[CONF_IPFW_START_RULE_NUM] == NULL)
484         set_config_entry(opts, CONF_IPFW_START_RULE_NUM,
485             DEF_IPFW_START_RULE_NUM);
486
487     /* Set IPFW max rules.
488     */
489     if(opts->config[CONF_IPFW_MAX_RULES] == NULL)
490         set_config_entry(opts, CONF_IPFW_MAX_RULES,
491             DEF_IPFW_MAX_RULES);
492
493     /* Set IPFW active set number.
494     */
495     if(opts->config[CONF_IPFW_ACTIVE_SET_NUM] == NULL)
496         set_config_entry(opts, CONF_IPFW_ACTIVE_SET_NUM,
497             DEF_IPFW_ACTIVE_SET_NUM);
498
499     /* Set IPFW expire set number.
500     */
501     if(opts->config[CONF_IPFW_EXPIRE_SET_NUM] == NULL)
502         set_config_entry(opts, CONF_IPFW_EXPIRE_SET_NUM,
503             DEF_IPFW_EXPIRE_SET_NUM);
504
505     /* Set IPFW Dynamic rule expiry interval.
506     */
507     if(opts->config[CONF_IPFW_EXPIRE_PURGE_INTERVAL] == NULL)
508         set_config_entry(opts, CONF_IPFW_EXPIRE_PURGE_INTERVAL,
509             DEF_IPFW_EXPIRE_PURGE_INTERVAL);
510
511     /* Set IPFW Dynamic rule expiry interval.
512     */
513     if(opts->config[CONF_IPFW_ADD_CHECK_STATE] == NULL)
514         set_config_entry(opts, CONF_IPFW_ADD_CHECK_STATE,
515             DEF_IPFW_ADD_CHECK_STATE);
516
517 #elif FIREWALL_PF
518     /* Set PF anchor name
519     */
520     if(opts->config[CONF_PF_ANCHOR_NAME] == NULL)
521         set_config_entry(opts, CONF_PF_ANCHOR_NAME,
522             DEF_PF_ANCHOR_NAME);
523
524     /* Set PF rule expiry interval.
525     */
526     if(opts->config[CONF_PF_EXPIRE_INTERVAL] == NULL)
527         set_config_entry(opts, CONF_PF_EXPIRE_INTERVAL,
528             DEF_PF_EXPIRE_INTERVAL);
529
530 #elif FIREWALL_IPF
531     /* --DSS Place-holder */
532
533 #endif /* FIREWALL type */
534
535     /* GPG Home dir.
536     */
537     if(opts->config[CONF_GPG_HOME_DIR] == NULL)
538         set_config_entry(opts, CONF_GPG_HOME_DIR, DEF_GPG_HOME_DIR);
539
540     /* Enable SPA over HTTP.
541     */
542     if(opts->config[CONF_ENABLE_SPA_OVER_HTTP] == NULL)
543         set_config_entry(opts, CONF_ENABLE_SPA_OVER_HTTP,
544             DEF_ENABLE_SPA_OVER_HTTP);
545
546     /* Enable TCP server.
547     */
548     if(opts->config[CONF_ENABLE_TCP_SERVER] == NULL)
549         set_config_entry(opts, CONF_ENABLE_TCP_SERVER, DEF_ENABLE_TCP_SERVER);
550
551     /* TCP Server port.
552     */
553     if(opts->config[CONF_TCPSERV_PORT] == NULL)
554         set_config_entry(opts, CONF_TCPSERV_PORT, DEF_TCPSERV_PORT);
555
556     /* Syslog identity.
557     */
558     if(opts->config[CONF_SYSLOG_IDENTITY] == NULL)
559         set_config_entry(opts, CONF_SYSLOG_IDENTITY, DEF_SYSLOG_IDENTITY);
560
561     /* Syslog facility.
562     */
563     if(opts->config[CONF_SYSLOG_FACILITY] == NULL)
564         set_config_entry(opts, CONF_SYSLOG_FACILITY, DEF_SYSLOG_FACILITY);
565
566
567     /* Validate integer variable ranges
568     */
569     validate_int_var_ranges(opts);
570
571     /* Some options just trigger some output of information, or trigger an
572      * external function, but do not actually start fwknopd.  If any of those
573      * are set, we can return here an skip the validation routines as all
574      * other options will be ignored anyway.
575      *
576      * These are also mutually exclusive (for now).
577     */
578     if((opts->dump_config + opts->kill + opts->restart + opts->status) == 1)
579         return;
580
581     if((opts->dump_config + opts->kill + opts->restart + opts->status) > 1)
582     {
583         fprintf(stderr,
584             "The -D, -K, -R, and -S options are mutually exclusive.  Pick only one.\n"
585         );
586         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
587     }
588
589     if(opts->config[CONF_FIREWALL_EXE] == NULL)
590     {
591         fprintf(stderr,
592             "No firewall command executable is set. Please check FIREWALL_EXE in fwknopd.conf.\n"
593         );
594         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
595     }
596
597     return;
598 }
599
600 void
601 set_preconfig_entries(fko_srv_options_t *opts)
602 {
603     /* First, set any default or otherwise static settings here.  Some may
604      * end up being overwritten via config file or command-line.
605     */
606
607     /* Setup the firewall executable based on build-time info.
608      * --DSS Note: We will want to either force external script mode, or
609      *             error out if we do not have a firewall executable defined.
610     */
611 #ifdef FIREWALL_EXE
612     set_config_entry(opts, CONF_FIREWALL_EXE, FIREWALL_EXE);
613 #endif
614
615 }
616
617 /* Initialize program configuration via config file and/or command-line
618  * switches.
619 */
620 void
621 config_init(fko_srv_options_t *opts, int argc, char **argv)
622 {
623     int             cmd_arg, index;
624     unsigned char   got_conf_file = 0, got_override_config = 0;
625
626     char            override_file[MAX_LINE_LEN];
627     char           *ndx, *cmrk;
628
629     /* Zero out options and opts_track.
630     */
631     memset(opts, 0x00, sizeof(fko_srv_options_t));
632
633     /* Set some preconfiguration options (i.e. build-time defaults)
634     */
635     set_preconfig_entries(opts);
636
637     /* In case this is a re-config.
638     */
639     optind = 0;
640
641     /* First, scan the command-line args for -h/--help or an alternate
642      * configuration file. If we find an alternate config file, use it,
643      * otherwise use the default.  We also grab any override config files
644      * as well.
645     */
646     while ((cmd_arg = getopt_long(argc, argv,
647             GETOPTS_OPTION_STRING, cmd_opts, &index)) != -1) {
648
649         /* If help is wanted, give it and exit.
650         */
651         switch(cmd_arg) {
652             case 'h':
653                 usage();
654                 clean_exit(opts, NO_FW_CLEANUP, EXIT_SUCCESS);
655                 break;
656
657         /* Look for configuration file arg.
658         */
659         case 'c':
660             set_config_entry(opts, CONF_CONFIG_FILE, optarg);
661             got_conf_file++;
662
663             /* If we already have the config_override option, we are done.
664             */
665             if(got_override_config > 0)
666                 break;
667
668         /* Look for override configuration file arg.
669         */
670         case 'O':
671             set_config_entry(opts, CONF_OVERRIDE_CONFIG, optarg);
672             got_override_config++;
673
674             /* If we already have the conf_file option, we are done.
675             */
676             if(got_conf_file > 0)
677                 break;
678         }
679     }
680
681     /* If no alternate configuration file was specified, we use the
682      * default.
683     */
684     if(opts->config[CONF_CONFIG_FILE] == NULL)
685         set_config_entry(opts, CONF_CONFIG_FILE, DEF_CONFIG_FILE);
686
687     /* Parse configuration file to populate any params not already specified
688      * via command-line options.
689     */
690     parse_config_file(opts, opts->config[CONF_CONFIG_FILE]);
691
692     /* If there are override configuration entries, process them
693      * here.
694     */
695     if(opts->config[CONF_OVERRIDE_CONFIG] != NULL)
696     {
697         /* Make a copy of the override_config string so we can munge it.
698         */
699         strlcpy(override_file, opts->config[CONF_OVERRIDE_CONFIG], MAX_LINE_LEN);
700
701         ndx  = override_file;
702         cmrk = strchr(ndx, ',');
703
704         if(cmrk == NULL)
705         {
706             /* Only one to process...
707             */
708             parse_config_file(opts, ndx);
709
710         } else {
711             /* Walk the string pulling the next config override
712              * at the comma delimiters.
713             */
714             while(cmrk != NULL) {
715                 *cmrk = '\0';
716                 parse_config_file(opts, ndx);
717                 ndx = cmrk + 1;
718                 cmrk = strchr(ndx, ',');
719             }
720
721             /* Process the last entry
722             */
723             parse_config_file(opts, ndx);
724         }
725     }
726
727     /* Reset the options index so we can run through them again.
728     */
729     optind = 0;
730
731     /* Last, but not least, we process command-line options (some of which
732      * may override configuration file options.
733     */
734     while ((cmd_arg = getopt_long(argc, argv,
735             GETOPTS_OPTION_STRING, cmd_opts, &index)) != -1) {
736
737         switch(cmd_arg) {
738             case 'a':
739                 set_config_entry(opts, CONF_ACCESS_FILE, optarg);
740                 break;
741             case 'c':
742                 /* This was handled earlier */
743                 break;
744             case 'C':
745                 opts->packet_ctr_limit = atoi(optarg);
746                 break;
747             case 'd':
748 #if USE_FILE_CACHE
749                 set_config_entry(opts, CONF_DIGEST_FILE, optarg);
750 #else
751                 set_config_entry(opts, CONF_DIGEST_DB_FILE, optarg);
752 #endif
753                 break;
754             case 'D':
755                 opts->dump_config = 1;
756                 break;
757             case 'f':
758                 opts->foreground = 1;
759                 break;
760             case FW_LIST:
761                 opts->fw_list = 1;
762                 break;
763             case FW_LIST_ALL:
764                 opts->fw_list = 1;
765                 opts->fw_list_all = 1;
766                 break;
767             case FW_FLUSH:
768                 opts->fw_flush = 1;
769                 break;
770             case GPG_HOME_DIR:
771                 if (is_valid_dir(optarg))
772                 {
773                     set_config_entry(opts, CONF_GPG_HOME_DIR, optarg);
774                 }
775                 else
776                 {
777                     fprintf(stderr,
778                         "[*] Directory '%s' could not stat()/does not exist?\n",
779                         optarg);
780                     clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
781                 }
782                 break;
783             case 'i':
784                 set_config_entry(opts, CONF_PCAP_INTF, optarg);
785                 break;
786             case 'K':
787                 opts->kill = 1;
788                 break;
789             case 'l':
790                 set_config_entry(opts, CONF_LOCALE, optarg);
791                 break;
792             case 'O':
793                 /* This was handled earlier */
794                 break;
795             case 'p':
796                 set_config_entry(opts, CONF_FWKNOP_PID_FILE, optarg);
797                 break;
798             case 'P':
799                 set_config_entry(opts, CONF_PCAP_FILTER, optarg);
800                 break;
801             case ROTATE_DIGEST_CACHE:
802                 opts->rotate_digest_cache = 1;
803                 break;
804             case 'R':
805                 opts->restart = 1;
806                 break;
807             case 'S':
808                 opts->status = 1;
809                 break;
810             case 'v':
811                 opts->verbose++;
812                 break;
813             case 'V':
814                 fprintf(stdout, "fwknopd server %s\n", MY_VERSION);
815                 clean_exit(opts, NO_FW_CLEANUP, EXIT_SUCCESS);
816                 break;
817             default:
818                 usage();
819                 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
820         }
821     }
822
823     /* Now that we have all of our options set, and we are actually going to
824      * start fwknopd, we can validate them.
825     */
826     validate_options(opts);
827
828     return;
829 }
830
831 /* Dump the configuration
832 */
833 void
834 dump_config(const fko_srv_options_t *opts)
835 {
836     int i;
837
838     fprintf(stdout, "Current fwknopd config settings:\n");
839
840     for(i=0; i<NUMBER_OF_CONFIG_ENTRIES; i++)
841         fprintf(stdout, "%3i. %-28s =  '%s'\n",
842             i,
843             config_map[i],
844             (opts->config[i] == NULL) ? "<not set>" : opts->config[i]
845         );
846
847     fprintf(stdout, "\n");
848     fflush(stdout);
849 }
850
851 /* Print usage message...
852 */
853 void
854 usage(void)
855 {
856     fprintf(stdout, "\n%s server version %s\n%s\n\n", MY_NAME, MY_VERSION, MY_DESC);
857     fprintf(stdout,
858       "Usage: fwknopd [options]\n\n"
859       " -h, --help              - Print this usage message and exit.\n"
860       " -a, --access-file       - Specify an alternate access.conf file.\n"
861       " -c, --config-file       - Specify an alternate configuration file.\n"
862       " -C, --packet-limit      - Limit the number of candidate SPA packets to\n"
863       "                           process and exit when this limit is reached.\n"
864       " -d, --digest-file       - Specify an alternate digest.cache file.\n"
865       " -D, --dump-config       - Dump the current fwknop configuration values.\n"
866       " -f, --foreground        - Run fwknopd in the foreground (do not become\n"
867       "                           a background daemon).\n"
868       " -i, --interface         - Specify interface to listen for incoming SPA\n"
869       "                           packets.\n"
870       " -K, --kill              - Kill the currently running fwknopd.\n"
871       "     --gpg-home-dir      - Specify the GPG home directory.\n"
872       " -l, --locale            - Provide a locale setting other than the system\n"
873       "                           default.\n"
874       " -O, --override-config   - Specify a file with configuration entries that will\n"
875       "                           overide those in fwknopd.conf\n"
876       " -p, --pid-file          - Specify an alternate fwknopd.pid file.\n"
877       " -P, --pcap-filter       - Specify a Berkeley packet filter statement to\n"
878       "                           override the PCAP_FILTER variable in fwknopd.conf.\n"
879       " -R, --restart           - Force the currently running fwknopd to restart.\n"
880       "     --rotate-digest-cache\n"
881       "                         - Rotate the digest cache file by renaming it to\n"
882       "                           '<name>-old', and starting a new one.\n"
883       " -S, --status            - Display the status of any running fwknopd process.\n"
884       " -v, --verbose           - Set verbose mode.\n"
885       " -V, --version           - Print version number.\n"
886       "     --fw-list           - List all firewall rules that fwknop has created\n"
887       "                           and then exit.\n"
888       "     --fw-list-all       - List all firewall rules in the complete policy,\n"
889       "                           including those that have nothing to do with\n"
890       "                           fwknop.\n"
891       "     --fw-flush          - Flush all firewall rules created by fwknop.\n"
892       "\n"
893     );
894
895     return;
896 }
897
898 /***EOF***/