Allow krb_realm (krb5, gssapi and sspi) and krb_server_hostname (krb5 only)
authorMagnus Hagander
Wed, 7 Jan 2009 12:38:11 +0000 (12:38 +0000)
committerMagnus Hagander
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 8e3b7c17919e4f5b00b2a8ead818cb49403a8ff9..1d0ce45ce7f494b32eab0bb04720163f7cbfe8f5 100644 (file)
@@ -1,4 +1,4 @@
-
+
 
 
  Client Authentication
@@ -784,6 +784,26 @@ omicron       bryanh            guest1
        
       
      
+
+     
+      krb_realm
+      
+       
+        Overrides the  parameter, setting which realm
+        to verify the authenticated user principal against.
+       
+      
+     
+
+     
+      krb_server_hostname
+      
+       
+        Overrides the  parameter, setting which
+        hostname will be used for the server principal when using Kerberos.
+       
+      
+     
     
    
   
@@ -825,6 +845,16 @@ omicron       bryanh            guest1
        
       
      
+
+     
+      krb_realm
+      
+       
+        Overrides the  parameter, setting which realm
+        to verify the authenticated user principal against.
+       
+      
+     
     
    
   
index 9a93e9ac02c11780ec639ed6fdf7052418b007fb..437061c21a23bb385d470d471ff745f9d3ab7b22 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 45edaa9bb8691c1d4f9e500053bc1fc937b167c2..e7068b10b2f388ed0e861dfe624a2070976da2d1 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 87d04640e4b410701d8be533d6247c1a42682934..53ecde2c1662e744091dba37b6662cad07e372fa 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;