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;
}
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)
{
char *addr = 0;
int addrlen = 0;
unsigned short family;
unsigned short family, port = 0;
char hostnamebuf[256]; /* big enough for max hostname */
char dispbuf[40]; /* big enough to hold more than 2^64 base 10 */
char *display;
@ -89,34 +97,47 @@ static Xauth *get_authptr(struct sockaddr *sockname, unsigned int socknamelen)
int i;
family = FamilyLocal; /* 256 */
switch (sockname->sa_family) {
case AF_INET:
/*block*/ {
struct sockaddr_in *si = (struct sockaddr_in *) sockname;
assert(sizeof(*si) == socknamelen);
addr = (char *) &si->sin_addr;
addrlen = 4;
if (ntohl(si->sin_addr.s_addr) != 0x7f000001)
family = XCB_FAMILY_INTERNET;
snprintf(dispbuf, sizeof(dispbuf), "%d", ntohs(si->sin_port) - X_TCP_PORT);
display = dispbuf;
switch(sockname->sa_family)
{
case AF_INET6:
addr = (char *) &((struct sockaddr_in6 *)sockname)->sin6_addr;
addrlen = sizeof(((struct sockaddr_in6 *)sockname)->sin6_addr);
port = ((struct sockaddr_in6 *)sockname)->sin6_port;
if(!IN6_IS_ADDR_V4MAPPED(addr))
{
if(!IN6_IS_ADDR_LOOPBACK(addr))
family = XCB_FAMILY_INTERNET_6;
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:
/*block*/ {
struct sockaddr_un *su = (struct sockaddr_un *) sockname;
char *sockbuf = (char *) sockname;
assert(sizeof(*su) >= socknamelen);
sockbuf[socknamelen] = 0; /* null-terminate path */
display = strrchr(su->sun_path, 'X');
if (display == 0)
return 0; /* sockname is mangled somehow */
display++;
}
break;
display = _xcb_memrchr(((struct sockaddr_un *) sockname)->sun_path, 'X',
socknamelen);
if(!display)
return 0; /* sockname is mangled somehow */
display++;
break;
default:
return 0; /* cannot authenticate this family */
}
if(port)
{
snprintf(dispbuf, sizeof(dispbuf), "%hu", ntohs(port) - X_TCP_PORT);
display = dispbuf;
}
if (family == FamilyLocal) {
if (gethostname(hostnamebuf, sizeof(hostnamebuf)) == -1)
return 0; /* do not know own hostname */