getnameinfo() can return both numeric and FQDN forms of the address specified in
sa. There is no return value that indicates whether the string returned in
host is a result of binary to numeric-text translation (like
inet_ntop(3)), or is the result of a DNS reverse lookup. Because of this, malicious parties could set up a PTR record as follows:
1.0.0.127.in-addr.arpa. IN PTR 10.1.1.1
and trick the caller of
getnameinfo() into believing that
sa is
10.1.1.1 when it is actually
127.0.0.1.
To prevent such attacks, the use of
NI_NAMEREQD is recommended when the result of
getnameinfo() is used for access control purposes:
struct sockaddr *sa;
socklen_t salen;
char addr[NI_MAXHOST];
struct addrinfo hints, *res;
int error;
error = getnameinfo(sa, salen, addr, sizeof(addr),
NULL, 0, NI_NAMEREQD);
if (error == 0) {
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
hints.ai_flags = AI_NUMERICHOST;
if (getaddrinfo(addr, "0", &hints, &res) == 0) {
/* malicious PTR record */
freeaddrinfo(res);
printf("bogus PTR record\n");
return -1;
}
/* addr is FQDN as a result of PTR lookup */
} else {
/* addr is numeric string */
error = getnameinfo(sa, salen, addr, sizeof(addr),
NULL, 0, NI_NUMERICHOST);
}