17a0395d0Smrg/* 296402570Smrg * 37a0395d0SmrgCopyright 1989, 1998 The Open Group 47a0395d0Smrg 57a0395d0SmrgPermission to use, copy, modify, distribute, and sell this software and its 67a0395d0Smrgdocumentation for any purpose is hereby granted without fee, provided that 77a0395d0Smrgthe above copyright notice appear in all copies and that both that 87a0395d0Smrgcopyright notice and this permission notice appear in supporting 97a0395d0Smrgdocumentation. 107a0395d0Smrg 117a0395d0SmrgThe above copyright notice and this permission notice shall be included in 127a0395d0Smrgall copies or substantial portions of the Software. 137a0395d0Smrg 147a0395d0SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 157a0395d0SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 167a0395d0SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 177a0395d0SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 187a0395d0SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 197a0395d0SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 207a0395d0Smrg 217a0395d0SmrgExcept as contained in this notice, the name of The Open Group shall not be 227a0395d0Smrgused in advertising or otherwise to promote the sale, use or other dealings 237a0395d0Smrgin this Software without prior written authorization from The Open Group. 247a0395d0Smrg * * 257a0395d0Smrg * Author: Jim Fulton, MIT X Consortium 267a0395d0Smrg */ 277a0395d0Smrg 287a0395d0Smrg#ifdef HAVE_CONFIG_H 297a0395d0Smrg#include "config.h" 307a0395d0Smrg#endif 317a0395d0Smrg 327a0395d0Smrg#ifdef WIN32 337a0395d0Smrg#include <X11/Xwinsock.h> 347a0395d0Smrg#define EPROTOTYPE WSAEPROTOTYPE 357a0395d0Smrg#endif 367a0395d0Smrg#include <X11/X.h> 377a0395d0Smrg#include <signal.h> 387a0395d0Smrg#include <setjmp.h> 397a0395d0Smrg#include <ctype.h> 407a0395d0Smrg#ifndef __TYPES__ 417a0395d0Smrg#include <sys/types.h> 427a0395d0Smrg#define __TYPES__ 437a0395d0Smrg#endif 447a0395d0Smrg#ifndef WIN32 457a0395d0Smrg#include <sys/socket.h> 467a0395d0Smrg#include <netdb.h> 477a0395d0Smrg#include <netinet/in.h> 487a0395d0Smrg#include <arpa/inet.h> 497a0395d0Smrg#ifdef HAVE_NET_ERRNO_H 507a0395d0Smrg#include <net/errno.h> 517a0395d0Smrg#endif /* HAVE_NET_ERRNO_H */ 527a0395d0Smrg#endif /* !WIN32 */ 537a0395d0Smrg#include <errno.h> 547a0395d0Smrg#include "xauth.h" 557a0395d0Smrg 5640c5344fSmrg#include <sys/stat.h> 5740c5344fSmrg#include <limits.h> 587a0395d0Smrg 597a0395d0Smrg#ifndef WIN32 607a0395d0Smrg#include <arpa/inet.h> 617a0395d0Smrg#endif 627a0395d0Smrg 63f6d57fdeSmrg#if defined(IPv6) && !defined(AF_INET6) 64f6d57fdeSmrg#error "Cannot build IPv6 support without AF_INET6" 65f6d57fdeSmrg#endif 66f6d57fdeSmrg 6796402570Smrgconst char * 687a0395d0Smrgget_hostname (Xauth *auth) 697a0395d0Smrg{ 707a0395d0Smrg if (auth->address_length == 0) 717a0395d0Smrg return "Illegal Address"; 727a0395d0Smrg#ifdef TCPCONN 737a0395d0Smrg if (auth->family == FamilyInternet 74f6d57fdeSmrg#ifdef IPv6 757a0395d0Smrg || auth->family == FamilyInternet6 7696402570Smrg#endif 777a0395d0Smrg ) 787a0395d0Smrg { 79273c00b8Smrg static struct hostent *hp = NULL; 80f6d57fdeSmrg#ifdef IPv6 81f6d57fdeSmrg static char addr[INET6_ADDRSTRLEN+2]; 82f6d57fdeSmrg#elif defined(HAVE_INET_NTOP) 83f6d57fdeSmrg static char addr[INET_ADDRSTRLEN]; 84f6d57fdeSmrg#endif 85273c00b8Smrg int af; 86273c00b8Smrg 87f6d57fdeSmrg#ifdef IPv6 887a0395d0Smrg if (auth->family == FamilyInternet6) 897a0395d0Smrg af = AF_INET6; 907a0395d0Smrg else 917a0395d0Smrg#endif 927a0395d0Smrg af = AF_INET; 937a0395d0Smrg if (no_name_lookups == False) { 947a0395d0Smrg hp = gethostbyaddr (auth->address, auth->address_length, af); 957a0395d0Smrg } 967a0395d0Smrg if (hp) 977a0395d0Smrg return (hp->h_name); 98f6d57fdeSmrg#ifdef IPv6 997a0395d0Smrg else if (af == AF_INET6) { 1007a0395d0Smrg /* Add [] for clarity to distinguish between address & display, 1017a0395d0Smrg like RFC 2732 for URL's. Not required, since X display syntax 1027a0395d0Smrg always ends in :<display>, but makes it easier for people to read 1037a0395d0Smrg and less confusing to those who expect the RFC 2732 style. */ 1047a0395d0Smrg addr[0] = '['; 1057a0395d0Smrg if (inet_ntop(af, auth->address, addr + 1, INET6_ADDRSTRLEN) == NULL) 1067a0395d0Smrg return NULL; 1077a0395d0Smrg strcat(addr, "]"); 1087a0395d0Smrg return addr; 1097a0395d0Smrg } 1107a0395d0Smrg#endif 1117a0395d0Smrg else { 112f6d57fdeSmrg#ifdef HAVE_INET_NTOP 113f6d57fdeSmrg return (inet_ntop(af, auth->address, addr, sizeof(addr))); 114f6d57fdeSmrg#else 1157a0395d0Smrg return (inet_ntoa(*((struct in_addr *)(auth->address)))); 116f6d57fdeSmrg#endif 1177a0395d0Smrg } 1187a0395d0Smrg } 1197a0395d0Smrg#endif 1207a0395d0Smrg 1217a0395d0Smrg return (NULL); 1227a0395d0Smrg} 1237a0395d0Smrg 124f6d57fdeSmrg#if defined(TCPCONN) && !defined(HAVE_GETADDRINFO) 1257a0395d0Smrg/* 1267a0395d0Smrg * cribbed from lib/X/XConnDis.c 1277a0395d0Smrg */ 12896402570Smrgstatic Bool 1297a0395d0Smrgget_inet_address(char *name, unsigned int *resultp) 1307a0395d0Smrg{ 1317a0395d0Smrg unsigned int hostinetaddr = inet_addr (name); 1327a0395d0Smrg struct hostent *host_ptr; 1337a0395d0Smrg struct sockaddr_in inaddr; /* dummy variable for size calcs */ 1347a0395d0Smrg 1357a0395d0Smrg#ifndef INADDR_NONE 1367a0395d0Smrg#define INADDR_NONE -1 1377a0395d0Smrg#endif 1387a0395d0Smrg 1397a0395d0Smrg if (hostinetaddr == INADDR_NONE) { 1407a0395d0Smrg if ((host_ptr = gethostbyname (name)) == NULL) { 1417a0395d0Smrg /* No such host! */ 1427a0395d0Smrg errno = EINVAL; 1437a0395d0Smrg return False; 1447a0395d0Smrg } 1457a0395d0Smrg /* Check the address type for an internet host. */ 1467a0395d0Smrg if (host_ptr->h_addrtype != AF_INET) { 1477a0395d0Smrg /* Not an Internet host! */ 1487a0395d0Smrg errno = EPROTOTYPE; 1497a0395d0Smrg return False; 1507a0395d0Smrg } 15196402570Smrg 15296402570Smrg memmove( (char *)&hostinetaddr, (char *)host_ptr->h_addr, 1537a0395d0Smrg sizeof(inaddr.sin_addr)); 1547a0395d0Smrg } 1557a0395d0Smrg *resultp = hostinetaddr; 1567a0395d0Smrg return True; 1577a0395d0Smrg} 1587a0395d0Smrg#endif 1597a0395d0Smrg 1607a0395d0Smrg 1617a0395d0Smrgstruct addrlist *get_address_info ( 1627a0395d0Smrg int family, 16396402570Smrg const char *fulldpyname, 1647a0395d0Smrg int prefix, 1657a0395d0Smrg char *host) 1667a0395d0Smrg{ 1677a0395d0Smrg struct addrlist *retval = NULL; 1687a0395d0Smrg int len = 0; 16996402570Smrg const void *src = NULL; 1707a0395d0Smrg#ifdef TCPCONN 171f6d57fdeSmrg#ifdef HAVE_GETADDRINFO 1727a0395d0Smrg struct addrlist *lastrv = NULL; 1737a0395d0Smrg struct addrinfo *firstai = NULL; 1747a0395d0Smrg struct addrinfo hints; 1757a0395d0Smrg#else 1767a0395d0Smrg unsigned int hostinetaddr; 1777a0395d0Smrg#endif 1787a0395d0Smrg#endif 1797a0395d0Smrg char buf[255]; 1807a0395d0Smrg 1817a0395d0Smrg /* 1827a0395d0Smrg * based on the family, set the pointer src to the start of the address 1837a0395d0Smrg * information to be copied and set len to the number of bytes. 1847a0395d0Smrg */ 1857a0395d0Smrg switch (family) { 1867a0395d0Smrg case FamilyLocal: /* hostname/unix:0 */ 1877a0395d0Smrg /* handle unix:0 and :0 specially */ 1887a0395d0Smrg if (prefix == 0 && (strncmp (fulldpyname, "unix:", 5) == 0 || 1897a0395d0Smrg fulldpyname[0] == ':')) { 1907a0395d0Smrg 1917a0395d0Smrg if (!get_local_hostname (buf, sizeof buf)) { 1927a0395d0Smrg len = 0; 1937a0395d0Smrg } else { 1947a0395d0Smrg src = buf; 1957a0395d0Smrg len = strlen (buf); 1967a0395d0Smrg } 19740c5344fSmrg } else { 19840c5344fSmrg char path[PATH_MAX]; 19940c5344fSmrg struct stat sbuf; 20040c5344fSmrg int is_path_to_socket = 0; 20140c5344fSmrg 20240c5344fSmrg#ifdef HAVE_STRLCPY 20340c5344fSmrg strlcpy(path, fulldpyname, sizeof(path)); 20440c5344fSmrg#else 2050d22642bSmrg strncpy(path, fulldpyname, sizeof(path) - 1); 20640c5344fSmrg path[sizeof(path) - 1] = '\0'; 20740c5344fSmrg#endif 2080d22642bSmrg if (0 == stat(path, &sbuf) && S_ISSOCK(sbuf.st_mode) ) { 20940c5344fSmrg is_path_to_socket = 1; 21040c5344fSmrg } else { 21140c5344fSmrg char *dot = strrchr(path, '.'); 21240c5344fSmrg if (dot) { 21340c5344fSmrg *dot = '\0'; 21440c5344fSmrg /* screen = atoi(dot + 1); */ 2150d22642bSmrg if (0 == stat(path, &sbuf) && S_ISSOCK(sbuf.st_mode)) { 21640c5344fSmrg is_path_to_socket = 1; 21740c5344fSmrg } 21840c5344fSmrg } 21940c5344fSmrg } 22040c5344fSmrg 22140c5344fSmrg if (is_path_to_socket) { 22240c5344fSmrg /* Use the bundle id (part preceding : in the basename) as our src id */ 22340c5344fSmrg char *c; 2240d22642bSmrg c = strrchr(fulldpyname, '/'); 2252adc0320Smrg#ifdef HAVE_STRLCPY 2260d22642bSmrg strlcpy(buf, (NULL != c) ? c + 1 : fulldpyname, sizeof(buf)); 2272adc0320Smrg#else 2280d22642bSmrg strncpy(buf, (NULL != c) ? c + 1 : fulldpyname, sizeof(buf) - 1); 22940c5344fSmrg buf[sizeof(buf) - 1] = '\0'; 2302adc0320Smrg#endif 2312adc0320Smrg 23240c5344fSmrg c = strchr(buf, ':'); 23396402570Smrg 23440c5344fSmrg /* In the legacy case with no bundle id, use the full path */ 23540c5344fSmrg if(c == buf) { 23640c5344fSmrg src = fulldpyname; 23740c5344fSmrg } else { 23840c5344fSmrg *c = '\0'; 23940c5344fSmrg src = buf; 24040c5344fSmrg } 2412adc0320Smrg 24240c5344fSmrg len = strlen(src); 24340c5344fSmrg } else { 24440c5344fSmrg src = fulldpyname; 24540c5344fSmrg len = prefix; 24640c5344fSmrg } 2477a0395d0Smrg } 2487a0395d0Smrg break; 2497a0395d0Smrg case FamilyInternet: /* host:0 */ 2507a0395d0Smrg#ifdef TCPCONN 251f6d57fdeSmrg#ifdef HAVE_GETADDRINFO 252f6d57fdeSmrg#ifdef IPv6 2537a0395d0Smrg case FamilyInternet6: 254f6d57fdeSmrg#endif 2557a0395d0Smrg memset(&hints, 0, sizeof(hints)); 256f6d57fdeSmrg#ifdef IPv6 2577a0395d0Smrg hints.ai_family = PF_UNSPEC; /* IPv4 or IPv6 */ 258f6d57fdeSmrg#else 259f6d57fdeSmrg hints.ai_family = PF_INET; /* IPv4 only */ 260f6d57fdeSmrg#endif 2617a0395d0Smrg hints.ai_socktype = SOCK_STREAM; /* only interested in TCP */ 26296402570Smrg hints.ai_protocol = 0; 2637a0395d0Smrg if (getaddrinfo(host,NULL,&hints,&firstai) !=0) return NULL; 264273c00b8Smrg for (struct addrinfo *ai = firstai; ai != NULL; ai = ai->ai_next) { 2657366012aSmrg struct addrlist *duplicate; 2667366012aSmrg 2678abc0ccfSmrg len = 0; 2687a0395d0Smrg if (ai->ai_family == AF_INET) { 2697a0395d0Smrg struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr; 2707a0395d0Smrg src = &(sin->sin_addr); 2718abc0ccfSmrg if (*(const in_addr_t *) src == htonl(INADDR_LOOPBACK)) { 2728abc0ccfSmrg family = FamilyLocal; 2738abc0ccfSmrg if (get_local_hostname (buf, sizeof buf)) { 2748abc0ccfSmrg src = buf; 2758abc0ccfSmrg len = strlen (buf); 2768abc0ccfSmrg } else 2778abc0ccfSmrg src = NULL; 2788abc0ccfSmrg } else { 2798abc0ccfSmrg len = sizeof(sin->sin_addr); 2808abc0ccfSmrg family = FamilyInternet; 2818abc0ccfSmrg } 282f6d57fdeSmrg#ifdef IPv6 2837a0395d0Smrg } else if (ai->ai_family == AF_INET6) { 2847a0395d0Smrg struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr; 2857a0395d0Smrg src = &(sin6->sin6_addr); 2868abc0ccfSmrg if (!IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src)) { 2878abc0ccfSmrg if (IN6_IS_ADDR_LOOPBACK((const struct in6_addr *)src)) { 2888abc0ccfSmrg family = FamilyLocal; 2898abc0ccfSmrg if (get_local_hostname (buf, sizeof buf)) { 2908abc0ccfSmrg src = buf; 2918abc0ccfSmrg len = strlen (buf); 2928abc0ccfSmrg } else 2938abc0ccfSmrg src = NULL; 2948abc0ccfSmrg } else { 2958abc0ccfSmrg len = sizeof(sin6->sin6_addr); 2968abc0ccfSmrg family = FamilyInternet6; 2978abc0ccfSmrg } 2988abc0ccfSmrg } else { 2998abc0ccfSmrg src = &(sin6->sin6_addr.s6_addr[12]); 3008abc0ccfSmrg len = sizeof(((struct sockaddr_in *) 3018abc0ccfSmrg ai->ai_addr)->sin_addr); 3028abc0ccfSmrg family = FamilyInternet; 3038abc0ccfSmrg } 304f6d57fdeSmrg#endif 3057a0395d0Smrg } 3067a0395d0Smrg 3077a0395d0Smrg for(duplicate = retval; duplicate != NULL; duplicate = duplicate->next) { 3087a0395d0Smrg if(duplicate->family == family && duplicate->len == len && 3097a0395d0Smrg memcmp(duplicate->address, src, len) == 0) { 3107a0395d0Smrg break; 3117a0395d0Smrg } 3127a0395d0Smrg } 3137a0395d0Smrg 3147a0395d0Smrg if (len > 0 && src != NULL && duplicate == NULL) { 3157a0395d0Smrg struct addrlist *newrv = malloc (sizeof(struct addrlist)); 3167a0395d0Smrg if (newrv) { 3177a0395d0Smrg newrv->address = malloc (len); 3187a0395d0Smrg if (newrv->address) { 3197a0395d0Smrg memcpy(newrv->address, src, len); 3207a0395d0Smrg newrv->next = NULL; 3217a0395d0Smrg newrv->family = family; 3227a0395d0Smrg newrv->len = len; 3237a0395d0Smrg if (retval == NULL) { 3247a0395d0Smrg lastrv = retval = newrv; 3257a0395d0Smrg } else { 3267a0395d0Smrg lastrv->next = newrv; 3277a0395d0Smrg lastrv = newrv; 3287a0395d0Smrg } 3297a0395d0Smrg } else { 3307a0395d0Smrg free(newrv); 3317a0395d0Smrg } 3327a0395d0Smrg } 3337a0395d0Smrg } 3347a0395d0Smrg /* reset to avoid copying into list twice */ 3357a0395d0Smrg len = 0; 3367a0395d0Smrg src = NULL; 3377a0395d0Smrg } 3387a0395d0Smrg freeaddrinfo(firstai); 3397a0395d0Smrg break; 340f6d57fdeSmrg#else /* !HAVE_GETADDRINFO */ 3417a0395d0Smrg if (!get_inet_address (host, &hostinetaddr)) return NULL; 3427a0395d0Smrg src = (char *) &hostinetaddr; 3438abc0ccfSmrg if (*(const in_addr_t *) src == htonl(INADDR_LOOPBACK)) { 3448abc0ccfSmrg family = FamilyLocal; 3458abc0ccfSmrg if (get_local_hostname (buf, sizeof buf)) { 3468abc0ccfSmrg src = buf; 3478abc0ccfSmrg len = strlen (buf); 3488abc0ccfSmrg } else { 3498abc0ccfSmrg len = 0; 3508abc0ccfSmrg src = NULL; 3518abc0ccfSmrg } 3528abc0ccfSmrg } else 3538abc0ccfSmrg len = 4; /* sizeof inaddr.sin_addr, would fail on Cray */ 3547a0395d0Smrg break; 355f6d57fdeSmrg#endif /* HAVE_GETADDRINFO */ 356f6d57fdeSmrg#else /* !TCPCONN */ 3577a0395d0Smrg return NULL; 3587a0395d0Smrg#endif 3597a0395d0Smrg case FamilyDECnet: /* host::0 */ 3607a0395d0Smrg /* fall through since we don't have code for it */ 3617a0395d0Smrg default: 3627a0395d0Smrg src = NULL; 3637a0395d0Smrg len = 0; 3647a0395d0Smrg } 3657a0395d0Smrg 3667a0395d0Smrg /* 3677a0395d0Smrg * if source was provided, allocate space and copy it 3687a0395d0Smrg */ 3697a0395d0Smrg if (len > 0 && src != NULL) { 3707a0395d0Smrg retval = malloc (sizeof(struct addrlist)); 3717a0395d0Smrg if (retval) { 3727a0395d0Smrg retval->address = malloc (len); 3737a0395d0Smrg if (retval->address) { 3747a0395d0Smrg memcpy(retval->address, src, len); 3757a0395d0Smrg retval->next = NULL; 3767a0395d0Smrg retval->family = family; 3777a0395d0Smrg retval->len = len; 3787a0395d0Smrg } else { 3797a0395d0Smrg free(retval); 3807a0395d0Smrg retval = NULL; 3817a0395d0Smrg } 3827a0395d0Smrg } 3837a0395d0Smrg } 3847a0395d0Smrg return retval; 3857a0395d0Smrg} 386