summaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/fe-connect.c
diff options
context:
space:
mode:
authorDaniel Gustafsson <dgustafsson@postgresql.org>2023-04-05 23:22:17 +0200
committerDaniel Gustafsson <dgustafsson@postgresql.org>2023-04-05 23:22:17 +0200
commit8eda7314652703a2ae30d6c4a69c378f6813a7f2 (patch)
tree0dfd6463eabef599134238781f3c59e4b031b733 /src/interfaces/libpq/fe-connect.c
parent12f3867f5534754c8bac5af35228d4079edc3a00 (diff)
Allow to use system CA pool for certificate verification
This adds a new option to libpq's sslrootcert, "system", which will load the system trusted CA roots for certificate verification. This is a more convenient way to achieve this than pointing to the system CA roots manually since the location can differ by installation and be locally adjusted by env vars in OpenSSL. When sslrootcert is set to system, sslmode is forced to be verify-full as weaker modes aren't providing much security for public CAs. Changing the location of the system roots by setting environment vars is not supported by LibreSSL so the tests will use a heuristic to determine if the system being tested is LibreSSL or OpenSSL. The workaround in .cirrus.yml is required to handle a strange interaction between homebrew and the openssl@3 formula; hopefully this can be removed in the near future. The original patch was written by Thomas Habets, which was later revived by Jacob Champion. Author: Jacob Champion <jchampion@timescale.com> Author: Thomas Habets <thomas@habets.se> Reviewed-by: Jelte Fennema <postgres@jeltef.nl> Reviewed-by: Andrew Dunstan <andrew@dunslane.net> Reviewed-by: Magnus Hagander <magnus@hagander.net> Discussion: https://www.postgresql.org/message-id/flat/CA%2BkHd%2BcJwCUxVb-Gj_0ptr3_KZPwi3%2B67vK6HnLFBK9MzuYrLA%40mail.gmail.com
Diffstat (limited to 'src/interfaces/libpq/fe-connect.c')
-rw-r--r--src/interfaces/libpq/fe-connect.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index bb7347cb0c0..40fef0e2c81 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -1465,6 +1465,23 @@ connectOptions2(PGconn *conn)
goto oom_error;
}
+#ifndef USE_SSL
+
+ /*
+ * sslrootcert=system is not supported. Since setting this changes the
+ * default sslmode, check this _before_ we validate sslmode, to avoid
+ * confusing the user with errors for an option they may not have set.
+ */
+ if (conn->sslrootcert
+ && strcmp(conn->sslrootcert, "system") == 0)
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "sslrootcert value \"%s\" invalid when SSL support is not compiled in",
+ conn->sslrootcert);
+ return false;
+ }
+#endif
+
/*
* validate sslmode option
*/
@@ -1511,6 +1528,22 @@ connectOptions2(PGconn *conn)
goto oom_error;
}
+#ifdef USE_SSL
+
+ /*
+ * If sslrootcert=system, make sure our chosen sslmode is compatible.
+ */
+ if (conn->sslrootcert
+ && strcmp(conn->sslrootcert, "system") == 0
+ && strcmp(conn->sslmode, "verify-full") != 0)
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslrootcert=system (use verify-full)",
+ conn->sslmode);
+ return false;
+ }
+#endif
+
/*
* Validate TLS protocol versions for ssl_min_protocol_version and
* ssl_max_protocol_version.
@@ -6236,6 +6269,8 @@ static bool
conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
{
PQconninfoOption *option;
+ PQconninfoOption *sslmode_default = NULL,
+ *sslrootcert = NULL;
char *tmp;
/*
@@ -6252,6 +6287,9 @@ conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
*/
for (option = options; option->keyword != NULL; option++)
{
+ if (strcmp(option->keyword, "sslrootcert") == 0)
+ sslrootcert = option; /* save for later */
+
if (option->val != NULL)
continue; /* Value was in conninfo or service */
@@ -6294,6 +6332,13 @@ conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
}
continue;
}
+
+ /*
+ * sslmode is not specified. Let it be filled in with the compiled
+ * default for now, but if sslrootcert=system, we'll override the
+ * default later before returning.
+ */
+ sslmode_default = option;
}
/*
@@ -6326,6 +6371,27 @@ conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
}
}
+ /*
+ * Special handling for sslrootcert=system with no sslmode explicitly
+ * defined. In this case we want to strengthen the default sslmode to
+ * verify-full.
+ */
+ if (sslmode_default && sslrootcert)
+ {
+ if (sslrootcert->val && strcmp(sslrootcert->val, "system") == 0)
+ {
+ free(sslmode_default->val);
+
+ sslmode_default->val = strdup("verify-full");
+ if (!sslmode_default->val)
+ {
+ if (errorMessage)
+ libpq_append_error(errorMessage, "out of memory");
+ return false;
+ }
+ }
+ }
+
return true;
}