Hackers,

I noticed recently that permissions checking is done differently for the server certificate key than the client key. Specifically, on the server the key can have 640 perms if it is owned by root.

On the server side this change was made in 9a83564c and I think the same rational applies equally well to the client key. At the time managed keys on the client may not have been common but they are now.

Attached is a patch to make this change.

I was able to this this manually by hacking 001_ssltests.pl like so:

-       chmod 0640, "ssl/${key}_tmp.key"
+       chmod 0600, "ssl/${key}_tmp.key"
          or die "failed to change permissions on ssl/${key}_tmp.key: $!";
-       system_or_bail("sudo chown root ssl/${key}_tmp.key");

But this is clearly not going to work for general purpose testing. The server keys also not tested for root ownership so perhaps we do not need that here either.

I looked at trying to make this code common between the server and client but due to the differences in error reporting it seemed like more trouble than it was worth.

Regards,
--
-David
da...@pgmasters.net
diff --git a/src/interfaces/libpq/fe-secure-openssl.c 
b/src/interfaces/libpq/fe-secure-openssl.c
index 3a7cc8f774..285e772170 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -1234,11 +1234,38 @@ initialize_SSL(PGconn *conn)
                                                          fnbuf);
                        return -1;
                }
+
+               /*
+               * Refuse to load key files owned by users other than us or root.
+               *
+               * XXX surely we can check this on Windows somehow, too.
+               */
+#ifndef WIN32
+               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;
+               }
+#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.
+               */
 #ifndef WIN32
-               if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO))
+               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;
                }

Reply via email to