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 : 2649 : verify_file_perms_ownership(const char *file)
61 : : {
62 : 2649 : 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 [ + + ]: 2649 : if((stat(file, &st)) == 0)
71 : : {
72 : : /* Make sure it is a regular file
73 : : */
74 [ + + ]: 2644 : 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 [ + + ]: 2644 : 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 [ + + ]: 2644 : if(st.st_uid != getuid())
99 : : {
100 : 260 : 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 : 2649 : 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 : 23 : get_in_addr(struct sockaddr *sa)
138 : : {
139 [ + - ]: 23 : if (sa->sa_family == AF_INET)
140 : : {
141 : 23 : 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 : 26 : 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 : 26 : error = getaddrinfo(dns_str, NULL, hints, &result);
175 [ + + ]: 26 : if (error != 0)
176 : 3 : fprintf(stderr, "resolve_dest_adr() : %s\n", gai_strerror(error));
177 : :
178 : : else
179 : : {
180 : 23 : error = 1;
181 : :
182 : : /* Go through the linked list of addrinfo structures */
183 [ + - ]: 23 : 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 : 23 : sai_remote = (struct sockaddr_in *)get_in_addr((struct sockaddr *)(rp->ai_addr));
196 [ - + ]: 23 : 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 : 23 : freeaddrinfo(result);
209 : : }
210 : :
211 : 26 : 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 : 1984 : proto_inttostr(int proto, char *proto_str, size_t proto_size)
228 : : {
229 : 1984 : 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 [ + - ]: 4031 : for (ndx_proto = 0 ; ndx_proto < ARRAY_SIZE(fko_protocol_array) ; ndx_proto++)
237 : : {
238 : : /* If the protocol matches, grab it */
239 [ + + ]: 4031 : if (fko_protocol_array[ndx_proto].val == proto)
240 : : {
241 : 1984 : strlcpy(proto_str, fko_protocol_array[ndx_proto].str, proto_size);
242 : 1984 : proto_error = 0;
243 : 1984 : break;
244 : : }
245 : : }
246 : :
247 : 1984 : 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 : 87 : 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 : : 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***/
|