diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 9e63c9164187bd5c1e3e44c77500d648e44d9bbb..2f1a248ca768c42360910e2fb320a67bd8e07f43 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.256 2008/03/06 15:37:56 momjian Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.257 2008/03/31 02:43:14 tgl Exp $ --> <chapter id="libpq"> <title><application>libpq</application> - C Library</title> @@ -5223,11 +5223,13 @@ defaultNoticeProcessor(void *arg, const char *message) authorities (<acronym>CA</acronym>) trusted by the server. A matching private key file <filename>~/.postgresql/postgresql.key</> must also be present, unless the secret key for the certificate is stored in a - hardware token, as specified by <envar>PGSSLKEY</envar>. (On Microsoft - Windows these files are named + hardware token, as specified by <envar>PGSSLKEY</envar>. 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>. + On Microsoft Windows these files are named <filename>%APPDATA%\postgresql\postgresql.crt</filename> and - <filename>%APPDATA%\postgresql\postgresql.key</filename>.) The private - key file must not be world-readable. + <filename>%APPDATA%\postgresql\postgresql.key</filename>, and there + is no special permissions check since the directory is presumed secure. </para> <para> diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 7d89be32fb192229d043714efa300308f3327e8f..1c799d8965b60d60e49474a31d8b1e74ecec0c3e 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.410 2008/03/21 14:23:37 momjian Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.411 2008/03/31 02:43:14 tgl Exp $ --> <chapter Id="runtime"> <title>Operating System Environment</title> @@ -1632,7 +1632,11 @@ $ <userinput>kill -INT `head -1 /usr/local/pgsql/data/postmaster.pid`</userinput To start in <acronym>SSL</> mode, the files <filename>server.crt</> and <filename>server.key</> must exist in the server's data directory. These files should contain the server certificate and private key, - respectively. If the private key is protected with a passphrase, the + respectively. + On Unix systems, the permissions on <filename>server.key</filename> must + disallow any access to world or group; achieve this by the command + <command>chmod 0600 server.key</command>. + If the private key is protected with a passphrase, the server will prompt for the passphrase and will not start until it has been entered. </para> @@ -1731,10 +1735,15 @@ rm privkey.pem Enter the old passphrase to unlock the existing key. Now do: <programlisting> openssl req -x509 -in server.req -text -key server.key -out server.crt -chmod og-rwx server.key </programlisting> to turn the certificate into a self-signed certificate and to copy the key and certificate to where the server will look for them. + Finally do +<programlisting> +chmod og-rwx server.key +</programlisting> + because the server will reject the file if its permissions are more + liberal than this. For more details on how to create your server private key and certificate, refer to the <productname>OpenSSL</> documentation. </para> diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c index 923ad6bcb3daea346d3f9d8661df7d85c3eabdc9..d03694717620969f89a975a8694f7c6f99f7c3fa 100644 --- a/src/backend/libpq/be-secure.c +++ b/src/backend/libpq/be-secure.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.83 2008/01/01 19:45:49 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.84 2008/03/31 02:43:14 tgl Exp $ * * Since the server static private key ($DataDir/server.key) * will normally be stored unencrypted so that the database @@ -735,7 +735,7 @@ initialize_SSL(void) errmsg("could not load server certificate file \"%s\": %s", SERVER_CERT_FILE, SSLerrmessage()))); - if (stat(SERVER_PRIVATE_KEY_FILE, &buf) == -1) + if (stat(SERVER_PRIVATE_KEY_FILE, &buf) != 0) ereport(FATAL, (errcode_for_file_access(), errmsg("could not access private key file \"%s\": %m", @@ -750,13 +750,12 @@ initialize_SSL(void) * directory permission check in postmaster.c) */ #if !defined(WIN32) && !defined(__CYGWIN__) - if (!S_ISREG(buf.st_mode) || (buf.st_mode & (S_IRWXG | S_IRWXO)) || - buf.st_uid != geteuid()) + if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO)) ereport(FATAL, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("unsafe permissions on private key file \"%s\"", + errmsg("private key file \"%s\" has group or world access", SERVER_PRIVATE_KEY_FILE), - errdetail("File must be owned by the database user and must have no permissions for \"group\" or \"other\"."))); + errdetail("Permissions should be u=rw (0600) or less."))); #endif if (!SSL_CTX_use_PrivateKey_file(SSL_context, diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 7a83e075b1898826bf2321a3de5eb0af64f948cd..7c6692b2a5dfd5a7ed5e587f2d497148a7dfe6b2 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.553 2008/03/09 04:56:28 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.554 2008/03/31 02:43:14 tgl Exp $ * * NOTES * @@ -1053,6 +1053,13 @@ checkDataDir(void) DataDir))); } + /* eventual chdir would fail anyway, but let's test ... */ + if (!S_ISDIR(stat_buf.st_mode)) + ereport(FATAL, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("specified data directory \"%s\" is not a directory", + DataDir))); + /* * Check that the directory belongs to my userid; if not, reject. * diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 90f9d4334ee40a6600d1b7c96d1aebdaf83fa084..dd6c988790bee1d64c67b650c80803c625341f39 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.356 2008/01/29 02:06:30 tgl Exp $ + * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.357 2008/03/31 02:43:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -3718,11 +3718,10 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username) } /* If password file cannot be opened, ignore it. */ - if (stat(pgpassfile, &stat_buf) == -1) + if (stat(pgpassfile, &stat_buf) != 0) return NULL; #ifndef WIN32 - if (!S_ISREG(stat_buf.st_mode)) { fprintf(stderr, @@ -3735,7 +3734,7 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username) if (stat_buf.st_mode & (S_IRWXG | S_IRWXO)) { fprintf(stderr, - libpq_gettext("WARNING: password file \"%s\" has world or group read access; permission should be u=rw (0600)\n"), + libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"), pgpassfile); return NULL; } diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c index 3b1f4cee60c1f24675bc1ea6a5a7b66640aaf3ee..4414baba4a82d03d281ef67bf17a2261a0a3a2d8 100644 --- a/src/interfaces/libpq/fe-secure.c +++ b/src/interfaces/libpq/fe-secure.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.103 2008/02/16 21:03:30 momjian Exp $ + * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.104 2008/03/31 02:43:14 tgl Exp $ * * NOTES * [ Most of these notes are wrong/obsolete, but perhaps not all ] @@ -703,7 +703,7 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) { /* read the user key from file */ snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE); - if (stat(fnbuf, &buf) == -1) + if (stat(fnbuf, &buf) != 0) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("certificate present, but not private key file \"%s\"\n"), @@ -712,11 +712,10 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) return 0; } #ifndef WIN32 - if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) || - buf.st_uid != geteuid()) + if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO)) { printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("private key file \"%s\" has wrong permissions\n"), + libpq_gettext("private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"), fnbuf); ERR_pop_to_mark(); return 0;