]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix up usage of krb_server_keyfile GUC parameter.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 30 Dec 2020 16:38:42 +0000 (11:38 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 30 Dec 2020 16:38:42 +0000 (11:38 -0500)
secure_open_gssapi() installed the krb_server_keyfile setting as
KRB5_KTNAME unconditionally, so long as it's not empty.  However,
pg_GSS_recvauth() only installed it if KRB5_KTNAME wasn't set already,
leading to a troubling inconsistency: in theory, clients could see
different sets of server principal names depending on whether they
use GSSAPI encryption.  Always using krb_server_keyfile seems like
the right thing, so make both places do that.  Also fix up
secure_open_gssapi()'s lack of a check for setenv() failure ---
it's unlikely, surely, but security-critical actions are no place
to be sloppy.

Also improve the associated documentation.

This patch does nothing about secure_open_gssapi()'s use of setenv(),
and indeed causes pg_GSS_recvauth() to use it too.  That's nominally
against project portability rules, but since this code is only built
with --with-gssapi, I do not feel a need to do something about this
in the back branches.  A fix will be forthcoming for HEAD though.

Back-patch to v12 where GSSAPI encryption was introduced.  The
dubious behavior in pg_GSS_recvauth() goes back further, but it
didn't have anything to be inconsistent with, so let it be.

Discussion: https://postgr.es/m/2187460.1609263156@sss.pgh.pa.us

doc/src/sgml/client-auth.sgml
doc/src/sgml/config.sgml
src/backend/libpq/auth.c
src/backend/libpq/be-secure-gssapi.c
src/backend/utils/misc/postgresql.conf.sample

index 9a5c9318cee42001a202d4e290f2951d43ee6d6c..c4b9971a206cc43d4cb360df1e58c3fc37ad91e0 100644 (file)
@@ -1265,11 +1265,7 @@ omicron         bryanh                  guest1
 
    <para>
     The location of the server's keytab file is specified by the <xref
-    linkend="guc-krb-server-keyfile"/> configuration
-    parameter. The default is
-    <filename>FILE:/usr/local/pgsql/etc/krb5.keytab</filename>
-    (where the directory part is whatever was specified
-    as <varname>sysconfdir</varname> at build time).
+    linkend="guc-krb-server-keyfile"/> configuration parameter.
     For security reasons, it is recommended to use a separate keytab
     just for the <productname>PostgreSQL</productname> server rather
     than allowing the server to read the system keytab file.
index 048bd6aa08a6bd4f6b354508c1234f912d2e125e..67de4150b8e48b9759c07b3111a5a7a80201ffc6 100644 (file)
@@ -1057,10 +1057,16 @@ include_dir 'conf.d'
       </term>
       <listitem>
        <para>
-        Sets the location of the Kerberos server key file. See
-        <xref linkend="gssapi-auth"/>
-        for details. This parameter can only be set in the
+        Sets the location of the server's Kerberos key file.  The default is
+        <filename>FILE:/usr/local/pgsql/etc/krb5.keytab</filename>
+        (where the directory part is whatever was specified
+        as <varname>sysconfdir</varname> at build time; use
+        <literal>pg_config --sysconfdir</literal> to determine that).
+        If this parameter is set to an empty string, it is ignored and a
+        system-dependent default is used.
+        This parameter can only be set in the
         <filename>postgresql.conf</filename> file or on the server command line.
+        See <xref linkend="gssapi-auth"/> for more information.
        </para>
       </listitem>
      </varlistentry>
index 515ae95fe109ad7907db84b942f68f4c8f0fac47..e51ede5a2228f91d26463a47fcf3de80a475efab 100644 (file)
@@ -1054,29 +1054,18 @@ pg_GSS_recvauth(Port *port)
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                 errmsg("GSSAPI is not supported in protocol version 2")));
 
-       if (pg_krb_server_keyfile && strlen(pg_krb_server_keyfile) > 0)
+       /*
+        * Use the configured keytab, if there is one.  Unfortunately, Heimdal
+        * doesn't support the cred store extensions, so use the env var.
+        */
+       if (pg_krb_server_keyfile != NULL && pg_krb_server_keyfile[0] != '\0')
        {
-               /*
-                * Set default Kerberos keytab file for the Krb5 mechanism.
-                *
-                * setenv("KRB5_KTNAME", pg_krb_server_keyfile, 0); except setenv()
-                * not always available.
-                */
-               if (getenv("KRB5_KTNAME") == NULL)
+               if (setenv("KRB5_KTNAME", pg_krb_server_keyfile, 1) != 0)
                {
-                       size_t          kt_len = strlen(pg_krb_server_keyfile) + 14;
-                       char       *kt_path = malloc(kt_len);
-
-                       if (!kt_path ||
-                               snprintf(kt_path, kt_len, "KRB5_KTNAME=%s",
-                                                pg_krb_server_keyfile) != kt_len - 2 ||
-                               putenv(kt_path) != 0)
-                       {
-                               ereport(LOG,
-                                               (errcode(ERRCODE_OUT_OF_MEMORY),
-                                                errmsg("out of memory")));
-                               return STATUS_ERROR;
-                       }
+                       /* The only likely failure cause is OOM, so use that errcode */
+                       ereport(FATAL,
+                                       (errcode(ERRCODE_OUT_OF_MEMORY),
+                                        errmsg("could not set environment: %m")));
                }
        }
 
index 1747fccb143e217ded37c15d9a3df6d0568457e6..547c7d6a177bd23f49016febc739ec83c74d6999 100644 (file)
@@ -525,8 +525,16 @@ secure_open_gssapi(Port *port)
         * Use the configured keytab, if there is one.  Unfortunately, Heimdal
         * doesn't support the cred store extensions, so use the env var.
         */
-       if (pg_krb_server_keyfile != NULL && strlen(pg_krb_server_keyfile) > 0)
-               setenv("KRB5_KTNAME", pg_krb_server_keyfile, 1);
+       if (pg_krb_server_keyfile != NULL && pg_krb_server_keyfile[0] != '\0')
+       {
+               if (setenv("KRB5_KTNAME", pg_krb_server_keyfile, 1) != 0)
+               {
+                       /* The only likely failure cause is OOM, so use that errcode */
+                       ereport(FATAL,
+                                       (errcode(ERRCODE_OUT_OF_MEMORY),
+                                        errmsg("could not set environment: %m")));
+               }
+       }
 
        while (true)
        {
index b7fb2ec1feb6bf00c493adc0156e9cfa67f4a3be..5298e18ecd5589919969d81e529ed4aa86b00e8d 100644 (file)
@@ -92,7 +92,7 @@
 #db_user_namespace = off
 
 # GSSAPI using Kerberos
-#krb_server_keyfile = ''
+#krb_server_keyfile = 'FILE:${sysconfdir}/krb5.keytab'
 #krb_caseins_users = off
 
 # - SSL -