LCOV - code coverage report
Current view: top level - server - access.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 916 980 93.5 %
Date: 2016-06-07 Functions: 37 37 100.0 %
Branches: 653 754 86.6 %

           Branch data     Line data    Source code
       1                 :            : /**
       2                 :            :  * \file server/access.c
       3                 :            :  *
       4                 :            :  * \brief Access.conf file processing for fwknop server.
       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                 :            : #include <sys/stat.h>
      31                 :            : 
      32                 :            : #if HAVE_SYS_SOCKET_H
      33                 :            :   #include <sys/socket.h>
      34                 :            : #endif
      35                 :            : 
      36                 :            : #include "fwknopd_common.h"
      37                 :            : #include <arpa/inet.h>
      38                 :            : #include "pwd.h"
      39                 :            : #include "access.h"
      40                 :            : #include "utils.h"
      41                 :            : #include "log_msg.h"
      42                 :            : #include "cmd_cycle.h"
      43                 :            : #include <dirent.h>
      44                 :            : 
      45                 :            : #define FATAL_ERR -1
      46                 :            : 
      47                 :            : #ifndef SUCCESS
      48                 :            :   #define SUCCESS    1
      49                 :            : #endif
      50                 :            : 
      51                 :            : #ifdef HAVE_C_UNIT_TESTS /* LCOV_EXCL_START */
      52                 :            :   #include "cunit_common.h"
      53                 :            :   DECLARE_TEST_SUITE(access, "Access test suite");
      54                 :            : #endif /* LCOV_EXCL_STOP */
      55                 :            : 
      56                 :            : /**
      57                 :            :  * \brief include keys file
      58                 :            :  *
      59                 :            :  * This function loads only the crypto keys from a given file.
      60                 :            :  * It inserts these keys into the active access stanza.
      61                 :            :  *
      62                 :            :  * \param curr_acc pointer to the current access stanza
      63                 :            :  * \param access_filename Pointer to the file containing the keys
      64                 :            :  * \param opts fko_srv_options_t Server options struct
      65                 :            :  *
      66                 :            :  */
      67                 :            : int
      68                 :            : include_keys_file(acc_stanza_t *, const char *, fko_srv_options_t *);
      69                 :            : 
      70                 :            : static int do_acc_stanza_init = 1;
      71                 :            : 
      72                 :       7068 : void enable_acc_stanzas_init(void)
      73                 :            : {
      74                 :       7068 :     do_acc_stanza_init = 1;
      75                 :       7068 :     return;
      76                 :            : }
      77                 :            : 
      78                 :            : /* Add an access string entry
      79                 :            : */
      80                 :            : static void
      81                 :       4195 : add_acc_string(char **var, const char *val, FILE *file_ptr,
      82                 :            :         fko_srv_options_t *opts)
      83                 :            : {
      84         [ -  + ]:       4195 :     if(var == NULL)
      85                 :            :     {
      86                 :          0 :         log_msg(LOG_ERR, "[*] add_acc_string() called with NULL variable");
      87         [ #  # ]:          0 :         if(file_ptr != NULL)
      88                 :          0 :             fclose(file_ptr);
      89                 :          0 :         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
      90                 :            :     }
      91                 :            : 
      92         [ +  + ]:       4195 :     if(*var != NULL)
      93                 :          5 :         free(*var);
      94                 :            : 
      95         [ -  + ]:       4195 :     if((*var = strdup(val)) == NULL)
      96                 :            :     {
      97                 :          0 :         log_msg(LOG_ERR,
      98                 :            :             "[*] Fatal memory allocation error adding access list entry: %s", *var
      99                 :            :         );
     100         [ #  # ]:          0 :         if(file_ptr != NULL)
     101                 :          0 :             fclose(file_ptr);
     102                 :          0 :         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
     103                 :            :     }
     104                 :       4195 :     return;
     105                 :            : }
     106                 :            : 
     107                 :            : /* Add an access user entry
     108                 :            : */
     109                 :            : static void
     110                 :         22 : add_acc_user(char **user_var, uid_t *uid_var, struct passwd **upw,
     111                 :            :         const char *val, const char *var_name, FILE *file_ptr,
     112                 :            :         fko_srv_options_t *opts)
     113                 :            : {
     114                 :         22 :     struct passwd  *pw = NULL;
     115                 :            : 
     116                 :         22 :     add_acc_string(user_var, val, file_ptr, opts);
     117                 :            : 
     118                 :         22 :     errno = 0;
     119                 :         22 :     *upw = pw = getpwnam(val);
     120                 :            : 
     121 [ +  + ][ -  + ]:         22 :     if(*upw == NULL || pw == NULL)
     122                 :            :     {
     123         [ -  + ]:          1 :         log_msg(LOG_ERR, "[*] Unable to determine UID for %s: %s.",
     124                 :          1 :                 var_name, errno ? strerror(errno) : "Not a user on this system");
     125                 :          1 :         fclose(file_ptr);
     126                 :          1 :         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
     127                 :            :     }
     128                 :            : 
     129                 :         21 :     *uid_var = pw->pw_uid;
     130                 :            : 
     131                 :         21 :     return;
     132                 :            : }
     133                 :            : 
     134                 :            : /* Add an access group entry
     135                 :            : */
     136                 :            : static void
     137                 :          9 : add_acc_group(char **group_var, gid_t *gid_var,
     138                 :            :         const char *val, const char *var_name, FILE *file_ptr,
     139                 :            :         fko_srv_options_t *opts)
     140                 :            : {
     141                 :          9 :     struct passwd  *pw = NULL;
     142                 :            : 
     143                 :          9 :     add_acc_string(group_var, val, file_ptr, opts);
     144                 :            : 
     145                 :          9 :     errno = 0;
     146                 :          9 :     pw = getpwnam(val);
     147                 :            : 
     148         [ +  + ]:          9 :     if(pw == NULL)
     149                 :            :     {
     150         [ -  + ]:          1 :         log_msg(LOG_ERR, "[*] Unable to determine GID for %s: %s.",
     151                 :          1 :                 var_name, errno ? strerror(errno) : "Not a group on this system");
     152                 :          1 :         fclose(file_ptr);
     153                 :          1 :         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
     154                 :            :     }
     155                 :            : 
     156                 :          8 :     *gid_var = pw->pw_gid;
     157                 :            : 
     158                 :          8 :     return;
     159                 :            : }
     160                 :            : 
     161                 :            : /* Decode base64 encoded string into access entry
     162                 :            : */
     163                 :            : static void
     164                 :        606 : add_acc_b64_string(char **var, int *len, const char *val, FILE *file_ptr,
     165                 :            :         fko_srv_options_t *opts)
     166                 :            : {
     167         [ -  + ]:        606 :     if(var == NULL)
     168                 :            :     {
     169                 :          0 :         log_msg(LOG_ERR, "[*] add_acc_b64_string() called with NULL variable");
     170         [ #  # ]:          0 :         if(file_ptr != NULL)
     171                 :          0 :             fclose(file_ptr);
     172                 :          0 :         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
     173                 :            :     }
     174                 :            : 
     175         [ +  + ]:        606 :     if(*var != NULL)
     176                 :          2 :         free(*var);
     177                 :            : 
     178         [ -  + ]:        606 :     if((*var = strdup(val)) == NULL)
     179                 :            :     {
     180                 :          0 :         log_msg(LOG_ERR,
     181                 :            :             "[*] Fatal memory allocation error adding access list entry: %s", *var
     182                 :            :         );
     183         [ #  # ]:          0 :         if(file_ptr != NULL)
     184                 :          0 :             fclose(file_ptr);
     185                 :          0 :         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
     186                 :            :     }
     187                 :        606 :     memset(*var, 0x0, strlen(val));
     188                 :        606 :     *len = fko_base64_decode(val, (unsigned char *) *var);
     189                 :            : 
     190         [ -  + ]:        606 :     if (*len < 0)
     191                 :            :     {
     192                 :          0 :         log_msg(LOG_ERR,
     193                 :            :             "[*] base64 decoding returned error for: %s", *var
     194                 :            :         );
     195         [ #  # ]:          0 :         if(file_ptr != NULL)
     196                 :          0 :             fclose(file_ptr);
     197                 :          0 :         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
     198                 :            :     }
     199                 :        606 :     return;
     200                 :            : }
     201                 :            : 
     202                 :            : /* Add an access bool entry (unsigned char of 1 or 0)
     203                 :            : */
     204                 :            : static unsigned char
     205                 :       1835 : add_acc_bool(unsigned char *var, const char *val)
     206                 :            : {
     207                 :       1835 :     return(*var = (strncasecmp(val, "Y", 1) == 0) ? 1 : 0);
     208                 :            : }
     209                 :            : 
     210                 :            : /* Add expiration time - convert date to epoch seconds
     211                 :            : */
     212                 :            : static int
     213                 :          6 : add_acc_expire_time(fko_srv_options_t *opts, time_t *access_expire_time, const char *val)
     214                 :            : {
     215                 :            :     struct tm tm;
     216                 :            : 
     217                 :            :     memset(&tm, 0, sizeof(struct tm));
     218                 :            : 
     219         [ +  + ]:          3 :     if (sscanf(val, "%2d/%2d/%4d", &tm.tm_mon, &tm.tm_mday, &tm.tm_year) != 3)
     220                 :            :     {
     221                 :            : 
     222                 :          1 :         log_msg(LOG_ERR,
     223                 :            :             "[*] Fatal: invalid date value '%s' (need MM/DD/YYYY) for access stanza expiration time",
     224                 :            :             val
     225                 :            :         );
     226                 :            :         return FATAL_ERR;
     227                 :            :     }
     228                 :            : 
     229         [ +  - ]:          2 :     if(tm.tm_mon > 0)
     230                 :          2 :         tm.tm_mon -= 1;  /* 0-11 */
     231                 :            : 
     232                 :            :     /* number of years since 1900
     233                 :            :     */
     234         [ +  + ]:          2 :     if(tm.tm_year > 1900)
     235                 :          1 :         tm.tm_year -= 1900;
     236                 :            :     else
     237         [ +  - ]:          1 :         if(tm.tm_year < 100)
     238                 :          1 :             tm.tm_year += 100;
     239                 :            : 
     240                 :          2 :     *access_expire_time = mktime(&tm);
     241                 :            : 
     242                 :            :     return 1;
     243                 :            : }
     244                 :            : 
     245                 :            : /* Add expiration time via epoch seconds defined in access.conf
     246                 :            : */
     247                 :            : static void
     248                 :          2 : add_acc_expire_time_epoch(fko_srv_options_t *opts,
     249                 :            :         time_t *access_expire_time, const char *val, FILE *file_ptr)
     250                 :            : {
     251                 :            :     char *endptr;
     252                 :          2 :     unsigned long expire_time = 0;
     253                 :            : 
     254                 :          2 :     errno = 0;
     255                 :            : 
     256                 :          2 :     expire_time = (time_t) strtoul(val, &endptr, 10);
     257                 :            : 
     258 [ +  + ][ -  + ]:          2 :     if (errno == ERANGE || (errno != 0 && expire_time == 0))
                 [ #  # ]
     259                 :            :     {
     260                 :          1 :         log_msg(LOG_ERR,
     261                 :            :             "[*] Fatal: invalid epoch seconds value '%s' for access stanza expiration time",
     262                 :            :             val
     263                 :            :         );
     264                 :          1 :         fclose(file_ptr);
     265                 :          1 :         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
     266                 :            :     }
     267                 :            : 
     268                 :          1 :     *access_expire_time = (time_t) expire_time;
     269                 :            : 
     270                 :          1 :     return;
     271                 :            : }
     272                 :            : 
     273                 :            : #if defined(FIREWALL_FIREWALLD) || defined(FIREWALL_IPTABLES)
     274                 :            : static void
     275                 :         28 : add_acc_force_nat(fko_srv_options_t *opts, acc_stanza_t *curr_acc,
     276                 :            :         const char *val, FILE *file_ptr)
     277                 :            : {
     278                 :         28 :     char      ip_str[MAX_IPV4_STR_LEN] = {0};
     279                 :            : 
     280         [ +  + ]:         28 :     if (sscanf(val, "%15s %5u", ip_str, &curr_acc->force_nat_port) != 2)
     281                 :            :     {
     282                 :          2 :         log_msg(LOG_ERR,
     283                 :            :             "[*] Fatal: invalid FORCE_NAT arg '%s', need <IP> <PORT>",
     284                 :            :             val
     285                 :            :         );
     286         [ +  - ]:          2 :         if(file_ptr != NULL)
     287                 :          2 :             fclose(file_ptr);
     288                 :          2 :         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
     289                 :            :     }
     290                 :            : 
     291         [ +  + ]:         26 :     if (curr_acc->force_nat_port > MAX_PORT)
     292                 :            :     {
     293                 :          1 :         log_msg(LOG_ERR,
     294                 :            :             "[*] Fatal: invalid FORCE_NAT port '%d'", curr_acc->force_nat_port);
     295         [ +  - ]:          1 :         if(file_ptr != NULL)
     296                 :          1 :             fclose(file_ptr);
     297                 :          1 :         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
     298                 :            :     }
     299                 :            : 
     300         [ +  + ]:         25 :     if(! is_valid_ipv4_addr(ip_str, strlen(ip_str)))
     301                 :            :     {
     302                 :          1 :         log_msg(LOG_ERR,
     303                 :            :             "[*] Fatal: invalid FORCE_NAT IP '%s'", ip_str);
     304         [ +  - ]:          1 :         if(file_ptr != NULL)
     305                 :          1 :             fclose(file_ptr);
     306                 :          1 :         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
     307                 :            :     }
     308                 :            : 
     309                 :         24 :     curr_acc->force_nat = 1;
     310                 :            : 
     311                 :         24 :     add_acc_string(&(curr_acc->force_nat_ip), ip_str, file_ptr, opts);
     312                 :         24 :     return;
     313                 :            : }
     314                 :            : 
     315                 :            : static void
     316                 :         12 : add_acc_force_snat(fko_srv_options_t *opts, acc_stanza_t *curr_acc,
     317                 :            :         const char *val, FILE *file_ptr)
     318                 :            : {
     319                 :         12 :     char      ip_str[MAX_IPV4_STR_LEN] = {0};
     320                 :            : 
     321         [ -  + ]:         12 :     if (sscanf(val, "%15s", ip_str) != 1)
     322                 :            :     {
     323                 :          0 :         log_msg(LOG_ERR,
     324                 :            :                 "[*] Fatal: invalid FORCE_SNAT arg '%s', need <IP>", val);
     325         [ #  # ]:          0 :         if(file_ptr != NULL)
     326                 :          0 :             fclose(file_ptr);
     327                 :          0 :         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
     328                 :            :     }
     329                 :            : 
     330         [ +  + ]:         12 :     if(! is_valid_ipv4_addr(ip_str, strlen(ip_str)))
     331                 :            :     {
     332                 :          2 :         log_msg(LOG_ERR,
     333                 :            :             "[*] Fatal: invalid FORCE_SNAT IP '%s'", ip_str);
     334         [ +  - ]:          2 :         if(file_ptr != NULL)
     335                 :          2 :             fclose(file_ptr);
     336                 :          2 :         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
     337                 :            :     }
     338                 :            : 
     339                 :         10 :     curr_acc->force_snat = 1;
     340                 :            : 
     341                 :         10 :     add_acc_string(&(curr_acc->force_snat_ip), ip_str, file_ptr, opts);
     342                 :         10 :     return;
     343                 :            : }
     344                 :            : 
     345                 :            : #endif
     346                 :            : 
     347                 :            : /* Take an IP or Subnet/Mask and convert it to mask for later
     348                 :            :  * comparisons of incoming source IPs against this mask.
     349                 :            : */
     350                 :            : static int
     351                 :       1809 : add_int_ent(acc_int_list_t **ilist, const char *ip)
     352                 :            : {
     353                 :            :     char                *ndx;
     354                 :       1809 :     char                ip_str[MAX_IPV4_STR_LEN] = {0};
     355                 :       1809 :     char                ip_mask_str[MAX_IPV4_STR_LEN] = {0};
     356                 :            :     uint32_t            mask;
     357                 :       1809 :     int                 is_err, mask_len = 0, need_shift = 1;
     358                 :            : 
     359                 :            :     struct in_addr      in;
     360                 :            :     struct in_addr      mask_in;
     361                 :            : 
     362                 :            :     acc_int_list_t      *last_sle, *new_sle, *tmp_sle;
     363                 :            : 
     364         [ +  + ]:       1809 :     if((new_sle = calloc(1, sizeof(acc_int_list_t))) == NULL)
     365                 :            :     {
     366                 :          2 :         log_msg(LOG_ERR,
     367                 :            :             "[*] Fatal memory allocation error adding stanza source_list entry"
     368                 :            :         );
     369                 :          2 :         exit(EXIT_FAILURE);
     370                 :            :     }
     371                 :            : 
     372                 :            :     /* Convert the IP data into the appropriate IP + (optional) mask
     373                 :            :     */
     374         [ +  + ]:       1807 :     if(strcasecmp(ip, "ANY") == 0)
     375                 :            :     {
     376                 :       1582 :         new_sle->maddr = 0x0;
     377                 :       1582 :         new_sle->mask = 0x0;
     378                 :            :     }
     379                 :            :     else
     380                 :            :     {
     381                 :            :         /* See if we have a subnet component.  If so pull out the IP and
     382                 :            :          * mask values, then create the final mask value.
     383                 :            :         */
     384         [ +  + ]:        225 :         if((ndx = strchr(ip, '/')) != NULL)
     385                 :            :         {
     386         [ +  + ]:        142 :             if(((ndx-ip)) >= MAX_IPV4_STR_LEN)
     387                 :            :             {
     388                 :          1 :                 log_msg(LOG_ERR, "[*] Error parsing string to IP");
     389                 :          1 :                 free(new_sle);
     390                 :          1 :                 new_sle = NULL;
     391                 :          1 :                 return 0;
     392                 :            :             }
     393                 :            : 
     394                 :        141 :             mask_len = strlen(ip) - (ndx-ip+1);
     395                 :            : 
     396         [ +  + ]:        141 :             if(mask_len > 2)
     397                 :            :             {
     398         [ +  + ]:         11 :                 if(mask_len >= MIN_IPV4_STR_LEN && mask_len < MAX_IPV4_STR_LEN)
     399                 :            :                 {
     400                 :            :                     /* IP formatted mask
     401                 :            :                     */
     402                 :          9 :                     strlcpy(ip_mask_str, (ip + (ndx-ip) + 1), mask_len+1);
     403         [ +  + ]:          9 :                     if(inet_aton(ip_mask_str, &mask_in) == 0)
     404                 :            :                     {
     405                 :          6 :                         log_msg(LOG_ERR,
     406                 :            :                             "[*] Fatal error parsing IP mask to int for: %s", ip_mask_str
     407                 :            :                         );
     408                 :          6 :                         free(new_sle);
     409                 :          6 :                         new_sle = NULL;
     410                 :          6 :                         return 0;
     411                 :            :                     }
     412                 :          3 :                     mask = ntohl(mask_in.s_addr);
     413                 :          3 :                     need_shift = 0;
     414                 :            :                 }
     415                 :            :                 else
     416                 :            :                 {
     417                 :          2 :                     log_msg(LOG_ERR, "[*] Invalid IP mask str '%s'.", ndx+1);
     418                 :          2 :                     free(new_sle);
     419                 :          2 :                     new_sle = NULL;
     420                 :          2 :                     return 0;
     421                 :            :                 }
     422                 :            :             }
     423                 :            :             else
     424                 :            :             {
     425         [ +  + ]:        130 :                 if(mask_len > 0)
     426                 :            :                 {
     427                 :            :                     /* CIDR mask
     428                 :            :                     */
     429                 :        128 :                     mask = strtol_wrapper(ndx+1, 1, 32, NO_EXIT_UPON_ERR, &is_err);
     430         [ +  + ]:        128 :                     if(is_err != FKO_SUCCESS)
     431                 :            :                     {
     432                 :          6 :                         log_msg(LOG_ERR, "[*] Invalid IP mask str '%s'.", ndx+1);
     433                 :          6 :                         free(new_sle);
     434                 :          6 :                         new_sle = NULL;
     435                 :          6 :                         return 0;
     436                 :            :                     }
     437                 :            :                 }
     438                 :            :                 else
     439                 :            :                 {
     440                 :          2 :                     log_msg(LOG_ERR, "[*] Missing mask value.");
     441                 :          2 :                     free(new_sle);
     442                 :          2 :                     new_sle = NULL;
     443                 :          2 :                     return 0;
     444                 :            :                 }
     445                 :            :             }
     446                 :            : 
     447                 :        125 :             strlcpy(ip_str, ip, (ndx-ip)+1);
     448                 :            :         }
     449                 :            :         else
     450                 :            :         {
     451                 :         83 :             mask = 32;
     452         [ +  + ]:         83 :             if(strnlen(ip, MAX_IPV4_STR_LEN+1) >= MAX_IPV4_STR_LEN)
     453                 :            :             {
     454                 :          2 :                 log_msg(LOG_ERR, "[*] Error parsing string to IP");
     455                 :          2 :                 free(new_sle);
     456                 :          2 :                 new_sle = NULL;
     457                 :          2 :                 return 0;
     458                 :            :             }
     459                 :         81 :             strlcpy(ip_str, ip, sizeof(ip_str));
     460                 :            :         }
     461                 :            : 
     462         [ +  + ]:        206 :         if(inet_aton(ip_str, &in) == 0)
     463                 :            :         {
     464                 :          1 :             log_msg(LOG_ERR,
     465                 :            :                 "[*] Fatal error parsing IP to int for: %s", ip_str
     466                 :            :             );
     467                 :            : 
     468                 :          1 :             free(new_sle);
     469                 :          1 :             new_sle = NULL;
     470                 :            : 
     471                 :          1 :             return 0;
     472                 :            :         }
     473                 :            : 
     474                 :            :         /* Store our mask converted from CIDR to a 32-bit value.
     475                 :            :         */
     476         [ +  + ]:        205 :         if(mask == 32)
     477                 :         82 :             new_sle->mask = 0xFFFFFFFF;
     478 [ +  + ][ +  - ]:        123 :         else if(need_shift && (mask > 0 && mask < 32))
     479                 :        120 :             new_sle->mask = (0xFFFFFFFF << (32 - mask));
     480                 :            :         else
     481                 :          3 :             new_sle->mask = mask;
     482                 :            : 
     483                 :            :         /* Store our masked address for comparisons with future incoming
     484                 :            :          * packets.
     485                 :            :         */
     486                 :        205 :         new_sle->maddr = ntohl(in.s_addr) & new_sle->mask;
     487                 :            :     }
     488                 :            : 
     489                 :            :     /* If this is not the first entry, we walk our pointer to the
     490                 :            :      * end of the list.
     491                 :            :     */
     492         [ +  + ]:       1787 :     if(*ilist == NULL)
     493                 :            :     {
     494                 :       1787 :         *ilist = new_sle;
     495                 :            :     }
     496                 :            :     else
     497                 :            :     {
     498                 :            :         tmp_sle = *ilist;
     499                 :            : 
     500                 :            :         do {
     501                 :        276 :             last_sle = tmp_sle;
     502         [ +  + ]:        276 :         } while((tmp_sle = tmp_sle->next));
     503                 :            : 
     504                 :        125 :         last_sle->next = new_sle;
     505                 :            :     }
     506                 :            : 
     507                 :            :     return 1;
     508                 :            : }
     509                 :            : 
     510                 :            : /* Expand the access SOURCE string to a list of masks.
     511                 :            : */
     512                 :            : static int
     513                 :       1682 : expand_acc_int_list(acc_int_list_t **ilist, char *ip)
     514                 :            : {
     515                 :            :     char           *ndx, *start;
     516                 :       1682 :     char            buf[ACCESS_BUF_LEN] = {0};
     517                 :       1682 :     int             res = 1;
     518                 :            : 
     519                 :       1682 :     start = ip;
     520                 :            : 
     521         [ +  + ]:       9342 :     for(ndx = start; *ndx; ndx++)
     522                 :            :     {
     523         [ +  + ]:       7663 :         if(*ndx == ',')
     524                 :            :         {
     525                 :            :             /* Skip over any leading whitespace.
     526                 :            :             */
     527         [ +  + ]:        217 :             while(isspace(*start))
     528                 :         87 :                 start++;
     529                 :            : 
     530         [ +  - ]:        130 :             if(((ndx-start)+1) >= ACCESS_BUF_LEN)
     531                 :            :                 return 0;
     532                 :            : 
     533                 :        130 :             strlcpy(buf, start, (ndx-start)+1);
     534                 :            : 
     535                 :        130 :             res = add_int_ent(ilist, buf);
     536         [ +  + ]:        130 :             if(res == 0)
     537                 :          3 :                 return res;
     538                 :            : 
     539                 :        127 :             start = ndx+1;
     540                 :            :         }
     541                 :            :     }
     542                 :            : 
     543                 :            :     /* Skip over any leading whitespace (once again for the last in the list).
     544                 :            :     */
     545         [ +  + ]:       1719 :     while(isspace(*start))
     546                 :         40 :         start++;
     547                 :            : 
     548         [ +  - ]:       1679 :     if(((ndx-start)+1) >= ACCESS_BUF_LEN)
     549                 :            :         return 0;
     550                 :            : 
     551                 :       1679 :     strlcpy(buf, start, (ndx-start)+1);
     552                 :            : 
     553                 :       1679 :     res = add_int_ent(ilist, buf);
     554                 :            : 
     555                 :       1677 :     return res;
     556                 :            : }
     557                 :            : 
     558                 :            : static int
     559                 :       1995 : parse_proto_and_port(char *pstr, int *proto, int *port)
     560                 :            : {
     561                 :            :     char    *ndx;
     562                 :       1995 :     char    proto_str[ACCESS_BUF_LEN] = {0};
     563                 :            :     int     is_err;
     564                 :            : 
     565                 :            :     /* Parse the string into its components.
     566                 :            :     */
     567         [ +  + ]:       1995 :     if((ndx = strchr(pstr, '/')) == NULL)
     568                 :            :     {
     569                 :          1 :         log_msg(LOG_ERR,
     570                 :            :             "[*] Parse error on access port entry: %s", pstr);
     571                 :            : 
     572                 :          1 :         return(-1);
     573                 :            :     }
     574                 :            : 
     575         [ -  + ]:       1994 :     if(((ndx - pstr)+1) >= ACCESS_BUF_LEN)
     576                 :            :     {
     577                 :          0 :         log_msg(LOG_ERR,
     578                 :            :             "[*] Parse error on access port entry: %s", pstr);
     579                 :          0 :         return(-1);
     580                 :            :     }
     581                 :            : 
     582                 :       1994 :     strlcpy(proto_str, pstr, (ndx - pstr)+1);
     583                 :            : 
     584                 :       1994 :     *port = strtol_wrapper(ndx+1, 0, MAX_PORT, NO_EXIT_UPON_ERR, &is_err);
     585         [ +  + ]:       1994 :     if(is_err != FKO_SUCCESS)
     586                 :            :     {
     587                 :          1 :         log_msg(LOG_ERR,
     588                 :            :             "[*] Invalid port '%s' in access request, must be in [%d,%d]",
     589                 :            :             pstr, 0, MAX_PORT);
     590                 :          1 :         return(-1);
     591                 :            :     }
     592                 :            : 
     593         [ +  + ]:       1993 :     if(strcasecmp(proto_str, "tcp") == 0)
     594                 :       1878 :         *proto = PROTO_TCP;
     595         [ +  + ]:        115 :     else if(strcasecmp(proto_str, "udp") == 0)
     596                 :        113 :         *proto = PROTO_UDP;
     597                 :            :     else
     598                 :            :     {
     599                 :          2 :         log_msg(LOG_ERR,
     600                 :            :             "[*] Invalid protocol in access port entry: %s", pstr);
     601                 :          2 :         return(-1);
     602                 :            :     }
     603                 :            : 
     604                 :            :     return(0);
     605                 :            : }
     606                 :            : 
     607                 :            : /* Take a proto/port string and convert it to appropriate integer values
     608                 :            :  * for comparisons of incoming SPA requests.
     609                 :            : */
     610                 :            : static int
     611                 :       1995 : add_port_list_ent(acc_port_list_t **plist, char *port_str)
     612                 :            : {
     613                 :            :     int                 proto_int, port;
     614                 :            : 
     615                 :            :     acc_port_list_t     *last_plist, *new_plist, *tmp_plist;
     616                 :            : 
     617                 :            :     /* Parse the string into its components and continue only if there
     618                 :            :      * are no problems with the incoming string.
     619                 :            :     */
     620         [ +  + ]:       1995 :     if(parse_proto_and_port(port_str, &proto_int, &port) != 0)
     621                 :            :         return 0;
     622                 :            : 
     623         [ -  + ]:       1991 :     if((new_plist = calloc(1, sizeof(acc_port_list_t))) == NULL)
     624                 :            :     {
     625                 :          0 :         log_msg(LOG_ERR,
     626                 :            :             "[*] Fatal memory allocation error adding stanza port_list entry"
     627                 :            :         );
     628                 :          0 :         exit(EXIT_FAILURE);
     629                 :            :     }
     630                 :            : 
     631                 :            :     /* If this is not the first entry, we walk our pointer to the
     632                 :            :      * end of the list.
     633                 :            :     */
     634         [ +  + ]:       1991 :     if(*plist == NULL)
     635                 :            :     {
     636                 :       1991 :         *plist = new_plist;
     637                 :            :     }
     638                 :            :     else
     639                 :            :     {
     640                 :            :         tmp_plist = *plist;
     641                 :            : 
     642                 :            :         do {
     643                 :        213 :             last_plist = tmp_plist;
     644         [ +  + ]:        213 :         } while((tmp_plist = tmp_plist->next));
     645                 :            : 
     646                 :        145 :         last_plist->next = new_plist;
     647                 :            :     }
     648                 :            : 
     649                 :       1991 :     new_plist->proto = proto_int;
     650                 :       1991 :     new_plist->port  = port;
     651                 :            : 
     652                 :       1991 :     return 1;
     653                 :            : }
     654                 :            : 
     655                 :            : /* Add a string list entry to the given acc_string_list.
     656                 :            : */
     657                 :            : static int
     658                 :        127 : add_string_list_ent(acc_string_list_t **stlist, const char *str_str)
     659                 :            : {
     660                 :            :     acc_string_list_t   *last_stlist, *new_stlist, *tmp_stlist;
     661                 :            : 
     662         [ -  + ]:        127 :     if((new_stlist = calloc(1, sizeof(acc_string_list_t))) == NULL)
     663                 :            :     {
     664                 :          0 :         log_msg(LOG_ERR,
     665                 :            :             "[*] Fatal memory allocation error creating string list entry"
     666                 :            :         );
     667                 :          0 :         return FATAL_ERR;
     668                 :            :     }
     669                 :            : 
     670                 :            :     /* If this is not the first entry, we walk our pointer to the
     671                 :            :      * end of the list.
     672                 :            :     */
     673         [ +  + ]:        127 :     if(*stlist == NULL)
     674                 :            :     {
     675                 :        127 :         *stlist = new_stlist;
     676                 :            :     }
     677                 :            :     else
     678                 :            :     {
     679                 :            :         tmp_stlist = *stlist;
     680                 :            : 
     681                 :            :         do {
     682                 :         75 :             last_stlist = tmp_stlist;
     683         [ +  + ]:         75 :         } while((tmp_stlist = tmp_stlist->next));
     684                 :            : 
     685                 :         50 :         last_stlist->next = new_stlist;
     686                 :            :     }
     687                 :            : 
     688         [ -  + ]:        127 :     if(new_stlist->str != NULL)
     689                 :          0 :         free(new_stlist->str);
     690                 :            : 
     691                 :        127 :     new_stlist->str = strdup(str_str);
     692                 :            : 
     693         [ -  + ]:        127 :     if(new_stlist->str == NULL)
     694                 :            :     {
     695                 :          0 :         log_msg(LOG_ERR,
     696                 :            :             "[*] Fatal memory allocation error adding string list entry item"
     697                 :            :         );
     698                 :          0 :         return FATAL_ERR;
     699                 :            :     }
     700                 :            :     return SUCCESS;
     701                 :            : }
     702                 :            : 
     703                 :            : /* Expand a proto/port access string to a list of access proto-port struct.
     704                 :            : */
     705                 :            : int
     706                 :       1244 : expand_acc_port_list(acc_port_list_t **plist, char *plist_str)
     707                 :            : {
     708                 :            :     char           *ndx, *start;
     709                 :       1244 :     char            buf[ACCESS_BUF_LEN] = {0};
     710                 :            : 
     711                 :       1244 :     start = plist_str;
     712                 :            : 
     713         [ +  + ]:       9573 :     for(ndx = start; *ndx != '\0'; ndx++)
     714                 :            :     {
     715         [ +  + ]:       8330 :         if(*ndx == ',')
     716                 :            :         {
     717                 :            :             /* Skip over any leading whitespace.
     718                 :            :             */
     719         [ +  + ]:        128 :             while(isspace(*start))
     720                 :         47 :                 start++;
     721                 :            : 
     722         [ +  - ]:         81 :             if(((ndx-start)+1) >= ACCESS_BUF_LEN)
     723                 :            :                 return 0;
     724                 :            : 
     725                 :         81 :             strlcpy(buf, start, (ndx-start)+1);
     726                 :            : 
     727         [ +  + ]:         81 :             if(add_port_list_ent(plist, buf) == 0)
     728                 :            :                 return 0;
     729                 :            : 
     730                 :         80 :             start = ndx+1;
     731                 :            :         }
     732                 :            :     }
     733                 :            : 
     734                 :            :     /* Skip over any leading whitespace (once again for the last in the list).
     735                 :            :     */
     736         [ +  + ]:       1268 :     while(isspace(*start))
     737                 :         25 :         start++;
     738                 :            : 
     739         [ +  + ]:       1243 :     if(((ndx-start)+1) >= ACCESS_BUF_LEN)
     740                 :            :         return 0;
     741                 :            : 
     742                 :       1242 :     strlcpy(buf, start, (ndx-start)+1);
     743                 :            : 
     744         [ +  + ]:       1242 :     if(add_port_list_ent(plist, buf) == 0)
     745                 :            :         return 0;
     746                 :            : 
     747                 :       1239 :     return 1;
     748                 :            : }
     749                 :            : 
     750                 :            : /* Expand a comma-separated string into a simple acc_string_list.
     751                 :            : */
     752                 :            : static int
     753                 :         77 : expand_acc_string_list(acc_string_list_t **stlist, char *stlist_str)
     754                 :            : {
     755                 :            :     char           *ndx, *start;
     756                 :         77 :     char            buf[MAX_LINE_LEN] = {0};
     757                 :            : 
     758                 :         77 :     start = stlist_str;
     759                 :            : 
     760         [ +  + ]:       1321 :     for(ndx = start; *ndx; ndx++)
     761                 :            :     {
     762         [ +  + ]:       1244 :         if(*ndx == ',')
     763                 :            :         {
     764                 :            :             /* Skip over any leading whitespace.
     765                 :            :             */
     766         [ +  + ]:         75 :             while(isspace(*start))
     767                 :         25 :                 start++;
     768                 :            : 
     769         [ +  - ]:         50 :             if(((ndx-start)+1) >= MAX_LINE_LEN)
     770                 :            :                 return FATAL_ERR;
     771                 :            : 
     772                 :         50 :             strlcpy(buf, start, (ndx-start)+1);
     773         [ +  - ]:         50 :             if(add_string_list_ent(stlist, buf) != SUCCESS)
     774                 :            :                 return FATAL_ERR;
     775                 :            : 
     776                 :         50 :             start = ndx+1;
     777                 :            :         }
     778                 :            :     }
     779                 :            : 
     780                 :            :     /* Skip over any leading whitespace (once again for the last in the list).
     781                 :            :     */
     782         [ +  + ]:        102 :     while(isspace(*start))
     783                 :         25 :         start++;
     784                 :            : 
     785         [ +  - ]:         77 :     if(((ndx-start)+1) >= MAX_LINE_LEN)
     786                 :            :         return FATAL_ERR;
     787                 :            : 
     788                 :         77 :     strlcpy(buf, start, (ndx-start)+1);
     789                 :            : 
     790         [ +  - ]:         77 :     if(add_string_list_ent(stlist, buf) != SUCCESS)
     791                 :            :         return FATAL_ERR;
     792                 :            : 
     793                 :         77 :     return SUCCESS;
     794                 :            : }
     795                 :            : 
     796                 :            : /* Free the acc source_list
     797                 :            : */
     798                 :            : static void
     799                 :       1739 : free_acc_int_list(acc_int_list_t *sle)
     800                 :            : {
     801                 :            :     acc_int_list_t    *last_sle;
     802                 :            : 
     803         [ +  + ]:       3523 :     while(sle != NULL)
     804                 :            :     {
     805                 :       1784 :         last_sle = sle;
     806                 :       1784 :         sle = last_sle->next;
     807                 :            : 
     808                 :       1784 :         free(last_sle);
     809                 :            :     }
     810                 :       1739 : }
     811                 :            : 
     812                 :            : /* Free a port_list
     813                 :            : */
     814                 :            : void
     815                 :       1851 : free_acc_port_list(acc_port_list_t *ple)
     816                 :            : {
     817                 :            :     acc_port_list_t    *last_ple;
     818                 :            : 
     819         [ +  + ]:       3833 :     while(ple != NULL)
     820                 :            :     {
     821                 :       1982 :         last_ple = ple;
     822                 :       1982 :         ple = last_ple->next;
     823                 :            : 
     824                 :       1982 :         free(last_ple);
     825                 :            :     }
     826                 :       1851 : }
     827                 :            : 
     828                 :            : /* Free a string_list
     829                 :            : */
     830                 :            : static void
     831                 :         77 : free_acc_string_list(acc_string_list_t *stl)
     832                 :            : {
     833                 :            :     acc_string_list_t    *last_stl;
     834                 :            : 
     835         [ +  + ]:        204 :     while(stl != NULL)
     836                 :            :     {
     837                 :        127 :         last_stl = stl;
     838                 :        127 :         stl = last_stl->next;
     839                 :            : 
     840                 :        127 :         free(last_stl->str);
     841                 :        127 :         free(last_stl);
     842                 :            :     }
     843                 :         77 : }
     844                 :            : 
     845                 :            : static void
     846                 :       2561 : zero_buf_wrapper(char *buf, int len)
     847                 :            : {
     848                 :            : 
     849         [ -  + ]:       2561 :     if(zero_buf(buf, len) != FKO_SUCCESS)
     850                 :          0 :         log_msg(LOG_ERR,
     851                 :            :                 "[*] Could not zero out sensitive data buffer.");
     852                 :            : 
     853                 :       2561 :     return;
     854                 :            : }
     855                 :            : 
     856                 :            : /* Free any allocated content of an access stanza.
     857                 :            :  *
     858                 :            :  * NOTE: If a new access.conf parameter is created, and it is a string
     859                 :            :  *       value, it also needs to be added to the list of items to check
     860                 :            :  *       and free below.
     861                 :            : */
     862                 :            : static void
     863                 :       1719 : free_acc_stanza_data(acc_stanza_t *acc)
     864                 :            : {
     865                 :            : 
     866         [ +  - ]:       1719 :     if(acc->source != NULL)
     867                 :            :     {
     868                 :       1719 :         free(acc->source);
     869                 :       1719 :         free_acc_int_list(acc->source_list);
     870                 :            :     }
     871                 :            : 
     872         [ +  + ]:       1719 :     if(acc->destination != NULL)
     873                 :            :     {
     874                 :         20 :         free(acc->destination);
     875                 :         20 :         free_acc_int_list(acc->destination_list);
     876                 :            :     }
     877                 :            : 
     878         [ +  + ]:       1719 :     if(acc->open_ports != NULL)
     879                 :            :     {
     880                 :         37 :         free(acc->open_ports);
     881                 :         37 :         free_acc_port_list(acc->oport_list);
     882                 :            :     }
     883                 :            : 
     884         [ +  + ]:       1719 :     if(acc->restrict_ports != NULL)
     885                 :            :     {
     886                 :          1 :         free(acc->restrict_ports);
     887                 :          1 :         free_acc_port_list(acc->rport_list);
     888                 :            :     }
     889                 :            : 
     890         [ +  + ]:       1719 :     if(acc->force_nat_ip != NULL)
     891                 :         24 :         free(acc->force_nat_ip);
     892                 :            : 
     893         [ +  + ]:       1719 :     if(acc->force_snat_ip != NULL)
     894                 :         10 :         free(acc->force_snat_ip);
     895                 :            : 
     896         [ +  + ]:       1719 :     if(acc->key != NULL)
     897                 :            :     {
     898                 :       1639 :         zero_buf_wrapper(acc->key, acc->key_len);
     899                 :       1639 :         free(acc->key);
     900                 :            :     }
     901                 :            : 
     902         [ +  + ]:       1719 :     if(acc->key_base64 != NULL)
     903                 :            :     {
     904                 :        284 :         zero_buf_wrapper(acc->key_base64, strlen(acc->key_base64));
     905                 :        284 :         free(acc->key_base64);
     906                 :            :     }
     907                 :            : 
     908         [ +  + ]:       1719 :     if(acc->hmac_key != NULL)
     909                 :            :     {
     910                 :        326 :         zero_buf_wrapper(acc->hmac_key, acc->hmac_key_len);
     911                 :        326 :         free(acc->hmac_key);
     912                 :            :     }
     913                 :            : 
     914         [ +  + ]:       1719 :     if(acc->hmac_key_base64 != NULL)
     915                 :            :     {
     916                 :        312 :         zero_buf_wrapper(acc->hmac_key_base64, strlen(acc->hmac_key_base64));
     917                 :        312 :         free(acc->hmac_key_base64);
     918                 :            :     }
     919                 :            : 
     920         [ +  + ]:       1719 :     if(acc->cmd_sudo_exec_user != NULL)
     921                 :          9 :         free(acc->cmd_sudo_exec_user);
     922                 :            : 
     923         [ +  + ]:       1719 :     if(acc->cmd_sudo_exec_group != NULL)
     924                 :          3 :         free(acc->cmd_sudo_exec_group);
     925                 :            : 
     926         [ +  + ]:       1719 :     if(acc->cmd_exec_user != NULL)
     927                 :         13 :         free(acc->cmd_exec_user);
     928                 :            : 
     929         [ +  + ]:       1719 :     if(acc->cmd_exec_group != NULL)
     930                 :          6 :         free(acc->cmd_exec_group);
     931                 :            : 
     932         [ +  + ]:       1719 :     if(acc->require_username != NULL)
     933                 :         15 :         free(acc->require_username);
     934                 :            : 
     935         [ +  + ]:       1719 :     if(acc->cmd_cycle_open != NULL)
     936                 :         25 :         free(acc->cmd_cycle_open);
     937                 :            : 
     938         [ +  + ]:       1719 :     if(acc->cmd_cycle_close != NULL)
     939                 :         25 :         free(acc->cmd_cycle_close);
     940                 :            : 
     941         [ +  + ]:       1719 :     if(acc->gpg_home_dir != NULL)
     942                 :         77 :         free(acc->gpg_home_dir);
     943                 :            : 
     944         [ +  + ]:       1719 :     if(acc->gpg_exe != NULL)
     945                 :          1 :         free(acc->gpg_exe);
     946                 :            : 
     947         [ +  + ]:       1719 :     if(acc->gpg_decrypt_id != NULL)
     948                 :         77 :         free(acc->gpg_decrypt_id);
     949                 :            : 
     950         [ +  + ]:       1719 :     if(acc->gpg_decrypt_pw != NULL)
     951                 :         79 :         free(acc->gpg_decrypt_pw);
     952                 :            : 
     953         [ +  + ]:       1719 :     if(acc->gpg_remote_id != NULL)
     954                 :            :     {
     955                 :         72 :         free(acc->gpg_remote_id);
     956                 :         72 :         free_acc_string_list(acc->gpg_remote_id_list);
     957                 :            :     }
     958         [ +  + ]:       1719 :     if(acc->gpg_remote_fpr != NULL)
     959                 :            :     {
     960                 :          5 :         free(acc->gpg_remote_fpr);
     961                 :          5 :         free_acc_string_list(acc->gpg_remote_fpr_list);
     962                 :            :     }
     963                 :       1719 :     return;
     964                 :            : }
     965                 :            : 
     966                 :            : /* Expand any access entries that may be multi-value.
     967                 :            : */
     968                 :            : static void
     969                 :       1613 : expand_acc_ent_lists(fko_srv_options_t *opts)
     970                 :            : {
     971                 :       1613 :     acc_stanza_t   *acc = opts->acc_stanzas;
     972                 :            : 
     973                 :            :     /* We need to do this for each stanza.
     974                 :            :     */
     975         [ +  + ]:       3249 :     while(acc)
     976                 :            :     {
     977                 :            :         /* Expand the source string to 32-bit integer IP + masks for each entry.
     978                 :            :         */
     979         [ +  + ]:       1663 :         if(expand_acc_int_list(&(acc->source_list), acc->source) == 0)
     980                 :            :         {
     981                 :         11 :             log_msg(LOG_ERR, "[*] Fatal invalid SOURCE in access stanza");
     982                 :         11 :             clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
     983                 :            :         }
     984                 :            : 
     985 [ +  + ][ +  - ]:       1650 :         if(acc->destination != NULL && strlen(acc->destination))
     986                 :            :         {
     987         [ +  + ]:         19 :             if(expand_acc_int_list(&(acc->destination_list), acc->destination) == 0)
     988                 :            :             {
     989                 :          9 :                 log_msg(LOG_ERR, "[*] Fatal invalid DESTINATION in access stanza");
     990                 :          9 :                 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
     991                 :            :             }
     992                 :            :         }
     993                 :            : 
     994                 :            :         /* Now expand the open_ports string.
     995                 :            :         */
     996 [ +  + ][ +  - ]:       1641 :         if(acc->open_ports != NULL && strlen(acc->open_ports))
     997                 :            :         {
     998         [ +  + ]:         34 :             if(expand_acc_port_list(&(acc->oport_list), acc->open_ports) == 0)
     999                 :            :             {
    1000                 :          4 :                 log_msg(LOG_ERR, "[*] Fatal invalid OPEN_PORTS in access stanza");
    1001                 :          4 :                 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
    1002                 :            :             }
    1003                 :            :         }
    1004                 :            : 
    1005 [ +  + ][ +  - ]:       1637 :         if(acc->restrict_ports != NULL && strlen(acc->restrict_ports))
    1006                 :            :         {
    1007         [ +  - ]:          1 :             if(expand_acc_port_list(&(acc->rport_list), acc->restrict_ports) == 0)
    1008                 :            :             {
    1009                 :          1 :                 log_msg(LOG_ERR, "[*] Fatal invalid RESTRICT_PORTS in access stanza");
    1010                 :          1 :                 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
    1011                 :            :             }
    1012                 :            :         }
    1013                 :            : 
    1014                 :            :         /* Expand the GPG_REMOTE_ID string.
    1015                 :            :         */
    1016 [ +  + ][ +  - ]:       1636 :         if(acc->gpg_remote_id != NULL && strlen(acc->gpg_remote_id))
    1017                 :            :         {
    1018         [ -  + ]:         72 :             if(expand_acc_string_list(&(acc->gpg_remote_id_list),
    1019                 :            :                         acc->gpg_remote_id) != SUCCESS)
    1020                 :            :             {
    1021                 :          0 :                 log_msg(LOG_ERR, "[*] Fatal invalid GPG_REMOTE_ID list in access stanza");
    1022                 :          0 :                 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
    1023                 :            :             }
    1024                 :            :         }
    1025                 :            : 
    1026                 :            :         /* Expand the GPG_FINGERPRINT_ID string.
    1027                 :            :         */
    1028 [ +  + ][ +  - ]:       1636 :         if(acc->gpg_remote_fpr != NULL && strlen(acc->gpg_remote_fpr))
    1029                 :            :         {
    1030         [ -  + ]:          5 :             if(expand_acc_string_list(&(acc->gpg_remote_fpr_list),
    1031                 :            :                         acc->gpg_remote_fpr) != SUCCESS)
    1032                 :            :             {
    1033                 :          0 :                 log_msg(LOG_ERR, "[*] Fatal invalid GPG_FINGERPRINT_ID list in access stanza");
    1034                 :          0 :                 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
    1035                 :            :             }
    1036                 :            :         }
    1037                 :            : 
    1038                 :       1636 :         acc = acc->next;
    1039                 :            :     }
    1040                 :       1586 :     return;
    1041                 :            : }
    1042                 :            : 
    1043                 :            : void
    1044                 :       8782 : free_acc_stanzas(fko_srv_options_t *opts)
    1045                 :            : {
    1046                 :            :     acc_stanza_t    *acc, *last_acc;
    1047                 :            : 
    1048                 :            :     /* Free any resources first (in case of reconfig). Assume non-NULL
    1049                 :            :      * entry needs to be freed.
    1050                 :            :     */
    1051                 :       8782 :     acc = opts->acc_stanzas;
    1052                 :            : 
    1053         [ +  + ]:      10489 :     while(acc != NULL)
    1054                 :            :     {
    1055                 :       1707 :         last_acc = acc;
    1056                 :       1707 :         acc = last_acc->next;
    1057                 :            : 
    1058                 :       1707 :         free_acc_stanza_data(last_acc);
    1059                 :       1707 :         free(last_acc);
    1060                 :            :     }
    1061                 :            : 
    1062                 :       8782 :     return;
    1063                 :            : }
    1064                 :            : 
    1065                 :            : /**
    1066                 :            :  * \brief Frees the final access stanza
    1067                 :            :  *
    1068                 :            :  * This function walks the access stanza list and frees the last member
    1069                 :            :  *
    1070                 :            :  * \param opts pointer to the server options struct
    1071                 :            :  *
    1072                 :            :  */
    1073                 :            : 
    1074                 :            : void
    1075                 :         12 : free_last_acc_stanza(fko_srv_options_t *opts)
    1076                 :            : {
    1077                 :         12 :     acc_stanza_t *tmp_root = opts->acc_stanzas;
    1078                 :            : 
    1079                 :            :     //deal with edge cases first, like a null list
    1080         [ +  - ]:         12 :     if (tmp_root == NULL)
    1081                 :            :         return;
    1082                 :            : 
    1083                 :            :     //check for only one element
    1084         [ +  + ]:         12 :     if (tmp_root->next == NULL)
    1085                 :            :     {
    1086                 :         10 :         free_acc_stanza_data(tmp_root);
    1087                 :         10 :         free(tmp_root);
    1088                 :         10 :         opts->acc_stanzas = NULL;
    1089                 :         10 :         return;
    1090                 :            :     }
    1091                 :            : 
    1092                 :            :     //more than one element uses the general case
    1093         [ -  + ]:          2 :     while (tmp_root->next->next != NULL)
    1094                 :            :     {
    1095                 :            :         tmp_root = tmp_root->next;
    1096                 :            :     }
    1097                 :            : 
    1098                 :          2 :     free_acc_stanza_data(tmp_root->next);
    1099                 :          2 :     free(tmp_root->next);
    1100                 :          2 :     tmp_root->next = NULL;
    1101                 :          2 :     return;
    1102                 :            : }
    1103                 :            : 
    1104                 :            : /* Wrapper for free_acc_stanzas(), we may put additional initialization
    1105                 :            :  * code here.
    1106                 :            : */
    1107                 :            : static void
    1108                 :       1687 : acc_stanza_init(fko_srv_options_t *opts)
    1109                 :            : {
    1110         [ +  + ]:       1687 :     if(do_acc_stanza_init)
    1111                 :            :     {
    1112                 :       1666 :         log_msg(LOG_DEBUG, "Initialize access stanzas");
    1113                 :            : 
    1114                 :            :         /* Free any resources first (in case of reconfig). Assume non-NULL
    1115                 :            :          * entry needs to be freed.
    1116                 :            :         */
    1117                 :       1666 :         free_acc_stanzas(opts);
    1118                 :            : 
    1119                 :            :         /* Make sure to only initialize access stanzas once.
    1120                 :            :         */
    1121                 :       1666 :         do_acc_stanza_init = 0;
    1122                 :            :     }
    1123                 :            : 
    1124                 :       1687 :     return;
    1125                 :            : }
    1126                 :            : 
    1127                 :            : /* Add a new stanza bay allocating the required memory at the required
    1128                 :            :  * location, yada-yada-yada.
    1129                 :            : */
    1130                 :            : static acc_stanza_t*
    1131                 :       1724 : acc_stanza_add(fko_srv_options_t *opts)
    1132                 :            : {
    1133                 :       1724 :     acc_stanza_t    *acc     = opts->acc_stanzas;
    1134                 :       1724 :     acc_stanza_t    *new_acc = calloc(1, sizeof(acc_stanza_t));
    1135                 :            :     acc_stanza_t    *last_acc;
    1136                 :            : 
    1137         [ +  + ]:       1724 :     if(new_acc == NULL)
    1138                 :            :     {
    1139                 :          4 :         log_msg(LOG_ERR,
    1140                 :            :             "[*] Fatal memory allocation error adding access stanza"
    1141                 :            :         );
    1142                 :          4 :         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
    1143                 :            :     }
    1144                 :            : 
    1145                 :            :     /* If this is not the first acc entry, we walk our acc pointer to the
    1146                 :            :      * end of the existing list.
    1147                 :            :     */
    1148         [ +  + ]:       1720 :     if(acc == NULL)
    1149                 :            :     {
    1150                 :       1720 :         opts->acc_stanzas = new_acc;
    1151                 :            :     }
    1152                 :            :     else
    1153                 :            :     {
    1154                 :            :         do {
    1155                 :        162 :             last_acc = acc;
    1156         [ +  + ]:        162 :         } while((acc = acc->next));
    1157                 :            : 
    1158                 :         58 :         last_acc->next = new_acc;
    1159                 :            :     }
    1160                 :            : 
    1161                 :       1720 :     return(new_acc);
    1162                 :            : }
    1163                 :            : 
    1164                 :            : /* Scan the access options for entries that have not been set, but need
    1165                 :            :  * a default value.
    1166                 :            : */
    1167                 :            : static void
    1168                 :       1586 : set_acc_defaults(fko_srv_options_t *opts)
    1169                 :            : {
    1170                 :       1586 :     acc_stanza_t    *acc = opts->acc_stanzas;
    1171                 :       1586 :     int              i=1;
    1172                 :            : 
    1173         [ +  - ]:       1586 :     if(!acc)
    1174                 :            :         return;
    1175                 :            : 
    1176         [ +  + ]:       3221 :     while(acc)
    1177                 :            :     {
    1178                 :            :         /* set default fw_access_timeout if necessary
    1179                 :            :         */
    1180         [ +  + ]:       1636 :         if(acc->fw_access_timeout < 1)
    1181                 :         67 :             acc->fw_access_timeout = DEF_FW_ACCESS_TIMEOUT;
    1182                 :            : 
    1183                 :            :         /* set default gpg keyring path if necessary
    1184                 :            :         */
    1185         [ +  + ]:       1636 :         if(acc->gpg_decrypt_pw != NULL)
    1186                 :            :         {
    1187         [ +  + ]:         77 :             if(acc->gpg_home_dir == NULL)
    1188                 :          2 :                 add_acc_string(&(acc->gpg_home_dir),
    1189                 :          2 :                         opts->config[CONF_GPG_HOME_DIR], NULL, opts);
    1190                 :            : 
    1191         [ +  + ]:         77 :             if(! acc->gpg_require_sig)
    1192                 :            :             {
    1193         [ +  + ]:         75 :                 if (acc->gpg_disable_sig)
    1194                 :            :                 {
    1195                 :          1 :                     log_msg(LOG_INFO,
    1196                 :            :                         "Warning: GPG_REQUIRE_SIG should really be enabled for stanza source: '%s' (#%d)",
    1197                 :            :                         acc->source, i
    1198                 :            :                     );
    1199                 :            :                 }
    1200                 :            :                 else
    1201                 :            :                 {
    1202                 :            :                     /* Make this the default unless explicitly disabled
    1203                 :            :                     */
    1204                 :         74 :                     acc->gpg_require_sig = 1;
    1205                 :            :                 }
    1206                 :            :             }
    1207                 :            :             else
    1208                 :            :             {
    1209         [ +  - ]:          2 :                 if (acc->gpg_disable_sig)
    1210                 :            :                 {
    1211                 :          2 :                     log_msg(LOG_INFO,
    1212                 :            :                         "Warning: GPG_REQUIRE_SIG and GPG_DISABLE_SIG are both set, will check sigs (stanza source: '%s' #%d)",
    1213                 :            :                         acc->source, i
    1214                 :            :                     );
    1215                 :            :                 }
    1216                 :            :             }
    1217                 :            : 
    1218                 :            :             /* If signature checking is enabled, make sure we either have sig ID's or
    1219                 :            :              * fingerprint ID's to check
    1220                 :            :             */
    1221         [ +  + ]:         77 :             if(! acc->gpg_disable_sig
    1222 [ +  + ][ +  + ]:         74 :                     && (acc->gpg_remote_id == NULL && acc->gpg_remote_fpr == NULL))
    1223                 :            :             {
    1224                 :          1 :                 log_msg(LOG_INFO,
    1225                 :            :                     "Warning: Must have either sig ID's or fingerprints to check via GPG_REMOTE_ID or GPG_FINGERPRINT_ID (stanza source: '%s' #%d)",
    1226                 :            :                     acc->source, i
    1227                 :            :                 );
    1228                 :          1 :                 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
    1229                 :            :             }
    1230                 :            :         }
    1231                 :            : 
    1232         [ +  + ]:       1635 :         if(acc->encryption_mode == FKO_ENC_MODE_UNKNOWN)
    1233                 :       1607 :             acc->encryption_mode = FKO_DEFAULT_ENC_MODE;
    1234                 :            : 
    1235                 :            :         /* if we're using an HMAC key and the HMAC digest type was not
    1236                 :            :          * set for HMAC_DIGEST_TYPE, then assume it's SHA256
    1237                 :            :         */
    1238                 :            : 
    1239         [ +  + ]:       1635 :         if(acc->hmac_type == FKO_HMAC_UNKNOWN
    1240 [ +  + ][ +  - ]:       1572 :                 && acc->hmac_key_len > 0 && acc->hmac_key != NULL)
    1241                 :            :         {
    1242                 :        260 :             acc->hmac_type = FKO_DEFAULT_HMAC_MODE;
    1243                 :            :         }
    1244                 :            : 
    1245                 :       1635 :         acc = acc->next;
    1246                 :       1635 :         i++;
    1247                 :            :     }
    1248                 :            :     return;
    1249                 :            : }
    1250                 :            : 
    1251                 :            : /* Perform some sanity checks on an acc stanza data.
    1252                 :            : */
    1253                 :            : static int
    1254                 :       1703 : acc_data_is_valid(fko_srv_options_t *opts,
    1255                 :            :         struct passwd *user_pw, struct passwd *sudo_user_pw,
    1256                 :            :         acc_stanza_t * const acc)
    1257                 :            : {
    1258         [ -  + ]:       1703 :     if(acc == NULL)
    1259                 :            :     {
    1260                 :          0 :         log_msg(LOG_ERR,
    1261                 :            :             "[*] acc_data_is_valid() called with NULL acc stanza");
    1262                 :          0 :         return(0);
    1263                 :            :     }
    1264                 :            : 
    1265 [ +  + ][ -  + ]:       1703 :     if(((acc->key == NULL || acc->key_len == 0)
    1266 [ +  + ][ +  + ]:         70 :       && ((acc->gpg_decrypt_pw == NULL || !strlen(acc->gpg_decrypt_pw))
    1267         [ +  + ]:         54 :           && acc->gpg_allow_no_pw == 0))
    1268 [ +  + ][ -  + ]:       1687 :       || (acc->use_rijndael == 0 && acc->use_gpg == 0 && acc->gpg_allow_no_pw == 0))
    1269                 :            :     {
    1270                 :         16 :         log_msg(LOG_ERR,
    1271                 :            :             "[*] No keys found for access stanza source: '%s'", acc->source
    1272                 :            :         );
    1273                 :         16 :         return(0);
    1274                 :            :     }
    1275                 :            : 
    1276 [ +  + ][ +  - ]:       1687 :     if(acc->use_rijndael && acc->key != NULL)
    1277                 :            :     {
    1278         [ +  + ]:       1633 :         if((acc->encryption_mode == FKO_ENC_MODE_CBC_LEGACY_IV)
    1279         [ +  + ]:         23 :                 && (acc->key_len > 16))
    1280                 :            :         {
    1281                 :          1 :             log_msg(LOG_INFO,
    1282                 :            :                 "Warning: truncating encryption key in legacy mode to 16 bytes for access stanza source: '%s'",
    1283                 :            :                 acc->source
    1284                 :            :             );
    1285                 :          1 :             acc->key_len = 16;
    1286                 :            :         }
    1287                 :            :     }
    1288                 :            : 
    1289 [ +  + ][ +  - ]:       1687 :     if((acc->hmac_key_len) != 0 && (acc->hmac_key != NULL))
    1290                 :            :     {
    1291 [ +  + ][ +  - ]:        331 :         if((acc->key != NULL) && (acc->key_len != 0)
    1292         [ +  + ]:        301 :                 && (acc->key_len == acc->hmac_key_len))
    1293                 :            :         {
    1294         [ +  + ]:          5 :             if(memcmp(acc->key, acc->hmac_key, acc->hmac_key_len) == 0)
    1295                 :            :             {
    1296                 :          1 :                 log_msg(LOG_ERR,
    1297                 :            :                     "[*] The encryption passphrase and HMAC key should not be identical for access stanza source: '%s'",
    1298                 :            :                     acc->source
    1299                 :            :                 );
    1300                 :          1 :                 return(0);
    1301                 :            :             }
    1302                 :            :         }
    1303         [ +  + ]:        326 :         else if((acc->gpg_allow_no_pw == 0)
    1304         [ +  + ]:        312 :                 && acc->gpg_decrypt_pw != NULL
    1305         [ +  + ]:         16 :                 && (strlen(acc->gpg_decrypt_pw) == acc->hmac_key_len))
    1306                 :            :         {
    1307         [ +  - ]:          1 :             if(memcmp(acc->gpg_decrypt_pw, acc->hmac_key, acc->hmac_key_len) == 0)
    1308                 :            :             {
    1309                 :          1 :                 log_msg(LOG_ERR,
    1310                 :            :                     "[*] The encryption passphrase and HMAC key should not be identical for access stanza source: '%s'",
    1311                 :            :                     acc->source
    1312                 :            :                 );
    1313                 :          1 :                 return(0);
    1314                 :            :             }
    1315                 :            :         }
    1316                 :            :     }
    1317                 :            : 
    1318                 :            : #if defined(FIREWALL_FIREWALLD) || defined(FIREWALL_IPTABLES)
    1319 [ +  + ][ -  + ]:       1685 :     if((acc->force_snat == 1 || acc->force_masquerade == 1)
    1320         [ +  + ]:         18 :             && acc->force_nat == 0)
    1321                 :            :     {
    1322         [ +  + ]:         12 :         if(acc->forward_all == 1)
    1323                 :            :         {
    1324                 :          8 :             add_acc_force_nat(opts, acc, "0.0.0.0 0", NULL);
    1325                 :            :         }
    1326                 :            :         else
    1327                 :            :         {
    1328                 :          4 :             log_msg(LOG_ERR,
    1329                 :            :                     "[*] FORCE_SNAT/FORCE_MASQUERADE requires either FORCE_NAT or FORWARD_ALL: '%s'",
    1330                 :            :                     acc->source
    1331                 :            :             );
    1332                 :          4 :             return(0);
    1333                 :            :         }
    1334                 :            :     }
    1335                 :            : #endif
    1336                 :            : 
    1337         [ +  + ]:       1681 :     if(acc->require_source_address == 0)
    1338                 :            :     {
    1339                 :       1679 :         log_msg(LOG_INFO,
    1340                 :            :             "Warning: REQUIRE_SOURCE_ADDRESS not enabled for access stanza source: '%s'",
    1341                 :            :             acc->source
    1342                 :            :         );
    1343                 :            :     }
    1344                 :            : 
    1345 [ +  + ][ +  - ]:       1681 :     if(user_pw != NULL && acc->cmd_exec_uid != 0 && acc->cmd_exec_gid == 0)
                 [ +  + ]
    1346                 :            :     {
    1347                 :          8 :         log_msg(LOG_INFO,
    1348                 :            :             "Setting gid to group associated with CMD_EXEC_USER '%s' for setgid() execution in stanza source: '%s'",
    1349                 :            :             acc->cmd_exec_user,
    1350                 :            :             acc->source
    1351                 :            :         );
    1352                 :          8 :         acc->cmd_exec_gid = user_pw->pw_gid;
    1353                 :            :     }
    1354                 :            : 
    1355         [ +  + ]:       1681 :     if(sudo_user_pw != NULL
    1356 [ +  - ][ +  + ]:          9 :             && acc->cmd_sudo_exec_uid != 0 && acc->cmd_sudo_exec_gid == 0)
    1357                 :            :     {
    1358                 :          7 :         log_msg(LOG_INFO,
    1359                 :            :             "Setting gid to group associated with CMD_SUDO_EXEC_USER '%s' in stanza source: '%s'",
    1360                 :            :             acc->cmd_sudo_exec_user,
    1361                 :            :             acc->source
    1362                 :            :         );
    1363                 :          7 :         acc->cmd_sudo_exec_gid = sudo_user_pw->pw_gid;
    1364                 :            :     }
    1365                 :            : 
    1366         [ +  + ]:       1681 :     if(acc->cmd_cycle_open != NULL)
    1367                 :            :     {
    1368         [ +  + ]:         24 :         if(acc->cmd_cycle_close == NULL)
    1369                 :            :         {
    1370                 :          1 :             log_msg(LOG_ERR,
    1371                 :            :                 "[*] Cannot set CMD_CYCLE_OPEN without also setting CMD_CYCLE_CLOSE: '%s'",
    1372                 :            :                 acc->source
    1373                 :            :             );
    1374                 :          1 :             return(0);
    1375                 :            :         }
    1376                 :            : 
    1377                 :            :         /* Allow the string "NONE" to short-circuit close command execution.
    1378                 :            :         */
    1379         [ +  + ]:         23 :         if(strncmp(acc->cmd_cycle_close, "NONE", 4) == 0)
    1380                 :          1 :             acc->cmd_cycle_do_close = 0;
    1381                 :            : 
    1382 [ +  + ][ +  + ]:         23 :         if(acc->cmd_cycle_timer == 0 && acc->cmd_cycle_do_close)
    1383                 :            :         {
    1384                 :          1 :             log_msg(LOG_ERR,
    1385                 :            :                 "[*] Must set the CMD_CYCLE_TIMER for command cycle functionality: '%s'",
    1386                 :            :                 acc->source
    1387                 :            :             );
    1388                 :          1 :             return(0);
    1389                 :            :         }
    1390         [ +  + ]:         22 :         if(strlen(acc->cmd_cycle_open) >= CMD_CYCLE_BUFSIZE)
    1391                 :            :         {
    1392                 :          1 :             log_msg(LOG_ERR,
    1393                 :            :                 "[*] CMD_CYCLE_OPEN command is too long: '%s'",
    1394                 :            :                 acc->source
    1395                 :            :             );
    1396                 :          1 :             return(0);
    1397                 :            :         }
    1398                 :            :     }
    1399                 :            : 
    1400         [ +  + ]:       1678 :     if(acc->cmd_cycle_close != NULL)
    1401                 :            :     {
    1402         [ +  + ]:         22 :         if(acc->cmd_cycle_open == NULL)
    1403                 :            :         {
    1404                 :          1 :             log_msg(LOG_ERR,
    1405                 :            :                 "[*] Cannot set CMD_CYCLE_CLOSE without also setting CMD_CYCLE_OPEN: '%s'",
    1406                 :            :                 acc->source
    1407                 :            :             );
    1408                 :          1 :             return(0);
    1409                 :            :         }
    1410         [ +  + ]:         21 :         if(strlen(acc->cmd_cycle_close) >= CMD_CYCLE_BUFSIZE)
    1411                 :            :         {
    1412                 :          1 :             log_msg(LOG_ERR,
    1413                 :            :                 "[*] CMD_CYCLE_CLOSE command is too long: '%s'",
    1414                 :            :                 acc->source
    1415                 :            :             );
    1416                 :          1 :             return(0);
    1417                 :            :         }
    1418                 :            :     }
    1419                 :            : 
    1420                 :            :     /* For any non-command cycle stanza, we enable global firewall handling
    1421                 :            :     */
    1422         [ +  + ]:       1676 :     if(acc->cmd_cycle_open == NULL)
    1423                 :       1656 :         opts->enable_fw = 1;
    1424                 :            : 
    1425                 :            :     return(1);
    1426                 :            : }
    1427                 :            : 
    1428                 :            : int
    1429                 :          8 : parse_access_folder(fko_srv_options_t *opts, char *access_folder, int *depth)
    1430                 :            : {
    1431                 :            :     char            *extension;
    1432                 :            :     DIR             *dir_ptr;
    1433                 :            : 
    1434                 :          8 :     char            include_file[MAX_PATH_LEN] = {0};
    1435                 :            :     struct dirent  *dp;
    1436                 :            : 
    1437                 :          8 :     chop_char(access_folder, PATH_SEP);
    1438                 :            : 
    1439                 :          8 :     dir_ptr = opendir(access_folder);
    1440                 :            : 
    1441                 :            :     //grab the file names in the directory and loop through them
    1442         [ +  + ]:          8 :     if (dir_ptr == NULL)
    1443                 :            :     {
    1444                 :          2 :         log_msg(LOG_ERR, "[*] Access folder: '%s' could not be opened.", access_folder);
    1445                 :          2 :         return EXIT_FAILURE;
    1446                 :            :     }
    1447         [ +  + ]:         63 :     while ((dp = readdir(dir_ptr)) != NULL) {
    1448                 :         57 :         extension = (strrchr(dp->d_name, '.')); // Capture just the extension
    1449 [ +  + ][ +  + ]:         57 :         if (extension && !strncmp(extension, ".conf", 5))
    1450                 :            :         {
    1451         [ -  + ]:          2 :             if (strlen(access_folder) + 1 + strlen(dp->d_name) > MAX_PATH_LEN - 1) //Bail out rather than write past the end of include_file
    1452                 :            :             {
    1453                 :          0 :                 closedir(dir_ptr);
    1454                 :          0 :                 return EXIT_FAILURE;
    1455                 :            :             }
    1456                 :          2 :             strlcpy(include_file, access_folder, sizeof(include_file)); //construct the full path
    1457                 :          2 :             strlcat(include_file, "/", sizeof(include_file));
    1458                 :          2 :             strlcat(include_file, dp->d_name, sizeof(include_file));
    1459         [ -  + ]:          2 :             if (parse_access_file(opts, include_file, depth) == EXIT_FAILURE)
    1460                 :            :             {
    1461                 :          0 :                 closedir(dir_ptr);
    1462                 :         57 :                 return EXIT_FAILURE;
    1463                 :            :             }
    1464                 :            :         }
    1465                 :            :     }
    1466                 :          6 :     closedir(dir_ptr);
    1467                 :          6 :     return EXIT_SUCCESS;
    1468                 :            : }
    1469                 :            : 
    1470                 :            : /* Read and parse the access file, popluating the access data as we go.
    1471                 :            : */
    1472                 :            : int
    1473                 :       1691 : parse_access_file(fko_srv_options_t *opts, char *access_filename, int *depth)
    1474                 :            : {
    1475                 :            :     FILE           *file_ptr;
    1476                 :            :     char           *ndx;
    1477                 :            :     int             is_err;
    1478                 :       1691 :     unsigned int    num_lines = 0;
    1479                 :            : 
    1480                 :       1691 :     char            access_line_buf[MAX_LINE_LEN] = {0};
    1481                 :       1691 :     char            var[MAX_LINE_LEN] = {0};
    1482                 :       1691 :     char            val[MAX_LINE_LEN] = {0};
    1483                 :            : 
    1484                 :       1691 :     struct passwd  *user_pw = NULL;
    1485                 :       1691 :     struct passwd  *sudo_user_pw = NULL;
    1486                 :            :     struct stat     st;
    1487                 :            : 
    1488                 :       1691 :     acc_stanza_t   *curr_acc = NULL;
    1489                 :            : 
    1490                 :            :     /* This allows us to limit include depth, and also tracks when we've returned to the root access.conf file.
    1491                 :            :     */
    1492                 :       1691 :     (*depth)++;
    1493                 :            : 
    1494                 :            :     /* First see if the access file exists.  If it doesn't, complain
    1495                 :            :      * and bail.
    1496                 :            :     */
    1497                 :            : #if HAVE_LSTAT
    1498         [ +  + ]:       1691 :     if(lstat(access_filename, &st) != 0)
    1499                 :            :     {
    1500                 :          1 :         log_msg(LOG_ERR, "[*] Access file: '%s' was not found.",
    1501                 :            :             access_filename);
    1502                 :            : 
    1503                 :          1 :         return EXIT_FAILURE;
    1504                 :            :     }
    1505                 :            : #elif HAVE_STAT
    1506                 :            :     if(stat(access_filename, &st) != 0)
    1507                 :            :     {
    1508                 :            :         log_msg(LOG_ERR, "[*] Access file: '%s' was not found.",
    1509                 :            :             access_filename);
    1510                 :            : 
    1511                 :            :         return EXIT_FAILURE;
    1512                 :            :     }
    1513                 :            : #endif
    1514                 :            : 
    1515         [ +  - ]:       1690 :     if(verify_file_perms_ownership(access_filename) != 1)
    1516                 :            :         return EXIT_FAILURE;
    1517                 :            : 
    1518                 :            :     /* A note on security here: Coverity flags the following fopen() as a
    1519                 :            :      * Time of check time of use (TOCTOU) bug with a low priority due to the
    1520                 :            :      * previous stat() call above.  I.e., the access.conf file on disk could
    1521                 :            :      * have been changed between the stat() and the fopen() causing a TOCTOU
    1522                 :            :      * bug.  While technically this is true, the return value of fopen() is
    1523                 :            :      * also checked below so stat() success does not imply we assume fopen()
    1524                 :            :      * success.  Also, we could just remove the stat() and
    1525                 :            :      * verify_file_perms_ownership() calls above to "fix" the bug, but this
    1526                 :            :      * would actually make things easier for an attacker that has already
    1527                 :            :      * compromised the local system since access.conf could be changed to, say,
    1528                 :            :      * a symbolic link (for which verify_file_perms_ownership() throws a
    1529                 :            :      * warning), and then there is no race at all before the fopen().  I.e.
    1530                 :            :      * forcing an attacker to do the race makes things harder for them.
    1531                 :            :     */
    1532         [ +  + ]:       1690 :     if ((file_ptr = fopen(access_filename, "r")) == NULL)
    1533                 :            :     {
    1534                 :          3 :         log_msg(LOG_ERR, "[*] Could not open access file: %s",
    1535                 :            :             access_filename);
    1536                 :          3 :         perror(NULL);
    1537                 :            : 
    1538                 :          3 :         return EXIT_FAILURE;
    1539                 :            :     }
    1540                 :            : 
    1541                 :       1687 :     log_msg(LOG_DEBUG, "Opened access file: %s", access_filename);
    1542                 :            : 
    1543                 :            :     /* Initialize the access list
    1544                 :            :     */
    1545                 :       1687 :     acc_stanza_init(opts);
    1546                 :            : 
    1547                 :            :     /* Now walk through access file pulling the access entries into the
    1548                 :            :      * current stanza.
    1549                 :            :     */
    1550         [ +  + ]:       9382 :     while ((fgets(access_line_buf, MAX_LINE_LEN, file_ptr)) != NULL)
    1551                 :            :     {
    1552                 :       6046 :         num_lines++;
    1553                 :       6046 :         access_line_buf[MAX_LINE_LEN-1] = '\0';
    1554                 :            : 
    1555                 :            :         /* Get past comments and empty lines (note: we only look at the
    1556                 :            :          * first character.
    1557                 :            :         */
    1558 [ +  + ][ +  - ]:       6046 :         if(IS_EMPTY_LINE(access_line_buf[0]))
         [ +  - ][ -  + ]
    1559                 :         38 :             continue;
    1560                 :            : 
    1561         [ +  + ]:       6008 :         if(sscanf(access_line_buf, "%s %[^;\n\r]", var, val) != 2)
    1562                 :            :         {
    1563                 :          1 :             log_msg(LOG_ERR,
    1564                 :            :                 "[*] Invalid access file entry in %s at line %i.\n - '%s'",
    1565                 :            :                 access_filename, num_lines, access_line_buf
    1566                 :            :             );
    1567                 :          1 :             fclose(file_ptr);
    1568                 :          1 :             return EXIT_FAILURE;
    1569                 :            :         }
    1570                 :            : 
    1571                 :            :         /* Remove any colon that may be on the end of the var
    1572                 :            :         */
    1573         [ +  + ]:       6007 :         if((ndx = strrchr(var, ':')) != NULL)
    1574                 :         15 :             *ndx = '\0';
    1575                 :            : 
    1576                 :            :         /* Even though sscanf should automatically add a terminating
    1577                 :            :          * NULL byte, an assumption is made that the input arrays are
    1578                 :            :          * big enough, so we'll force a terminating NULL byte regardless
    1579                 :            :         */
    1580                 :       6007 :         var[MAX_LINE_LEN-1] = 0x0;
    1581                 :       6007 :         val[MAX_LINE_LEN-1] = 0x0;
    1582                 :            : 
    1583         [ +  + ]:       6007 :         if (opts->verbose > 3)
    1584                 :         31 :             log_msg(LOG_DEBUG,
    1585                 :            :                 "ACCESS FILE: %s, LINE: %s\tVar: %s, Val: '%s'",
    1586                 :            :                 access_filename, access_line_buf, var, val
    1587                 :            :             );
    1588                 :            : 
    1589                 :            :         /* Process the entry.
    1590                 :            :          *
    1591                 :            :          * NOTE: If a new access.conf parameter is created.  It also needs
    1592                 :            :          *       to be accounted for in the following if/if else construct.
    1593                 :            :         */
    1594         [ +  + ]:       6007 :         if(CONF_VAR_IS(var, "%include"))
    1595                 :            :         {
    1596         [ +  + ]:         22 :             if ((*depth) < MAX_DEPTH)
    1597                 :            :             {
    1598                 :         21 :                 log_msg(LOG_DEBUG, "[+] Processing include directive for file: '%s'", val);
    1599         [ +  + ]:         21 :                 if (parse_access_file(opts, val, depth) == EXIT_FAILURE)
    1600                 :            :                 {
    1601                 :          3 :                     fclose(file_ptr);
    1602                 :          3 :                     return EXIT_FAILURE;
    1603                 :            :                 }
    1604                 :            :             }
    1605                 :            :             else
    1606                 :            :             {
    1607                 :          1 :                 log_msg(LOG_ERR, "[*] Refusing to go deeper than 3 levels. Lost in Limbo: '%s'",
    1608                 :            :                         access_filename);
    1609                 :          1 :                 fclose(file_ptr);
    1610                 :          1 :                 return EXIT_FAILURE;
    1611                 :            :             }
    1612                 :            :         }
    1613         [ +  + ]:       5985 :         else if(CONF_VAR_IS(var, "%include_folder"))
    1614                 :            :         {
    1615                 :          6 :             log_msg(LOG_DEBUG, "[+] Processing include_folder directive for: '%s'", val);
    1616         [ +  + ]:          6 :             if (parse_access_folder(opts, val, depth) == EXIT_FAILURE)
    1617                 :            :             {
    1618                 :          2 :                 fclose(file_ptr);
    1619                 :          2 :                 return EXIT_FAILURE;
    1620                 :            :             }
    1621                 :            :         }
    1622         [ +  + ]:       5979 :         else if(CONF_VAR_IS(var, "SOURCE"))
    1623                 :            :         {
    1624                 :            :             /* If this is not the first stanza, sanity check the previous
    1625                 :            :              * stanza for the minimum required data.
    1626                 :            :             */
    1627         [ +  + ]:       1727 :             if(curr_acc != NULL) {
    1628         [ +  + ]:         42 :                 if(!acc_data_is_valid(opts, user_pw, sudo_user_pw, curr_acc))
    1629                 :            :                 {
    1630                 :          3 :                     log_msg(LOG_ERR, "[*] Data error in access file: '%s'",
    1631                 :            :                         access_filename);
    1632                 :          3 :                     fclose(file_ptr);
    1633                 :          3 :                     return EXIT_FAILURE;
    1634                 :            :                 }
    1635                 :            :             }
    1636                 :            : 
    1637                 :            :             /* Start new stanza.
    1638                 :            :             */
    1639                 :       1724 :             curr_acc = acc_stanza_add(opts);
    1640                 :       1720 :             add_acc_string(&(curr_acc->source), val, file_ptr, opts);
    1641                 :            :         }
    1642         [ +  + ]:       4252 :         else if (curr_acc == NULL)
    1643                 :            :         {
    1644                 :            :             /* The stanza must start with the "SOURCE" variable
    1645                 :            :             */
    1646                 :          2 :             continue;
    1647                 :            :         }
    1648         [ +  + ]:       4250 :         else if(CONF_VAR_IS(var, "%include_keys")) //Only valid options from this file are those defining keys.
    1649                 :            :         {
    1650                 :            :           // This directive is only valid within a SOURCE stanza
    1651                 :         20 :             log_msg(LOG_DEBUG, "[+] Processing include_keys directive for: '%s'", val);
    1652                 :         20 :             include_keys_file(curr_acc, val, opts);
    1653         [ +  + ]:         20 :             if(!acc_data_is_valid(opts, user_pw, sudo_user_pw, curr_acc))
    1654                 :            :             {
    1655                 :         12 :                 log_msg(LOG_DEBUG, "[*] Data error in included keyfile: '%s', skipping stanza.", val);
    1656                 :         12 :                 free_last_acc_stanza(opts);
    1657                 :         12 :                 curr_acc = NULL;
    1658                 :            :             }
    1659                 :            :         }
    1660         [ +  + ]:       4230 :         else if(CONF_VAR_IS(var, "DESTINATION"))
    1661                 :         20 :             add_acc_string(&(curr_acc->destination), val, file_ptr, opts);
    1662         [ +  + ]:       4210 :         else if(CONF_VAR_IS(var, "OPEN_PORTS"))
    1663                 :         38 :             add_acc_string(&(curr_acc->open_ports), val, file_ptr, opts);
    1664         [ +  + ]:       4172 :         else if(CONF_VAR_IS(var, "RESTRICT_PORTS"))
    1665                 :          1 :             add_acc_string(&(curr_acc->restrict_ports), val, file_ptr, opts);
    1666         [ +  + ]:       4171 :         else if(CONF_VAR_IS(var, "KEY"))
    1667                 :            :         {
    1668         [ +  + ]:       1347 :             if(strcasecmp(val, "__CHANGEME__") == 0)
    1669                 :            :             {
    1670                 :          1 :                 log_msg(LOG_ERR,
    1671                 :            :                     "[*] KEY value is not properly set in stanza source '%s' in access file: '%s'",
    1672                 :            :                     curr_acc->source, access_filename);
    1673                 :          1 :                 fclose(file_ptr);
    1674                 :          1 :                 return EXIT_FAILURE;
    1675                 :            :             }
    1676                 :       1346 :             add_acc_string(&(curr_acc->key), val, file_ptr, opts);
    1677                 :       1346 :             curr_acc->key_len = strlen(curr_acc->key);
    1678                 :       1346 :             add_acc_bool(&(curr_acc->use_rijndael), "Y");
    1679                 :            :         }
    1680         [ +  + ]:       2824 :         else if(CONF_VAR_IS(var, "KEY_BASE64"))
    1681                 :            :         {
    1682         [ +  + ]:        290 :             if(strcasecmp(val, "__CHANGEME__") == 0)
    1683                 :            :             {
    1684                 :          1 :                 log_msg(LOG_ERR,
    1685                 :            :                     "[*] KEY_BASE64 value is not properly set in stanza source '%s' in access file: '%s'",
    1686                 :            :                     curr_acc->source, access_filename);
    1687                 :          1 :                 fclose(file_ptr);
    1688                 :          1 :                 return EXIT_FAILURE;
    1689                 :            :             }
    1690         [ +  + ]:        289 :             if (! is_base64((unsigned char *) val, strlen(val)))
    1691                 :            :             {
    1692                 :          1 :                 log_msg(LOG_ERR,
    1693                 :            :                     "[*] KEY_BASE64 argument '%s' doesn't look like base64-encoded data.",
    1694                 :            :                     val);
    1695                 :          1 :                 fclose(file_ptr);
    1696                 :          1 :                 return EXIT_FAILURE;
    1697                 :            :             }
    1698                 :        288 :             add_acc_string(&(curr_acc->key_base64), val, file_ptr, opts);
    1699                 :        288 :             add_acc_b64_string(&(curr_acc->key), &(curr_acc->key_len),
    1700                 :        288 :                     curr_acc->key_base64, file_ptr, opts);
    1701                 :        288 :             add_acc_bool(&(curr_acc->use_rijndael), "Y");
    1702                 :            :         }
    1703                 :            :         /* HMAC digest type */
    1704         [ +  + ]:       2534 :         else if(CONF_VAR_IS(var, "HMAC_DIGEST_TYPE"))
    1705                 :            :         {
    1706                 :         64 :             curr_acc->hmac_type = hmac_digest_strtoint(val);
    1707         [ +  + ]:         64 :             if(curr_acc->hmac_type < 0)
    1708                 :            :             {
    1709                 :          1 :                 log_msg(LOG_ERR,
    1710                 :            :                     "[*] HMAC_DIGEST_TYPE argument '%s' must be one of {md5,sha1,sha256,sha384,sha512,sha3_256,sha3_512}",
    1711                 :            :                     val);
    1712                 :          1 :                 fclose(file_ptr);
    1713                 :          1 :                 return EXIT_FAILURE;
    1714                 :            :             }
    1715                 :            :         }
    1716         [ +  + ]:       2470 :         else if(CONF_VAR_IS(var, "HMAC_KEY_BASE64"))
    1717                 :            :         {
    1718         [ +  + ]:        318 :             if(strcasecmp(val, "__CHANGEME__") == 0)
    1719                 :            :             {
    1720                 :          1 :                 log_msg(LOG_ERR,
    1721                 :            :                     "[*] HMAC_KEY_BASE64 value is not properly set in stanza source '%s' in access file: '%s'",
    1722                 :            :                     curr_acc->source, opts->config[CONF_ACCESS_FILE]);
    1723                 :          1 :                 fclose(file_ptr);
    1724                 :          1 :                 return EXIT_FAILURE;
    1725                 :            :             }
    1726         [ +  + ]:        317 :             if (! is_base64((unsigned char *) val, strlen(val)))
    1727                 :            :             {
    1728                 :          1 :                 log_msg(LOG_ERR,
    1729                 :            :                     "[*] HMAC_KEY_BASE64 argument '%s' doesn't look like base64-encoded data.",
    1730                 :            :                     val);
    1731                 :          1 :                 fclose(file_ptr);
    1732                 :          1 :                 return EXIT_FAILURE;
    1733                 :            :             }
    1734                 :        316 :             add_acc_string(&(curr_acc->hmac_key_base64), val, file_ptr, opts);
    1735                 :        316 :             add_acc_b64_string(&(curr_acc->hmac_key), &(curr_acc->hmac_key_len),
    1736                 :        316 :                     curr_acc->hmac_key_base64, file_ptr, opts);
    1737                 :            :         }
    1738         [ +  + ]:       2152 :         else if(CONF_VAR_IS(var, "HMAC_KEY"))
    1739                 :            :         {
    1740         [ +  + ]:         13 :             if(strcasecmp(val, "__CHANGEME__") == 0)
    1741                 :            :             {
    1742                 :          1 :                 log_msg(LOG_ERR,
    1743                 :            :                     "[*] HMAC_KEY value is not properly set in stanza source '%s' in access file: '%s'",
    1744                 :            :                     curr_acc->source, opts->config[CONF_ACCESS_FILE]);
    1745                 :          1 :                 fclose(file_ptr);
    1746                 :          1 :                 return EXIT_FAILURE;
    1747                 :            :             }
    1748                 :         12 :             add_acc_string(&(curr_acc->hmac_key), val, file_ptr, opts);
    1749                 :         12 :             curr_acc->hmac_key_len = strlen(curr_acc->hmac_key);
    1750                 :            :         }
    1751         [ +  + ]:       2139 :         else if(CONF_VAR_IS(var, "FW_ACCESS_TIMEOUT"))
    1752                 :            :         {
    1753                 :       1582 :             curr_acc->fw_access_timeout = strtol_wrapper(val, 0,
    1754                 :            :                     RCHK_MAX_FW_TIMEOUT, NO_EXIT_UPON_ERR, &is_err);
    1755         [ +  + ]:       1582 :             if(is_err != FKO_SUCCESS)
    1756                 :            :             {
    1757                 :          1 :                 log_msg(LOG_ERR,
    1758                 :            :                     "[*] FW_ACCESS_TIMEOUT value not in range.");
    1759                 :          1 :                 fclose(file_ptr);
    1760                 :          1 :                 return EXIT_FAILURE;
    1761                 :            :             }
    1762                 :            :         }
    1763         [ +  + ]:        557 :         else if(CONF_VAR_IS(var, "ENCRYPTION_MODE"))
    1764                 :            :         {
    1765         [ +  + ]:         28 :             if((curr_acc->encryption_mode = enc_mode_strtoint(val)) < 0)
    1766                 :            :             {
    1767                 :          1 :                 log_msg(LOG_ERR,
    1768                 :            :                     "[*] Unrecognized ENCRYPTION_MODE '%s', use {CBC,CTR,legacy,Asymmetric}",
    1769                 :            :                     val);
    1770                 :          1 :                 fclose(file_ptr);
    1771                 :          1 :                 return EXIT_FAILURE;
    1772                 :            :             }
    1773                 :            :         }
    1774         [ +  + ]:        529 :         else if(CONF_VAR_IS(var, "ENABLE_CMD_EXEC"))
    1775                 :            :         {
    1776                 :         21 :             add_acc_bool(&(curr_acc->enable_cmd_exec), val);
    1777                 :            :         }
    1778         [ +  + ]:        508 :         else if(CONF_VAR_IS(var, "ENABLE_CMD_SUDO_EXEC"))
    1779                 :            :         {
    1780                 :          9 :             add_acc_bool(&(curr_acc->enable_cmd_sudo_exec), val);
    1781                 :            :         }
    1782         [ +  + ]:        499 :         else if(CONF_VAR_IS(var, "CMD_SUDO_EXEC_USER"))
    1783                 :          9 :             add_acc_user(&(curr_acc->cmd_sudo_exec_user),
    1784                 :            :                         &(curr_acc->cmd_sudo_exec_uid), &sudo_user_pw,
    1785                 :            :                         val, "CMD_SUDO_EXEC_USER", file_ptr, opts);
    1786         [ +  + ]:        490 :         else if(CONF_VAR_IS(var, "CMD_SUDO_EXEC_GROUP"))
    1787                 :          3 :             add_acc_group(&(curr_acc->cmd_sudo_exec_group),
    1788                 :            :                         &(curr_acc->cmd_sudo_exec_gid), val,
    1789                 :            :                         "CMD_SUDO_EXEC_GROUP", file_ptr, opts);
    1790         [ +  + ]:        487 :         else if(CONF_VAR_IS(var, "CMD_EXEC_USER"))
    1791                 :         13 :             add_acc_user(&(curr_acc->cmd_exec_user),
    1792                 :            :                         &(curr_acc->cmd_exec_uid), &user_pw,
    1793                 :            :                         val, "CMD_EXEC_USER", file_ptr, opts);
    1794         [ +  + ]:        474 :         else if(CONF_VAR_IS(var, "CMD_EXEC_GROUP"))
    1795                 :          6 :             add_acc_group(&(curr_acc->cmd_exec_group),
    1796                 :            :                         &(curr_acc->cmd_exec_gid), val,
    1797                 :            :                         "CMD_EXEC_GROUP", file_ptr, opts);
    1798         [ +  + ]:        468 :         else if(CONF_VAR_IS(var, "CMD_CYCLE_OPEN"))
    1799                 :            :         {
    1800                 :         25 :             add_acc_string(&(curr_acc->cmd_cycle_open), val, file_ptr, opts);
    1801                 :         25 :             curr_acc->cmd_cycle_do_close = 1; /* default, will be validated */
    1802                 :            :         }
    1803         [ +  + ]:        443 :         else if(CONF_VAR_IS(var, "CMD_CYCLE_CLOSE"))
    1804                 :         25 :             add_acc_string(&(curr_acc->cmd_cycle_close), val, file_ptr, opts);
    1805         [ +  + ]:        418 :         else if(CONF_VAR_IS(var, "CMD_CYCLE_TIMER"))
    1806                 :            :         {
    1807                 :         22 :             curr_acc->cmd_cycle_timer = strtol_wrapper(val,
    1808                 :            :                     RCHK_MIN_CMD_CYCLE_TIMER, RCHK_MAX_CMD_CYCLE_TIMER,
    1809                 :            :                     NO_EXIT_UPON_ERR, &is_err);
    1810         [ +  + ]:         22 :             if(is_err != FKO_SUCCESS)
    1811                 :            :             {
    1812                 :          1 :                 log_msg(LOG_ERR,
    1813                 :            :                     "[*] CMD_CYCLE_TIMER value not in range [1,%d].",
    1814                 :            :                     RCHK_MAX_CMD_CYCLE_TIMER);
    1815                 :          1 :                 fclose(file_ptr);
    1816                 :          1 :                 return EXIT_FAILURE;
    1817                 :            :             }
    1818                 :            :         }
    1819         [ +  + ]:        396 :         else if(CONF_VAR_IS(var, "REQUIRE_USERNAME"))
    1820                 :         15 :             add_acc_string(&(curr_acc->require_username), val, file_ptr, opts);
    1821         [ +  + ]:        381 :         else if(CONF_VAR_IS(var, "REQUIRE_SOURCE_ADDRESS"))
    1822                 :          2 :             add_acc_bool(&(curr_acc->require_source_address), val);
    1823         [ +  + ]:        379 :         else if(CONF_VAR_IS(var, "REQUIRE_SOURCE"))  /* synonym for REQUIRE_SOURCE_ADDRESS */
    1824                 :          1 :             add_acc_bool(&(curr_acc->require_source_address), val);
    1825         [ +  + ]:        378 :         else if(CONF_VAR_IS(var, "GPG_HOME_DIR"))
    1826                 :            :         {
    1827         [ +  + ]:         76 :             if (is_valid_dir(val))
    1828                 :            :             {
    1829                 :         75 :                 add_acc_string(&(curr_acc->gpg_home_dir), val, file_ptr, opts);
    1830                 :            :             }
    1831                 :            :             else
    1832                 :            :             {
    1833                 :          1 :                 log_msg(LOG_ERR,
    1834                 :            :                     "[*] GPG_HOME_DIR directory '%s' stat()/existence problem in stanza source '%s' in access file: '%s'",
    1835                 :            :                     val, curr_acc->source, access_filename);
    1836                 :          1 :                 fclose(file_ptr);
    1837                 :          1 :                 return EXIT_FAILURE;
    1838                 :            :             }
    1839                 :            :         }
    1840         [ +  + ]:        302 :         else if(CONF_VAR_IS(var, "GPG_EXE"))
    1841                 :          1 :             add_acc_string(&(curr_acc->gpg_exe), val, file_ptr, opts);
    1842         [ +  + ]:        301 :         else if(CONF_VAR_IS(var, "GPG_DECRYPT_ID"))
    1843                 :         76 :             add_acc_string(&(curr_acc->gpg_decrypt_id), val, file_ptr, opts);
    1844         [ +  + ]:        225 :         else if(CONF_VAR_IS(var, "GPG_DECRYPT_PW"))
    1845                 :            :         {
    1846         [ +  + ]:         43 :             if(strcasecmp(val, "__CHANGEME__") == 0)
    1847                 :            :             {
    1848                 :          1 :                 log_msg(LOG_ERR,
    1849                 :            :                     "[*] GPG_DECRYPT_PW value is not properly set in stanza source '%s' in access file: '%s'",
    1850                 :            :                     curr_acc->source, access_filename);
    1851                 :          1 :                 fclose(file_ptr);
    1852                 :          1 :                 return EXIT_FAILURE;
    1853                 :            :             }
    1854                 :         42 :             add_acc_string(&(curr_acc->gpg_decrypt_pw), val, file_ptr, opts);
    1855                 :         42 :             add_acc_bool(&(curr_acc->use_gpg), "Y");
    1856                 :            :         }
    1857         [ +  + ]:        182 :         else if(CONF_VAR_IS(var, "GPG_ALLOW_NO_PW"))
    1858                 :            :         {
    1859                 :         36 :             add_acc_bool(&(curr_acc->gpg_allow_no_pw), val);
    1860         [ +  - ]:         36 :             if(curr_acc->gpg_allow_no_pw == 1)
    1861                 :            :             {
    1862                 :         36 :                 add_acc_bool(&(curr_acc->use_gpg), "Y");
    1863                 :         36 :                 add_acc_string(&(curr_acc->gpg_decrypt_pw), "", file_ptr, opts);
    1864                 :            :             }
    1865                 :            :         }
    1866         [ +  + ]:        146 :         else if(CONF_VAR_IS(var, "GPG_REQUIRE_SIG"))
    1867                 :            :         {
    1868                 :          2 :             add_acc_bool(&(curr_acc->gpg_require_sig), val);
    1869                 :            :         }
    1870         [ +  + ]:        144 :         else if(CONF_VAR_IS(var, "GPG_DISABLE_SIG"))
    1871                 :            :         {
    1872                 :          3 :             add_acc_bool(&(curr_acc->gpg_disable_sig), val);
    1873                 :            :         }
    1874         [ +  + ]:        141 :         else if(CONF_VAR_IS(var, "GPG_IGNORE_SIG_VERIFY_ERROR"))
    1875                 :            :         {
    1876                 :          1 :             add_acc_bool(&(curr_acc->gpg_ignore_sig_error), val);
    1877                 :            :         }
    1878         [ +  + ]:        140 :         else if(CONF_VAR_IS(var, "GPG_REMOTE_ID"))
    1879                 :         71 :             add_acc_string(&(curr_acc->gpg_remote_id), val, file_ptr, opts);
    1880         [ +  + ]:         69 :         else if(CONF_VAR_IS(var, "GPG_FINGERPRINT_ID"))
    1881                 :          4 :             add_acc_string(&(curr_acc->gpg_remote_fpr), val, file_ptr, opts);
    1882         [ +  + ]:         65 :         else if(CONF_VAR_IS(var, "ACCESS_EXPIRE"))
    1883                 :            :         {
    1884         [ +  + ]:          3 :             if (add_acc_expire_time(opts, &(curr_acc->access_expire_time), val) != 1)
    1885                 :            :             {
    1886                 :          1 :                 fclose(file_ptr);
    1887                 :          1 :                 return EXIT_FAILURE;
    1888                 :            :             }
    1889                 :            :         }
    1890         [ +  + ]:         62 :         else if(CONF_VAR_IS(var, "ACCESS_EXPIRE_EPOCH"))
    1891                 :          2 :             add_acc_expire_time_epoch(opts,
    1892                 :            :                     &(curr_acc->access_expire_time), val, file_ptr);
    1893         [ +  + ]:         60 :         else if(CONF_VAR_IS(var, "FORCE_NAT"))
    1894                 :            :         {
    1895                 :            : #if FIREWALL_FIREWALLD
    1896         [ +  + ]:         21 :             if(strncasecmp(opts->config[CONF_ENABLE_FIREWD_FORWARDING], "Y", 1) !=0
    1897         [ +  + ]:          5 :                 && (strncasecmp(opts->config[CONF_ENABLE_FIREWD_LOCAL_NAT], "Y", 1) !=0 ))
    1898                 :            :             {
    1899                 :          1 :                 log_msg(LOG_ERR,
    1900                 :            :                     "[*] FORCE_NAT requires either ENABLE_FIREWD_FORWARDING or ENABLE_FIREWD_LOCAL_NAT in fwknopd.conf");
    1901                 :          1 :                 fclose(file_ptr);
    1902                 :          1 :                 return EXIT_FAILURE;
    1903                 :            :             }
    1904                 :         20 :             add_acc_force_nat(opts, curr_acc, val, file_ptr);
    1905                 :            : #elif FIREWALL_IPTABLES
    1906                 :            :             if(strncasecmp(opts->config[CONF_ENABLE_IPT_FORWARDING], "Y", 1) !=0
    1907                 :            :                 && (strncasecmp(opts->config[CONF_ENABLE_IPT_LOCAL_NAT], "Y", 1) !=0 ))
    1908                 :            :             {
    1909                 :            :                 log_msg(LOG_ERR,
    1910                 :            :                     "[*] FORCE_NAT requires either ENABLE_IPT_FORWARDING or ENABLE_IPT_LOCAL_NAT in fwknopd.conf");
    1911                 :            :                 fclose(file_ptr);
    1912                 :            :                 return EXIT_FAILURE;
    1913                 :            :             }
    1914                 :            :             add_acc_force_nat(opts, curr_acc, val, file_ptr);
    1915                 :            : #else
    1916                 :            :             log_msg(LOG_ERR,
    1917                 :            :                 "[*] FORCE_NAT not supported.");
    1918                 :            :             fclose(file_ptr);
    1919                 :            :             return EXIT_FAILURE;
    1920                 :            : #endif
    1921                 :            :         }
    1922         [ +  + ]:         39 :         else if(CONF_VAR_IS(var, "FORCE_SNAT"))
    1923                 :            :         {
    1924                 :            : #if FIREWALL_FIREWALLD
    1925         [ +  + ]:         13 :             if(strncasecmp(opts->config[CONF_ENABLE_FIREWD_FORWARDING], "Y", 1) !=0
    1926         [ +  - ]:          1 :                 && (strncasecmp(opts->config[CONF_ENABLE_FIREWD_LOCAL_NAT], "Y", 1) !=0 ))
    1927                 :            :             {
    1928                 :          1 :                 log_msg(LOG_ERR,
    1929                 :            :                     "[*] FORCE_SNAT requires either ENABLE_FIREWD_FORWARDING or ENABLE_FIREWD_LOCAL_NAT in fwknopd.conf");
    1930                 :          1 :                 fclose(file_ptr);
    1931                 :          1 :                 return EXIT_FAILURE;
    1932                 :            :             }
    1933                 :         12 :             add_acc_force_snat(opts, curr_acc, val, file_ptr);
    1934                 :            : #elif FIREWALL_IPTABLES
    1935                 :            :             if(strncasecmp(opts->config[CONF_ENABLE_IPT_FORWARDING], "Y", 1) !=0
    1936                 :            :                 && (strncasecmp(opts->config[CONF_ENABLE_IPT_LOCAL_NAT], "Y", 1) !=0 ))
    1937                 :            :             {
    1938                 :            :                 log_msg(LOG_ERR,
    1939                 :            :                     "[*] FORCE_SNAT requires either ENABLE_IPT_FORWARDING or ENABLE_IPT_LOCAL_NAT in fwknopd.conf");
    1940                 :            :                 fclose(file_ptr);
    1941                 :            :                 return EXIT_FAILURE;
    1942                 :            :             }
    1943                 :            :             add_acc_force_snat(opts, curr_acc, val, file_ptr);
    1944                 :            : #else
    1945                 :            :             log_msg(LOG_ERR,
    1946                 :            :                 "[*] FORCE_SNAT not supported.");
    1947                 :            :             fclose(file_ptr);
    1948                 :            :             return EXIT_FAILURE;
    1949                 :            : #endif
    1950                 :            :         }
    1951         [ +  + ]:         26 :         else if(CONF_VAR_IS(var, "FORCE_MASQUERADE"))
    1952                 :            :         {
    1953                 :          8 :             add_acc_bool(&(curr_acc->force_masquerade), val);
    1954                 :          8 :             add_acc_bool(&(curr_acc->force_snat), val);
    1955                 :            :         }
    1956         [ +  + ]:         18 :         else if(CONF_VAR_IS(var, "DISABLE_DNAT"))
    1957                 :            :         {
    1958                 :          7 :             add_acc_bool(&(curr_acc->disable_dnat), val);
    1959                 :            :         }
    1960         [ +  + ]:         11 :         else if(CONF_VAR_IS(var, "FORWARD_ALL"))
    1961                 :            :         {
    1962                 :         10 :             add_acc_bool(&(curr_acc->forward_all), val);
    1963                 :            :         }
    1964                 :            :         else
    1965                 :            :         {
    1966                 :       6008 :             log_msg(LOG_ERR,
    1967                 :            :                 "[*] Ignoring unknown access parameter: '%s' in %s",
    1968                 :            :                 var, access_filename
    1969                 :            :             );
    1970                 :            :         }
    1971                 :            :     }
    1972                 :            : 
    1973                 :       1649 :     fclose(file_ptr);
    1974         [ +  - ]:       1649 :     if(*depth > 0)
    1975                 :       1649 :         (*depth)--;
    1976                 :            : 
    1977         [ +  + ]:       1649 :     if(*depth == 0) //means we just closed the root access.conf
    1978                 :            :     {
    1979         [ +  + ]:       1631 :         if(curr_acc != NULL)
    1980                 :            :         {
    1981         [ +  + ]:       1623 :             if(!acc_data_is_valid(opts, user_pw, sudo_user_pw, curr_acc))
    1982                 :            :             {
    1983                 :         12 :                 log_msg(LOG_ERR,
    1984                 :            :                     "[*] Data error in access file: '%s'",
    1985                 :            :                     access_filename);
    1986                 :         12 :                 return EXIT_FAILURE;
    1987                 :            :             }
    1988                 :            :         }
    1989         [ +  + ]:          8 :         else if (opts->acc_stanzas == NULL)
    1990                 :            :         {
    1991                 :          6 :             log_msg(LOG_ERR,
    1992                 :            :                 "[*] Could not find valid SOURCE stanza in access file: '%s'",
    1993                 :            :                 opts->config[CONF_ACCESS_FILE]);
    1994                 :          6 :             return EXIT_FAILURE;
    1995                 :            :         }
    1996                 :            : 
    1997                 :            :         /* Expand our the expandable fields into their respective data buckets.
    1998                 :            :         */
    1999                 :       1613 :         expand_acc_ent_lists(opts);
    2000                 :            : 
    2001                 :            :         /* Make sure default values are set where needed.
    2002                 :            :         */
    2003                 :       1586 :         set_acc_defaults(opts);
    2004                 :            :     }
    2005                 :            :     else // this is an %included file
    2006                 :            :     {
    2007                 :            :         /* If this file had a stanza, check the last one.
    2008                 :            :          *
    2009                 :            :          *
    2010                 :            :         */
    2011         [ +  - ]:         18 :         if(curr_acc != NULL)
    2012                 :            :         {
    2013         [ -  + ]:         18 :             if(!acc_data_is_valid(opts, user_pw, sudo_user_pw, curr_acc))
    2014                 :            :             {
    2015                 :          0 :                 log_msg(LOG_ERR,
    2016                 :            :                     "[*] Data error in access file: '%s'",
    2017                 :            :                     access_filename);
    2018                 :          0 :                 return EXIT_FAILURE;
    2019                 :            :             }
    2020                 :            :         }
    2021                 :            :     }
    2022                 :            : 
    2023                 :            :     return EXIT_SUCCESS;
    2024                 :            : }
    2025                 :            : 
    2026                 :       1585 : int valid_access_stanzas(acc_stanza_t *acc)
    2027                 :            : {
    2028         [ +  + ]:       1585 :     if(acc == NULL)
    2029                 :            :         return 0;
    2030                 :            : 
    2031                 :            :     /* This is a basic check to ensure at least one access stanza
    2032                 :            :      * with the "source" variable populated, and this function is only
    2033                 :            :      * called after all access.conf files are processed. This allows
    2034                 :            :      * %include_folder processing to proceed against directories that
    2035                 :            :      * have files that are not access.conf files. Additional stronger
    2036                 :            :      * validations are done in acc_data_is_valid(), but this function
    2037                 :            :      * is only called when a "SOURCE" variable has been parsed out of
    2038                 :            :      * the file.
    2039                 :            :     */
    2040         [ +  + ]:       3218 :     while(acc)
    2041                 :            :     {
    2042 [ +  - ][ +  - ]:       1634 :         if(acc->source == NULL || acc->source[0] == '\0')
    2043                 :            :             return 0;
    2044                 :       1634 :         acc = acc->next;
    2045                 :            :     }
    2046                 :            :     return 1;
    2047                 :            : }
    2048                 :            : 
    2049                 :            : int
    2050                 :      31706 : compare_addr_list(acc_int_list_t *ip_list, const uint32_t ip)
    2051                 :            : {
    2052                 :      31706 :     int match = 0;
    2053                 :            : 
    2054         [ +  + ]:      31790 :     while(ip_list)
    2055                 :            :     {
    2056         [ +  + ]:      31777 :         if((ip & ip_list->mask) == (ip_list->maddr & ip_list->mask))
    2057                 :            :         {
    2058                 :            :             match = 1;
    2059                 :            :             break;
    2060                 :            :         }
    2061                 :            : 
    2062                 :         84 :         ip_list = ip_list->next;
    2063                 :            :     }
    2064                 :            : 
    2065                 :      31706 :     return(match);
    2066                 :            : }
    2067                 :            : 
    2068                 :            : /**
    2069                 :            :  * \brief Compares port lists
    2070                 :            :  *
    2071                 :            :  * Compare the contents of 2 port lists.  Return true on a match.
    2072                 :            :  * Match depends on the match_any flag.  if match_any is 1 then any
    2073                 :            :  * entry in the incoming data need only match one item to return true.
    2074                 :            :  * Otherwise all entries in the incoming data must have a corresponding
    2075                 :            :  * match in the access port_list.
    2076                 :            :  *
    2077                 :            :  * \param acc Pointer to the acc_stanza_t struct that holds the access stanzas
    2078                 :            :  * \param port_str pointer to the
    2079                 :            :  *
    2080                 :            :  * \return Returns true on a match
    2081                 :            :  *
    2082                 :            :  */
    2083                 :            : static int
    2084                 :         32 : compare_port_list(acc_port_list_t *in, acc_port_list_t *ac, const int match_any)
    2085                 :            : {
    2086                 :         32 :     int a_cnt = 0;
    2087                 :         32 :     int i_cnt = 0;
    2088                 :            : 
    2089                 :            :     acc_port_list_t *tlist;
    2090         [ +  + ]:         65 :     while(in)
    2091                 :            :     {
    2092                 :         35 :         i_cnt++;
    2093                 :            : 
    2094                 :         35 :         tlist = ac;
    2095         [ +  + ]:        131 :         while(tlist)
    2096                 :            :         {
    2097         [ +  + ]:         98 :             if(in->proto == tlist->proto && in->port == tlist->port)
    2098                 :            :             {
    2099                 :         31 :                 a_cnt++;
    2100         [ +  + ]:         31 :                 if(match_any == 1)
    2101                 :            :                     return(1);
    2102                 :            :             }
    2103                 :         96 :             tlist = tlist->next;
    2104                 :            :         }
    2105                 :         33 :         in = in->next;
    2106                 :            :     }
    2107                 :            : 
    2108                 :         30 :     return(i_cnt == a_cnt);
    2109                 :            : }
    2110                 :            : 
    2111                 :            : /* Take a proto/port string (or mulitple comma-separated strings) and check
    2112                 :            :  * them against the list for the given access stanza.
    2113                 :            :  *
    2114                 :            :  * Return 1 if we are allowed
    2115                 :            : */
    2116                 :            : int
    2117                 :        605 : acc_check_port_access(acc_stanza_t *acc, char *port_str)
    2118                 :            : {
    2119                 :        605 :     int             res = 1, ctr = 0;
    2120                 :            : 
    2121                 :        605 :     char            buf[ACCESS_BUF_LEN] = {0};
    2122                 :            :     char           *ndx, *start;
    2123                 :            : 
    2124                 :        605 :     acc_port_list_t *o_pl   = acc->oport_list;
    2125                 :        605 :     acc_port_list_t *r_pl   = acc->rport_list;
    2126                 :            : 
    2127                 :        605 :     acc_port_list_t *in_pl  = NULL;
    2128                 :            : 
    2129                 :        605 :     start = port_str;
    2130                 :            : 
    2131                 :            :     /* Create our own internal port_list from the incoming SPA data
    2132                 :            :      * for comparison.
    2133                 :            :     */
    2134         [ +  + ]:       5127 :     for(ndx = start; *ndx != '\0'; ndx++)
    2135                 :            :     {
    2136         [ +  + ]:       4522 :         if(*ndx == ',')
    2137                 :            :         {
    2138         [ +  - ]:         67 :             if((ctr >= ACCESS_BUF_LEN)
    2139         [ -  + ]:         67 :                     || (((ndx-start)+1) >= ACCESS_BUF_LEN))
    2140                 :            :             {
    2141                 :          0 :                 log_msg(LOG_ERR,
    2142                 :            :                     "[*] Unable to create acc_port_list from incoming data: %s",
    2143                 :            :                     port_str
    2144                 :            :                 );
    2145                 :          0 :                 free_acc_port_list(in_pl);
    2146                 :          0 :                 return(0);
    2147                 :            :             }
    2148                 :         67 :             strlcpy(buf, start, (ndx-start)+1);
    2149         [ -  + ]:         67 :             if(add_port_list_ent(&in_pl, buf) == 0)
    2150                 :            :             {
    2151                 :          0 :                 log_msg(LOG_ERR, "[*] Invalid proto/port string");
    2152                 :          0 :                 free_acc_port_list(in_pl);
    2153                 :          0 :                 return(0);
    2154                 :            :             }
    2155                 :            : 
    2156                 :         67 :             start = ndx+1;
    2157                 :         67 :             ctr = 0;
    2158                 :            :         }
    2159                 :       4522 :         ctr++;
    2160                 :            :     }
    2161         [ +  - ]:        605 :     if((ctr >= ACCESS_BUF_LEN)
    2162         [ -  + ]:        605 :             || (((ndx-start)+1) >= ACCESS_BUF_LEN))
    2163                 :            :     {
    2164                 :          0 :         log_msg(LOG_ERR,
    2165                 :            :             "[*] Unable to create acc_port_list from incoming data: %s",
    2166                 :            :             port_str
    2167                 :            :         );
    2168                 :          0 :         free_acc_port_list(in_pl);
    2169                 :          0 :         return(0);
    2170                 :            :     }
    2171                 :        605 :     strlcpy(buf, start, (ndx-start)+1);
    2172         [ -  + ]:        605 :     if(add_port_list_ent(&in_pl, buf) == 0)
    2173                 :            :     {
    2174                 :          0 :         log_msg(LOG_ERR, "[*] Invalid proto/port string");
    2175                 :          0 :         free_acc_port_list(in_pl);
    2176                 :          0 :         return 0;
    2177                 :            :     }
    2178                 :            : 
    2179         [ -  + ]:        605 :     if(in_pl == NULL)
    2180                 :            :     {
    2181                 :          0 :         log_msg(LOG_ERR,
    2182                 :            :             "[*] Unable to create acc_port_list from incoming data: %s", port_str
    2183                 :            :         );
    2184                 :          0 :         return(0);
    2185                 :            :     }
    2186                 :            : 
    2187                 :            :     /* Start with restricted ports (if any).  Any match (even if only one
    2188                 :            :      * entry) means not allowed.
    2189                 :            :     */
    2190 [ -  + ][ #  # ]:        605 :     if((acc->rport_list != NULL) && (compare_port_list(in_pl, r_pl, 1)))
    2191                 :            :     {
    2192                 :            :         res = 0;
    2193                 :            :         goto cleanup_and_bail;
    2194                 :            :     }
    2195                 :            : 
    2196                 :            :     /* For open port list, all must match.
    2197                 :            :     */
    2198 [ +  + ][ +  + ]:        605 :     if((acc->oport_list != NULL) && (!compare_port_list(in_pl, o_pl, 0)))
    2199                 :          3 :             res = 0;
    2200                 :            : 
    2201                 :            : cleanup_and_bail:
    2202                 :        605 :     free_acc_port_list(in_pl);
    2203                 :        605 :     return(res);
    2204                 :            : }
    2205                 :            : 
    2206                 :            : /* Dump the configuration
    2207                 :            : */
    2208                 :            : void
    2209                 :        523 : dump_access_list(const fko_srv_options_t *opts)
    2210                 :            : {
    2211                 :        523 :     int             i = 0;
    2212                 :            : 
    2213                 :        523 :     acc_stanza_t    *acc = opts->acc_stanzas;
    2214                 :            : 
    2215                 :        523 :     fprintf(stdout, "Current fwknopd access settings:\n");
    2216                 :            : 
    2217         [ +  - ]:        523 :     if(!acc)
    2218                 :            :     {
    2219                 :          0 :         fprintf(stderr, "\n    ** No Access Settings Defined **\n\n");
    2220                 :        523 :         return;
    2221                 :            :     }
    2222                 :            : 
    2223         [ +  + ]:       1083 :     while(acc)
    2224                 :            :     {
    2225 [ +  + ][ +  + ]:        581 :         fprintf(stdout,
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ -  + ][ +  + ]
                 [ +  + ]
    2226                 :            :             "SOURCE (%i):  %s\n"
    2227                 :            :             "==============================================================\n"
    2228                 :            :             "                DESTINATION:  %s\n"
    2229                 :            :             "                 OPEN_PORTS:  %s\n"
    2230                 :            :             "             RESTRICT_PORTS:  %s\n"
    2231                 :            :             "                        KEY:  %s\n"
    2232                 :            :             "                 KEY_BASE64:  %s\n"
    2233                 :            :             "                    KEY_LEN:  %d\n"
    2234                 :            :             "                   HMAC_KEY:  %s\n"
    2235                 :            :             "            HMAC_KEY_BASE64:  %s\n"
    2236                 :            :             "               HMAC_KEY_LEN:  %d\n"
    2237                 :            :             "           HMAC_DIGEST_TYPE:  %d\n"
    2238                 :            :             "          FW_ACCESS_TIMEOUT:  %i\n"
    2239                 :            :             "            ENABLE_CMD_EXEC:  %s\n"
    2240                 :            :             "       ENABLE_CMD_SUDO_EXEC:  %s\n"
    2241                 :            :             "         CMD_SUDO_EXEC_USER:  %s\n"
    2242                 :            :             "        CMD_SUDO_EXEC_GROUP:  %s\n"
    2243                 :            :             "              CMD_EXEC_USER:  %s\n"
    2244                 :            :             "             CMD_EXEC_GROUP:  %s\n"
    2245                 :            :             "             CMD_CYCLE_OPEN:  %s\n"
    2246                 :            :             "            CMD_CYCLE_CLOSE:  %s\n"
    2247                 :            :             "            CMD_CYCLE_TIMER:  %i\n"
    2248                 :            :             "           REQUIRE_USERNAME:  %s\n"
    2249                 :            :             "     REQUIRE_SOURCE_ADDRESS:  %s\n"
    2250                 :            :             "             FORCE_NAT (ip):  %s\n"
    2251                 :            :             "          FORCE_NAT (proto):  %s\n"
    2252                 :            :             "           FORCE_NAT (port):  %d\n"
    2253                 :            :             "            FORCE_SNAT (ip):  %s\n"
    2254                 :            :             "           FORCE_MASQUERADE:  %s\n"
    2255                 :            :             "               DISABLE_DNAT:  %s\n"
    2256                 :            :             "                FORWARD_ALL:  %s\n"
    2257                 :            :             "              ACCESS_EXPIRE:  %s"  /* asctime() adds a newline */
    2258                 :            :             "               GPG_HOME_DIR:  %s\n"
    2259                 :            :             "                    GPG_EXE:  %s\n"
    2260                 :            :             "             GPG_DECRYPT_ID:  %s\n"
    2261                 :            :             "             GPG_DECRYPT_PW:  %s\n"
    2262                 :            :             "            GPG_REQUIRE_SIG:  %s\n"
    2263                 :            :             "GPG_IGNORE_SIG_VERIFY_ERROR:  %s\n"
    2264                 :            :             "              GPG_REMOTE_ID:  %s\n"
    2265                 :            :             "         GPG_FINGERPRINT_ID:  %s\n",
    2266                 :            :             ++i,
    2267                 :            :             acc->source,
    2268                 :        560 :             (acc->destination == NULL) ? "<not set>" : acc->destination,
    2269                 :        560 :             (acc->open_ports == NULL) ? "<not set>" : acc->open_ports,
    2270                 :        560 :             (acc->restrict_ports == NULL) ? "<not set>" : acc->restrict_ports,
    2271                 :        560 :             (acc->key == NULL) ? "<not set>" : "<see the access.conf file>",
    2272                 :        560 :             (acc->key_base64 == NULL) ? "<not set>" : "<see the access.conf file>",
    2273                 :            :             acc->key_len ? acc->key_len : 0,
    2274                 :        560 :             (acc->hmac_key == NULL) ? "<not set>" : "<see the access.conf file>",
    2275                 :        560 :             (acc->hmac_key_base64 == NULL) ? "<not set>" : "<see the access.conf file>",
    2276                 :            :             acc->hmac_key_len ? acc->hmac_key_len : 0,
    2277                 :            :             acc->hmac_type,
    2278                 :            :             acc->fw_access_timeout,
    2279                 :        560 :             acc->enable_cmd_exec ? "Yes" : "No",
    2280                 :        560 :             acc->enable_cmd_sudo_exec ? "Yes" : "No",
    2281                 :        560 :             (acc->cmd_sudo_exec_user == NULL) ? "<not set>" : acc->cmd_sudo_exec_user,
    2282                 :        560 :             (acc->cmd_sudo_exec_group == NULL) ? "<not set>" : acc->cmd_sudo_exec_group,
    2283                 :        560 :             (acc->cmd_exec_user == NULL) ? "<not set>" : acc->cmd_exec_user,
    2284                 :        560 :             (acc->cmd_exec_group == NULL) ? "<not set>" : acc->cmd_exec_group,
    2285                 :        560 :             (acc->cmd_cycle_open == NULL) ? "<not set>" : acc->cmd_cycle_open,
    2286                 :        560 :             (acc->cmd_cycle_close == NULL) ? "<not set>" : acc->cmd_cycle_close,
    2287                 :            :             acc->cmd_cycle_timer,
    2288                 :        560 :             (acc->require_username == NULL) ? "<not set>" : acc->require_username,
    2289                 :        560 :             acc->require_source_address ? "Yes" : "No",
    2290                 :            :             acc->force_nat ? acc->force_nat_ip : "<not set>",
    2291         [ -  + ]:         18 :             acc->force_nat && acc->force_nat_proto != NULL ? acc->force_nat_proto : "<not set>",
    2292                 :        560 :             acc->force_nat ? acc->force_nat_port : 0,
    2293                 :        560 :             acc->force_snat ? acc->force_snat_ip : "<not set>",
    2294                 :        560 :             acc->force_masquerade ? "Yes" : "No",
    2295                 :        560 :             acc->disable_dnat ? "Yes" : "No",
    2296                 :        560 :             acc->forward_all ? "Yes" : "No",
    2297                 :          3 :             (acc->access_expire_time > 0) ? asctime(localtime(&acc->access_expire_time)) : "<not set>\n",
    2298                 :        560 :             (acc->gpg_home_dir == NULL) ? "<not set>" : acc->gpg_home_dir,
    2299                 :        560 :             (acc->gpg_exe == NULL) ? "<not set>" : acc->gpg_exe,
    2300                 :        560 :             (acc->gpg_decrypt_id == NULL) ? "<not set>" : acc->gpg_decrypt_id,
    2301                 :        560 :             (acc->gpg_decrypt_pw == NULL) ? "<not set>" : "<see the access.conf file>",
    2302                 :        560 :             acc->gpg_require_sig ? "Yes" : "No",
    2303                 :        560 :             acc->gpg_ignore_sig_error  ? "Yes" : "No",
    2304                 :        560 :             (acc->gpg_remote_id == NULL) ? "<not set>" : acc->gpg_remote_id,
    2305                 :        560 :             (acc->gpg_remote_fpr == NULL) ? "<not set>" : acc->gpg_remote_fpr
    2306                 :            :         );
    2307                 :            : 
    2308                 :        560 :         fprintf(stdout, "\n");
    2309                 :            : 
    2310                 :        560 :         acc = acc->next;
    2311                 :            :     }
    2312                 :            : 
    2313                 :        523 :     fprintf(stdout, "\n");
    2314                 :        523 :     fflush(stdout);
    2315                 :            : }
    2316                 :            : 
    2317                 :            : int
    2318                 :         20 : include_keys_file(acc_stanza_t *curr_acc, const char *access_filename, fko_srv_options_t *opts)
    2319                 :            : {
    2320                 :            :     FILE           *file_ptr;
    2321                 :            :     struct stat     st;
    2322                 :         20 :     unsigned int    num_lines = 0;
    2323                 :            : 
    2324                 :         20 :     char            access_line_buf[MAX_LINE_LEN] = {0};
    2325                 :         20 :     char            var[MAX_LINE_LEN] = {0};
    2326                 :         20 :     char            val[MAX_LINE_LEN] = {0};
    2327                 :            :     char           *ndx;
    2328                 :            : 
    2329                 :         20 :     log_msg(LOG_INFO, "Including key file: '%s'", access_filename);
    2330         [ +  + ]:         20 :     if(stat(access_filename, &st) != 0)
    2331                 :            :     {
    2332                 :          2 :         log_msg(LOG_ERR, "[*] Access file: '%s' was not found.",
    2333                 :            :             access_filename);
    2334                 :            : 
    2335                 :          2 :         return EXIT_FAILURE;
    2336                 :            :     }
    2337                 :            : 
    2338         [ +  - ]:         18 :     if ((file_ptr = fopen(access_filename, "r")) == NULL)
    2339                 :            :     {
    2340                 :          0 :         log_msg(LOG_ERR, "[*] Could not open access file: %s",
    2341                 :            :             access_filename);
    2342                 :          0 :         perror(NULL);
    2343                 :            : 
    2344                 :          0 :         return EXIT_FAILURE;
    2345                 :            :     }
    2346                 :            : 
    2347         [ +  + ]:         44 :     while ((fgets(access_line_buf, MAX_LINE_LEN, file_ptr)) != NULL)
    2348                 :            :     {
    2349                 :         34 :         num_lines++;
    2350                 :         34 :         access_line_buf[MAX_LINE_LEN-1] = '\0';
    2351                 :            : 
    2352                 :            :         /* Get past comments and empty lines (note: we only look at the
    2353                 :            :          * first character.
    2354                 :            :         */
    2355 [ +  - ][ +  - ]:         34 :         if(IS_EMPTY_LINE(access_line_buf[0]))
         [ +  - ][ -  + ]
    2356                 :          0 :             continue;
    2357                 :            : 
    2358         [ +  + ]:         34 :         if(sscanf(access_line_buf, "%s %[^;\n\r]", var, val) != 2)
    2359                 :            :         {
    2360                 :          1 :             log_msg(LOG_ERR,
    2361                 :            :                 "[*] Invalid access file entry in %s at line %i.\n - '%s'",
    2362                 :            :                 access_filename, num_lines, access_line_buf
    2363                 :            :             );
    2364                 :          1 :             fclose(file_ptr);
    2365                 :          1 :             return EXIT_FAILURE;
    2366                 :            :         }
    2367                 :            : 
    2368                 :            :         /* Remove the colon if present
    2369                 :            :         */
    2370         [ +  + ]:         33 :         if((ndx = strrchr(var, ':')) != NULL)
    2371                 :          4 :             *ndx = '\0';
    2372                 :            : 
    2373         [ +  + ]:         33 :         if(CONF_VAR_IS(var, "KEY"))
    2374                 :            :         {
    2375         [ +  + ]:          9 :             if(strcasecmp(val, "__CHANGEME__") == 0)
    2376                 :            :             {
    2377                 :          1 :                 log_msg(LOG_ERR,
    2378                 :            :                     "[*] KEY value is not properly set in stanza source '%s' in access file: '%s'",
    2379                 :            :                     curr_acc->source, access_filename);
    2380                 :          1 :                 fclose(file_ptr);
    2381                 :          1 :                 return EXIT_FAILURE;
    2382                 :            :             }
    2383                 :          8 :             add_acc_string(&(curr_acc->key), val, file_ptr, opts);
    2384                 :          8 :             curr_acc->key_len = strlen(curr_acc->key);
    2385                 :          8 :             add_acc_bool(&(curr_acc->use_rijndael), "Y");
    2386                 :            :         }
    2387         [ +  + ]:         24 :         else if(CONF_VAR_IS(var, "KEY_BASE64"))
    2388                 :            :         {
    2389         [ +  + ]:          3 :             if(strcasecmp(val, "__CHANGEME__") == 0)
    2390                 :            :             {
    2391                 :          1 :                 log_msg(LOG_ERR,
    2392                 :            :                     "[*] KEY_BASE64 value is not properly set in stanza source '%s' in access file: '%s'",
    2393                 :            :                     curr_acc->source, access_filename);
    2394                 :          1 :                 fclose(file_ptr);
    2395                 :          1 :                 return EXIT_FAILURE;
    2396                 :            :             }
    2397         [ +  + ]:          2 :             if (! is_base64((unsigned char *) val, strlen(val)))
    2398                 :            :             {
    2399                 :          1 :                 log_msg(LOG_ERR,
    2400                 :            :                     "[*] KEY_BASE64 argument '%s' doesn't look like base64-encoded data.",
    2401                 :            :                     val);
    2402                 :          1 :                 fclose(file_ptr);
    2403                 :          1 :                 return EXIT_FAILURE;
    2404                 :            :             }
    2405                 :          1 :             add_acc_string(&(curr_acc->key_base64), val, file_ptr, opts);
    2406                 :          1 :             add_acc_b64_string(&(curr_acc->key), &(curr_acc->key_len),
    2407                 :          1 :                     curr_acc->key_base64, file_ptr, opts);
    2408                 :          1 :             add_acc_bool(&(curr_acc->use_rijndael), "Y");
    2409                 :            :         }
    2410         [ +  + ]:         21 :         else if(CONF_VAR_IS(var, "HMAC_KEY_BASE64"))
    2411                 :            :         {
    2412         [ +  + ]:          3 :             if(strcasecmp(val, "__CHANGEME__") == 0)
    2413                 :            :             {
    2414                 :          1 :                 log_msg(LOG_ERR,
    2415                 :            :                     "[*] HMAC_KEY_BASE64 value is not properly set in stanza source '%s' in access file: '%s'",
    2416                 :            :                     curr_acc->source, opts->config[CONF_ACCESS_FILE]);
    2417                 :          1 :                 fclose(file_ptr);
    2418                 :          1 :                 return EXIT_FAILURE;
    2419                 :            :             }
    2420         [ +  + ]:          2 :             if (! is_base64((unsigned char *) val, strlen(val)))
    2421                 :            :             {
    2422                 :          1 :                 log_msg(LOG_ERR,
    2423                 :            :                     "[*] HMAC_KEY_BASE64 argument '%s' doesn't look like base64-encoded data.",
    2424                 :            :                     val);
    2425                 :          1 :                 fclose(file_ptr);
    2426                 :          1 :                 return EXIT_FAILURE;
    2427                 :            :             }
    2428                 :          1 :             add_acc_string(&(curr_acc->hmac_key_base64), val, file_ptr, opts);
    2429                 :          1 :             add_acc_b64_string(&(curr_acc->hmac_key), &(curr_acc->hmac_key_len),
    2430                 :          1 :                     curr_acc->hmac_key_base64, file_ptr, opts);
    2431                 :            :         }
    2432         [ +  + ]:         18 :         else if(CONF_VAR_IS(var, "HMAC_KEY"))
    2433                 :            :         {
    2434         [ +  + ]:          3 :             if(strcasecmp(val, "__CHANGEME__") == 0)
    2435                 :            :             {
    2436                 :          1 :                 log_msg(LOG_ERR,
    2437                 :            :                     "[*] HMAC_KEY value is not properly set in stanza source '%s' in access file: '%s'",
    2438                 :            :                     curr_acc->source, opts->config[CONF_ACCESS_FILE]);
    2439                 :          1 :                 fclose(file_ptr);
    2440                 :          1 :                 return EXIT_FAILURE;
    2441                 :            :             }
    2442                 :          2 :             add_acc_string(&(curr_acc->hmac_key), val, file_ptr, opts);
    2443                 :          2 :             curr_acc->hmac_key_len = strlen(curr_acc->hmac_key);
    2444                 :            :         }
    2445         [ +  + ]:         15 :         else if(CONF_VAR_IS(var, "GPG_DECRYPT_ID"))
    2446                 :          1 :             add_acc_string(&(curr_acc->gpg_decrypt_id), val, file_ptr, opts);
    2447         [ +  + ]:         14 :         else if(CONF_VAR_IS(var, "GPG_DECRYPT_PW"))
    2448                 :            :         {
    2449         [ +  + ]:          2 :             if(strcasecmp(val, "__CHANGEME__") == 0)
    2450                 :            :             {
    2451                 :          1 :                 log_msg(LOG_ERR,
    2452                 :            :                     "[*] GPG_DECRYPT_PW value is not properly set in stanza source '%s' in access file: '%s'",
    2453                 :            :                     curr_acc->source, access_filename);
    2454                 :          1 :                 fclose(file_ptr);
    2455                 :          1 :                 return EXIT_FAILURE;
    2456                 :            :             }
    2457                 :          1 :             add_acc_string(&(curr_acc->gpg_decrypt_pw), val, file_ptr, opts);
    2458                 :          1 :             add_acc_bool(&(curr_acc->use_gpg), "Y");
    2459                 :            :         }
    2460         [ +  + ]:         12 :         else if(CONF_VAR_IS(var, "GPG_ALLOW_NO_PW"))
    2461                 :            :         {
    2462                 :          1 :             add_acc_bool(&(curr_acc->gpg_allow_no_pw), val);
    2463         [ +  - ]:          1 :             if(curr_acc->gpg_allow_no_pw == 1)
    2464                 :            :             {
    2465                 :          1 :                 add_acc_bool(&(curr_acc->use_gpg), "Y");
    2466                 :          1 :                 add_acc_string(&(curr_acc->gpg_decrypt_pw), "", file_ptr, opts);
    2467                 :            :             }
    2468                 :            :         }
    2469         [ +  + ]:         11 :         else if(CONF_VAR_IS(var, "GPG_REQUIRE_SIG"))
    2470                 :            :         {
    2471                 :          1 :             add_acc_bool(&(curr_acc->gpg_require_sig), val);
    2472                 :            :         }
    2473         [ +  + ]:         10 :         else if(CONF_VAR_IS(var, "GPG_DISABLE_SIG"))
    2474                 :            :         {
    2475                 :          1 :             add_acc_bool(&(curr_acc->gpg_disable_sig), val);
    2476                 :            :         }
    2477         [ +  + ]:          9 :         else if(CONF_VAR_IS(var, "GPG_IGNORE_SIG_VERIFY_ERROR"))
    2478                 :            :         {
    2479                 :          1 :             add_acc_bool(&(curr_acc->gpg_ignore_sig_error), val);
    2480                 :            :         }
    2481         [ +  + ]:          8 :         else if(CONF_VAR_IS(var, "GPG_REMOTE_ID"))
    2482                 :          1 :             add_acc_string(&(curr_acc->gpg_remote_id), val, file_ptr, opts);
    2483         [ +  + ]:          7 :         else if(CONF_VAR_IS(var, "GPG_FINGERPRINT_ID"))
    2484                 :          1 :             add_acc_string(&(curr_acc->gpg_remote_fpr), val, file_ptr, opts);
    2485                 :            :         else
    2486                 :         26 :             log_msg(LOG_INFO, "Ignoring invalid entry: '%s'", var);
    2487                 :            :     }
    2488                 :         10 :     fclose(file_ptr);
    2489                 :         10 :     return EXIT_SUCCESS;
    2490                 :            : }
    2491                 :            : 
    2492                 :            : #ifdef HAVE_C_UNIT_TESTS /* LCOV_EXCL_START */
    2493                 :            : 
    2494                 :            : DECLARE_UTEST(compare_port_list, "check compare_port_list function")
    2495                 :            : {
    2496                 :            :     acc_port_list_t *in1_pl = NULL;
    2497                 :            :     acc_port_list_t *in2_pl = NULL;
    2498                 :            :     acc_port_list_t *acc_pl = NULL;
    2499                 :            : 
    2500                 :            :     /* Match any test */
    2501                 :            :     free_acc_port_list(in1_pl);
    2502                 :            :     free_acc_port_list(acc_pl);
    2503                 :            :     expand_acc_port_list(&in1_pl, "udp/6002");
    2504                 :            :     expand_acc_port_list(&in2_pl, "udp/6002, udp/6003");
    2505                 :            :     expand_acc_port_list(&acc_pl, "udp/6002, udp/6003");
    2506                 :            :     CU_ASSERT(compare_port_list(in1_pl, acc_pl, 1) == 1);       /* Only one match is needed from access port list - 1 */
    2507                 :            :     CU_ASSERT(compare_port_list(in2_pl, acc_pl, 1) == 1);       /* Only match is needed from access port list - 2 */
    2508                 :            :     CU_ASSERT(compare_port_list(in1_pl, acc_pl, 0) == 1);       /* All ports must match access port list - 1 */
    2509                 :            :     CU_ASSERT(compare_port_list(in2_pl, acc_pl, 0) == 1);       /* All ports must match access port list - 2 */
    2510                 :            :     CU_ASSERT(compare_port_list(acc_pl, in1_pl, 0) == 0);       /* All ports must match in1 port list - 1 */
    2511                 :            :     CU_ASSERT(compare_port_list(acc_pl, in2_pl, 0) == 1);       /* All ports must match in2 port list - 2 */
    2512                 :            : }
    2513                 :            : 
    2514                 :            : int register_ts_access(void)
    2515                 :            : {
    2516                 :            :     ts_init(&TEST_SUITE(access), TEST_SUITE_DESCR(access), NULL, NULL);
    2517                 :            :     ts_add_utest(&TEST_SUITE(access), UTEST_FCT(compare_port_list), UTEST_DESCR(compare_port_list));
    2518                 :            : 
    2519                 :            :     return register_ts(&TEST_SUITE(access));
    2520                 :            : }
    2521                 :            : #endif /* HAVE_C_UNIT_TESTS */ /* LCOV_EXCL_STOP */
    2522                 :            : /***EOF***/

Generated by: LCOV version 1.10