1/* 2 * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 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 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "kx.h" 35 36RCSID("$Id$"); 37 38char x_socket[MaxPathLen]; 39 40uint32_t display_num; 41char display[MaxPathLen]; 42int display_size = sizeof(display); 43char xauthfile[MaxPathLen]; 44int xauthfile_size = sizeof(xauthfile); 45u_char cookie[16]; 46size_t cookie_len = sizeof(cookie); 47 48#ifndef X_UNIX_PATH 49#define X_UNIX_PATH "/tmp/.X11-unix/X" 50#endif 51 52#ifndef X_PIPE_PATH 53#define X_PIPE_PATH "/tmp/.X11-pipe/X" 54#endif 55 56/* 57 * Allocate a unix domain socket in `s' for display `dpy' and with 58 * filename `pattern' 59 * 60 * 0 if all is OK 61 * -1 if bind failed badly 62 * 1 if dpy is already used */ 63 64static int 65try_socket (struct x_socket *s, int dpy, const char *pattern) 66{ 67 struct sockaddr_un addr; 68 int fd; 69 70 fd = socket (AF_UNIX, SOCK_STREAM, 0); 71 if (fd < 0) 72 err (1, "socket AF_UNIX"); 73 memset (&addr, 0, sizeof(addr)); 74 addr.sun_family = AF_UNIX; 75 snprintf (addr.sun_path, sizeof(addr.sun_path), pattern, dpy); 76 if(bind(fd, 77 (struct sockaddr *)&addr, 78 sizeof(addr)) < 0) { 79 close (fd); 80 if (errno == EADDRINUSE || 81 errno == EACCES /* Cray return EACCESS */ 82#ifdef ENOTUNIQ 83 || errno == ENOTUNIQ /* bug in Solaris 2.4 */ 84#endif 85 ) 86 return 1; 87 else 88 return -1; 89 } 90 s->fd = fd; 91 s->pathname = strdup (addr.sun_path); 92 if (s->pathname == NULL) 93 errx (1, "strdup: out of memory"); 94 s->flags = UNIX_SOCKET; 95 return 0; 96} 97 98#ifdef MAY_HAVE_X11_PIPES 99/* 100 * Allocate a stream (masqueraded as a named pipe) 101 * 102 * 0 if all is OK 103 * -1 if bind failed badly 104 * 1 if dpy is already used 105 */ 106 107static int 108try_pipe (struct x_socket *s, int dpy, const char *pattern) 109{ 110 char path[MAXPATHLEN]; 111 int ret; 112 int fd; 113 int pipefd[2]; 114 115 snprintf (path, sizeof(path), pattern, dpy); 116 fd = open (path, O_WRONLY | O_CREAT | O_EXCL, 0600); 117 if (fd < 0) { 118 if (errno == EEXIST) 119 return 1; 120 else 121 return -1; 122 } 123 124 close (fd); 125 126 ret = pipe (pipefd); 127 if (ret < 0) 128 err (1, "pipe"); 129 130 ret = ioctl (pipefd[1], I_PUSH, "connld"); 131 if (ret < 0) { 132 if(errno == ENOSYS) 133 return -1; 134 err (1, "ioctl I_PUSH"); 135 } 136 137 ret = fattach (pipefd[1], path); 138 if (ret < 0) 139 err (1, "fattach %s", path); 140 141 s->fd = pipefd[0]; 142 close (pipefd[1]); 143 s->pathname = strdup (path); 144 if (s->pathname == NULL) 145 errx (1, "strdup: out of memory"); 146 s->flags = STREAM_PIPE; 147 return 0; 148} 149#endif /* MAY_HAVE_X11_PIPES */ 150 151/* 152 * Try to create a TCP socket in `s' corresponding to display `dpy'. 153 * 154 * 0 if all is OK 155 * -1 if bind failed badly 156 * 1 if dpy is already used 157 */ 158 159static int 160try_tcp (struct x_socket *s, int dpy) 161{ 162 struct sockaddr_in tcpaddr; 163 struct in_addr local; 164 int one = 1; 165 int fd; 166 167 memset(&local, 0, sizeof(local)); 168 local.s_addr = htonl(INADDR_LOOPBACK); 169 170 fd = socket (AF_INET, SOCK_STREAM, 0); 171 if (fd < 0) 172 err (1, "socket AF_INET"); 173#if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT) 174 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&one, 175 sizeof(one)); 176#endif 177 memset (&tcpaddr, 0, sizeof(tcpaddr)); 178 tcpaddr.sin_family = AF_INET; 179 tcpaddr.sin_addr = local; 180 tcpaddr.sin_port = htons(6000 + dpy); 181 if (bind (fd, (struct sockaddr *)&tcpaddr, 182 sizeof(tcpaddr)) < 0) { 183 close (fd); 184 if (errno == EADDRINUSE) 185 return 1; 186 else 187 return -1; 188 } 189 s->fd = fd; 190 s->pathname = NULL; 191 s->flags = TCP; 192 return 0; 193} 194 195/* 196 * The potential places to create unix sockets. 197 */ 198 199static char *x_sockets[] = { 200X_UNIX_PATH "%u", 201"/var/X/.X11-unix/X" "%u", 202"/usr/spool/sockets/X11/" "%u", 203NULL 204}; 205 206/* 207 * Dito for stream pipes. 208 */ 209 210#ifdef MAY_HAVE_X11_PIPES 211static char *x_pipes[] = { 212X_PIPE_PATH "%u", 213"/var/X/.X11-pipe/X" "%u", 214NULL 215}; 216#endif 217 218/* 219 * Create the directory corresponding to dirname of `path' or fail. 220 */ 221 222static void 223try_mkdir (const char *path) 224{ 225 char *dir; 226 char *p; 227 int oldmask; 228 229 if((dir = strdup (path)) == NULL) 230 errx (1, "strdup: out of memory"); 231 p = strrchr (dir, '/'); 232 if (p) 233 *p = '\0'; 234 235 oldmask = umask(0); 236 mkdir (dir, 01777); 237 umask (oldmask); 238 free (dir); 239} 240 241/* 242 * Allocate a display, returning the number of sockets in `number' and 243 * all the corresponding sockets in `sockets'. If `tcp_socket' is 244 * true, also allcoaet a TCP socket. 245 * 246 * The return value is the display allocated or -1 if an error occurred. 247 */ 248 249int 250get_xsockets (int *number, struct x_socket **sockets, int tcp_socket) 251{ 252 int dpy; 253 struct x_socket *s; 254 int n; 255 int i; 256 257 s = malloc (sizeof(*s) * 5); 258 if (s == NULL) 259 errx (1, "malloc: out of memory"); 260 261 try_mkdir (X_UNIX_PATH); 262 try_mkdir (X_PIPE_PATH); 263 264 for(dpy = 4; dpy < 256; ++dpy) { 265 char **path; 266 int tmp = 0; 267 268 n = 0; 269 for (path = x_sockets; *path; ++path) { 270 tmp = try_socket (&s[n], dpy, *path); 271 if (tmp == -1) { 272 if (errno != ENOTDIR && errno != ENOENT) 273 err(1, "failed to open '%s'", *path); 274 } else if (tmp == 1) { 275 while(--n >= 0) { 276 close (s[n].fd); 277 free (s[n].pathname); 278 } 279 break; 280 } else if (tmp == 0) 281 ++n; 282 } 283 if (tmp == 1) 284 continue; 285 286#ifdef MAY_HAVE_X11_PIPES 287 for (path = x_pipes; *path; ++path) { 288 tmp = try_pipe (&s[n], dpy, *path); 289 if (tmp == -1) { 290 if (errno != ENOTDIR && errno != ENOENT && errno != ENOSYS) 291 err(1, "failed to open '%s'", *path); 292 } else if (tmp == 1) { 293 while (--n >= 0) { 294 close (s[n].fd); 295 free (s[n].pathname); 296 } 297 break; 298 } else if (tmp == 0) 299 ++n; 300 } 301 302 if (tmp == 1) 303 continue; 304#endif 305 306 if (tcp_socket) { 307 tmp = try_tcp (&s[n], dpy); 308 if (tmp == -1) 309 err(1, "failed to open tcp stocket"); 310 else if (tmp == 1) { 311 while (--n >= 0) { 312 close (s[n].fd); 313 free (s[n].pathname); 314 } 315 break; 316 } else if (tmp == 0) 317 ++n; 318 } 319 break; 320 } 321 if (dpy == 256) 322 errx (1, "no free x-servers"); 323 for (i = 0; i < n; ++i) 324 if (s[i].flags & LISTENP 325 && listen (s[i].fd, SOMAXCONN) < 0) 326 err (1, "listen %s", s[i].pathname ? s[i].pathname : "tcp"); 327 *number = n; 328 *sockets = s; 329 return dpy; 330} 331 332/* 333 * Change owner on the `n' sockets in `sockets' to `uid', `gid'. 334 * Return 0 is succesful or -1 if an error occurred. 335 */ 336 337int 338chown_xsockets (int n, struct x_socket *sockets, uid_t uid, gid_t gid) 339{ 340 int i; 341 342 for (i = 0; i < n; ++i) 343 if (sockets[i].pathname != NULL) 344 if (chown (sockets[i].pathname, uid, gid) < 0) 345 return -1; 346 return 0; 347} 348 349/* 350 * Connect to local display `dnr' with local transport or TCP. 351 * Return a file descriptor. 352 */ 353 354int 355connect_local_xsocket (unsigned dnr) 356{ 357 int fd; 358 char **path; 359 360 for (path = x_sockets; *path; ++path) { 361 struct sockaddr_un addr; 362 363 fd = socket (AF_UNIX, SOCK_STREAM, 0); 364 if (fd < 0) 365 break; 366 memset (&addr, 0, sizeof(addr)); 367 addr.sun_family = AF_UNIX; 368 snprintf (addr.sun_path, sizeof(addr.sun_path), *path, dnr); 369 if (connect (fd, (struct sockaddr *)&addr, sizeof(addr)) == 0) 370 return fd; 371 close(fd); 372 } 373 { 374 struct sockaddr_in addr; 375 376 fd = socket(AF_INET, SOCK_STREAM, 0); 377 if (fd < 0) 378 err (1, "socket AF_INET"); 379 memset (&addr, 0, sizeof(addr)); 380 addr.sin_family = AF_INET; 381 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 382 addr.sin_port = htons(6000 + dnr); 383 if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == 0) 384 return fd; 385 close(fd); 386 } 387 err (1, "connecting to local display %u", dnr); 388} 389 390/* 391 * Create a cookie file with a random cookie for the localhost. The 392 * file name will be stored in `xauthfile' (but not larger than 393 * `xauthfile_size'), and the cookie returned in `cookie', `cookie_sz'. 394 * Return 0 if succesful, or errno. 395 */ 396 397int 398create_and_write_cookie (char *file, 399 size_t file_size, 400 u_char *cookie_buf, 401 size_t cookie_sz) 402{ 403 Xauth auth; 404 char tmp[64]; 405 int fd; 406 FILE *f; 407 char hostname[MaxHostNameLen]; 408 int saved_errno; 409 410 gethostname (hostname, sizeof(hostname)); 411 412 auth.family = FamilyLocal; 413 auth.address = hostname; 414 auth.address_length = strlen(auth.address); 415 snprintf (tmp, sizeof(tmp), "%d", display_num); 416 auth.number_length = strlen(tmp); 417 auth.number = tmp; 418 auth.name = COOKIE_TYPE; 419 auth.name_length = strlen(auth.name); 420 auth.data_length = cookie_sz; 421 auth.data = (char*)cookie_buf; 422#ifdef KRB5 423 krb5_generate_random_block (cookie_buf, cookie_sz); 424#else 425 krb_generate_random_block (cookie_buf, cookie_sz); 426#endif 427 428 strlcpy(file, "/tmp/AXXXXXX", file_size); 429 fd = mkstemp(file); 430 if(fd < 0) { 431 saved_errno = errno; 432 syslog(LOG_ERR, "create_and_write_cookie: mkstemp: %m"); 433 return saved_errno; 434 } 435 f = fdopen(fd, "r+"); 436 if(f == NULL){ 437 saved_errno = errno; 438 close(fd); 439 return errno; 440 } 441 if(XauWriteAuth(f, &auth) == 0) { 442 saved_errno = errno; 443 fclose(f); 444 return saved_errno; 445 } 446 447 /* 448 * I would like to write a cookie for localhost:n here, but some 449 * stupid code in libX11 will not look for cookies of that type, 450 * so we are forced to use FamilyWild instead. 451 */ 452 453 auth.family = FamilyWild; 454 auth.address_length = 0; 455 456 if (XauWriteAuth(f, &auth) == 0) { 457 saved_errno = errno; 458 fclose (f); 459 return saved_errno; 460 } 461 462 if(fclose(f)) 463 return errno; 464 return 0; 465} 466 467/* 468 * Verify and remove cookies. Read and parse a X-connection from 469 * `fd'. Check the cookie used is the same as in `cookie'. Remove the 470 * cookie and copy the rest of it to `sock'. 471 * Expect cookies iff cookiesp. 472 * Return 0 iff ok. 473 * 474 * The protocol is as follows: 475 * 476 * C->S: [Bl] 1 477 * unused 1 478 * protocol major version 2 479 * protocol minor version 2 480 * length of auth protocol name(n) 2 481 * length of auth protocol data 2 482 * unused 2 483 * authorization protocol name n 484 * pad pad(n) 485 * authorization protocol data d 486 * pad pad(d) 487 * 488 * S->C: Failed 489 * 0 1 490 * length of reason 1 491 * protocol major version 2 492 * protocol minor version 2 493 * length in 4 bytes unit of 494 * additional data (n+p)/4 2 495 * reason n 496 * unused p = pad(n) 497 */ 498 499int 500verify_and_remove_cookies (int fd, int sock, int cookiesp) 501{ 502 u_char beg[12]; 503 int bigendianp; 504 unsigned n, d, npad, dpad; 505 char *protocol_name, *protocol_data; 506 u_char zeros[6] = {0, 0, 0, 0, 0, 0}; 507 u_char refused[20] = {0, 10, 508 0, 0, /* protocol major version */ 509 0, 0, /* protocol minor version */ 510 0, 0, /* length of additional data / 4 */ 511 'b', 'a', 'd', ' ', 'c', 'o', 'o', 'k', 'i', 'e', 512 0, 0}; 513 514 if (net_read (fd, beg, sizeof(beg)) != sizeof(beg)) 515 return 1; 516 if (net_write (sock, beg, 6) != 6) 517 return 1; 518 bigendianp = beg[0] == 'B'; 519 if (bigendianp) { 520 n = (beg[6] << 8) | beg[7]; 521 d = (beg[8] << 8) | beg[9]; 522 } else { 523 n = (beg[7] << 8) | beg[6]; 524 d = (beg[9] << 8) | beg[8]; 525 } 526 npad = (4 - (n % 4)) % 4; 527 dpad = (4 - (d % 4)) % 4; 528 protocol_name = malloc(n + npad); 529 if (n + npad != 0 && protocol_name == NULL) 530 return 1; 531 protocol_data = malloc(d + dpad); 532 if (d + dpad != 0 && protocol_data == NULL) { 533 free (protocol_name); 534 return 1; 535 } 536 if (net_read (fd, protocol_name, n + npad) != n + npad) 537 goto fail; 538 if (net_read (fd, protocol_data, d + dpad) != d + dpad) 539 goto fail; 540 if (cookiesp) { 541 if (strncmp (protocol_name, COOKIE_TYPE, strlen(COOKIE_TYPE)) != 0) 542 goto refused; 543 if (d != cookie_len || 544 memcmp (protocol_data, cookie, cookie_len) != 0) 545 goto refused; 546 } 547 free (protocol_name); 548 free (protocol_data); 549 if (net_write (sock, zeros, 6) != 6) 550 return 1; 551 return 0; 552refused: 553 refused[2] = beg[2]; 554 refused[3] = beg[3]; 555 refused[4] = beg[4]; 556 refused[5] = beg[5]; 557 if (bigendianp) 558 refused[7] = 3; 559 else 560 refused[6] = 3; 561 562 net_write (fd, refused, sizeof(refused)); 563fail: 564 free (protocol_name); 565 free (protocol_data); 566 return 1; 567} 568 569/* 570 * Return 0 iff `cookie' is compatible with the cookie for the 571 * localhost with name given in `ai' (or `hostname') and display 572 * number in `disp_nr'. 573 */ 574 575static int 576match_local_auth (Xauth* auth, 577 struct addrinfo *ai, const char *hostname, int disp_nr) 578{ 579 int auth_disp; 580 char *tmp_disp; 581 struct addrinfo *a; 582 583 tmp_disp = malloc(auth->number_length + 1); 584 if (tmp_disp == NULL) 585 return -1; 586 memcpy(tmp_disp, auth->number, auth->number_length); 587 tmp_disp[auth->number_length] = '\0'; 588 auth_disp = atoi(tmp_disp); 589 free (tmp_disp); 590 if (auth_disp != disp_nr) 591 return 1; 592 for (a = ai; a != NULL; a = a->ai_next) { 593 if ((auth->family == FamilyLocal 594 || auth->family == FamilyWild) 595 && a->ai_canonname != NULL 596 && strncmp (auth->address, 597 a->ai_canonname, 598 auth->address_length) == 0) 599 return 0; 600 } 601 if (hostname != NULL 602 && (auth->family == FamilyLocal 603 || auth->family == FamilyWild) 604 && strncmp (auth->address, hostname, auth->address_length) == 0) 605 return 0; 606 return 1; 607} 608 609/* 610 * Find `our' cookie from the cookie file `f' and return it or NULL. 611 */ 612 613static Xauth* 614find_auth_cookie (FILE *f) 615{ 616 Xauth *ret = NULL; 617 char local_hostname[MaxHostNameLen]; 618 char *display_str = getenv("DISPLAY"); 619 char d[MaxHostNameLen + 4]; 620 char *colon; 621 struct addrinfo *ai; 622 struct addrinfo hints; 623 int disp; 624 int error; 625 626 if(display_str == NULL) 627 display_str = ":0"; 628 strlcpy(d, display_str, sizeof(d)); 629 display_str = d; 630 colon = strchr (display_str, ':'); 631 if (colon == NULL) 632 disp = 0; 633 else { 634 *colon = '\0'; 635 disp = atoi (colon + 1); 636 } 637 if (strcmp (display_str, "") == 0 638 || strncmp (display_str, "unix", 4) == 0 639 || strncmp (display_str, "localhost", 9) == 0) { 640 gethostname (local_hostname, sizeof(local_hostname)); 641 display_str = local_hostname; 642 } 643 memset (&hints, 0, sizeof(hints)); 644 hints.ai_flags = AI_CANONNAME; 645 hints.ai_socktype = SOCK_STREAM; 646 hints.ai_protocol = IPPROTO_TCP; 647 648 error = getaddrinfo (display_str, NULL, &hints, &ai); 649 if (error) 650 ai = NULL; 651 652 for (; (ret = XauReadAuth (f)) != NULL; XauDisposeAuth(ret)) { 653 if (match_local_auth (ret, ai, display_str, disp) == 0) { 654 if (ai != NULL) 655 freeaddrinfo (ai); 656 return ret; 657 } 658 } 659 if (ai != NULL) 660 freeaddrinfo (ai); 661 return NULL; 662} 663 664/* 665 * Get rid of the cookie that we were sent and get the correct one 666 * from our own cookie file instead. 667 */ 668 669int 670replace_cookie(int xserver, int fd, char *filename, int cookiesp) /* XXX */ 671{ 672 u_char beg[12]; 673 int bigendianp; 674 unsigned n, d, npad, dpad; 675 FILE *f; 676 u_char zeros[6] = {0, 0, 0, 0, 0, 0}; 677 678 if (net_read (fd, beg, sizeof(beg)) != sizeof(beg)) 679 return 1; 680 if (net_write (xserver, beg, 6) != 6) 681 return 1; 682 bigendianp = beg[0] == 'B'; 683 if (bigendianp) { 684 n = (beg[6] << 8) | beg[7]; 685 d = (beg[8] << 8) | beg[9]; 686 } else { 687 n = (beg[7] << 8) | beg[6]; 688 d = (beg[9] << 8) | beg[8]; 689 } 690 if (n != 0 || d != 0) 691 return 1; 692 f = fopen(filename, "r"); 693 if (f != NULL) { 694 Xauth *auth = find_auth_cookie (f); 695 u_char len[6] = {0, 0, 0, 0, 0, 0}; 696 697 fclose (f); 698 699 if (auth != NULL) { 700 n = auth->name_length; 701 d = auth->data_length; 702 } else { 703 n = 0; 704 d = 0; 705 } 706 if (bigendianp) { 707 len[0] = n >> 8; 708 len[1] = n & 0xFF; 709 len[2] = d >> 8; 710 len[3] = d & 0xFF; 711 } else { 712 len[0] = n & 0xFF; 713 len[1] = n >> 8; 714 len[2] = d & 0xFF; 715 len[3] = d >> 8; 716 } 717 if (net_write (xserver, len, 6) != 6) { 718 XauDisposeAuth(auth); 719 return 1; 720 } 721 if(n != 0 && net_write (xserver, auth->name, n) != n) { 722 XauDisposeAuth(auth); 723 return 1; 724 } 725 npad = (4 - (n % 4)) % 4; 726 if (npad && net_write (xserver, zeros, npad) != npad) { 727 XauDisposeAuth(auth); 728 return 1; 729 } 730 if (d != 0 && net_write (xserver, auth->data, d) != d) { 731 XauDisposeAuth(auth); 732 return 1; 733 } 734 XauDisposeAuth(auth); 735 dpad = (4 - (d % 4)) % 4; 736 if (dpad && net_write (xserver, zeros, dpad) != dpad) 737 return 1; 738 } else { 739 if(net_write(xserver, zeros, 6) != 6) 740 return 1; 741 } 742 return 0; 743} 744 745/* 746 * Some simple controls on the address and corresponding socket 747 */ 748 749int 750suspicious_address (int sock, struct sockaddr *addr) 751{ 752 char data[40]; 753 socklen_t len = sizeof(data); 754 755 switch (addr->sa_family) { 756 case AF_INET: 757 return ((struct sockaddr_in *)addr)->sin_addr.s_addr != 758 htonl(INADDR_LOOPBACK) 759#if defined(IP_OPTIONS) && defined(HAVE_GETSOCKOPT) 760 || getsockopt (sock, IPPROTO_IP, IP_OPTIONS, data, &len) < 0 761 || len != 0 762#endif 763 ; 764 break; 765#ifdef HAVE_IPV6 766 case AF_INET6: 767 /* XXX check route headers */ 768 return !IN6_IS_ADDR_LOOPBACK(&((struct sockaddr_in6*)addr)->sin6_addr); 769#endif 770 default: 771 return 1; 772 } 773} 774 775/* 776 * This really sucks, but these functions are used and if we're not 777 * linking against libkrb they don't exist. Using the heimdal storage 778 * functions will not work either cause we do not always link with 779 * libkrb5 either. 780 */ 781 782int 783kx_get_int(void *f, uint32_t *to, int size, int lsb) 784{ 785 int i; 786 unsigned char *from = (unsigned char *)f; 787 788 *to = 0; 789 if(lsb){ 790 for(i = size-1; i >= 0; i--) 791 *to = (*to << 8) | from[i]; 792 }else{ 793 for(i = 0; i < size; i++) 794 *to = (*to << 8) | from[i]; 795 } 796 return size; 797} 798 799int 800kx_put_int(uint32_t from, void *to, size_t rem, int size) 801{ 802 int i; 803 unsigned char *p = (unsigned char *)to; 804 805 if (rem < size) 806 return -1; 807 808 for(i = size - 1; i >= 0; i--){ 809 p[i] = from & 0xff; 810 from >>= 8; 811 } 812 return size; 813} 814