OSDN Git Service

Allow krb_realm (krb5, gssapi and sspi) and krb_server_hostname (krb5 only)
authorMagnus Hagander <magnus@hagander.net>
Wed, 7 Jan 2009 12:38:11 +0000 (12:38 +0000)
committerMagnus Hagander <magnus@hagander.net>
Wed, 7 Jan 2009 12:38:11 +0000 (12:38 +0000)
authentication options to be set in pg_hba.conf on a per-line basis, to
override the defaults set in postgresql.conf.

doc/src/sgml/client-auth.sgml
src/backend/libpq/auth.c
src/backend/libpq/hba.c
src/include/libpq/hba.h

index 8e3b7c1..1d0ce45 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.115 2009/01/02 11:51:53 mha Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.116 2009/01/07 12:38:10 mha Exp $ -->
 
 <chapter id="client-authentication">
  <title>Client Authentication</title>
@@ -784,6 +784,26 @@ omicron       bryanh            guest1
        </para>
       </listitem>
      </varlistentry>
+
+     <varlistentry>
+      <term>krb_realm</term>
+      <listitem>
+       <para>
+        Overrides the <xref linkend="guc-krb-realm"> parameter, setting which realm
+        to verify the authenticated user principal against.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term>krb_server_hostname</term>
+      <listitem>
+       <para>
+        Overrides the <xref linkend="guc-krb-server-hostname"> parameter, setting which
+        hostname will be used for the server principal when using Kerberos.
+       </para>
+      </listitem>
+     </varlistentry>
     </variablelist>
    </para>
   </sect2>
@@ -825,6 +845,16 @@ omicron       bryanh            guest1
        </para>
       </listitem>
      </varlistentry>
+
+     <varlistentry>
+      <term>krb_realm</term>
+      <listitem>
+       <para>
+        Overrides the <xref linkend="guc-krb-realm"> parameter, setting which realm
+        to verify the authenticated user principal against.
+       </para>
+      </listitem>
+     </varlistentry>
     </variablelist>
    </para>
   </sect2>
index 9a93e9a..437061c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.175 2009/01/01 17:23:42 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.176 2009/01/07 12:38:11 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -611,7 +611,7 @@ recv_and_check_password_packet(Port *port)
 #ifdef KRB5
 
 static int
-pg_krb5_init(void)
+pg_krb5_init(Port *port)
 {
        krb5_error_code retval;
        char       *khostname;
@@ -645,7 +645,10 @@ pg_krb5_init(void)
         * If no hostname was specified, pg_krb_server_hostname is already NULL.
         * If it's set to blank, force it to NULL.
         */
-       khostname = pg_krb_server_hostname;
+       if (port->hba->krb_server_hostname)
+               khostname = port->hba->krb_server_hostname;
+       else
+               khostname = pg_krb_server_hostname;
        if (khostname && khostname[0] == '\0')
                khostname = NULL;
 
@@ -691,11 +694,12 @@ pg_krb5_recvauth(Port *port)
        krb5_ticket *ticket;
        char       *kusername;
        char       *cp;
+       char       *realmmatch;
 
        if (get_role_line(port->user_name) == NULL)
                return STATUS_ERROR;
 
-       ret = pg_krb5_init();
+       ret = pg_krb5_init(port);
        if (ret != STATUS_OK)
                return ret;
 
@@ -736,25 +740,30 @@ pg_krb5_recvauth(Port *port)
                return STATUS_ERROR;
        }
 
+       if (port->hba->krb_realm)
+               realmmatch = port->hba->krb_realm;
+       else
+               realmmatch = pg_krb_realm;
+
        cp = strchr(kusername, '@');
        if (cp)
        {
                *cp = '\0';
                cp++;
 
-               if (pg_krb_realm != NULL && strlen(pg_krb_realm))
+               if (realmmatch != NULL && strlen(realmmatch))
                {
                        /* Match realm against configured */
                        if (pg_krb_caseins_users)
-                               ret = pg_strcasecmp(pg_krb_realm, cp);
+                               ret = pg_strcasecmp(realmmatch, cp);
                        else
-                               ret = strcmp(pg_krb_realm, cp);
+                               ret = strcmp(realmmatch, cp);
 
                        if (ret)
                        {
                                elog(DEBUG2,
                                         "krb5 realm (%s) and configured realm (%s) don't match",
-                                        cp, pg_krb_realm);
+                                        cp, realmmatch);
 
                                krb5_free_ticket(pg_krb5_context, ticket);
                                krb5_auth_con_free(pg_krb5_context, auth_context);
@@ -762,7 +771,7 @@ pg_krb5_recvauth(Port *port)
                        }
                }
        }
-       else if (pg_krb_realm && strlen(pg_krb_realm))
+       else if (realmmatch && strlen(realmmatch))
        {
                elog(DEBUG2,
                         "krb5 did not return realm but realm matching was requested");
@@ -859,6 +868,7 @@ pg_GSS_recvauth(Port *port)
        int                     ret;
        StringInfoData buf;
        gss_buffer_desc gbuf;
+       char       *realmmatch;
 
        /*
         * GSS auth is not supported for protocol versions before 3, because it
@@ -1018,6 +1028,11 @@ pg_GSS_recvauth(Port *port)
                                         gettext_noop("retrieving GSS user name failed"),
                                         maj_stat, min_stat);
 
+       if (port->hba->krb_realm)
+               realmmatch = port->hba->krb_realm;
+       else
+               realmmatch = pg_krb_realm;
+
        /*
         * Split the username at the realm separator
         */
@@ -1028,28 +1043,28 @@ pg_GSS_recvauth(Port *port)
                *cp = '\0';
                cp++;
 
-               if (pg_krb_realm != NULL && strlen(pg_krb_realm))
+               if (realmmatch != NULL && strlen(realmmatch))
                {
                        /*
                         * Match the realm part of the name first
                         */
                        if (pg_krb_caseins_users)
-                               ret = pg_strcasecmp(pg_krb_realm, cp);
+                               ret = pg_strcasecmp(realmmatch, cp);
                        else
-                               ret = strcmp(pg_krb_realm, cp);
+                               ret = strcmp(realmmatch, cp);
 
                        if (ret)
                        {
                                /* GSS realm does not match */
                                elog(DEBUG2,
                                   "GSSAPI realm (%s) and configured realm (%s) don't match",
-                                        cp, pg_krb_realm);
+                                        cp, realmmatch);
                                gss_release_buffer(&lmin_s, &gbuf);
                                return STATUS_ERROR;
                        }
                }
        }
-       else if (pg_krb_realm && strlen(pg_krb_realm))
+       else if (realmmatch && strlen(realmmatch))
        {
                elog(DEBUG2,
                         "GSSAPI did not return realm but realm matching was requested");
@@ -1113,6 +1128,7 @@ pg_SSPI_recvauth(Port *port)
        SID_NAME_USE accountnameuse;
        HMODULE         secur32;
        QUERY_SECURITY_CONTEXT_TOKEN_FN _QuerySecurityContextToken;
+       char       *realmmatch;
 
        /*
         * SSPI auth is not supported for protocol versions before 3, because it
@@ -1325,13 +1341,18 @@ pg_SSPI_recvauth(Port *port)
         * Compare realm/domain if requested. In SSPI, always compare case
         * insensitive.
         */
-       if (pg_krb_realm && strlen(pg_krb_realm))
+       if (port->hba->krb_realm)
+               realmmatch = port->hba->krb_realm;
+       else
+               realmmatch = pg_krb_realm;
+
+       if (realmmatch && strlen(realmmatch))
        {
-               if (pg_strcasecmp(pg_krb_realm, domainname))
+               if (pg_strcasecmp(realmmatch, domainname))
                {
                        elog(DEBUG2,
                                 "SSPI domain (%s) and configured domain (%s) don't match",
-                                domainname, pg_krb_realm);
+                                domainname, realmmatch);
 
                        return STATUS_ERROR;
                }
index 45edaa9..e7068b1 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.178 2009/01/02 11:34:03 mha Exp $
+ *       $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.179 2009/01/07 12:38:11 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1040,6 +1040,19 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
                                REQUIRE_AUTH_OPTION(uaLDAP, "ldapsuffix", "ldap");
                                parsedline->ldapsuffix = pstrdup(c);
                        }
+                       else if (strcmp(token, "krb_server_hostname") == 0)
+                       {
+                               REQUIRE_AUTH_OPTION(uaKrb5, "krb_server_hostname", "krb5");
+                               parsedline->krb_server_hostname = pstrdup(c);
+                       }
+                       else if (strcmp(token, "krb_realm") == 0)
+                       {
+                               if (parsedline->auth_method != uaKrb5 &&
+                                       parsedline->auth_method != uaGSS &&
+                                       parsedline->auth_method != uaSSPI)
+                                       INVALID_AUTH_OPTION("krb_realm", "krb5, gssapi and sspi");
+                               parsedline->krb_realm = pstrdup(c);
+                       }
                        else
                        {
                                ereport(LOG,
@@ -1242,6 +1255,10 @@ free_hba_record(HbaLine *record)
                pfree(record->ldapprefix);
        if (record->ldapsuffix)
                pfree(record->ldapsuffix);
+       if (record->krb_server_hostname)
+               pfree(record->krb_server_hostname);
+       if (record->krb_realm)
+               pfree(record->krb_realm);
 }
 
 /*
index 87d0464..53ecde2 100644 (file)
@@ -4,7 +4,7 @@
  *       Interface to hba.c
  *
  *
- * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.53 2008/11/20 11:48:26 mha Exp $
+ * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.54 2009/01/07 12:38:11 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -56,6 +56,8 @@ typedef struct
        char       *ldapprefix;
        char       *ldapsuffix;
        bool            clientcert;
+       char       *krb_server_hostname;
+       char       *krb_realm;
 } HbaLine;
 
 typedef struct Port hbaPort;