public inbox for [email protected]  
help / color / mirror / Atom feed
From: Jim Jones <[email protected]>
To: PostgreSQL Hackers <[email protected]>
Subject: Authentication fails for md5 connections if ~/.postgresql/postgresql.{crt and key} exist
Date: Fri, 9 Dec 2022 13:55:25 +0100
Message-ID: <[email protected]> (raw)

Dear PostgreSQL Hackers,

Some time ago we faced a small issue in libpq regarding connections 
configured in the pg_hba.conf as type *hostssl* and using *md5* as 
authentication method.

One of our users placed the client certificates in ~/.postgresql/ 
(*postgresql.crt,**postgresql.key*), so that libpq sends them to the 
server without having to manually set *sslcert* and *sslkey* - which is 
quite convenient. However, there are other servers where the same user 
authenticates with password (md5), but libpq still sends the client 
certificates for authentication by default. This causes the 
authentication to fail even before the user has the chance to enter his 
password, since he has no certificate registered in the server.

To make it clearer:

Although the connection is configured as ...

*host  all  dummyuser 192.168.178.42/32  md5
*

... and the client uses the following connection string ...

*psql "host=myserver dbname=db user=***dummyuser*" *

... the server tries to authenticate the user using the client 
certificates in *~/.postgresql/* and, as expected, the authentication fails:

*psql: error: connection to server at "myserver" (xx.xx.xx.xx), port 
5432 failed: SSL error: tlsv1 alert unknown ca*

Server log:
**

*2022-12-09 10:50:59.376 UTC [13896] LOG:  could not accept SSL 
connection: certificate verify failed
*

Am I missing something?**

Obviously it would suffice to just remove or rename 
*~/.postgresql/**postgresql.{crt,key}*, but the user needs them to 
authenticate in other servers. So we came up with the workaround to 
create a new sslmode (no-clientcert) to make libpq explicitly ignore the 
client certificates, so that we can avoid ssl authentication errors. 
These small changes can be seen in the patch file attached.

*psql "host=myserver dbname=db user=****dummyuser** 
sslrootcert=server.crt sslmode=no-clientcert"*

Any better ideas to make libpq ignore 
*~/.postgresql/**postgresql.{crt,key}***? Preferably without having to 
change the source code :) Thanks in advance!

Best,

Jim


Attachments:

  [text/x-patch] v1-0001-add-sslmode-no-clientcert.patch (2.9K, ../[email protected]/3-v1-0001-add-sslmode-no-clientcert.patch)
  download | inline diff:
From 8013619a1ee2187fce289054a846e17a5414801d Mon Sep 17 00:00:00 2001
From: Jim Jones <[email protected]>
Date: Mon, 21 Nov 2022 15:05:33 +0100
Subject: [PATCH v1] add sslmode no-clientcert

---
 doc/src/sgml/libpq.sgml                  | 11 +++++++++
 src/interfaces/libpq/fe-connect.c        |  1 +
 src/interfaces/libpq/fe-secure-openssl.c | 29 +++++++++++++++++++++++-
 3 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index f9558dec3b..aa14253f7e 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -8638,6 +8638,17 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
       </entry>
      </row>
 
+     <row>
+      <entry><literal>no-clientcert</literal></entry>
+      <entry>Yes</entry>
+      <entry>Depends on CA policy</entry>
+      <entry>I want my data encrypted, and I accept the overhead. I want to be
+       sure that I connect to a server that I trust, but I do not wish to 
+       authenticate the client using ssl certificates.
+      </entry>
+     </row>
+     
+     
      <row>
       <entry><literal>verify-ca</literal></entry>
       <entry>Yes</entry>
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index f88d672c6c..08c7f21ec1 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -1268,6 +1268,7 @@ connectOptions2(PGconn *conn)
 			&& strcmp(conn->sslmode, "allow") != 0
 			&& strcmp(conn->sslmode, "prefer") != 0
 			&& strcmp(conn->sslmode, "require") != 0
+			&& strcmp(conn->sslmode, "no-clientcert") != 0
 			&& strcmp(conn->sslmode, "verify-ca") != 0
 			&& strcmp(conn->sslmode, "verify-full") != 0)
 		{
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index bad85359b6..c092020c5e 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -1098,7 +1098,34 @@ initialize_SSL(PGconn *conn)
 	if (conn->sslcert && strlen(conn->sslcert) > 0)
 		strlcpy(fnbuf, conn->sslcert, sizeof(fnbuf));
 	else if (have_homedir)
-		snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
+	{
+
+		/* sslmode no-clientcert */
+		if (conn->sslmode[0] == 'n')
+		{
+
+			/*
+			 * The option "no-clientcert" ignores the client certificate in case they are
+			 * stored in ~/.postgresql/postgresql.crt and ~/.postgresql/postgresql.key,
+			 * and therefore automatically sent to the server. This is useful for
+			 * pg_hba.conf entries of type "hostssl" without "cert" as authentication
+			 * method - e.g. using "md5" or "scram-sha-256" - as they will fail if
+			 * the client certificate is sent to the server in the background and it
+			 * does not exist in the server's 'ssl_ca_file'.
+			 */
+
+			fnbuf[0] = '\0';
+
+		}
+		else
+		{
+
+			snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
+
+		}
+
+
+	}
 	else
 		fnbuf[0] = '\0';
 
-- 
2.25.1



view thread (2+ messages)

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected]
  Subject: Re: Authentication fails for md5 connections if ~/.postgresql/postgresql.{crt and key} exist
  In-Reply-To: <[email protected]>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox