xref: /openbsd-src/sbin/isakmpd/util.c (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
1 /*	$OpenBSD: util.c,v 1.34 2003/06/03 14:28:16 ho Exp $	*/
2 /*	$EOM: util.c,v 1.23 2000/11/23 12:22:08 niklas Exp $	*/
3 
4 /*
5  * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist.  All rights reserved.
6  * Copyright (c) 2000, 2001 H�kan Olsson.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * This code was written under funding by Ericsson Radio Systems.
31  */
32 
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <sys/stat.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <limits.h>
39 #include <netdb.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <errno.h>
44 
45 #include "sysdep.h"
46 
47 #include "log.h"
48 #include "message.h"
49 #include "monitor.h"
50 #include "sysdep.h"
51 #include "transport.h"
52 #include "util.h"
53 
54 /*
55  * Set if -N is given, allowing name lookups to be done, possibly stalling
56  * the daemon for quite a while.
57  */
58 int allow_name_lookups = 0;
59 
60 /*
61  * This is set to true in case of regression-test mode, when it will
62  * cause predictable random numbers be generated.
63  */
64 int regrand = 0;
65 
66 /*
67  * If in regression-test mode, this is the seed used.
68  */
69 unsigned long seed;
70 
71 /*
72  * XXX These might be turned into inlines or macros, maybe even
73  * machine-dependent ones, for performance reasons.
74  */
75 u_int16_t
76 decode_16 (u_int8_t *cp)
77 {
78   return cp[0] << 8 | cp[1];
79 }
80 
81 u_int32_t
82 decode_32 (u_int8_t *cp)
83 {
84   return cp[0] << 24 | cp[1] << 16 | cp[2] << 8 | cp[3];
85 }
86 
87 u_int64_t
88 decode_64 (u_int8_t *cp)
89 {
90   return (u_int64_t)cp[0] << 56 | (u_int64_t)cp[1] << 48
91     | (u_int64_t)cp[2] << 40 | (u_int64_t)cp[3] << 32
92     | cp[4] << 24 | cp[5] << 16 | cp[6] << 8 | cp[7];
93 }
94 
95 #if 0
96 /*
97  * XXX I severly doubt that we will need this.  IPv6 does not have the legacy
98  * of representation in host byte order, AFAIK.
99  */
100 
101 void
102 decode_128 (u_int8_t *cp, u_int8_t *cpp)
103 {
104 #if BYTE_ORDER == LITTLE_ENDIAN
105   int i;
106 
107   for (i = 0; i < 16; i++)
108     cpp[i] = cp[15 - i];
109 #elif BYTE_ORDER == BIG_ENDIAN
110   bcopy (cp, cpp, 16);
111 #else
112 #error "Byte order unknown!"
113 #endif
114 }
115 #endif
116 
117 void
118 encode_16 (u_int8_t *cp, u_int16_t x)
119 {
120   *cp++ = x >> 8;
121   *cp = x & 0xff;
122 }
123 
124 void
125 encode_32 (u_int8_t *cp, u_int32_t x)
126 {
127   *cp++ = x >> 24;
128   *cp++ = (x >> 16) & 0xff;
129   *cp++ = (x >> 8) & 0xff;
130   *cp = x & 0xff;
131 }
132 
133 void
134 encode_64 (u_int8_t *cp, u_int64_t x)
135 {
136   *cp++ = x >> 56;
137   *cp++ = (x >> 48) & 0xff;
138   *cp++ = (x >> 40) & 0xff;
139   *cp++ = (x >> 32) & 0xff;
140   *cp++ = (x >> 24) & 0xff;
141   *cp++ = (x >> 16) & 0xff;
142   *cp++ = (x >> 8) & 0xff;
143   *cp = x & 0xff;
144 }
145 
146 #if 0
147 /*
148  * XXX I severly doubt that we will need this.  IPv6 does not have the legacy
149  * of representation in host byte order, AFAIK.
150  */
151 
152 void
153 encode_128 (u_int8_t *cp, u_int8_t *cpp)
154 {
155   decode_128 (cpp, cp);
156 }
157 #endif
158 
159 /* Check a buffer for all zeroes.  */
160 int
161 zero_test (const u_int8_t *p, size_t sz)
162 {
163   while (sz-- > 0)
164     if (*p++ != 0)
165       return 0;
166   return 1;
167 }
168 
169 /* Check a buffer for all ones.  */
170 int
171 ones_test (const u_int8_t *p, size_t sz)
172 {
173   while (sz-- > 0)
174     if (*p++ != 0xff)
175       return 0;
176   return 1;
177 }
178 
179 /*
180  * Generate a random data, len bytes long.
181  */
182 u_int8_t *
183 getrandom (u_int8_t *buf, size_t len)
184 {
185   u_int32_t tmp = 0;
186   int i;
187 
188   for (i = 0; i < len; i++)
189     {
190       if (i % sizeof tmp == 0)
191 	tmp = sysdep_random ();
192 
193       buf[i] = tmp & 0xff;
194       tmp >>= 8;
195     }
196 
197   return buf;
198 }
199 
200 static __inline int
201 hex2nibble (char c)
202 {
203   if (c >= '0' && c <= '9')
204     return c - '0';
205   if (c >= 'a' && c <= 'f')
206     return c - 'a' + 10;
207   if (c >= 'A' && c <= 'F')
208     return c - 'A' + 10;
209   return -1;
210 }
211 
212 /*
213  * Convert hexadecimal string in S to raw binary buffer at BUF sized SZ
214  * bytes.  Return 0 if everything is OK, -1 otherwise.
215  */
216 int
217 hex2raw (char *s, u_int8_t *buf, size_t sz)
218 {
219   char *p;
220   u_int8_t *bp;
221   int tmp;
222 
223   if (strlen (s) > sz * 2)
224     return -1;
225   for (p = s + strlen (s) - 1, bp = &buf[sz - 1]; bp >= buf; bp--)
226     {
227       *bp = 0;
228       if (p >= s)
229 	{
230 	  tmp = hex2nibble (*p--);
231 	  if (tmp == -1)
232 	    return -1;
233 	  *bp = tmp;
234 	}
235       if (p >= s)
236 	{
237 	  tmp = hex2nibble (*p--);
238 	  if (tmp == -1)
239 	    return -1;
240 	  *bp |= tmp << 4;
241 	}
242     }
243   return 0;
244 }
245 
246 int
247 text2sockaddr (char *address, char *port, struct sockaddr **sa)
248 {
249 #ifdef HAVE_GETNAMEINFO
250   struct addrinfo *ai, hints;
251 
252   memset (&hints, 0, sizeof hints);
253   if (!allow_name_lookups)
254     hints.ai_flags = AI_NUMERICHOST;
255   hints.ai_family = PF_UNSPEC;
256   hints.ai_socktype = SOCK_DGRAM;
257   hints.ai_protocol = IPPROTO_UDP;
258 
259   if (getaddrinfo (address, port, &hints, &ai))
260     return -1;
261 
262   *sa = malloc (sysdep_sa_len (ai->ai_addr));
263   if (!sa)
264     return -1;
265 
266   memcpy (*sa, ai->ai_addr, sysdep_sa_len (ai->ai_addr));
267   freeaddrinfo (ai);
268   return 0;
269 #else
270   int af = strchr (address, ':') != NULL ? AF_INET6 : AF_INET;
271   size_t sz = af == AF_INET
272     ? sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6);
273   long lport;
274   struct servent *sp;
275   char *ep;
276 
277   *sa = calloc (1, sz);
278   if (!*sa)
279     return -1;
280 
281 #ifndef USE_OLD_SOCKADDR
282   (*sa)->sa_len = sz;
283 #endif
284   (*sa)->sa_family = af;
285   if (inet_pton (af, address, sockaddr_addrdata (*sa)) != 1)
286     {
287       free (*sa);
288       return -1;
289     }
290   if (!port)
291     return 0;
292   sp = getservbyname (port, "udp");
293   if (!sp)
294     {
295       lport = strtol (port, &ep, 10);
296       if (ep == port || lport < 0 || lport > USHRT_MAX)
297 	{
298 	  free (*sa);
299 	  return -1;
300 	}
301       lport = htons (lport);
302     }
303   else
304     lport = sp->s_port;
305   if ((*sa)->sa_family == AF_INET)
306     ((struct sockaddr_in *)*sa)->sin_port = lport;
307   else
308     ((struct sockaddr_in6 *)*sa)->sin6_port = lport;
309   return 0;
310 #endif
311 }
312 
313 /*
314  * Convert a sockaddr to text. With zflag non-zero fill out with zeroes,
315  * i.e 10.0.0.10 --> "010.000.000.010"
316  */
317 int
318 sockaddr2text (struct sockaddr *sa, char **address, int zflag)
319 {
320   char buf[NI_MAXHOST];
321   char *token, *bstart, *ep;
322   int addrlen;
323   long val;
324   int i, j;
325 
326 #ifdef HAVE_GETNAMEINFO
327   if (getnameinfo (sa, sysdep_sa_len (sa), buf, sizeof buf, 0, 0,
328 		   allow_name_lookups ? 0 : NI_NUMERICHOST))
329     return -1;
330 #else
331   switch (sa->sa_family)
332     {
333     case AF_INET:
334     case AF_INET6:
335       if (inet_ntop (sa->sa_family, sa->sa_data, buf, NI_MAXHOST - 1) == NULL)
336 	{
337 	  log_error ("sockaddr2text: inet_ntop (%d, %p, %p, %d) failed",
338 		     sa->sa_family, sa->sa_data, buf, NI_MAXHOST - 1);
339 	  return -1;
340 	}
341       buf[NI_MAXHOST - 1] = '\0';
342       break;
343 
344     default:
345       log_print ("sockaddr2text: unsupported protocol family %d\n",
346 		  sa->sa_family);
347       return -1;
348     }
349 #endif
350 
351   if (zflag == 0)
352     {
353       *address = strdup (buf);
354       if (!*address)
355 	return -1;
356     }
357   else
358     switch (sa->sa_family)
359       {
360       case AF_INET:
361 	addrlen = sizeof "000.000.000.000";
362 	*address = malloc (addrlen);
363 	if (!*address)
364 	  return -1;
365 	buf[addrlen] = '\0';
366 	bstart = buf;
367 	**address = '\0';
368 	while ((token = strsep (&bstart, ".")) != NULL)
369 	  {
370 	    if (strlen (*address) > 12)
371 	      {
372 		free (*address);
373 		return -1;
374 	      }
375 	    val = strtol (token, &ep, 10);
376 	    if (ep == token || val < 0 || val > UCHAR_MAX)
377 	      {
378 		free (*address);
379 		return -1;
380 	      }
381 	    snprintf (*address + strlen (*address),
382 		      addrlen - strlen (*address), "%03ld", val);
383 	    if (bstart)
384 	      strlcat (*address, ".", addrlen);
385 	  }
386 	break;
387 
388       case AF_INET6:
389 	/*
390 	 * XXX In the algorithm below there are some magic numbers we
391 	 * probably could give explaining names.
392 	 */
393 	addrlen = sizeof "0000:0000:0000:0000:0000:0000:0000:0000";
394 	*address = malloc (addrlen);
395 	if (!*address)
396 	  return -1;
397 
398 	for (i = 0, j = 0; i < 8; i++)
399 	  {
400 	    snprintf ((*address) + j, addrlen - j, "%02x%02x",
401 		      ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[2 * i],
402 		      ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[2 * i + 1]);
403 	    j += 4;
404 	    (*address)[j] = (j < (addrlen - 1)) ? ':' : '\0';
405 	    j++;
406 	  }
407 	break;
408 
409       default:
410 	*address = strdup ("<error>");
411 	if (!*address)
412 	  return -1;
413       }
414 
415   return 0;
416 }
417 
418 /*
419  * sockaddr_addrlen and sockaddr_addrdata return the relevant sockaddr info
420  * depending on address family.  Useful to keep other code shorter(/clearer?).
421  */
422 int
423 sockaddr_addrlen (struct sockaddr *sa)
424 {
425   switch (sa->sa_family)
426     {
427     case AF_INET6:
428       return sizeof ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr;
429     case AF_INET:
430       return sizeof ((struct sockaddr_in *)sa)->sin_addr.s_addr;
431     default:
432       log_print ("sockaddr_addrlen: unsupported protocol family %d",
433 		 sa->sa_family);
434       return 0;
435     }
436 }
437 
438 u_int8_t *
439 sockaddr_addrdata (struct sockaddr *sa)
440 {
441   switch (sa->sa_family)
442     {
443     case AF_INET6:
444       return (u_int8_t *)&((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr;
445     case AF_INET:
446       return (u_int8_t *)&((struct sockaddr_in *)sa)->sin_addr.s_addr;
447     default:
448       log_print ("sockaddr_addrdata: unsupported protocol family %d",
449 		 sa->sa_family);
450       return 0;
451     }
452 }
453 
454 /*
455  * Convert network address to text. The network address does not need
456  * to be properly aligned.
457  */
458 void
459 util_ntoa (char **buf, int af, u_int8_t *addr)
460 {
461   struct sockaddr_storage from;
462   struct sockaddr *sfrom = (struct sockaddr *)&from;
463   socklen_t fromlen = sizeof from;
464 
465   memset (&from, 0, fromlen);
466   sfrom->sa_family = af;
467 #ifndef USE_OLD_SOCKADDR
468   switch (af)
469     {
470     case AF_INET:
471       sfrom->sa_len = sizeof (struct sockaddr_in);
472       break;
473     case AF_INET6:
474       sfrom->sa_len = sizeof (struct sockaddr_in6);
475       break;
476     }
477 #endif
478   memcpy (sockaddr_addrdata (sfrom), addr, sockaddr_addrlen (sfrom));
479 
480   if (sockaddr2text (sfrom, buf, 0))
481     {
482       log_print ("util_ntoa: "
483 		 "could not make printable address out of sockaddr %p", sfrom);
484       *buf = 0;
485     }
486 }
487 
488 /*
489  * Perform sanity check on files containing secret information.
490  * Returns -1 on failure, 0 otherwise.
491  * Also, if FILE_SIZE is a not a null pointer, store file size here.
492  */
493 int
494 check_file_secrecy (char *name, size_t *file_size)
495 {
496   struct stat st;
497 
498   if (monitor_stat (name, &st) == -1)
499     {
500       log_error ("check_file_secrecy: stat (\"%s\") failed", name);
501       return -1;
502     }
503   if (st.st_uid != 0 && st.st_uid != getuid ())
504     {
505       log_print ("check_file_secrecy: "
506 		 "not loading %s - file owner is not process user", name);
507       errno = EPERM;
508       return -1;
509     }
510   if ((st.st_mode & (S_IRWXG | S_IRWXO)) != 0)
511     {
512       log_print ("conf_file_secrecy: not loading %s - too open permissions",
513 		 name);
514       errno = EPERM;
515       return -1;
516     }
517 
518   if (file_size)
519     *file_size = (size_t)st.st_size;
520 
521   return 0;
522 }
523