1 /* 2 * gen_uuid.c --- generate a DCE-compatible uuid 3 * 4 * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o. 5 * 6 * %Begin-Header% 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, and the entire permission notice in its entirety, 12 * including the disclaimer of warranties. 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. The name of the author may not be used to endorse or promote 17 * products derived from this software without specific prior 18 * written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 21 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF 23 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 27 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 30 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH 31 * DAMAGE. 32 * %End-Header% 33 */ 34 35 /* 36 * Force inclusion of SVID stuff since we need it if we're compiling in 37 * gcc-wall wall mode 38 */ 39 #define _SVID_SOURCE 40 #define _DEFAULT_SOURCE /* since glibc 2.20 _SVID_SOURCE is deprecated */ 41 42 #include "config.h" 43 44 #ifdef _WIN32 45 #define _WIN32_WINNT 0x0500 46 #include <windows.h> 47 #define UUID MYUUID 48 #endif 49 #include <stdio.h> 50 #ifdef HAVE_UNISTD_H 51 #include <unistd.h> 52 #endif 53 #ifdef HAVE_STDLIB_H 54 #include <stdlib.h> 55 #endif 56 #include <string.h> 57 #include <fcntl.h> 58 #include <errno.h> 59 #include <sys/types.h> 60 #ifdef HAVE_SYS_TIME_H 61 #include <sys/time.h> 62 #endif 63 #ifdef HAVE_SYS_WAIT_H 64 #include <sys/wait.h> 65 #endif 66 #include <sys/stat.h> 67 #ifdef HAVE_SYS_FILE_H 68 #include <sys/file.h> 69 #endif 70 #ifdef HAVE_SYS_IOCTL_H 71 #include <sys/ioctl.h> 72 #endif 73 #ifdef HAVE_SYS_SOCKET_H 74 #include <sys/socket.h> 75 #endif 76 #ifdef HAVE_SYS_UN_H 77 #include <sys/un.h> 78 #endif 79 #ifdef HAVE_SYS_SOCKIO_H 80 #include <sys/sockio.h> 81 #endif 82 #ifdef HAVE_NET_IF_H 83 #include <net/if.h> 84 #endif 85 #ifdef HAVE_NETINET_IN_H 86 #include <netinet/in.h> 87 #endif 88 #ifdef HAVE_NET_IF_DL_H 89 #include <net/if_dl.h> 90 #endif 91 #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) 92 #include <sys/syscall.h> 93 #endif 94 #ifdef HAVE_SYS_RESOURCE_H 95 #include <sys/resource.h> 96 #endif 97 98 #include "uuidP.h" 99 #include "uuidd.h" 100 101 #ifdef HAVE_SRANDOM 102 #define srand(x) srandom(x) 103 #define rand() random() 104 #endif 105 106 #ifdef TLS 107 #define THREAD_LOCAL static TLS 108 #else 109 #define THREAD_LOCAL static 110 #endif 111 112 #if defined(__linux__) && defined(__NR_gettid) && defined(HAVE_JRAND48) 113 #define DO_JRAND_MIX 114 THREAD_LOCAL unsigned short jrand_seed[3]; 115 #endif 116 117 #ifdef _WIN32 118 #ifndef USE_MINGW 119 static void gettimeofday (struct timeval *tv, void *dummy) 120 { 121 FILETIME ftime; 122 uint64_t n; 123 124 GetSystemTimeAsFileTime (&ftime); 125 n = (((uint64_t) ftime.dwHighDateTime << 32) 126 + (uint64_t) ftime.dwLowDateTime); 127 if (n) { 128 n /= 10; 129 n -= ((369 * 365 + 89) * (uint64_t) 86400) * 1000000; 130 } 131 132 tv->tv_sec = n / 1000000; 133 tv->tv_usec = n % 1000000; 134 } 135 #endif 136 #endif 137 138 static int get_random_fd(void) 139 { 140 struct timeval tv; 141 static int fd = -2; 142 int i; 143 144 if (fd == -2) { 145 gettimeofday(&tv, 0); 146 #ifndef _WIN32 147 fd = open("/dev/urandom", O_RDONLY); 148 if (fd == -1) 149 fd = open("/dev/random", O_RDONLY | O_NONBLOCK); 150 if (fd >= 0) { 151 i = fcntl(fd, F_GETFD); 152 if (i >= 0) 153 fcntl(fd, F_SETFD, i | FD_CLOEXEC); 154 } 155 #endif 156 srand(((unsigned)getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); 157 #ifdef DO_JRAND_MIX 158 jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF); 159 jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF); 160 jrand_seed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16; 161 #endif 162 } 163 /* Crank the random number generator a few times */ 164 gettimeofday(&tv, 0); 165 for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) 166 rand(); 167 return fd; 168 } 169 170 171 /* 172 * Generate a series of random bytes. Use /dev/urandom if possible, 173 * and if not, use srandom/random. 174 */ 175 static void get_random_bytes(void *buf, int nbytes) 176 { 177 int i, n = nbytes, fd = get_random_fd(); 178 int lose_counter = 0; 179 unsigned char *cp = buf; 180 181 if (fd >= 0) { 182 while (n > 0) { 183 i = read(fd, cp, n); 184 if (i <= 0) { 185 if (lose_counter++ > 16) 186 break; 187 continue; 188 } 189 n -= i; 190 cp += i; 191 lose_counter = 0; 192 } 193 } 194 195 /* 196 * We do this all the time, but this is the only source of 197 * randomness if /dev/random/urandom is out to lunch. 198 */ 199 for (cp = buf, i = 0; i < nbytes; i++) 200 *cp++ ^= (rand() >> 7) & 0xFF; 201 #ifdef DO_JRAND_MIX 202 { 203 unsigned short tmp_seed[3]; 204 205 memcpy(tmp_seed, jrand_seed, sizeof(tmp_seed)); 206 jrand_seed[2] = jrand_seed[2] ^ syscall(__NR_gettid); 207 for (cp = buf, i = 0; i < nbytes; i++) 208 *cp++ ^= (jrand48(tmp_seed) >> 7) & 0xFF; 209 memcpy(jrand_seed, tmp_seed, 210 sizeof(jrand_seed) - sizeof(unsigned short)); 211 } 212 #endif 213 214 return; 215 } 216 217 /* 218 * Get the ethernet hardware address, if we can find it... 219 * 220 * XXX for a windows version, probably should use GetAdaptersInfo: 221 * http://www.codeguru.com/cpp/i-n/network/networkinformation/article.php/c5451 222 * commenting out get_node_id just to get gen_uuid to compile under windows 223 * is not the right way to go! 224 */ 225 static int get_node_id(unsigned char *node_id) 226 { 227 #ifdef HAVE_NET_IF_H 228 int sd; 229 struct ifreq ifr, *ifrp; 230 struct ifconf ifc; 231 char buf[1024]; 232 int n, i; 233 unsigned char *a; 234 #ifdef HAVE_NET_IF_DL_H 235 struct sockaddr_dl *sdlp; 236 #endif 237 238 /* 239 * BSD 4.4 defines the size of an ifreq to be 240 * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len 241 * However, under earlier systems, sa_len isn't present, so the size is 242 * just sizeof(struct ifreq) 243 */ 244 #ifdef HAVE_SA_LEN 245 #ifndef max 246 #define max(a,b) ((a) > (b) ? (a) : (b)) 247 #endif 248 #define ifreq_size(i) max(sizeof(struct ifreq),\ 249 sizeof((i).ifr_name)+(i).ifr_addr.sa_len) 250 #else 251 #define ifreq_size(i) sizeof(struct ifreq) 252 #endif /* HAVE_SA_LEN*/ 253 254 sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 255 if (sd < 0) { 256 return -1; 257 } 258 memset(buf, 0, sizeof(buf)); 259 ifc.ifc_len = sizeof(buf); 260 ifc.ifc_buf = buf; 261 if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) { 262 close(sd); 263 return -1; 264 } 265 n = ifc.ifc_len; 266 for (i = 0; i < n; i+= ifreq_size(*ifrp) ) { 267 ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i); 268 strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); 269 #ifdef SIOCGIFHWADDR 270 if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) 271 continue; 272 a = (unsigned char *) &ifr.ifr_hwaddr.sa_data; 273 #else 274 #ifdef SIOCGENADDR 275 if (ioctl(sd, SIOCGENADDR, &ifr) < 0) 276 continue; 277 a = (unsigned char *) ifr.ifr_enaddr; 278 #else 279 #ifdef HAVE_NET_IF_DL_H 280 sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr; 281 if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6)) 282 continue; 283 a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen]; 284 #else 285 /* 286 * XXX we don't have a way of getting the hardware 287 * address 288 */ 289 close(sd); 290 return 0; 291 #endif /* HAVE_NET_IF_DL_H */ 292 #endif /* SIOCGENADDR */ 293 #endif /* SIOCGIFHWADDR */ 294 if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) 295 continue; 296 if (node_id) { 297 memcpy(node_id, a, 6); 298 close(sd); 299 return 1; 300 } 301 } 302 close(sd); 303 #endif 304 return 0; 305 } 306 307 /* Assume that the gettimeofday() has microsecond granularity */ 308 #define MAX_ADJUSTMENT 10 309 310 static int get_clock(uint32_t *clock_high, uint32_t *clock_low, 311 uint16_t *ret_clock_seq, int *num) 312 { 313 THREAD_LOCAL int adjustment = 0; 314 THREAD_LOCAL struct timeval last = {0, 0}; 315 THREAD_LOCAL int state_fd = -2; 316 THREAD_LOCAL FILE *state_f; 317 THREAD_LOCAL uint16_t clock_seq; 318 struct timeval tv; 319 #ifndef _WIN32 320 struct flock fl; 321 #endif 322 uint64_t clock_reg; 323 mode_t save_umask; 324 int len; 325 326 if (state_fd == -2) { 327 save_umask = umask(0); 328 state_fd = open("/var/lib/libuuid/clock.txt", 329 O_RDWR|O_CREAT, 0660); 330 (void) umask(save_umask); 331 if (state_fd >= 0) { 332 state_f = fdopen(state_fd, "r+"); 333 if (!state_f) { 334 close(state_fd); 335 state_fd = -1; 336 } 337 } 338 } 339 #ifndef _WIN32 340 fl.l_type = F_WRLCK; 341 fl.l_whence = SEEK_SET; 342 fl.l_start = 0; 343 fl.l_len = 0; 344 fl.l_pid = 0; 345 if (state_fd >= 0) { 346 rewind(state_f); 347 while (fcntl(state_fd, F_SETLKW, &fl) < 0) { 348 if ((errno == EAGAIN) || (errno == EINTR)) 349 continue; 350 fclose(state_f); 351 state_fd = -1; 352 break; 353 } 354 } 355 #endif 356 if (state_fd >= 0) { 357 unsigned int cl; 358 unsigned long tv1, tv2; 359 int a; 360 361 if (fscanf(state_f, "clock: %04x tv: %lu %lu adj: %d\n", 362 &cl, &tv1, &tv2, &a) == 4) { 363 clock_seq = cl & 0x3FFF; 364 last.tv_sec = tv1; 365 last.tv_usec = tv2; 366 adjustment = a; 367 } 368 } 369 370 if ((last.tv_sec == 0) && (last.tv_usec == 0)) { 371 get_random_bytes(&clock_seq, sizeof(clock_seq)); 372 clock_seq &= 0x3FFF; 373 gettimeofday(&last, 0); 374 last.tv_sec--; 375 } 376 377 try_again: 378 gettimeofday(&tv, 0); 379 if ((tv.tv_sec < last.tv_sec) || 380 ((tv.tv_sec == last.tv_sec) && 381 (tv.tv_usec < last.tv_usec))) { 382 clock_seq = (clock_seq+1) & 0x3FFF; 383 adjustment = 0; 384 last = tv; 385 } else if ((tv.tv_sec == last.tv_sec) && 386 (tv.tv_usec == last.tv_usec)) { 387 if (adjustment >= MAX_ADJUSTMENT) 388 goto try_again; 389 adjustment++; 390 } else { 391 adjustment = 0; 392 last = tv; 393 } 394 395 clock_reg = tv.tv_usec*10 + adjustment; 396 clock_reg += ((uint64_t) tv.tv_sec)*10000000; 397 clock_reg += (((uint64_t) 0x01B21DD2) << 32) + 0x13814000; 398 399 if (num && (*num > 1)) { 400 adjustment += *num - 1; 401 last.tv_usec += adjustment / 10; 402 adjustment = adjustment % 10; 403 last.tv_sec += last.tv_usec / 1000000; 404 last.tv_usec = last.tv_usec % 1000000; 405 } 406 407 if (state_fd > 0) { 408 rewind(state_f); 409 len = fprintf(state_f, 410 "clock: %04x tv: %016lu %08lu adj: %08d\n", 411 clock_seq, last.tv_sec, (long)last.tv_usec, 412 adjustment); 413 fflush(state_f); 414 if (ftruncate(state_fd, len) < 0) { 415 fprintf(state_f, " \n"); 416 fflush(state_f); 417 } 418 rewind(state_f); 419 #ifndef _WIN32 420 fl.l_type = F_UNLCK; 421 if (fcntl(state_fd, F_SETLK, &fl) < 0) { 422 fclose(state_f); 423 state_fd = -1; 424 } 425 #endif 426 } 427 428 *clock_high = clock_reg >> 32; 429 *clock_low = clock_reg; 430 *ret_clock_seq = clock_seq; 431 return 0; 432 } 433 434 #if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) 435 static ssize_t read_all(int fd, char *buf, size_t count) 436 { 437 ssize_t ret; 438 ssize_t c = 0; 439 int tries = 0; 440 441 memset(buf, 0, count); 442 while (count > 0) { 443 ret = read(fd, buf, count); 444 if (ret <= 0) { 445 if ((errno == EAGAIN || errno == EINTR || ret == 0) && 446 (tries++ < 5)) 447 continue; 448 return c ? c : -1; 449 } 450 if (ret > 0) 451 tries = 0; 452 count -= ret; 453 buf += ret; 454 c += ret; 455 } 456 return c; 457 } 458 459 /* 460 * Close all file descriptors 461 */ 462 static void close_all_fds(void) 463 { 464 int i, max; 465 466 #if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX) 467 max = sysconf(_SC_OPEN_MAX); 468 #elif defined(HAVE_GETDTABLESIZE) 469 max = getdtablesize(); 470 #elif defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) 471 struct rlimit rl; 472 473 getrlimit(RLIMIT_NOFILE, &rl); 474 max = rl.rlim_cur; 475 #else 476 max = OPEN_MAX; 477 #endif 478 479 for (i=0; i < max; i++) { 480 close(i); 481 if (i <= 2) 482 open("/dev/null", O_RDWR); 483 } 484 } 485 #endif /* defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) */ 486 487 #if __GNUC_PREREQ (4, 6) 488 #pragma GCC diagnostic push 489 #if !defined(USE_UUIDD) || !defined(HAVE_SYS_UN_H) 490 #pragma GCC diagnostic ignored "-Wunused-parameter" 491 #endif 492 #endif 493 /* 494 * Try using the uuidd daemon to generate the UUID 495 * 496 * Returns 0 on success, non-zero on failure. 497 */ 498 static int get_uuid_via_daemon(int op, uuid_t out, int *num) 499 { 500 #if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) 501 char op_buf[64]; 502 int op_len; 503 int s; 504 ssize_t ret; 505 int32_t reply_len = 0, expected = 16; 506 struct sockaddr_un srv_addr; 507 struct stat st; 508 pid_t pid; 509 static const char *uuidd_path = UUIDD_PATH; 510 static int access_ret = -2; 511 static int start_attempts = 0; 512 513 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 514 return -1; 515 516 srv_addr.sun_family = AF_UNIX; 517 strcpy(srv_addr.sun_path, UUIDD_SOCKET_PATH); 518 519 if (connect(s, (const struct sockaddr *) &srv_addr, 520 sizeof(struct sockaddr_un)) < 0) { 521 if (access_ret == -2) 522 access_ret = access(uuidd_path, X_OK); 523 if (access_ret == 0) 524 access_ret = stat(uuidd_path, &st); 525 if (access_ret == 0 && (st.st_mode & (S_ISUID | S_ISGID)) == 0) 526 access_ret = access(UUIDD_DIR, W_OK); 527 if (access_ret == 0 && start_attempts++ < 5) { 528 if ((pid = fork()) == 0) { 529 close_all_fds(); 530 execl(uuidd_path, "uuidd", "-qT", "300", 531 (char *) NULL); 532 exit(1); 533 } 534 (void) waitpid(pid, 0, 0); 535 if (connect(s, (const struct sockaddr *) &srv_addr, 536 sizeof(struct sockaddr_un)) < 0) 537 goto fail; 538 } else 539 goto fail; 540 } 541 op_buf[0] = op; 542 op_len = 1; 543 if (op == UUIDD_OP_BULK_TIME_UUID) { 544 memcpy(op_buf+1, num, sizeof(*num)); 545 op_len += sizeof(*num); 546 expected += sizeof(*num); 547 } 548 549 ret = write(s, op_buf, op_len); 550 if (ret < 1) 551 goto fail; 552 553 ret = read_all(s, (char *) &reply_len, sizeof(reply_len)); 554 if (ret < 0) 555 goto fail; 556 557 if (reply_len != expected) 558 goto fail; 559 560 ret = read_all(s, op_buf, reply_len); 561 562 if (op == UUIDD_OP_BULK_TIME_UUID) 563 memcpy(op_buf+16, num, sizeof(int)); 564 565 memcpy(out, op_buf, 16); 566 567 close(s); 568 return ((ret == expected) ? 0 : -1); 569 570 fail: 571 close(s); 572 #endif 573 return -1; 574 } 575 #if __GNUC_PREREQ (4, 6) 576 #pragma GCC diagnostic pop 577 #endif 578 579 void uuid__generate_time(uuid_t out, int *num) 580 { 581 static unsigned char node_id[6]; 582 static int has_init = 0; 583 struct uuid uu; 584 uint32_t clock_mid; 585 586 if (!has_init) { 587 if (get_node_id(node_id) <= 0) { 588 get_random_bytes(node_id, 6); 589 /* 590 * Set multicast bit, to prevent conflicts 591 * with IEEE 802 addresses obtained from 592 * network cards 593 */ 594 node_id[0] |= 0x01; 595 } 596 has_init = 1; 597 } 598 get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num); 599 uu.clock_seq |= 0x8000; 600 uu.time_mid = (uint16_t) clock_mid; 601 uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000; 602 memcpy(uu.node, node_id, 6); 603 uuid_pack(&uu, out); 604 } 605 606 void uuid_generate_time(uuid_t out) 607 { 608 #ifdef TLS 609 THREAD_LOCAL int num = 0; 610 THREAD_LOCAL struct uuid uu; 611 THREAD_LOCAL time_t last_time = 0; 612 time_t now; 613 614 if (num > 0) { 615 now = time(0); 616 if (now > last_time+1) 617 num = 0; 618 } 619 if (num <= 0) { 620 num = 1000; 621 if (get_uuid_via_daemon(UUIDD_OP_BULK_TIME_UUID, 622 out, &num) == 0) { 623 last_time = time(0); 624 uuid_unpack(out, &uu); 625 num--; 626 return; 627 } 628 num = 0; 629 } 630 if (num > 0) { 631 uu.time_low++; 632 if (uu.time_low == 0) { 633 uu.time_mid++; 634 if (uu.time_mid == 0) 635 uu.time_hi_and_version++; 636 } 637 num--; 638 uuid_pack(&uu, out); 639 return; 640 } 641 #else 642 if (get_uuid_via_daemon(UUIDD_OP_TIME_UUID, out, 0) == 0) 643 return; 644 #endif 645 646 uuid__generate_time(out, 0); 647 } 648 649 650 void uuid__generate_random(uuid_t out, int *num) 651 { 652 uuid_t buf; 653 struct uuid uu; 654 int i, n; 655 656 if (!num || !*num) 657 n = 1; 658 else 659 n = *num; 660 661 for (i = 0; i < n; i++) { 662 get_random_bytes(buf, sizeof(buf)); 663 uuid_unpack(buf, &uu); 664 665 uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000; 666 uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) 667 | 0x4000; 668 uuid_pack(&uu, out); 669 out += sizeof(uuid_t); 670 } 671 } 672 673 void uuid_generate_random(uuid_t out) 674 { 675 int num = 1; 676 /* No real reason to use the daemon for random uuid's -- yet */ 677 678 uuid__generate_random(out, &num); 679 } 680 681 682 /* 683 * This is the generic front-end to uuid_generate_random and 684 * uuid_generate_time. It uses uuid_generate_random only if 685 * /dev/urandom is available, since otherwise we won't have 686 * high-quality randomness. 687 */ 688 void uuid_generate(uuid_t out) 689 { 690 if (get_random_fd() >= 0) 691 uuid_generate_random(out); 692 else 693 uuid_generate_time(out); 694 }