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