LCOV - code coverage report
Current view: top level - client - config_init.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 891 942 94.6 %
Date: 2016-06-07 Functions: 26 26 100.0 %
Branches: 536 600 89.3 %

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

Generated by: LCOV version 1.10