*/
#include "includes.h"
-RCSID("$OpenBSD: canohost.c,v 1.29 2001/12/19 07:18:56 deraadt Exp $");
+RCSID("$OpenBSD: canohost.c,v 1.37 2003/06/02 09:17:34 markus Exp $");
#include "packet.h"
#include "xmalloc.h"
*/
static char *
-get_remote_hostname(int socket, int reverse_mapping_check)
+get_remote_hostname(int socket, int use_dns)
{
struct sockaddr_storage from;
int i;
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
- if (getpeername(socket, (struct sockaddr *) &from, &fromlen) < 0) {
+ if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
memset(&from, 0, sizeof(from));
from4->sin_family = AF_INET;
+ fromlen = sizeof(*from4);
memcpy(&from4->sin_addr, &addr, sizeof(addr));
from4->sin_port = port;
}
}
#endif
- if (from.ss_family == AF_INET)
- check_ip_options(socket, ntop);
+ if (from.ss_family == AF_INET6)
+ fromlen = sizeof(struct sockaddr_in6);
if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
NULL, 0, NI_NUMERICHOST) != 0)
fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
+ if (!use_dns)
+ return xstrdup(ntop);
+
+ if (from.ss_family == AF_INET)
+ check_ip_options(socket, ntop);
+
debug3("Trying to reverse map address %.100s.", ntop);
/* Map the IP address to a host name. */
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
NULL, 0, NI_NAMEREQD) != 0) {
/* Host name not found. Use ip address. */
- log("Could not reverse map address %.100s.", ntop);
return xstrdup(ntop);
}
- /* Got host name. */
- name[sizeof(name) - 1] = '\0';
+ /*
+ * if reverse lookup result looks like a numeric hostname,
+ * someone is trying to trick us by PTR record like following:
+ * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5
+ */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ hints.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(name, "0", &hints, &ai) == 0) {
+ logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
+ name, ntop);
+ freeaddrinfo(ai);
+ return xstrdup(ntop);
+ }
+
/*
* Convert it to all lowercase (which is expected by the rest
* of this software).
for (i = 0; name[i]; i++)
if (isupper(name[i]))
name[i] = tolower(name[i]);
-
- if (!reverse_mapping_check)
- return xstrdup(name);
/*
* Map it back to an IP address and check that the given
* address actually is an address of this host. This is
hints.ai_family = from.ss_family;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
- log("reverse mapping checking getaddrinfo for %.700s "
+ logit("reverse mapping checking getaddrinfo for %.700s "
"failed - POSSIBLE BREAKIN ATTEMPT!", name);
return xstrdup(ntop);
}
/* If we reached the end of the list, the address was not there. */
if (!ai) {
/* Address not found for the host name. */
- log("Address %.100s maps to %.600s, but this does not "
+ logit("Address %.100s maps to %.600s, but this does not "
"map back to the address - POSSIBLE BREAKIN ATTEMPT!",
ntop, name);
return xstrdup(ntop);
static void
check_ip_options(int socket, char *ipaddr)
{
+#ifdef IP_OPTIONS
u_char options[200];
char text[sizeof(options) * 3 + 1];
socklen_t option_size;
else
ipproto = IPPROTO_IP;
option_size = sizeof(options);
- if (getsockopt(socket, ipproto, IP_OPTIONS, (void *)options,
+ if (getsockopt(socket, ipproto, IP_OPTIONS, options,
&option_size) >= 0 && option_size != 0) {
text[0] = '\0';
for (i = 0; i < option_size; i++)
snprintf(text + i*3, sizeof(text) - i*3,
" %2.2x", options[i]);
- log("Connection from %.100s with IP options:%.800s",
+ logit("Connection from %.100s with IP options:%.800s",
ipaddr, text);
packet_disconnect("Connection from %.100s with IP options:%.800s",
ipaddr, text);
}
+#endif /* IP_OPTIONS */
}
/*
*/
const char *
-get_canonical_hostname(int reverse_mapping_check)
+get_canonical_hostname(int use_dns)
{
static char *canonical_host_name = NULL;
- static int reverse_mapping_checked = 0;
+ static int use_dns_done = 0;
/* Check if we have previously retrieved name with same option. */
if (canonical_host_name != NULL) {
- if (reverse_mapping_checked != reverse_mapping_check)
+ if (use_dns_done != use_dns)
xfree(canonical_host_name);
else
return canonical_host_name;
/* Get the real hostname if socket; otherwise return UNKNOWN. */
if (packet_connection_is_on_socket())
canonical_host_name = get_remote_hostname(
- packet_get_connection_in(), reverse_mapping_check);
+ packet_get_connection_in(), use_dns);
else
canonical_host_name = xstrdup("UNKNOWN");
- reverse_mapping_checked = reverse_mapping_check;
+ use_dns_done = use_dns;
return canonical_host_name;
}
/*
- * Returns the remote IP-address of socket as a string. The returned
- * string must be freed.
+ * Returns the local/remote IP-address/hostname of socket as a string.
+ * The returned string must be freed.
*/
static char *
get_socket_address(int socket, int remote, int flags)
if (remote) {
if (getpeername(socket, (struct sockaddr *)&addr, &addrlen)
- < 0) {
- debug("get_socket_ipaddr: getpeername failed: %.100s",
- strerror(errno));
+ < 0)
return NULL;
- }
} else {
if (getsockname(socket, (struct sockaddr *)&addr, &addrlen)
- < 0) {
- debug("get_socket_ipaddr: getsockname failed: %.100s",
- strerror(errno));
+ < 0)
return NULL;
- }
}
+
+ /* Work around Linux IPv6 weirdness */
+ if (addr.ss_family == AF_INET6)
+ addrlen = sizeof(struct sockaddr_in6);
+
/* Get the address in ascii. */
if (getnameinfo((struct sockaddr *)&addr, addrlen, ntop, sizeof(ntop),
NULL, 0, flags) != 0) {
- error("get_socket_ipaddr: getnameinfo %d failed", flags);
+ error("get_socket_address: getnameinfo %d failed", flags);
return NULL;
}
return xstrdup(ntop);
char *
get_peer_ipaddr(int socket)
{
- return get_socket_address(socket, 1, NI_NUMERICHOST);
+ char *p;
+
+ if ((p = get_socket_address(socket, 1, NI_NUMERICHOST)) != NULL)
+ return p;
+ return xstrdup("UNKNOWN");
}
char *
get_local_ipaddr(int socket)
{
- return get_socket_address(socket, 0, NI_NUMERICHOST);
+ char *p;
+
+ if ((p = get_socket_address(socket, 0, NI_NUMERICHOST)) != NULL)
+ return p;
+ return xstrdup("UNKNOWN");
}
char *
}
const char *
-get_remote_name_or_ip(u_int utmp_len, int reverse_mapping_check)
+get_remote_name_or_ip(u_int utmp_len, int use_dns)
{
static const char *remote = "";
if (utmp_len > 0)
- remote = get_canonical_hostname(reverse_mapping_check);
+ remote = get_canonical_hostname(use_dns);
if (utmp_len == 0 || strlen(remote) > utmp_len)
remote = get_remote_ipaddr();
return remote;
return 0;
}
} else {
- if (getpeername(sock, (struct sockaddr *) & from, &fromlen) < 0) {
+ if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
}
+
+ /* Work around Linux IPv6 weirdness */
+ if (from.ss_family == AF_INET6)
+ fromlen = sizeof(struct sockaddr_in6);
+
/* Return port number. */
if (getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
strport, sizeof(strport), NI_NUMERICSERV) != 0)