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