Hi Tom,
On 1/18/22 14:41, Tom Lane wrote:
David Steele <da...@pgmasters.net> writes:
[ client-key-perm-002.patch ]
I took a quick look at this and agree with the proposed behavior
change, but also with your self-criticisms:
We may want to do the same on the server side to make the code blocks
look more similar.
Also, on the server side the S_ISREG() check gets its own error and that
might be a good idea on the client side as well. As it is, the error
message on the client is going to be pretty confusing in this case.
Particularly, I think the S_ISREG check should happen before any
ownership/permissions checks; it just seems saner that way.
The two blocks of code now look pretty much identical except for error
handling and the reference to the other file. Also, the indentation for
the comment on the server side is less but I kept the comment formatting
the same to make it easier to copy the comment back and forth.
The only other nitpick I have is that I'd make the cross-references be
to the two file names, ie like "Note that similar checks are performed
in fe-secure-openssl.c ..." References to the specific functions seem
likely to bit-rot in the face of future code rearrangements.
I suppose filename references could become obsolete too, but it
seems less likely.
Updated these to reference the file instead of the function.
I still don't think we can commit the test for root ownership, but
testing it manually got a whole lot easier after the refactor in
c3b34a0f. Before that you had to hack up the source tree, which is a
pain depending on how it is mounted (I'm testing in a container).
So, to test the new functionality, just add this snippet on line 57 of
001_ssltests.pl:
chmod 0640, "$cert_tempdir/client.key"
or die "failed to change permissions on $cert_tempdir/client.key: $!";
system_or_bail("sudo chown root $cert_tempdir/client.key");
If you can think of a way to add this to the tests I'm all ears. Perhaps
we could add these lines commented out and explain what they are for?
Regards,
-David
diff --git a/src/backend/libpq/be-secure-common.c
b/src/backend/libpq/be-secure-common.c
index 7e9a64d08e..3f00040efe 100644
--- a/src/backend/libpq/be-secure-common.c
+++ b/src/backend/libpq/be-secure-common.c
@@ -143,6 +143,7 @@ check_ssl_key_file_permissions(const char *ssl_key_file,
bool isServerStart)
return false;
}
+ /* Key file must be a regular file */
if (!S_ISREG(buf.st_mode))
{
ereport(loglevel,
@@ -153,10 +154,20 @@ check_ssl_key_file_permissions(const char *ssl_key_file,
bool isServerStart)
}
/*
- * Refuse to load key files owned by users other than us or root.
- *
- * XXX surely we can check this on Windows somehow, too.
- */
+ * Refuse to load key files owned by users other than us or root and
+ * require no public access to the key file. If the file is owned by us,
+ * require mode 0600 or less. If owned by root, require 0640 or less to
+ * allow read access through our gid, or a supplementary gid that allows
+ * us to read system-wide certificates.
+ *
+ * Note that similar checks are performed in
+ * src/interfaces/libpq/fe-secure-openssl.c so any changes here may need
to
+ * be made there as well.
+ *
+ * Ideally we would do similar permissions checks on Windows but it is
+ * not clear how that would work since unix-style permissions may not be
+ * available.
+ */
#if !defined(WIN32) && !defined(__CYGWIN__)
if (buf.st_uid != geteuid() && buf.st_uid != 0)
{
@@ -166,20 +177,7 @@ check_ssl_key_file_permissions(const char *ssl_key_file,
bool isServerStart)
ssl_key_file)));
return false;
}
-#endif
- /*
- * Require no public access to key file. If the file is owned by us,
- * require mode 0600 or less. If owned by root, require 0640 or less to
- * allow read access through our gid, or a supplementary gid that allows
- * to read system-wide certificates.
- *
- * XXX temporarily suppress check when on Windows, because there may not
- * be proper support for Unix-y file permissions. Need to think of a
- * reasonable check to apply on Windows. (See also the data directory
- * permission check in postmaster.c)
- */
-#if !defined(WIN32) && !defined(__CYGWIN__)
if ((buf.st_uid == geteuid() && buf.st_mode & (S_IRWXG | S_IRWXO)) ||
(buf.st_uid == 0 && buf.st_mode & (S_IWGRP | S_IXGRP |
S_IRWXO)))
{
diff --git a/src/interfaces/libpq/fe-secure-openssl.c
b/src/interfaces/libpq/fe-secure-openssl.c
index f6e563a2e5..59e3224f97 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -1245,11 +1245,45 @@ initialize_SSL(PGconn *conn)
fnbuf);
return -1;
}
+
+ /* Key file must be a regular file */
+ if (!S_ISREG(buf.st_mode))
+ {
+ appendPQExpBuffer(&conn->errorMessage,
+
libpq_gettext("private key file \"%s\" is not a regular file"),
+ fnbuf);
+ return -1;
+ }
+
+ /*
+ * Refuse to load key files owned by users other than us or root
and
+ * require no public access to the key file. If the file is
owned by us,
+ * require mode 0600 or less. If owned by root, require 0640 or
less to
+ * allow read access through our gid, or a supplementary gid
that allows
+ * us to read system-wide certificates.
+ *
+ * Note that similar checks are performed in
+ * src/backend/libpq/be-secure-common.c so any changes here may
need to
+ * be made there as well.
+ *
+ * Ideally we would do similar permissions checks on Windows but
it is
+ * not clear how that would work since unix-style permissions
may not be
+ * available.
+ */
#ifndef WIN32
- if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO))
+ if (buf.st_uid != geteuid() && buf.st_uid != 0)
+ {
+ appendPQExpBuffer(&conn->errorMessage,
+
libpq_gettext("private key file \"%s\" must be owned by the current user or
root\n"),
+ fnbuf);
+ return -1;
+ }
+
+ if ((buf.st_uid == geteuid() && buf.st_mode & (S_IRWXG |
S_IRWXO)) ||
+ (buf.st_uid == 0 && buf.st_mode & (S_IWGRP | S_IXGRP |
S_IRWXO)))
{
appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("private key file \"%s\" has group or world access; permissions
should be u=rw (0600) or less\n"),
+
libpq_gettext("private key file \"%s\" has group or world access; file must
have permissions u=rw (0600) or less if owned by the current user, or
permissions u=rw,g=r (0640) or less if owned by root.\n"),
fnbuf);
return -1;
}