Support authentication for IPv6 connections

Support AF_INET6 in get_authptr, and refactor to use common code for IPv4 and
v4-mapped IPv6 addresses.

Commit by Jamey Sharp and Josh Triplett.
This commit is contained in:
Josh Triplett 2006-11-20 22:16:24 -08:00
parent 48776ce233
commit 907f8c8c49

View File

@ -77,11 +77,19 @@ static int authname_match(enum auth_protos kind, char *name, int namelen)
return 1; return 1;
} }
static void *_xcb_memrchr(const void *s, int c, size_t n)
{
for(s = (char *) s + n - 1; n--; s = (char *) s - 1)
if(*(char *)s == (char)c)
return (void *) s;
return 0;
}
static Xauth *get_authptr(struct sockaddr *sockname, unsigned int socknamelen) static Xauth *get_authptr(struct sockaddr *sockname, unsigned int socknamelen)
{ {
char *addr = 0; char *addr = 0;
int addrlen = 0; int addrlen = 0;
unsigned short family; unsigned short family, port = 0;
char hostnamebuf[256]; /* big enough for max hostname */ char hostnamebuf[256]; /* big enough for max hostname */
char dispbuf[40]; /* big enough to hold more than 2^64 base 10 */ char dispbuf[40]; /* big enough to hold more than 2^64 base 10 */
char *display; char *display;
@ -89,34 +97,47 @@ static Xauth *get_authptr(struct sockaddr *sockname, unsigned int socknamelen)
int i; int i;
family = FamilyLocal; /* 256 */ family = FamilyLocal; /* 256 */
switch (sockname->sa_family) { switch(sockname->sa_family)
case AF_INET: {
/*block*/ { case AF_INET6:
struct sockaddr_in *si = (struct sockaddr_in *) sockname; addr = (char *) &((struct sockaddr_in6 *)sockname)->sin6_addr;
assert(sizeof(*si) == socknamelen); addrlen = sizeof(((struct sockaddr_in6 *)sockname)->sin6_addr);
addr = (char *) &si->sin_addr; port = ((struct sockaddr_in6 *)sockname)->sin6_port;
addrlen = 4; if(!IN6_IS_ADDR_V4MAPPED(addr))
if (ntohl(si->sin_addr.s_addr) != 0x7f000001) {
family = XCB_FAMILY_INTERNET; if(!IN6_IS_ADDR_LOOPBACK(addr))
snprintf(dispbuf, sizeof(dispbuf), "%d", ntohs(si->sin_port) - X_TCP_PORT); family = XCB_FAMILY_INTERNET_6;
display = dispbuf; break;
} }
break; addr += 12;
/* if v4-mapped, fall through. */
case AF_INET:
if(!addr)
{
addr = (char *) &((struct sockaddr_in *)sockname)->sin_addr;
port = ((struct sockaddr_in *)sockname)->sin_port;
}
addrlen = sizeof(((struct sockaddr_in *)sockname)->sin_addr);
if(*(in_addr_t *) addr != htonl(INADDR_LOOPBACK))
family = XCB_FAMILY_INTERNET;
break;
case AF_UNIX: case AF_UNIX:
/*block*/ { display = _xcb_memrchr(((struct sockaddr_un *) sockname)->sun_path, 'X',
struct sockaddr_un *su = (struct sockaddr_un *) sockname; socknamelen);
char *sockbuf = (char *) sockname; if(!display)
assert(sizeof(*su) >= socknamelen); return 0; /* sockname is mangled somehow */
sockbuf[socknamelen] = 0; /* null-terminate path */ display++;
display = strrchr(su->sun_path, 'X'); break;
if (display == 0)
return 0; /* sockname is mangled somehow */
display++;
}
break;
default: default:
return 0; /* cannot authenticate this family */ return 0; /* cannot authenticate this family */
} }
if(port)
{
snprintf(dispbuf, sizeof(dispbuf), "%hu", ntohs(port) - X_TCP_PORT);
display = dispbuf;
}
if (family == FamilyLocal) { if (family == FamilyLocal) {
if (gethostname(hostnamebuf, sizeof(hostnamebuf)) == -1) if (gethostname(hostnamebuf, sizeof(hostnamebuf)) == -1)
return 0; /* do not know own hostname */ return 0; /* do not know own hostname */