]> granicus.if.org Git - postgresql/commitdiff
Add support for RADIUS authentication.
authorMagnus Hagander <magnus@hagander.net>
Wed, 27 Jan 2010 12:12:00 +0000 (12:12 +0000)
committerMagnus Hagander <magnus@hagander.net>
Wed, 27 Jan 2010 12:12:00 +0000 (12:12 +0000)
doc/src/sgml/client-auth.sgml
src/backend/libpq/auth.c
src/backend/libpq/hba.c
src/backend/libpq/md5.c
src/backend/libpq/pg_hba.conf.sample
src/include/libpq/hba.h
src/include/libpq/md5.h

index 9ceae856448b4ab9803ea807e718a8dcc73251ef..a8360936b2e66ca2080080d63e9a16251f7dd319 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.127 2010/01/26 06:45:31 petere Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.128 2010/01/27 12:11:59 mha Exp $ -->
 
 <chapter id="client-authentication">
  <title>Client Authentication</title>
@@ -394,6 +394,16 @@ hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>
         </listitem>
        </varlistentry>
 
+       <varlistentry>
+        <term><literal>radius</></term>
+        <listitem>
+         <para>
+          Authenticate using a RADIUS server. See <xref
+          linkend="auth-radius"> for detauls.
+         </para>
+        </listitem>
+       </varlistentry>
+
        <varlistentry>
         <term><literal>cert</></term>
         <listitem>
@@ -1331,6 +1341,95 @@ ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net"
 
   </sect2>
 
+  <sect2 id="auth-radius">
+   <title>RADIUS authentication</title>
+
+   <indexterm zone="auth-radius">
+    <primary>RADIUS</primary>
+   </indexterm>
+
+   <para>
+    This authentication method operates similarly to
+    <literal>password</literal> except that it uses RADIUS
+    as the password verification method. RADIUS is used only to validate
+    the user name/password pairs. Therefore the user must already
+    exist in the database before RADIUS can be used for
+    authentication.
+   </para>
+
+   <para>
+    When using RADIUS authentication, an Access Request message will be sent
+    to the configured RADIUS server. This request will be of type
+    <literal>Authenticate Only</literal>, and include parameters for
+    <literal>user name</>, <literal>password</> (encrypted) and
+    <literal>NAS Identifier</>. The request will be encrypted using
+    a secret shared with the server. The RADIUS server will respond to
+    this server with either <literal>Access Accept</> or
+    <literal>Access Reject</>. There is no support for RADIUS accounting.
+   </para>
+
+   <para>
+    The following configuration options are supported for RADIUS:
+     <variablelist>
+      <varlistentry>
+       <term><literal>radiusserver</literal></term>
+       <listitem>
+        <para>
+         The IP address of the RADIUS server to connect to. This must
+         be an IPV4 address and not a hostname. This parameter is required.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><literal>radiussecret</literal></term>
+       <listitem>
+        <para>
+         The shared secret used when talking securely to the RADIUS
+         server. This must have exactly the same value on the PostgreSQL
+         and RADIUS servers. It is recommended that this is a string of
+         at least 16 characters. This parameter is required.
+         <note>
+         <para>
+          The encryption vector used will only be cryptographically
+          strong if <productname>PostgreSQL</> is built with support for
+          <productname>OpenSSL</>. In other cases, the transmission to the
+          RADIUS server should only be considered obfuscated, not secured, and
+          external security measures should be applied if necessary.
+         </para>
+         </note>
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><literal>radiusport</literal></term>
+       <listitem>
+        <para>
+         The port number on the RADIUS server to connect to. If no port
+         is specified, the default port <literal>1812</> will be used.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><literal>radiusidentifier</literal></term>
+       <listitem>
+        <para>
+         The string used as <literal>NAS Identifier</> in the RADIUS
+         requests. This parameter can be used as a second parameter
+         identifying for example which database the user is attempting
+         to authenticate as, which can be used for policy matching on
+         the RADIUS server. If no identifier is specified, the default
+         <literal>postgresql</> will be used.
+        </para>
+       </listitem>
+      </varlistentry>
+
+     </variablelist>
+   </para>
+  </sect2>
+
   <sect2 id="auth-cert">
    <title>Certificate authentication</title>
 
index e7d0dbb29854cf782ceb1a9c2cf626358f01be25..26d2080e6f975eae9abd42c99d8f9e96ebf492ee 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.191 2010/01/10 14:16:07 mha Exp $
+ *       $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.192 2010/01/27 12:11:59 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <unistd.h>
+#include <stddef.h>
 
 #include "libpq/auth.h"
 #include "libpq/crypt.h"
 #include "libpq/ip.h"
 #include "libpq/libpq.h"
 #include "libpq/pqformat.h"
+#include "libpq/md5.h"
 #include "miscadmin.h"
 #include "storage/ipc.h"
 
@@ -182,6 +184,15 @@ typedef SECURITY_STATUS
 static int     pg_SSPI_recvauth(Port *port);
 #endif
 
+/*----------------------------------------------------------------
+ * RADIUS Authentication
+ *----------------------------------------------------------------
+ */
+#ifdef USE_SSL
+#include <openssl/rand.h>
+#endif
+static int     CheckRADIUSAuth(Port *port);
+
 
 /*
  * Maximum accepted size of GSS and SSPI authentication tokens.
@@ -265,6 +276,9 @@ auth_failed(Port *port, int status)
                case uaLDAP:
                        errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
                        break;
+               case uaRADIUS:
+                       errstr = gettext_noop("RADIUS authentication failed for user \"%s\"");
+                       break;
                default:
                        errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
                        break;
@@ -473,7 +487,9 @@ ClientAuthentication(Port *port)
                        Assert(false);
 #endif
                        break;
-
+               case uaRADIUS:
+                       status = CheckRADIUSAuth(port);
+                       break;
                case uaTrust:
                        status = STATUS_OK;
                        break;
@@ -2415,3 +2431,350 @@ CheckCertAuth(Port *port)
 }
 
 #endif
+
+
+/*----------------------------------------------------------------
+ * RADIUS authentication
+ *----------------------------------------------------------------
+ */
+
+/*
+ * RADIUS authentication is described in RFC2865 (and several
+ * others).
+ */
+
+#define RADIUS_VECTOR_LENGTH 16
+#define RADIUS_HEADER_LENGTH 20
+
+typedef struct
+{
+       uint8   attribute;
+       uint8   length;
+       uint8   data[1];
+} radius_attribute;
+
+typedef struct
+{
+       uint8   code;
+       uint8   id;
+       uint16  length;
+       uint8   vector[RADIUS_VECTOR_LENGTH];
+} radius_packet;
+
+/* RADIUS packet types */
+#define RADIUS_ACCESS_REQUEST  1
+#define RADIUS_ACCESS_ACCEPT   2
+#define RADIUS_ACCESS_REJECT   3
+
+/* RAIDUS attributes */
+#define RADIUS_USER_NAME               1
+#define RADIUS_PASSWORD                        2
+#define RADIUS_SERVICE_TYPE            6
+#define RADIUS_NAS_IDENTIFIER  32
+
+/* RADIUS service types */
+#define RADIUS_AUTHENTICATE_ONLY       8
+
+/* 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)
+{
+       radius_attribute                *attr;
+
+       if (packet->length + len > RADIUS_BUFFER_SIZE)
+       {
+               /*
+                * With remotely realistic data, this can never happen. But catch it just to make
+                * sure we don't overrun a buffer. We'll just skip adding the broken attribute,
+                * which will in the end cause authentication to fail.
+                */
+               elog(WARNING,
+                        "Adding attribute code %i with length %i to radius packet would create oversize packet, ignoring",
+                        type, len);
+               return;
+
+       }
+
+       attr = (radius_attribute *) ((unsigned char *)packet + packet->length);
+       attr->attribute = type;
+       attr->length = len + 2; /* total size includes type and length */
+       memcpy(attr->data, data, len);
+       packet->length += attr->length;
+}
+
+static int
+CheckRADIUSAuth(Port *port)
+{
+       char                       *passwd;
+       char                       *identifier = "postgresql";
+       char                            radius_buffer[RADIUS_BUFFER_SIZE];
+       char                            receive_buffer[RADIUS_BUFFER_SIZE];
+       radius_packet      *packet = (radius_packet *)radius_buffer;
+       radius_packet      *receivepacket = (radius_packet *)receive_buffer;
+       int32                           service = htonl(RADIUS_AUTHENTICATE_ONLY);
+       uint8                      *cryptvector;
+       uint8                           encryptedpassword[RADIUS_VECTOR_LENGTH];
+       int                                     packetlength;
+       pgsocket                        sock;
+       struct sockaddr_in      localaddr;
+       struct sockaddr_in      remoteaddr;
+       socklen_t                       addrsize;
+       fd_set                          fdset;
+       struct timeval          timeout;
+       int                                     i,r;
+
+       /* Make sure struct alignment is correct */
+       Assert(offsetof(radius_packet, vector) == 4);
+
+       /* Verify parameters */
+       if (!port->hba->radiusserver || port->hba->radiusserver[0] == '\0')
+       {
+               ereport(LOG,
+                               (errmsg("RADIUS server not specified")));
+               return STATUS_ERROR;
+       }
+
+       if (!port->hba->radiussecret || port->hba->radiussecret[0] == '\0')
+       {
+               ereport(LOG,
+                               (errmsg("RADIUS secret not specified")));
+               return STATUS_ERROR;
+       }
+
+       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)
+       {
+               ereport(LOG,
+                               (errmsg("RADIUS server '%s' is not a valid IP address",
+                                               port->hba->radiusserver)));
+               return STATUS_ERROR;
+       }
+       remoteaddr.sin_port = htons(port->hba->radiusport);
+
+       if (port->hba->radiusidentifier && port->hba->radiusidentifier[0])
+               identifier = port->hba->radiusidentifier;
+
+       /* Send regular password request to client, and get the response */
+       sendAuthRequest(port, AUTH_REQ_PASSWORD);
+
+       passwd = recv_password_packet(port);
+       if (passwd == NULL)
+               return STATUS_EOF;              /* client wouldn't send password */
+
+       if (strlen(passwd) == 0)
+       {
+               ereport(LOG,
+                               (errmsg("empty password returned by client")));
+               return STATUS_ERROR;
+       }
+
+       if (strlen(passwd) > RADIUS_VECTOR_LENGTH)
+       {
+               ereport(LOG,
+                               (errmsg("RADIUS authentication does not support passwords longer than 16 characters")));
+               return STATUS_ERROR;
+       }
+
+       /* Construct RADIUS packet */
+       packet->code = RADIUS_ACCESS_REQUEST;
+       packet->length = RADIUS_HEADER_LENGTH;
+#ifdef USE_SSL
+       if (RAND_bytes(packet->vector, RADIUS_VECTOR_LENGTH) != 1)
+       {
+               ereport(LOG,
+                               (errmsg("could not generate random encryption vector")));
+               return STATUS_ERROR;
+       }
+#else
+       for (i = 0; i < RADIUS_VECTOR_LENGTH; i++)
+               /* Use a lower strengh random number of OpenSSL is not available */
+               packet->vector[i] = random() % 255;
+#endif
+       packet->id = packet->vector[0];
+       radius_add_attribute(packet, RADIUS_SERVICE_TYPE, (unsigned char *) &service, sizeof(service));
+       radius_add_attribute(packet, RADIUS_USER_NAME, (unsigned char *) port->user_name, strlen(port->user_name));
+       radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (unsigned char *) identifier, strlen(identifier));
+
+       /*
+        * RADIUS password attributes are calculated as:
+        * e[0] = p[0] XOR MD5(secret + vector)
+        */
+       cryptvector = palloc(RADIUS_VECTOR_LENGTH + strlen(port->hba->radiussecret));
+       memcpy(cryptvector, port->hba->radiussecret, strlen(port->hba->radiussecret));
+       memcpy(cryptvector + strlen(port->hba->radiussecret), packet->vector, RADIUS_VECTOR_LENGTH);
+       if (!pg_md5_binary(cryptvector, RADIUS_VECTOR_LENGTH + strlen(port->hba->radiussecret), encryptedpassword))
+       {
+               ereport(LOG,
+                               (errmsg("could not perform md5 encryption of password")));
+               pfree(cryptvector);
+               return STATUS_ERROR;
+       }
+       pfree(cryptvector);
+       for (i = 0; i < RADIUS_VECTOR_LENGTH; i++)
+       {
+               if (i < strlen(passwd))
+                       encryptedpassword[i] = passwd[i] ^ encryptedpassword[i];
+               else
+                       encryptedpassword[i] = '\0' ^ encryptedpassword[i];
+       }
+       radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, RADIUS_VECTOR_LENGTH);
+
+       /* Length need to be in network order on the wire */
+       packetlength = packet->length;
+       packet->length = htons(packet->length);
+
+       sock = socket(AF_INET, SOCK_DGRAM, 0);
+       if (sock < 0)
+       {
+               ereport(LOG,
+                               (errmsg("could not create RADIUS socket: %m")));
+               return STATUS_ERROR;
+       }
+
+       memset(&localaddr, 0, sizeof(localaddr));
+       localaddr.sin_family = AF_INET;
+       localaddr.sin_addr.s_addr = INADDR_ANY;
+       if (bind(sock, (struct sockaddr *) &localaddr, sizeof(localaddr)))
+       {
+               ereport(LOG,
+                               (errmsg("could not bind local RADIUS socket: %m")));
+               closesocket(sock);
+               return STATUS_ERROR;
+       }
+
+       if (sendto(sock, radius_buffer, packetlength, 0,
+                          (struct sockaddr *) &remoteaddr, sizeof(remoteaddr)) < 0)
+       {
+               ereport(LOG,
+                               (errmsg("could not send RADIUS packet: %m")));
+               closesocket(sock);
+               return STATUS_ERROR;
+       }
+
+       timeout.tv_sec = RADIUS_TIMEOUT;
+       timeout.tv_usec = 0;
+       FD_ZERO(&fdset);
+       FD_SET(sock, &fdset);
+       while (true)
+       {
+               r = select(sock + 1, &fdset, NULL, NULL, &timeout);
+               if (r < 0)
+               {
+                       if (errno == EINTR)
+                               continue;
+
+                       /* Anything else is an actual error */
+                       ereport(LOG,
+                                       (errmsg("could not check status on RADIUS socket: %m")));
+                       closesocket(sock);
+                       return STATUS_ERROR;
+               }
+               if (r == 0)
+               {
+                       ereport(LOG,
+                                       (errmsg("timeout waiting for RADIUS response")));
+                       closesocket(sock);
+                       return STATUS_ERROR;
+               }
+
+               /* else we actually have a packet ready to read */
+               break;
+       }
+
+       /* Read the response packet */
+       addrsize = sizeof(remoteaddr);
+       packetlength = recvfrom(sock, receive_buffer, RADIUS_BUFFER_SIZE, 0,
+                                                       (struct sockaddr *) &remoteaddr, &addrsize);
+       if (packetlength < 0)
+       {
+               ereport(LOG,
+                               (errmsg("could not read RADIUS response: %m")));
+               closesocket(sock);
+               return STATUS_ERROR;
+       }
+
+       closesocket(sock);
+
+       if (remoteaddr.sin_port != htons(port->hba->radiusport))
+       {
+               ereport(LOG,
+                               (errmsg("RADIUS response was sent from incorrect port: %i",
+                                               ntohs(remoteaddr.sin_port))));
+               return STATUS_ERROR;
+       }
+
+       if (packetlength < RADIUS_HEADER_LENGTH)
+       {
+               ereport(LOG,
+                               (errmsg("RADIUS response too short: %i", packetlength)));
+               return STATUS_ERROR;
+       }
+
+       if (packetlength != ntohs(receivepacket->length))
+       {
+               ereport(LOG,
+                               (errmsg("RADIUS response has corrupt length: %i (actual length %i)",
+                                               ntohs(receivepacket->length), packetlength)));
+               return STATUS_ERROR;
+       }
+
+       if (packet->id != receivepacket->id)
+       {
+               ereport(LOG,
+                               (errmsg("RADIUS response is to a different request: %i (should be %i)",
+                                               receivepacket->id, packet->id)));
+               return STATUS_ERROR;
+       }
+
+       /*
+        * Verify the response authenticator, which is calculated as
+        * MD5(Code+ID+Length+RequestAuthenticator+Attributes+Secret)
+        */
+       cryptvector = palloc(packetlength + strlen(port->hba->radiussecret));
+
+       memcpy(cryptvector, receivepacket, 4);          /* code+id+length */
+       memcpy(cryptvector+4, packet->vector, RADIUS_VECTOR_LENGTH);    /* request authenticator, from original packet */
+       if (packetlength > RADIUS_HEADER_LENGTH)        /* there may be no attributes at all */
+               memcpy(cryptvector+RADIUS_HEADER_LENGTH, receive_buffer + RADIUS_HEADER_LENGTH, packetlength-RADIUS_HEADER_LENGTH);
+       memcpy(cryptvector+packetlength, port->hba->radiussecret, strlen(port->hba->radiussecret));
+
+       if (!pg_md5_binary(cryptvector,
+                                          packetlength + strlen(port->hba->radiussecret),
+                                          encryptedpassword))
+       {
+               ereport(LOG,
+                               (errmsg("could not perform md5 encryption of received packet")));
+               pfree(cryptvector);
+               return STATUS_ERROR;
+       }
+       pfree(cryptvector);
+
+       if (memcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH)  != 0)
+       {
+               ereport(LOG,
+                               (errmsg("RADIUS response has incorrect MD5 signature")));
+               return STATUS_ERROR;
+       }
+
+       if (receivepacket->code == RADIUS_ACCESS_ACCEPT)
+               return STATUS_OK;
+       else if (receivepacket->code == RADIUS_ACCESS_REJECT)
+               return STATUS_ERROR;
+       else
+       {
+               ereport(LOG,
+                               (errmsg("RADIUS response has invalid code (%i) for user '%s'",
+                                               receivepacket->code, port->user_name)));
+               return STATUS_ERROR;
+       }
+}
index 98011c2822bab399ae921aa3b0d1707ab3b4bc0d..588ce643afcd1e641b3916873f634367cf783d8e 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.195 2010/01/15 09:19:02 heikki Exp $
+ *       $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.196 2010/01/27 12:11:59 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -952,6 +952,8 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
 #else
                unsupauth = "cert";
 #endif
+       else if (strcmp(token, "radius")== 0)
+               parsedline->auth_method = uaRADIUS;
        else
        {
                ereport(LOG,
@@ -1162,6 +1164,45 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
                                else
                                        parsedline->include_realm = false;
                        }
+                       else if (strcmp(token, "radiusserver") == 0)
+                       {
+                               REQUIRE_AUTH_OPTION(uaRADIUS, "radiusserver", "radius");
+                               if (inet_addr(c) == INADDR_NONE)
+                               {
+                                       ereport(LOG,
+                                                       (errcode(ERRCODE_CONFIG_FILE_ERROR),
+                                                        errmsg("invalid RADIUS server IP address: \"%s\"", c),
+                                                  errcontext("line %d of configuration file \"%s\"",
+                                                                         line_num, HbaFileName)));
+                                       return false;
+
+                               }
+                               parsedline->radiusserver = pstrdup(c);
+                       }
+                       else if (strcmp(token, "radiusport") == 0)
+                       {
+                               REQUIRE_AUTH_OPTION(uaRADIUS, "radiusport", "radius");
+                               parsedline->radiusport = atoi(c);
+                               if (parsedline->radiusport == 0)
+                               {
+                                       ereport(LOG,
+                                                       (errcode(ERRCODE_CONFIG_FILE_ERROR),
+                                                        errmsg("invalid RADIUS port number: \"%s\"", c),
+                                                  errcontext("line %d of configuration file \"%s\"",
+                                                                         line_num, HbaFileName)));
+                                       return false;
+                               }
+                       }
+                       else if (strcmp(token, "radiussecret") == 0)
+                       {
+                               REQUIRE_AUTH_OPTION(uaRADIUS, "radiussecret", "radius");
+                               parsedline->radiussecret = pstrdup(c);
+                       }
+                       else if (strcmp(token, "radiusidentifier") == 0)
+                       {
+                               REQUIRE_AUTH_OPTION(uaRADIUS, "radiusidentifier", "radius");
+                               parsedline->radiusidentifier = pstrdup(c);
+                       }
                        else
                        {
                                ereport(LOG,
@@ -1214,6 +1255,12 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
                }
        }
 
+       if (parsedline->auth_method == uaRADIUS)
+       {
+               MANDATORY_AUTH_ARG(parsedline->radiusserver, "radiusserver", "radius");
+               MANDATORY_AUTH_ARG(parsedline->radiussecret, "radiussecret", "radius");
+       }
+
        /*
         * Enforce any parameters implied by other settings.
         */
index 002afcf0ff51639f95ed61d4dd4e0ddbf7791120..e875f51ed72cc7af493f0c17074472b0ac34bd52 100644 (file)
@@ -14,7 +14,7 @@
  *     Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/libpq/md5.c,v 1.38 2010/01/02 16:57:45 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/libpq/md5.c,v 1.39 2010/01/27 12:11:59 mha Exp $
  */
 
 /* This is intended to be used in both frontend and backend, so use c.h */
@@ -298,6 +298,12 @@ pg_md5_hash(const void *buff, size_t len, char *hexsum)
        return true;
 }
 
+bool pg_md5_binary(const void *buff, size_t len, void *outbuf)
+{
+       if (!calculateDigestFromBuffer((uint8 *) buff, len, outbuf))
+               return false;
+       return true;
+}
 
 
 /*
index 22bb14730aa31c23e74ba24e5f330e8174ba580c..e1017cf28cd61d840f50a207631cd13b1b79b031 100644 (file)
@@ -39,9 +39,9 @@
 # any subnet that the server is directly connected to.
 #
 # METHOD can be "trust", "reject", "md5", "password", "gss", "sspi",
-# "krb5", "ident", "pam", "ldap" or "cert".  Note that "password"
-# sends passwords in clear text; "md5" is preferred since it sends
-# encrypted passwords.
+# "krb5", "ident", "pam", "ldap", "radius" or "cert".  Note that
+# "password" sends passwords in clear text; "md5" is preferred since
+# it sends encrypted passwords.
 #
 # OPTIONS are a set of options for the authentication in the format
 # NAME=VALUE.  The available options depend on the different
index 8ee71a7e093647b84047e71374edce20ef5c3510..54261bba61dbd3d9fdca6c50ff478b52f50e3203 100644 (file)
@@ -4,7 +4,7 @@
  *       Interface to hba.c
  *
  *
- * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.60 2009/12/12 21:35:21 mha Exp $
+ * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.61 2010/01/27 12:12:00 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,7 +27,8 @@ typedef enum UserAuth
        uaSSPI,
        uaPAM,
        uaLDAP,
-       uaCert
+       uaCert,
+       uaRADIUS
 } UserAuth;
 
 typedef enum IPCompareMethod
@@ -71,6 +72,10 @@ typedef struct
        char       *krb_server_hostname;
        char       *krb_realm;
        bool            include_realm;
+       char       *radiusserver;
+       char       *radiussecret;
+       char       *radiusidentifier;
+       int                     radiusport;
 } HbaLine;
 
 /* kluge to avoid including libpq/libpq-be.h here */
index aa36ac6fa2388c129521c331c19addd86fff6227..decc6ddf120dc4754cb83133fd0bc01e84ccd123 100644 (file)
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/libpq/md5.h,v 1.7 2010/01/02 16:58:04 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/libpq/md5.h,v 1.8 2010/01/27 12:12:00 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,6 +23,7 @@
 
 
 extern bool pg_md5_hash(const void *buff, size_t len, char *hexsum);
+extern bool pg_md5_binary(const void *buff, size_t len, void *outbuf);
 extern bool pg_md5_encrypt(const char *passwd, const char *salt,
                           size_t salt_len, char *buf);