*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.193 2010/01/31 17:27:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.194 2010/02/02 19:09:36 mha Exp $
*
*-------------------------------------------------------------------------
*/
uint8 encryptedpassword[RADIUS_VECTOR_LENGTH];
int packetlength;
pgsocket sock;
+#ifdef HAVE_IPV6
+ struct sockaddr_in6 localaddr;
+ struct sockaddr_in6 remoteaddr;
+#else
struct sockaddr_in localaddr;
struct sockaddr_in remoteaddr;
+#endif
+ struct addrinfo hint;
+ struct addrinfo *serveraddrs;
+ char portstr[128];
ACCEPT_TYPE_ARG3 addrsize;
fd_set fdset;
struct timeval timeout;
if (port->hba->radiusport == 0)
port->hba->radiusport = 1812;
- memset(&remoteaddr, 0, sizeof(remoteaddr));
- remoteaddr.sin_family = AF_INET;
- remoteaddr.sin_addr.s_addr = inet_addr(port->hba->radiusserver);
- if (remoteaddr.sin_addr.s_addr == INADDR_NONE)
+ MemSet(&hint, 0, sizeof(hint));
+ hint.ai_socktype = SOCK_DGRAM;
+ hint.ai_family = AF_UNSPEC;
+ snprintf(portstr, sizeof(portstr), "%d", port->hba->radiusport);
+
+ r = pg_getaddrinfo_all(port->hba->radiusserver, portstr, &hint, &serveraddrs);
+ if (r || !serveraddrs)
{
ereport(LOG,
- (errmsg("RADIUS server '%s' is not a valid IP address",
- port->hba->radiusserver)));
+ (errmsg("could not translate RADIUS server name \"%s\" to address: %s",
+ port->hba->radiusserver, gai_strerror(r))));
+ if (serveraddrs)
+ pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
return STATUS_ERROR;
}
- remoteaddr.sin_port = htons(port->hba->radiusport);
+ /* XXX: add support for multiple returned addresses? */
if (port->hba->radiusidentifier && port->hba->radiusidentifier[0])
identifier = port->hba->radiusidentifier;
packetlength = packet->length;
packet->length = htons(packet->length);
- sock = socket(AF_INET, SOCK_DGRAM, 0);
+ sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0);
if (sock < 0)
{
ereport(LOG,
(errmsg("could not create RADIUS socket: %m")));
+ pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
return STATUS_ERROR;
}
memset(&localaddr, 0, sizeof(localaddr));
- localaddr.sin_family = AF_INET;
+#ifdef HAVE_IPV6
+ localaddr.sin6_family = serveraddrs[0].ai_family;
+ localaddr.sin6_addr = in6addr_any;
+ if (localaddr.sin6_family == AF_INET6)
+ addrsize = sizeof(struct sockaddr_in6);
+ else
+ addrsize = sizeof(struct sockaddr_in);
+#else
+ localaddr.sin_family = serveraddrs[0].ai_family;
localaddr.sin_addr.s_addr = INADDR_ANY;
- if (bind(sock, (struct sockaddr *) &localaddr, sizeof(localaddr)))
+ addrsize = sizeof(struct sockaddr_in);
+#endif
+ if (bind(sock, (struct sockaddr *) &localaddr, addrsize))
{
ereport(LOG,
(errmsg("could not bind local RADIUS socket: %m")));
closesocket(sock);
+ pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
return STATUS_ERROR;
}
if (sendto(sock, radius_buffer, packetlength, 0,
- (struct sockaddr *) &remoteaddr, sizeof(remoteaddr)) < 0)
+ serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0)
{
ereport(LOG,
(errmsg("could not send RADIUS packet: %m")));
closesocket(sock);
+ pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
return STATUS_ERROR;
}
+ /* Don't need the server address anymore */
+ pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
+
+ /* Wait for a response */
timeout.tv_sec = RADIUS_TIMEOUT;
timeout.tv_usec = 0;
FD_ZERO(&fdset);
closesocket(sock);
+#ifdef HAVE_IPV6
+ if (remoteaddr.sin6_port != htons(port->hba->radiusport))
+#else
if (remoteaddr.sin_port != htons(port->hba->radiusport))
+#endif
{
+#ifdef HAVE_IPV6
+ ereport(LOG,
+ (errmsg("RADIUS response was sent from incorrect port: %i",
+ ntohs(remoteaddr.sin6_port))));
+#else
ereport(LOG,
(errmsg("RADIUS response was sent from incorrect port: %i",
ntohs(remoteaddr.sin_port))));
+#endif
return STATUS_ERROR;
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.196 2010/01/27 12:11:59 mha Exp $
+ * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.197 2010/02/02 19:09:37 mha Exp $
*
*-------------------------------------------------------------------------
*/
else if (strcmp(token, "radiusserver") == 0)
{
REQUIRE_AUTH_OPTION(uaRADIUS, "radiusserver", "radius");
- if (inet_addr(c) == INADDR_NONE)
+
+ MemSet(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_family = AF_UNSPEC;
+
+ ret = pg_getaddrinfo_all(c, NULL, &hints, &gai_result);
+ if (ret || !gai_result)
{
ereport(LOG,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("invalid RADIUS server IP address: \"%s\"", c),
+ errmsg("could not translate RADIUS server name \"%s\" to address: %s",
+ c, gai_strerror(ret)),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
+ if (gai_result)
+ pg_freeaddrinfo_all(hints.ai_family, gai_result);
return false;
-
}
+ pg_freeaddrinfo_all(hints.ai_family, gai_result);
parsedline->radiusserver = pstrdup(c);
}
else if (strcmp(token, "radiusport") == 0)