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