1 /* 2 3 Copyright 1988, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 10 11 The above copyright notice and this permission notice shall be included 12 in all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 OTHER DEALINGS IN THE SOFTWARE. 21 22 Except as contained in this notice, the name of The Open Group shall 23 not be used in advertising or otherwise to promote the sale, use or 24 other dealings in this Software without prior written authorization 25 from The Open Group. 26 27 */ 28 29 /* 30 * xdm - display manager daemon 31 * Author: Keith Packard, MIT X Consortium 32 * 33 * xdmcp.c - Support for XDMCP 34 */ 35 36 #include "dm.h" 37 #include "dm_auth.h" 38 #include "dm_error.h" 39 40 #ifdef XDMCP 41 42 # include <X11/X.h> 43 # include <X11/Xfuncs.h> 44 # include <sys/types.h> 45 # include <ctype.h> 46 47 # include "dm_socket.h" 48 49 # include <sys/un.h> 50 # include <netdb.h> 51 # include <arpa/inet.h> 52 53 # include <time.h> 54 # define Time_t time_t 55 56 # define getString(name,len) ((name = malloc (len + 1)) ? 1 : 0) 57 58 /* 59 * misc externs 60 */ 61 extern volatile int Rescan; 62 extern int sourceAddress, ChildReady; 63 64 /* 65 * Forward reference 66 */ 67 static void broadcast_respond (struct sockaddr *from, int fromlen, int length, int fd); 68 static void forward_respond (struct sockaddr *from, int fromlen, int length, int fd); 69 static void manage (struct sockaddr *from, int fromlen, int length, int fd); 70 static void query_respond (struct sockaddr *from, int fromlen, int length, int fd); 71 static void request_respond (struct sockaddr *from, int fromlen, int length, int fd); 72 static void send_accept (struct sockaddr *to, int tolen, CARD32 sessionID, ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData, ARRAY8Ptr authorizationName, ARRAY8Ptr authorizationData, int fd); 73 static void send_alive (struct sockaddr *from, int fromlen, int length, int fd); 74 static void send_decline (struct sockaddr *to, int tolen, ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData, ARRAY8Ptr status, int fd); 75 static void send_failed (struct sockaddr *from, int fromlen, const char *name, CARD32 sessionID, const char *reason, int fd); 76 static void send_refuse (struct sockaddr *from, int fromlen, CARD32 sessionID, int fd); 77 static void send_unwilling (struct sockaddr *from, int fromlen, ARRAY8Ptr authenticationName, ARRAY8Ptr status, int fd); 78 static void send_willing (struct sockaddr *from, int fromlen, ARRAY8Ptr authenticationName, ARRAY8Ptr status, int fd); 79 80 int chooserFd = -1; 81 # ifdef IPv6 82 int chooserFd6 = -1; 83 # endif 84 85 FD_TYPE WellKnownSocketsMask; 86 int WellKnownSocketsMax; 87 88 # define pS(s) ((s) ? ((char *) (s)) : "empty string") 89 90 void 91 DestroyWellKnownSockets (void) 92 { 93 if (chooserFd != -1) 94 { 95 close (chooserFd); 96 FD_CLR(chooserFd, &WellKnownSocketsMask); 97 chooserFd = -1; 98 } 99 # ifdef IPv6 100 if (chooserFd6 != -1) 101 { 102 close (chooserFd6); 103 FD_CLR(chooserFd6, &WellKnownSocketsMask); 104 chooserFd6 = -1; 105 } 106 # endif 107 CloseListenSockets(); 108 } 109 110 static int 111 FD_ANYSET(fd_set *fds) 112 { 113 int i; 114 char *mask = (char *) fds; 115 116 for (i = 0 ; i < sizeof(fds); i++) { 117 if (mask[i]) 118 return TRUE; 119 } 120 return FALSE; 121 } 122 123 int 124 AnyWellKnownSockets (void) 125 { 126 return 127 # ifdef IPv6 128 chooserFd6 != -1 || 129 # endif 130 chooserFd != -1 || FD_ANYSET(&WellKnownSocketsMask); 131 } 132 133 static XdmcpBuffer buffer; 134 135 /*ARGSUSED*/ 136 static void 137 sendForward ( 138 CARD16 connectionType, 139 ARRAY8Ptr address, 140 char *closure) 141 { 142 # ifdef AF_INET 143 struct sockaddr_in in_addr; 144 # endif 145 # ifdef IPv6 146 struct sockaddr_in6 in6_addr; 147 # endif 148 struct sockaddr *addr; 149 int addrlen; 150 151 switch (connectionType) 152 { 153 # ifdef AF_INET 154 case FamilyInternet: 155 addr = (struct sockaddr *) &in_addr; 156 bzero ((char *) &in_addr, sizeof (in_addr)); 157 # ifdef BSD44SOCKETS 158 in_addr.sin_len = sizeof(in_addr); 159 # endif 160 in_addr.sin_family = AF_INET; 161 in_addr.sin_port = htons ((short) XDM_UDP_PORT); 162 if (address->length != 4) 163 return; 164 memcpy(&in_addr.sin_addr, address->data, address->length); 165 addrlen = sizeof (struct sockaddr_in); 166 break; 167 # endif 168 # ifdef IPv6 169 case FamilyInternet6: 170 addr = (struct sockaddr *) &in6_addr; 171 bzero ((char *) &in6_addr, sizeof (in6_addr)); 172 # ifdef SIN6_LEN 173 in6_addr.sin6_len = sizeof(in6_addr); 174 # endif 175 in6_addr.sin6_family = AF_INET6; 176 in6_addr.sin6_port = htons ((short) XDM_UDP_PORT); 177 if (address->length != 16) 178 return; 179 memcpy(&in6_addr.sin6_addr, address->data, address->length); 180 addrlen = sizeof (struct sockaddr_in6); 181 break; 182 # endif 183 default: 184 return; 185 } 186 XdmcpFlush (*((int *) closure), &buffer, (XdmcpNetaddr) addr, addrlen); 187 return; 188 } 189 190 static void 191 ClientAddress ( 192 struct sockaddr *from, 193 ARRAY8Ptr addr, /* return */ 194 ARRAY8Ptr port, /* return */ 195 CARD16 *type) /* return */ 196 { 197 int length, family; 198 char *data; 199 200 data = NetaddrPort((XdmcpNetaddr) from, &length); 201 XdmcpAllocARRAY8 (port, length); 202 memcpy(port->data, data, length); 203 port->length = length; 204 205 family = ConvertAddr((XdmcpNetaddr) from, &length, &data); 206 XdmcpAllocARRAY8 (addr, length); 207 memcpy(addr->data, data, length); 208 addr->length = length; 209 210 *type = family; 211 } 212 213 static void 214 all_query_respond ( 215 struct sockaddr *from, 216 int fromlen, 217 ARRAYofARRAY8Ptr authenticationNames, 218 xdmOpCode type, 219 int fd) 220 { 221 ARRAY8Ptr authenticationName; 222 ARRAY8 status = {0, NULL}; 223 ARRAY8 addr = {0, NULL}; 224 CARD16 connectionType; 225 int family; 226 int length; 227 const char *addrstring; 228 # ifdef IPv6 229 char addrbuf[INET6_ADDRSTRLEN] = ""; 230 # elif defined(HAVE_INET_NTOP) 231 char addrbuf[INET_ADDRSTRLEN] = ""; 232 # endif 233 234 family = ConvertAddr((XdmcpNetaddr) from, &length, (char **)&(addr.data)); 235 if (family < 0) { 236 Debug("all_query_respond: ConvertAddr failed: conntype=%d\n", family); 237 return; 238 } 239 addr.length = length; /* convert int to short */ 240 if (debugLevel > 0) { 241 # ifdef HAVE_INET_NTOP 242 void *ipaddr; 243 int af_type; 244 # ifdef IPv6 245 if (family == FamilyInternet6) { 246 ipaddr = & ((struct sockaddr_in6 *) from)->sin6_addr; 247 af_type = AF_INET6; 248 } else 249 # endif 250 { 251 ipaddr = & ((struct sockaddr_in *) from)->sin_addr; 252 af_type = AF_INET; 253 } 254 addrstring = inet_ntop(af_type, ipaddr, addrbuf, sizeof(addrbuf)); 255 # else 256 addrstring = inet_ntoa(((struct sockaddr_in *)from)->sin_addr); 257 # endif 258 Debug("all_query_respond: conntype=%d, addr=%s, len=%d\n", 259 family, addrstring, addr.length); 260 } 261 connectionType = family; 262 263 if (type == INDIRECT_QUERY) 264 RememberIndirectClient (&addr, connectionType); 265 else 266 ForgetIndirectClient (&addr, connectionType); 267 268 authenticationName = ChooseAuthentication (authenticationNames); 269 if (Willing (&addr, connectionType, authenticationName, &status, type)) 270 send_willing (from, fromlen, authenticationName, &status, fd); 271 else 272 if (type == QUERY) 273 send_unwilling (from, fromlen, authenticationName, &status, fd); 274 XdmcpDisposeARRAY8 (&status); 275 } 276 277 static void 278 indirect_respond ( 279 struct sockaddr *from, 280 int fromlen, 281 int length, 282 int fd) 283 { 284 ARRAYofARRAY8 queryAuthenticationNames = {0, NULL}; 285 ARRAY8 clientAddress = {0, NULL}; 286 ARRAY8 clientPort = {0, NULL}; 287 CARD16 connectionType; 288 int expectedLen; 289 int i; 290 XdmcpHeader header; 291 int localHostAsWell; 292 293 Debug ("Indirect respond %d\n", length); 294 if (!XdmcpReadARRAYofARRAY8 (&buffer, &queryAuthenticationNames)) 295 return; 296 expectedLen = 1; 297 for (i = 0; i < (int)queryAuthenticationNames.length; i++) 298 expectedLen += 2 + queryAuthenticationNames.data[i].length; 299 if (length == expectedLen) 300 { 301 ClientAddress (from, &clientAddress, &clientPort, &connectionType); 302 /* 303 * set up the forward query packet 304 */ 305 header.version = XDM_PROTOCOL_VERSION; 306 header.opcode = (CARD16) FORWARD_QUERY; 307 header.length = 0; 308 header.length += 2 + clientAddress.length; 309 header.length += 2 + clientPort.length; 310 header.length += 1; 311 for (i = 0; i < (int)queryAuthenticationNames.length; i++) 312 header.length += 2 + queryAuthenticationNames.data[i].length; 313 XdmcpWriteHeader (&buffer, &header); 314 XdmcpWriteARRAY8 (&buffer, &clientAddress); 315 XdmcpWriteARRAY8 (&buffer, &clientPort); 316 XdmcpWriteARRAYofARRAY8 (&buffer, &queryAuthenticationNames); 317 318 localHostAsWell = ForEachMatchingIndirectHost (&clientAddress, connectionType, sendForward, (char *) &fd); 319 320 XdmcpDisposeARRAY8 (&clientAddress); 321 XdmcpDisposeARRAY8 (&clientPort); 322 if (localHostAsWell) 323 all_query_respond (from, fromlen, &queryAuthenticationNames, 324 INDIRECT_QUERY, fd); 325 } 326 else 327 { 328 Debug ("Indirect length error got %d expect %d\n", length, expectedLen); 329 } 330 XdmcpDisposeARRAYofARRAY8 (&queryAuthenticationNames); 331 } 332 333 void 334 ProcessRequestSocket (int fd) 335 { 336 XdmcpHeader header; 337 # ifdef HAVE_STRUCT_SOCKADDR_STORAGE 338 struct sockaddr_storage addr; 339 # else 340 struct sockaddr addr; 341 # endif 342 int addrlen = sizeof addr; 343 344 Debug ("ProcessRequestSocket\n"); 345 bzero ((char *) &addr, sizeof (addr)); 346 if (!XdmcpFill (fd, &buffer, (XdmcpNetaddr) &addr, &addrlen)) { 347 Debug ("XdmcpFill failed\n"); 348 return; 349 } 350 if (!XdmcpReadHeader (&buffer, &header)) { 351 Debug ("XdmcpReadHeader failed\n"); 352 return; 353 } 354 if (header.version != XDM_PROTOCOL_VERSION) { 355 Debug ("XDMCP header version read was %d, expected %d\n", 356 header.version, XDM_PROTOCOL_VERSION); 357 return; 358 } 359 Debug ("header: %d %d %d\n", header.version, header.opcode, header.length); 360 switch (header.opcode) 361 { 362 case BROADCAST_QUERY: 363 broadcast_respond ((struct sockaddr *) &addr, addrlen, header.length, fd); 364 break; 365 case QUERY: 366 query_respond ((struct sockaddr *) &addr, addrlen, header.length, fd); 367 break; 368 case INDIRECT_QUERY: 369 indirect_respond ((struct sockaddr *) &addr, addrlen, header.length, fd); 370 break; 371 case FORWARD_QUERY: 372 forward_respond ((struct sockaddr *) &addr, addrlen, header.length, fd); 373 break; 374 case REQUEST: 375 request_respond ((struct sockaddr *) &addr, addrlen, header.length, fd); 376 break; 377 case MANAGE: 378 manage ((struct sockaddr *) &addr, addrlen, header.length, fd); 379 break; 380 case KEEPALIVE: 381 send_alive ((struct sockaddr *) &addr, addrlen, header.length, fd); 382 break; 383 } 384 } 385 386 void 387 WaitForSomething (void) 388 { 389 FD_TYPE reads; 390 int nready; 391 392 Debug ("WaitForSomething\n"); 393 if (AnyWellKnownSockets () && !ChildReady) { 394 reads = WellKnownSocketsMask; 395 nready = select (WellKnownSocketsMax + 1, &reads, NULL, NULL, NULL); 396 Debug ("select returns %d. Rescan: %d ChildReady: %d\n", 397 nready, Rescan, ChildReady); 398 if (nready > 0) 399 { 400 if (chooserFd >= 0 && FD_ISSET (chooserFd, &reads)) 401 { 402 ProcessChooserSocket (chooserFd); 403 FD_CLR(chooserFd, &reads); 404 } 405 # ifdef IPv6 406 if (chooserFd6 >= 0 && FD_ISSET (chooserFd6, &reads)) 407 { 408 ProcessChooserSocket (chooserFd6); 409 FD_CLR(chooserFd6, &reads); 410 } 411 # endif 412 ProcessListenSockets(&reads); 413 } 414 if (ChildReady) 415 { 416 WaitForChild (); 417 } 418 } else 419 WaitForChild (); 420 } 421 422 /* 423 * respond to a request on the UDP socket. 424 */ 425 426 static ARRAY8 Hostname; 427 428 void 429 registerHostname ( 430 char *name, 431 int namelen) 432 { 433 int i; 434 435 if (!XdmcpReallocARRAY8 (&Hostname, namelen)) 436 return; 437 for (i = 0; i < namelen; i++) 438 Hostname.data[i] = name[i]; 439 } 440 441 static void 442 direct_query_respond ( 443 struct sockaddr *from, 444 int fromlen, 445 int length, 446 xdmOpCode type, 447 int fd) 448 { 449 ARRAYofARRAY8 queryAuthenticationNames = {0, NULL}; 450 int expectedLen; 451 int i; 452 453 if (!XdmcpReadARRAYofARRAY8 (&buffer, &queryAuthenticationNames)) 454 return; 455 expectedLen = 1; 456 for (i = 0; i < (int)queryAuthenticationNames.length; i++) 457 expectedLen += 2 + queryAuthenticationNames.data[i].length; 458 if (length == expectedLen) 459 all_query_respond (from, fromlen, &queryAuthenticationNames, type, fd); 460 XdmcpDisposeARRAYofARRAY8 (&queryAuthenticationNames); 461 } 462 463 static void 464 query_respond ( 465 struct sockaddr *from, 466 int fromlen, 467 int length, 468 int fd) 469 { 470 Debug ("Query respond %d\n", length); 471 direct_query_respond (from, fromlen, length, QUERY, fd); 472 } 473 474 static void 475 broadcast_respond ( 476 struct sockaddr *from, 477 int fromlen, 478 int length, 479 int fd) 480 { 481 direct_query_respond (from, fromlen, length, BROADCAST_QUERY, fd); 482 } 483 484 /* computes an X display name */ 485 486 static char * 487 NetworkAddressToName( 488 CARD16 connectionType, 489 ARRAY8Ptr connectionAddress, 490 struct sockaddr *originalAddress, 491 CARD16 displayNumber) 492 { 493 switch (connectionType) 494 { 495 case FamilyInternet: 496 # if defined(HAVE_GETADDRINFO) && defined(HAVE_INET_NTOP) 497 # ifdef IPv6 498 case FamilyInternet6: 499 # endif 500 { 501 CARD8 *data; 502 struct hostent *hostent; 503 char *hostname = NULL; 504 char *name; 505 char *localhost; 506 int multiHomed = 0; 507 struct addrinfo hints, *ai = NULL, *nai; 508 int type; 509 510 # ifdef IPv6 511 if (connectionType == FamilyInternet6) 512 type = AF_INET6; 513 else 514 # endif 515 type = AF_INET; 516 517 data = connectionAddress->data; 518 hostent = gethostbyaddr ((char *)data, 519 connectionAddress->length, type); 520 if (hostent) { 521 if (sourceAddress) { 522 bzero(&hints, sizeof(hints)); 523 hints.ai_flags = AI_CANONNAME; 524 # ifdef IPv6 525 hints.ai_family = AF_UNSPEC; 526 # else 527 hints.ai_family = AF_INET; 528 # endif 529 if (getaddrinfo(hostent->h_name, NULL, &hints, &ai) == 0) { 530 hostname = ai->ai_canonname; 531 for (nai = ai->ai_next; nai!=NULL; nai=nai->ai_next) { 532 if ((ai->ai_protocol == nai->ai_protocol) && 533 (ai->ai_addrlen == nai->ai_addrlen) && 534 (memcmp(ai->ai_addr,nai->ai_addr, 535 ai->ai_addrlen) != 0) ) { 536 multiHomed = 1; 537 } 538 } 539 } 540 } else { 541 hostname = hostent->h_name; 542 } 543 } 544 545 localhost = localHostname (); 546 547 /* 548 * protect against bogus host names 549 */ 550 if (hostname && hostname[0] && (hostname[0] != '.') 551 && !multiHomed) 552 { 553 if (!strcmp (localhost, hostname)) 554 { 555 if (asprintf(&name, ":%d", displayNumber) < 0) { 556 if (ai) 557 freeaddrinfo(ai); 558 return NULL; 559 } 560 } 561 else 562 { 563 if (removeDomainname) 564 { 565 char *localDot, *remoteDot; 566 567 /* check for a common domain name. This 568 * could reduce names by recognising common 569 * super-domain names as well, but I don't think 570 * this is as useful, and will confuse more 571 * people 572 */ 573 if ((localDot = strchr(localhost, '.')) && 574 (remoteDot = strchr(hostname, '.'))) 575 { 576 /* smash the name in place; it won't 577 * be needed later. 578 */ 579 if (!strcmp (localDot+1, remoteDot+1)) 580 *remoteDot = '\0'; 581 } 582 } 583 584 if (asprintf (&name, "%s:%d", 585 hostname, displayNumber) < 0) { 586 if (ai) 587 freeaddrinfo(ai); 588 return NULL; 589 } 590 } 591 } 592 else 593 { 594 if (!getString (name, INET6_ADDRSTRLEN + 10)) { 595 if (ai) 596 freeaddrinfo(ai); 597 return NULL; 598 } 599 if (multiHomed) { 600 if (connectionType == FamilyInternet) { 601 data = (CARD8 *) 602 &((struct sockaddr_in *)originalAddress)-> 603 sin_addr; 604 # ifdef IPv6 605 } else { 606 data = (CARD8 *) 607 &((struct sockaddr_in6 *)originalAddress)->sin6_addr; 608 # endif 609 } 610 } 611 if (inet_ntop(type, data, name, INET6_ADDRSTRLEN) == NULL) { 612 free(name); 613 if (ai) 614 freeaddrinfo(ai); 615 return NULL; 616 } 617 snprintf(name + strlen(name), 10, ":%d", displayNumber); 618 } 619 if (ai) 620 freeaddrinfo(ai); 621 return name; 622 } 623 # else /* !HAVE_GETADDRINFO */ 624 { 625 CARD8 *data; 626 struct hostent *hostent; 627 char *name; 628 char *localhost; 629 int multiHomed = 0; 630 631 data = connectionAddress->data; 632 hostent = gethostbyaddr ((char *)data, 633 connectionAddress->length, AF_INET); 634 if (sourceAddress && hostent) { 635 hostent = gethostbyname(hostent->h_name); 636 if (hostent) 637 multiHomed = hostent->h_addr_list[1] != NULL; 638 } 639 640 localhost = localHostname (); 641 642 /* 643 * protect against bogus host names 644 */ 645 if (hostent && hostent->h_name && hostent->h_name[0] 646 && (hostent->h_name[0] != '.') 647 && !multiHomed) 648 { 649 if (!strcmp (localhost, hostent->h_name)) 650 { 651 if (asprintf(&name, ":%d", displayNumber) < 0) { 652 return NULL; 653 } 654 } 655 else 656 { 657 if (removeDomainname) 658 { 659 char *localDot, *remoteDot; 660 661 /* check for a common domain name. This 662 * could reduce names by recognising common 663 * super-domain names as well, but I don't think 664 * this is as useful, and will confuse more 665 * people 666 */ 667 if ((localDot = strchr(localhost, '.')) && 668 (remoteDot = strchr(hostent->h_name, '.'))) 669 { 670 /* smash the name in place; it won't 671 * be needed later. 672 */ 673 if (!strcmp (localDot+1, remoteDot+1)) 674 *remoteDot = '\0'; 675 } 676 } 677 678 if (asprintf(&name, "%s:%d", 679 hostent->h_name, displayNumber) < 0) { 680 return NULL; 681 } 682 } 683 } 684 else 685 { 686 if (multiHomed) 687 data = (CARD8 *) &((struct sockaddr_in *)originalAddress)-> 688 sin_addr.s_addr; 689 690 if (asprintf(&name, "%d.%d.%d.%d:%d", 691 data[0], data[1], data[2], data[3], 692 displayNumber) < 0) { 693 return NULL; 694 } 695 } 696 return name; 697 } 698 # endif /* HAVE_GETADDRINFO */ 699 default: 700 return NULL; 701 } 702 } 703 704 /*ARGSUSED*/ 705 static void 706 forward_respond ( 707 struct sockaddr *from, 708 int fromlen, 709 int length, 710 int fd) 711 { 712 ARRAY8 clientAddress = {0, NULL}; 713 ARRAY8 clientPort = {0, NULL}; 714 ARRAYofARRAY8 authenticationNames = {0, NULL}; 715 struct sockaddr *client; 716 int clientlen; 717 int expectedLen; 718 int i; 719 720 Debug ("Forward respond %d\n", length); 721 if (XdmcpReadARRAY8 (&buffer, &clientAddress) && 722 XdmcpReadARRAY8 (&buffer, &clientPort) && 723 XdmcpReadARRAYofARRAY8 (&buffer, &authenticationNames)) 724 { 725 expectedLen = 0; 726 expectedLen += 2 + clientAddress.length; 727 expectedLen += 2 + clientPort.length; 728 expectedLen += 1; /* authenticationNames */ 729 for (i = 0; i < (int)authenticationNames.length; i++) 730 expectedLen += 2 + authenticationNames.data[i].length; 731 if (length == expectedLen) 732 { 733 int j; 734 735 j = 0; 736 for (i = 0; i < (int)clientPort.length; i++) 737 j = j * 256 + clientPort.data[i]; 738 Debug ("Forward client address (port %d)", j); 739 for (i = 0; i < (int)clientAddress.length; i++) 740 Debug (" %d", clientAddress.data[i]); 741 Debug ("\n"); 742 switch (from->sa_family) 743 { 744 # ifdef AF_INET 745 case AF_INET: 746 { 747 struct sockaddr_in in_addr; 748 749 if (clientAddress.length != 4 || 750 clientPort.length != 2) 751 { 752 goto badAddress; 753 } 754 bzero ((char *) &in_addr, sizeof (in_addr)); 755 # ifdef BSD44SOCKETS 756 in_addr.sin_len = sizeof(in_addr); 757 # endif 758 in_addr.sin_family = AF_INET; 759 memcpy(&in_addr.sin_addr, clientAddress.data, 4); 760 memcpy(&in_addr.sin_port, clientPort.data, 2); 761 client = (struct sockaddr *) &in_addr; 762 clientlen = sizeof (in_addr); 763 all_query_respond (client, clientlen, &authenticationNames, 764 FORWARD_QUERY, fd); 765 } 766 break; 767 # endif 768 # ifdef IPv6 769 case AF_INET6: 770 { 771 struct sockaddr_in6 in6_addr; 772 773 if ((clientAddress.length != 16 && clientAddress.length != 4) || 774 (clientPort.length != 2)) 775 { 776 goto badAddress; 777 } 778 bzero ((char *) &in6_addr, sizeof (in6_addr)); 779 # ifdef SIN6_LEN 780 in6_addr.sin6_len = sizeof(in6_addr); 781 # endif 782 in6_addr.sin6_family = AF_INET6; 783 if (clientAddress.length == 16) { 784 memcpy(in6_addr.sin6_addr.s6_addr, clientAddress.data, 16); 785 } else { 786 /* If the client wants to forward the xdm server to an 787 ipv4 hosts it sends an ipv4 address in the forward 788 packet. On dual-stack hosts the packet arrives as a 789 ipv6 packet. To respond to the ipv4 host one has 790 to create an ipv4-mapped address of the form 791 792 ::ffff::xxx.xxx.xxx.xxx 793 794 One example where this is necessary is an ipv4-only 795 thin client that connects to a dual-stacked xdm. 796 */ 797 in6_addr.sin6_addr.s6_addr[10] = 0xff; 798 in6_addr.sin6_addr.s6_addr[11] = 0xff; 799 memcpy(in6_addr.sin6_addr.s6_addr + 12, 800 clientAddress.data, 4); 801 } 802 memcpy(&in6_addr.sin6_port, clientPort.data, 2); 803 client = (struct sockaddr *) &in6_addr; 804 clientlen = sizeof (in6_addr); 805 all_query_respond (client, clientlen, &authenticationNames, 806 FORWARD_QUERY, fd); 807 } 808 break; 809 # endif 810 # ifdef AF_UNIX 811 case AF_UNIX: 812 { 813 struct sockaddr_un un_addr; 814 815 if (clientAddress.length >= sizeof (un_addr.sun_path)) 816 goto badAddress; 817 bzero ((char *) &un_addr, sizeof (un_addr)); 818 un_addr.sun_family = AF_UNIX; 819 memcpy(un_addr.sun_path, clientAddress.data, 820 clientAddress.length); 821 un_addr.sun_path[clientAddress.length] = '\0'; 822 client = (struct sockaddr *) &un_addr; 823 # if defined(BSD44SOCKETS) && defined(UNIXCONN) 824 un_addr.sun_len = strlen(un_addr.sun_path); 825 clientlen = SUN_LEN(&un_addr); 826 # else 827 clientlen = sizeof (un_addr); 828 # endif 829 all_query_respond (client, clientlen, &authenticationNames, 830 FORWARD_QUERY, fd); 831 } 832 break; 833 # endif 834 } 835 } 836 else 837 { 838 Debug ("Forward length error got %d expect %d\n", length, expectedLen); 839 } 840 } 841 badAddress: 842 XdmcpDisposeARRAY8 (&clientAddress); 843 XdmcpDisposeARRAY8 (&clientPort); 844 XdmcpDisposeARRAYofARRAY8 (&authenticationNames); 845 } 846 847 static void 848 send_willing ( 849 struct sockaddr *from, 850 int fromlen, 851 ARRAY8Ptr authenticationName, 852 ARRAY8Ptr status, 853 int fd) 854 { 855 XdmcpHeader header; 856 857 Debug ("Send willing %*.*s %*.*s\n", authenticationName->length, 858 authenticationName->length, 859 pS(authenticationName->data), 860 status->length, 861 status->length, 862 pS(status->data)); 863 header.version = XDM_PROTOCOL_VERSION; 864 header.opcode = (CARD16) WILLING; 865 header.length = 6 + authenticationName->length + 866 Hostname.length + status->length; 867 XdmcpWriteHeader (&buffer, &header); 868 XdmcpWriteARRAY8 (&buffer, authenticationName); 869 XdmcpWriteARRAY8 (&buffer, &Hostname); 870 XdmcpWriteARRAY8 (&buffer, status); 871 XdmcpFlush (fd, &buffer, (XdmcpNetaddr) from, fromlen); 872 } 873 874 static void 875 send_unwilling ( 876 struct sockaddr *from, 877 int fromlen, 878 ARRAY8Ptr authenticationName, 879 ARRAY8Ptr status, 880 int fd) 881 { 882 XdmcpHeader header; 883 884 Debug ("Send unwilling %*.*s %*.*s\n", authenticationName->length, 885 authenticationName->length, 886 pS(authenticationName->data), 887 status->length, 888 status->length, 889 pS(status->data)); 890 header.version = XDM_PROTOCOL_VERSION; 891 header.opcode = (CARD16) UNWILLING; 892 header.length = 4 + Hostname.length + status->length; 893 XdmcpWriteHeader (&buffer, &header); 894 XdmcpWriteARRAY8 (&buffer, &Hostname); 895 XdmcpWriteARRAY8 (&buffer, status); 896 XdmcpFlush (fd, &buffer, (XdmcpNetaddr) from, fromlen); 897 } 898 899 static unsigned long globalSessionID; 900 901 # define NextSessionID() (++globalSessionID) 902 903 void init_session_id(void) 904 { 905 /* Set randomly so we are unlikely to reuse id's from a previous 906 * incarnation so we don't say "Alive" to those displays. 907 * Start with low digits 0 to make debugging easier. 908 */ 909 globalSessionID = (time((Time_t *)0)&0x7fff) * 16000; 910 } 911 912 static ARRAY8 outOfMemory = { (CARD16) 13, (CARD8Ptr) "Out of memory" }; 913 static ARRAY8 noValidAddr = { (CARD16) 16, (CARD8Ptr) "No valid address" }; 914 static ARRAY8 noValidAuth = { (CARD16) 22, (CARD8Ptr) "No valid authorization" }; 915 static ARRAY8 noAuthentic = { (CARD16) 29, (CARD8Ptr) "XDM has no authentication key" }; 916 917 static void 918 request_respond ( 919 struct sockaddr *from, 920 int fromlen, 921 int length, 922 int fd) 923 { 924 CARD16 displayNumber; 925 ARRAY16 connectionTypes = {0, NULL}; 926 ARRAYofARRAY8 connectionAddresses = {0, NULL}; 927 ARRAY8 authenticationName = {0, NULL}; 928 ARRAY8 authenticationData = {0, NULL}; 929 ARRAYofARRAY8 authorizationNames = {0, NULL}; 930 ARRAY8 manufacturerDisplayID = {0, NULL}; 931 ARRAY8Ptr reason = NULL; 932 int expectlen; 933 int i, j; 934 struct protoDisplay *pdpy = NULL; 935 ARRAY8 authorizationName = {0, NULL}, 936 authorizationData = {0, NULL}; 937 ARRAY8Ptr connectionAddress; 938 939 Debug ("Request respond %d\n", length); 940 if (XdmcpReadCARD16 (&buffer, &displayNumber) && 941 XdmcpReadARRAY16 (&buffer, &connectionTypes) && 942 XdmcpReadARRAYofARRAY8 (&buffer, &connectionAddresses) && 943 XdmcpReadARRAY8 (&buffer, &authenticationName) && 944 XdmcpReadARRAY8 (&buffer, &authenticationData) && 945 XdmcpReadARRAYofARRAY8 (&buffer, &authorizationNames) && 946 XdmcpReadARRAY8 (&buffer, &manufacturerDisplayID)) 947 { 948 expectlen = 0; 949 expectlen += 2; /* displayNumber */ 950 expectlen += 1 + 2*connectionTypes.length; /* connectionTypes */ 951 expectlen += 1; /* connectionAddresses */ 952 for (i = 0; i < (int)connectionAddresses.length; i++) 953 expectlen += 2 + connectionAddresses.data[i].length; 954 expectlen += 2 + authenticationName.length; /* authenticationName */ 955 expectlen += 2 + authenticationData.length; /* authenticationData */ 956 expectlen += 1; /* authoriationNames */ 957 for (i = 0; i < (int)authorizationNames.length; i++) 958 expectlen += 2 + authorizationNames.data[i].length; 959 expectlen += 2 + manufacturerDisplayID.length; /* displayID */ 960 if (expectlen != length) 961 { 962 Debug ("Request length error got %d expect %d\n", length, expectlen); 963 goto abort; 964 } 965 if (connectionTypes.length == 0 || 966 connectionAddresses.length != connectionTypes.length) 967 { 968 reason = &noValidAddr; 969 goto decline; 970 } 971 pdpy = FindProtoDisplay ((XdmcpNetaddr) from, fromlen, displayNumber); 972 if (!pdpy) { 973 974 /* Check this Display against the Manager's policy */ 975 reason = Accept (from, fromlen, displayNumber); 976 if (reason) 977 goto decline; 978 979 /* Check the Display's stream services against Manager's policy */ 980 i = SelectConnectionTypeIndex (&connectionTypes, 981 &connectionAddresses); 982 if (i < 0) { 983 reason = &noValidAddr; 984 goto decline; 985 } 986 987 /* The Manager considers this a new session */ 988 connectionAddress = &connectionAddresses.data[i]; 989 pdpy = NewProtoDisplay ((XdmcpNetaddr) from, fromlen, displayNumber, 990 connectionTypes.data[i], connectionAddress, 991 NextSessionID()); 992 Debug ("NewProtoDisplay %p\n", pdpy); 993 if (!pdpy) { 994 reason = &outOfMemory; 995 goto decline; 996 } 997 } 998 if (authorizationNames.length == 0) 999 j = 0; 1000 else 1001 j = SelectAuthorizationTypeIndex (&authenticationName, 1002 &authorizationNames); 1003 if (j < 0) 1004 { 1005 reason = &noValidAuth; 1006 goto decline; 1007 } 1008 if (!CheckAuthentication (pdpy, 1009 &manufacturerDisplayID, 1010 &authenticationName, 1011 &authenticationData)) 1012 { 1013 reason = &noAuthentic; 1014 goto decline; 1015 } 1016 if (j < (int)authorizationNames.length) 1017 { 1018 Xauth *auth; 1019 SetProtoDisplayAuthorization (pdpy, 1020 (unsigned short) authorizationNames.data[j].length, 1021 (char *) authorizationNames.data[j].data); 1022 auth = pdpy->xdmcpAuthorization; 1023 if (!auth) 1024 auth = pdpy->fileAuthorization; 1025 if (auth) 1026 { 1027 authorizationName.length = auth->name_length; 1028 authorizationName.data = (CARD8Ptr) auth->name; 1029 authorizationData.length = auth->data_length; 1030 authorizationData.data = (CARD8Ptr) auth->data; 1031 } 1032 } 1033 if (pdpy) 1034 { 1035 send_accept (from, fromlen, pdpy->sessionID, 1036 &authenticationName, 1037 &authenticationData, 1038 &authorizationName, 1039 &authorizationData, fd); 1040 } 1041 else 1042 { 1043 decline: ; 1044 send_decline (from, fromlen, &authenticationName, 1045 &authenticationData, 1046 reason, fd); 1047 if (pdpy) 1048 DisposeProtoDisplay (pdpy); 1049 } 1050 } 1051 abort: 1052 XdmcpDisposeARRAY16 (&connectionTypes); 1053 XdmcpDisposeARRAYofARRAY8 (&connectionAddresses); 1054 XdmcpDisposeARRAY8 (&authenticationName); 1055 XdmcpDisposeARRAY8 (&authenticationData); 1056 XdmcpDisposeARRAYofARRAY8 (&authorizationNames); 1057 XdmcpDisposeARRAY8 (&manufacturerDisplayID); 1058 } 1059 1060 static void 1061 send_accept ( 1062 struct sockaddr *to, 1063 int tolen, 1064 CARD32 sessionID, 1065 ARRAY8Ptr authenticationName, 1066 ARRAY8Ptr authenticationData, 1067 ARRAY8Ptr authorizationName, 1068 ARRAY8Ptr authorizationData, 1069 int fd) 1070 { 1071 XdmcpHeader header; 1072 1073 Debug ("Accept Session ID %ld\n", (long) sessionID); 1074 header.version = XDM_PROTOCOL_VERSION; 1075 header.opcode = (CARD16) ACCEPT; 1076 header.length = 4; /* session ID */ 1077 header.length += 2 + authenticationName->length; 1078 header.length += 2 + authenticationData->length; 1079 header.length += 2 + authorizationName->length; 1080 header.length += 2 + authorizationData->length; 1081 XdmcpWriteHeader (&buffer, &header); 1082 XdmcpWriteCARD32 (&buffer, sessionID); 1083 XdmcpWriteARRAY8 (&buffer, authenticationName); 1084 XdmcpWriteARRAY8 (&buffer, authenticationData); 1085 XdmcpWriteARRAY8 (&buffer, authorizationName); 1086 XdmcpWriteARRAY8 (&buffer, authorizationData); 1087 XdmcpFlush (fd, &buffer, (XdmcpNetaddr) to, tolen); 1088 } 1089 1090 static void 1091 send_decline ( 1092 struct sockaddr *to, 1093 int tolen, 1094 ARRAY8Ptr authenticationName, 1095 ARRAY8Ptr authenticationData, 1096 ARRAY8Ptr status, 1097 int fd) 1098 { 1099 XdmcpHeader header; 1100 1101 Debug ("Decline %*.*s\n", status->length, status->length, pS(status->data)); 1102 header.version = XDM_PROTOCOL_VERSION; 1103 header.opcode = (CARD16) DECLINE; 1104 header.length = 0; 1105 header.length += 2 + status->length; 1106 header.length += 2 + authenticationName->length; 1107 header.length += 2 + authenticationData->length; 1108 XdmcpWriteHeader (&buffer, &header); 1109 XdmcpWriteARRAY8 (&buffer, status); 1110 XdmcpWriteARRAY8 (&buffer, authenticationName); 1111 XdmcpWriteARRAY8 (&buffer, authenticationData); 1112 XdmcpFlush (fd, &buffer, (XdmcpNetaddr) to, tolen); 1113 } 1114 1115 static void 1116 manage ( 1117 struct sockaddr *from, 1118 int fromlen, 1119 int length, 1120 int fd) 1121 { 1122 CARD32 sessionID; 1123 CARD16 displayNumber; 1124 ARRAY8 displayClass = {0, NULL}; 1125 int expectlen; 1126 struct protoDisplay *pdpy; 1127 struct display *d; 1128 char *name = NULL; 1129 char *class = NULL; 1130 XdmcpNetaddr from_save; 1131 ARRAY8 clientAddress = {0, NULL}, 1132 clientPort = {0, NULL}; 1133 CARD16 connectionType; 1134 1135 Debug ("Manage %d\n", length); 1136 if (XdmcpReadCARD32 (&buffer, &sessionID) && 1137 XdmcpReadCARD16 (&buffer, &displayNumber) && 1138 XdmcpReadARRAY8 (&buffer, &displayClass)) 1139 { 1140 expectlen = 4 + /* session ID */ 1141 2 + /* displayNumber */ 1142 2 + displayClass.length; /* displayClass */ 1143 if (expectlen != length) 1144 { 1145 Debug ("Manage length error got %d expect %d\n", length, expectlen); 1146 goto abort; 1147 } 1148 pdpy = FindProtoDisplay ((XdmcpNetaddr) from, fromlen, displayNumber); 1149 Debug ("Manage Session ID %ld, pdpy %p\n", (long) sessionID, pdpy); 1150 if (!pdpy || pdpy->sessionID != sessionID) 1151 { 1152 /* 1153 * We may have already started a session for this display 1154 * but it hasn't seen the response in the form of an 1155 * XOpenDisplay() yet. So check if it is in the list of active 1156 * displays, and if so check that the session id's match. 1157 * If all this is true, then we have a duplicate request that 1158 * can be ignored. 1159 */ 1160 if (!pdpy 1161 && (d = FindDisplayByAddress((XdmcpNetaddr) from, fromlen, displayNumber)) 1162 && d->sessionID == sessionID) { 1163 Debug("manage: got duplicate pkt, ignoring\n"); 1164 goto abort; 1165 } 1166 Debug ("Session ID %ld refused\n", (long) sessionID); 1167 if (pdpy) 1168 Debug ("Existing Session ID %ld\n", (long) pdpy->sessionID); 1169 send_refuse (from, fromlen, sessionID, fd); 1170 } 1171 else 1172 { 1173 name = NetworkAddressToName (pdpy->connectionType, 1174 &pdpy->connectionAddress, 1175 from, 1176 pdpy->displayNumber); 1177 Debug ("Computed display name: %s for: %s\n", 1178 name, (char *)pdpy->connectionAddress.data); 1179 if (!name) 1180 { 1181 send_failed (from, fromlen, "(no name)", sessionID, 1182 "out of memory", fd); 1183 goto abort; 1184 } 1185 d = FindDisplayByName (name); 1186 if (d) 1187 { 1188 Debug ("Terminating active session for %s\n", d->name); 1189 StopDisplay (d); 1190 } 1191 class = malloc (displayClass.length + 1); 1192 if (!class) 1193 { 1194 send_failed (from, fromlen, name, sessionID, 1195 "out of memory", fd); 1196 goto abort; 1197 } 1198 if (displayClass.length) 1199 { 1200 memcpy(class, displayClass.data, displayClass.length); 1201 class[displayClass.length] = '\0'; 1202 } 1203 else 1204 { 1205 free (class); 1206 class = (char *) NULL; 1207 } 1208 from_save = malloc (fromlen); 1209 if (!from_save) 1210 { 1211 send_failed (from, fromlen, name, sessionID, 1212 "out of memory", fd); 1213 goto abort; 1214 } 1215 memcpy(from_save, from, fromlen); 1216 d = NewDisplay (name, class); 1217 if (!d) 1218 { 1219 free (from_save); 1220 send_failed (from, fromlen, name, sessionID, 1221 "out of memory", fd); 1222 goto abort; 1223 } 1224 d->displayType.location = Foreign; 1225 d->displayType.lifetime = Transient; 1226 d->displayType.origin = FromXDMCP; 1227 d->sessionID = pdpy->sessionID; 1228 d->from = from_save; 1229 d->fromlen = fromlen; 1230 d->displayNumber = pdpy->displayNumber; 1231 ClientAddress (from, &clientAddress, &clientPort, &connectionType); 1232 d->useChooser = 0; 1233 d->xdmcpFd = fd; 1234 if (IsIndirectClient (&clientAddress, connectionType)) 1235 { 1236 Debug ("IsIndirectClient\n"); 1237 ForgetIndirectClient (&clientAddress, connectionType); 1238 if (UseChooser (&clientAddress, connectionType)) 1239 { 1240 d->useChooser = 1; 1241 Debug ("Use chooser for %s\n", d->name); 1242 } 1243 } 1244 d->clientAddr = clientAddress; 1245 d->connectionType = connectionType; 1246 XdmcpDisposeARRAY8 (&clientPort); 1247 if (pdpy->fileAuthorization) 1248 { 1249 d->authorizations = malloc (sizeof (Xauth *)); 1250 if (!d->authorizations) 1251 { 1252 free (from_save); 1253 free (d); 1254 send_failed (from, fromlen, name, sessionID, 1255 "out of memory", fd); 1256 goto abort; 1257 } 1258 d->authorizations[0] = pdpy->fileAuthorization; 1259 d->authNum = 1; 1260 pdpy->fileAuthorization = NULL; 1261 } 1262 DisposeProtoDisplay (pdpy); 1263 Debug ("Starting display %s,%s\n", d->name, d->class); 1264 StartDisplay (d); 1265 } 1266 } 1267 abort: 1268 XdmcpDisposeARRAY8 (&displayClass); 1269 free (name); 1270 free (class); 1271 } 1272 1273 void 1274 SendFailed ( 1275 struct display *d, 1276 const char *reason) 1277 { 1278 Debug ("Display start failed, sending Failed\n"); 1279 send_failed ((struct sockaddr *)(d->from), d->fromlen, d->name, 1280 d->sessionID, reason, d->xdmcpFd); 1281 } 1282 1283 static void 1284 send_failed ( 1285 struct sockaddr *from, 1286 int fromlen, 1287 const char *name, 1288 CARD32 sessionID, 1289 const char *reason, 1290 int fd) 1291 { 1292 static char buf[256]; 1293 XdmcpHeader header; 1294 ARRAY8 status; 1295 1296 snprintf (buf, sizeof(buf), "Session %ld failed for display %.100s: %s", 1297 (long) sessionID, name, reason); 1298 Debug ("Send failed %ld %s\n", (long) sessionID, buf); 1299 status.length = strlen (buf); 1300 status.data = (CARD8Ptr) buf; 1301 header.version = XDM_PROTOCOL_VERSION; 1302 header.opcode = (CARD16) FAILED; 1303 header.length = 6 + status.length; 1304 XdmcpWriteHeader (&buffer, &header); 1305 XdmcpWriteCARD32 (&buffer, sessionID); 1306 XdmcpWriteARRAY8 (&buffer, &status); 1307 XdmcpFlush (fd, &buffer, (XdmcpNetaddr) from, fromlen); 1308 } 1309 1310 static void 1311 send_refuse ( 1312 struct sockaddr *from, 1313 int fromlen, 1314 CARD32 sessionID, 1315 int fd) 1316 { 1317 XdmcpHeader header; 1318 1319 Debug ("Send refuse %ld\n", (long) sessionID); 1320 header.version = XDM_PROTOCOL_VERSION; 1321 header.opcode = (CARD16) REFUSE; 1322 header.length = 4; 1323 XdmcpWriteHeader (&buffer, &header); 1324 XdmcpWriteCARD32 (&buffer, sessionID); 1325 XdmcpFlush (fd, &buffer, (XdmcpNetaddr) from, fromlen); 1326 } 1327 1328 static void 1329 send_alive ( 1330 struct sockaddr *from, 1331 int fromlen, 1332 int length, 1333 int fd) 1334 { 1335 CARD32 sessionID; 1336 CARD16 displayNumber; 1337 struct display *d; 1338 XdmcpHeader header; 1339 CARD8 sendRunning; 1340 CARD32 sendSessionID; 1341 1342 Debug ("Send alive\n"); 1343 if (XdmcpReadCARD16 (&buffer, &displayNumber) && 1344 XdmcpReadCARD32 (&buffer, &sessionID)) 1345 { 1346 if (length == 6) 1347 { 1348 d = FindDisplayBySessionID (sessionID); 1349 if (!d) { 1350 d = FindDisplayByAddress ((XdmcpNetaddr) from, fromlen, displayNumber); 1351 } 1352 sendRunning = 0; 1353 sendSessionID = 0; 1354 if (d && d->status == running) 1355 { 1356 if (d->sessionID == sessionID) 1357 sendRunning = 1; 1358 sendSessionID = d->sessionID; 1359 } 1360 header.version = XDM_PROTOCOL_VERSION; 1361 header.opcode = (CARD16) ALIVE; 1362 header.length = 5; 1363 Debug ("alive: %d %ld\n", sendRunning, (long) sendSessionID); 1364 XdmcpWriteHeader (&buffer, &header); 1365 XdmcpWriteCARD8 (&buffer, sendRunning); 1366 XdmcpWriteCARD32 (&buffer, sendSessionID); 1367 XdmcpFlush (fd, &buffer, (XdmcpNetaddr) from, fromlen); 1368 } 1369 } 1370 } 1371 1372 char * 1373 NetworkAddressToHostname ( 1374 CARD16 connectionType, 1375 ARRAY8Ptr connectionAddress) 1376 { 1377 char *name = NULL; 1378 1379 switch (connectionType) 1380 { 1381 case FamilyInternet: 1382 # ifdef IPv6 1383 case FamilyInternet6: 1384 # endif 1385 { 1386 struct hostent *hostent = NULL; 1387 # ifdef IPv6 1388 char dotted[INET6_ADDRSTRLEN]; 1389 # else 1390 char dotted[20]; 1391 # endif 1392 const char *local_name = ""; 1393 int af_type; 1394 1395 # ifdef IPv6 1396 if (connectionType == FamilyInternet6) 1397 af_type = AF_INET6; 1398 else 1399 # endif 1400 af_type = AF_INET; 1401 1402 hostent = gethostbyaddr ((char *)connectionAddress->data, 1403 connectionAddress->length, af_type); 1404 1405 if (hostent) { 1406 /* check for DNS spoofing */ 1407 # if defined(HAVE_GETADDRINFO) && defined(HAVE_INET_NTOP) 1408 struct addrinfo *ai = NULL, *nai; 1409 if (getaddrinfo(hostent->h_name, NULL, NULL, &ai) == 0) { 1410 for (nai = ai; nai != NULL; nai = nai->ai_next) { 1411 if ((af_type == nai->ai_family) && ( 1412 ((nai->ai_family == AF_INET) && 1413 (connectionAddress->length == sizeof(struct in_addr)) && 1414 (memcmp(connectionAddress->data, 1415 &((struct sockaddr_in *)nai->ai_addr)->sin_addr, 1416 connectionAddress->length) == 0)) 1417 # ifdef IPv6 1418 || ((nai->ai_family == AF_INET6) && 1419 (connectionAddress->length == 1420 sizeof(struct in6_addr)) && 1421 (memcmp(connectionAddress->data, 1422 &((struct sockaddr_in6 *)nai->ai_addr)->sin6_addr, 1423 connectionAddress->length) == 0)) 1424 # endif 1425 )) 1426 break; 1427 } 1428 if (nai == NULL) { 1429 inet_ntop(af_type, connectionAddress->data, 1430 dotted, sizeof(dotted)); 1431 1432 LogError("Possible DNS spoof attempt %s->%s.\n", dotted, 1433 hostent->h_name); 1434 hostent = NULL; 1435 } else { 1436 local_name = hostent->h_name; 1437 } 1438 freeaddrinfo(ai); 1439 } else { 1440 hostent = NULL; 1441 } 1442 # else /* !HAVE_GETADDRINFO */ 1443 char *s = strdup(hostent->h_name); /* fscking non-reentrancy of getXXX() */ 1444 if ((hostent = gethostbyname(s))) { 1445 if (memcmp((char*)connectionAddress->data, hostent->h_addr, 1446 hostent->h_length) != 0) { 1447 LogError("Possible DNS spoof attempt.\n"); 1448 hostent = NULL; /* so it enters next if() */ 1449 } else { 1450 local_name = hostent->h_name; 1451 } 1452 } 1453 free(s); 1454 # endif 1455 } 1456 1457 if (!hostent) { 1458 /* can't get name, so use emergency fallback */ 1459 # ifdef HAVE_INET_NTOP 1460 inet_ntop(af_type, connectionAddress->data, 1461 dotted, sizeof(dotted)); 1462 # else 1463 snprintf(dotted, sizeof(dotted), "%d.%d.%d.%d", 1464 connectionAddress->data[0], 1465 connectionAddress->data[1], 1466 connectionAddress->data[2], 1467 connectionAddress->data[3]); 1468 # endif 1469 local_name = dotted; 1470 LogError ("Cannot convert Internet address %s to host name\n", 1471 dotted); 1472 } 1473 name = strdup (local_name); 1474 break; 1475 } 1476 default: 1477 break; 1478 } 1479 return name; 1480 } 1481 1482 #endif /* XDMCP */ 1483