On Tue, Mar 18, 2025 at 12:32 PM Peter Eisentraut <pe...@eisentraut.org> wrote:
> Yeah, I think option (2) is enough for now.  If someone wants to enable
> the kinds of things you describe, they can always come back and
> implement option (1) later.

Sounds good to me.

--

Notes on v8:

- The following documentation pieces need to be adjusted, now that
we've decided that `use_scram_passthrough` will enforce
`require_auth=scram-sha-256`:

> +       The remote server must request SCRAM authentication.  (If desired,
> +       enforce this on the client side (FDW side) with the option
> +       <literal>require_auth</literal>.)  If another authentication method is
> +       requested by the server, then that one will be used normally.

and

> +      The user mapping password is not used.  (It could be set to support 
> other
> +      authentication methods, but that would arguably violate the point of 
> this
> +      feature, which is to avoid storing plain-text passwords.)

I think they should just be reduced to "The remote server must request
SCRAM authentication." and "The user mapping password is not used."

- In get_connect_string():

> +   /* first gather the server connstr options */
> +   Oid         serverid = foreign_server->serverid;

I think this comment belongs elsewhere (connect_pg_server) and should
be deleted from this block.

- Sorry for not realizing this before now, but I couldn't figure out
why connect_pg_server() took the rconn pointer, and it turns out it
just passes it along to dblink_security_check(), which pfree's it
before throwing an error. So that will double-free with the current
refactoring patch (and I'm not sure why assertions aren't catching
that?).

I thought for sure this inconsistency would be a problem on HEAD, but
it turns out that rconn is set to NULL in the code path where it would
be a bug... How confusing.

Now that we handle the pfree() in PG_CATCH instead, that lower-level
pfree should be removed, and then connect_pg_server() doesn't need to
take an rconn pointer at all. For extra credit you could maybe move
the allocation of rconn down below the call to connect_pg_server(),
and get rid of the try/catch?

> +   /* Verify the set of connection parameters. */
>     dblink_connstr_check(connstr);
> ...
> +   /* Perform post-connection security checks. */
>     dblink_security_check(conn, rconn, connstr);

- These comment additions probably belong in 0001 rather than 0002.

- As discussed offlist, 0002 needs pgperltidy'd rather than perltidy'd.

- I have attached some additional nitpicky comment edits and
whitespace changes as a diff; pick and choose as desired.

Thanks!
--Jacob
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 50959c4f5bb..d333f1c5429 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -2567,14 +2567,14 @@ deleteConnection(const char *name)
 }
 
  /*
-  * Ensure that require_auth and scram keys are correctly set on connstr.
-  * SCRAM keys used to pass-through is coming from the initial connection from
-  * the client with the server.
+  * Ensure that require_auth and SCRAM keys are correctly set on connstr.
+  * SCRAM keys used to pass-through are coming from the initial connection
+  * from the client with the server.
   *
-  * All required scram options is set by ourself, so we just need to ensure
+  * All required SCRAM options are set by dblink, so we just need to ensure
   * that these options are not overwritten by the user.
   *
-  * See appendSCRAMKeysInfo and it's usage for more.
+  * See appendSCRAMKeysInfo and its usage for more.
   */
 bool
 dblink_connstr_has_required_scram_options(const char *connstr)
@@ -2645,13 +2645,13 @@ dblink_security_check(PGconn *conn, remoteConn *rconn, 
const char *connstr)
                return;
 
        /*
-        * Password was not used to connect, check if scram pass-through is in
+        * Password was not used to connect, check if SCRAM pass-through is in
         * use.
         *
         * If dblink_connstr_has_required_scram_options is true we assume that
-        * UseScramPassthrough is also true because the required scram keys is
+        * UseScramPassthrough is also true because the required SCRAM keys are
         * only added if UseScramPassthrough is set, and the user is not allowed
-        * to add the scram keys on fdw and user mapping options.
+        * to add the SCRAM keys on fdw and user mapping options.
         */
        if (MyProcPort->has_scram_keys && 
dblink_connstr_has_required_scram_options(connstr))
                return;
@@ -2710,12 +2710,12 @@ dblink_connstr_has_pw(const char *connstr)
 /*
  * For non-superusers, insist that the connstr specify a password, except if
  * GSSAPI credentials have been delegated (and we check that they are used for
- * the connection in dblink_security_check later) or if scram pass-through is
+ * the connection in dblink_security_check later) or if SCRAM pass-through is
  * being used.  This prevents a password or GSSAPI credentials from being
  * picked up from .pgpass, a service file, the environment, etc.  We don't want
  * the postgres user's passwords or Kerberos credentials to be accessible to
- * non-superusers. In case of scram pass-through insist that the connstr
- * has the required scram pass-through options.
+ * non-superusers. In case of SCRAM pass-through insist that the connstr
+ * has the required SCRAM pass-through options.
  */
 static void
 dblink_connstr_check(const char *connstr)
@@ -2729,7 +2729,6 @@ dblink_connstr_check(const char *connstr)
        if (MyProcPort->has_scram_keys && 
dblink_connstr_has_required_scram_options(connstr))
                return;
 
-
 #ifdef ENABLE_GSS
        if (be_gssapi_get_delegation(MyProcPort))
                return;
@@ -2876,8 +2875,8 @@ get_connect_string(ForeignServer *foreign_server)
 
        /*
         * First append hardcoded options needed for SCRAM pass-through, so if 
the
-        * user overwrite these options we can ereport on dblink_connstr_check 
and
-        * dblink_security_check.
+        * user overwrites these options we can ereport on dblink_connstr_check
+        * and dblink_security_check.
         */
        if (MyProcPort->has_scram_keys && UseScramPassthrough(foreign_server, 
user_mapping))
                appendSCRAMKeysInfo(&buf);
@@ -3063,7 +3062,6 @@ is_valid_dblink_option(const PQconninfoOption *options, 
const char *option,
        return true;
 }
 
-
 /*
  * Same as is_valid_dblink_option but also check for only dblink_fdw specific
  * options.
@@ -3078,7 +3076,6 @@ is_valid_dblink_fdw_option(const PQconninfoOption 
*options, const char *option,
        return is_valid_dblink_option(options, option, context);
 }
 
-
 /*
  * Copy the remote session's values of GUCs that affect datatype I/O
  * and apply them locally in a new GUC nesting level.  Returns the new
@@ -3161,7 +3158,6 @@ appendSCRAMKeysInfo(StringInfo buf)
        char       *client_key;
        char       *server_key;
 
-
        len = pg_b64_enc_len(sizeof(MyProcPort->scram_ClientKey));
        /* don't forget the zero-terminator */
        client_key = palloc0(len + 1);
diff --git a/doc/src/sgml/dblink.sgml b/doc/src/sgml/dblink.sgml
index e3b4129ae26..9cbcf645e78 100644
--- a/doc/src/sgml/dblink.sgml
+++ b/doc/src/sgml/dblink.sgml
@@ -136,7 +136,7 @@ dblink_connect(text connname, text connstr) returns text
    </para>
   </refsect1>
 
-<refsect1>
+  <refsect1>
    <title>Foreign Data Wrapper</title>
 
    <para>
@@ -208,8 +208,6 @@ dblink_connect(text connname, text connstr) returns text
     </listitem>
     </itemizedlist>
    </para>
-
-
   </refsect1>
 
   <refsect1>
@@ -257,7 +255,7 @@ SELECT dblink_connect('myconn', 'dbname=postgres 
options=-csearch_path=');
 (1 row)
 
 -- FOREIGN DATA WRAPPER functionality
--- Note: local connection that don't use SCRAM pass-through require password
+-- Note: local connections that don't use SCRAM pass-through require password
 --       authentication for this to work properly. Otherwise, you will receive
 --       the following error from dblink_connect():
 --       ERROR:  password is required

Reply via email to