LCOV - code coverage report
Current view: top level - client - config_init.c (source / functions) Hit Total Coverage
Test: id:002084,src:002034,op:havoc,rep:2.lcov_info_final Lines: 310 917 33.8 %
Date: 2015-05-30 Functions: 14 26 53.8 %
Branches: 222 582 38.1 %

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

Generated by: LCOV version 1.10