Branch data Line data Source code
1 : : /*
2 : : ******************************************************************************
3 : : *
4 : : * File: config_init.c
5 : : *
6 : : * Purpose: Command-line and config file processing for fwknop server.
7 : : *
8 : : * Fwknop is developed primarily by the people listed in the file 'AUTHORS'.
9 : : * Copyright (C) 2009-2014 fwknop developers and contributors. For a full
10 : : * list of contributors, see the file 'CREDITS'.
11 : : *
12 : : * License (GNU General 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 "fwknopd_errors.h"
33 : : #include "config_init.h"
34 : : #include "access.h"
35 : : #include "cmd_opts.h"
36 : : #include "utils.h"
37 : : #include "log_msg.h"
38 : :
39 : : #if FIREWALL_FIREWALLD
40 : : #include "fw_util_firewalld.h"
41 : : #elif FIREWALL_IPTABLES
42 : : #include "fw_util_iptables.h"
43 : : #endif
44 : :
45 : : /* Check to see if an integer variable has a value that is within a
46 : : * specific range
47 : : */
48 : : static void
49 : 27914 : range_check(fko_srv_options_t *opts, char *var, char *val, int low, int high)
50 : : {
51 : : int is_err;
52 : :
53 : 27914 : strtol_wrapper(val, low, high, NO_EXIT_UPON_ERR, &is_err);
54 [ + + ]: 27914 : if(is_err != FKO_SUCCESS)
55 : : {
56 : 3 : log_msg(LOG_ERR, "[*] var %s value '%s' not in the range %d-%d",
57 : : var, val, low, high);
58 : 3 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
59 : : }
60 : :
61 : 27911 : return;
62 : : }
63 : :
64 : : /* Take an index and a string value. malloc the space for the value
65 : : * and assign it to the array at the specified index.
66 : : */
67 : : static void
68 : 200377 : set_config_entry(fko_srv_options_t *opts, const int var_ndx, const char *value)
69 : : {
70 : : int space_needed;
71 : :
72 : : /* Sanity check the index value.
73 : : */
74 [ - + ]: 200377 : if(var_ndx < 0 || var_ndx >= NUMBER_OF_CONFIG_ENTRIES)
75 : : {
76 : 0 : log_msg(LOG_ERR, "[*] Index value of %i is not valid", var_ndx);
77 : 0 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
78 : : }
79 : :
80 : : /* If this particular entry was already set (i.e. not NULL), then
81 : : * assume it needs to be freed first.
82 : : */
83 [ + + ]: 200377 : if(opts->config[var_ndx] != NULL)
84 : 439 : free(opts->config[var_ndx]);
85 : :
86 : : /* If we are setting it to NULL, do it and be done.
87 : : */
88 [ - + ]: 200377 : if(value == NULL)
89 : : {
90 : 0 : opts->config[var_ndx] = NULL;
91 : 0 : return;
92 : : }
93 : :
94 : : /* Otherwise, make the space we need and set it.
95 : : */
96 : 200377 : space_needed = strlen(value) + 1;
97 : :
98 : 200377 : opts->config[var_ndx] = calloc(1, space_needed);
99 : :
100 [ + + ]: 200377 : if(opts->config[var_ndx] == NULL)
101 : : {
102 : 1599 : log_msg(LOG_ERR, "[*] Fatal memory allocation error!");
103 : 1599 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
104 : : }
105 : :
106 : 198778 : strlcpy(opts->config[var_ndx], value, space_needed);
107 : :
108 : 198778 : return;
109 : : }
110 : :
111 : : /* Given a config parameter name, return its index or -1 if not found.
112 : : */
113 : : static int
114 : 6 : config_entry_index(const fko_srv_options_t *opts, const char *var)
115 : : {
116 : : int i;
117 : :
118 [ + + ]: 290 : for(i=0; i<NUMBER_OF_CONFIG_ENTRIES; i++)
119 [ + + ][ + + ]: 286 : if(opts->config[i] != NULL && CONF_VAR_IS(var, config_map[i]))
120 : 2 : return(i);
121 : :
122 : : return(-1);
123 : : }
124 : :
125 : : /* Free the config memory
126 : : */
127 : : void
128 : 5795 : free_configs(fko_srv_options_t *opts)
129 : : {
130 : : int i;
131 : :
132 : 5795 : free_acc_stanzas(opts);
133 : :
134 [ + + ]: 301340 : for(i=0; i<NUMBER_OF_CONFIG_ENTRIES; i++)
135 [ + + ]: 295545 : if(opts->config[i] != NULL)
136 : 195594 : free(opts->config[i]);
137 : 5795 : }
138 : :
139 : : static void
140 : 3989 : validate_int_var_ranges(fko_srv_options_t *opts)
141 : : {
142 : : #if FIREWALL_IPFW
143 : : int is_err = FKO_SUCCESS;
144 : : #endif
145 : :
146 : 3989 : range_check(opts, "PCAP_LOOP_SLEEP", opts->config[CONF_PCAP_LOOP_SLEEP],
147 : : 1, RCHK_MAX_PCAP_LOOP_SLEEP);
148 : 3988 : range_check(opts, "MAX_SPA_PACKET_AGE", opts->config[CONF_MAX_SPA_PACKET_AGE],
149 : : 1, RCHK_MAX_SPA_PACKET_AGE);
150 : 3988 : range_check(opts, "MAX_SNIFF_BYTES", opts->config[CONF_MAX_SNIFF_BYTES],
151 : : 1, RCHK_MAX_SNIFF_BYTES);
152 : 3988 : range_check(opts, "RULES_CHECK_THRESHOLD", opts->config[CONF_RULES_CHECK_THRESHOLD],
153 : : 0, RCHK_MAX_RULES_CHECK_THRESHOLD);
154 : 3988 : range_check(opts, "TCPSERV_PORT", opts->config[CONF_TCPSERV_PORT],
155 : : 1, RCHK_MAX_TCPSERV_PORT);
156 : 3987 : range_check(opts, "UDPSERV_PORT", opts->config[CONF_UDPSERV_PORT],
157 : : 1, RCHK_MAX_UDPSERV_PORT);
158 : 3986 : range_check(opts, "UDPSERV_PORT", opts->config[CONF_UDPSERV_SELECT_TIMEOUT],
159 : : 1, RCHK_MAX_UDPSERV_SELECT_TIMEOUT);
160 : :
161 : : #if FIREWALL_IPFW
162 : : range_check(opts, "IPFW_START_RULE_NUM", opts->config[CONF_IPFW_START_RULE_NUM],
163 : : 0, RCHK_MAX_IPFW_START_RULE_NUM);
164 : : range_check(opts, "IPFW_MAX_RULES", opts->config[CONF_IPFW_MAX_RULES],
165 : : 1, RCHK_MAX_IPFW_MAX_RULES);
166 : : range_check(opts, "IPFW_ACTIVE_SET_NUM", opts->config[CONF_IPFW_ACTIVE_SET_NUM],
167 : : 0, RCHK_MAX_IPFW_SET_NUM);
168 : : range_check(opts, "IPFW_EXPIRE_SET_NUM", opts->config[CONF_IPFW_EXPIRE_SET_NUM],
169 : : 0, RCHK_MAX_IPFW_SET_NUM);
170 : : range_check(opts, "IPFW_EXPIRE_PURGE_INTERVAL",
171 : : opts->config[CONF_IPFW_EXPIRE_PURGE_INTERVAL],
172 : : 1, RCHK_MAX_IPFW_PURGE_INTERVAL);
173 : :
174 : : /* Make sure the active and expire sets are not identical whenever
175 : : * they are non-zero
176 : : */
177 : : if((strtol_wrapper(opts->config[CONF_IPFW_ACTIVE_SET_NUM],
178 : : 0, RCHK_MAX_IPFW_SET_NUM, NO_EXIT_UPON_ERR, &is_err) > 0
179 : : && strtol_wrapper(opts->config[CONF_IPFW_EXPIRE_SET_NUM],
180 : : 0, RCHK_MAX_IPFW_SET_NUM, NO_EXIT_UPON_ERR, &is_err) > 0)
181 : : && strtol_wrapper(opts->config[CONF_IPFW_ACTIVE_SET_NUM],
182 : : 0, RCHK_MAX_IPFW_SET_NUM, NO_EXIT_UPON_ERR, &is_err)
183 : : == strtol_wrapper(opts->config[CONF_IPFW_EXPIRE_SET_NUM],
184 : : 0, RCHK_MAX_IPFW_SET_NUM, NO_EXIT_UPON_ERR, &is_err))
185 : : {
186 : : log_msg(LOG_ERR,
187 : : "[*] Cannot set identical ipfw active and expire sets.");
188 : : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
189 : : }
190 : :
191 : : if(is_err != FKO_SUCCESS)
192 : : {
193 : : log_msg(LOG_ERR, "[*] invalid integer conversion error.\n");
194 : : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
195 : : }
196 : :
197 : : #elif FIREWALL_PF
198 : : range_check(opts, "PF_EXPIRE_INTERVAL", opts->config[CONF_PF_EXPIRE_INTERVAL],
199 : : 1, RCHK_MAX_PF_EXPIRE_INTERVAL);
200 : :
201 : : #endif /* FIREWALL type */
202 : :
203 : 3986 : return;
204 : : }
205 : :
206 : : /**
207 : : * @brief Generate Rijndael + HMAC keys from /dev/urandom (base64 encoded).
208 : : *
209 : : * @param options FKO command line option structure
210 : : */
211 : : static void
212 : 103 : generate_keys(fko_srv_options_t *options)
213 : : {
214 : : char key_base64[MAX_B64_KEY_LEN+1];
215 : : char hmac_key_base64[MAX_B64_KEY_LEN+1];
216 : :
217 : 103 : FILE *key_gen_file_ptr = NULL;
218 : : int res;
219 : :
220 : : /* Set defaults and validate for --key-gen mode
221 : : */
222 [ + - ]: 103 : if(options->key_len == 0)
223 : 103 : options->key_len = FKO_DEFAULT_KEY_LEN;
224 : :
225 [ + - ]: 103 : if(options->hmac_key_len == 0)
226 : 103 : options->hmac_key_len = FKO_DEFAULT_HMAC_KEY_LEN;
227 : :
228 [ + - ]: 103 : if(options->hmac_type == 0)
229 : 103 : options->hmac_type = FKO_DEFAULT_HMAC_MODE;
230 : :
231 : : /* Zero out the key buffers */
232 : : memset(key_base64, 0x00, sizeof(key_base64));
233 : : memset(hmac_key_base64, 0x00, sizeof(hmac_key_base64));
234 : :
235 : : /* Generate the key through libfko */
236 : 103 : res = fko_key_gen(key_base64, options->key_len,
237 : : hmac_key_base64, options->hmac_key_len,
238 : : options->hmac_type);
239 : :
240 [ - + ]: 103 : if(res != FKO_SUCCESS)
241 : : {
242 : 0 : log_msg(LOG_ERR, "%s: fko_key_gen: Error %i - %s",
243 : : MY_NAME, res, fko_errstr(res));
244 : 0 : clean_exit(options, NO_FW_CLEANUP, EXIT_FAILURE);
245 : : }
246 : :
247 [ + + ]: 103 : if(options->key_gen_file[0] != '\0')
248 : : {
249 [ + + ]: 2 : if ((key_gen_file_ptr = fopen(options->key_gen_file, "w")) == NULL)
250 : : {
251 : 1 : log_msg(LOG_ERR, "Unable to create key gen file: %s: %s",
252 : 1 : options->key_gen_file, strerror(errno));
253 : 1 : clean_exit(options, NO_FW_CLEANUP, EXIT_FAILURE);
254 : : }
255 : : fprintf(key_gen_file_ptr, "KEY_BASE64: %s\nHMAC_KEY_BASE64: %s\n",
256 : : key_base64, hmac_key_base64);
257 : 1 : fclose(key_gen_file_ptr);
258 : 1 : fprintf(stdout, "[+] Wrote Rijndael and HMAC keys to: %s",
259 : : options->key_gen_file);
260 : : }
261 : : else
262 : : {
263 : 101 : fprintf(stdout, "KEY_BASE64: %s\nHMAC_KEY_BASE64: %s\n",
264 : : key_base64, hmac_key_base64);
265 : : }
266 : 102 : clean_exit(options, NO_FW_CLEANUP, EXIT_SUCCESS);
267 : 0 : }
268 : :
269 : : /* Parse the config file...
270 : : */
271 : : static void
272 : 10875 : parse_config_file(fko_srv_options_t *opts, const char *config_file)
273 : : {
274 : : FILE *cfile_ptr;
275 : 10875 : unsigned int numLines = 0;
276 : : unsigned int i, good_ent;
277 : : int cndx;
278 : :
279 : 10875 : char conf_line_buf[MAX_LINE_LEN] = {0};
280 : 10875 : char var[MAX_LINE_LEN] = {0};
281 : 10875 : char val[MAX_LINE_LEN] = {0};
282 : 10875 : char tmp1[MAX_LINE_LEN] = {0};
283 : 10875 : char tmp2[MAX_LINE_LEN] = {0};
284 : :
285 : : struct stat st;
286 : :
287 : : /* Make sure the config file exists.
288 : : */
289 [ + + ]: 10875 : if(stat(config_file, &st) != 0)
290 : : {
291 : 1 : log_msg(LOG_ERR, "[*] Config file: '%s' was not found.",
292 : : config_file);
293 : 1 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
294 : : }
295 : :
296 [ + + ]: 10874 : if(verify_file_perms_ownership(config_file) != 1)
297 : 1 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
298 : :
299 : : /* See the comment in the parse_access_file() function regarding security
300 : : * here relative to a TOCTOU bug flagged by Coverity.
301 : : */
302 [ + + ]: 10873 : if ((cfile_ptr = fopen(config_file, "r")) == NULL)
303 : : {
304 : 142 : log_msg(LOG_ERR, "[*] Could not open config file: %s",
305 : : config_file);
306 : 142 : perror(NULL);
307 : :
308 : 10873 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
309 : : }
310 : :
311 [ + + ]: 22240 : while ((fgets(conf_line_buf, MAX_LINE_LEN, cfile_ptr)) != NULL)
312 : : {
313 : 11509 : numLines++;
314 : 11509 : conf_line_buf[MAX_LINE_LEN-1] = '\0';
315 : :
316 : : /* Get past comments and empty lines (note: we only look at the
317 : : * first character.
318 : : */
319 [ + + ][ + - ]: 11509 : if(IS_EMPTY_LINE(conf_line_buf[0]))
[ + - ][ - + ]
320 : 10625 : continue;
321 : :
322 [ + + ]: 884 : if(sscanf(conf_line_buf, "%s %[^;\n\r]", var, val) != 2)
323 : : {
324 : 2 : log_msg(LOG_ERR,
325 : : "*Invalid config file entry in %s at line %i.\n - '%s'",
326 : : config_file, numLines, conf_line_buf
327 : : );
328 : 2 : continue;
329 : : }
330 : :
331 : : good_ent = 0;
332 [ + + ]: 21753 : for(i=0; i<NUMBER_OF_CONFIG_ENTRIES; i++)
333 : : {
334 [ + + ]: 21751 : if(CONF_VAR_IS(config_map[i], var))
335 : : {
336 : : /* First check to see if we need to do a varable expansion
337 : : * on this value. Note: this only supports one expansion and
338 : : * only if the value starts with the variable.
339 : : */
340 [ + + ]: 880 : if(*val == '$')
341 : : {
342 [ + - ]: 6 : if(sscanf((val+1), "%[A-Z_]%s", tmp1, tmp2))
343 : : {
344 [ + + ]: 6 : if((cndx = config_entry_index(opts, tmp1)) >= 0)
345 : : {
346 : 2 : strlcpy(val, opts->config[cndx], sizeof(val));
347 : 2 : strlcat(val, tmp2, sizeof(val));
348 : : }
349 : : else
350 : : {
351 : : /* We didn't map the embedded variable to a valid
352 : : * config parameter
353 : : */
354 : 4 : log_msg(LOG_ERR,
355 : : "[*] Invalid embedded variable in: '%s'", val);
356 : 4 : break;
357 : : }
358 : : }
359 : : }
360 : :
361 : 876 : set_config_entry(opts, i, val);
362 : 876 : good_ent++;
363 : 876 : break;
364 : : }
365 : : }
366 : :
367 [ + + ]: 882 : if(good_ent == 0)
368 : 11509 : log_msg(LOG_ERR,
369 : : "[*] Ignoring unknown configuration parameter: '%s' in %s",
370 : : var, config_file
371 : : );
372 : : }
373 : :
374 : 10731 : fclose(cfile_ptr);
375 : :
376 : 10731 : return;
377 : : }
378 : :
379 : : /* Set defaults, and do sanity and bounds checks for the various options.
380 : : */
381 : : static void
382 : 5026 : validate_options(fko_srv_options_t *opts)
383 : : {
384 : 5026 : char tmp_path[MAX_PATH_LEN] = {0};
385 : :
386 : : /* If no conf dir is set in the config file, use the default.
387 : : */
388 [ + - ]: 5026 : if(opts->config[CONF_FWKNOP_CONF_DIR] == NULL)
389 : 5026 : set_config_entry(opts, CONF_FWKNOP_CONF_DIR, DEF_CONF_DIR);
390 : :
391 : : /* If no access.conf path was specified on the command line or set in
392 : : * the config file, use the default.
393 : : */
394 [ - + ]: 4955 : if(opts->config[CONF_ACCESS_FILE] == NULL)
395 : 0 : set_config_entry(opts, CONF_ACCESS_FILE, DEF_ACCESS_FILE);
396 : :
397 : : /* If the pid and digest cache files where not set in the config file or
398 : : * via command-line, then grab the defaults. Start with RUN_DIR as the
399 : : * files may depend on that.
400 : : */
401 [ + + ]: 4955 : if(opts->config[CONF_FWKNOP_RUN_DIR] == NULL)
402 : 4950 : set_config_entry(opts, CONF_FWKNOP_RUN_DIR, DEF_RUN_DIR);
403 : :
404 [ + + ]: 4905 : if(opts->config[CONF_FWKNOP_PID_FILE] == NULL)
405 : : {
406 : 37 : strlcpy(tmp_path, opts->config[CONF_FWKNOP_RUN_DIR], sizeof(tmp_path));
407 : :
408 [ + - ]: 37 : if(tmp_path[strlen(tmp_path)-1] != '/')
409 : 37 : strlcat(tmp_path, "/", sizeof(tmp_path));
410 : :
411 : 37 : strlcat(tmp_path, DEF_PID_FILENAME, sizeof(tmp_path));
412 : :
413 : 37 : set_config_entry(opts, CONF_FWKNOP_PID_FILE, tmp_path);
414 : : }
415 : :
416 : : #if USE_FILE_CACHE
417 [ + + ]: 4905 : if(opts->config[CONF_DIGEST_FILE] == NULL)
418 : : #else
419 : : if(opts->config[CONF_DIGEST_DB_FILE] == NULL)
420 : : #endif
421 : : {
422 : 36 : strlcpy(tmp_path, opts->config[CONF_FWKNOP_RUN_DIR], sizeof(tmp_path));
423 : :
424 [ + - ]: 36 : if(tmp_path[strlen(tmp_path)-1] != '/')
425 : 36 : strlcat(tmp_path, "/", sizeof(tmp_path));
426 : :
427 : : #if USE_FILE_CACHE
428 : 36 : strlcat(tmp_path, DEF_DIGEST_CACHE_FILENAME, sizeof(tmp_path));
429 : 36 : set_config_entry(opts, CONF_DIGEST_FILE, tmp_path);
430 : : #else
431 : : strlcat(tmp_path, DEF_DIGEST_CACHE_DB_FILENAME, sizeof(tmp_path));
432 : : set_config_entry(opts, CONF_DIGEST_DB_FILE, tmp_path);
433 : : #endif
434 : : }
435 : :
436 : : /* Set remaining require CONF_ vars if they are not already set. */
437 : :
438 : : /* PCAP capture interface - note that if '-r <pcap file>' is specified
439 : : * on the command line, then this will override the pcap interface setting.
440 : : */
441 [ + + ]: 4905 : if(opts->config[CONF_PCAP_INTF] == NULL)
442 : 2857 : set_config_entry(opts, CONF_PCAP_INTF, DEF_INTERFACE);
443 : :
444 : : /* PCAP Promiscuous mode.
445 : : */
446 [ + + ]: 4883 : if(opts->config[CONF_ENABLE_PCAP_PROMISC] == NULL)
447 : 4880 : set_config_entry(opts, CONF_ENABLE_PCAP_PROMISC,
448 : : DEF_ENABLE_PCAP_PROMISC);
449 : :
450 : : /* The packet count argument to pcap_dispatch()
451 : : */
452 [ + + ]: 4838 : if(opts->config[CONF_PCAP_DISPATCH_COUNT] == NULL)
453 : 4837 : set_config_entry(opts, CONF_PCAP_DISPATCH_COUNT,
454 : : DEF_PCAP_DISPATCH_COUNT);
455 : :
456 : : /* Microseconds to sleep between pcap loop iterations
457 : : */
458 [ + + ]: 4791 : if(opts->config[CONF_PCAP_LOOP_SLEEP] == NULL)
459 : 4790 : set_config_entry(opts, CONF_PCAP_LOOP_SLEEP,
460 : : DEF_PCAP_LOOP_SLEEP);
461 : :
462 : : /* Control whether to exit if the interface where we're sniffing
463 : : * goes down.
464 : : */
465 [ + + ]: 4743 : if(opts->config[CONF_EXIT_AT_INTF_DOWN] == NULL)
466 : 4742 : set_config_entry(opts, CONF_EXIT_AT_INTF_DOWN,
467 : : DEF_EXIT_AT_INTF_DOWN);
468 : :
469 : : /* PCAP Filter.
470 : : */
471 [ + + ]: 4703 : if(opts->config[CONF_PCAP_FILTER] == NULL)
472 : 4689 : set_config_entry(opts, CONF_PCAP_FILTER, DEF_PCAP_FILTER);
473 : :
474 : : /* Enable SPA packet aging unless we're getting packet data
475 : : * directly from a pcap file
476 : : */
477 [ + + ]: 4659 : if(opts->config[CONF_ENABLE_SPA_PACKET_AGING] == NULL)
478 : : {
479 [ + + ]: 4572 : if(opts->config[CONF_PCAP_FILE] == NULL)
480 : : {
481 : 4168 : set_config_entry(opts, CONF_ENABLE_SPA_PACKET_AGING,
482 : : DEF_ENABLE_SPA_PACKET_AGING);
483 : : }
484 : : else
485 : : {
486 : 404 : set_config_entry(opts, CONF_ENABLE_SPA_PACKET_AGING, "N");
487 : : }
488 : : }
489 : :
490 : : /* SPA packet age.
491 : : */
492 [ + - ]: 4614 : if(opts->config[CONF_MAX_SPA_PACKET_AGE] == NULL)
493 : 4614 : set_config_entry(opts, CONF_MAX_SPA_PACKET_AGE,
494 : : DEF_MAX_SPA_PACKET_AGE);
495 : :
496 : : /* Enable digest persistence.
497 : : */
498 [ + - ]: 4574 : if(opts->config[CONF_ENABLE_DIGEST_PERSISTENCE] == NULL)
499 : 4574 : set_config_entry(opts, CONF_ENABLE_DIGEST_PERSISTENCE,
500 : : DEF_ENABLE_DIGEST_PERSISTENCE);
501 : :
502 : : /* Set firewall rule "deep" collection interval - this allows
503 : : * fwknopd to remove rules with proper _exp_<time> expiration
504 : : * times even when added by a different program.
505 : : */
506 [ + - ]: 4541 : if(opts->config[CONF_RULES_CHECK_THRESHOLD] == NULL)
507 : 4541 : set_config_entry(opts, CONF_RULES_CHECK_THRESHOLD,
508 : : DEF_RULES_CHECK_THRESHOLD);
509 : :
510 : : /* Enable destination rule.
511 : : */
512 [ + + ]: 4508 : if(opts->config[CONF_ENABLE_DESTINATION_RULE] == NULL)
513 : 4500 : set_config_entry(opts, CONF_ENABLE_DESTINATION_RULE,
514 : : DEF_ENABLE_DESTINATION_RULE);
515 : :
516 : : /* Max sniff bytes.
517 : : */
518 [ + - ]: 4470 : if(opts->config[CONF_MAX_SNIFF_BYTES] == NULL)
519 : 4470 : set_config_entry(opts, CONF_MAX_SNIFF_BYTES, DEF_MAX_SNIFF_BYTES);
520 : :
521 : : #if FIREWALL_FIREWALLD
522 : : /* Enable FIREWD forwarding.
523 : : */
524 [ + + ]: 4434 : if(opts->config[CONF_ENABLE_FIREWD_FORWARDING] == NULL)
525 : 4273 : set_config_entry(opts, CONF_ENABLE_FIREWD_FORWARDING,
526 : : DEF_ENABLE_FIREWD_FORWARDING);
527 : :
528 : : /* Enable FIREWD local NAT.
529 : : */
530 [ + + ]: 4402 : if(opts->config[CONF_ENABLE_FIREWD_LOCAL_NAT] == NULL)
531 : 4368 : set_config_entry(opts, CONF_ENABLE_FIREWD_LOCAL_NAT,
532 : : DEF_ENABLE_FIREWD_LOCAL_NAT);
533 : :
534 : : /* Enable FIREWD SNAT.
535 : : */
536 [ + + ]: 4362 : if(opts->config[CONF_ENABLE_FIREWD_SNAT] == NULL)
537 : 4315 : set_config_entry(opts, CONF_ENABLE_FIREWD_SNAT,
538 : : DEF_ENABLE_FIREWD_SNAT);
539 : :
540 : : /* Make sure we have a valid IP if SNAT is enabled
541 : : */
542 [ + + ]: 4335 : if(strncasecmp(opts->config[CONF_ENABLE_FIREWD_SNAT], "Y", 1) == 0)
543 : : {
544 : : /* Note that fw_config_init() will set use_masquerade if necessary
545 : : */
546 [ + + ]: 47 : if(opts->config[CONF_SNAT_TRANSLATE_IP] != NULL)
547 : : {
548 [ + + ]: 19 : if(! is_valid_ipv4_addr(opts->config[CONF_SNAT_TRANSLATE_IP]))
549 : : {
550 : 1 : log_msg(LOG_ERR,
551 : : "Invalid IPv4 addr for SNAT_TRANSLATE_IP"
552 : : );
553 : 1 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
554 : : }
555 : : }
556 : : }
557 : :
558 : : /* Enable FIREWD OUTPUT.
559 : : */
560 [ + + ]: 4334 : if(opts->config[CONF_ENABLE_FIREWD_OUTPUT] == NULL)
561 : 4333 : set_config_entry(opts, CONF_ENABLE_FIREWD_OUTPUT,
562 : : DEF_ENABLE_FIREWD_OUTPUT);
563 : :
564 : : /* Flush FIREWD at init.
565 : : */
566 [ + + ]: 4312 : if(opts->config[CONF_FLUSH_FIREWD_AT_INIT] == NULL)
567 : 4304 : set_config_entry(opts, CONF_FLUSH_FIREWD_AT_INIT, DEF_FLUSH_FIREWD_AT_INIT);
568 : :
569 : : /* Flush FIREWD at exit.
570 : : */
571 [ + + ]: 4289 : if(opts->config[CONF_FLUSH_FIREWD_AT_EXIT] == NULL)
572 : 4281 : set_config_entry(opts, CONF_FLUSH_FIREWD_AT_EXIT, DEF_FLUSH_FIREWD_AT_EXIT);
573 : :
574 : : /* FIREWD input access.
575 : : */
576 [ + + ]: 4260 : if(opts->config[CONF_FIREWD_INPUT_ACCESS] == NULL)
577 : 4246 : set_config_entry(opts, CONF_FIREWD_INPUT_ACCESS,
578 : : DEF_FIREWD_INPUT_ACCESS);
579 : :
580 [ + + ]: 4240 : if(validate_firewd_chain_conf(opts->config[CONF_FIREWD_INPUT_ACCESS]) != 1)
581 : : {
582 : 3 : log_msg(LOG_ERR,
583 : : "Invalid FIREWD_INPUT_ACCESS specification, see fwknopd.conf comments"
584 : : );
585 : 3 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
586 : : }
587 : :
588 : : /* FIREWD output access.
589 : : */
590 [ + + ]: 4237 : if(opts->config[CONF_FIREWD_OUTPUT_ACCESS] == NULL)
591 : 4235 : set_config_entry(opts, CONF_FIREWD_OUTPUT_ACCESS,
592 : : DEF_FIREWD_OUTPUT_ACCESS);
593 : :
594 [ + + ]: 4216 : if(validate_firewd_chain_conf(opts->config[CONF_FIREWD_OUTPUT_ACCESS]) != 1)
595 : : {
596 : 1 : log_msg(LOG_ERR,
597 : : "Invalid FIREWD_OUTPUT_ACCESS specification, see fwknopd.conf comments"
598 : : );
599 : 1 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
600 : : }
601 : :
602 : : /* FIREWD forward access.
603 : : */
604 [ + + ]: 4215 : if(opts->config[CONF_FIREWD_FORWARD_ACCESS] == NULL)
605 : 4211 : set_config_entry(opts, CONF_FIREWD_FORWARD_ACCESS,
606 : : DEF_FIREWD_FORWARD_ACCESS);
607 : :
608 [ + + ]: 4199 : if(validate_firewd_chain_conf(opts->config[CONF_FIREWD_FORWARD_ACCESS]) != 1)
609 : : {
610 : 1 : log_msg(LOG_ERR,
611 : : "Invalid FIREWD_FORWARD_ACCESS specification, see fwknopd.conf comments"
612 : : );
613 : 1 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
614 : : }
615 : :
616 : : /* FIREWD dnat access.
617 : : */
618 [ + + ]: 4198 : if(opts->config[CONF_FIREWD_DNAT_ACCESS] == NULL)
619 : 4194 : set_config_entry(opts, CONF_FIREWD_DNAT_ACCESS,
620 : : DEF_FIREWD_DNAT_ACCESS);
621 : :
622 [ + + ]: 4178 : if(validate_firewd_chain_conf(opts->config[CONF_FIREWD_DNAT_ACCESS]) != 1)
623 : : {
624 : 1 : log_msg(LOG_ERR,
625 : : "Invalid FIREWD_DNAT_ACCESS specification, see fwknopd.conf comments"
626 : : );
627 : 1 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
628 : : }
629 : :
630 : : /* FIREWD snat access.
631 : : */
632 [ + + ]: 4177 : if(opts->config[CONF_FIREWD_SNAT_ACCESS] == NULL)
633 : 4176 : set_config_entry(opts, CONF_FIREWD_SNAT_ACCESS,
634 : : DEF_FIREWD_SNAT_ACCESS);
635 : :
636 [ + + ]: 4159 : if(validate_firewd_chain_conf(opts->config[CONF_FIREWD_SNAT_ACCESS]) != 1)
637 : : {
638 : 1 : log_msg(LOG_ERR,
639 : : "Invalid FIREWD_SNAT_ACCESS specification, see fwknopd.conf comments"
640 : : );
641 : 1 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
642 : : }
643 : :
644 : : /* FIREWD masquerade access.
645 : : */
646 [ + + ]: 4158 : if(opts->config[CONF_FIREWD_MASQUERADE_ACCESS] == NULL)
647 : 4157 : set_config_entry(opts, CONF_FIREWD_MASQUERADE_ACCESS,
648 : : DEF_FIREWD_MASQUERADE_ACCESS);
649 : :
650 [ + + ]: 4145 : if(validate_firewd_chain_conf(opts->config[CONF_FIREWD_MASQUERADE_ACCESS]) != 1)
651 : : {
652 : 1 : log_msg(LOG_ERR,
653 : : "Invalid FIREWD_MASQUERADE_ACCESS specification, see fwknopd.conf comments"
654 : : );
655 : 1 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
656 : : }
657 : :
658 : : /* Check for the firewalld 'comment' match at init time
659 : : */
660 [ + - ]: 4144 : if(opts->config[CONF_ENABLE_FIREWD_COMMENT_CHECK] == NULL)
661 : 4144 : set_config_entry(opts, CONF_ENABLE_FIREWD_COMMENT_CHECK,
662 : : DEF_ENABLE_FIREWD_COMMENT_CHECK);
663 : :
664 : : #elif FIREWALL_IPTABLES
665 : : /* Enable IPT forwarding.
666 : : */
667 : : if(opts->config[CONF_ENABLE_IPT_FORWARDING] == NULL)
668 : : set_config_entry(opts, CONF_ENABLE_IPT_FORWARDING,
669 : : DEF_ENABLE_IPT_FORWARDING);
670 : :
671 : : /* Enable IPT local NAT.
672 : : */
673 : : if(opts->config[CONF_ENABLE_IPT_LOCAL_NAT] == NULL)
674 : : set_config_entry(opts, CONF_ENABLE_IPT_LOCAL_NAT,
675 : : DEF_ENABLE_IPT_LOCAL_NAT);
676 : :
677 : : /* Enable IPT SNAT.
678 : : */
679 : : if(opts->config[CONF_ENABLE_IPT_SNAT] == NULL)
680 : : set_config_entry(opts, CONF_ENABLE_IPT_SNAT,
681 : : DEF_ENABLE_IPT_SNAT);
682 : :
683 : : /* Make sure we have a valid IP if SNAT is enabled
684 : : */
685 : : if(strncasecmp(opts->config[CONF_ENABLE_IPT_SNAT], "Y", 1) == 0)
686 : : {
687 : : /* Note that fw_config_init() will set use_masquerade if necessary
688 : : */
689 : : if(opts->config[CONF_SNAT_TRANSLATE_IP] != NULL)
690 : : {
691 : : if(! is_valid_ipv4_addr(opts->config[CONF_SNAT_TRANSLATE_IP]))
692 : : {
693 : : log_msg(LOG_ERR,
694 : : "Invalid IPv4 addr for SNAT_TRANSLATE_IP"
695 : : );
696 : : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
697 : : }
698 : : }
699 : : }
700 : :
701 : : /* Enable IPT OUTPUT.
702 : : */
703 : : if(opts->config[CONF_ENABLE_IPT_OUTPUT] == NULL)
704 : : set_config_entry(opts, CONF_ENABLE_IPT_OUTPUT,
705 : : DEF_ENABLE_IPT_OUTPUT);
706 : :
707 : : /* Flush IPT at init.
708 : : */
709 : : if(opts->config[CONF_FLUSH_IPT_AT_INIT] == NULL)
710 : : set_config_entry(opts, CONF_FLUSH_IPT_AT_INIT, DEF_FLUSH_IPT_AT_INIT);
711 : :
712 : : /* Flush IPT at exit.
713 : : */
714 : : if(opts->config[CONF_FLUSH_IPT_AT_EXIT] == NULL)
715 : : set_config_entry(opts, CONF_FLUSH_IPT_AT_EXIT, DEF_FLUSH_IPT_AT_EXIT);
716 : :
717 : : /* IPT input access.
718 : : */
719 : : if(opts->config[CONF_IPT_INPUT_ACCESS] == NULL)
720 : : set_config_entry(opts, CONF_IPT_INPUT_ACCESS,
721 : : DEF_IPT_INPUT_ACCESS);
722 : :
723 : : if(validate_ipt_chain_conf(opts->config[CONF_IPT_INPUT_ACCESS]) != 1)
724 : : {
725 : : log_msg(LOG_ERR,
726 : : "Invalid IPT_INPUT_ACCESS specification, see fwknopd.conf comments"
727 : : );
728 : : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
729 : : }
730 : :
731 : : /* IPT output access.
732 : : */
733 : : if(opts->config[CONF_IPT_OUTPUT_ACCESS] == NULL)
734 : : set_config_entry(opts, CONF_IPT_OUTPUT_ACCESS,
735 : : DEF_IPT_OUTPUT_ACCESS);
736 : :
737 : : if(validate_ipt_chain_conf(opts->config[CONF_IPT_OUTPUT_ACCESS]) != 1)
738 : : {
739 : : log_msg(LOG_ERR,
740 : : "Invalid IPT_OUTPUT_ACCESS specification, see fwknopd.conf comments"
741 : : );
742 : : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
743 : : }
744 : :
745 : : /* IPT forward access.
746 : : */
747 : : if(opts->config[CONF_IPT_FORWARD_ACCESS] == NULL)
748 : : set_config_entry(opts, CONF_IPT_FORWARD_ACCESS,
749 : : DEF_IPT_FORWARD_ACCESS);
750 : :
751 : : if(validate_ipt_chain_conf(opts->config[CONF_IPT_FORWARD_ACCESS]) != 1)
752 : : {
753 : : log_msg(LOG_ERR,
754 : : "Invalid IPT_FORWARD_ACCESS specification, see fwknopd.conf comments"
755 : : );
756 : : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
757 : : }
758 : :
759 : : /* IPT dnat access.
760 : : */
761 : : if(opts->config[CONF_IPT_DNAT_ACCESS] == NULL)
762 : : set_config_entry(opts, CONF_IPT_DNAT_ACCESS,
763 : : DEF_IPT_DNAT_ACCESS);
764 : :
765 : : if(validate_ipt_chain_conf(opts->config[CONF_IPT_DNAT_ACCESS]) != 1)
766 : : {
767 : : log_msg(LOG_ERR,
768 : : "Invalid IPT_DNAT_ACCESS specification, see fwknopd.conf comments"
769 : : );
770 : : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
771 : : }
772 : :
773 : : /* IPT snat access.
774 : : */
775 : : if(opts->config[CONF_IPT_SNAT_ACCESS] == NULL)
776 : : set_config_entry(opts, CONF_IPT_SNAT_ACCESS,
777 : : DEF_IPT_SNAT_ACCESS);
778 : :
779 : : if(validate_ipt_chain_conf(opts->config[CONF_IPT_SNAT_ACCESS]) != 1)
780 : : {
781 : : log_msg(LOG_ERR,
782 : : "Invalid IPT_SNAT_ACCESS specification, see fwknopd.conf comments"
783 : : );
784 : : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
785 : : }
786 : :
787 : : /* IPT masquerade access.
788 : : */
789 : : if(opts->config[CONF_IPT_MASQUERADE_ACCESS] == NULL)
790 : : set_config_entry(opts, CONF_IPT_MASQUERADE_ACCESS,
791 : : DEF_IPT_MASQUERADE_ACCESS);
792 : :
793 : : if(validate_ipt_chain_conf(opts->config[CONF_IPT_MASQUERADE_ACCESS]) != 1)
794 : : {
795 : : log_msg(LOG_ERR,
796 : : "Invalid IPT_MASQUERADE_ACCESS specification, see fwknopd.conf comments"
797 : : );
798 : : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
799 : : }
800 : :
801 : : /* Check for the iptables 'comment' match at init time
802 : : */
803 : : if(opts->config[CONF_ENABLE_IPT_COMMENT_CHECK] == NULL)
804 : : set_config_entry(opts, CONF_ENABLE_IPT_COMMENT_CHECK,
805 : : DEF_ENABLE_IPT_COMMENT_CHECK);
806 : :
807 : : #elif FIREWALL_IPFW
808 : :
809 : : /* Flush ipfw rules at init.
810 : : */
811 : : if(opts->config[CONF_FLUSH_IPFW_AT_INIT] == NULL)
812 : : set_config_entry(opts, CONF_FLUSH_IPFW_AT_INIT, DEF_FLUSH_IPFW_AT_INIT);
813 : :
814 : : /* Flush ipfw rules at exit.
815 : : */
816 : : if(opts->config[CONF_FLUSH_IPFW_AT_EXIT] == NULL)
817 : : set_config_entry(opts, CONF_FLUSH_IPFW_AT_EXIT, DEF_FLUSH_IPFW_AT_EXIT);
818 : :
819 : : /* Set IPFW start rule number.
820 : : */
821 : : if(opts->config[CONF_IPFW_START_RULE_NUM] == NULL)
822 : : set_config_entry(opts, CONF_IPFW_START_RULE_NUM,
823 : : DEF_IPFW_START_RULE_NUM);
824 : :
825 : : /* Set IPFW max rules.
826 : : */
827 : : if(opts->config[CONF_IPFW_MAX_RULES] == NULL)
828 : : set_config_entry(opts, CONF_IPFW_MAX_RULES,
829 : : DEF_IPFW_MAX_RULES);
830 : :
831 : : /* Set IPFW active set number.
832 : : */
833 : : if(opts->config[CONF_IPFW_ACTIVE_SET_NUM] == NULL)
834 : : set_config_entry(opts, CONF_IPFW_ACTIVE_SET_NUM,
835 : : DEF_IPFW_ACTIVE_SET_NUM);
836 : :
837 : : /* Set IPFW expire set number.
838 : : */
839 : : if(opts->config[CONF_IPFW_EXPIRE_SET_NUM] == NULL)
840 : : set_config_entry(opts, CONF_IPFW_EXPIRE_SET_NUM,
841 : : DEF_IPFW_EXPIRE_SET_NUM);
842 : :
843 : : /* Set IPFW Dynamic rule expiry interval.
844 : : */
845 : : if(opts->config[CONF_IPFW_EXPIRE_PURGE_INTERVAL] == NULL)
846 : : set_config_entry(opts, CONF_IPFW_EXPIRE_PURGE_INTERVAL,
847 : : DEF_IPFW_EXPIRE_PURGE_INTERVAL);
848 : :
849 : : /* Set IPFW Dynamic rule expiry interval.
850 : : */
851 : : if(opts->config[CONF_IPFW_ADD_CHECK_STATE] == NULL)
852 : : set_config_entry(opts, CONF_IPFW_ADD_CHECK_STATE,
853 : : DEF_IPFW_ADD_CHECK_STATE);
854 : :
855 : : #elif FIREWALL_PF
856 : : /* Set PF anchor name
857 : : */
858 : : if(opts->config[CONF_PF_ANCHOR_NAME] == NULL)
859 : : set_config_entry(opts, CONF_PF_ANCHOR_NAME,
860 : : DEF_PF_ANCHOR_NAME);
861 : :
862 : : /* Set PF rule expiry interval.
863 : : */
864 : : if(opts->config[CONF_PF_EXPIRE_INTERVAL] == NULL)
865 : : set_config_entry(opts, CONF_PF_EXPIRE_INTERVAL,
866 : : DEF_PF_EXPIRE_INTERVAL);
867 : :
868 : : #elif FIREWALL_IPF
869 : : /* --DSS Place-holder */
870 : :
871 : : #endif /* FIREWALL type */
872 : :
873 : : /* GPG Home dir.
874 : : */
875 [ + + ]: 4120 : if(opts->config[CONF_GPG_HOME_DIR] == NULL)
876 : 4119 : set_config_entry(opts, CONF_GPG_HOME_DIR, DEF_GPG_HOME_DIR);
877 : :
878 : : /* GPG executable
879 : : */
880 [ + - ]: 4095 : if(opts->config[CONF_GPG_EXE] == NULL)
881 : 4095 : set_config_entry(opts, CONF_GPG_EXE, DEF_GPG_EXE);
882 : :
883 : : /* sudo executable
884 : : */
885 [ + + ]: 4085 : if(opts->config[CONF_SUDO_EXE] == NULL)
886 : 4077 : set_config_entry(opts, CONF_SUDO_EXE, DEF_SUDO_EXE);
887 : :
888 : : /* Enable SPA over HTTP.
889 : : */
890 [ + + ]: 4074 : if(opts->config[CONF_ENABLE_SPA_OVER_HTTP] == NULL)
891 : 4073 : set_config_entry(opts, CONF_ENABLE_SPA_OVER_HTTP,
892 : : DEF_ENABLE_SPA_OVER_HTTP);
893 : :
894 : : /* Enable TCP server.
895 : : */
896 [ + + ]: 4059 : if(opts->config[CONF_ENABLE_TCP_SERVER] == NULL)
897 : 4058 : set_config_entry(opts, CONF_ENABLE_TCP_SERVER, DEF_ENABLE_TCP_SERVER);
898 : :
899 : : /* TCP Server port.
900 : : */
901 [ + + ]: 4046 : if(opts->config[CONF_TCPSERV_PORT] == NULL)
902 : 4044 : set_config_entry(opts, CONF_TCPSERV_PORT, DEF_TCPSERV_PORT);
903 : :
904 : : /* Enable UDP server.
905 : : */
906 [ + + ]: 4037 : if(opts->config[CONF_ENABLE_UDP_SERVER] == NULL)
907 : : {
908 [ - + ][ # # ]: 4035 : if((strncasecmp(DEF_ENABLE_UDP_SERVER, "Y", 1) == 0) &&
909 : 0 : !opts->enable_udp_server)
910 : : {
911 : 0 : log_msg(LOG_ERR, "pcap capture not compiled in, forcing UDP server mode");
912 : 0 : opts->enable_udp_server = 1;
913 : : }
914 : 4035 : set_config_entry(opts, CONF_ENABLE_UDP_SERVER, DEF_ENABLE_UDP_SERVER);
915 : : }
916 : :
917 : : /* UDP Server port.
918 : : */
919 [ + + ]: 4030 : if(opts->config[CONF_UDPSERV_PORT] == NULL)
920 : 4027 : set_config_entry(opts, CONF_UDPSERV_PORT, DEF_UDPSERV_PORT);
921 : :
922 : : /* UDP server select() timeout in microseconds
923 : : */
924 [ + - ]: 4016 : if(opts->config[CONF_UDPSERV_SELECT_TIMEOUT] == NULL)
925 : 4016 : set_config_entry(opts, CONF_UDPSERV_SELECT_TIMEOUT,
926 : : DEF_UDPSERV_SELECT_TIMEOUT);
927 : :
928 : : /* Syslog identity.
929 : : */
930 [ + - ]: 4009 : if(opts->config[CONF_SYSLOG_IDENTITY] == NULL)
931 : 4009 : set_config_entry(opts, CONF_SYSLOG_IDENTITY, DEF_SYSLOG_IDENTITY);
932 : :
933 : : /* Syslog facility.
934 : : */
935 [ + + ]: 4002 : if(opts->config[CONF_SYSLOG_FACILITY] == NULL)
936 : 3992 : set_config_entry(opts, CONF_SYSLOG_FACILITY, DEF_SYSLOG_FACILITY);
937 : :
938 : :
939 : : /* Validate integer variable ranges
940 : : */
941 : 3989 : validate_int_var_ranges(opts);
942 : :
943 : : /* Some options just trigger some output of information, or trigger an
944 : : * external function, but do not actually start fwknopd. If any of those
945 : : * are set, we can return here an skip the validation routines as all
946 : : * other options will be ignored anyway.
947 : : *
948 : : * These are also mutually exclusive (for now).
949 : : */
950 [ + + ]: 3986 : if((opts->dump_config + opts->kill + opts->restart + opts->status) == 1)
951 : : return;
952 : :
953 [ + + ]: 2714 : if((opts->dump_config + opts->kill + opts->restart + opts->status) > 1)
954 : : {
955 : 2 : log_msg(LOG_ERR,
956 : : "The -D, -K, -R, and -S options are mutually exclusive. Pick only one."
957 : : );
958 : 2 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
959 : : }
960 : :
961 [ - + ]: 2712 : if(opts->config[CONF_FIREWALL_EXE] == NULL)
962 : : {
963 : 0 : log_msg(LOG_ERR,
964 : : "[*] No firewall command executable is set. Please check FIREWALL_EXE in fwknopd.conf."
965 : : );
966 : 0 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
967 : : }
968 : :
969 : : return;
970 : : }
971 : :
972 : : void
973 : 5857 : set_preconfig_entries(fko_srv_options_t *opts)
974 : : {
975 : : /* First, set any default or otherwise static settings here. Some may
976 : : * end up being overwritten via config file or command-line.
977 : : */
978 : :
979 : : /* Setup the firewall executable based on build-time info.
980 : : * --DSS Note: We will want to either force external script mode, or
981 : : * error out if we do not have a firewall executable defined.
982 : : */
983 : : #ifdef FIREWALL_EXE
984 : 5857 : set_config_entry(opts, CONF_FIREWALL_EXE, FIREWALL_EXE);
985 : : #endif
986 : :
987 : 5780 : }
988 : :
989 : : /* Initialize program configuration via config file and/or command-line
990 : : * switches.
991 : : */
992 : : void
993 : 5857 : config_init(fko_srv_options_t *opts, int argc, char **argv)
994 : : {
995 : : int cmd_arg, index, is_err;
996 : 5857 : unsigned char got_conf_file = 0, got_override_config = 0;
997 : :
998 : 5857 : char override_file[MAX_LINE_LEN] = {0};
999 : : char *ndx, *cmrk;
1000 : :
1001 : : /* Zero out options and opts_track.
1002 : : */
1003 : : memset(opts, 0x00, sizeof(fko_srv_options_t));
1004 : :
1005 : : /* Set some preconfiguration options (i.e. build-time defaults)
1006 : : */
1007 : 5857 : set_preconfig_entries(opts);
1008 : :
1009 : : /* In case this is a re-config.
1010 : : */
1011 : 5780 : optind = 0;
1012 : :
1013 : : /* First, scan the command-line args to see if we are in key-generation
1014 : : * mode. This is independent of config parsing and other operations, so
1015 : : * it is done as the very first thing. Also handle printing of the fwknop
1016 : : * version string since we don't need to parse a config for this.
1017 : : */
1018 [ + + ]: 54850 : while ((cmd_arg = getopt_long(argc, argv,
1019 : : GETOPTS_OPTION_STRING, cmd_opts, &index)) != -1) {
1020 : :
1021 [ + + + - : 43291 : switch(cmd_arg) {
- - + ]
1022 : : case 'V':
1023 : 1 : fprintf(stdout, "fwknopd server %s, compiled for firewall bin: %s\n",
1024 : : MY_VERSION, FIREWALL_EXE);
1025 : 1 : clean_exit(opts, NO_FW_CLEANUP, EXIT_SUCCESS);
1026 : : case 'k':
1027 : 103 : opts->key_gen = 1;
1028 : 103 : break;
1029 : : case KEY_GEN_FILE:
1030 : 2 : opts->key_gen = 1;
1031 : 2 : strlcpy(opts->key_gen_file, optarg, sizeof(opts->key_gen_file));
1032 : 2 : break;
1033 : : case KEY_LEN: /* used in --key-gen mode only */
1034 : 0 : opts->key_len = strtol_wrapper(optarg, 1,
1035 : : MAX_KEY_LEN, NO_EXIT_UPON_ERR, &is_err);
1036 [ # # ]: 0 : if(is_err != FKO_SUCCESS)
1037 : : {
1038 : 0 : log_msg(LOG_ERR,
1039 : : "Invalid key length '%s', must be in [%d-%d]",
1040 : : optarg, 1, MAX_KEY_LEN);
1041 : 0 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1042 : : }
1043 : : break;
1044 : : case HMAC_DIGEST_TYPE: /* used in --key-gen mode only */
1045 [ # # ]: 0 : if((opts->hmac_type = hmac_digest_strtoint(optarg)) < 0)
1046 : : {
1047 : 0 : log_msg(LOG_ERR,
1048 : : "* Invalid hmac digest type: %s, use {md5,sha1,sha256,sha384,sha512}",
1049 : : optarg);
1050 : 0 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1051 : : }
1052 : : break;
1053 : : case HMAC_KEY_LEN: /* used in --key-gen mode only */
1054 : 0 : opts->hmac_key_len = strtol_wrapper(optarg, 1,
1055 : : MAX_KEY_LEN, NO_EXIT_UPON_ERR, &is_err);
1056 [ # # ]: 0 : if(is_err != FKO_SUCCESS)
1057 : : {
1058 : 0 : log_msg(LOG_ERR,
1059 : : "Invalid hmac key length '%s', must be in [%d-%d]",
1060 : : optarg, 1, MAX_KEY_LEN);
1061 : 5885 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1062 : : }
1063 : : break;
1064 : : }
1065 : : }
1066 : :
1067 [ + + ]: 5779 : if(opts->key_gen)
1068 : 103 : generate_keys(opts); /* this function exits */
1069 : :
1070 : : /* Reset the options index so we can run through them again.
1071 : : */
1072 : 5676 : optind = 0;
1073 : :
1074 : : /* Now, scan the command-line args for -h/--help or an alternate
1075 : : * configuration file. If we find an alternate config file, use it,
1076 : : * otherwise use the default. We also grab any override config files
1077 : : * as well. In addition, we handle key generation here since this is
1078 : : * independent of configuration parsing.
1079 : : */
1080 [ + + ]: 52513 : while ((cmd_arg = getopt_long(argc, argv,
1081 : : GETOPTS_OPTION_STRING, cmd_opts, &index)) != -1) {
1082 : :
1083 : : /* If help is wanted, give it and exit.
1084 : : */
1085 [ + + + + ]: 41363 : switch(cmd_arg) {
1086 : : case 'h':
1087 : 1 : usage();
1088 : 1 : clean_exit(opts, NO_FW_CLEANUP, EXIT_SUCCESS);
1089 : :
1090 : : /* Look for configuration file arg.
1091 : : */
1092 : : case 'c':
1093 : 5674 : set_config_entry(opts, CONF_CONFIG_FILE, optarg);
1094 : 5562 : got_conf_file++;
1095 : :
1096 : : /* If we already have the config_override option, we are done.
1097 : : */
1098 [ + - ]: 5562 : if(got_override_config > 0)
1099 : : break;
1100 : :
1101 : : /* Look for override configuration file arg.
1102 : : */
1103 : : case 'O':
1104 : 5564 : set_config_entry(opts, CONF_OVERRIDE_CONFIG, optarg);
1105 : 11151 : got_override_config++;
1106 : :
1107 : : /* If we already have the conf_file option, we are done.
1108 : : */
1109 : : if(got_conf_file > 0)
1110 : : break;
1111 : : }
1112 : : }
1113 : :
1114 : : /* If no alternate configuration file was specified, we use the
1115 : : * default.
1116 : : */
1117 [ + + ]: 5474 : if(opts->config[CONF_CONFIG_FILE] == NULL)
1118 : 1 : set_config_entry(opts, CONF_CONFIG_FILE, DEF_CONFIG_FILE);
1119 : :
1120 : : /* Parse configuration file to populate any params not already specified
1121 : : * via command-line options.
1122 : : */
1123 : 5474 : parse_config_file(opts, opts->config[CONF_CONFIG_FILE]);
1124 : :
1125 : : /* If there are override configuration entries, process them
1126 : : * here.
1127 : : */
1128 [ + + ]: 5401 : if(opts->config[CONF_OVERRIDE_CONFIG] != NULL)
1129 : : {
1130 : : /* Make a copy of the override_config string so we can munge it.
1131 : : */
1132 : 5400 : strlcpy(override_file, opts->config[CONF_OVERRIDE_CONFIG], sizeof(override_file));
1133 : :
1134 : 5400 : ndx = override_file;
1135 : 5400 : cmrk = strchr(ndx, ',');
1136 : :
1137 [ + + ]: 5400 : if(cmrk == NULL)
1138 : : {
1139 : : /* Only one to process...
1140 : : */
1141 : 5399 : parse_config_file(opts, ndx);
1142 : :
1143 : : } else {
1144 : : /* Walk the string pulling the next config override
1145 : : * at the comma delimiters.
1146 : : */
1147 [ + + ]: 2 : while(cmrk != NULL) {
1148 : 1 : *cmrk = '\0';
1149 : 1 : parse_config_file(opts, ndx);
1150 : 1 : ndx = cmrk + 1;
1151 : 1 : cmrk = strchr(ndx, ',');
1152 : : }
1153 : :
1154 : : /* Process the last entry
1155 : : */
1156 : 1 : parse_config_file(opts, ndx);
1157 : : }
1158 : : }
1159 : :
1160 : : /* Set up the verbosity level according to the value found in the
1161 : : * config files */
1162 [ + + ]: 5330 : if (opts->config[CONF_VERBOSE] != NULL)
1163 : : {
1164 : 1 : opts->verbose = strtol_wrapper(opts->config[CONF_VERBOSE], 0, -1,
1165 : : NO_EXIT_UPON_ERR, &is_err);
1166 [ + - ]: 1 : if(is_err != FKO_SUCCESS)
1167 : : {
1168 : 1 : log_msg(LOG_ERR, "[*] VERBOSE value '%s' not in the range (>0)",
1169 : : opts->config[CONF_VERBOSE]);
1170 : 1 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1171 : : }
1172 : : }
1173 : :
1174 : : /* Reset the options index so we can run through them again.
1175 : : */
1176 : 5329 : optind = 0;
1177 : :
1178 : : /* Last, but not least, we process command-line options (some of which
1179 : : * may override configuration file options.
1180 : : */
1181 [ + + ]: 48250 : while ((cmd_arg = getopt_long(argc, argv,
1182 : : GETOPTS_OPTION_STRING, cmd_opts, &index)) != -1) {
1183 : :
1184 [ + - + + : 37895 : switch(cmd_arg) {
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + - + +
+ + + + +
+ ]
1185 : : case 'A':
1186 : : #if AFL_FUZZING
1187 : : opts->afl_fuzzing = 1;
1188 : : #else
1189 : 1 : log_msg(LOG_ERR, "[*] fwknopd not compiled with AFL fuzzing support");
1190 : 1 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1191 : : #endif
1192 : 0 : break;
1193 : : case AFL_PKT_FILE:
1194 : : #if AFL_FUZZING
1195 : : opts->afl_fuzzing = 1;
1196 : : set_config_entry(opts, CONF_AFL_PKT_FILE, optarg);
1197 : : #else
1198 : 0 : log_msg(LOG_ERR, "[*] fwknopd not compiled with AFL fuzzing support");
1199 : 0 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1200 : : #endif
1201 : 0 : break;
1202 : : case 'a':
1203 : 5328 : set_config_entry(opts, CONF_ACCESS_FILE, optarg);
1204 : 5251 : break;
1205 : : case 'c':
1206 : : /* This was handled earlier */
1207 : : break;
1208 : : case 'C':
1209 : 711 : opts->packet_ctr_limit = strtol_wrapper(optarg,
1210 : : 0, (2 << 30), NO_EXIT_UPON_ERR, &is_err);
1211 [ + + ]: 711 : if(is_err != FKO_SUCCESS)
1212 : : {
1213 : 1 : log_msg(LOG_ERR,
1214 : : "[*] invalid -C packet count limit '%s'",
1215 : : optarg);
1216 : 1 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1217 : : }
1218 : : break;
1219 : : case 'd':
1220 : : #if USE_FILE_CACHE
1221 : 5215 : set_config_entry(opts, CONF_DIGEST_FILE, optarg);
1222 : : #else
1223 : : set_config_entry(opts, CONF_DIGEST_DB_FILE, optarg);
1224 : : #endif
1225 : 5143 : break;
1226 : : case 'D':
1227 : 18 : opts->dump_config = 1;
1228 : 18 : break;
1229 : : case DUMP_SERVER_ERR_CODES:
1230 : 1 : dump_server_errors();
1231 : 1 : clean_exit(opts, NO_FW_CLEANUP, EXIT_SUCCESS);
1232 : : case EXIT_AFTER_PARSE_CONFIG:
1233 : 1632 : opts->exit_after_parse_config = 1;
1234 : 1632 : opts->foreground = 1;
1235 : 1632 : break;
1236 : : case 'f':
1237 : 2715 : opts->foreground = 1;
1238 : 2715 : break;
1239 : : case FAULT_INJECTION_TAG:
1240 : : #if HAVE_LIBFIU
1241 : 35 : set_config_entry(opts, CONF_FAULT_INJECTION_TAG, optarg);
1242 : : #else
1243 : : log_msg(LOG_ERR, "[*] fwknopd not compiled with libfiu support");
1244 : : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1245 : : #endif
1246 : 35 : break;
1247 : : case FW_LIST:
1248 : 1024 : opts->fw_list = 1;
1249 : 1024 : break;
1250 : : case FW_LIST_ALL:
1251 : 2 : opts->fw_list = 1;
1252 : 2 : opts->fw_list_all = 1;
1253 : 2 : break;
1254 : : case FW_FLUSH:
1255 : 19 : opts->fw_flush = 1;
1256 : 19 : break;
1257 : : case GPG_EXE_PATH:
1258 [ - + ]: 1 : if (is_valid_exe(optarg))
1259 : : {
1260 : 0 : set_config_entry(opts, CONF_GPG_EXE, optarg);
1261 : : }
1262 : : else
1263 : : {
1264 : 1 : log_msg(LOG_ERR,
1265 : : "[*] gpg path '%s' could not stat()/not executable?",
1266 : : optarg);
1267 : 1 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1268 : : }
1269 : : break;
1270 : : case GPG_HOME_DIR:
1271 [ + + ]: 3 : if (is_valid_dir(optarg))
1272 : : {
1273 : 1 : set_config_entry(opts, CONF_GPG_HOME_DIR, optarg);
1274 : : }
1275 : : else
1276 : : {
1277 : 2 : log_msg(LOG_ERR,
1278 : : "[*] gpg home directory '%s' could not stat()/does not exist?",
1279 : : optarg);
1280 : 2 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1281 : : }
1282 : : break;
1283 : : case 'i':
1284 : 2139 : set_config_entry(opts, CONF_PCAP_INTF, optarg);
1285 : 2108 : break;
1286 : : case FIREWD_DISABLE_CHECK_SUPPORT:
1287 : 9 : opts->firewd_disable_check_support = 1;
1288 : 9 : break;
1289 : : case IPT_DISABLE_CHECK_SUPPORT:
1290 : 599 : opts->ipt_disable_check_support = 1;
1291 : 599 : break;
1292 : : case 'K':
1293 : 419 : opts->kill = 1;
1294 : 419 : break;
1295 : : case 'l':
1296 : 2 : set_config_entry(opts, CONF_LOCALE, optarg);
1297 : 2 : break;
1298 : : case 'O':
1299 : : /* This was handled earlier */
1300 : : break;
1301 : : case 'p':
1302 : 5141 : set_config_entry(opts, CONF_FWKNOP_PID_FILE, optarg);
1303 : 5066 : break;
1304 : : case 'P':
1305 : 7 : set_config_entry(opts, CONF_PCAP_FILTER, optarg);
1306 : 7 : break;
1307 : : case PCAP_FILE:
1308 : 632 : set_config_entry(opts, CONF_PCAP_FILE, optarg);
1309 : 594 : break;
1310 : : case ENABLE_PCAP_ANY_DIRECTION:
1311 : 1 : opts->pcap_any_direction = 1;
1312 : 1 : break;
1313 : : case ROTATE_DIGEST_CACHE:
1314 : 2 : opts->rotate_digest_cache = 1;
1315 : 2 : break;
1316 : : case 'R':
1317 : 6 : opts->restart = 1;
1318 : 6 : break;
1319 : : case 'r':
1320 : 0 : set_config_entry(opts, CONF_FWKNOP_RUN_DIR, optarg);
1321 : 0 : break;
1322 : : case 'S':
1323 : 833 : opts->status = 1;
1324 : 833 : break;
1325 : : case SUDO_EXE_PATH:
1326 [ + + ]: 10 : if (is_valid_exe(optarg))
1327 : : {
1328 : 8 : set_config_entry(opts, CONF_SUDO_EXE, optarg);
1329 : : }
1330 : : else
1331 : : {
1332 : 2 : log_msg(LOG_ERR,
1333 : : "[*] sudo path '%s' could not stat()/not executable?",
1334 : : optarg);
1335 : 2 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1336 : : }
1337 : : break;
1338 : : case 't':
1339 : 595 : opts->test = 1;
1340 : 595 : break;
1341 : : case 'U':
1342 : 9 : opts->enable_udp_server = 1;
1343 : 9 : break;
1344 : : /* Verbosity level */
1345 : : case 'v':
1346 : 5452 : opts->verbose++;
1347 : 5452 : break;
1348 : : case SYSLOG_ENABLE:
1349 : 2 : opts->syslog_enable = 1;
1350 : 2 : break;
1351 : : default:
1352 : 2 : usage();
1353 : 37593 : clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1354 : : }
1355 : : }
1356 : :
1357 : : /* Now that we have all of our options set, and we are actually going to
1358 : : * start fwknopd, we can validate them.
1359 : : */
1360 : 5026 : validate_options(opts);
1361 : :
1362 : 3984 : return;
1363 : : }
1364 : :
1365 : : /* Dump the configuration
1366 : : */
1367 : : void
1368 : 1574 : dump_config(const fko_srv_options_t *opts)
1369 : : {
1370 : : int i;
1371 : :
1372 : 1574 : fprintf(stdout, "Current fwknopd config settings:\n");
1373 : :
1374 [ + + ]: 81848 : for(i=0; i<NUMBER_OF_CONFIG_ENTRIES; i++)
1375 [ + + ]: 80274 : fprintf(stdout, "%3i. %-28s = '%s'\n",
1376 : : i,
1377 : : config_map[i],
1378 : 80274 : (opts->config[i] == NULL) ? "<not set>" : opts->config[i]
1379 : : );
1380 : :
1381 : 1574 : fprintf(stdout, "\n");
1382 : 1574 : fflush(stdout);
1383 : 1574 : }
1384 : :
1385 : : /* Print usage message...
1386 : : */
1387 : : void
1388 : 3 : usage(void)
1389 : : {
1390 : 3 : fprintf(stdout, "\n%s server version %s\n%s - http://www.cipherdyne.org/fwknop/\n\n",
1391 : : MY_NAME, MY_VERSION, MY_DESC);
1392 : 3 : fprintf(stdout,
1393 : : "Usage: fwknopd [options]\n\n"
1394 : : " -a, --access-file - Specify an alternate access.conf file.\n"
1395 : : " -c, --config-file - Specify an alternate configuration file.\n"
1396 : : " -f, --foreground - Run fwknopd in the foreground (do not become\n"
1397 : : " a background daemon).\n"
1398 : : " -i, --interface - Specify interface to listen for incoming SPA\n"
1399 : : " packets.\n"
1400 : : " -C, --packet-limit - Limit the number of candidate SPA packets to\n"
1401 : : " process and exit when this limit is reached.\n"
1402 : : " -d, --digest-file - Specify an alternate digest.cache file.\n"
1403 : : " -D, --dump-config - Dump the current fwknop configuration values.\n"
1404 : : " -K, --kill - Kill the currently running fwknopd.\n"
1405 : : " -l, --locale - Provide a locale setting other than the system\n"
1406 : : " default.\n"
1407 : : " -O, --override-config - Specify a file with configuration entries that will\n"
1408 : : " overide those in fwknopd.conf\n"
1409 : : " -p, --pid-file - Specify an alternate fwknopd.pid file.\n"
1410 : : " -P, --pcap-filter - Specify a Berkeley packet filter statement to\n"
1411 : : " override the PCAP_FILTER variable in fwknopd.conf.\n"
1412 : : " -R, --restart - Force the currently running fwknopd to restart.\n"
1413 : : " --rotate-digest-cache\n"
1414 : : " - Rotate the digest cache file by renaming the file\n"
1415 : : " to the same path with the -old suffix.\n"
1416 : : " -r, --run-dir - Set path to local state run directory.\n"
1417 : : " - Rotate the digest cache file by renaming it to\n"
1418 : : " '<name>-old', and starting a new one.\n"
1419 : : " -S, --status - Display the status of any running fwknopd process.\n"
1420 : : " -t, --test - Test mode, process SPA packets but do not make any\n"
1421 : : " firewall modifications.\n"
1422 : : " -U, --udp-server - Set UDP server mode.\n"
1423 : : " -v, --verbose - Set verbose mode.\n"
1424 : : " --syslog-enable - Allow messages to be sent to syslog even if the\n"
1425 : : " foreground mode is set.\n"
1426 : : " -V, --version - Print version number.\n"
1427 : : " -A, --afl-fuzzing - Run in American Fuzzy Lop (AFL) fuzzing mode so\n"
1428 : : " that plaintext SPA packets are accepted via stdin.\n"
1429 : : " -h, --help - Print this usage message and exit.\n"
1430 : : " --dump-serv-err-codes - List all server error codes (only needed by the\n"
1431 : : " test suite).\n"
1432 : : " --exit-parse-config - Parse config files and exit.\n"
1433 : : " --fault-injection-tag - Enable a fault injection tag (only needed by the\n"
1434 : : " test suite).\n"
1435 : : " --pcap-file - Read potential SPA packets from an existing pcap\n"
1436 : : " file.\n"
1437 : : " --pcap-any-direction - By default fwknopd processes packets that are\n"
1438 : : " sent to the sniffing interface, but this option\n"
1439 : : " enables processing of packets that originate from\n"
1440 : : " an interface (such as in a forwarding situation).\n"
1441 : : " --fw-list - List all firewall rules that fwknop has created\n"
1442 : : " and then exit.\n"
1443 : : " --fw-list-all - List all firewall rules in the complete policy,\n"
1444 : : " including those that have nothing to do with\n"
1445 : : " fwknop.\n"
1446 : : " --fw-flush - Flush all firewall rules created by fwknop.\n"
1447 : : " --gpg-home-dir - Specify the GPG home directory (this is normally\n"
1448 : : " done in the access.conf file).\n"
1449 : : " --gpg-exe - Specify the path to GPG (this is normally done in\n"
1450 : : " the access.conf file).\n"
1451 : : " --sudo-exe - Specify the path to sudo (the default path is\n"
1452 : : " /usr/bin/sudo).\n"
1453 : : " --no-firewd-check-support\n"
1454 : : " - Disable test for 'firewall-cmd ... -C' support.\n"
1455 : : " --no-ipt-check-support - Disable test for 'iptables -C' support.\n"
1456 : : "\n"
1457 : : );
1458 : :
1459 : 3 : return;
1460 : : }
1461 : :
1462 : : /***EOF***/
|