diff --git a/src/backend/libpq/be-secure-common.c b/src/backend/libpq/be-secure-common.c index a212308666..c6e4329653 100644 --- a/src/backend/libpq/be-secure-common.c +++ b/src/backend/libpq/be-secure-common.c @@ -155,6 +155,9 @@ 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. * + * Note that a similar check is performed in initialize_SSL() so any changes + * here may need to be made there as well. + * * XXX surely we can check this on Windows somehow, too. */ #if !defined(WIN32) && !defined(__CYGWIN__) @@ -174,6 +177,9 @@ check_ssl_key_file_permissions(const char *ssl_key_file, bool isServerStart) * allow read access through our gid, or a supplementary gid that allows * to read system-wide certificates. * + * Note that a similar check is performed in initialize_SSL() so any changes + * here may need to be made there as well. + * * 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 diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c index a90d891c6c..d581ff6ca5 100644 --- a/src/interfaces/libpq/fe-secure-openssl.c +++ b/src/interfaces/libpq/fe-secure-openssl.c @@ -1240,11 +1240,37 @@ initialize_SSL(PGconn *conn) 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 + * check_ssl_key_file_permissions() so any changes here may need to be + * made there as well. + * + * Ideally we would do similar checks on Windows but it is not clear how + * that would work since unix-style permissions may not be available. See + * also the data directory permissions checks in checkDataDir(). + */ #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 (!S_ISREG(buf.st_mode) || + (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; }