Add radiustimeout parameter for RADIUS HBA
Hello everyone,
I’d like to submit the attached patch for feedback from the PostgreSQL community and potential future inclusion in the codebase. The patch adds a new parameter to the RADIUS authentication method named “radiustimeout”, allowing the database administrator to configure the timeout in seconds to wait for responses from a configured RADIUS server. Until now, this has been hardcoded to three seconds by the RADIUS_TIMEOUT define in auth.c. While this is usually sufficient for typical RADIUS server configurations, there are some more unusual configurations where a higher timeout is required. Examples include:
- Authenticating against a RADIUS server over a high latency link
- Authenticating against a RADIUS server that is performing additional out-of-band authentication
The latter case is applicable to a server I admin and spurred the development of this patch. We implemented multi-factor authentication for user access to a sensitive database via a RADIUS server implementation which performs the standard username & password verification, and if it succeeds, subsequently performs a second factor of authentication via a configured mobile app. The RADIUS response confirming successful authentication is only returned after both authentication factors have completed. In our deployment, a timeout of 60 seconds seems to work well, but certainly three seconds is not at all workable.
Thanks in advance for any and all feedback.
Kind regards,
-SDL
Attachments:
radiustimeout.patchapplication/octet-stream; name=radiustimeout.patchDownload
diff --git i/doc/src/sgml/client-auth.sgml w/doc/src/sgml/client-auth.sgml
index 960f5b5..7055d13 100644
--- i/doc/src/sgml/client-auth.sgml
+++ w/doc/src/sgml/client-auth.sgml
@@ -1612,6 +1612,17 @@ host ... ldap ldapurl="ldap://ldap.example.net/dc=example,dc=net?uid?sub"
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal>radiustimeout</literal></term>
+ <listitem>
+ <para>
+ The timeout to wait for a response from the RADIUS server in seconds.
+ If no value is specified, a default timeout of <literal>3</> seconds
+ will be used.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><literal>radiusidentifier</literal></term>
<listitem>
diff --git i/src/backend/libpq/auth.c w/src/backend/libpq/auth.c
index 0ba8530..8a4e9ab 100644
--- i/src/backend/libpq/auth.c
+++ w/src/backend/libpq/auth.c
@@ -2379,9 +2379,6 @@ typedef struct
/* Maximum size of a RADIUS packet we will create or accept */
#define RADIUS_BUFFER_SIZE 1024
-/* Seconds to wait - XXX: should be in a config variable! */
-#define RADIUS_TIMEOUT 3
-
static void
radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *data, int len)
{
@@ -2463,6 +2460,9 @@ CheckRADIUSAuth(Port *port)
if (port->hba->radiusport == 0)
port->hba->radiusport = 1812;
+ if (port->hba->radiustimeout == 0)
+ port->hba->radiustimeout = 3;
+
MemSet(&hint, 0, sizeof(hint));
hint.ai_socktype = SOCK_DGRAM;
hint.ai_family = AF_UNSPEC;
@@ -2626,7 +2626,7 @@ CheckRADIUSAuth(Port *port)
* timeouts/cancellations.
*/
gettimeofday(&endtime, NULL);
- endtime.tv_sec += RADIUS_TIMEOUT;
+ endtime.tv_sec += port->hba->radiustimeout;
while (true)
{
diff --git i/src/backend/libpq/hba.c w/src/backend/libpq/hba.c
index f1e9a38..7ef2888 100644
--- i/src/backend/libpq/hba.c
+++ w/src/backend/libpq/hba.c
@@ -1665,6 +1665,20 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
REQUIRE_AUTH_OPTION(uaRADIUS, "radiusidentifier", "radius");
hbaline->radiusidentifier = pstrdup(val);
}
+ else if (strcmp(name, "radiustimeout") == 0)
+ {
+ REQUIRE_AUTH_OPTION(uaRADIUS, "radiustimeout", "radius");
+ hbaline->radiustimeout = atoi(val);
+ if (hbaline->radiustimeout == 0)
+ {
+ ereport(LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("invalid RADIUS timeout value: \"%s\"", val),
+ errcontext("line %d of configuration file \"%s\"",
+ line_num, HbaFileName)));
+ return false;
+ }
+ }
else
{
ereport(LOG,
diff --git i/src/include/libpq/hba.h w/src/include/libpq/hba.h
index dc7d257..e206fe9 100644
--- i/src/include/libpq/hba.h
+++ w/src/include/libpq/hba.h
@@ -85,6 +85,7 @@ typedef struct HbaLine
char *radiussecret;
char *radiusidentifier;
int radiusport;
+ int radiustimeout;
} HbaLine;
typedef struct IdentLine
On Mon, Oct 24, 2016 at 2:03 PM, Samuel D. Leslie <SDL@nexiom.net> wrote:
Hello everyone,
I’d like to submit the attached patch for feedback from the PostgreSQL
community and potential future inclusion in the codebase. The patch adds a
new parameter to the RADIUS authentication method named “radiustimeout”,
allowing the database administrator to configure the timeout in seconds to
wait for responses from a configured RADIUS server. Until now, this has
been hardcoded to three seconds by the RADIUS_TIMEOUT define in auth.c.
While this is usually sufficient for typical RADIUS server configurations,
there are some more unusual configurations where a higher timeout is
required. Examples include:
- Authenticating against a RADIUS server over a high latency link
- Authenticating against a RADIUS server that is performing additional
out-of-band authenticationThe latter case is applicable to a server I admin and spurred the
development of this patch. We implemented multi-factor authentication for
user access to a sensitive database via a RADIUS server implementation
which performs the standard username & password verification, and if it
succeeds, subsequently performs a second factor of authentication via a
configured mobile app. The RADIUS response confirming successful
authentication is only returned after both authentication factors have
completed. In our deployment, a timeout of 60 seconds seems to work well,
but certainly three seconds is not at all workable.Thanks in advance for any and all feedback.
I reviewed and tested the patch. It works as expected.
Following are my observations during the test.
1. In case if the radiustimeout is more than authentication_timeout the
client connection is stopped only when the radiustimeout is occurred.
Do we need add the CHECK_FOR_INTERRUPTS() call or add this
behavior information in the docs?
2. When the Postgresql Backend is waiting for a response from
Radius server, in case if the client disconnects, still backend waits
for the response from RADIUS server and then it closes.
I feel the second case is rare, may not be a problem.
Regards,
Hari Babu
Fujitsu Australia