LCOV - code coverage report
Current view: top level - client - config_init.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 858 914 93.9 %
Date: 2014-11-16 Functions: 26 26 100.0 %
Branches: 513 578 88.8 %

           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, &param) == 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, &param))
    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                 :            : 

Generated by: LCOV version 1.10