LCOV - code coverage report
Current view: top level - client - utils.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 74 80 92.5 %
Date: 2014-11-16 Functions: 8 8 100.0 %
Branches: 43 52 82.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  *****************************************************************************
       3                 :            :  *
       4                 :            :  * File:    utils.c
       5                 :            :  *
       6                 :            :  * Purpose: General/Generic functions for the fwknop client.
       7                 :            :  *
       8                 :            :  *  Fwknop is developed primarily by the people listed in the file 'AUTHORS'.
       9                 :            :  *  Copyright (C) 2009-2014 fwknop developers and contributors. For a full
      10                 :            :  *  list of contributors, see the file 'CREDITS'.
      11                 :            :  *
      12                 :            :  *  License (GNU General Public License):
      13                 :            :  *
      14                 :            :  *  This program is free software; you can redistribute it and/or
      15                 :            :  *  modify it under the terms of the GNU General Public License
      16                 :            :  *  as published by the Free Software Foundation; either version 2
      17                 :            :  *  of the License, or (at your option) any later version.
      18                 :            :  *
      19                 :            :  *  This program is distributed in the hope that it will be useful,
      20                 :            :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      21                 :            :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      22                 :            :  *  GNU General Public License for more details.
      23                 :            :  *
      24                 :            :  *  You should have received a copy of the GNU General Public License
      25                 :            :  *  along with this program; if not, write to the Free Software
      26                 :            :  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
      27                 :            :  *  USA
      28                 :            :  *
      29                 :            :  *****************************************************************************
      30                 :            : */
      31                 :            : #include "common.h"
      32                 :            : #include "fwknop_common.h"
      33                 :            : #include "utils.h"
      34                 :            : #ifndef WIN32
      35                 :            : #include <arpa/inet.h>
      36                 :            : #endif
      37                 :            : 
      38                 :            : static void *get_in_addr(struct sockaddr *sa);
      39                 :            : 
      40                 :            : /**
      41                 :            :  * Structure to handle a protocol string and its associated integer value
      42                 :            :  */
      43                 :            : typedef struct fko_protocol
      44                 :            : {
      45                 :            :     const char  str[PROTOCOL_BUFSIZE];      /*!< String which represents a protocol value for the FKO library */
      46                 :            :     int         val;                        /*!< Value of the protocol according to the FKO library */
      47                 :            : } fko_protocol_t;
      48                 :            : 
      49                 :            : static fko_protocol_t fko_protocol_array[] =
      50                 :            : {
      51                 :            :     { "udpraw", FKO_PROTO_UDP_RAW   },
      52                 :            :     { "udp",    FKO_PROTO_UDP       },
      53                 :            :     { "tcpraw", FKO_PROTO_TCP_RAW   },
      54                 :            :     { "tcp",    FKO_PROTO_TCP       },
      55                 :            :     { "icmp",   FKO_PROTO_ICMP      },
      56                 :            :     { "http",   FKO_PROTO_HTTP      }
      57                 :            : };
      58                 :            : 
      59                 :            : int
      60                 :       2641 : verify_file_perms_ownership(const char *file)
      61                 :            : {
      62                 :       2641 :     int res = 1;
      63                 :            : 
      64                 :            : #if HAVE_STAT
      65                 :            :     struct stat st;
      66                 :            : 
      67                 :            :     /* Every file that the fwknop client deals with should be owned
      68                 :            :      * by the user and permissions set to 600 (user read/write)
      69                 :            :     */
      70         [ +  + ]:       2641 :     if((stat(file, &st)) == 0)
      71                 :            :     {
      72                 :            :         /* Make sure it is a regular file
      73                 :            :         */
      74         [ +  + ]:       2636 :         if(S_ISREG(st.st_mode) != 1 && S_ISLNK(st.st_mode) != 1)
      75                 :            :         {
      76                 :          2 :             log_msg(LOG_VERBOSITY_ERROR,
      77                 :            :                 "[-] file: %s is not a regular file or symbolic link.",
      78                 :            :                 file
      79                 :            :             );
      80                 :            :             /* when we start in enforcing this instead of just warning
      81                 :            :              * the user
      82                 :            :             res = 0;
      83                 :            :             */
      84                 :            :         }
      85                 :            : 
      86         [ +  + ]:       2636 :         if((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != (S_IRUSR|S_IWUSR))
      87                 :            :         {
      88                 :         39 :             log_msg(LOG_VERBOSITY_ERROR,
      89                 :            :                 "[-] file: %s permissions should only be user read/write (0600, -rw-------)",
      90                 :            :                 file
      91                 :            :             );
      92                 :            :             /* when we start in enforcing this instead of just warning
      93                 :            :              * the user
      94                 :            :             res = 0;
      95                 :            :             */
      96                 :            :         }
      97                 :            : 
      98         [ +  + ]:       2636 :         if(st.st_uid != getuid())
      99                 :            :         {
     100                 :        224 :             log_msg(LOG_VERBOSITY_ERROR, "[-] file: %s not owned by current effective user id",
     101                 :            :                 file);
     102                 :            :             /* when we start in enforcing this instead of just warning
     103                 :            :              * the user
     104                 :            :             res = 0;
     105                 :            :             */
     106                 :            :         }
     107                 :            :     }
     108                 :            :     else
     109                 :            :     {
     110                 :            :         /* if the path doesn't exist, just return, but otherwise something
     111                 :            :          * went wrong
     112                 :            :         */
     113         [ +  + ]:          5 :         if(errno != ENOENT)
     114                 :            :         {
     115                 :          1 :             log_msg(LOG_VERBOSITY_ERROR, "[-] stat() against file: %s returned: %s",
     116                 :            :                 file, strerror(errno));
     117                 :          1 :             res = 0;
     118                 :            :         }
     119                 :            :     }
     120                 :            : #endif
     121                 :            : 
     122                 :       2641 :     return res;
     123                 :            : }
     124                 :            : 
     125                 :            : /**
     126                 :            :  * @brief Grab the sin address from the sockaddr structure.
     127                 :            :  *
     128                 :            :  * This function returns the sin address as a sockaddr_in or sockaddr_in6
     129                 :            :  * structure according to the family set (ipv4 or ipv6) in the sockaddr
     130                 :            :  * structure.
     131                 :            :  *
     132                 :            :  * @param sa sockaddr strcuture
     133                 :            :  *
     134                 :            :  * @return the sin addr if the sa family is AF_INET or the sin6_addr otherwise.
     135                 :            :  */
     136                 :            : static void *
     137                 :         14 : get_in_addr(struct sockaddr *sa)
     138                 :            : {
     139         [ +  - ]:         14 :   if (sa->sa_family == AF_INET)
     140                 :            :   {
     141                 :         14 :     return &(((struct sockaddr_in*)sa)->sin_addr);
     142                 :            :   }
     143                 :            : 
     144                 :            :   else
     145                 :            :   {
     146                 :          0 :     return &(((struct sockaddr_in6*)sa)->sin6_addr);
     147                 :            :   }
     148                 :            : }
     149                 :            : 
     150                 :            : /**
     151                 :            :  * @brief  Resolve a domain name as an ip adress.
     152                 :            :  *
     153                 :            :  * @param dns_str    Name of the host to resolve.
     154                 :            :  * @param hints      Hints to reduce the number of result from getaddrinfo()
     155                 :            :  * @param ip_str     String where to store the resolve ip address
     156                 :            :  * @param ip_bufsize Number of bytes available in the ip_str buffer
     157                 :            :  *
     158                 :            :  * @return 0 if successful, 1 if an error occured.
     159                 :            :  */
     160                 :            : int
     161                 :         17 : resolve_dest_adr(const char *dns_str, struct addrinfo *hints, char *ip_str, size_t ip_bufsize)
     162                 :            : {
     163                 :            :     int                 error;      /* Function error return code */
     164                 :            :     struct addrinfo    *result;     /* Result of getaddrinfo() */
     165                 :            :     struct addrinfo    *rp;         /* Element of the linked list returned by getaddrinfo() */
     166                 :            : #if WIN32 && WINVER <= 0x0600
     167                 :            :         struct sockaddr_in *in;
     168                 :            :         char                       *win_ip;
     169                 :            : #else
     170                 :            :     struct sockaddr_in *sai_remote; /* Remote host information as a sockaddr_in structure */
     171                 :            : #endif
     172                 :            : 
     173                 :            :     /* Try to resolve the host name */
     174                 :         17 :     error = getaddrinfo(dns_str, NULL, hints, &result);
     175         [ +  + ]:         17 :     if (error != 0)
     176                 :          3 :         fprintf(stderr, "resolve_dest_adr() : %s\n", gai_strerror(error));
     177                 :            : 
     178                 :            :     else
     179                 :            :     {
     180                 :         14 :         error = 1;
     181                 :            : 
     182                 :            :         /* Go through the linked list of addrinfo structures */
     183         [ +  - ]:         14 :         for (rp = result; rp != NULL; rp = rp->ai_next)
     184                 :            :         {
     185                 :            :             memset(ip_str, 0, ip_bufsize);
     186                 :            : #if WIN32 && WINVER <= 0x0600
     187                 :            :                         /* On older Windows systems (anything before Vista?),
     188                 :            :                          * we use inet_ntoa for now.
     189                 :            :                         */
     190                 :            :                         in = (struct sockaddr_in*)(rp->ai_addr);
     191                 :            :                         win_ip = inet_ntoa(in->sin_addr);
     192                 :            : 
     193                 :            :                         if (win_ip != NULL && (strlcpy(ip_str, win_ip, ip_bufsize) > 0))
     194                 :            : #else
     195                 :         14 :             sai_remote = (struct sockaddr_in *)get_in_addr((struct sockaddr *)(rp->ai_addr));
     196         [ -  + ]:         14 :             if (inet_ntop(rp->ai_family, sai_remote, ip_str, ip_bufsize) != NULL)
     197                 :            : #endif
     198                 :            :                         {
     199                 :            :                 error = 0;
     200                 :            :                 break;
     201                 :            :             }
     202                 :            :             else
     203                 :          0 :                 log_msg(LOG_VERBOSITY_ERROR, "resolve_dest_adr() : inet_ntop (%d) - %s",
     204                 :          0 :                         errno, strerror(errno));
     205                 :            :         }
     206                 :            : 
     207                 :            :         /* Free our result from getaddrinfo() */
     208                 :         14 :         freeaddrinfo(result);
     209                 :            :     }
     210                 :            : 
     211                 :         17 :     return error;
     212                 :            : }
     213                 :            : 
     214                 :            : /**
     215                 :            :  * @brief Return a protocol string according to a protocol integer value
     216                 :            :  *
     217                 :            :  * This function checks if the protocol integer is valid, and write the protocol
     218                 :            :  * string associated.
     219                 :            :  *
     220                 :            :  * @param proto protocol inetger value (UDP_RAW, UDP, TCPRAW...)
     221                 :            :  * @param proto_str Buffer to write the protocol string
     222                 :            :  * @param proto_size size of the protocol string buffer
     223                 :            :  *
     224                 :            :  * @return -1 if the protocol integer value is not supported, 0 otherwise
     225                 :            :  */
     226                 :            : short
     227                 :       1929 : proto_inttostr(int proto, char *proto_str, size_t proto_size)
     228                 :            : {
     229                 :       1929 :     short           proto_error = -1;
     230                 :            :     unsigned char   ndx_proto;          /* Index for the fko_protocol_t structure */
     231                 :            : 
     232                 :            :     /* Initialize the protocol string */
     233                 :            :     memset(proto_str, 0, proto_size);
     234                 :            : 
     235                 :            :     /* Look into the fko_protocol_array to find out the right protocol */
     236         [ +  - ]:       3921 :     for (ndx_proto = 0 ; ndx_proto < ARRAY_SIZE(fko_protocol_array) ; ndx_proto++)
     237                 :            :     {
     238                 :            :         /* If the protocol matches, grab it */
     239         [ +  + ]:       3921 :         if (fko_protocol_array[ndx_proto].val == proto)
     240                 :            :         {
     241                 :       1929 :             strlcpy(proto_str, fko_protocol_array[ndx_proto].str, proto_size);
     242                 :       1929 :             proto_error = 0;
     243                 :       1929 :             break;
     244                 :            :         }
     245                 :            :     }
     246                 :            : 
     247                 :       1929 :     return proto_error;
     248                 :            : 
     249                 :            : }
     250                 :            : 
     251                 :            : /**
     252                 :            :  * @brief Convert a protocol string to its integer value.
     253                 :            :  *
     254                 :            :  * @param pr_str Protocol string (UDP_RAW, UDP, TCPRAW...)
     255                 :            :  *
     256                 :            :  * @return -1 if the protocol string is not supported, otherwise the protocol value
     257                 :            :  */
     258                 :            : short
     259                 :         50 : proto_strtoint(const char *pr_str)
     260                 :            : {
     261                 :            :     unsigned char   ndx_proto;          /* Index for the fko_protocol_t structure */
     262                 :         50 :     int             proto_int = -1;     /* Protocol integer value */
     263                 :            : 
     264                 :            :     /* Look into the fko_protocol_array to find out the right protocol */
     265         [ +  + ]:        165 :     for (ndx_proto = 0 ; ndx_proto < ARRAY_SIZE(fko_protocol_array) ; ndx_proto++)
     266                 :            :     {
     267                 :            :         /* If the protocol matches, grab it */
     268         [ +  + ]:        163 :         if (strcasecmp(pr_str, fko_protocol_array[ndx_proto].str) == 0)
     269                 :            :         {
     270                 :         48 :             proto_int = fko_protocol_array[ndx_proto].val;
     271                 :         48 :             break;
     272                 :            :         }
     273                 :            :     }
     274                 :            : 
     275                 :         50 :     return proto_int;
     276                 :            : }
     277                 :            : 
     278                 :            : static int
     279                 :        217 : add_argv(char **argv_new, int *argc_new,
     280                 :            :         const char *new_arg, fko_cli_options_t *opts)
     281                 :            : {
     282                 :        217 :     int buf_size = 0;
     283                 :            : 
     284         [ +  + ]:        217 :     if(opts->verbose > 2)
     285                 :          9 :         log_msg(LOG_VERBOSITY_NORMAL, "[+] add_argv() + arg: %s", new_arg);
     286                 :            : 
     287                 :        217 :     buf_size = strlen(new_arg) + 1;
     288                 :        217 :     argv_new[*argc_new] = calloc(1, buf_size);
     289                 :            : 
     290         [ -  + ]:        217 :     if(argv_new[*argc_new] == NULL)
     291                 :            :     {
     292                 :          0 :         log_msg(LOG_VERBOSITY_ERROR, "[*] Memory allocation error.");
     293                 :            :         return 0;
     294                 :            :     }
     295                 :        217 :     strlcpy(argv_new[*argc_new], new_arg, buf_size);
     296                 :            : 
     297                 :        217 :     *argc_new += 1;
     298                 :            : 
     299         [ +  + ]:        217 :     if(*argc_new >= MAX_CMDLINE_ARGS-1)
     300                 :            :     {
     301                 :          1 :         log_msg(LOG_VERBOSITY_ERROR, "[*] max command line args exceeded.");
     302                 :            :         return 0;
     303                 :            :     }
     304                 :            : 
     305                 :        216 :     argv_new[*argc_new] = NULL;
     306                 :            : 
     307                 :            :     return 1;
     308                 :            : }
     309                 :            : 
     310                 :            : int
     311                 :         25 : strtoargv(char *args_str, char **argv_new, int *argc_new,
     312                 :        217 :         fko_cli_options_t *opts)
     313                 :            : {
     314                 :         25 :     int       current_arg_ctr = 0, i;
     315                 :         25 :     char      arg_tmp[MAX_LINE_LEN] = {0};
     316                 :            : 
     317         [ +  + ]:       2475 :     for (i=0; i < (int)strlen(args_str); i++)
     318                 :            :     {
     319         [ +  + ]:       2451 :         if (!isspace(args_str[i]))
     320                 :            :         {
     321                 :       2250 :             arg_tmp[current_arg_ctr] = args_str[i];
     322                 :       2250 :             current_arg_ctr++;
     323                 :            :         }
     324                 :            :         else
     325                 :            :         {
     326         [ +  + ]:        201 :             if(current_arg_ctr > 0)
     327                 :            :             {
     328                 :        195 :                 arg_tmp[current_arg_ctr] = '\0';
     329         [ +  + ]:        195 :                 if (add_argv(argv_new, argc_new, arg_tmp, opts) != 1)
     330                 :            :                 {
     331                 :          1 :                     free_argv(argv_new, argc_new);
     332                 :          1 :                     return 0;
     333                 :            :                 }
     334                 :            :                 current_arg_ctr = 0;
     335                 :            :             }
     336                 :            :         }
     337                 :            :     }
     338                 :            : 
     339                 :            :     /* pick up the last argument in the string
     340                 :            :     */
     341         [ +  + ]:         24 :     if(current_arg_ctr > 0)
     342                 :            :     {
     343                 :         22 :         arg_tmp[current_arg_ctr] = '\0';
     344         [ -  + ]:         22 :         if (add_argv(argv_new, argc_new, arg_tmp, opts) != 1)
     345                 :            :         {
     346                 :          0 :             free_argv(argv_new, argc_new);
     347                 :          0 :             return 0;
     348                 :            :         }
     349                 :            :     }
     350                 :            :     return 1;
     351                 :            : }
     352                 :            : 
     353                 :            : void
     354                 :         26 : free_argv(char **argv_new, int *argc_new)
     355                 :            : {
     356                 :            :     int i;
     357                 :            : 
     358 [ +  - ][ +  - ]:         26 :     if(argv_new == NULL || *argv_new == NULL)
     359                 :            :         return;
     360                 :            : 
     361         [ +  + ]:        251 :     for (i=0; i < *argc_new; i++)
     362                 :            :     {
     363         [ +  - ]:        225 :         if(argv_new[i] == NULL)
     364                 :            :             break;
     365                 :            :         else
     366                 :        225 :             free(argv_new[i]);
     367                 :            :     }
     368                 :            :     return;
     369                 :            : }
     370                 :            : 
     371                 :            : /***EOF***/

Generated by: LCOV version 1.10