diff options
-rw-r--r-- | doc/src/sgml/libpq.sgml | 26 | ||||
-rw-r--r-- | src/backend/libpq/be-secure-common.c | 28 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-secure-openssl.c | 40 |
3 files changed, 69 insertions, 25 deletions
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 14f35d37f66..6659300e3ff 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -8397,24 +8397,36 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*) <para> If the server attempts to verify the identity of the client by requesting the client's leaf certificate, - <application>libpq</application> will send the certificates stored in + <application>libpq</application> will send the certificate(s) stored in file <filename>~/.postgresql/postgresql.crt</filename> in the user's home directory. The certificates must chain to the root certificate trusted by the server. A matching private key file <filename>~/.postgresql/postgresql.key</filename> must also - be present. The private - key file must not allow any access to world or group; achieve this by the - command <command>chmod 0600 ~/.postgresql/postgresql.key</command>. + be present. On Microsoft Windows these files are named <filename>%APPDATA%\postgresql\postgresql.crt</filename> and - <filename>%APPDATA%\postgresql\postgresql.key</filename>, and there - is no special permissions check since the directory is presumed secure. + <filename>%APPDATA%\postgresql\postgresql.key</filename>. The location of the certificate and key files can be overridden by the - connection parameters <literal>sslcert</literal> and <literal>sslkey</literal> or the + connection parameters <literal>sslcert</literal> + and <literal>sslkey</literal>, or by the environment variables <envar>PGSSLCERT</envar> and <envar>PGSSLKEY</envar>. </para> <para> + On Unix systems, the permissions on the private key file must disallow + any access to world or group; achieve this by a command such as + <command>chmod 0600 ~/.postgresql/postgresql.key</command>. + Alternatively, the file can be owned by root and have group read access + (that is, <literal>0640</literal> permissions). That setup is intended + for installations where certificate and key files are managed by the + operating system. The user of <application>libpq</application> should + then be made a member of the group that has access to those certificate + and key files. (On Microsoft Windows, there is no file permissions + check, since the <filename>%APPDATA%\postgresql</filename> directory is + presumed secure.) + </para> + + <para> The first certificate in <filename>postgresql.crt</filename> must be the client's certificate because it must match the client's private key. <quote>Intermediate</quote> certificates can be optionally appended diff --git a/src/backend/libpq/be-secure-common.c b/src/backend/libpq/be-secure-common.c index a212308666a..612f6f3777e 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,9 +154,19 @@ 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. + * 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 either our gid or a supplementary gid that + * allows us to read system-wide certificates. * - * XXX surely we can check this on Windows somehow, too. + * 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 0ad4dfaa9cc..daaf062b2ab 100644 --- a/src/interfaces/libpq/fe-secure-openssl.c +++ b/src/interfaces/libpq/fe-secure-openssl.c @@ -1229,11 +1229,45 @@ initialize_SSL(PGconn *conn) fnbuf); return -1; } -#ifndef WIN32 - if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO)) + + /* 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 either 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. + */ +#if !defined(WIN32) && !defined(__CYGWIN__) + 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; } |