diff --git a/appl/kx/common.c b/appl/kx/common.c index 631c74987..8c603a034 100644 --- a/appl/kx/common.c +++ b/appl/kx/common.c @@ -754,17 +754,29 @@ replace_cookie(int xserver, int fd, char *filename, int cookiesp) /* XXX */ */ int -suspicious_address (int sock, struct sockaddr_in addr) +suspicious_address (int sock, struct sockaddr_storage *addr) { char data[40]; socklen_t len = sizeof(data); - return addr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) + switch (addr->ss_family) { + case AF_INET: + return ((struct sockaddr_in *)addr)->sin_addr.s_addr != + htonl(INADDR_LOOPBACK) #if defined(IP_OPTIONS) && defined(HAVE_GETSOCKOPT) - || getsockopt (sock, IPPROTO_IP, IP_OPTIONS, data, &len) < 0 - || len != 0 + || getsockopt (sock, IPPROTO_IP, IP_OPTIONS, data, &len) < 0 + || len != 0 #endif - ; + ; + break; +#ifdef HAVE_IPV6 + case AF_INET6: + /* XXX check route headers */ + return !IN6_IS_ADDR_LOOPBACK(&((struct sockaddr_in6*)addr)->sin6_addr); +#endif + default: + return 1; + } } /* diff --git a/appl/kx/krb4.c b/appl/kx/krb4.c index 9423fae41..fee8b2c0e 100644 --- a/appl/kx/krb4.c +++ b/appl/kx/krb4.c @@ -71,6 +71,12 @@ krb4_authenticate (kx_context *kc, int s) krb4_kx_context *c = (krb4_kx_context *)kc->data; const char *host = kc->host; + if (kc->thisaddr.ss_family != AF_INET) { + warnx ("%s: used Kerberos v4 authentiocation on on non-IP4 address", + host); + return -1; + } + #ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM if (krb_get_config_bool("nat_in_use")) { struct in_addr natAddr; @@ -78,14 +84,15 @@ krb4_authenticate (kx_context *kc, int s) if (krb_get_our_ip_for_realm(krb_realmofhost(kc->host), &natAddr) == KSUCCESS || krb_get_our_ip_for_realm (NULL, &natAddr) == KSUCCESS) - kc->thisaddr.sin_addr = natAddr; + ((struct sockaddr_in *)&kc->thisaddr)->sin_addr = natAddr; } #endif status = krb_sendauth (KOPT_DO_MUTUAL, s, &text, "rcmd", (char *)host, krb_realmofhost (host), getpid(), &msg, &cred, c->schedule, - &kc->thisaddr, &kc->thataddr, KX_VERSION); + (struct sockaddr_in *)&kc->thisaddr, + (struct sockaddr_in *)&kc->thataddr, KX_VERSION); if (status != KSUCCESS) { warnx ("%s: %s\n", host, krb_get_err_text(status)); return -1; @@ -93,7 +100,7 @@ krb4_authenticate (kx_context *kc, int s) memcpy (c->key, cred.session, sizeof(des_cblock)); return 0; } - + /* * Read a krb4 priv packet from `fd' into `buf' (of size `len'). * Return the number of bytes read or 0 on EOF or -1 on error. @@ -121,7 +128,8 @@ krb4_read (kx_context *kc, if (krb_net_read (fd, buf, l) != l) return -1; status = krb_rd_priv (buf, l, c->schedule, &c->key, - &kc->thataddr, &kc->thisaddr, &msg); + (struct sockaddr_in *)&kc->thataddr, + (struct sockaddr_in *)&kc->thisaddr, &msg); if (status != RD_AP_OK) { warnx ("krb4_read: %s", krb_get_err_text(status)); return -1; @@ -148,7 +156,8 @@ krb4_write(kx_context *kc, if (outbuf == NULL) return -1; outlen = krb_mk_priv ((void *)buf, outbuf, len, c->schedule, &c->key, - &kc->thisaddr, &kc->thataddr); + (struct sockaddr_in *)&kc->thisaddr, + (struct sockaddr_in *)&kc->thataddr); if (outlen < 0) { free (outbuf); return -1; @@ -303,6 +312,9 @@ recv_v4_auth (kx_context *kc, int sock, u_char *buf) AUTH_DAT auth; des_key_schedule schedule; + if (kc->thisaddr.ss_family != AF_INET) + return -1; + if (memcmp (buf, KRB_SENDAUTH_VERS, 4) != 0) return -1; if (net_read (sock, buf + 4, KRB_SENDAUTH_VLEN - 4) != @@ -321,8 +333,8 @@ recv_v4_auth (kx_context *kc, int sock, u_char *buf) &ticket, "rcmd", instance, - &kc->thataddr, - &kc->thisaddr, + (struct sockaddr_in *)&kc->thataddr, + (struct sockaddr_in *)&kc->thisaddr, &auth, "", schedule, diff --git a/appl/kx/kx.c b/appl/kx/kx.c index c11652809..7a57741ab 100644 --- a/appl/kx/kx.c +++ b/appl/kx/kx.c @@ -137,7 +137,9 @@ connect_host (kx_context *kc) addrlen != a->ai_addrlen) err(1, "getsockname(%s)", kc->host); memcpy (&kc->thisaddr, thisaddr, sizeof(kc->thisaddr)); + kc->thisaddr_len = addrlen; memcpy (&kc->thataddr, a->ai_addr, sizeof(kc->thataddr)); + kc->thataddr_len = a->ai_addrlen; freeaddrinfo (ai); if ((*kc->authenticate)(kc, s)) return -1; @@ -284,15 +286,16 @@ doit_passive (kx_context *kc) warn("fork"); continue; } else if (child == 0) { - struct sockaddr_in addr; + struct sockaddr *addr; int fd; int xserver; - addr = kc->thataddr; + addr = (struct sockaddr *)&kc->thataddr; close (otherside); - addr.sin_port = htons(tmp); - fd = socket (AF_INET, SOCK_STREAM, 0); + socket_set_port(addr, htons(tmp)); + + fd = socket (addr->sa_family, SOCK_STREAM, 0); if (fd < 0) err(1, "socket"); #if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT) @@ -312,7 +315,7 @@ doit_passive (kx_context *kc) } #endif - if (connect (fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) + if (connect (fd, addr, kc->thataddr_len) < 0) err(1, "connect(%s)", host); { int d = 0; @@ -496,16 +499,17 @@ doit_active (kx_context *kc) continue; } else if (child == 0) { int s; - struct sockaddr_in addr; + struct sockaddr *addr; for (i = 0; i < nsockets; ++i) close (sockets[i].fd); - addr = kc->thataddr; + addr = (struct sockaddr *)&kc->thataddr; close (otherside); - addr.sin_port = htons(other_port); - s = socket (AF_INET, SOCK_STREAM, 0); + socket_set_port(addr, htons(tmp)); + + s = socket (addr->sa_family, SOCK_STREAM, 0); if (s < 0) err(1, "socket"); #if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT) @@ -525,7 +529,7 @@ doit_active (kx_context *kc) } #endif - if (connect (s, (struct sockaddr *)&addr, sizeof(addr)) < 0) + if (connect (s, addr, kc->thataddr_len) < 0) err(1, "connect"); return active_session (fd, s, kc); diff --git a/appl/kx/kx.h b/appl/kx/kx.h index d87617053..5451ba71c 100644 --- a/appl/kx/kx.h +++ b/appl/kx/kx.h @@ -166,7 +166,7 @@ int create_and_write_cookie (char *xauthfile, int verify_and_remove_cookies (int fd, int sock, int cookiesp); int replace_cookie(int xserver, int fd, char *filename, int cookiesp); -int suspicious_address (int sock, struct sockaddr_in addr); +int suspicious_address (int sock, struct sockaddr_storage *addr); #define KX_PORT 2111 @@ -197,7 +197,8 @@ struct kx_context { int debug_flag; int keepalive_flag; int tcp_flag; - struct sockaddr_in thisaddr, thataddr; + struct sockaddr_storage thisaddr, thataddr; + socklen_t thisaddr_len, thataddr_len; void *data; }; diff --git a/appl/kx/kxd.c b/appl/kx/kxd.c index 1d9c332d6..1e652d44e 100644 --- a/appl/kx/kxd.c +++ b/appl/kx/kxd.c @@ -114,7 +114,6 @@ recv_conn (int sock, kx_context *kc, char user[256]; socklen_t addrlen; struct passwd *passwd; - struct sockaddr_in thisaddr, thataddr; char remotehost[MaxHostNameLen]; char remoteaddr[INET6_ADDRSTRLEN]; int ret = 1; @@ -122,23 +121,21 @@ recv_conn (int sock, kx_context *kc, int len; u_int32_t tmp32; - addrlen = sizeof(thisaddr); - if (getsockname (sock, (struct sockaddr *)&thisaddr, &addrlen) < 0 || - addrlen != sizeof(thisaddr)) { + addrlen = sizeof(kc->thisaddr); + if (getsockname (sock, (struct sockaddr *)&kc->thisaddr, &addrlen) < 0) { syslog (LOG_ERR, "getsockname: %m"); exit (1); } - addrlen = sizeof(thataddr); - if (getpeername (sock, (struct sockaddr *)&thataddr, &addrlen) < 0 || - addrlen != sizeof(thataddr)) { + kc->thisaddr_len = addrlen; + addrlen = sizeof(kc->thataddr); + if (getpeername (sock, (struct sockaddr *)&kc->thataddr, &addrlen) < 0) { syslog (LOG_ERR, "getpeername: %m"); exit (1); } + kc->thataddr_len = addrlen; - kc->thisaddr = thisaddr; - kc->thataddr = thataddr; - - getnameinfo_verified ((struct sockaddr *)&thataddr, addrlen, + getnameinfo_verified ((struct sockaddr *)&kc->thataddr, + kc->thataddr_len, remotehost, sizeof(remotehost), NULL, 0, 0); @@ -226,8 +223,12 @@ recv_conn (int sock, kx_context *kc, syslog(LOG_ERR, "setting uid/groups: %m"); fatal (kc, sock, "cannot set uid"); } - inet_ntop (thataddr.sin_family, - &thataddr.sin_addr, remoteaddr, sizeof(remoteaddr)); + + ret = getnameinfo((struct sockaddr *)&kc->thataddr, kc->thataddr_len, + remoteaddr, sizeof(remoteaddr), + NULL, 0, NI_NUMERICHOST); + if (ret != 0) + fatal (kc, sock, "getnameinfo failed"); syslog (LOG_INFO, "from %s(%s): %s -> %s", remotehost, remoteaddr, @@ -292,13 +293,13 @@ static int doit_conn (kx_context *kc, int fd, int meta_sock, int flags, int cookiesp) { - int sock, sock2; - struct sockaddr_in addr; - struct sockaddr_in thisaddr; + int sock, sock2, port; + struct sockaddr_storage addr; + struct sockaddr_storage thisaddr; socklen_t addrlen; u_char msg[1024], *p; - sock = socket (AF_INET, SOCK_STREAM, 0); + sock = socket (kc->thisaddr.ss_family, SOCK_STREAM, 0); if (sock < 0) { syslog (LOG_ERR, "socket: %m"); return 1; @@ -318,8 +319,12 @@ doit_conn (kx_context *kc, } #endif memset (&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - if (bind (sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + addr.ss_family = kc->thisaddr.ss_family; + if (kc->thisaddr_len > sizeof(addr)) { + syslog(LOG_ERR, "error in af"); + return 1; + } + if (bind (sock, (struct sockaddr *)&addr, kc->thisaddr_len) < 0) { syslog (LOG_ERR, "bind: %m"); return 1; } @@ -332,9 +337,11 @@ doit_conn (kx_context *kc, syslog (LOG_ERR, "listen: %m"); return 1; } + port = socket_get_port((struct sockaddr *)&addr); + p = msg; *p++ = NEW_CONN; - p += KRB_PUT_INT (ntohs(addr.sin_port), p, 4, 4); + p += KRB_PUT_INT (ntohs(port), p, 4, 4); if (kx_write (kc, meta_sock, msg, p - msg) < 0) { syslog (LOG_ERR, "write: %m"); @@ -520,7 +527,7 @@ doit_passive (kx_context *kc, for (i = 0; i < nsockets; ++i) { if (FD_ISSET(sockets[i].fd, &fds)) { if (sockets[i].flags == TCP) { - struct sockaddr_in peer; + struct sockaddr_storage peer; socklen_t len = sizeof(peer); fd = accept (sockets[i].fd, @@ -530,7 +537,7 @@ doit_passive (kx_context *kc, syslog (LOG_ERR, "accept: %m"); /* XXX */ - if (fd >= 0 && suspicious_address (fd, peer)) { + if (fd >= 0 && suspicious_address (fd, &peer)) { close (fd); fd = -1; errno = EINTR;