LCOV - code coverage report
Current view: top level - common - fko_util.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 382 397 96.2 %
Date: 2016-06-07 Functions: 29 29 100.0 %
Branches: 293 360 81.4 %

           Branch data     Line data    Source code
       1                 :            : /**
       2                 :            :  * \file common/fko_util.c
       3                 :            :  *
       4                 :            :  * \brief Provide a set of common utility functions that fwknop can use.
       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 "fko_common.h"
      31                 :            : #include "fko_util.h"
      32                 :            : #include <errno.h>
      33                 :            : #include <stdarg.h>
      34                 :            : 
      35                 :            : #ifndef WIN32
      36                 :            :   /* for inet_aton() IP validation
      37                 :            :   */
      38                 :            :   #include <sys/socket.h>
      39                 :            :   #include <netinet/in.h>
      40                 :            :   #include <arpa/inet.h>
      41                 :            : #endif
      42                 :            : 
      43                 :            : /* Check for a FKO error returned by a function an return the error code */
      44                 :            : #define RETURN_ON_FKO_ERROR(e, f)   do { if (((e)=(f)) != FKO_SUCCESS) { return (e); } } while(0);
      45                 :            : 
      46                 :            : #define FKO_ENCRYPTION_MODE_BUFSIZE 16                      /*!< Maximum size of an encryption mode string */
      47                 :            : #define FKO_ENC_MODE_SUPPORTED      0                       /*!< Defined a supported fko encryption mode */
      48                 :            : #define FKO_ENC_MODE_NOT_SUPPORTED  !FKO_ENC_MODE_SUPPORTED /*!< Defined an unsupported fko encryption mode */
      49                 :            : 
      50                 :            : #define NULL_STRING                 "<NULL>"                /*!< String which represents a NULL buffer */
      51                 :            : 
      52                 :            : #ifdef HAVE_C_UNIT_TESTS /* LCOV_EXCL_START */
      53                 :            : #include "cunit_common.h"
      54                 :            : DECLARE_TEST_SUITE(utils_test, "Utility functions test suite");
      55                 :            : #endif /* LCOV_EXCL_STOP */
      56                 :            : 
      57                 :            : /**
      58                 :            :  * Structure to handle an encryption mode string string and its associated integer value
      59                 :            :  */
      60                 :            : typedef struct fko_enc_mode_str
      61                 :            : {
      62                 :            :     const char  str[FKO_ENCRYPTION_MODE_BUFSIZE];   /*!< String which represents an encryption mode value for the FKO library */
      63                 :            :     int         val;                                /*!< Value of the encryption mode according to the FKO library */
      64                 :            :     int         supported;                          /*!< SUPPORTED or NOT_SUPPORTED */
      65                 :            : } fko_enc_mode_str_t;
      66                 :            : 
      67                 :            : /**
      68                 :            :  * Array to associate all of encryption modes with their respective string
      69                 :            :  */
      70                 :            : static fko_enc_mode_str_t fko_enc_mode_strs[] =
      71                 :            : {
      72                 :            :     { "CBC",            FKO_ENC_MODE_CBC,           FKO_ENC_MODE_SUPPORTED      },
      73                 :            :     { "ECB",            FKO_ENC_MODE_ECB,           FKO_ENC_MODE_SUPPORTED      },
      74                 :            :     { "CFB",            FKO_ENC_MODE_CFB,           FKO_ENC_MODE_SUPPORTED      },
      75                 :            :     { "PCBC",           FKO_ENC_MODE_PCBC,          FKO_ENC_MODE_NOT_SUPPORTED  },
      76                 :            :     { "OFB",            FKO_ENC_MODE_OFB,           FKO_ENC_MODE_SUPPORTED      },
      77                 :            :     { "CTR",            FKO_ENC_MODE_CTR,           FKO_ENC_MODE_SUPPORTED      },
      78                 :            :     { "Asymmetric",     FKO_ENC_MODE_ASYMMETRIC,    FKO_ENC_MODE_SUPPORTED      },
      79                 :            :     { "legacy",         FKO_ENC_MODE_CBC_LEGACY_IV, FKO_ENC_MODE_SUPPORTED      }
      80                 :            : };
      81                 :            : 
      82                 :            : /* Compare all bytes with constant run time regardless of
      83                 :            :  * input characteristics (i.e. don't return early if a difference
      84                 :            :  * is found before comparing all bytes).  This code was adapted
      85                 :            :  * from YaSSL which is GPLv2 after a timing bug was reported by
      86                 :            :  * Ryman through github (#85)
      87                 :            : */
      88                 :            : int
      89                 :   12581282 : constant_runtime_cmp(const char *a, const char *b, int len)
      90                 :            : {
      91                 :   12581282 :     int good = 0;
      92                 :   12581282 :     int bad  = 0;
      93                 :            :     int i;
      94                 :            : 
      95         [ +  + ]:  527205342 :     for(i=0; i < len; i++) {
      96         [ +  + ]:  514624060 :         if (a[i] == b[i])
      97                 :   77221050 :             good++;
      98                 :            :         else
      99                 :  437403010 :             bad++;
     100                 :            :     }
     101                 :            : 
     102         [ +  + ]:   12581282 :     if (good == len)
     103                 :            :         return 0;
     104                 :            :     else
     105                 :   10956187 :         return 0 - bad;
     106                 :            : }
     107                 :            : 
     108                 :            : /* Validate encoded message length
     109                 :            : */
     110                 :            : int
     111                 :    7356446 : is_valid_encoded_msg_len(const int len)
     112                 :            : {
     113                 :            : #if HAVE_LIBFIU
     114         [ +  + ]:    7356446 :     fiu_return_on("is_valid_encoded_msg_len_val", 0);
     115                 :            : #endif
     116         [ +  + ]:    7356445 :     if(len < MIN_SPA_ENCODED_MSG_SIZE || len >= MAX_SPA_ENCODED_MSG_SIZE)
     117                 :            :         return(0);
     118                 :            : 
     119                 :    7254552 :     return(1);
     120                 :            : }
     121                 :            : 
     122                 :            : /* Validate an IPv4 address
     123                 :            : */
     124                 :            : int
     125                 :     393422 : is_valid_ipv4_addr(const char * const ip_str, const int len)
     126                 :            : {
     127                 :     393422 :     const char         *ndx     = ip_str;
     128                 :     393422 :     char         tmp_ip_str[MAX_IPV4_STR_LEN + 1]={0};
     129                 :     393422 :     int                 dot_ctr = 0, char_ctr = 0;
     130                 :     393422 :     int                 res     = 1;
     131                 :            : #if HAVE_SYS_SOCKET_H
     132                 :            :     struct in_addr      in;
     133                 :            : #endif
     134                 :            : 
     135         [ +  - ]:     393422 :     if(ip_str == NULL)
     136                 :            :         return 0;
     137                 :            : 
     138         [ +  + ]:     393422 :     if((len > MAX_IPV4_STR_LEN) || (len < MIN_IPV4_STR_LEN))
     139                 :            :         return 0;
     140                 :            : 
     141                 :            : 
     142         [ +  + ]:    3721772 :     while(char_ctr < len)
     143                 :            :     {
     144                 :            :         /* If we've hit a null within the given length, then not valid regardless*/
     145         [ +  - ]:    3338808 :         if(*ndx == '\0')
     146                 :            :             return 0;
     147                 :            : 
     148                 :    3338808 :         char_ctr++;
     149                 :            : 
     150         [ +  + ]:    3338808 :         if(*ndx == '.')
     151                 :    1151173 :             dot_ctr++;
     152         [ +  + ]:    2187635 :         else if(isdigit(*ndx) == 0)
     153                 :            :         {
     154                 :            :             res = 0;
     155                 :            :             break;
     156                 :            :         }
     157                 :    3338798 :         ndx++;
     158                 :            :     }
     159                 :            : 
     160                 :            : 
     161                 :            : 
     162         [ +  + ]:     382974 :     if((res == 1) && (dot_ctr != 3))
     163                 :       2614 :         res = 0;
     164                 :            : 
     165                 :            : #if HAVE_SYS_SOCKET_H
     166                 :            :     /* Stronger IP validation now that we have a candidate that looks
     167                 :            :      * close enough
     168                 :            :     */
     169         [ +  + ]:     382974 :     if(res == 1) {
     170                 :     380350 :         strncpy(tmp_ip_str, ip_str, len);
     171         [ +  + ]:     380350 :         if (inet_aton(tmp_ip_str, &in) == 0)
     172                 :       1348 :             res = 0;
     173                 :            :     }
     174                 :            : #endif
     175                 :     382974 :     return(res);
     176                 :            : }
     177                 :            : 
     178                 :            : /* Validate a hostname
     179                 :            : */
     180                 :            : int
     181                 :         15 : is_valid_hostname(const char * const hostname_str, const int len)
     182                 :            : {
     183                 :         15 :     int                 label_size = 0, total_size = 0;
     184                 :         15 :     const char         *ndx     = hostname_str;
     185                 :            : 
     186         [ +  - ]:         15 :     if (hostname_str == NULL)
     187                 :            :         return 0;
     188                 :            : 
     189         [ +  - ]:         15 :     if (len > 254)
     190                 :            :         return 0;
     191                 :            : 
     192         [ +  + ]:        138 :     while(total_size < len)
     193                 :            :     {
     194         [ +  - ]:        129 :         if (*ndx == '\0')
     195                 :            :             return 0;
     196                 :            : 
     197         [ +  + ]:        129 :         if (label_size == 0) //More restrictions on first character of a label
     198                 :            :         {
     199         [ +  + ]:         18 :             if (!isalnum(*ndx))
     200                 :            :                 return 0;
     201                 :            :         }
     202         [ +  + ]:        111 :         else if (!(isalnum(*ndx) | (*ndx == '.') | (*ndx == '-')))
     203                 :            :             return 0;
     204                 :            : 
     205         [ +  + ]:        125 :         if (*ndx == '.')
     206                 :            :         {
     207         [ +  + ]:          7 :             if (label_size > 63)
     208                 :            :                 return 0;
     209         [ +  + ]:          6 :             if (!isalnum(*(ndx-1)))  //checks that previous character was not a . or -
     210                 :            :                 return 0;
     211                 :            : 
     212                 :            :             label_size = 0;
     213                 :            :         }
     214                 :            :         else
     215                 :            :         {
     216                 :        118 :             label_size++;
     217                 :            :         }
     218                 :            : 
     219                 :        123 :         total_size++;
     220                 :            : 
     221                 :        123 :         ndx++; //move to next character
     222                 :            :     }
     223                 :            :     /* At this point, we're pointing at the null.  Decrement ndx for simplicity
     224                 :            :     */
     225                 :          9 :     ndx--;
     226         [ +  - ]:          9 :     if (*ndx == '-')
     227                 :            :         return 0;
     228                 :            : 
     229                 :            :     if (*ndx == '.')
     230                 :            :         total_size--;
     231                 :            : 
     232         [ +  - ]:          9 :     if (label_size > 63)
     233                 :            :         return 0;
     234                 :            : 
     235                 :            :     /* By now we've bailed if invalid
     236                 :            :     */
     237                 :          9 :     return 1;
     238                 :            : }
     239                 :            : 
     240                 :            : /* Convert a digest_type string to its integer value.
     241                 :            : */
     242                 :            : short
     243                 :         73 : digest_strtoint(const char *dt_str)
     244                 :            : {
     245         [ +  + ]:         73 :     if(strcasecmp(dt_str, "md5") == 0)
     246                 :            :         return(FKO_DIGEST_MD5);
     247         [ +  + ]:         53 :     else if(strcasecmp(dt_str, "sha1") == 0)
     248                 :            :         return(FKO_DIGEST_SHA1);
     249         [ +  + ]:         22 :     else if(strcasecmp(dt_str, "sha256") == 0)
     250                 :            :         return(FKO_DIGEST_SHA256);
     251         [ +  + ]:         12 :     else if(strcasecmp(dt_str, "sha384") == 0)
     252                 :            :         return(FKO_DIGEST_SHA384);
     253         [ +  + ]:          9 :     else if(strcasecmp(dt_str, "sha512") == 0)
     254                 :            :         return(FKO_DIGEST_SHA512);
     255         [ +  + ]:          4 :     else if(strcasecmp(dt_str, "sha3_256") == 0)
     256                 :            :         return(FKO_DIGEST_SHA3_256);
     257         [ +  + ]:          3 :     else if(strcasecmp(dt_str, "sha3_512") == 0)
     258                 :            :         return(FKO_DIGEST_SHA3_512);
     259                 :            :     else
     260                 :          2 :         return(-1);
     261                 :            : }
     262                 :            : 
     263                 :            : /**
     264                 :            :  * \brief Return a digest string according to a digest integer value
     265                 :            :  *
     266                 :            :  * This function checks the digest integer is valid, and write the digest
     267                 :            :  * string associated.
     268                 :            :  *
     269                 :            :  * \param digest Digest inetger value (FKO_DIGEST_MD5, FKO_DIGEST_SHA1 ...)
     270                 :            :  * \param digest_str Buffer to write the digest string
     271                 :            :  * \param digest_size size of the digest string buffer
     272                 :            :  *
     273                 :            :  * \return -1 if the digest integer value is not supported, 0 otherwise
     274                 :            :  */
     275                 :            : short
     276                 :       3877 : digest_inttostr(int digest, char* digest_str, size_t digest_size)
     277                 :            : {
     278                 :       3877 :     short digest_not_valid = 0;
     279                 :            : 
     280                 :            :     memset(digest_str, 0, digest_size);
     281                 :            : 
     282   [ +  +  +  +  :       3877 :     switch (digest)
             +  +  +  - ]
     283                 :            :     {
     284                 :            :         case FKO_DIGEST_MD5:
     285                 :         10 :             strlcpy(digest_str, "MD5", digest_size);
     286                 :         10 :             break;
     287                 :            :         case FKO_DIGEST_SHA1:
     288                 :         39 :             strlcpy(digest_str, "SHA1", digest_size);
     289                 :         39 :             break;
     290                 :            :         case FKO_DIGEST_SHA256:
     291                 :       3802 :             strlcpy(digest_str, "SHA256", digest_size);
     292                 :       3802 :             break;
     293                 :            :         case FKO_DIGEST_SHA384:
     294                 :         10 :             strlcpy(digest_str, "SHA384", digest_size);
     295                 :         10 :             break;
     296                 :            :         case FKO_DIGEST_SHA512:
     297                 :         12 :             strlcpy(digest_str, "SHA512", digest_size);
     298                 :         12 :             break;
     299                 :            :         case FKO_DIGEST_SHA3_256:
     300                 :          2 :             strlcpy(digest_str, "SHA3_256", digest_size);
     301                 :          2 :             break;
     302                 :            :         case FKO_DIGEST_SHA3_512:
     303                 :          2 :             strlcpy(digest_str, "SHA3_512", digest_size);
     304                 :          2 :             break;
     305                 :            :         default:
     306                 :          0 :             strlcpy(digest_str, "Unknown", digest_size);
     307                 :          0 :             digest_not_valid = -1;
     308                 :          0 :             break;
     309                 :            :     }
     310                 :            : 
     311                 :       3877 :     return digest_not_valid;
     312                 :            : }
     313                 :            : 
     314                 :            : short
     315                 :        859 : hmac_digest_strtoint(const char *dt_str)
     316                 :            : {
     317         [ +  + ]:        859 :     if(strcasecmp(dt_str, "md5") == 0)
     318                 :            :         return(FKO_HMAC_MD5);
     319         [ +  + ]:        842 :     else if(strcasecmp(dt_str, "sha1") == 0)
     320                 :            :         return(FKO_HMAC_SHA1);
     321         [ +  + ]:        791 :     else if(strcasecmp(dt_str, "sha256") == 0)
     322                 :            :         return(FKO_HMAC_SHA256);
     323         [ +  + ]:         43 :     else if(strcasecmp(dt_str, "sha384") == 0)
     324                 :            :         return(FKO_HMAC_SHA384);
     325         [ +  + ]:         30 :     else if(strcasecmp(dt_str, "sha512") == 0)
     326                 :            :         return(FKO_HMAC_SHA512);
     327         [ +  + ]:         13 :     else if(strcasecmp(dt_str, "sha3_256") == 0)
     328                 :            :         return(FKO_HMAC_SHA3_256);
     329         [ +  + ]:         10 :     else if(strcasecmp(dt_str, "sha3_512") == 0)
     330                 :            :         return(FKO_HMAC_SHA3_512);
     331                 :            :     else
     332                 :          7 :         return(-1);
     333                 :            : }
     334                 :            : 
     335                 :            : /* Return encryption type string representation
     336                 :            : */
     337                 :            : const char *
     338                 :       3865 : enc_type_inttostr(const int type)
     339                 :            : {
     340         [ +  - ]:       3865 :     if(type == FKO_ENC_MODE_UNKNOWN)
     341                 :            :         return("Unknown encryption type");
     342         [ +  + ]:       3865 :     else if(type == FKO_ENCRYPTION_RIJNDAEL)
     343                 :            :         return("Rijndael");
     344         [ -  + ]:        137 :     else if(type == FKO_ENCRYPTION_GPG)
     345                 :            :         return("GPG");
     346                 :            : 
     347                 :          0 :     return("Unknown encryption type");
     348                 :            : }
     349                 :            : 
     350                 :            : /* Return message type string representation
     351                 :            : */
     352                 :            : const char *
     353                 :       3865 : msg_type_inttostr(const int type)
     354                 :            : {
     355         [ +  + ]:       3865 :     if(type == FKO_COMMAND_MSG)
     356                 :            :         return("Command msg");
     357         [ +  + ]:       3652 :     else if(type == FKO_ACCESS_MSG)
     358                 :            :         return("Access msg");
     359         [ +  + ]:        414 :     else if(type == FKO_NAT_ACCESS_MSG)
     360                 :            :         return("NAT access msg");
     361         [ +  + ]:        292 :     else if(type == FKO_CLIENT_TIMEOUT_ACCESS_MSG)
     362                 :            :         return("Client timeout access msg");
     363         [ +  + ]:        223 :     else if(type == FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG)
     364                 :            :         return("Client timeout NAT access msg");
     365         [ +  + ]:        150 :     else if(type == FKO_LOCAL_NAT_ACCESS_MSG)
     366                 :            :         return("Local NAT access msg");
     367         [ -  + ]:         63 :     else if(type == FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG)
     368                 :            :         return("Client timeout local NAT access msg");
     369                 :            : 
     370                 :          0 :     return("Unknown message type");
     371                 :            : }
     372                 :            : 
     373                 :            : /**
     374                 :            :  * \brief Return a hmac digest string according to a hmac digest integer value
     375                 :            :  *
     376                 :            :  * This function checks if the digest integer is valid, and write the digest
     377                 :            :  * string associated.
     378                 :            :  *
     379                 :            :  * \param digest Digest inetger value (FKO_HMAC_MD5, FKO_HMAC_SHA1 ...)
     380                 :            :  * \param digest_str Buffer to write the digest string
     381                 :            :  * \param digest_size size of the digest string buffer
     382                 :            :  *
     383                 :            :  * \return -1 if the digest integer value is not supported, 0 otherwise
     384                 :            :  */
     385                 :            : short
     386                 :       2108 : hmac_digest_inttostr(int digest, char* digest_str, size_t digest_size)
     387                 :            : {
     388                 :       2108 :     short digest_not_valid = 0;
     389                 :            : 
     390                 :            :     memset(digest_str, 0, digest_size);
     391                 :            : 
     392   [ +  +  +  +  :       2108 :     switch (digest)
             +  +  +  - ]
     393                 :            :     {
     394                 :            :         case FKO_HMAC_MD5:
     395                 :         12 :             strlcpy(digest_str, "MD5", digest_size);
     396                 :         12 :             break;
     397                 :            :         case FKO_HMAC_SHA1:
     398                 :         49 :             strlcpy(digest_str, "SHA1", digest_size);
     399                 :         49 :             break;
     400                 :            :         case FKO_HMAC_SHA256:
     401                 :       2016 :             strlcpy(digest_str, "SHA256", digest_size);
     402                 :       2016 :             break;
     403                 :            :         case FKO_HMAC_SHA384:
     404                 :         12 :             strlcpy(digest_str, "SHA384", digest_size);
     405                 :         12 :             break;
     406                 :            :         case FKO_HMAC_SHA512:
     407                 :         15 :             strlcpy(digest_str, "SHA512", digest_size);
     408                 :         15 :             break;
     409                 :            :         case FKO_HMAC_SHA3_256:
     410                 :          2 :             strlcpy(digest_str, "SHA3_256", digest_size);
     411                 :          2 :             break;
     412                 :            :         case FKO_HMAC_SHA3_512:
     413                 :          2 :             strlcpy(digest_str, "SHA3_512", digest_size);
     414                 :          2 :             break;
     415                 :            :         default:
     416                 :          0 :             strlcpy(digest_str, "Unknown", digest_size);
     417                 :          0 :             digest_not_valid = -1;
     418                 :          0 :             break;
     419                 :            :     }
     420                 :            : 
     421                 :       2108 :     return digest_not_valid;
     422                 :            : }
     423                 :            : 
     424                 :            : /* Validate plaintext input size
     425                 :            : */
     426                 :            : int
     427                 :     800830 : is_valid_pt_msg_len(const int len)
     428                 :            : {
     429                 :            : #if HAVE_LIBFIU
     430         [ +  + ]:     800830 :     fiu_return_on("is_valid_pt_msg_len_val", 0);
     431                 :            : #endif
     432         [ +  - ]:     800829 :     if(len < MIN_SPA_PLAINTEXT_MSG_SIZE || len >= MAX_SPA_PLAINTEXT_MSG_SIZE)
     433                 :            :         return(0);
     434                 :            : 
     435                 :     800829 :     return(1);
     436                 :            : }
     437                 :            : 
     438                 :            : /**
     439                 :            :  * @brief Convert an encryption mode string to its integer value.
     440                 :            :  *
     441                 :            :  * @param enc_mode_str Encryption mode string (CBC,ECB...)
     442                 :            :  *
     443                 :            :  * @return -1 if the encryption mode string is not supported,
     444                 :            :  *         otherwise the encryption mode value
     445                 :            :  */
     446                 :            : int
     447                 :         55 : enc_mode_strtoint(const char *enc_mode_str)
     448                 :            : {
     449                 :            :     unsigned char           ndx_enc_mode;
     450                 :         55 :     int                     enc_mode_int = -1;     /* Encryption mode integer value */
     451                 :            :     fko_enc_mode_str_t     *enc_mode_str_pt;
     452                 :            : 
     453                 :            :     /* Look into the fko_enc_mode_strs array to find out the right encryption mode */
     454         [ +  + ]:        326 :     for (ndx_enc_mode = 0 ; ndx_enc_mode < ARRAY_SIZE(fko_enc_mode_strs) ; ndx_enc_mode++)
     455                 :            :     {
     456                 :        322 :         enc_mode_str_pt = &(fko_enc_mode_strs[ndx_enc_mode]);
     457                 :            : 
     458                 :            :         /* If the encryption mode matches, grab it */
     459         [ +  + ]:        322 :         if (   (strcasecmp(enc_mode_str, enc_mode_str_pt->str) == 0)
     460         [ +  + ]:         52 :             && (enc_mode_str_pt->supported == FKO_ENC_MODE_SUPPORTED) )
     461                 :            :         {
     462                 :         51 :             enc_mode_int = enc_mode_str_pt->val;
     463                 :         51 :             break;
     464                 :            :         }
     465                 :            :     }
     466                 :            : 
     467                 :         55 :     return enc_mode_int;
     468                 :            : }
     469                 :            : 
     470                 :            : /**
     471                 :            :  * @brief Return an encryption mode string according to an enc_mode integer value
     472                 :            :  *
     473                 :            :  * This function checks if the encryption mode integer is valid, and write the
     474                 :            :  * encryption mode string associated.
     475                 :            :  *
     476                 :            :  * @param enc_mode Encryption mode integer value (FKO_ENC_MODE_CBC, FKO_ENC_MODE_ECB ...)
     477                 :            :  * @param enc_mode_str Buffer to write the encryption mode string to
     478                 :            :  * @param enc_mode_size Size of the encryption mode string buffer
     479                 :            :  *
     480                 :            :  * @return -1 if the encryption mode integer value is not supported, 0 otherwise
     481                 :            :  */
     482                 :            : short
     483                 :       3867 : enc_mode_inttostr(int enc_mode, char* enc_mode_str, size_t enc_mode_size)
     484                 :            : {
     485                 :       3867 :     short                   enc_mode_error = -1;
     486                 :            :     unsigned char           ndx_enc_mode;
     487                 :            :     fko_enc_mode_str_t     *enc_mode_str_pt;
     488                 :            : 
     489                 :            :     /* Initialize the protocol string */
     490                 :            :     memset(enc_mode_str, 0, enc_mode_size);
     491                 :            : 
     492                 :            :     /* Look into the fko_enc_mode_strs array to find out the right protocol */
     493         [ +  - ]:       4878 :     for (ndx_enc_mode = 0 ; ndx_enc_mode < ARRAY_SIZE(fko_enc_mode_strs) ; ndx_enc_mode++)
     494                 :            :     {
     495                 :       4878 :         enc_mode_str_pt = &(fko_enc_mode_strs[ndx_enc_mode]);
     496                 :            : 
     497                 :            :         /* If the encryption mode matches, grab it */
     498         [ +  + ]:       4878 :         if (   (enc_mode_str_pt->val == enc_mode)
     499         [ +  - ]:       3867 :             && (enc_mode_str_pt->supported == FKO_ENC_MODE_SUPPORTED) )
     500                 :            :         {
     501                 :       3867 :             strlcpy(enc_mode_str, enc_mode_str_pt->str, enc_mode_size);
     502                 :       3867 :             enc_mode_error = 0;
     503                 :       3867 :             break;
     504                 :            :         }
     505                 :            :     }
     506                 :            : 
     507                 :       3867 :     return enc_mode_error;
     508                 :            : }
     509                 :            : 
     510                 :            : int
     511                 :    1708179 : strtol_wrapper(const char * const str, const int min,
     512                 :            :     const int max, const int exit_upon_err, int *err)
     513                 :            : {
     514                 :            :     int val;
     515                 :            : 
     516                 :    1708179 :     errno = 0;
     517                 :    1708179 :     *err = FKO_SUCCESS;
     518                 :            : 
     519                 :    1708179 :     val = strtol(str, (char **) NULL, 10);
     520                 :            : 
     521 [ -  + ][ #  # ]:    1708179 :     if ((errno == ERANGE || (errno != 0 && val == 0)))
                 [ +  + ]
     522                 :            :     {
     523                 :          1 :         *err = errno;
     524         [ +  - ]:          1 :         if(exit_upon_err == EXIT_UPON_ERR)
     525                 :            :         {
     526                 :          1 :             perror("strtol");
     527                 :          1 :             fprintf(stderr, "[*] Value %d out of range [(%d)-(%d)]\n",
     528                 :            :                 val, min, max);
     529                 :          1 :             exit(EXIT_FAILURE);
     530                 :            :         }
     531                 :            :     }
     532                 :            : 
     533         [ +  + ]:    1708178 :     if(val < min)
     534                 :            :     {
     535                 :        713 :         *err = FKO_ERROR_INVALID_DATA_UTIL_STRTOL_LT_MIN;
     536         [ +  + ]:        713 :         if(exit_upon_err == EXIT_UPON_ERR)
     537                 :            :         {
     538                 :          1 :             fprintf(stderr, "[*] Value %d out of range [(%d)-(%d)]\n",
     539                 :            :                 val, min, max);
     540                 :          1 :             exit(EXIT_FAILURE);
     541                 :            :         }
     542                 :            :     }
     543                 :            : 
     544                 :            :     /* allow max == -1 to be an exception where we don't care about the
     545                 :            :      * maximum - note that the ERANGE check is still in place above
     546                 :            :     */
     547         [ +  + ]:    1708177 :     if((max >= 0) && (val > max))
     548                 :            :     {
     549                 :        319 :         *err = FKO_ERROR_INVALID_DATA_UTIL_STRTOL_GT_MAX;
     550         [ +  + ]:        319 :         if(exit_upon_err == EXIT_UPON_ERR)
     551                 :            :         {
     552                 :          1 :             fprintf(stderr, "[*] Value %d out of range [(%d)-(%d)]\n",
     553                 :            :                 val, min, max);
     554                 :          1 :             exit(EXIT_FAILURE);
     555                 :            :         }
     556                 :            :     }
     557                 :            : 
     558                 :            : #if HAVE_LIBFIU
     559         [ +  - ]:    1708176 :     fiu_return_on("strtol_wrapper_lt_min",
     560                 :            :             FKO_ERROR_INVALID_DATA_UTIL_STRTOL_LT_MIN);
     561         [ +  - ]:    1708176 :     fiu_return_on("strtol_wrapper_gt_max",
     562                 :            :             FKO_ERROR_INVALID_DATA_UTIL_STRTOL_GT_MAX);
     563                 :            : #endif
     564                 :            : 
     565                 :    1708176 :     return val;
     566                 :            : }
     567                 :            : 
     568                 :            : /* zero out a buffer before free()
     569                 :            : */
     570                 :   10149178 : int zero_free(char *buf, int len)
     571                 :            : {
     572                 :   10149178 :     int res = FKO_SUCCESS;
     573                 :            : 
     574         [ +  - ]:   10149178 :     if(buf == NULL)
     575                 :            :         return res;
     576                 :            : 
     577         [ -  + ]:   10149178 :     if(len == 0)
     578                 :            :     {
     579                 :          0 :         free(buf);  /* always free() if buf != NULL */
     580                 :          0 :         return res;
     581                 :            :     }
     582                 :            : 
     583                 :   10149178 :     res = zero_buf(buf, len);
     584                 :            : 
     585                 :   10149178 :     free(buf);
     586                 :            : 
     587                 :            : #if HAVE_LIBFIU
     588         [ +  + ]:   10149178 :     fiu_return_on("zero_free_err", FKO_ERROR_ZERO_OUT_DATA);
     589                 :            : #endif
     590                 :            : 
     591                 :   10149169 :     return res;
     592                 :            : }
     593                 :            : 
     594                 :            : /* zero out sensitive information in a way that isn't optimized out by the compiler
     595                 :            :  * since we force a comparison and return an error if there is a problem (though
     596                 :            :  * the caller should do something with this information too).
     597                 :            : */
     598                 :            : int
     599                 :   14231987 : zero_buf(char *buf, int len)
     600                 :            : {
     601                 :   14231987 :     int i, res = FKO_SUCCESS;
     602                 :            : 
     603                 :            : #if HAVE_LIBFIU
     604         [ +  + ]:   14231987 :     fiu_return_on("zero_buf_err", FKO_ERROR_ZERO_OUT_DATA);
     605                 :            : #endif
     606                 :            : 
     607         [ +  - ]:   14231975 :     if(buf == NULL || len == 0)
     608                 :            :         return res;
     609                 :            : 
     610         [ +  + ]:   14231975 :     if(len < 0 || len > MAX_SPA_ENCODED_MSG_SIZE)
     611                 :            :         return FKO_ERROR_ZERO_OUT_DATA;
     612                 :            : 
     613         [ +  + ]: 2471924718 :     for(i=0; i < len; i++)
     614                 : 2457750615 :         buf[i] = 0x0;
     615                 :            : 
     616         [ +  + ]: 2471924718 :     for(i=0; i < len; i++)
     617         [ -  + ]: 2457750615 :         if(buf[i] != 0x0)
     618                 :          0 :             res = FKO_ERROR_ZERO_OUT_DATA;
     619                 :            : 
     620                 :   14174103 :     return res;
     621                 :            : }
     622                 :            : 
     623                 :            : #if defined(WIN32) || !defined(HAVE_STRNDUP)
     624                 :            : /* Windows does not have strndup, so we well implement it here.
     625                 :            :  * This was the Public Domain C Library (PDCLib).
     626                 :            : */
     627                 :            : char
     628                 :            : *strndup( const char * s, size_t len )
     629                 :            : {
     630                 :            :     char* ns = NULL;
     631                 :            :     if(s) {
     632                 :            :         ns = calloc(1, len + 1);
     633                 :            :         if(ns) {
     634                 :            :             ns[len] = 0;
     635                 :            :             // strncpy to be pedantic about modification in multithreaded
     636                 :            :             // applications
     637                 :            :             return strncpy(ns, s, len);
     638                 :            :         }
     639                 :            :     }
     640                 :            :     return ns;
     641                 :            : }
     642                 :            : #endif
     643                 :            : 
     644                 :            : /**
     645                 :            :  * @brief Add a printf style message to a buffer
     646                 :            :  *
     647                 :            :  * This function allows to append a printf style message to a buffer
     648                 :            :  * and prevents buffer overflow by taking care of the size the buffer.
     649                 :            :  * It returns the number of bytes really written to the buffer.
     650                 :            :  * Thus if an error is encoutered during the process the number of bytes
     651                 :            :  * written is set to 0. This way the user knows exactly how many bytes
     652                 :            :  * can be appended afterwards.
     653                 :            :  *
     654                 :            :  * @param buf       Buffer to write the formatted message to
     655                 :            :  * @param buf_size  Maximum number of bytes to write to the buffer
     656                 :            :  * @param msg       Message to format and to append to the buffer
     657                 :            :  *
     658                 :            :  * @return the number of bytes written to the buffer
     659                 :            :  */
     660                 :            : static int
     661                 :      70940 : append_msg_to_buf(char *buf, size_t buf_size, const char* msg, ...)
     662                 :            : {
     663                 :      70940 :     int     bytes_written = 0;  /* Number of bytes written to buf */
     664                 :            :     va_list ap;
     665                 :            : 
     666                 :            :     /* Check if the buffer is valid */
     667         [ +  - ]:      70940 :     if (buf_size > 0)
     668                 :            :     {
     669                 :      70940 :         va_start(ap, msg);
     670                 :            : 
     671                 :            :         /* Format the message like a printf message */
     672                 :      70940 :         bytes_written = vsnprintf(buf, buf_size, msg, ap);
     673                 :            : 
     674                 :            :         /* It looks like the message has been truncated or an error occurred*/
     675         [ +  - ]:      70940 :         if (bytes_written < 0)
     676                 :            :             bytes_written = 0;
     677                 :            : 
     678         [ -  + ]:      70940 :         else if (bytes_written >= buf_size)
     679                 :          0 :             bytes_written = buf_size;
     680                 :            : 
     681                 :            :         /* The messsage has been formatted correctly */
     682                 :            :         else;
     683                 :            : 
     684                 :      70940 :         va_end(ap);
     685                 :            :     }
     686                 :            : 
     687                 :            :     /* No valid buffer has been supplied, thus we do not write anything */
     688                 :            :     else;
     689                 :            : 
     690                 :            :     /* Return the number of bytes written to the buffer */
     691                 :      70940 :     return bytes_written;
     692                 :            : }
     693                 :            : 
     694                 :            : /* Determine if a buffer contains only characters from the base64
     695                 :            :  * encoding set
     696                 :            : */
     697                 :            : int
     698                 :     792650 : is_base64(const unsigned char * const buf, const unsigned short int len)
     699                 :            : {
     700                 :            :     unsigned short int  i;
     701                 :     792650 :     int                 rv = 1;
     702                 :            : 
     703         [ +  + ]:  277624831 :     for(i=0; i<len; i++)
     704                 :            :     {
     705 [ +  + ][ +  + ]:  276832810 :         if(!(isalnum(buf[i]) || buf[i] == '/' || buf[i] == '+' || buf[i] == '='))
         [ +  + ][ +  + ]
     706                 :            :         {
     707                 :            :             rv = 0;
     708                 :            :             break;
     709                 :            :         }
     710                 :            :     }
     711                 :            : 
     712                 :     792650 :     return rv;
     713                 :            : }
     714                 :            : 
     715                 :            : void
     716                 :      13429 : chop_char(char *str, const char chop)
     717                 :            : {
     718         [ +  - ]:      13429 :     if(str != NULL
     719         [ +  + ]:      13429 :             && str[0] != 0x0
     720         [ +  + ]:      13427 :             && strlen(str) > 1 /* don't truncate a single-char string */
     721         [ +  + ]:      13424 :             && str[strlen(str)-1] == chop)
     722                 :      13316 :         str[strlen(str)-1] = 0x0;
     723                 :      13429 :     return;
     724                 :            : }
     725                 :            : 
     726                 :            : void
     727                 :      13327 : chop_newline(char *str)
     728                 :            : {
     729                 :      13327 :     chop_char(str, 0x0a);
     730                 :      13327 :     return;
     731                 :            : }
     732                 :            : 
     733                 :       4164 : void chop_spaces(char *str)
     734                 :            : {
     735                 :            :     int i;
     736 [ +  - ][ +  - ]:       4164 :     if (str != NULL && str[0] != 0x0)
     737                 :            :     {
     738         [ +  - ]:       8328 :         for (i=strlen(str)-1; i > 0; i--)
     739                 :            :         {
     740         [ +  + ]:       8328 :             if(str[i] != 0x20)
     741                 :            :                 break;
     742                 :       4164 :             str[i] = 0x0;
     743                 :            :         }
     744                 :            :     }
     745                 :       4164 :     return;
     746                 :            : }
     747                 :            : 
     748                 :            : static int
     749                 :     193912 : add_argv(char **argv_new, int *argc_new, const char *new_arg)
     750                 :            : {
     751                 :     193912 :     int buf_size = 0;
     752                 :            : 
     753                 :     193912 :     buf_size = strlen(new_arg) + 1;
     754                 :     193912 :     argv_new[*argc_new] = calloc(1, buf_size);
     755                 :            : 
     756         [ +  - ]:     193912 :     if(argv_new[*argc_new] == NULL)
     757                 :            :         return 0;
     758                 :            : 
     759                 :     193912 :     strlcpy(argv_new[*argc_new], new_arg, buf_size);
     760                 :            : 
     761                 :     193912 :     *argc_new += 1;
     762                 :            : 
     763         [ +  + ]:     193912 :     if(*argc_new >= MAX_CMDLINE_ARGS-1)
     764                 :            :         return 0;
     765                 :            : 
     766                 :     193909 :     argv_new[*argc_new] = NULL;
     767                 :            : 
     768                 :     193909 :     return 1;
     769                 :            : }
     770                 :            : 
     771                 :            : int
     772                 :      19270 : strtoargv(const char * const args_str, char **argv_new, int *argc_new)
     773                 :            : {
     774                 :      19270 :     int       current_arg_ctr = 0, i;
     775                 :      19270 :     char      arg_tmp[MAX_ARGS_LINE_LEN] = {0};
     776                 :            : 
     777         [ +  + ]:    1733768 :     for (i=0; i < (int)strlen(args_str); i++)
     778                 :            :     {
     779         [ +  + ]:    1714501 :         if (!isspace(args_str[i]))
     780                 :            :         {
     781                 :    1521509 :             arg_tmp[current_arg_ctr] = args_str[i];
     782                 :    1521509 :             current_arg_ctr++;
     783                 :            :         }
     784                 :            :         else
     785                 :            :         {
     786         [ +  + ]:     192992 :             if(current_arg_ctr > 0)
     787                 :            :             {
     788                 :     174651 :                 arg_tmp[current_arg_ctr] = '\0';
     789         [ +  + ]:     174651 :                 if (add_argv(argv_new, argc_new, arg_tmp) != 1)
     790                 :            :                 {
     791                 :          3 :                     free_argv(argv_new, argc_new);
     792                 :          3 :                     return 0;
     793                 :            :                 }
     794                 :            :                 current_arg_ctr = 0;
     795                 :            :             }
     796                 :            :         }
     797                 :            :     }
     798                 :            : 
     799                 :            :     /* pick up the last argument in the string
     800                 :            :     */
     801         [ +  + ]:      19267 :     if(current_arg_ctr > 0)
     802                 :            :     {
     803                 :      19261 :         arg_tmp[current_arg_ctr] = '\0';
     804         [ -  + ]:      19261 :         if (add_argv(argv_new, argc_new, arg_tmp) != 1)
     805                 :            :         {
     806                 :          0 :             free_argv(argv_new, argc_new);
     807                 :          0 :             return 0;
     808                 :            :         }
     809                 :            :     }
     810                 :            :     return 1;
     811                 :            : }
     812                 :            : 
     813                 :            : void
     814                 :      19270 : free_argv(char **argv_new, int *argc_new)
     815                 :            : {
     816                 :            :     int i;
     817                 :            : 
     818 [ +  - ][ +  - ]:      19270 :     if(argv_new == NULL || *argv_new == NULL)
     819                 :            :         return;
     820                 :            : 
     821         [ +  + ]:     213182 :     for (i=0; i < *argc_new; i++)
     822                 :            :     {
     823         [ +  - ]:     193912 :         if(argv_new[i] == NULL)
     824                 :            :             break;
     825                 :            :         else
     826                 :     193912 :             free(argv_new[i]);
     827                 :            :     }
     828                 :            :     return;
     829                 :            : }
     830                 :            : 
     831                 :            : #define ASCII_LEN 16
     832                 :            : 
     833                 :            : /* Generic hex dump function.
     834                 :            : */
     835                 :            : void
     836                 :        110 : hex_dump(const unsigned char *data, const int size)
     837                 :            : {
     838                 :        110 :     int ln=0, i=0, j=0;
     839                 :        110 :     char ascii_str[ASCII_LEN+1] = {0};
     840                 :            : 
     841         [ +  + ]:      18468 :     for(i=0; i<size; i++)
     842                 :            :     {
     843         [ +  + ]:      18358 :         if((i % ASCII_LEN) == 0)
     844                 :            :         {
     845                 :            :             printf(" %s\n  0x%.4x:  ", ascii_str, i);
     846                 :            :             memset(ascii_str, 0x0, ASCII_LEN-1);
     847                 :       1240 :             j = 0;
     848                 :            :         }
     849                 :            : 
     850                 :      18358 :         printf("%.2x ", data[i]);
     851                 :            : 
     852         [ +  + ]:      18358 :         ascii_str[j++] = (data[i] < 0x20 || data[i] > 0x7e) ? '.' : data[i];
     853                 :            : 
     854         [ +  + ]:      18358 :         if(j == 8)
     855                 :            :             printf(" ");
     856                 :            :     }
     857                 :            : 
     858                 :            :     /* Remainder...
     859                 :            :     */
     860                 :        110 :     ln = strlen(ascii_str);
     861         [ +  - ]:        110 :     if(ln > 0)
     862                 :            :     {
     863         [ +  + ]:       1592 :         for(i=0; i < ASCII_LEN-ln; i++)
     864                 :            :             printf("   ");
     865         [ +  + ]:        110 :         if(ln < 8)
     866                 :            :             printf(" ");
     867                 :            : 
     868                 :            :         printf(" %s\n\n", ascii_str);
     869                 :            :     }
     870                 :        110 :     return;
     871                 :            : }
     872                 :            : 
     873                 :            : /**
     874                 :            :  * @brief Dump a FKO context to a buffer
     875                 :            :  *
     876                 :            :  * This function parses a FKO context and decodes each field to dump them to a
     877                 :            :  * buffer in a comprehensible way.
     878                 :            :  *
     879                 :            :  * @param ctx           FKO context to dump
     880                 :            :  * @param dump_buf      Buffer where to store the dump of the context
     881                 :            :  * @param dump_buf_len  Number of bytes available in the dump_buf array
     882                 :            :  *
     883                 :            :  * @return a FKO error code. FKO_SUCCESS if successful.
     884                 :            :  */
     885                 :            : int
     886                 :       3885 : dump_ctx_to_buffer(fko_ctx_t ctx, char *dump_buf, size_t dump_buf_len)
     887                 :            : {
     888                 :       3885 :     int         cp = 0;
     889                 :       3885 :     int         err = FKO_LAST_ERROR;
     890                 :            : 
     891                 :       3885 :     char       *rand_val        = NULL;
     892                 :       3885 :     char       *username        = NULL;
     893                 :       3885 :     char       *version         = NULL;
     894                 :       3885 :     char       *spa_message     = NULL;
     895                 :       3885 :     char       *nat_access      = NULL;
     896                 :       3885 :     char       *server_auth     = NULL;
     897                 :       3885 :     char       *enc_data        = NULL;
     898                 :       3885 :     char       *hmac_data       = NULL;
     899                 :       3885 :     char       *spa_digest      = NULL;
     900                 :            : #if HAVE_LIBGPGME
     901                 :       3885 :     char          *gpg_signer        = NULL;
     902                 :       3885 :     char          *gpg_recip         = NULL;
     903                 :       3885 :     char          *gpg_sig_id        = NULL;
     904                 :       3885 :     unsigned char  gpg_sig_verify    = 0;
     905                 :       3885 :     unsigned char  gpg_ignore_verify = 0;
     906                 :       3885 :     char          *gpg_sig_fpr       = NULL;
     907                 :       3885 :     char          *gpg_home_dir      = NULL;
     908                 :       3885 :     char          *gpg_exe           = NULL;
     909                 :       3885 :     int            gpg_sigsum        = -1;
     910                 :       3885 :     int            gpg_sig_stat      = -1;
     911                 :            : #endif
     912                 :       3885 :     char       *spa_data         = NULL;
     913                 :       3885 :     char        digest_str[24]   = {0};
     914                 :       3885 :     char        hmac_str[24]     = {0};
     915                 :       3885 :     char        enc_mode_str[FKO_ENCRYPTION_MODE_BUFSIZE] = {0};
     916                 :            : 
     917                 :       3885 :     time_t      timestamp       = 0;
     918                 :       3885 :     short       msg_type        = -1;
     919                 :       3885 :     short       digest_type     = -1;
     920                 :       3885 :     short       hmac_type       = -1;
     921                 :       3885 :     short       encryption_type = -1;
     922                 :       3885 :     int         encryption_mode = -1;
     923                 :       3885 :     int         client_timeout  = -1;
     924                 :            : 
     925                 :            :     /* Zero-ed the buffer */
     926                 :            :     memset(dump_buf, 0, dump_buf_len);
     927                 :            : 
     928                 :            :     /* Make sure the FKO context is initialized before printing it */
     929 [ +  - ][ +  - ]:       3885 :     if(!CTX_INITIALIZED(ctx))
     930                 :            :         err = FKO_ERROR_CTX_NOT_INITIALIZED;
     931                 :            : 
     932                 :            :     else
     933                 :            :     {
     934                 :            :         /* Parse the FKO context and collect data */
     935         [ +  - ]:       3885 :         RETURN_ON_FKO_ERROR(err, fko_get_rand_value(ctx, &rand_val));
     936         [ +  + ]:       3885 :         RETURN_ON_FKO_ERROR(err, fko_get_username(ctx, &username));
     937         [ +  + ]:       3883 :         RETURN_ON_FKO_ERROR(err, fko_get_timestamp(ctx, &timestamp));
     938         [ +  + ]:       3881 :         RETURN_ON_FKO_ERROR(err, fko_get_version(ctx, &version));
     939         [ +  + ]:       3879 :         RETURN_ON_FKO_ERROR(err, fko_get_spa_message_type(ctx, &msg_type));
     940         [ +  + ]:       3877 :         RETURN_ON_FKO_ERROR(err, fko_get_spa_message(ctx, &spa_message));
     941         [ +  + ]:       3875 :         RETURN_ON_FKO_ERROR(err, fko_get_spa_nat_access(ctx, &nat_access));
     942         [ +  + ]:       3873 :         RETURN_ON_FKO_ERROR(err, fko_get_spa_server_auth(ctx, &server_auth));
     943         [ +  + ]:       3871 :         RETURN_ON_FKO_ERROR(err, fko_get_spa_client_timeout(ctx, &client_timeout));
     944         [ +  + ]:       3869 :         RETURN_ON_FKO_ERROR(err, fko_get_spa_digest_type(ctx, &digest_type));
     945         [ +  - ]:       3867 :         RETURN_ON_FKO_ERROR(err, fko_get_spa_hmac_type(ctx, &hmac_type));
     946         [ +  - ]:       3867 :         RETURN_ON_FKO_ERROR(err, fko_get_spa_encryption_type(ctx, &encryption_type));
     947         [ +  - ]:       3867 :         RETURN_ON_FKO_ERROR(err, fko_get_spa_encryption_mode(ctx, &encryption_mode));
     948         [ +  - ]:       3867 :         RETURN_ON_FKO_ERROR(err, fko_get_encoded_data(ctx, &enc_data));
     949         [ +  - ]:       3867 :         RETURN_ON_FKO_ERROR(err, fko_get_spa_hmac(ctx, &hmac_data));
     950         [ +  + ]:       3867 :         RETURN_ON_FKO_ERROR(err, fko_get_spa_digest(ctx, &spa_digest));
     951         [ +  - ]:       3865 :         RETURN_ON_FKO_ERROR(err, fko_get_spa_data(ctx, &spa_data));
     952                 :            : 
     953                 :            : #if HAVE_LIBGPGME
     954         [ +  + ]:       3865 :         if(encryption_mode == FKO_ENC_MODE_ASYMMETRIC)
     955                 :            :         {
     956                 :            :             /* Populate GPG variables
     957                 :            :             */
     958         [ +  - ]:        137 :             RETURN_ON_FKO_ERROR(err, fko_get_gpg_signer(ctx, &gpg_signer));
     959         [ +  - ]:        137 :             RETURN_ON_FKO_ERROR(err, fko_get_gpg_recipient(ctx, &gpg_recip));
     960         [ +  - ]:        137 :             RETURN_ON_FKO_ERROR(err, fko_get_gpg_signature_verify(ctx, &gpg_sig_verify));
     961         [ +  - ]:        137 :             RETURN_ON_FKO_ERROR(err, fko_get_gpg_ignore_verify_error(ctx, &gpg_ignore_verify));
     962         [ +  - ]:        137 :             RETURN_ON_FKO_ERROR(err, fko_get_gpg_home_dir(ctx, &gpg_home_dir));
     963         [ +  - ]:        137 :             RETURN_ON_FKO_ERROR(err, fko_get_gpg_exe(ctx, &gpg_exe));
     964         [ +  + ]:        137 :             if(fko_get_gpg_signature_id(ctx, &gpg_sig_id) != FKO_SUCCESS)
     965                 :         77 :                 gpg_sig_id = NULL;
     966         [ +  + ]:        137 :             if(fko_get_gpg_signature_summary(ctx, &gpg_sigsum) != FKO_SUCCESS)
     967                 :         77 :                 gpg_sigsum = -1;
     968         [ +  + ]:        137 :             if(fko_get_gpg_signature_status(ctx, &gpg_sig_stat) != FKO_SUCCESS)
     969                 :         77 :                 gpg_sig_stat = -1;
     970         [ +  + ]:        137 :             if(fko_get_gpg_signature_fpr(ctx, &gpg_sig_fpr) != FKO_SUCCESS)
     971                 :         77 :                 gpg_sig_fpr = NULL;
     972                 :            :         }
     973                 :            : #endif
     974                 :            : 
     975                 :            :         /* Convert the digest integer to a string */
     976         [ +  - ]:       3865 :         if (digest_inttostr(digest_type, digest_str, sizeof(digest_str)) != 0)
     977                 :            :             return (FKO_ERROR_INVALID_DIGEST_TYPE);
     978                 :            : 
     979                 :            :         /* Convert the encryption mode integer to a string */
     980         [ +  - ]:       3865 :         if (enc_mode_inttostr(encryption_mode, enc_mode_str, sizeof(enc_mode_str)) != 0)
     981                 :            :             return (FKO_ERROR_INVALID_ENCRYPTION_TYPE);
     982                 :            : 
     983                 :            :         /* Convert the HMAC digest integer to a string if a HMAC message is available */
     984         [ +  + ]:       3865 :         if (ctx->msg_hmac_len != 0)
     985                 :            :         {
     986         [ +  - ]:       2098 :             if (hmac_digest_inttostr(hmac_type, hmac_str, sizeof(hmac_str)) != 0)
     987                 :            :                 return (FKO_ERROR_UNSUPPORTED_HMAC_MODE);
     988                 :            :         }
     989                 :            : 
     990                 :            :         /* Fill in the buffer to dump */
     991                 :       3865 :         cp  = append_msg_to_buf(dump_buf,    dump_buf_len,    "SPA Field Values:\n=================\n");
     992         [ +  - ]:       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "   Random Value: %s\n", rand_val == NULL ? NULL_STRING : rand_val);
     993         [ +  - ]:       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "       Username: %s\n", username == NULL ? NULL_STRING : username);
     994                 :       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "      Timestamp: %u\n", (unsigned int) timestamp);
     995         [ +  - ]:       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "    FKO Version: %s\n", version == NULL ? NULL_STRING : version);
     996                 :       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "   Message Type: %i (%s)\n", msg_type, msg_type_inttostr(msg_type));
     997         [ +  - ]:       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " Message String: %s\n", spa_message == NULL ? NULL_STRING : spa_message);
     998         [ +  + ]:       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "     Nat Access: %s\n", nat_access == NULL ? NULL_STRING : nat_access);
     999         [ +  + ]:       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "    Server Auth: %s\n", server_auth == NULL ? NULL_STRING : server_auth);
    1000                 :       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " Client Timeout: %u\n", client_timeout);
    1001                 :       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "    Digest Type: %u (%s)\n", digest_type, digest_str);
    1002         [ +  + ]:       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "      HMAC Type: %u (%s)\n", hmac_type, hmac_type == 0 ? "None" : hmac_str);
    1003                 :       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "Encryption Type: %d (%s)\n", encryption_type, enc_type_inttostr(encryption_type));
    1004                 :       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "Encryption Mode: %d (%s)\n", encryption_mode, enc_mode_str);
    1005                 :            : #if HAVE_LIBGPGME
    1006         [ +  + ]:       3865 :         if(encryption_mode == FKO_ENC_MODE_ASYMMETRIC)
    1007                 :            :         {
    1008         [ +  + ]:        137 :             cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "     GPG signer: %s\n", gpg_signer == NULL ? NULL_STRING : gpg_signer);
    1009         [ +  + ]:        137 :             cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "  GPG recipient: %s\n", gpg_recip == NULL ? NULL_STRING : gpg_recip);
    1010         [ +  + ]:        137 :             cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " GPG sig verify: %s\n", gpg_sig_verify == 0 ? "No" : "Yes");
    1011         [ +  + ]:        137 :             cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " GPG ignore sig: %s\n", gpg_ignore_verify == 0 ? "No" : "Yes");
    1012         [ +  + ]:        137 :             cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "     GPG sig ID: %s\n", gpg_sig_id == NULL ? NULL_STRING : gpg_sig_id);
    1013         [ +  + ]:        137 :             cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "    GPG sig fpr: %s\n", gpg_sig_fpr == NULL ? NULL_STRING : gpg_sig_fpr);
    1014                 :        137 :             cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "GPG sig summary: %d\n", gpg_sigsum);
    1015                 :        137 :             cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " GPG sig status: %d\n", gpg_sig_stat);
    1016         [ +  - ]:        137 :             cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "   GPG home dir: %s\n", gpg_home_dir == NULL ? NULL_STRING : gpg_home_dir);
    1017         [ +  + ]:        137 :             cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "        GPG exe: %s\n", gpg_exe == NULL ? GPG_EXE : gpg_exe);
    1018                 :            :         }
    1019                 :            : #endif
    1020         [ +  - ]:       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "   Encoded Data: %s\n", enc_data == NULL ? NULL_STRING : enc_data);
    1021         [ +  - ]:       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "SPA Data Digest: %s\n", spa_digest == NULL ? NULL_STRING : spa_digest);
    1022         [ +  + ]:       3865 :         cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "           HMAC: %s\n", hmac_data == NULL ? NULL_STRING : hmac_data);
    1023                 :       3865 :         append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " Final SPA Data: %s\n", spa_data);
    1024                 :            : 
    1025                 :       3865 :         err = FKO_SUCCESS;
    1026                 :            :     }
    1027                 :            : 
    1028                 :       3865 :     return (err);
    1029                 :            : }
    1030                 :            : 
    1031                 :            : /**
    1032                 :            :  * @brief Grab the sin address from the sockaddr structure.
    1033                 :            :  *
    1034                 :            :  * This function returns the sin address as a sockaddr_in or sockaddr_in6
    1035                 :            :  * structure according to the family set (ipv4 or ipv6) in the sockaddr
    1036                 :            :  * structure.
    1037                 :            :  *
    1038                 :            :  * @param sa sockaddr strcuture
    1039                 :            :  *
    1040                 :            :  * @return the sin addr if the sa family is AF_INET or the sin6_addr otherwise.
    1041                 :            :  */
    1042                 :            : static void *
    1043                 :          1 : get_in_addr(struct sockaddr *sa)
    1044                 :            : {
    1045         [ +  - ]:          1 :   if (sa->sa_family == AF_INET)
    1046                 :            :   {
    1047                 :          1 :     return &(((struct sockaddr_in*)sa)->sin_addr);
    1048                 :            :   }
    1049                 :            : 
    1050                 :            :   else
    1051                 :            :   {
    1052                 :          0 :     return &(((struct sockaddr_in6*)sa)->sin6_addr);
    1053                 :            :   }
    1054                 :            : }
    1055                 :            : 
    1056                 :            : /**
    1057                 :            :  * @brief  Resolve a domain name as an IP address.
    1058                 :            :  *
    1059                 :            :  * @param dns_str    Name of the host to resolve.
    1060                 :            :  * @param hints      Hints to reduce the number of result from getaddrinfo()
    1061                 :            :  * @param ip_str     String where to store the resolve ip address
    1062                 :            :  * @param ip_bufsize Number of bytes available in the ip_str buffer
    1063                 :            :  * @param opts       Client command line options
    1064                 :            :  *
    1065                 :            :  * @return 0 if successful, 1 if an error occurred.
    1066                 :            :  */
    1067                 :            : int
    1068                 :          2 : ipv4_resolve(const char *dns_str, char *ip_str)
    1069                 :            : {
    1070                 :            :     int                 error;      /* Function error return code */
    1071                 :          2 :     size_t ip_bufsize = MAX_IPV4_STR_LEN;
    1072                 :            :     struct addrinfo     hints;
    1073                 :            :     struct addrinfo    *result;     /* Result of getaddrinfo() */
    1074                 :            :     struct addrinfo    *rp;         /* Element of the linked list returned by getaddrinfo() */
    1075                 :            : 
    1076                 :            : #if WIN32 && WINVER <= 0x0600
    1077                 :            :     struct sockaddr_in *in;
    1078                 :            :     char               *win_ip;
    1079                 :            : #else
    1080                 :            :     struct sockaddr_in *sai_remote; /* Remote host information as a sockaddr_in structure */
    1081                 :            : #endif
    1082                 :            : 
    1083                 :            : #if WIN32 
    1084                 :            :     WSADATA wsa_data;
    1085                 :            :         error = WSAStartup( MAKEWORD(1,1), &wsa_data );
    1086                 :            :     if( error != 0 )
    1087                 :            :     {
    1088                 :            :         fprintf(stderr, "Winsock initialization error %d", error);
    1089                 :            :         return(error);
    1090                 :            :     }
    1091                 :            : #endif
    1092                 :            : 
    1093                 :            :     memset(&hints, 0 , sizeof(hints));
    1094                 :          2 :     hints.ai_family = AF_INET;
    1095                 :          2 :     hints.ai_socktype = SOCK_STREAM;
    1096                 :          2 :     hints.ai_protocol = IPPROTO_TCP;
    1097                 :            : 
    1098                 :            :     /* Try to resolve the host name */
    1099                 :          2 :     error = getaddrinfo(dns_str, NULL, &hints, &result);
    1100         [ +  + ]:          2 :     if (error != 0)
    1101                 :          1 :         fprintf(stderr, "ipv4_resolve() : %s\n", gai_strerror(error));
    1102                 :            : 
    1103                 :            :     else
    1104                 :            :     {
    1105                 :          1 :         error = 1;
    1106                 :            : 
    1107                 :            :         /* Go through the linked list of addrinfo structures */
    1108         [ +  - ]:          1 :         for (rp = result; rp != NULL; rp = rp->ai_next)
    1109                 :            :         {
    1110                 :            :             memset(ip_str, 0, ip_bufsize);
    1111                 :            : 
    1112                 :            : #if WIN32 && WINVER <= 0x0600
    1113                 :            :                         /* On older Windows systems (anything before Vista?),
    1114                 :            :                          * we use inet_ntoa for now.
    1115                 :            :                         */
    1116                 :            :                         in = (struct sockaddr_in*)(rp->ai_addr);
    1117                 :            :                         win_ip = inet_ntoa(in->sin_addr);
    1118                 :            : 
    1119                 :            :                         if (win_ip != NULL && (strlcpy(ip_str, win_ip, ip_bufsize) > 0))
    1120                 :            : #else
    1121                 :          1 :             sai_remote = (struct sockaddr_in *)get_in_addr((struct sockaddr *)(rp->ai_addr));
    1122         [ -  + ]:          1 :             if (inet_ntop(rp->ai_family, sai_remote, ip_str, ip_bufsize) != NULL)
    1123                 :            : #endif
    1124                 :            :             {
    1125                 :            :                 error = 0;
    1126                 :            :                 break;
    1127                 :            :             }
    1128                 :            :         }
    1129                 :            : 
    1130                 :            :         /* Free our result from getaddrinfo() */
    1131                 :          1 :         freeaddrinfo(result);
    1132                 :            :     }
    1133                 :            : 
    1134                 :            : #if WIN32
    1135                 :            :         WSACleanup();
    1136                 :            : #endif
    1137                 :          2 :     return error;
    1138                 :            : }
    1139                 :            : 
    1140                 :            : int
    1141                 :     192499 : count_characters(const char *str, const char match, int len)
    1142                 :            : {
    1143                 :     192499 :     int i, count = 0;
    1144                 :            : 
    1145 [ +  + ][ +  - ]:    6293975 :     for (i=0; i < len && str[i] != '\0'; i++) {
    1146         [ +  + ]:    6101476 :         if (str[i] == match)
    1147                 :     687044 :             count++;
    1148                 :            :     }
    1149                 :     192499 :     return count;
    1150                 :            : }
    1151                 :            : 
    1152                 :            : #ifdef HAVE_C_UNIT_TESTS /* LCOV_EXCL_START */
    1153                 :            : 
    1154                 :            : DECLARE_UTEST(test_hostname_validator, "test the is_valid_hostname function")
    1155                 :            : {
    1156                 :            :     char test_hostname[300];
    1157                 :            :     strcpy(test_hostname, "a");
    1158                 :            :     CU_ASSERT(is_valid_hostname(test_hostname, strlen(test_hostname)) == 1);
    1159                 :            :     strcpy(test_hostname, "a.b");
    1160                 :            :     CU_ASSERT(is_valid_hostname(test_hostname, strlen(test_hostname)) == 1);
    1161                 :            :     strcpy(test_hostname, "a.b.");
    1162                 :            :     CU_ASSERT(is_valid_hostname(test_hostname, strlen(test_hostname)) == 1);
    1163                 :            :     strcpy(test_hostname, "a.");
    1164                 :            :     CU_ASSERT(is_valid_hostname(test_hostname, strlen(test_hostname)) == 1);
    1165                 :            : 
    1166                 :            :     strcpy(test_hostname, "a..b");
    1167                 :            :     CU_ASSERT(is_valid_hostname(test_hostname, strlen(test_hostname)) == 0);
    1168                 :            :     strcpy(test_hostname, ".a.b");
    1169                 :            :     CU_ASSERT(is_valid_hostname(test_hostname, strlen(test_hostname)) == 0);
    1170                 :            :     strcpy(test_hostname, "a-.b");
    1171                 :            :     CU_ASSERT(is_valid_hostname(test_hostname, strlen(test_hostname)) == 0);
    1172                 :            :     strcpy(test_hostname, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.b");
    1173                 :            :     CU_ASSERT(is_valid_hostname(test_hostname, strlen(test_hostname)) == 0);
    1174                 :            : }
    1175                 :            : DECLARE_UTEST(test_ipv4_validator, "test the is_valid_ipv4_addr function")
    1176                 :            : {
    1177                 :            :     char test_str[32];
    1178                 :            :     strcpy(test_str, "1.2.3.4");
    1179                 :            :     CU_ASSERT(is_valid_ipv4_addr(test_str, strlen(test_str)));
    1180                 :            :     strcpy(test_str, "127.0.0.2");
    1181                 :            :     CU_ASSERT(is_valid_ipv4_addr(test_str, 9));
    1182                 :            :     strcpy(test_str, "1.2.3.400");
    1183                 :            :     CU_ASSERT(is_valid_ipv4_addr(test_str, strlen(test_str)) == 0);
    1184                 :            : }
    1185                 :            : 
    1186                 :            : DECLARE_UTEST(test_count_characters, "test the count_characters function")
    1187                 :            : {
    1188                 :            :     char test_str[32];
    1189                 :            :     strcpy(test_str, "abcd");
    1190                 :            :     CU_ASSERT(count_characters(test_str, 'a', 4) == 1);
    1191                 :            :     strcpy(test_str, "aacd");
    1192                 :            :     CU_ASSERT(count_characters(test_str, 'a', 4) == 2);
    1193                 :            :     strcpy(test_str, "a,b,c,d,");
    1194                 :            :     CU_ASSERT(count_characters(test_str, ',', 4) == 2);
    1195                 :            :     strcpy(test_str, "a,b,c,d,");
    1196                 :            :     CU_ASSERT(count_characters(test_str, ',', 8) == 4);
    1197                 :            :     strcpy(test_str, "aaaa");
    1198                 :            :     CU_ASSERT(count_characters(test_str, 'a', 3) == 3);
    1199                 :            : }
    1200                 :            : 
    1201                 :            : int register_utils_test(void)
    1202                 :            : {
    1203                 :            :     ts_init(&TEST_SUITE(utils_test), TEST_SUITE_DESCR(utils_test), NULL, NULL);
    1204                 :            :     ts_add_utest(&TEST_SUITE(utils_test), UTEST_FCT(test_count_characters), UTEST_DESCR(test_count_characters));
    1205                 :            :     ts_add_utest(&TEST_SUITE(utils_test), UTEST_FCT(test_ipv4_validator), UTEST_DESCR(test_ipv4_validator));
    1206                 :            :     ts_add_utest(&TEST_SUITE(utils_test), UTEST_FCT(test_hostname_validator), UTEST_DESCR(test_hostname_validator));
    1207                 :            :     return register_ts(&TEST_SUITE(utils_test));
    1208                 :            : }
    1209                 :            : #endif /* LCOV_EXCL_STOP */
    1210                 :            : /***EOF***/

Generated by: LCOV version 1.10