mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-27 08:39:28 +08:00
Make RADIUS authentication use pg_getaddrinfo_all() to get address of
the server. Gets rid of a fairly ugly hack for Solaris, and also provides hostname and IPV6 support.
This commit is contained in:
parent
d8db6a6096
commit
0a27347141
@ -1,4 +1,4 @@
|
|||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.129 2010/01/27 13:03:17 mha Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.130 2010/02/02 19:09:36 mha Exp $ -->
|
||||||
|
|
||||||
<chapter id="client-authentication">
|
<chapter id="client-authentication">
|
||||||
<title>Client Authentication</title>
|
<title>Client Authentication</title>
|
||||||
@ -1375,8 +1375,8 @@ ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net"
|
|||||||
<term><literal>radiusserver</literal></term>
|
<term><literal>radiusserver</literal></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The IP address of the RADIUS server to connect to. This must
|
The name or IP address of the RADIUS server to connect to.
|
||||||
be an IPV4 address and not a hostname. This parameter is required.
|
This parameter is required.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -2521,8 +2521,16 @@ CheckRADIUSAuth(Port *port)
|
|||||||
uint8 encryptedpassword[RADIUS_VECTOR_LENGTH];
|
uint8 encryptedpassword[RADIUS_VECTOR_LENGTH];
|
||||||
int packetlength;
|
int packetlength;
|
||||||
pgsocket sock;
|
pgsocket sock;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
struct sockaddr_in6 localaddr;
|
||||||
|
struct sockaddr_in6 remoteaddr;
|
||||||
|
#else
|
||||||
struct sockaddr_in localaddr;
|
struct sockaddr_in localaddr;
|
||||||
struct sockaddr_in remoteaddr;
|
struct sockaddr_in remoteaddr;
|
||||||
|
#endif
|
||||||
|
struct addrinfo hint;
|
||||||
|
struct addrinfo *serveraddrs;
|
||||||
|
char portstr[128];
|
||||||
ACCEPT_TYPE_ARG3 addrsize;
|
ACCEPT_TYPE_ARG3 addrsize;
|
||||||
fd_set fdset;
|
fd_set fdset;
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
@ -2549,17 +2557,22 @@ CheckRADIUSAuth(Port *port)
|
|||||||
if (port->hba->radiusport == 0)
|
if (port->hba->radiusport == 0)
|
||||||
port->hba->radiusport = 1812;
|
port->hba->radiusport = 1812;
|
||||||
|
|
||||||
memset(&remoteaddr, 0, sizeof(remoteaddr));
|
MemSet(&hint, 0, sizeof(hint));
|
||||||
remoteaddr.sin_family = AF_INET;
|
hint.ai_socktype = SOCK_DGRAM;
|
||||||
remoteaddr.sin_addr.s_addr = inet_addr(port->hba->radiusserver);
|
hint.ai_family = AF_UNSPEC;
|
||||||
if (remoteaddr.sin_addr.s_addr == INADDR_NONE)
|
snprintf(portstr, sizeof(portstr), "%d", port->hba->radiusport);
|
||||||
|
|
||||||
|
r = pg_getaddrinfo_all(port->hba->radiusserver, portstr, &hint, &serveraddrs);
|
||||||
|
if (r || !serveraddrs)
|
||||||
{
|
{
|
||||||
ereport(LOG,
|
ereport(LOG,
|
||||||
(errmsg("RADIUS server '%s' is not a valid IP address",
|
(errmsg("could not translate RADIUS server name \"%s\" to address: %s",
|
||||||
port->hba->radiusserver)));
|
port->hba->radiusserver, gai_strerror(r))));
|
||||||
|
if (serveraddrs)
|
||||||
|
pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
|
||||||
return STATUS_ERROR;
|
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])
|
if (port->hba->radiusidentifier && port->hba->radiusidentifier[0])
|
||||||
identifier = port->hba->radiusidentifier;
|
identifier = port->hba->radiusidentifier;
|
||||||
@ -2633,34 +2646,51 @@ CheckRADIUSAuth(Port *port)
|
|||||||
packetlength = packet->length;
|
packetlength = packet->length;
|
||||||
packet->length = htons(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)
|
if (sock < 0)
|
||||||
{
|
{
|
||||||
ereport(LOG,
|
ereport(LOG,
|
||||||
(errmsg("could not create RADIUS socket: %m")));
|
(errmsg("could not create RADIUS socket: %m")));
|
||||||
|
pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
|
||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&localaddr, 0, sizeof(localaddr));
|
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;
|
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,
|
ereport(LOG,
|
||||||
(errmsg("could not bind local RADIUS socket: %m")));
|
(errmsg("could not bind local RADIUS socket: %m")));
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
|
pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
|
||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sendto(sock, radius_buffer, packetlength, 0,
|
if (sendto(sock, radius_buffer, packetlength, 0,
|
||||||
(struct sockaddr *) &remoteaddr, sizeof(remoteaddr)) < 0)
|
serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0)
|
||||||
{
|
{
|
||||||
ereport(LOG,
|
ereport(LOG,
|
||||||
(errmsg("could not send RADIUS packet: %m")));
|
(errmsg("could not send RADIUS packet: %m")));
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
|
pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
|
||||||
return STATUS_ERROR;
|
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_sec = RADIUS_TIMEOUT;
|
||||||
timeout.tv_usec = 0;
|
timeout.tv_usec = 0;
|
||||||
FD_ZERO(&fdset);
|
FD_ZERO(&fdset);
|
||||||
@ -2705,11 +2735,21 @@ CheckRADIUSAuth(Port *port)
|
|||||||
|
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
|
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (remoteaddr.sin6_port != htons(port->hba->radiusport))
|
||||||
|
#else
|
||||||
if (remoteaddr.sin_port != htons(port->hba->radiusport))
|
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,
|
ereport(LOG,
|
||||||
(errmsg("RADIUS response was sent from incorrect port: %i",
|
(errmsg("RADIUS response was sent from incorrect port: %i",
|
||||||
ntohs(remoteaddr.sin_port))));
|
ntohs(remoteaddr.sin_port))));
|
||||||
|
#endif
|
||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1167,16 +1167,25 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
|
|||||||
else if (strcmp(token, "radiusserver") == 0)
|
else if (strcmp(token, "radiusserver") == 0)
|
||||||
{
|
{
|
||||||
REQUIRE_AUTH_OPTION(uaRADIUS, "radiusserver", "radius");
|
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,
|
ereport(LOG,
|
||||||
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
(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\"",
|
errcontext("line %d of configuration file \"%s\"",
|
||||||
line_num, HbaFileName)));
|
line_num, HbaFileName)));
|
||||||
|
if (gai_result)
|
||||||
|
pg_freeaddrinfo_all(hints.ai_family, gai_result);
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
pg_freeaddrinfo_all(hints.ai_family, gai_result);
|
||||||
parsedline->radiusserver = pstrdup(c);
|
parsedline->radiusserver = pstrdup(c);
|
||||||
}
|
}
|
||||||
else if (strcmp(token, "radiusport") == 0)
|
else if (strcmp(token, "radiusport") == 0)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $PostgreSQL: pgsql/src/include/port/solaris.h,v 1.18 2010/01/28 11:36:14 mha Exp $ */
|
/* $PostgreSQL: pgsql/src/include/port/solaris.h,v 1.19 2010/02/02 19:09:37 mha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sort this out for all operating systems some time. The __xxx
|
* Sort this out for all operating systems some time. The __xxx
|
||||||
@ -36,11 +36,3 @@
|
|||||||
* still use our own fix for the buggy version.
|
* still use our own fix for the buggy version.
|
||||||
*/
|
*/
|
||||||
#define HAVE_BUGGY_SOLARIS_STRTOD
|
#define HAVE_BUGGY_SOLARIS_STRTOD
|
||||||
|
|
||||||
/*
|
|
||||||
* Many versions of Solaris are missing the definition of INADDR_NONE
|
|
||||||
*/
|
|
||||||
#ifndef INADDR_NONE
|
|
||||||
#define INADDR_NONE ((in_addr_t)(-1))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user