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