Branch data Line data Source code
1 : : /**
2 : : ******************************************************************************
3 : : *
4 : : * \file config_init.c
5 : : *
6 : : * \brief Command-line and config file processing for fwknop client.
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 : :
32 : : #include "fwknop_common.h"
33 : : #include "netinet_common.h"
34 : : #include "config_init.h"
35 : : #include "cmd_opts.h"
36 : : #include "utils.h"
37 : : #include <sys/stat.h>
38 : : #include <fcntl.h>
39 : :
40 : : #ifdef WIN32
41 : : #define STDIN_FILENO 0
42 : : #endif
43 : :
44 : : #define RC_PARAM_TEMPLATE "%-24s %s\n" /*!< Template to define param = val in a rc file */
45 : : #define RC_SECTION_DEFAULT "default" /*!< Name of the default section in fwknoprc */
46 : : #define RC_SECTION_TEMPLATE "[%s]\n" /*!< Template to define a section in a rc file */
47 : : #define FWKNOPRC_OFLAGS (O_WRONLY|O_CREAT|O_EXCL) /*!< O_flags used to create an fwknoprc file with the open function */
48 : : #define FWKNOPRC_MODE (S_IRUSR|S_IWUSR) /*!< mode used to create an fwknoprc file with the open function */
49 : : #define PARAM_YES_VALUE "Y" /*!< String which represents a YES value for a parameter in fwknoprc */
50 : : #define PARAM_NO_VALUE "N" /*!< String which represents a NO value for a parameter in fwknoprc */
51 : : #define POSITION_TO_BITMASK(x) ((uint32_t)(1) << ((x) % 32)) /*!< Macro do get a bitmask from a position */
52 : : #define BITMASK_ARRAY_SIZE 2 /*!< Number of 32bits integer used to handle bitmask in the fko_var_bitmask_t structure */
53 : : #define LF_CHAR 0x0A /*!< Hexadecimal value associated to the LF char */
54 : :
55 : : /**
56 : : * Structure to handle long bitmask.
57 : : *
58 : : * The structure is built as an array of unsigned 32 bits integer to be able to
59 : : * easily increase the size of the bitmask.
60 : : * This bitmask can contains at most (BITMASK_ARRAY_SIZE * 32) values.
61 : : */
62 : : typedef struct fko_var_bitmask
63 : : {
64 : : uint32_t dw[BITMASK_ARRAY_SIZE]; /*!< Array of bitmasks */
65 : : } fko_var_bitmask_t;
66 : :
67 : : /**
68 : : * Structure to handle a variable in an rcfile (name and value)
69 : : */
70 : : typedef struct rc_file_param
71 : : {
72 : : char name[MAX_LINE_LEN]; /*!< Variable name */
73 : : char val[MAX_LINE_LEN]; /*!< Variable value */
74 : : } rc_file_param_t;
75 : :
76 : : /**
77 : : * Structure to identify a configuration variable (name and position)
78 : : */
79 : : typedef struct fko_var
80 : : {
81 : : const char name[32]; /*!< Variable name in fwknoprc */
82 : : unsigned int pos; /*!< Variable position from the fwknop_cli_arg_t enumeration */
83 : : } fko_var_t;
84 : :
85 : : enum
86 : : {
87 : : FWKNOP_CLI_FIRST_ARG = 0,
88 : : FWKNOP_CLI_ARG_DIGEST_TYPE = 0,
89 : : FWKNOP_CLI_ARG_SPA_SERVER_PROTO,
90 : : FWKNOP_CLI_ARG_SPA_SERVER_PORT,
91 : : FWKNOP_CLI_ARG_SPA_SOURCE_PORT,
92 : : FWKNOP_CLI_ARG_FW_TIMEOUT,
93 : : FWKNOP_CLI_ARG_ALLOW_IP,
94 : : FWKNOP_CLI_ARG_TIME_OFFSET,
95 : : FWKNOP_CLI_ARG_ENCRYPTION_MODE,
96 : : FWKNOP_CLI_ARG_USE_GPG,
97 : : FWKNOP_CLI_ARG_USE_GPG_AGENT,
98 : : FWKNOP_CLI_ARG_GPG_NO_SIGNING_PW,
99 : : FWKNOP_CLI_ARG_GPG_RECIPIENT,
100 : : FWKNOP_CLI_ARG_GPG_SIGNER,
101 : : FWKNOP_CLI_ARG_GPG_HOMEDIR,
102 : : FWKNOP_CLI_ARG_GPG_EXE_PATH,
103 : : FWKNOP_CLI_ARG_SPOOF_USER,
104 : : FWKNOP_CLI_ARG_SPOOF_SOURCE_IP,
105 : : FWKNOP_CLI_ARG_ACCESS,
106 : : FWKNOP_CLI_ARG_SPA_SERVER,
107 : : FWKNOP_CLI_ARG_RAND_PORT,
108 : : FWKNOP_CLI_ARG_KEY_RIJNDAEL,
109 : : FWKNOP_CLI_ARG_KEY_RIJNDAEL_BASE64,
110 : : FWKNOP_CLI_ARG_GPG_SIGNING_PW,
111 : : FWKNOP_CLI_ARG_GPG_SIGNING_PW_BASE64,
112 : : FWKNOP_CLI_ARG_HMAC_DIGEST_TYPE,
113 : : FWKNOP_CLI_ARG_KEY_HMAC_BASE64,
114 : : FWKNOP_CLI_ARG_KEY_HMAC,
115 : : FWKNOP_CLI_ARG_USE_HMAC,
116 : : FWKNOP_CLI_ARG_KEY_FILE,
117 : : FWKNOP_CLI_ARG_HMAC_KEY_FILE,
118 : : FWKNOP_CLI_ARG_NAT_ACCESS,
119 : : FWKNOP_CLI_ARG_HTTP_USER_AGENT,
120 : : FWKNOP_CLI_ARG_RESOLVE_URL,
121 : : FWKNOP_CLI_ARG_NAT_LOCAL,
122 : : FWKNOP_CLI_ARG_NAT_RAND_PORT,
123 : : FWKNOP_CLI_ARG_NAT_PORT,
124 : : FWKNOP_CLI_ARG_VERBOSE,
125 : : FWKNOP_CLI_ARG_RESOLVE_IP_HTTP,
126 : : FWKNOP_CLI_ARG_RESOLVE_IP_HTTPS,
127 : : FWKNOP_CLI_ARG_RESOLVE_HTTP_ONLY,
128 : : FWKNOP_CLI_ARG_WGET_CMD,
129 : : FWKNOP_CLI_LAST_ARG
130 : : } fwknop_cli_arg_t;
131 : :
132 : : static fko_var_t fko_var_array[FWKNOP_CLI_LAST_ARG] =
133 : : {
134 : : { "DIGEST_TYPE", FWKNOP_CLI_ARG_DIGEST_TYPE },
135 : : { "SPA_SERVER_PROTO", FWKNOP_CLI_ARG_SPA_SERVER_PROTO },
136 : : { "SPA_SERVER_PORT", FWKNOP_CLI_ARG_SPA_SERVER_PORT },
137 : : { "SPA_SOURCE_PORT", FWKNOP_CLI_ARG_SPA_SOURCE_PORT },
138 : : { "FW_TIMEOUT", FWKNOP_CLI_ARG_FW_TIMEOUT },
139 : : { "ALLOW_IP", FWKNOP_CLI_ARG_ALLOW_IP },
140 : : { "TIME_OFFSET", FWKNOP_CLI_ARG_TIME_OFFSET },
141 : : { "ENCRYPTION_MODE", FWKNOP_CLI_ARG_ENCRYPTION_MODE },
142 : : { "USE_GPG", FWKNOP_CLI_ARG_USE_GPG },
143 : : { "USE_GPG_AGENT", FWKNOP_CLI_ARG_USE_GPG_AGENT },
144 : : { "GPG_RECIPIENT", FWKNOP_CLI_ARG_GPG_RECIPIENT },
145 : : { "GPG_SIGNER", FWKNOP_CLI_ARG_GPG_SIGNER },
146 : : { "GPG_HOMEDIR", FWKNOP_CLI_ARG_GPG_HOMEDIR },
147 : : { "GPG_EXE", FWKNOP_CLI_ARG_GPG_EXE_PATH },
148 : : { "GPG_SIGNING_PW", FWKNOP_CLI_ARG_GPG_SIGNING_PW },
149 : : { "GPG_SIGNING_PW_BASE64", FWKNOP_CLI_ARG_GPG_SIGNING_PW_BASE64 },
150 : : { "GPG_NO_SIGNING_PW", FWKNOP_CLI_ARG_GPG_NO_SIGNING_PW },
151 : : { "SPOOF_USER", FWKNOP_CLI_ARG_SPOOF_USER },
152 : : { "SPOOF_SOURCE_IP", FWKNOP_CLI_ARG_SPOOF_SOURCE_IP },
153 : : { "ACCESS", FWKNOP_CLI_ARG_ACCESS },
154 : : { "SPA_SERVER", FWKNOP_CLI_ARG_SPA_SERVER },
155 : : { "RAND_PORT", FWKNOP_CLI_ARG_RAND_PORT },
156 : : { "KEY", FWKNOP_CLI_ARG_KEY_RIJNDAEL },
157 : : { "KEY_BASE64", FWKNOP_CLI_ARG_KEY_RIJNDAEL_BASE64 },
158 : : { "HMAC_DIGEST_TYPE", FWKNOP_CLI_ARG_HMAC_DIGEST_TYPE },
159 : : { "HMAC_KEY_BASE64", FWKNOP_CLI_ARG_KEY_HMAC_BASE64 },
160 : : { "HMAC_KEY", FWKNOP_CLI_ARG_KEY_HMAC },
161 : : { "USE_HMAC", FWKNOP_CLI_ARG_USE_HMAC },
162 : : { "KEY_FILE", FWKNOP_CLI_ARG_KEY_FILE },
163 : : { "HMAC_KEY_FILE", FWKNOP_CLI_ARG_HMAC_KEY_FILE },
164 : : { "NAT_ACCESS", FWKNOP_CLI_ARG_NAT_ACCESS },
165 : : { "HTTP_USER_AGENT", FWKNOP_CLI_ARG_HTTP_USER_AGENT },
166 : : { "RESOLVE_URL", FWKNOP_CLI_ARG_RESOLVE_URL },
167 : : { "NAT_LOCAL", FWKNOP_CLI_ARG_NAT_LOCAL },
168 : : { "NAT_RAND_PORT", FWKNOP_CLI_ARG_NAT_RAND_PORT },
169 : : { "NAT_PORT", FWKNOP_CLI_ARG_NAT_PORT },
170 : : { "VERBOSE", FWKNOP_CLI_ARG_VERBOSE },
171 : : { "RESOLVE_IP_HTTP", FWKNOP_CLI_ARG_RESOLVE_IP_HTTP },
172 : : { "RESOLVE_IP_HTTPS", FWKNOP_CLI_ARG_RESOLVE_IP_HTTPS },
173 : : { "RESOLVE_HTTP_ONLY", FWKNOP_CLI_ARG_RESOLVE_HTTP_ONLY },
174 : : { "WGET_CMD", FWKNOP_CLI_ARG_WGET_CMD }
175 : : };
176 : :
177 : : /* Array to define which conf. variables are critical and should not be
178 : : * overwritten when a stanza is updated using the --save-rc-stanza arg
179 : : * without the user validation */
180 : : static int critical_var_array[] =
181 : : {
182 : : FWKNOP_CLI_ARG_KEY_RIJNDAEL,
183 : : FWKNOP_CLI_ARG_KEY_RIJNDAEL_BASE64,
184 : : FWKNOP_CLI_ARG_KEY_HMAC,
185 : : FWKNOP_CLI_ARG_KEY_HMAC_BASE64,
186 : : FWKNOP_CLI_ARG_GPG_RECIPIENT,
187 : : FWKNOP_CLI_ARG_GPG_SIGNER,
188 : : FWKNOP_CLI_ARG_GPG_SIGNING_PW,
189 : : FWKNOP_CLI_ARG_GPG_SIGNING_PW_BASE64
190 : : };
191 : :
192 : : /**
193 : : * @brief Generate Rijndael + HMAC keys from /dev/random (base64 encoded) and exit.
194 : : *
195 : : * @param options FKO command line option structure
196 : : */
197 : : static void
198 : 2472 : generate_keys(fko_cli_options_t *options)
199 : : {
200 : : int res;
201 : :
202 : : /* If asked, we have to generate the keys */
203 [ + + ]: 2472 : if(options->key_gen)
204 : : {
205 : : /* Zero out the key buffers */
206 : 114 : memset(&(options->key_base64), 0x00, sizeof(options->key_base64));
207 : 114 : memset(&(options->hmac_key_base64), 0x00, sizeof(options->hmac_key_base64));
208 : :
209 : : /* Generate the key through libfko */
210 : 114 : res = fko_key_gen(options->key_base64, options->key_len,
211 : : options->hmac_key_base64, options->hmac_key_len,
212 : : options->hmac_type);
213 : :
214 : : /* Exit upon key generation failure*/
215 [ - + ]: 114 : if(res != FKO_SUCCESS)
216 : : {
217 : 0 : log_msg(LOG_VERBOSITY_ERROR, "%s: fko_key_gen: Error %i - %s",
218 : : MY_NAME, res, fko_errstr(res));
219 : 0 : exit(EXIT_FAILURE);
220 : : }
221 : :
222 : : /* Everything is ok - nothing to do */
223 : : else;
224 : : }
225 : :
226 : : /* No key generation asked - nothing to do */
227 : : else;
228 : 2472 : }
229 : :
230 : : /**
231 : : * @brief Check if a variable is a critical var.
232 : : *
233 : : * This function check the critical_var_array table to find if the variable
234 : : * position is available.
235 : : *
236 : : * @param var_pos Fwknop configuration variable position
237 : : *
238 : : * @return 1 the variable is critical, 0 otherwise
239 : : */
240 : : static int
241 : 10 : var_is_critical(short var_pos)
242 : : {
243 : : int ndx; /* Index on the critical_var_array array */
244 : 10 : int var_found = 0;
245 : :
246 : : /* Go through the array of critical vars */
247 [ + + ]: 57 : for (ndx=0 ; ndx<ARRAY_SIZE(critical_var_array) ; ndx++)
248 : : {
249 : : /* and check if we find it */
250 [ + + ]: 52 : if (var_pos == critical_var_array[ndx])
251 : : {
252 : : var_found = 1;
253 : : break;
254 : : }
255 : : }
256 : :
257 : 10 : return var_found;
258 : : }
259 : :
260 : : /**
261 : : * @brief Add a variable to a bitmask
262 : : *
263 : : * This function adds the bitmask associated to a variable position, to a
264 : : * bitmask.
265 : : *
266 : : * @param var_pos Fwknop configuration variable position
267 : : * @param bm fko_var_bitmask_t variable to update
268 : : */
269 : : static void
270 : 15144 : add_var_to_bitmask(short var_pos, fko_var_bitmask_t *bm)
271 : : {
272 : : unsigned int bitmask_ndx;
273 : :
274 : : /* Look for the index on the uint32_t array we have to process */
275 : 15144 : bitmask_ndx = var_pos / 32;
276 : :
277 : : /* Set the bitmask according to the index found */
278 [ + - ]: 15144 : if (bitmask_ndx < BITMASK_ARRAY_SIZE)
279 : 15144 : bm->dw[bitmask_ndx] |= POSITION_TO_BITMASK(var_pos);
280 : :
281 : : /* The index on the uint32_t bitmask is invalid */
282 : : else
283 : 0 : log_msg(LOG_VERBOSITY_WARNING, "add_var_to_bitmask() : Bad variable position %u", var_pos);
284 : 15144 : }
285 : :
286 : : /**
287 : : * @brief Remove a variable from a bitmask
288 : : *
289 : : * This function removes the bitmask associated to the variable position from a
290 : : * bitmask.
291 : : *
292 : : * @param var_pos Fwknop configuration variable position
293 : : * @param bm fko_var_bitmask_t structure to update
294 : : */
295 : : static void
296 : 1 : remove_var_from_bitmask(short var_pos, fko_var_bitmask_t *bm)
297 : : {
298 : : unsigned int bitmask_ndx;
299 : :
300 : : /* Look for the index on the uint32_t array we have to process */
301 : 1 : bitmask_ndx = var_pos / 32;
302 : :
303 : : /* Set the bitmask according to the index found */
304 [ + - ]: 1 : if (bitmask_ndx < BITMASK_ARRAY_SIZE)
305 : 1 : bm->dw[bitmask_ndx] &= ~POSITION_TO_BITMASK(var_pos);
306 : :
307 : : /* The index on the uint32_t bitmask is invalid */
308 : : else
309 : 0 : log_msg(LOG_VERBOSITY_WARNING, "remove_from_bitmask() : Bad variable position %u", var_pos);
310 : 1 : }
311 : :
312 : : /**
313 : : * @brief Return whether a variable is available in a bitmask
314 : : *
315 : : * The variable bitmask is looked for in the bitmask.
316 : : *
317 : : * @param var_pos Fwknop configuration variable position
318 : : * @param bm fko_var_bitmask_t structure to check
319 : : *
320 : : * @return 1 if the bitmsk contains the variable, 0 otherwise.
321 : : */
322 : : static int
323 : 3608 : bitmask_has_var(short var_pos, fko_var_bitmask_t *bm)
324 : : {
325 : : unsigned int bitmask_ndx;
326 : 3608 : int var_found = 0;
327 : :
328 : : /* Look for the index on the uint32_t array we have to process */
329 : 3608 : bitmask_ndx = var_pos / 32;
330 : :
331 : : /* Check the bitmask according to the index found */
332 [ + - ]: 3608 : if (bitmask_ndx < BITMASK_ARRAY_SIZE)
333 : : {
334 [ + + ]: 3608 : if ( bm->dw[bitmask_ndx] & POSITION_TO_BITMASK(var_pos) )
335 : 530 : var_found = 1;
336 : : }
337 : :
338 : : /* The index on the uint32_t bitmask is invalid */
339 : : else
340 : 0 : log_msg(LOG_VERBOSITY_WARNING, "bitmask_has_var_ndx() : Bad variable position %u", var_pos);
341 : :
342 : 3608 : return var_found;
343 : : }
344 : :
345 : : /**
346 : : * @brief Ask the user if a variable must be overwritten or not for a specific stanza
347 : : *
348 : : * If the user sets other chars than a 'y' char, we assume he does not want to
349 : : * overwrite the variable.
350 : : *
351 : : * @param var Variable which should be overwritten
352 : : * @param stanza Stanza where the variable should be overwritten
353 : : *
354 : : * @return 1 if the user wants to overwrite the variable, 0 otherwise
355 : : */
356 : : static int
357 : 5 : ask_overwrite_var(const char *var, const char *stanza)
358 : : {
359 : 5 : char user_input = 'N';
360 : 5 : int overwrite = 0;
361 : : int c;
362 : 5 : int first_char = 1;;
363 : :
364 : 5 : log_msg(LOG_VERBOSITY_NORMAL,
365 : : "Variable '%s' found in stanza '%s'. Overwrite [N/y] ? ",
366 : : var, stanza);
367 : :
368 [ + + ]: 10 : while ((c=getchar()) != LF_CHAR)
369 : : {
370 [ + - ]: 5 : if (first_char)
371 : 5 : user_input = c;
372 : : first_char = 0;
373 : : }
374 : :
375 [ + + ]: 5 : if (user_input == 'y')
376 : 4 : overwrite = 1;
377 : :
378 : 5 : return overwrite;
379 : : }
380 : :
381 : : /**
382 : : * @brief Lookup a variable in the variable array according to its name
383 : : *
384 : : * This function parses the fko_var_array table and try to find a match
385 : : * for the user string, which indicates we have found a configuration variable.
386 : : *
387 : : * @param str String to compare against every fwknop conf variables
388 : : *
389 : : * @return A pointer on the variable structure, or NULL if not found
390 : : */
391 : : static fko_var_t *
392 : 1049 : lookup_var_by_name(const char *var_name)
393 : : {
394 : : short ndx; /* Index on the the fko_var_array table */
395 : 1049 : fko_var_t *var = NULL;
396 : :
397 : : /* Check str against each variable available in fko_var_array */
398 [ + + ]: 22593 : for (ndx=0 ; ndx<ARRAY_SIZE(fko_var_array) ; ndx++)
399 : : {
400 [ + + ]: 22590 : if (CONF_VAR_IS(var_name, fko_var_array[ndx].name))
401 : : {
402 : : var = &(fko_var_array[ndx]);
403 : : break;
404 : : }
405 : : }
406 : :
407 : 1049 : return var;
408 : : }
409 : :
410 : : /**
411 : : * @brief Lookup a variable in the variable array according to its position
412 : : *
413 : : * This function parses the fko_var_array table and try to find a match
414 : : * for the position, which indicates we have found a configuration variable.
415 : : *
416 : : * @param var_pos Position to compare against every fwknop conf variables
417 : : *
418 : : * @return A pointer on the variable structure, or NULL if not found
419 : : */
420 : : static fko_var_t *
421 : 530 : lookup_var_by_position(short var_pos)
422 : : {
423 : : short ndx; /* Index on the the fko_var_array table */
424 : 530 : fko_var_t *var = NULL;
425 : :
426 : : /* Check str against each variable available in fko_var_array */
427 [ + - ]: 10985 : for (ndx=0 ; ndx<ARRAY_SIZE(fko_var_array) ; ndx++)
428 : : {
429 [ + + ]: 10985 : if (var_pos == fko_var_array[ndx].pos)
430 : : {
431 : 530 : var = &(fko_var_array[ndx]);
432 : 530 : break;
433 : : }
434 : : }
435 : :
436 : 530 : return var;
437 : : }
438 : :
439 : : /**
440 : : * @brief Set a string as a Yes or No value according to a boolean (0 or 1).
441 : : *
442 : : * This function checks whether a value is set to zero or not, and updates a
443 : : * string to a YES_NO parameter value.
444 : : * The string must be zeroed before being passed to the function.
445 : : *
446 : : * @param val Variable to check
447 : : * @param s String where to store the YES_NO value.
448 : : * @param len Number of bytes avaialble for the s buffer.
449 : : */
450 : : static void
451 : 51 : bool_to_yesno(int val, char* s, size_t len)
452 : : {
453 [ - + ]: 51 : if (val == 0)
454 : 0 : strlcpy(s, PARAM_NO_VALUE, len);
455 : : else
456 : 51 : strlcpy(s, PARAM_YES_VALUE, len);
457 : 51 : }
458 : :
459 : : /**
460 : : * @brief Is a string formatted as YES string.
461 : : *
462 : : * @param s String to check for a YES string
463 : : *
464 : : * @return 1 if the string match the YES pattern, 0 otherwise
465 : : */
466 : : static int
467 : 48 : is_yes_str(const char *s)
468 : : {
469 : : int valid;
470 : :
471 [ + + ]: 48 : if (strcasecmp(PARAM_YES_VALUE, s) == 0)
472 : : valid = 1;
473 : : else
474 : 22 : valid = 0;
475 : :
476 : 48 : return valid;
477 : : }
478 : :
479 : : /**
480 : : * @brief Check if a section is in a line and fetch it.
481 : : *
482 : : * This function parses a NULL terminated string in order to find a section,
483 : : * something like [mysection]. If it succeeds, the stanza is retrieved.
484 : : *
485 : : * @param line String containing a line from the rc file to check for a section
486 : : * @param line_size size of the line buffer
487 : : * @param rc_section String to store the section found
488 : : * @param rc_section_size Size of the rc_section buffer
489 : : *
490 : : * @return 1 if a section was found, 0 otherwise
491 : : */
492 : : static int
493 : 3903 : is_rc_section(const char* line, uint16_t line_size, char* rc_section, uint16_t rc_section_size)
494 : : {
495 : : char *ndx, *emark;
496 : 3903 : char buf[MAX_LINE_LEN] = {0};
497 : 3903 : int section_found = 0;
498 : :
499 [ + - ]: 3903 : if (line_size < sizeof(buf))
500 : : {
501 : 3903 : strlcpy(buf, line, sizeof(buf));
502 : :
503 : 3903 : ndx = buf;
504 : :
505 [ + + ]: 3907 : while(isspace(*ndx))
506 : 4 : ndx++;
507 : :
508 [ + + ]: 3903 : if(*ndx == '[')
509 : : {
510 : 2592 : ndx++;
511 : 2592 : emark = strchr(ndx, ']');
512 [ + - ]: 2592 : if(emark != NULL)
513 : : {
514 : 2592 : *emark = '\0';
515 : 2592 : memset(rc_section, 0, rc_section_size);
516 : 2592 : strlcpy(rc_section, ndx, rc_section_size);
517 : 2592 : section_found = 1;
518 : : }
519 : : else
520 : : {
521 : : }
522 : : }
523 : : }
524 : : else
525 : : {
526 : : }
527 : :
528 : 3903 : return section_found;
529 : : }
530 : :
531 : : /**
532 : : * @brief Grab a variable and its value from a rc line.
533 : : *
534 : : * @param line Line to parse for a variable
535 : : * @param param Parameter structure where to store the variable name and its value
536 : : *
537 : : * @return 0 if no variable has been found, 1 otherwise.
538 : : */
539 : : static int
540 : 1050 : is_rc_param(const char *line, rc_file_param_t *param)
541 : : {
542 : 1050 : char var[MAX_LINE_LEN] = {0};
543 : 1050 : char val[MAX_LINE_LEN] = {0};
544 : : char *ndx;
545 : :
546 : : memset(param, 0, sizeof(*param));
547 : :
548 : : /* Fetch the variable and its value */
549 [ + + ]: 1050 : if(sscanf(line, "%s %[^ ;\t\n\r#]", var, val) != 2)
550 : : {
551 : 1 : log_msg(LOG_VERBOSITY_WARNING,
552 : : "*Invalid entry in '%s'", line);
553 : 1 : return 0;
554 : : }
555 : :
556 : : /* Remove any colon that may be on the end of the var */
557 [ + + ]: 1049 : if((ndx = strrchr(var, ':')) != NULL)
558 : 15 : *ndx = '\0';
559 : :
560 : : /* Even though sscanf should automatically add a terminating
561 : : * NULL byte, an assumption is made that the input arrays are
562 : : * big enough, so we'll force a terminating NULL byte regardless
563 : : */
564 : 1049 : var[MAX_LINE_LEN-1] = 0x0;
565 : 1049 : val[MAX_LINE_LEN-1] = 0x0;
566 : :
567 : : /* Copy back the val and var in the structure */
568 : 1049 : strlcpy(param->name, var, sizeof(param->name));
569 : 1049 : strlcpy(param->val, val, sizeof(param->val));
570 : :
571 : 1049 : return 1;
572 : : }
573 : :
574 : : /**
575 : : * @brief Dump available stanzas from a fwknoprc file
576 : : *
577 : : * This function parses a rcfile and looks for configured stanzas.
578 : : * They are all displayed except the default stanza.
579 : : *
580 : : * @param rcfile full path to the rcfile to parse
581 : : */
582 : : static int
583 : 2 : dump_configured_stanzas_from_rcfile(const char* rcfile)
584 : : {
585 : : FILE *rc;
586 : 2 : char line[MAX_LINE_LEN] = {0};
587 : 2 : char curr_stanza[MAX_LINE_LEN] = {0};
588 : :
589 : : /* Open the rcfile in read mode */
590 [ + + ]: 2 : if ((rc = fopen(rcfile, "r")) == NULL)
591 : : {
592 : 1 : log_msg(LOG_VERBOSITY_WARNING, "Unable to open rc file: %s: %s",
593 : 1 : rcfile, strerror(errno));
594 : :
595 : 1 : return EXIT_FAILURE;
596 : : }
597 : :
598 : 1 : log_msg(LOG_VERBOSITY_NORMAL, "The following stanzas are configured in %s :", rcfile);
599 : :
600 : : /* Parse the rcfile line by line to find stanza */
601 [ + + ]: 10 : while ((fgets(line, MAX_LINE_LEN, rc)) != NULL)
602 : : {
603 : 8 : line[MAX_LINE_LEN-1] = '\0';
604 : :
605 : : /* Get past comments and empty lines (note: we only look at the first
606 : : * character. */
607 [ + + ][ + - ]: 8 : if(IS_EMPTY_LINE(line[0]))
[ + - ][ - + ]
608 : 2 : continue;
609 : :
610 : : /* Check which section we are working on */
611 [ + + ]: 6 : else if (is_rc_section(line, strlen(line), curr_stanza, sizeof(curr_stanza)))
612 : : {
613 : : /* Print the stanza and continue - we exclude the default stanza */
614 [ + + ]: 3 : if (strcasecmp(curr_stanza, RC_SECTION_DEFAULT) != 0)
615 : 2 : log_msg(LOG_VERBOSITY_NORMAL, " - %s", curr_stanza);
616 : 8 : continue;
617 : : }
618 : :
619 : : /* Nothing we care about */
620 : : else;
621 : : }
622 : :
623 : 1 : fclose(rc);
624 : :
625 : 1 : return EXIT_SUCCESS;
626 : : }
627 : :
628 : : /* Assign path to fwknop rc file
629 : : */
630 : : static void
631 : 2625 : set_rc_file(char *rcfile, fko_cli_options_t *options)
632 : : {
633 : : int rcf_offset;
634 : : char *homedir;
635 : :
636 : : memset(rcfile, 0x0, MAX_PATH_LEN);
637 : :
638 [ + + ]: 2625 : if(options->rc_file[0] == 0x0)
639 : : {
640 : : #ifdef WIN32
641 : : homedir = getenv("USERPROFILE");
642 : : #else
643 : 2181 : homedir = getenv("HOME");
644 : : #endif
645 : :
646 [ - + ]: 2181 : if(homedir == NULL)
647 : : {
648 : 0 : log_msg(LOG_VERBOSITY_ERROR, "Warning: Unable to determine HOME directory.\n"
649 : : " No .fwknoprc file processed.");
650 : 0 : exit(EXIT_FAILURE);
651 : : }
652 : :
653 : 2181 : strlcpy(rcfile, homedir, MAX_PATH_LEN);
654 : :
655 : 2181 : rcf_offset = strlen(rcfile);
656 : :
657 : : /* Sanity check the path to .fwknoprc.
658 : : * The preceeding path plus the path separator and '.fwknoprc' = 11
659 : : * cannot exceed MAX_PATH_LEN.
660 : : */
661 [ + + ]: 2181 : if(rcf_offset > (MAX_PATH_LEN - 11))
662 : : {
663 : 1 : log_msg(LOG_VERBOSITY_ERROR, "Warning: Path to .fwknoprc file is too long.\n"
664 : : " No .fwknoprc file processed.");
665 : 1 : exit(EXIT_FAILURE);
666 : : }
667 : :
668 : 2180 : rcfile[rcf_offset] = PATH_SEP;
669 : 2180 : strlcat(rcfile, ".fwknoprc", MAX_PATH_LEN);
670 : : }
671 : : else
672 : : {
673 : 444 : strlcpy(rcfile, options->rc_file, MAX_PATH_LEN);
674 : : }
675 : :
676 : : /* Check rc file permissions - if anything other than user read/write,
677 : : * then throw a warning. This change was made to help ensure that the
678 : : * client consumes a proper rc file with strict permissions set (thanks
679 : : * to Fernando Arnaboldi from IOActive for pointing this out).
680 : : */
681 [ + + ]: 2624 : if(verify_file_perms_ownership(rcfile) != 1)
682 : 1 : exit(EXIT_FAILURE);
683 : :
684 : 2623 : return;
685 : : }
686 : :
687 : : static void
688 : 2472 : keys_status(fko_cli_options_t *options)
689 : : {
690 : 2472 : FILE *key_gen_file_ptr = NULL;
691 : 2472 : char rcfile[MAX_PATH_LEN] = {0};
692 : :
693 [ + + ]: 2472 : if(options->key_gen == 1)
694 : : {
695 [ + + ]: 114 : if(options->key_gen_file[0] != '\0')
696 : : {
697 [ + + ]: 2 : if ((key_gen_file_ptr = fopen(options->key_gen_file, "w")) == NULL)
698 : : {
699 : 1 : log_msg(LOG_VERBOSITY_ERROR, "Unable to create key gen file: %s: %s",
700 : 1 : options->key_gen_file, strerror(errno));
701 : 1 : exit(EXIT_FAILURE);
702 : : }
703 : : fprintf(key_gen_file_ptr, "KEY_BASE64: %s\nHMAC_KEY_BASE64: %s\n",
704 : 1 : options->key_base64, options->hmac_key_base64);
705 : 1 : fclose(key_gen_file_ptr);
706 : 1 : log_msg(LOG_VERBOSITY_NORMAL,
707 : : "[+] Wrote Rijndael and HMAC keys to: %s",
708 : : options->key_gen_file);
709 : : }
710 : : else
711 : : {
712 [ + + ]: 112 : if(options->save_rc_stanza == 1)
713 : : {
714 : 11 : set_rc_file(rcfile, options);
715 : 11 : log_msg(LOG_VERBOSITY_NORMAL,
716 : : "[+] Wrote Rijndael and HMAC keys to rc file: %s", rcfile);
717 : : }
718 : : else
719 : 101 : log_msg(LOG_VERBOSITY_NORMAL,
720 : : "KEY_BASE64: %s\nHMAC_KEY_BASE64: %s",
721 : 101 : options->key_base64, options->hmac_key_base64);
722 : : }
723 : :
724 : : /* Always exit out in --key-gen mode since the fwknopd server
725 : : * has no way to know what the new keys are
726 : : */
727 : 113 : exit(EXIT_SUCCESS);
728 : : }
729 : 2358 : }
730 : :
731 : :
732 : : /* Parse any time offset from the command line
733 : : */
734 : : static int
735 : 15 : parse_time_offset(const char *offset_str, int *offset)
736 : : {
737 : : int i, j;
738 : 15 : int offset_type = TIME_OFFSET_SECONDS;
739 : 15 : int os_len = strlen(offset_str);
740 : 15 : int is_err = 0;
741 : :
742 : 15 : char offset_digits[MAX_TIME_STR_LEN] = {0};
743 : :
744 : 15 : j=0;
745 [ + + ]: 53 : for (i=0; i < os_len; i++) {
746 [ + + ]: 47 : if (isdigit(offset_str[i])) {
747 : 26 : offset_digits[j] = offset_str[i];
748 : 26 : j++;
749 [ + + ]: 26 : if(j >= MAX_TIME_STR_LEN)
750 : : {
751 : : return 0;
752 : : }
753 [ + + ]: 21 : } else if (offset_str[i] == 'm' || offset_str[i] == 'M') {
754 : : offset_type = TIME_OFFSET_MINUTES;
755 : : break;
756 [ + + ]: 18 : } else if (offset_str[i] == 'h' || offset_str[i] == 'H') {
757 : : offset_type = TIME_OFFSET_HOURS;
758 : : break;
759 [ + + ]: 16 : } else if (offset_str[i] == 'd' || offset_str[i] == 'D') {
760 : : offset_type = TIME_OFFSET_DAYS;
761 : : break;
762 : : }
763 : : }
764 : :
765 : 14 : offset_digits[j] = '\0';
766 : :
767 [ + + ]: 14 : if (j < 1)
768 : : return 0;
769 : :
770 : 13 : *offset = strtol_wrapper(offset_digits, 0, (2 << 15),
771 : : NO_EXIT_UPON_ERR, &is_err);
772 : :
773 : : /* Apply the offset_type multiplier
774 : : */
775 : 13 : *offset *= offset_type;
776 : :
777 : 13 : return is_err == 0 ? 1 : 0;
778 : : }
779 : :
780 : : static int
781 : 1 : create_fwknoprc(const char *rcfile)
782 : : {
783 : 1 : FILE *rc = NULL;
784 : 1 : int rcfile_fd = -1;
785 : :
786 : 1 : log_msg(LOG_VERBOSITY_NORMAL, "[*] Creating initial rc file: %s.", rcfile);
787 : :
788 : : /* Try to create the initial rcfile with user read/write rights only.
789 : : * If the rcfile already exists, an error is returned */
790 : 1 : rcfile_fd = open(rcfile, FWKNOPRC_OFLAGS ,FWKNOPRC_MODE);
791 : :
792 : : // If an error occured ...
793 [ - + ]: 1 : if (rcfile_fd == -1) {
794 : 0 : log_msg(LOG_VERBOSITY_WARNING, "Unable to create initial rc file: %s: %s",
795 : 0 : rcfile, strerror(errno));
796 : 0 : return(-1);
797 : : }
798 : :
799 : : // Free the rcfile descriptor
800 : 1 : close(rcfile_fd);
801 : :
802 [ - + ]: 1 : if ((rc = fopen(rcfile, "w")) == NULL)
803 : : {
804 : 0 : log_msg(LOG_VERBOSITY_WARNING, "Unable to write default setup to rcfile: %s: %s",
805 : 0 : rcfile, strerror(errno));
806 : 0 : return(-1);
807 : : }
808 : :
809 : : fprintf(rc,
810 : : "# .fwknoprc\n"
811 : : "##############################################################################\n"
812 : : "#\n"
813 : : "# Firewall Knock Operator (fwknop) client rc file.\n"
814 : : "#\n"
815 : : "# This file contains user-specific fwknop client configuration default\n"
816 : : "# and named parameter sets for specific invocations of the fwknop client.\n"
817 : : "#\n"
818 : : "# Each section (or stanza) is identified and started by a line in this\n"
819 : : "# file that contains a single identifier surrounded by square brackets.\n"
820 : : "# It is this identifier (or name) that is used from the fwknop command line\n"
821 : : "# via the '-n <name>' argument to reference the corresponding stanza.\n"
822 : : "#\n"
823 : : "# The parameters within the stanza typically match corresponding client \n"
824 : : "# command-line parameters.\n"
825 : : "#\n"
826 : : "# The first one should always be `[default]' as it defines the global\n"
827 : : "# default settings for the user. These override the program defaults\n"
828 : : "# for these parameters. If a named stanza is used, its entries will\n"
829 : : "# override any of the default values. Command-line options will trump them\n"
830 : : "# all.\n"
831 : : "#\n"
832 : : "# Subsequent stanzas will have only the overriding and destination\n"
833 : : "# specific parameters.\n"
834 : : "#\n"
835 : : "# Lines starting with `#' and empty lines are ignored.\n"
836 : : "#\n"
837 : : "# See the fwknop.8 man page for a complete list of valid parameters\n"
838 : : "# and their values.\n"
839 : : "#\n"
840 : : "##############################################################################\n"
841 : : "#\n"
842 : : "# We start with the 'default' stanza. Uncomment and edit for your\n"
843 : : "# preferences. The client will use its built-in default for those items\n"
844 : : "# that are commented out.\n"
845 : : "#\n"
846 : : "[default]\n"
847 : : "\n"
848 : : "#DIGEST_TYPE sha256\n"
849 : : "#FW_TIMEOUT 30\n"
850 : : "#SPA_SERVER_PORT 62201\n"
851 : : "#SPA_SERVER_PROTO udp\n"
852 : : "#ALLOW_IP <ip addr>\n"
853 : : "#SPOOF_USER <username>\n"
854 : : "#SPOOF_SOURCE_IP <IPaddr>\n"
855 : : "#TIME_OFFSET 0\n"
856 : : "#USE_GPG N\n"
857 : : "#GPG_HOMEDIR /path/to/.gnupg\n"
858 : : "#GPG_EXE /path/to/gpg\n"
859 : : "#GPG_SIGNER <signer ID>\n"
860 : : "#GPG_RECIPIENT <recipient ID>\n"
861 : : "\n"
862 : : "# User-provided named stanzas:\n"
863 : : "\n"
864 : : "# Example for a destination server of 192.168.1.20 to open access to\n"
865 : : "# SSH for an IP that is resolved externally, and one with a NAT request\n"
866 : : "# for a specific source IP that maps port 8088 on the server\n"
867 : : "# to port 88 on 192.168.1.55 with timeout.\n"
868 : : "#\n"
869 : : "#[myssh]\n"
870 : : "#SPA_SERVER 192.168.1.20\n"
871 : : "#ACCESS tcp/22\n"
872 : : "#ALLOW_IP resolve\n"
873 : : "#\n"
874 : : "#[mynatreq]\n"
875 : : "#SPA_SERVER 192.168.1.20\n"
876 : : "#ACCESS tcp/8088\n"
877 : : "#ALLOW_IP 10.21.2.6\n"
878 : : "#NAT_ACCESS 192.168.1.55,88\n"
879 : : "#CLIENT_TIMEOUT 60\n"
880 : : "#\n"
881 : : "\n"
882 : : );
883 : :
884 : 1 : fclose(rc);
885 : :
886 : 1 : return(0);
887 : : }
888 : :
889 : : static int
890 : 1039 : parse_rc_param(fko_cli_options_t *options, const char *var_name, char * val)
891 : : {
892 : : int tmpint, is_err;
893 : 1039 : int parse_error = 0; /* 0 if the variable has been successfully processed, < 0 otherwise */
894 : : fko_var_t *var; /* Pointer on an fwknop variable structure */
895 : :
896 : 1039 : log_msg(LOG_VERBOSITY_DEBUG, "parse_rc_param() : Parsing variable %s...", var_name);
897 : :
898 : : /* Lookup the variable according to its name. */
899 : 1039 : var = lookup_var_by_name(var_name);
900 : :
901 : : /* The variable is not handled if its pointer is NULL */
902 [ + + ]: 1039 : if (var == NULL)
903 : : parse_error = -1;
904 : :
905 : : /* Digest Type */
906 [ + + ]: 1036 : else if (var->pos == FWKNOP_CLI_ARG_DIGEST_TYPE)
907 : : {
908 : 53 : tmpint = digest_strtoint(val);
909 [ + + ]: 53 : if(tmpint < 0)
910 : : parse_error = -1;
911 : : else
912 : 52 : options->digest_type = tmpint;
913 : : }
914 : : /* Server protocol */
915 [ + + ]: 983 : else if (var->pos == FWKNOP_CLI_ARG_SPA_SERVER_PROTO)
916 : : {
917 : 21 : tmpint = proto_strtoint(val);
918 [ + + ]: 21 : if(tmpint < 0)
919 : : parse_error = -1;
920 : : else
921 : 20 : options->spa_proto = tmpint;
922 : : }
923 : : /* Server port */
924 [ + + ]: 962 : else if (var->pos == FWKNOP_CLI_ARG_SPA_SERVER_PORT)
925 : : {
926 : 10 : tmpint = strtol_wrapper(val, 0, MAX_PORT, NO_EXIT_UPON_ERR, &is_err);
927 [ + - ]: 10 : if(is_err == FKO_SUCCESS)
928 : 10 : options->spa_dst_port = tmpint;
929 : : else
930 : : parse_error = -1;
931 : : }
932 : : /* Source port */
933 [ + + ]: 952 : else if (var->pos == FWKNOP_CLI_ARG_SPA_SOURCE_PORT)
934 : : {
935 : 3 : tmpint = strtol_wrapper(val, 0, MAX_PORT, NO_EXIT_UPON_ERR, &is_err);
936 [ + - ]: 3 : if(is_err == FKO_SUCCESS)
937 : 3 : options->spa_src_port = tmpint;
938 : : else
939 : : parse_error = -1;
940 : : }
941 : : /* Firewall rule timeout */
942 [ + + ]: 949 : else if (var->pos == FWKNOP_CLI_ARG_FW_TIMEOUT)
943 : : {
944 : 26 : tmpint = strtol_wrapper(val, 0, (2 << 15), NO_EXIT_UPON_ERR, &is_err);
945 [ + - ]: 26 : if(is_err == FKO_SUCCESS)
946 : 26 : options->fw_timeout = tmpint;
947 : : else
948 : : parse_error = -1;
949 : : }
950 : : /* Allow IP */
951 [ + + ]: 923 : else if (var->pos == FWKNOP_CLI_ARG_ALLOW_IP)
952 : : {
953 : : /* In case this was set previously
954 : : */
955 : 10 : options->resolve_ip_http_https = 0;
956 : :
957 : : /* use source, resolve, or an actual IP
958 : : */
959 [ + + ]: 10 : if(strcasecmp(val, "source") == 0)
960 : 3 : strlcpy(options->allow_ip_str, "0.0.0.0", sizeof(options->allow_ip_str));
961 [ + + ]: 7 : else if(strcasecmp(val, "resolve") == 0)
962 : 3 : options->resolve_ip_http_https = 1;
963 : : else /* Assume IP address and validate */
964 : : {
965 : 4 : strlcpy(options->allow_ip_str, val, sizeof(options->allow_ip_str));
966 [ - + ]: 4 : if(! is_valid_ipv4_addr(options->allow_ip_str))
967 : 0 : parse_error = -1;
968 : : }
969 : : }
970 : : /* Time Offset */
971 [ + + ]: 913 : else if (var->pos == FWKNOP_CLI_ARG_TIME_OFFSET)
972 : : {
973 [ + + ]: 9 : if(val[0] == '-')
974 : : {
975 : 6 : val++;
976 [ - + ]: 6 : if(! parse_time_offset(val, &options->time_offset_minus))
977 : 0 : parse_error = -1;
978 : : }
979 : : else
980 [ + + ]: 3 : if (! parse_time_offset(val, &options->time_offset_plus))
981 : 2 : parse_error = -1;
982 : :
983 [ + + ]: 9 : if(parse_error == -1)
984 : 2 : log_msg(LOG_VERBOSITY_WARNING,
985 : : "TIME_OFFSET argument '%s' invalid.", val);
986 : : }
987 : : /* symmetric encryption mode */
988 [ + + ]: 904 : else if (var->pos == FWKNOP_CLI_ARG_ENCRYPTION_MODE)
989 : : {
990 : 9 : tmpint = enc_mode_strtoint(val);
991 [ + + ]: 9 : if(tmpint < 0)
992 : : parse_error = -1;
993 : : else
994 : 8 : options->encryption_mode = tmpint;
995 : : }
996 : : /* Use GPG ? */
997 [ + + ]: 895 : else if (var->pos == FWKNOP_CLI_ARG_USE_GPG)
998 : : {
999 [ + + ]: 9 : if (is_yes_str(val))
1000 : 2 : options->use_gpg = 1;
1001 : : else;
1002 : : }
1003 : : /* Use GPG Agent ? */
1004 [ + + ]: 886 : else if (var->pos == FWKNOP_CLI_ARG_USE_GPG_AGENT)
1005 : : {
1006 [ + + ]: 9 : if (is_yes_str(val))
1007 : 1 : options->use_gpg_agent = 1;
1008 : : else;
1009 : : }
1010 : : /* No GPG signing passphrase ? */
1011 [ + + ]: 877 : else if (var->pos == FWKNOP_CLI_ARG_GPG_NO_SIGNING_PW)
1012 : : {
1013 [ + - ]: 1 : if (is_yes_str(val))
1014 : 1 : options->gpg_no_signing_pw = 1;
1015 : : else;
1016 : : }
1017 : : /* GPG Recipient */
1018 [ + + ]: 876 : else if (var->pos == FWKNOP_CLI_ARG_GPG_RECIPIENT)
1019 : : {
1020 : 2 : strlcpy(options->gpg_recipient_key, val, sizeof(options->gpg_recipient_key));
1021 : : }
1022 : : /* GPG Signer */
1023 [ + + ]: 874 : else if (var->pos == FWKNOP_CLI_ARG_GPG_SIGNER)
1024 : : {
1025 : 10 : strlcpy(options->gpg_signer_key, val, sizeof(options->gpg_signer_key));
1026 : : }
1027 : : /* GPG Homedir */
1028 [ + + ]: 864 : else if (var->pos == FWKNOP_CLI_ARG_GPG_HOMEDIR)
1029 : : {
1030 : 11 : strlcpy(options->gpg_home_dir, val, sizeof(options->gpg_home_dir));
1031 : : }
1032 : : /* GPG path */
1033 [ + + ]: 853 : else if (var->pos == FWKNOP_CLI_ARG_GPG_EXE_PATH)
1034 : : {
1035 : 1 : strlcpy(options->gpg_exe, val, sizeof(options->gpg_exe));
1036 : : }
1037 : : /* Spoof User */
1038 [ + + ]: 852 : else if (var->pos == FWKNOP_CLI_ARG_SPOOF_USER)
1039 : : {
1040 : 7 : strlcpy(options->spoof_user, val, sizeof(options->spoof_user));
1041 : : }
1042 : : /* Spoof Source IP */
1043 [ + + ]: 845 : else if (var->pos == FWKNOP_CLI_ARG_SPOOF_SOURCE_IP)
1044 : : {
1045 : 4 : strlcpy(options->spoof_ip_src_str, val, sizeof(options->spoof_ip_src_str));
1046 : : }
1047 : : /* ACCESS request */
1048 [ + + ]: 841 : else if (var->pos == FWKNOP_CLI_ARG_ACCESS)
1049 : : {
1050 : 7 : strlcpy(options->access_str, val, sizeof(options->access_str));
1051 : : }
1052 : : /* SPA Server (destination) */
1053 [ + + ]: 834 : else if (var->pos == FWKNOP_CLI_ARG_SPA_SERVER)
1054 : : {
1055 : 7 : strlcpy(options->spa_server_str, val, sizeof(options->spa_server_str));
1056 : : }
1057 : : /* Rand port ? */
1058 [ + + ]: 827 : else if (var->pos == FWKNOP_CLI_ARG_RAND_PORT)
1059 : : {
1060 [ + - ]: 1 : if (is_yes_str(val))
1061 : 1 : options->rand_port = 1;
1062 : : else;
1063 : : }
1064 : : /* Rijndael key */
1065 [ + + ]: 826 : else if (var->pos == FWKNOP_CLI_ARG_KEY_RIJNDAEL)
1066 : : {
1067 : 132 : strlcpy(options->key, val, sizeof(options->key));
1068 : 132 : options->have_key = 1;
1069 : : }
1070 : : /* Rijndael key (base-64 encoded) */
1071 [ + + ]: 694 : else if (var->pos == FWKNOP_CLI_ARG_KEY_RIJNDAEL_BASE64)
1072 : : {
1073 [ + + ]: 177 : if (! is_base64((unsigned char *) val, strlen(val)))
1074 : : {
1075 : 2 : log_msg(LOG_VERBOSITY_WARNING,
1076 : : "KEY_BASE64 argument '%s' doesn't look like base64-encoded data.",
1077 : : val);
1078 : 2 : parse_error = -1;
1079 : : }
1080 : 177 : strlcpy(options->key_base64, val, sizeof(options->key_base64));
1081 : 177 : options->have_base64_key = 1;
1082 : : }
1083 : : /* GnuPG signing passphrase */
1084 [ + + ]: 517 : else if (var->pos == FWKNOP_CLI_ARG_GPG_SIGNING_PW)
1085 : : {
1086 : 2 : strlcpy(options->key, val, sizeof(options->key));
1087 : 2 : options->have_key = 1;
1088 : : }
1089 : : /* GnuPG signing passphrase (base-64 encoded) */
1090 [ + + ]: 515 : else if (var->pos == FWKNOP_CLI_ARG_GPG_SIGNING_PW_BASE64)
1091 : : {
1092 [ + + ]: 2 : if (! is_base64((unsigned char *) val, strlen(val)))
1093 : : {
1094 : 1 : log_msg(LOG_VERBOSITY_WARNING,
1095 : : "GPG_SIGNING_KEY_BASE64 argument '%s' doesn't look like base64-encoded data.",
1096 : : val);
1097 : 1 : parse_error = -1;
1098 : : }
1099 : 2 : strlcpy(options->key_base64, val, sizeof(options->key_base64));
1100 : 2 : options->have_base64_key = 1;
1101 : : }
1102 : : /* HMAC digest type */
1103 [ + + ]: 513 : else if (var->pos == FWKNOP_CLI_ARG_HMAC_DIGEST_TYPE)
1104 : : {
1105 : 232 : tmpint = hmac_digest_strtoint(val);
1106 [ + + ]: 232 : if(tmpint < 0)
1107 : : {
1108 : 1 : log_msg(LOG_VERBOSITY_WARNING,
1109 : : "HMAC_DIGEST_TYPE argument '%s' must be one of {md5,sha1,sha256,sha384,sha512}",
1110 : : val);
1111 : 1 : parse_error = -1;
1112 : : }
1113 : : else
1114 : : {
1115 : 231 : options->hmac_type = tmpint;
1116 : : }
1117 : : }
1118 : : /* HMAC key (base64 encoded) */
1119 [ + + ]: 281 : else if (var->pos == FWKNOP_CLI_ARG_KEY_HMAC_BASE64)
1120 : : {
1121 [ + + ]: 189 : if (! is_base64((unsigned char *) val, strlen(val)))
1122 : : {
1123 : 1 : log_msg(LOG_VERBOSITY_WARNING,
1124 : : "HMAC_KEY_BASE64 argument '%s' doesn't look like base64-encoded data.",
1125 : : val);
1126 : 1 : parse_error = -1;
1127 : : }
1128 : 189 : strlcpy(options->hmac_key_base64, val, sizeof(options->hmac_key_base64));
1129 : 189 : options->have_hmac_base64_key = 1;
1130 : 189 : options->use_hmac = 1;
1131 : : }
1132 : :
1133 : : /* HMAC key */
1134 [ + + ]: 92 : else if (var->pos == FWKNOP_CLI_ARG_KEY_HMAC)
1135 : : {
1136 : 47 : strlcpy(options->hmac_key, val, sizeof(options->hmac_key));
1137 : 47 : options->have_hmac_key = 1;
1138 : 47 : options->use_hmac = 1;
1139 : : }
1140 : :
1141 : : /* --use-hmac */
1142 [ + + ]: 45 : else if (var->pos == FWKNOP_CLI_ARG_USE_HMAC)
1143 : : {
1144 [ + - ]: 8 : if (is_yes_str(val))
1145 : 8 : options->use_hmac = 1;
1146 : : }
1147 : : /* Key file */
1148 [ + + ]: 37 : else if (var->pos == FWKNOP_CLI_ARG_KEY_FILE)
1149 : : {
1150 : 1 : strlcpy(options->get_key_file, val, sizeof(options->get_key_file));
1151 : : }
1152 : : /* HMAC key file */
1153 [ + + ]: 36 : else if (var->pos == FWKNOP_CLI_ARG_HMAC_KEY_FILE)
1154 : : {
1155 : 1 : strlcpy(options->get_key_file, val,
1156 : : sizeof(options->get_hmac_key_file));
1157 : : }
1158 : : /* NAT Access Request */
1159 [ + + ]: 35 : else if (var->pos == FWKNOP_CLI_ARG_NAT_ACCESS)
1160 : : {
1161 : 1 : strlcpy(options->nat_access_str, val, sizeof(options->nat_access_str));
1162 : : }
1163 : : /* HTTP User Agent */
1164 [ + + ]: 34 : else if (var->pos == FWKNOP_CLI_ARG_HTTP_USER_AGENT)
1165 : : {
1166 : 3 : strlcpy(options->http_user_agent, val, sizeof(options->http_user_agent));
1167 : : }
1168 : : /* Resolve URL */
1169 [ + + ]: 31 : else if (var->pos == FWKNOP_CLI_ARG_RESOLVE_URL)
1170 : : {
1171 [ - + ]: 3 : if(options->resolve_url != NULL)
1172 : 0 : free(options->resolve_url);
1173 : 3 : tmpint = strlen(val)+1;
1174 : 3 : options->resolve_url = calloc(1, tmpint);
1175 [ - + ]: 3 : if(options->resolve_url == NULL)
1176 : : {
1177 : 0 : log_msg(LOG_VERBOSITY_ERROR,"Memory allocation error for resolve URL.");
1178 : 0 : exit(EXIT_FAILURE);
1179 : : }
1180 : 3 : strlcpy(options->resolve_url, val, tmpint);
1181 : : }
1182 : : /* wget command */
1183 [ + + ]: 28 : else if (var->pos == FWKNOP_CLI_ARG_WGET_CMD)
1184 : : {
1185 [ - + ]: 2 : if(options->wget_bin != NULL)
1186 : 0 : free(options->wget_bin);
1187 : 2 : tmpint = strlen(val)+1;
1188 : 2 : options->wget_bin = calloc(1, tmpint);
1189 [ - + ]: 2 : if(options->wget_bin == NULL)
1190 : : {
1191 : 0 : log_msg(LOG_VERBOSITY_ERROR,"Memory allocation error for wget command path.");
1192 : 0 : exit(EXIT_FAILURE);
1193 : : }
1194 : 2 : strlcpy(options->wget_bin, val, tmpint);
1195 : : }
1196 : : /* NAT Local ? */
1197 [ + + ]: 26 : else if (var->pos == FWKNOP_CLI_ARG_NAT_LOCAL)
1198 : : {
1199 [ + - ]: 2 : if (is_yes_str(val))
1200 : 2 : options->nat_local = 1;
1201 : : else;
1202 : : }
1203 : : /* NAT rand port ? */
1204 [ + + ]: 24 : else if (var->pos == FWKNOP_CLI_ARG_NAT_RAND_PORT)
1205 : : {
1206 [ + + ]: 2 : if (is_yes_str(val))
1207 : 1 : options->nat_rand_port = 1;
1208 : : else;
1209 : : }
1210 : : /* NAT port */
1211 [ + + ]: 22 : else if (var->pos == FWKNOP_CLI_ARG_NAT_PORT)
1212 : : {
1213 : 6 : tmpint = strtol_wrapper(val, 0, MAX_PORT, NO_EXIT_UPON_ERR, &is_err);
1214 [ + - ]: 6 : if(is_err == FKO_SUCCESS)
1215 : 6 : options->nat_port = tmpint;
1216 : : else
1217 : : parse_error = -1;
1218 : : }
1219 : : /* VERBOSE level */
1220 [ + + ]: 16 : else if (var->pos == FWKNOP_CLI_ARG_VERBOSE)
1221 : : {
1222 [ + + ]: 8 : if (is_yes_str(val))
1223 : 6 : options->verbose = 1;
1224 : : else
1225 : : {
1226 : 2 : tmpint = strtol_wrapper(val, 0, LOG_LAST_VERBOSITY - 1, NO_EXIT_UPON_ERR, &is_err);
1227 [ + + ]: 2 : if(is_err == FKO_SUCCESS)
1228 : 1 : options->verbose = tmpint;
1229 : : else
1230 : : parse_error = -1;
1231 : : }
1232 : :
1233 [ + + ]: 8 : if (parse_error == 0)
1234 : 7 : log_set_verbosity(LOG_DEFAULT_VERBOSITY + options->verbose);
1235 : : }
1236 : : /* RESOLVE_IP_HTTPS ? */
1237 [ + + ]: 8 : else if (var->pos == FWKNOP_CLI_ARG_RESOLVE_IP_HTTPS)
1238 : : {
1239 [ + - ]: 2 : if (is_yes_str(val))
1240 : 2 : options->resolve_ip_http_https = 1;
1241 : : else;
1242 : : }
1243 : : /* RESOLVE_IP_HTTP ? This actually results in HTTPS resolution by default
1244 : : * unless --resolve-http-only is also given
1245 : : */
1246 [ + + ]: 6 : else if (var->pos == FWKNOP_CLI_ARG_RESOLVE_IP_HTTP)
1247 : : {
1248 [ + + ]: 5 : if (is_yes_str(val))
1249 : 1 : options->resolve_ip_http_https = 1;
1250 : : else;
1251 : : }
1252 : : /* RESOLVE_HTTP_ONLY ? Force HTTP instead of HTTPS IP resolution.
1253 : : */
1254 [ + - ]: 1 : else if (var->pos == FWKNOP_CLI_ARG_RESOLVE_HTTP_ONLY)
1255 : : {
1256 [ + - ]: 1 : if (is_yes_str(val))
1257 : 1 : options->resolve_http_only = 1;
1258 : : else;
1259 : : }
1260 : : /* The variable is not a configuration variable */
1261 : : else
1262 : : {
1263 : : parse_error = -1;
1264 : : }
1265 : :
1266 : 1039 : return(parse_error);
1267 : : }
1268 : :
1269 : : /**
1270 : : * @brief Write a cli parameter to a file handle
1271 : : *
1272 : : * This function writes into a file handle a command line parameter
1273 : : *
1274 : : * @param fhandle File handle to write the new parameter to
1275 : : * @param var_pos Variable position
1276 : : * @param options FKO command line option structure
1277 : : */
1278 : : static void
1279 : 530 : add_single_var_to_rc(FILE* fhandle, short var_pos, fko_cli_options_t *options)
1280 : : {
1281 : 530 : char val[MAX_LINE_LEN] = {0};
1282 : : fko_var_t *var;
1283 : :
1284 : 530 : var = lookup_var_by_position(var_pos);
1285 : :
1286 [ + - ]: 530 : if (var == NULL)
1287 : 0 : return;
1288 : :
1289 [ + - ]: 530 : if (fhandle == NULL)
1290 : : return;
1291 : :
1292 : : /* Select the argument to add and store its string value into val */
1293 [ + + + + : 530 : switch (var->pos)
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + - + +
- ]
1294 : : {
1295 : : case FWKNOP_CLI_ARG_DIGEST_TYPE :
1296 : 12 : digest_inttostr(options->digest_type, val, sizeof(val));
1297 : 12 : break;
1298 : : case FWKNOP_CLI_ARG_SPA_SERVER_PROTO :
1299 : 6 : proto_inttostr(options->spa_proto, val, sizeof(val));
1300 : 6 : break;
1301 : : case FWKNOP_CLI_ARG_SPA_SERVER_PORT :
1302 : 1 : snprintf(val, sizeof(val)-1, "%d", options->spa_dst_port);
1303 : : break;
1304 : : case FWKNOP_CLI_ARG_SPA_SOURCE_PORT :
1305 : 1 : snprintf(val, sizeof(val)-1, "%d", options->spa_src_port);
1306 : : break;
1307 : : case FWKNOP_CLI_ARG_FW_TIMEOUT :
1308 : 13 : snprintf(val, sizeof(val)-1, "%d", options->fw_timeout);
1309 : : break;
1310 : : case FWKNOP_CLI_ARG_ALLOW_IP :
1311 : 88 : strlcpy(val, options->allow_ip_str, sizeof(val));
1312 : 88 : break;
1313 : : case FWKNOP_CLI_ARG_TIME_OFFSET :
1314 [ + + ]: 4 : if (options->time_offset_minus != 0)
1315 : 1 : snprintf(val, sizeof(val)-1, "-%d", options->time_offset_minus);
1316 [ + - ]: 3 : else if (options->time_offset_plus != 0)
1317 : 3 : snprintf(val, sizeof(val)-1, "%d", options->time_offset_plus);
1318 : : else;
1319 : : break;
1320 : : case FWKNOP_CLI_ARG_ENCRYPTION_MODE :
1321 : 2 : enc_mode_inttostr(options->encryption_mode, val, sizeof(val));
1322 : 2 : break;
1323 : : case FWKNOP_CLI_ARG_USE_GPG :
1324 : 7 : bool_to_yesno(options->use_gpg, val, sizeof(val));
1325 : 7 : break;
1326 : : case FWKNOP_CLI_ARG_USE_GPG_AGENT :
1327 : 1 : bool_to_yesno(options->use_gpg_agent, val, sizeof(val));
1328 : 1 : break;
1329 : : case FWKNOP_CLI_ARG_GPG_RECIPIENT :
1330 : 7 : strlcpy(val, options->gpg_recipient_key, sizeof(val));
1331 : 7 : break;
1332 : : case FWKNOP_CLI_ARG_GPG_SIGNER :
1333 : 7 : strlcpy(val, options->gpg_signer_key, sizeof(val));
1334 : 7 : break;
1335 : : case FWKNOP_CLI_ARG_GPG_HOMEDIR :
1336 : 7 : strlcpy(val, options->gpg_home_dir, sizeof(val));
1337 : 7 : break;
1338 : : case FWKNOP_CLI_ARG_GPG_EXE_PATH :
1339 : 1 : strlcpy(val, options->gpg_exe, sizeof(val));
1340 : 1 : break;
1341 : : case FWKNOP_CLI_ARG_GPG_NO_SIGNING_PW :
1342 : 7 : bool_to_yesno(options->gpg_no_signing_pw, val, sizeof(val));
1343 : 7 : break;
1344 : : case FWKNOP_CLI_ARG_SPOOF_USER :
1345 : 2 : strlcpy(val, options->spoof_user, sizeof(val));
1346 : 2 : break;
1347 : : case FWKNOP_CLI_ARG_SPOOF_SOURCE_IP :
1348 : 1 : strlcpy(val, options->spoof_ip_src_str, sizeof(val));
1349 : 1 : break;
1350 : : case FWKNOP_CLI_ARG_ACCESS :
1351 : 87 : strlcpy(val, options->access_str, sizeof(val));
1352 : 87 : break;
1353 : : case FWKNOP_CLI_ARG_SPA_SERVER :
1354 : 88 : strlcpy(val, options->spa_server_str, sizeof(val));
1355 : 88 : break;
1356 : : case FWKNOP_CLI_ARG_RAND_PORT :
1357 : 1 : bool_to_yesno(options->rand_port, val, sizeof(val));
1358 : 1 : break;
1359 : : case FWKNOP_CLI_ARG_KEY_FILE :
1360 : 9 : strlcpy(val, options->get_key_file, sizeof(val));
1361 : 9 : break;
1362 : : case FWKNOP_CLI_ARG_HMAC_KEY_FILE :
1363 : 2 : strlcpy(val, options->get_hmac_key_file, sizeof(val));
1364 : 2 : break;
1365 : : case FWKNOP_CLI_ARG_KEY_RIJNDAEL:
1366 : 1 : strlcpy(val, options->key, sizeof(val));
1367 : 1 : break;
1368 : : case FWKNOP_CLI_ARG_KEY_RIJNDAEL_BASE64:
1369 : 10 : strlcpy(val, options->key_base64, sizeof(val));
1370 : 10 : break;
1371 : : case FWKNOP_CLI_ARG_KEY_HMAC_BASE64:
1372 : 11 : strlcpy(val, options->hmac_key_base64, sizeof(val));
1373 : 11 : break;
1374 : : case FWKNOP_CLI_ARG_KEY_HMAC:
1375 : 1 : strlcpy(val, options->hmac_key, sizeof(val));
1376 : 1 : break;
1377 : : case FWKNOP_CLI_ARG_HMAC_DIGEST_TYPE :
1378 : 10 : hmac_digest_inttostr(options->hmac_type, val, sizeof(val));
1379 : 10 : break;
1380 : : case FWKNOP_CLI_ARG_USE_HMAC :
1381 : 18 : bool_to_yesno(options->use_hmac, val, sizeof(val));
1382 : 18 : break;
1383 : : case FWKNOP_CLI_ARG_NAT_ACCESS :
1384 : 11 : strlcpy(val, options->nat_access_str, sizeof(val));
1385 : 11 : break;
1386 : : case FWKNOP_CLI_ARG_HTTP_USER_AGENT :
1387 : 1 : strlcpy(val, options->http_user_agent, sizeof(val));
1388 : 1 : break;
1389 : : case FWKNOP_CLI_ARG_RESOLVE_URL :
1390 [ + - ]: 8 : if (options->resolve_url != NULL)
1391 : 8 : strlcpy(val, options->resolve_url, sizeof(val));
1392 : : else;
1393 : : break;
1394 : : case FWKNOP_CLI_ARG_NAT_LOCAL :
1395 : 2 : bool_to_yesno(options->nat_local, val, sizeof(val));
1396 : 2 : break;
1397 : : case FWKNOP_CLI_ARG_NAT_RAND_PORT :
1398 : 1 : bool_to_yesno(options->nat_rand_port, val, sizeof(val));
1399 : 1 : break;
1400 : : case FWKNOP_CLI_ARG_NAT_PORT :
1401 : 6 : snprintf(val, sizeof(val)-1, "%d", options->nat_port);
1402 : : break;
1403 : : case FWKNOP_CLI_ARG_VERBOSE:
1404 [ + + ]: 81 : if((options->verbose == 0) || (options->verbose == 1))
1405 : 1 : bool_to_yesno(options->verbose, val, sizeof(val));
1406 : : else
1407 : 80 : snprintf(val, sizeof(val)-1, "%d", options->verbose);
1408 : : break;
1409 : : case FWKNOP_CLI_ARG_RESOLVE_IP_HTTPS:
1410 : 12 : bool_to_yesno(options->resolve_ip_http_https, val, sizeof(val));
1411 : 12 : break;
1412 : : case FWKNOP_CLI_ARG_RESOLVE_IP_HTTP:
1413 : 0 : bool_to_yesno(options->resolve_ip_http_https, val, sizeof(val));
1414 : 0 : break;
1415 : : case FWKNOP_CLI_ARG_RESOLVE_HTTP_ONLY:
1416 : 1 : bool_to_yesno(options->resolve_http_only, val, sizeof(val));
1417 : 1 : break;
1418 : : case FWKNOP_CLI_ARG_WGET_CMD :
1419 [ + - ]: 2 : if (options->wget_bin != NULL)
1420 : 2 : strlcpy(val, options->wget_bin, sizeof(val));
1421 : : break;
1422 : : default:
1423 : 0 : log_msg(LOG_VERBOSITY_WARNING, "Warning from add_single_var_to_rc() : Bad variable position %u", var->pos);
1424 : 0 : return;
1425 : : }
1426 : :
1427 : 530 : log_msg(LOG_VERBOSITY_DEBUG, "add_single_var_to_rc() : Updating param (%u) %s to %s",
1428 : 530 : var->pos, var->name, val);
1429 : :
1430 : 530 : fprintf(fhandle, RC_PARAM_TEMPLATE, var->name, val);
1431 : : }
1432 : :
1433 : : /**
1434 : : * @brief Add configuration variables in a file
1435 : : *
1436 : : * The parameters are selected by a bitmask and extracted from the
1437 : : * fko_cli_options_t structure.
1438 : : *
1439 : : * @param rc File handle on the file to write to
1440 : : * @param options fko_cli_options_t structure containing the values of the parameters
1441 : : * @param bitmask Bitmask used to select the parameters to add
1442 : : */
1443 : : static void
1444 : 88 : add_multiple_vars_to_rc(FILE* rc, fko_cli_options_t *options, fko_var_bitmask_t *bitmask)
1445 : : {
1446 : 88 : short ndx = 0; /* Index of a configuration variable in fko_var_array table */
1447 : : short position; /* Position of the configuration variable */
1448 : :
1449 [ + + ]: 3696 : for (ndx=0 ; ndx<ARRAY_SIZE(fko_var_array) ; ndx++)
1450 : : {
1451 : 3608 : position = fko_var_array[ndx].pos;
1452 [ + + ]: 3608 : if (bitmask_has_var(position, bitmask))
1453 : 530 : add_single_var_to_rc(rc, position, options);
1454 : : }
1455 : 88 : }
1456 : :
1457 : : /**
1458 : : * @brief Process the fwknoprc file and lookup a section to extract its settings.
1459 : : *
1460 : : * This function aims at loading the settings for a specific section in
1461 : : * a fwknoprc file.
1462 : : *
1463 : : * @param section_name Name of the section to lookup.
1464 : : * @param options Fwknop option structure where settings have to
1465 : : * be stored.
1466 : : *
1467 : : * @return 0 if the section has been found and processed successfully
1468 : : * a negative value if one or more errors occured
1469 : : */
1470 : : static int
1471 : 2522 : process_rc_section(char *section_name, fko_cli_options_t *options)
1472 : : {
1473 : : FILE *rc;
1474 : 2522 : int line_num = 0, do_exit = 0;
1475 : 2522 : char line[MAX_LINE_LEN] = {0};
1476 : 2522 : char rcfile[MAX_PATH_LEN] = {0};
1477 : 2522 : char curr_stanza[MAX_LINE_LEN] = {0};
1478 : : rc_file_param_t param;
1479 : 2522 : int rc_section_found = 0;
1480 : :
1481 : 2522 : set_rc_file(rcfile, options);
1482 : :
1483 : : /* Open the rc file for reading, if it does not exist, then create
1484 : : * an initial .fwknoprc file with defaults and go on.
1485 : : */
1486 [ + + ]: 2522 : if ((rc = fopen(rcfile, "r")) == NULL)
1487 : : {
1488 [ + + ]: 43 : if(errno == ENOENT)
1489 : : {
1490 : 1 : if(create_fwknoprc(rcfile) != 0)
1491 : : return -1;
1492 : : }
1493 : : else
1494 : 42 : log_msg(LOG_VERBOSITY_WARNING, "Unable to open rc file: %s: %s",
1495 : : rcfile, strerror(errno));
1496 : :
1497 : : return -1;
1498 : : }
1499 : :
1500 : 2479 : log_msg(LOG_VERBOSITY_DEBUG, "process_rc_section() : Parsing section '%s' ...",
1501 : : section_name);
1502 : :
1503 [ + + ]: 160363 : while ((fgets(line, MAX_LINE_LEN, rc)) != NULL)
1504 : : {
1505 : 155406 : line_num++;
1506 : 155406 : line[MAX_LINE_LEN-1] = '\0';
1507 : :
1508 : : /* Get past comments and empty lines (note: we only look at the
1509 : : * first character.
1510 : : */
1511 [ + + ][ + - ]: 155406 : if(IS_EMPTY_LINE(line[0]))
[ + - ][ - + ]
1512 : 151848 : continue;
1513 : :
1514 : : /* Check which section we are working on */
1515 [ + + ]: 3558 : if (is_rc_section(line, strlen(line), curr_stanza, sizeof(curr_stanza)))
1516 : : {
1517 : 2498 : rc_section_found = (strcasecmp(curr_stanza, section_name) == 0) ? 1 : 0;
1518 : :
1519 [ + + ]: 2498 : if (strcasecmp(curr_stanza, options->use_rc_stanza) == 0)
1520 : 104 : options->got_named_stanza = 1;
1521 : :
1522 : 2498 : continue;
1523 : : }
1524 : :
1525 : : /* We are not in the good section */
1526 [ + + ]: 1060 : else if (rc_section_found == 0)
1527 : 20 : continue;
1528 : :
1529 : : /* We have not found a valid parameter */
1530 [ + + ]: 1040 : else if (is_rc_param(line, ¶m) == 0)
1531 : : {
1532 : : do_exit = 1; /* We don't allow improperly formatted lines */
1533 : : break;
1534 : : }
1535 : :
1536 : : /* We have a valid parameter */
1537 : : else
1538 : : {
1539 [ + + ]: 1039 : if(parse_rc_param(options, param.name, param.val) < 0)
1540 : : {
1541 : 14 : log_msg(LOG_VERBOSITY_WARNING,
1542 : : "Parameter error in %s, line %i: var=%s, val=%s",
1543 : : rcfile, line_num, param.name, param.val);
1544 : 155405 : do_exit = 1;
1545 : : }
1546 : : }
1547 : : }
1548 : :
1549 : 2479 : fclose(rc);
1550 : :
1551 [ + + ]: 2479 : if (do_exit)
1552 : 15 : exit(EXIT_FAILURE);
1553 : :
1554 : : return 0;
1555 : : }
1556 : :
1557 : : /**
1558 : : * @brief Update the user rc file with the new parameters for a selected stanza.
1559 : : *
1560 : : * This function writes the new configuration in a temporary file and renames it
1561 : : * as the new rc file afterwards. All of the previous parameters for the
1562 : : * selected stanza are removed and replaced by the arguments from the command
1563 : : * line.
1564 : : *
1565 : : * @param options structure containing all of the fko settings
1566 : : * @param args_bitmask command line argument bitmask
1567 : : */
1568 : : static void
1569 : 88 : update_rc(fko_cli_options_t *options, fko_var_bitmask_t *bitmask)
1570 : : {
1571 : : FILE *rc;
1572 : : FILE *rc_update;
1573 : 88 : int rcfile_fd = -1;
1574 : 88 : int stanza_found = 0;
1575 : 88 : int stanza_updated = 0;
1576 : 88 : char line[MAX_LINE_LEN] = {0};
1577 : 88 : char rcfile[MAX_PATH_LEN] = {0};
1578 : 88 : char rcfile_update[MAX_PATH_LEN] = {0};
1579 : 88 : char curr_stanza[MAX_LINE_LEN] = {0};
1580 : : rc_file_param_t param; /* Structure to contain a conf. variable name with its value */
1581 : : fko_var_t *var;
1582 : :
1583 : 88 : set_rc_file(rcfile, options);
1584 : :
1585 : 88 : strlcpy(rcfile_update, rcfile, sizeof(rcfile_update));
1586 : 88 : strlcat(rcfile_update, ".updated", sizeof(rcfile_update));
1587 : :
1588 : : /* Create a new temporary rc file */
1589 : 88 : rcfile_fd = open(rcfile_update, FWKNOPRC_OFLAGS, FWKNOPRC_MODE);
1590 [ - + ]: 88 : if (rcfile_fd == -1)
1591 : : {
1592 : 0 : log_msg(LOG_VERBOSITY_WARNING,
1593 : : "update_rc() : Unable to create temporary rc file: %s: %s",
1594 : 0 : rcfile_update, strerror(errno));
1595 : 0 : return;
1596 : : }
1597 : 88 : close(rcfile_fd);
1598 : :
1599 : : /* Open the current rcfile and a temporary one respectively in read and
1600 : : * write mode */
1601 [ - + ]: 88 : if ((rc = fopen(rcfile, "r")) == NULL)
1602 : : {
1603 : 0 : log_msg(LOG_VERBOSITY_WARNING,
1604 : : "update_rc() : Unable to open rc file: %s: %s",
1605 : 0 : rcfile, strerror(errno));
1606 : 0 : return;
1607 : : }
1608 : :
1609 [ + - ]: 88 : if ((rc_update = fopen(rcfile_update, "w")) == NULL)
1610 : : {
1611 : 0 : log_msg(LOG_VERBOSITY_WARNING,
1612 : : "update_rc() : Unable to open rc file: %s: %s",
1613 : 0 : rcfile_update, strerror(errno));
1614 : 0 : fclose(rc);
1615 : 0 : return;
1616 : : }
1617 : :
1618 : : /* Go through the file line by line */
1619 : : stanza_found = 0;
1620 [ + + ]: 427 : while ((fgets(line, MAX_LINE_LEN, rc)) != NULL)
1621 : : {
1622 : 339 : line[MAX_LINE_LEN-1] = '\0';
1623 : :
1624 : : /* Get past comments and empty lines (note: we only look at the
1625 : : * first character.
1626 : : */
1627 [ + - ][ + - ]: 339 : if(IS_EMPTY_LINE(line[0]))
[ + - ][ - + ]
1628 : 0 : continue;
1629 : :
1630 : : /* If we find a section... */
1631 [ + + ]: 339 : if(is_rc_section(line, strlen(line), curr_stanza, sizeof(curr_stanza)) == 1)
1632 : : {
1633 : : /* and we have already parsed the section we wanted to save, we
1634 : : * can update our parameters */
1635 [ + + ]: 91 : if (stanza_found)
1636 : : {
1637 : 1 : log_msg(LOG_VERBOSITY_DEBUG, "update_rc() : Updating %s stanza", options->use_rc_stanza);
1638 : 1 : add_multiple_vars_to_rc(rc_update, options, bitmask);
1639 : : fprintf(rc_update, "\n");
1640 : 1 : stanza_found = 0;
1641 : 1 : stanza_updated = 1;
1642 : : }
1643 : :
1644 : : /* and this is the one we are looking for, we set the stanza
1645 : : * as found */
1646 [ + + ]: 90 : else if (strncasecmp(curr_stanza, options->use_rc_stanza, MAX_LINE_LEN) == 0)
1647 : : stanza_found = 1;
1648 : :
1649 : : /* otherwise we disable the stanza */
1650 : : else
1651 : 10 : stanza_found = 0;
1652 : : }
1653 : :
1654 : : /* If we are processing a parameter for our stanza */
1655 [ + + ]: 248 : else if (stanza_found)
1656 : : {
1657 : : /* and the user has specified a force option, there is no need to
1658 : : * check for critical variables */
1659 [ + + ]: 209 : if (options->force_save_rc_stanza)
1660 : 199 : continue;
1661 : :
1662 : : /* ask the user what to do with the critical var found in the
1663 : : * rcfile */
1664 [ + - ]: 10 : else if (is_rc_param(line, ¶m))
1665 : : {
1666 [ + - ]: 10 : if ( ((var=lookup_var_by_name(param.name)) != NULL)
1667 [ + + ]: 10 : && var_is_critical(var->pos) )
1668 : : {
1669 [ + + ]: 5 : if (ask_overwrite_var(var->name, curr_stanza))
1670 : 4 : continue;
1671 : : else
1672 : 1 : remove_var_from_bitmask(var->pos, bitmask);
1673 : : }
1674 : : else
1675 : 5 : continue;
1676 : : }
1677 : : else
1678 : : {
1679 : : /* is_rc_param() returns false only when there is an
1680 : : * improperly formatted line - bail
1681 : : */
1682 : 0 : fclose(rc);
1683 : 0 : fclose(rc_update);
1684 : 0 : return;
1685 : : }
1686 : : }
1687 : :
1688 : : /* We're not processing any important variables from our stanza and no new
1689 : : * stanza */
1690 : : else;
1691 : :
1692 : : /* Add the line to the new rcfile */
1693 : : fprintf(rc_update, "%s", line);
1694 : : }
1695 : :
1696 : : /* The configuration has not been updated yet */
1697 [ + + ]: 88 : if (stanza_updated == 0)
1698 : : {
1699 : : /* but the stanza has been found, We update it now. */
1700 [ + + ]: 87 : if (stanza_found == 1)
1701 : 79 : log_msg(LOG_VERBOSITY_DEBUG, "update_rc() : Updating %s stanza",
1702 : 79 : options->use_rc_stanza);
1703 : :
1704 : : /* otherwise we append the new settings to the file */
1705 : : else
1706 : : {
1707 : : fprintf(rc_update, "\n");
1708 : 8 : log_msg(LOG_VERBOSITY_DEBUG, "update_rc() : Inserting new %s stanza",
1709 : 8 : options->use_rc_stanza);
1710 : 8 : fprintf(rc_update, RC_SECTION_TEMPLATE, options->use_rc_stanza);
1711 : : }
1712 : :
1713 : 87 : add_multiple_vars_to_rc(rc_update, options, bitmask);
1714 : : }
1715 : :
1716 : : /* otherwise we have already done everything. Nothing to do. */
1717 : : else;
1718 : :
1719 : : /* Close file handles */
1720 : 88 : fclose(rc);
1721 : 88 : fclose(rc_update);
1722 : :
1723 : : /* Renamed the temporary file as the new rc file */
1724 [ - + ]: 88 : if (remove(rcfile) != 0)
1725 : : {
1726 : 0 : log_msg(LOG_VERBOSITY_WARNING,
1727 : : "update_rc() : Unable to remove %s to %s : %s",
1728 : 0 : rcfile_update, rcfile, strerror(errno));
1729 : : }
1730 : :
1731 [ - + ]: 88 : if (rename(rcfile_update, rcfile) != 0)
1732 : : {
1733 : 88 : log_msg(LOG_VERBOSITY_WARNING,
1734 : : "update_rc() : Unable to rename %s to %s",
1735 : : rcfile_update, rcfile);
1736 : : }
1737 : : }
1738 : :
1739 : : /* Sanity and bounds checks for the various options.
1740 : : */
1741 : : static void
1742 : 2485 : validate_options(fko_cli_options_t *options)
1743 : : {
1744 : :
1745 [ + + ]: 2485 : if ( (options->use_rc_stanza[0] != 0x0)
1746 : : && (options->got_named_stanza == 0)
1747 [ + + ]: 89 : && (options->save_rc_stanza == 0) )
1748 : : {
1749 : 1 : log_msg(LOG_VERBOSITY_ERROR,
1750 : : "Named configuration stanza: [%s] was not found.",
1751 : 1 : options->use_rc_stanza);
1752 : :
1753 : 1 : exit(EXIT_FAILURE);
1754 : : }
1755 : :
1756 [ + + ][ + + ]: 2484 : if ( (options->save_rc_stanza == 1) && (options->use_rc_stanza[0] == 0) )
1757 : : {
1758 : : /* Set the stanza name to the -D arg value
1759 : : */
1760 [ + + ]: 9 : if (options->spa_server_str[0] == 0x0)
1761 : : {
1762 : 2 : log_msg(LOG_VERBOSITY_ERROR,
1763 : : "Must use --destination unless --test mode is used");
1764 : 2 : exit(EXIT_FAILURE);
1765 : : }
1766 : :
1767 : 7 : strlcpy(options->use_rc_stanza, options->spa_server_str, sizeof(options->use_rc_stanza));
1768 : : }
1769 : :
1770 : : /* Gotta have a Destination unless we are just testing or getting the
1771 : : * the version, and must use one of [-s|-R|-a].
1772 : : */
1773 [ + + ]: 2482 : if(!options->test
1774 [ + + ]: 2344 : && !options->key_gen
1775 [ + + ]: 2241 : && !options->version
1776 [ + + ]: 2240 : && !options->show_last_command
1777 [ + + ]: 2236 : && !options->run_last_command)
1778 : : {
1779 [ + + ]: 2232 : if (options->spa_server_str[0] == 0x0)
1780 : : {
1781 : 2 : log_msg(LOG_VERBOSITY_ERROR,
1782 : : "Must use --destination unless --test mode is used");
1783 : 2 : exit(EXIT_FAILURE);
1784 : : }
1785 : :
1786 [ + + ]: 2230 : if (options->resolve_url != NULL)
1787 : 14 : options->resolve_ip_http_https = 1;
1788 : :
1789 [ + + ]: 2230 : if (!options->resolve_ip_http_https)
1790 : : {
1791 [ + + ]: 2212 : if(options->allow_ip_str[0] == 0x0)
1792 : : {
1793 : 1 : log_msg(LOG_VERBOSITY_ERROR,
1794 : : "Must use one of [-s|-R|-a] to specify IP for SPA access.");
1795 : 1 : exit(EXIT_FAILURE);
1796 : : }
1797 [ + + ]: 2211 : else if(options->verbose
1798 [ + + ]: 2206 : && strncmp(options->allow_ip_str, "0.0.0.0", strlen("0.0.0.0")) == 0)
1799 : : {
1800 : 2 : log_msg(LOG_VERBOSITY_WARNING,
1801 : : "[-] WARNING: Should use -a or -R to harden SPA against potential MITM attacks");
1802 : : }
1803 : :
1804 [ + + ]: 2211 : if(! is_valid_ipv4_addr(options->allow_ip_str))
1805 : : {
1806 : 1 : log_msg(LOG_VERBOSITY_ERROR,
1807 : : "Invalid allow IP specified for SPA access");
1808 : 1 : exit(EXIT_FAILURE);
1809 : : }
1810 : : }
1811 : : }
1812 : :
1813 [ + + ]: 2478 : if (options->spoof_ip_src_str[0] != 0x00)
1814 : : {
1815 [ + + ]: 10 : if(! is_valid_ipv4_addr(options->spoof_ip_src_str))
1816 : : {
1817 : 1 : log_msg(LOG_VERBOSITY_ERROR, "Invalid spoof IP");
1818 : 1 : exit(EXIT_FAILURE);
1819 : : }
1820 [ + + ]: 9 : if(options->spa_proto != FKO_PROTO_TCP_RAW
1821 : 9 : && options->spa_proto != FKO_PROTO_UDP_RAW
1822 [ + + ]: 3 : && options->spa_proto != FKO_PROTO_ICMP)
1823 : : {
1824 : 1 : log_msg(LOG_VERBOSITY_ERROR,
1825 : : "Must set -P <udpraw|tcpraw|icmp> with a spoofed source IP");
1826 : 1 : exit(EXIT_FAILURE);
1827 : : }
1828 : : }
1829 : :
1830 [ + + ][ + + ]: 2476 : if(options->resolve_ip_http_https || options->spa_proto == FKO_PROTO_HTTP)
1831 [ + + ]: 35 : if (options->http_user_agent[0] == '\0')
1832 : 30 : snprintf(options->http_user_agent, HTTP_MAX_USER_AGENT_LEN,
1833 : : "%s%s", "Fwknop/", MY_VERSION);
1834 : :
1835 [ + + ][ + + ]: 2476 : if(options->http_proxy[0] != 0x0 && options->spa_proto != FKO_PROTO_HTTP)
1836 : : {
1837 : 1 : log_msg(LOG_VERBOSITY_ERROR,
1838 : : "Cannot set --http-proxy with a non-HTTP protocol.");
1839 : 1 : exit(EXIT_FAILURE);
1840 : : }
1841 : :
1842 : : /* If we are using gpg, we must at least have the recipient set.
1843 : : */
1844 [ + + ]: 2475 : if(options->use_gpg)
1845 : : {
1846 [ + + ]: 80 : if(strlen(options->gpg_recipient_key) == 0)
1847 : : {
1848 : 1 : log_msg(LOG_VERBOSITY_ERROR,
1849 : : "Must specify --gpg-recipient-key when GPG is used.");
1850 : 1 : exit(EXIT_FAILURE);
1851 : : }
1852 : : }
1853 : :
1854 [ + + ]: 2474 : if(options->encryption_mode == FKO_ENC_MODE_ASYMMETRIC
1855 [ + - ]: 1 : && ! options->use_gpg)
1856 : : {
1857 : 1 : log_msg(LOG_VERBOSITY_ERROR,
1858 : : "Must specify GPG recipient/signing keys when Asymmetric encryption mode is used.");
1859 : 1 : exit(EXIT_FAILURE);
1860 : : }
1861 : :
1862 [ + + ]: 2473 : if(options->encryption_mode == FKO_ENC_MODE_CBC_LEGACY_IV
1863 [ + + ]: 4 : && options->use_hmac)
1864 : : {
1865 : 1 : log_msg(LOG_VERBOSITY_ERROR,
1866 : : "Legacy encryption mode is incompatible with HMAC usage.");
1867 : 1 : exit(EXIT_FAILURE);
1868 : : }
1869 : :
1870 : : /* Validate HMAC digest type
1871 : : */
1872 [ + + ][ + + ]: 2472 : if(options->use_hmac && options->hmac_type == FKO_HMAC_UNKNOWN)
1873 : 18 : options->hmac_type = FKO_DEFAULT_HMAC_MODE;
1874 : :
1875 [ + + ][ + + ]: 2472 : if(options->key_gen && options->hmac_type == FKO_HMAC_UNKNOWN)
1876 : 103 : options->hmac_type = FKO_DEFAULT_HMAC_MODE;
1877 : :
1878 : 2472 : return;
1879 : : }
1880 : :
1881 : : /* Establish a few defaults such as UDP/62201 for sending the SPA
1882 : : * packet (can be changed with --server-proto/--server-port)
1883 : : */
1884 : : static void
1885 : 2521 : set_defaults(fko_cli_options_t *options)
1886 : : {
1887 : 2521 : options->spa_proto = FKO_DEFAULT_PROTO;
1888 : 2521 : options->spa_dst_port = FKO_DEFAULT_PORT;
1889 : 2521 : options->fw_timeout = -1;
1890 : :
1891 : 2521 : options->key_len = FKO_DEFAULT_KEY_LEN;
1892 : 2521 : options->hmac_key_len = FKO_DEFAULT_HMAC_KEY_LEN;
1893 : 2521 : options->hmac_type = FKO_HMAC_UNKNOWN; /* updated when HMAC key is used */
1894 : :
1895 : 2521 : options->spa_icmp_type = ICMP_ECHOREPLY; /* only used in '-P icmp' mode */
1896 : 2521 : options->spa_icmp_code = 0; /* only used in '-P icmp' mode */
1897 : :
1898 : 2521 : options->input_fd = FD_INVALID;
1899 : :
1900 : 2521 : return;
1901 : : }
1902 : :
1903 : : /* Initialize program configuration via config file and/or command-line
1904 : : * switches.
1905 : : */
1906 : : void
1907 : 2521 : config_init(fko_cli_options_t *options, int argc, char **argv)
1908 : : {
1909 : 2521 : int cmd_arg, index, is_err, rlen=0;
1910 : : fko_var_bitmask_t var_bitmask;
1911 : 2521 : char rcfile[MAX_PATH_LEN] = {0};
1912 : :
1913 : : /* Zero out options, opts_track and bitmask.
1914 : : */
1915 : : memset(options, 0x00, sizeof(fko_cli_options_t));
1916 : : memset(&var_bitmask, 0x00, sizeof(fko_var_bitmask_t));
1917 : :
1918 : : /* Make sure a few reasonable defaults are set
1919 : : */
1920 : 2521 : set_defaults(options);
1921 : :
1922 : : /* First pass over cmd_line args to see if a named-stanza in the
1923 : : * rc file is used.
1924 : : */
1925 [ + + ]: 23288 : while ((cmd_arg = getopt_long(argc, argv,
1926 : : GETOPTS_OPTION_STRING, cmd_opts, &index)) != -1) {
1927 [ + + + + : 18247 : switch(cmd_arg) {
+ + + +
+ ]
1928 : : case 'h':
1929 : 1 : usage();
1930 : 1 : exit(EXIT_SUCCESS);
1931 : : case NO_SAVE_ARGS:
1932 : 2325 : options->no_save_args = 1;
1933 : 2325 : break;
1934 : : case 'n':
1935 : 100 : strlcpy(options->use_rc_stanza, optarg, sizeof(options->use_rc_stanza));
1936 : 100 : break;
1937 : : case SAVE_RC_STANZA:
1938 : 104 : options->save_rc_stanza = 1;
1939 : 104 : break;
1940 : : case STANZA_LIST:
1941 : 4 : options->stanza_list = 1;
1942 : 4 : break;
1943 : : case 'E':
1944 : 10 : strlcpy(options->args_save_file, optarg, sizeof(options->args_save_file));
1945 : 10 : break;
1946 : : case RC_FILE_PATH:
1947 : 339 : strlcpy(options->rc_file, optarg, sizeof(options->rc_file));
1948 : 339 : break;
1949 : : case 'v':
1950 : 4781 : options->verbose++;
1951 : 4781 : add_var_to_bitmask(FWKNOP_CLI_ARG_VERBOSE, &var_bitmask);
1952 : 10184 : break;
1953 : : }
1954 : : }
1955 : :
1956 : : /* Update the verbosity level for the log module */
1957 : 2520 : log_set_verbosity(LOG_DEFAULT_VERBOSITY + options->verbose);
1958 : :
1959 : : /* Dump the configured stanzas from an rcfile */
1960 [ + + ]: 2520 : if (options->stanza_list == 1)
1961 : : {
1962 : 4 : set_rc_file(rcfile, options);
1963 : 2 : exit(dump_configured_stanzas_from_rcfile(rcfile));
1964 : : }
1965 : :
1966 : : /* First process the .fwknoprc file.
1967 : : */
1968 : 2516 : process_rc_section(RC_SECTION_DEFAULT, options);
1969 : :
1970 : : /* Load the user specified stanza from .fwknoprc file */
1971 [ + + ][ + + ]: 2503 : if ( (options->got_named_stanza) && (options->save_rc_stanza == 0) )
1972 : 6 : process_rc_section(options->use_rc_stanza, options);
1973 : :
1974 : : /* Reset the options index so we can run through them again.
1975 : : */
1976 : 2501 : optind = 0;
1977 : :
1978 [ + + ]: 23039 : while ((cmd_arg = getopt_long(argc, argv,
1979 : : GETOPTS_OPTION_STRING, cmd_opts, &index)) != -1) {
1980 : :
1981 [ + + + + : 18053 : switch(cmd_arg) {
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + ]
1982 : : case 'a':
1983 : 2365 : strlcpy(options->allow_ip_str, optarg, sizeof(options->allow_ip_str));
1984 : 2365 : add_var_to_bitmask(FWKNOP_CLI_ARG_ALLOW_IP, &var_bitmask);
1985 : 15605 : break;
1986 : : case 'A':
1987 : 2679 : strlcpy(options->access_str, optarg, sizeof(options->access_str));
1988 : 2679 : add_var_to_bitmask(FWKNOP_CLI_ARG_ACCESS, &var_bitmask);
1989 : 2679 : break;
1990 : : case 'b':
1991 : 1 : options->save_packet_file_append = 1;
1992 : 1 : break;
1993 : : case 'B':
1994 : 6 : strlcpy(options->save_packet_file, optarg, sizeof(options->save_packet_file));
1995 : 6 : break;
1996 : : case 'C':
1997 : 2 : strlcpy(options->server_command, optarg, sizeof(options->server_command));
1998 : 2 : break;
1999 : : case 'D':
2000 : 2381 : strlcpy(options->spa_server_str, optarg, sizeof(options->spa_server_str));
2001 : 2381 : add_var_to_bitmask(FWKNOP_CLI_ARG_SPA_SERVER, &var_bitmask);
2002 : 2381 : break;
2003 : : case 'E':
2004 : 10 : strlcpy(options->args_save_file, optarg, sizeof(options->args_save_file));
2005 : 10 : break;
2006 : : case 'f':
2007 : 16 : options->fw_timeout = strtol_wrapper(optarg, 0,
2008 : : (2 << 16), NO_EXIT_UPON_ERR, &is_err);
2009 [ + + ]: 16 : if(is_err != FKO_SUCCESS)
2010 : : {
2011 : 1 : log_msg(LOG_VERBOSITY_ERROR, "--fw-timeout must be within [%d-%d]",
2012 : : 0, (2 << 16));
2013 : 1 : exit(EXIT_FAILURE);
2014 : : }
2015 : 15 : add_var_to_bitmask(FWKNOP_CLI_ARG_FW_TIMEOUT, &var_bitmask);
2016 : 15 : break;
2017 : : case FAULT_INJECTION_TAG:
2018 : : #if HAVE_LIBFIU
2019 : 30 : strlcpy(options->fault_injection_tag, optarg, sizeof(options->fault_injection_tag));
2020 : : #else
2021 : : log_msg(LOG_VERBOSITY_ERROR,
2022 : : "fwknop not compiled with fault injection support.", optarg);
2023 : : exit(EXIT_FAILURE);
2024 : : #endif
2025 : 30 : break;
2026 : : case 'g':
2027 : : case GPG_ENCRYPTION:
2028 : 4 : options->use_gpg = 1;
2029 : 4 : add_var_to_bitmask(FWKNOP_CLI_ARG_USE_GPG, &var_bitmask);
2030 : 4 : break;
2031 : : case 'G':
2032 : 2061 : strlcpy(options->get_key_file, optarg, sizeof(options->get_key_file));
2033 : 2061 : add_var_to_bitmask(FWKNOP_CLI_ARG_KEY_FILE, &var_bitmask);
2034 : 2061 : break;
2035 : : case GET_HMAC_KEY:
2036 : 3 : strlcpy(options->get_hmac_key_file, optarg,
2037 : : sizeof(options->get_hmac_key_file));
2038 : 3 : options->use_hmac = 1;
2039 : 3 : add_var_to_bitmask(FWKNOP_CLI_ARG_HMAC_KEY_FILE, &var_bitmask);
2040 : 3 : break;
2041 : : case 'H':
2042 : 4 : options->spa_proto = FKO_PROTO_HTTP;
2043 : 4 : strlcpy(options->http_proxy, optarg, sizeof(options->http_proxy));
2044 : 4 : break;
2045 : : case 'k':
2046 : 116 : options->key_gen = 1;
2047 : 116 : break;
2048 : : case 'K':
2049 : 2 : options->key_gen = 1;
2050 : 2 : strlcpy(options->key_gen_file, optarg, sizeof(options->key_gen_file));
2051 : 2 : break;
2052 : : case KEY_RIJNDAEL:
2053 : 10 : strlcpy(options->key, optarg, sizeof(options->key));
2054 : 10 : options->have_key = 1;
2055 : 10 : add_var_to_bitmask(FWKNOP_CLI_ARG_KEY_RIJNDAEL, &var_bitmask);
2056 : 10 : break;
2057 : : case KEY_RIJNDAEL_BASE64:
2058 [ + + ]: 7 : if (! is_base64((unsigned char *) optarg, strlen(optarg)))
2059 : : {
2060 : 1 : log_msg(LOG_VERBOSITY_ERROR,
2061 : : "Base64 encoded Rijndael argument '%s' doesn't look like base64-encoded data.",
2062 : : optarg);
2063 : 1 : exit(EXIT_FAILURE);
2064 : : }
2065 : 6 : strlcpy(options->key_base64, optarg, sizeof(options->key_base64));
2066 : 6 : options->have_base64_key = 1;
2067 : 6 : add_var_to_bitmask(FWKNOP_CLI_ARG_KEY_RIJNDAEL_BASE64, &var_bitmask);
2068 : 6 : break;
2069 : : case KEY_HMAC_BASE64:
2070 [ + + ]: 4 : if (! is_base64((unsigned char *) optarg, strlen(optarg)))
2071 : : {
2072 : 1 : log_msg(LOG_VERBOSITY_ERROR,
2073 : : "Base64 encoded HMAC argument '%s' doesn't look like base64-encoded data.",
2074 : : optarg);
2075 : 1 : exit(EXIT_FAILURE);
2076 : : }
2077 : 3 : strlcpy(options->hmac_key_base64, optarg, sizeof(options->hmac_key_base64));
2078 : 3 : options->have_hmac_base64_key = 1;
2079 : 3 : options->use_hmac = 1;
2080 : 3 : add_var_to_bitmask(FWKNOP_CLI_ARG_KEY_HMAC_BASE64, &var_bitmask);
2081 : 3 : add_var_to_bitmask(FWKNOP_CLI_ARG_USE_HMAC, &var_bitmask);
2082 : 3 : break;
2083 : : case KEY_HMAC:
2084 : 4 : strlcpy(options->hmac_key, optarg, sizeof(options->hmac_key));
2085 : 4 : options->have_hmac_key = 1;
2086 : 4 : options->use_hmac = 1;
2087 : 4 : add_var_to_bitmask(FWKNOP_CLI_ARG_KEY_HMAC, &var_bitmask);
2088 : 4 : add_var_to_bitmask(FWKNOP_CLI_ARG_USE_HMAC, &var_bitmask);
2089 : 4 : break;
2090 : : case KEY_LEN:
2091 : 2 : options->key_len = strtol_wrapper(optarg, 1,
2092 : : MAX_KEY_LEN, NO_EXIT_UPON_ERR, &is_err);
2093 [ + + ]: 2 : if(is_err != FKO_SUCCESS)
2094 : : {
2095 : 1 : log_msg(LOG_VERBOSITY_ERROR,
2096 : : "Invalid key length '%s', must be in [%d-%d]",
2097 : : optarg, 1, MAX_KEY_LEN);
2098 : 1 : exit(EXIT_FAILURE);
2099 : : }
2100 : : break;
2101 : : case HMAC_DIGEST_TYPE:
2102 [ + + ]: 28 : if((options->hmac_type = hmac_digest_strtoint(optarg)) < 0)
2103 : : {
2104 : 3 : log_msg(LOG_VERBOSITY_ERROR,
2105 : : "* Invalid hmac digest type: %s, use {md5,sha1,sha256,sha384,sha512}",
2106 : : optarg);
2107 : 3 : exit(EXIT_FAILURE);
2108 : : }
2109 : 25 : add_var_to_bitmask(FWKNOP_CLI_ARG_HMAC_DIGEST_TYPE, &var_bitmask);
2110 : 25 : add_var_to_bitmask(FWKNOP_CLI_ARG_USE_HMAC, &var_bitmask);
2111 : 25 : options->use_hmac = 1;
2112 : 25 : break;
2113 : : case HMAC_KEY_LEN:
2114 : 2 : options->hmac_key_len = strtol_wrapper(optarg, 1,
2115 : : MAX_KEY_LEN, NO_EXIT_UPON_ERR, &is_err);
2116 [ + + ]: 2 : if(is_err != FKO_SUCCESS)
2117 : : {
2118 : 1 : log_msg(LOG_VERBOSITY_ERROR,
2119 : : "Invalid hmac key length '%s', must be in [%d-%d]",
2120 : : optarg, 1, MAX_KEY_LEN);
2121 : 1 : exit(EXIT_FAILURE);
2122 : : }
2123 : 1 : add_var_to_bitmask(FWKNOP_CLI_ARG_USE_HMAC, &var_bitmask);
2124 : 1 : options->use_hmac = 1;
2125 : 1 : break;
2126 : : case SPA_ICMP_TYPE:
2127 : 2 : options->spa_icmp_type = strtol_wrapper(optarg, 0,
2128 : : MAX_ICMP_TYPE, NO_EXIT_UPON_ERR, &is_err);
2129 [ + + ]: 2 : if(is_err != FKO_SUCCESS)
2130 : : {
2131 : 1 : log_msg(LOG_VERBOSITY_ERROR,
2132 : : "Invalid icmp type '%s', must be in [%d-%d]",
2133 : : optarg, 0, MAX_ICMP_TYPE);
2134 : 1 : exit(EXIT_FAILURE);
2135 : : }
2136 : : break;
2137 : : case SPA_ICMP_CODE:
2138 : 2 : options->spa_icmp_code = strtol_wrapper(optarg, 0,
2139 : : MAX_ICMP_CODE, NO_EXIT_UPON_ERR, &is_err);
2140 [ + + ]: 2 : if(is_err != FKO_SUCCESS)
2141 : : {
2142 : 1 : log_msg(LOG_VERBOSITY_ERROR,
2143 : : "Invalid icmp code '%s', must be in [%d-%d]",
2144 : : optarg, 0, MAX_ICMP_CODE);
2145 : 1 : exit(EXIT_FAILURE);
2146 : : }
2147 : : break;
2148 : : case 'l':
2149 : 4 : options->run_last_command = 1;
2150 : 4 : break;
2151 : : case 'm':
2152 : : case FKO_DIGEST_NAME:
2153 [ + + ]: 18 : if((options->digest_type = digest_strtoint(optarg)) < 0)
2154 : : {
2155 : 1 : log_msg(LOG_VERBOSITY_ERROR,
2156 : : "* Invalid digest type: %s, use {md5,sha1,sha256,sha384,sha512}",
2157 : : optarg);
2158 : 1 : exit(EXIT_FAILURE);
2159 : : }
2160 : 17 : add_var_to_bitmask(FWKNOP_CLI_ARG_DIGEST_TYPE, &var_bitmask);
2161 : 17 : break;
2162 : : case 'M':
2163 : : case ENCRYPTION_MODE:
2164 [ + + ]: 18 : if((options->encryption_mode = enc_mode_strtoint(optarg)) < 0)
2165 : : {
2166 : 2 : log_msg(LOG_VERBOSITY_ERROR,
2167 : : "* Invalid encryption mode: %s, use {CBC,CTR,legacy,Asymmetric}",
2168 : : optarg);
2169 : 2 : exit(EXIT_FAILURE);
2170 : : }
2171 : 16 : add_var_to_bitmask(FWKNOP_CLI_ARG_ENCRYPTION_MODE, &var_bitmask);
2172 : 16 : break;
2173 : : case NO_SAVE_ARGS:
2174 : 2306 : options->no_save_args = 1;
2175 : 2306 : break;
2176 : : case 'n':
2177 : : /* We already handled this earlier, so we do nothing here
2178 : : */
2179 : : break;
2180 : : case 'N':
2181 : 30 : strlcpy(options->nat_access_str, optarg, sizeof(options->nat_access_str));
2182 : 30 : add_var_to_bitmask(FWKNOP_CLI_ARG_NAT_ACCESS, &var_bitmask);
2183 : 30 : break;
2184 : : case 'p':
2185 : 2 : options->spa_dst_port = strtol_wrapper(optarg, 0,
2186 : : MAX_PORT, EXIT_UPON_ERR, &is_err);
2187 : 2 : add_var_to_bitmask(FWKNOP_CLI_ARG_SPA_SERVER_PORT, &var_bitmask);
2188 : 2 : break;
2189 : : case 'P':
2190 [ + + ]: 29 : if((options->spa_proto = proto_strtoint(optarg)) < 0)
2191 : : {
2192 : 1 : log_msg(LOG_VERBOSITY_ERROR, "Unrecognized protocol: %s", optarg);
2193 : 1 : exit(EXIT_FAILURE);
2194 : : }
2195 : 28 : add_var_to_bitmask(FWKNOP_CLI_ARG_SPA_SERVER_PROTO, &var_bitmask);
2196 : 28 : break;
2197 : : case 'Q':
2198 : 9 : strlcpy(options->spoof_ip_src_str, optarg, sizeof(options->spoof_ip_src_str));
2199 : 9 : add_var_to_bitmask(FWKNOP_CLI_ARG_SPOOF_SOURCE_IP, &var_bitmask);
2200 : 9 : break;
2201 : : case RC_FILE_PATH:
2202 : 321 : strlcpy(options->rc_file, optarg, sizeof(options->rc_file));
2203 : 321 : break;
2204 : : case 'r':
2205 : 5 : options->rand_port = 1;
2206 : 5 : add_var_to_bitmask(FWKNOP_CLI_ARG_RAND_PORT, &var_bitmask);
2207 : 5 : break;
2208 : : case 'R':
2209 : 27 : options->resolve_ip_http_https = 1;
2210 : 27 : add_var_to_bitmask(FWKNOP_CLI_ARG_RESOLVE_IP_HTTPS, &var_bitmask);
2211 : 27 : break;
2212 : : case RESOLVE_HTTP_ONLY:
2213 : 5 : options->resolve_http_only = 1;
2214 : 5 : options->resolve_ip_http_https = 1;
2215 : 5 : add_var_to_bitmask(FWKNOP_CLI_ARG_RESOLVE_HTTP_ONLY, &var_bitmask);
2216 : 5 : add_var_to_bitmask(FWKNOP_CLI_ARG_RESOLVE_IP_HTTPS, &var_bitmask);
2217 : 5 : break;
2218 : : case RESOLVE_URL:
2219 [ - + ]: 19 : if(options->resolve_url != NULL)
2220 : 0 : free(options->resolve_url);
2221 : 19 : rlen = strlen(optarg) + 1;
2222 : 19 : options->resolve_url = calloc(1, rlen);
2223 [ - + ]: 19 : if(options->resolve_url == NULL)
2224 : : {
2225 : 0 : log_msg(LOG_VERBOSITY_ERROR, "Memory allocation error for resolve URL.");
2226 : 0 : exit(EXIT_FAILURE);
2227 : : }
2228 : 19 : strlcpy(options->resolve_url, optarg, rlen);
2229 : 19 : add_var_to_bitmask(FWKNOP_CLI_ARG_RESOLVE_URL, &var_bitmask);
2230 : 19 : break;
2231 : : case 'w':
2232 [ - + ]: 2 : if(options->wget_bin != NULL)
2233 : 0 : free(options->wget_bin);
2234 : 2 : rlen = strlen(optarg) + 1;
2235 : 2 : options->wget_bin = calloc(1, rlen);
2236 [ - + ]: 2 : if(options->wget_bin == NULL)
2237 : : {
2238 : 0 : log_msg(LOG_VERBOSITY_ERROR, "Memory allocation error for resolve URL.");
2239 : 0 : exit(EXIT_FAILURE);
2240 : : }
2241 : 2 : strlcpy(options->wget_bin, optarg, rlen);
2242 : 2 : add_var_to_bitmask(FWKNOP_CLI_ARG_WGET_CMD, &var_bitmask);
2243 : 2 : break;
2244 : : case SHOW_LAST_ARGS:
2245 : 4 : options->show_last_command = 1;
2246 : 4 : break;
2247 : : case 's':
2248 : 5 : strlcpy(options->allow_ip_str, "0.0.0.0", sizeof(options->allow_ip_str));
2249 : 5 : break;
2250 : : case 'S':
2251 : 1 : options->spa_src_port = strtol_wrapper(optarg, 0,
2252 : : MAX_PORT, EXIT_UPON_ERR, &is_err);
2253 : 1 : add_var_to_bitmask(FWKNOP_CLI_ARG_SPA_SOURCE_PORT, &var_bitmask);
2254 : 1 : break;
2255 : : case SAVE_RC_STANZA:
2256 : : /* We already handled this earlier, so we do nothing here
2257 : : */
2258 : : break;
2259 : : case 'T':
2260 : 147 : options->test = 1;
2261 : 147 : break;
2262 : : case 'u':
2263 : 2 : strlcpy(options->http_user_agent, optarg, sizeof(options->http_user_agent));
2264 : 2 : add_var_to_bitmask(FWKNOP_CLI_ARG_HTTP_USER_AGENT, &var_bitmask);
2265 : 2 : break;
2266 : : case 'U':
2267 : 3 : strlcpy(options->spoof_user, optarg, sizeof(options->spoof_user));
2268 : 3 : add_var_to_bitmask(FWKNOP_CLI_ARG_SPOOF_USER, &var_bitmask);
2269 : 3 : break;
2270 : : case 'v':
2271 : : /* Handled earlier.
2272 : : */
2273 : : break;
2274 : : case 'V':
2275 : 1 : options->version = 1;
2276 : 1 : break;
2277 : : case GPG_RECIP_KEY:
2278 : 77 : options->use_gpg = 1;
2279 : 77 : strlcpy(options->gpg_recipient_key, optarg, sizeof(options->gpg_recipient_key));
2280 : 77 : add_var_to_bitmask(FWKNOP_CLI_ARG_USE_GPG, &var_bitmask);
2281 : 77 : add_var_to_bitmask(FWKNOP_CLI_ARG_GPG_RECIPIENT, &var_bitmask);
2282 : 77 : break;
2283 : : case GPG_SIGNER_KEY:
2284 : 77 : options->use_gpg = 1;
2285 : 77 : strlcpy(options->gpg_signer_key, optarg, sizeof(options->gpg_signer_key));
2286 : 77 : add_var_to_bitmask(FWKNOP_CLI_ARG_USE_GPG, &var_bitmask);
2287 : 77 : add_var_to_bitmask(FWKNOP_CLI_ARG_GPG_SIGNER, &var_bitmask);
2288 : 77 : break;
2289 : : case GPG_HOME_DIR:
2290 : 79 : options->use_gpg = 1;
2291 : 79 : strlcpy(options->gpg_home_dir, optarg, sizeof(options->gpg_home_dir));
2292 : 79 : add_var_to_bitmask(FWKNOP_CLI_ARG_USE_GPG, &var_bitmask);
2293 : 79 : add_var_to_bitmask(FWKNOP_CLI_ARG_GPG_HOMEDIR, &var_bitmask);
2294 : 79 : break;
2295 : : case GPG_EXE_PATH:
2296 : 4 : options->use_gpg = 1;
2297 : 4 : strlcpy(options->gpg_exe, optarg, sizeof(options->gpg_exe));
2298 : 4 : add_var_to_bitmask(FWKNOP_CLI_ARG_USE_GPG, &var_bitmask);
2299 : 4 : add_var_to_bitmask(FWKNOP_CLI_ARG_GPG_EXE_PATH, &var_bitmask);
2300 : 4 : break;
2301 : : case GPG_AGENT:
2302 : 1 : options->use_gpg = 1;
2303 : 1 : options->use_gpg_agent = 1;
2304 : 1 : add_var_to_bitmask(FWKNOP_CLI_ARG_USE_GPG, &var_bitmask);
2305 : 1 : add_var_to_bitmask(FWKNOP_CLI_ARG_USE_GPG_AGENT, &var_bitmask);
2306 : 1 : break;
2307 : : case GPG_ALLOW_NO_SIGNING_PW:
2308 : 28 : options->use_gpg = 1;
2309 : 28 : options->gpg_no_signing_pw = 1;
2310 : 28 : add_var_to_bitmask(FWKNOP_CLI_ARG_USE_GPG, &var_bitmask);
2311 : 28 : add_var_to_bitmask(FWKNOP_CLI_ARG_GPG_NO_SIGNING_PW, &var_bitmask);
2312 : 28 : break;
2313 : : case NAT_LOCAL:
2314 : 11 : options->nat_local = 1;
2315 : 11 : add_var_to_bitmask(FWKNOP_CLI_ARG_NAT_LOCAL, &var_bitmask);
2316 : 11 : break;
2317 : : case NAT_RAND_PORT:
2318 : 7 : options->nat_rand_port = 1;
2319 : 7 : add_var_to_bitmask(FWKNOP_CLI_ARG_NAT_RAND_PORT, &var_bitmask);
2320 : 7 : break;
2321 : : case NAT_PORT:
2322 : 9 : options->nat_port = strtol_wrapper(optarg, 0,
2323 : : MAX_PORT, EXIT_UPON_ERR, &is_err);
2324 : 9 : add_var_to_bitmask(FWKNOP_CLI_ARG_NAT_PORT, &var_bitmask);
2325 : 9 : break;
2326 : : case TIME_OFFSET_PLUS:
2327 [ - + ]: 4 : if (! parse_time_offset(optarg, &options->time_offset_plus))
2328 : : {
2329 : 0 : log_msg(LOG_VERBOSITY_WARNING,
2330 : : "Invalid time offset: '%s'", optarg);
2331 : 0 : exit(EXIT_FAILURE);
2332 : : }
2333 : 4 : add_var_to_bitmask(FWKNOP_CLI_ARG_TIME_OFFSET, &var_bitmask);
2334 : 4 : break;
2335 : : case TIME_OFFSET_MINUS:
2336 [ - + ]: 2 : if (! parse_time_offset(optarg, &options->time_offset_minus))
2337 : : {
2338 : 0 : log_msg(LOG_VERBOSITY_WARNING,
2339 : : "Invalid time offset: '%s'", optarg);
2340 : 0 : exit(EXIT_FAILURE);
2341 : : }
2342 : 2 : add_var_to_bitmask(FWKNOP_CLI_ARG_TIME_OFFSET, &var_bitmask);
2343 : 2 : break;
2344 : : case USE_HMAC:
2345 : 16 : add_var_to_bitmask(FWKNOP_CLI_ARG_USE_HMAC, &var_bitmask);
2346 : 16 : options->use_hmac = 1;
2347 : 16 : break;
2348 : : case FORCE_SAVE_RC_STANZA:
2349 : 92 : options->force_save_rc_stanza = 1;
2350 : 92 : break;
2351 : : case FD_SET_STDIN:
2352 : 1 : options->input_fd = STDIN_FILENO;
2353 : 1 : break;
2354 : : case FD_SET_ALT:
2355 : : #ifdef WIN32
2356 : : log_msg(LOG_VERBOSITY_ERROR, "Read password from FD not supported on Windows");
2357 : : exit(EXIT_FAILURE);
2358 : : #endif
2359 : 12 : options->input_fd = strtol_wrapper(optarg, 0,
2360 : : -1, EXIT_UPON_ERR, &is_err);
2361 : 11 : break;
2362 : : default:
2363 : 1 : usage();
2364 : 1 : exit(EXIT_FAILURE);
2365 : : }
2366 : : }
2367 : :
2368 : : /* Now that we have all of our options set, we can validate them */
2369 : 2485 : validate_options(options);
2370 : :
2371 : : /* Generate Rijndael + HMAC keys from /dev/random and base64 encode
2372 : : */
2373 : 2472 : generate_keys(options);
2374 : :
2375 : : /* We can upgrade our settings with the parameters set on the command
2376 : : * line by the user */
2377 [ + + ]: 2472 : if (options->save_rc_stanza == 1)
2378 : : {
2379 : : /* If we are asked to generate keys, we add them to the bitmask so
2380 : : * that they can be added to the stanza when updated */
2381 [ + + ]: 88 : if (options->key_gen == 1)
2382 : : {
2383 : 11 : add_var_to_bitmask(FWKNOP_CLI_ARG_KEY_RIJNDAEL_BASE64, &var_bitmask);
2384 : 11 : add_var_to_bitmask(FWKNOP_CLI_ARG_KEY_HMAC_BASE64, &var_bitmask);
2385 : : }
2386 : : else;
2387 : :
2388 : 88 : update_rc(options, &var_bitmask);
2389 : : }
2390 : : else;
2391 : :
2392 : 2472 : keys_status(options);
2393 : :
2394 : 2358 : return;
2395 : : }
2396 : :
2397 : : /* Print usage message...
2398 : : */
2399 : : void
2400 : 2 : usage(void)
2401 : : {
2402 : 2 : log_msg(LOG_VERBOSITY_NORMAL,
2403 : : "\n%s client version %s\n%s - http://%s/fwknop/\n",
2404 : : MY_NAME, MY_VERSION, MY_DESC, HTTP_RESOLVE_HOST);
2405 : 2 : log_msg(LOG_VERBOSITY_NORMAL,
2406 : : "Usage: fwknop -A <port list> [-s|-R|-a] -D <spa_server> [options]\n\n"
2407 : : " -n, --named-config Specify a named configuration stanza in the\n"
2408 : : " '$HOME/.fwknoprc' file to provide some of all\n"
2409 : : " of the configuration parameters.\n"
2410 : : " If more arguments are set through the command\n"
2411 : : " line, the configuration is updated accordingly\n"
2412 : : " -A, --access Provide a list of ports/protocols to open\n"
2413 : : " on the server (e.g. 'tcp/22').\n"
2414 : : " -a, --allow-ip Specify IP address to allow within the SPA\n"
2415 : : " packet (e.g. '123.2.3.4'). If \n"
2416 : : " -D, --destination Specify the hostname or IP address of the\n"
2417 : : " fwknop server.\n"
2418 : : " --use-hmac Add an HMAC to the outbound SPA packet for\n"
2419 : : " authenticated encryption.\n"
2420 : : " -h, --help Print this usage message and exit.\n"
2421 : : " -B, --save-packet Save the generated packet data to the\n"
2422 : : " specified file.\n"
2423 : : " -b, --save-packet-append Append the generated packet data to the\n"
2424 : : " file specified with the -B option.\n"
2425 : : " -C, --server-cmd Specify a command that the fwknop server will\n"
2426 : : " execute on behalf of the fwknop client..\n"
2427 : : " -N, --nat-access Gain NAT access to an internal service.\n"
2428 : : " -p, --server-port Set the destination port for outgoing SPA\n"
2429 : : " packet.\n"
2430 : : " -P, --server-proto Set the protocol (udp, tcp, http, tcpraw,\n"
2431 : : " icmp) for the outgoing SPA packet.\n"
2432 : : " Note: The 'tcpraw' and 'icmp' modes use raw\n"
2433 : : " sockets and thus require root access to use.\n"
2434 : : " -s, --source-ip Tell the fwknopd server to accept whatever\n"
2435 : : " source IP the SPA packet has as the IP that\n"
2436 : : " needs access (not recommended, and the\n"
2437 : : " fwknopd server can ignore such requests).\n"
2438 : : " -S, --source-port Set the source port for outgoing SPA packet.\n"
2439 : : " -Q, --spoof-source Set the source IP for outgoing SPA packet.\n"
2440 : : " -R, --resolve-ip-https Resolve the external network IP by\n"
2441 : : " connecting to a URL such as the default of:\n"
2442 : : " https://" HTTP_RESOLVE_HOST HTTP_RESOLVE_URL "\n"
2443 : : " with wget in --secure-protocol mode (SSL).\n"
2444 : : " The URL can be overridden with the\n"
2445 : : " --resolve-url option.\n"
2446 : : " --resolve-http-only Force external IP resolution via HTTP instead\n"
2447 : : " HTTPS (via the URL mentioned above). This is\n"
2448 : : " not recommended since it would open fwknop\n"
2449 : : " to potential MITM attacks if the IP resolution\n"
2450 : : " HTTP connection is altered en-route by a third\n"
2451 : : " party.\n"
2452 : : " --resolve-url Override the default URL used for resolving\n"
2453 : : " the source IP address.\n"
2454 : : " -u, --user-agent Set the HTTP User-Agent for resolving the\n"
2455 : : " external IP via -R, or for sending SPA\n"
2456 : : " packets over HTTP.\n"
2457 : : " -H, --http-proxy Specify an HTTP proxy host through which the\n"
2458 : : " SPA packet will be sent. The port can also be\n"
2459 : : " specified here by following the host/ip with\n"
2460 : : " \":<port>\".\n"
2461 : : " -U, --spoof-user Set the username within outgoing SPA packet.\n"
2462 : : " -l, --last-cmd Run the fwknop client with the same command\n"
2463 : : " line args as the last time it was executed\n"
2464 : : " (args are read from the ~/.fwknop.run file).\n"
2465 : : " -G, --get-key Load an encryption key/password from a file.\n"
2466 : : " --stdin Read the encryption key/password from stdin\n"
2467 : : " --fd Specify the file descriptor to read the\n"
2468 : : " encryption key/password from.\n"
2469 : : " -k, --key-gen Generate SPA Rijndael + HMAC keys.\n"
2470 : : " -K, --key-gen-file Write generated Rijndael + HMAC keys to a\n"
2471 : : " file\n"
2472 : : " --key-rijndael Specify the Rijndael key. Since the password is\n"
2473 : : " visible to utilities (like 'ps' under Unix) this\n"
2474 : : " form should only be used where security is not\n"
2475 : : " important.\n"
2476 : : " --key-base64-rijndael Specify the base64 encoded Rijndael key. Since\n"
2477 : : " the password is visible to utilities (like 'ps'\n"
2478 : : " under Unix) this form should only be used where\n"
2479 : : " security is not important.\n"
2480 : : " --key-base64-hmac Specify the base64 encoded HMAC key. Since the\n"
2481 : : " password is visible to utilities (like 'ps'\n"
2482 : : " under Unix) this form should only be used where\n"
2483 : : " security is not important.\n"
2484 : : " -r, --rand-port Send the SPA packet over a randomly assigned\n"
2485 : : " port (requires a broader pcap filter on the\n"
2486 : : " server side than the default of udp 62201).\n"
2487 : : " -T, --test Build the SPA packet but do not send it over\n"
2488 : : " the network.\n"
2489 : : " -v, --verbose Set verbose mode (may specify multiple times).\n"
2490 : : " -V, --version Print version number.\n"
2491 : : " -m, --digest-type Specify the message digest algorithm to use.\n"
2492 : : " (md5, sha1, sha256, sha384, or sha512). The\n"
2493 : : " default is sha256.\n"
2494 : : " -M, --encryption-mode Specify the encryption mode when AES is used\n"
2495 : : " for encrypting SPA packets.The default is CBC\n"
2496 : : " mode, but others can be chosen such as CFB or\n"
2497 : : " OFB as long as this is also specified in the\n"
2498 : : " access.conf file on the server side. Note that\n"
2499 : : " the string ``legacy'' can be specified in order\n"
2500 : : " to generate SPA packets with the old initialization\n"
2501 : : " vector strategy used by versions of *fwknop*\n"
2502 : : " before 2.5.\n"
2503 : : " -f, --fw-timeout Specify SPA server firewall timeout from the\n"
2504 : : " client side.\n"
2505 : : " --hmac-digest-type Set the HMAC digest algorithm (default is\n"
2506 : : " sha256). Options are md5, sha1, sha256,\n"
2507 : : " sha384, or sha512.\n"
2508 : : " --icmp-type Set the ICMP type (used with '-P icmp')\n"
2509 : : " --icmp-code Set the ICMP code (used with '-P icmp')\n"
2510 : : " --gpg-encryption Use GPG encryption (default is Rijndael).\n"
2511 : : " --gpg-recipient-key Specify the recipient GPG key name or ID.\n"
2512 : : " --gpg-signer-key Specify the signer's GPG key name or ID.\n"
2513 : : " --gpg-home-dir Specify the GPG home directory.\n"
2514 : : " --gpg-agent Use GPG agent if available.\n"
2515 : : " --gpg-exe Set path to GPG binary.\n"
2516 : : " --no-save-args Do not save fwknop command line args to the\n"
2517 : : " $HOME/fwknop.run file\n"
2518 : : " --rc-file Specify path to the fwknop rc file (default\n"
2519 : : " is $HOME/.fwknoprc)\n"
2520 : : " --save-rc-stanza Save command line arguments to the\n"
2521 : : " $HOME/.fwknoprc stanza specified with the\n"
2522 : : " -n option.\n"
2523 : : " --force-stanza Used with --save-rc-stanza to overwrite all of\n"
2524 : : " the variables for the specified stanza\n"
2525 : : " --stanza-list Dump a list of the stanzas found in\n"
2526 : : " $HOME/.fwknoprc\n"
2527 : : " --nat-local Access a local service via a forwarded port\n"
2528 : : " on the fwknopd server system.\n"
2529 : : " --nat-port Specify the port to forward to access a\n"
2530 : : " service via NAT.\n"
2531 : : " --nat-rand-port Have the fwknop client assign a random port\n"
2532 : : " for NAT access.\n"
2533 : : " --show-last Show the last fwknop command line arguments.\n"
2534 : : " --time-offset-plus Add time to outgoing SPA packet timestamp.\n"
2535 : : " --time-offset-minus Subtract time from outgoing SPA packet\n"
2536 : : " timestamp.\n"
2537 : : );
2538 : :
2539 : 2 : return;
2540 : : }
2541 : :
|