Add hba parameter include_realm to krb5, gss and sspi authentication, used
authorMagnus Hagander <magnus@hagander.net>
Wed, 7 Jan 2009 13:09:21 +0000 (13:09 +0000)
committerMagnus Hagander <magnus@hagander.net>
Wed, 7 Jan 2009 13:09:21 +0000 (13:09 +0000)
to pass the full username@realm string to the authentication instead of
just the username. This makes it possible to use pg_ident.conf to authenticate
users from multiple realms as different database users.

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

index e1bb7158bf5405d1c3fd6af629d1ef6409dce59e..68cade19ecf70b0998421605bbda3db3326a1411 100644 (file)
@@ -785,6 +785,18 @@ omicron       bryanh            guest1
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term>include_realm</term>
+      <listitem>
+       <para>
+        Include the realm name from the authenticated user principal. This is useful
+        in combination with Username maps (See <xref linkend="auth-username-maps">
+        for details), especially with regular expressions, to map users from
+        multiple realms.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term>krb_realm</term>
       <listitem>
@@ -846,6 +858,18 @@ omicron       bryanh            guest1
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term>include_realm</term>
+      <listitem>
+       <para>
+        Include the realm name from the authenticated user principal. This is useful
+        in combination with Username maps (See <xref linkend="auth-username-maps">
+        for details), especially with regular expressions, to map users from
+        multiple realms.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term>krb_realm</term>
       <listitem>
index a0545e8d85b3d0bcc920412bd693c2ed25b6fabf..fc3de097fee531ae43430855044ba279624f6dc4 100644 (file)
@@ -748,7 +748,13 @@ pg_krb5_recvauth(Port *port)
        cp = strchr(kusername, '@');
        if (cp)
        {
-               *cp = '\0';
+               /*
+                * If we are not going to include the realm in the username that is passed
+                * to the ident map, destructively modify it here to remove the realm. Then
+                * advance past the separator to check the realm.
+                */
+               if (!port->hba->include_realm)
+                       *cp = '\0';
                cp++;
 
                if (realmmatch != NULL && strlen(realmmatch))
@@ -1040,7 +1046,13 @@ pg_GSS_recvauth(Port *port)
        {
                char       *cp = strchr(gbuf.value, '@');
 
-               *cp = '\0';
+               /*
+                * If we are not going to include the realm in the username that is passed
+                * to the ident map, destructively modify it here to remove the realm. Then
+                * advance past the separator to check the realm.
+                */
+               if (!port->hba->include_realm)
+                       *cp = '\0';
                cp++;
 
                if (realmmatch != NULL && strlen(realmmatch))
@@ -1361,8 +1373,22 @@ pg_SSPI_recvauth(Port *port)
        /*
         * We have the username (without domain/realm) in accountname, compare to
         * the supplied value. In SSPI, always compare case insensitive.
+        *
+        * If set to include realm, append it in <username>@<realm> format.
         */
-       return check_usermap(port->hba->usermap, port->user_name, accountname, true);
+       if (port->hba->include_realm)
+       {
+               char   *namebuf;
+               int             retval;
+
+               namebuf = palloc(strlen(accountname) + strlen(domainname) + 2);
+               sprintf(namebuf, "%s@%s", accountname, domainname);
+               retval = check_usermap(port->hba->usermap, port->user_name, namebuf, true);
+               pfree(namebuf);
+               return retval;
+       }
+       else
+               return check_usermap(port->hba->usermap, port->user_name, accountname, true);
 }
 #endif   /* ENABLE_SSPI */
 
index 0d83cceb8981b7e3a46d57113da56aea914a278b..a134b4565b1247f0ee1d7c1a8d907609f20ff15a 100644 (file)
@@ -1053,6 +1053,17 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
                                        INVALID_AUTH_OPTION("krb_realm", "krb5, gssapi and sspi");
                                parsedline->krb_realm = pstrdup(c);
                        }
+                       else if (strcmp(token, "include_realm") == 0)
+                       {
+                               if (parsedline->auth_method != uaKrb5 &&
+                                       parsedline->auth_method != uaGSS &&
+                                       parsedline->auth_method != uaSSPI)
+                                       INVALID_AUTH_OPTION("include_realm", "krb5, gssapi and sspi");
+                               if (strcmp(c, "1") == 0)
+                                       parsedline->include_realm = true;
+                               else
+                                       parsedline->include_realm = false;
+                       }
                        else
                        {
                                ereport(LOG,
index 522a3b96df96ca4512b553e8d62f4317e3c80c0b..c766352caa91a1e9ddbafd6df0b99fbd174b6cf8 100644 (file)
@@ -58,6 +58,7 @@ typedef struct
        bool            clientcert;
        char       *krb_server_hostname;
        char       *krb_realm;
+       bool            include_realm;
 } HbaLine;
 
 typedef struct Port hbaPort;