From 8efbc9099667dab31eea3dfb4d61e307175231d8 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson Date: Mon, 8 Feb 2021 23:52:42 +0100 Subject: [PATCH v46 06/10] nss: Documentation Basic documentation of the new API (keypass hooks) as well as config parameters and installation. Additionally there is a section on how to create certificate and keys using the NSS toolchain. --- doc/src/sgml/acronyms.sgml | 33 ++++ doc/src/sgml/config.sgml | 30 ++- doc/src/sgml/installation.sgml | 34 +++- doc/src/sgml/libpq.sgml | 341 +++++++++++++++++++++++++-------- doc/src/sgml/runtime.sgml | 124 +++++++++++- src/backend/libpq/README.SSL | 28 +++ 6 files changed, 497 insertions(+), 93 deletions(-) diff --git a/doc/src/sgml/acronyms.sgml b/doc/src/sgml/acronyms.sgml index 9ed148ab84..4da20cb4d3 100644 --- a/doc/src/sgml/acronyms.sgml +++ b/doc/src/sgml/acronyms.sgml @@ -452,6 +452,28 @@ + + NSPR + + + + Netscape Portable Runtime + + + + + + NSS + + + + Network Security Services + + + + ODBC @@ -550,6 +572,17 @@ + + PKCS#12 + + + + Public-Key Cryptography Standards #12 + + + + PL diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index de77f14573..aa8cc2c8bb 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1310,6 +1310,24 @@ include_dir 'conf.d' + + ssl_database (string) + + ssl_database configuration parameter + + + + + Specifies the name of the file containing the server certificates and + keys when using NSS for + SSL/TLS + connections. This parameter can only be set in the + postgresql.conf file or on the server command + line. + + + + ssl_ciphers (string) @@ -1326,7 +1344,9 @@ include_dir 'conf.d' connections using TLS version 1.2 and lower are affected. There is currently no setting that controls the cipher choices used by TLS version 1.3 connections. The default value is - HIGH:MEDIUM:+3DES:!aNULL. The default is usually a + HIGH:MEDIUM:+3DES:!aNULL for servers which have + been built with OpenSSL as the + SSL library. The default is usually a reasonable choice unless you have specific security requirements. @@ -1538,8 +1558,12 @@ include_dir 'conf.d' Sets an external command to be invoked when a passphrase for decrypting an SSL file such as a private key needs to be obtained. By - default, this parameter is empty, which means the built-in prompting - mechanism is used. + default, this parameter is empty. When the server is using + OpenSSL, this means the built-in prompting + mechanism is used. When using NSS, there is + no default prompting so a blank callback will be used returning an + empty password. This requires that the certificate database hasn't + been created with a password. The command must print the passphrase to the standard output and exit diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml index d38f9bc916..fdf198729e 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -999,14 +999,34 @@ build-postgresql: Build with support for SSL (encrypted) - connections. The only LIBRARY - supported is . This requires the - OpenSSL package to be installed. - configure will check for the required - header files and libraries to make sure that your - OpenSSL installation is sufficient - before proceeding. + connections. LIBRARY must be one of: + + + + to build with OpenSSL support. + This requires the OpenSSL + package to be installed. configure will check + for the required header files and libraries to make sure + your OpenSSL installation is sufficient + before proceeding. + + + + + to build with libnss support. + This requires the NSS package to be installed. + Additionally, NSS requires + NSPR to be installed. configure + will check for the required header files and libraries to make sure that your + NSS installation is sufficient before + proceeding. On systems where nss-config + is not installed in a location that is searched by default, you + must use the option in addition + to this option to indicate where the header files are located. + + + diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index b449c834a9..5dbfe9f98c 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -835,6 +835,12 @@ int callback_fn(char *buf, int size, PGconn *conn); longjmp(...), etc. It must return normally. + + PQsetSSLKeyPassHook_OpenSSL has no effect unless + the server was compiled with OpenSSL + support. + + @@ -851,6 +857,70 @@ PQsslKeyPassHook_OpenSSL_type PQgetSSLKeyPassHook_OpenSSL(void); + + PQgetSSLKeyPassHook_OpenSSL has no effect unless + the server was compiled with OpenSSL + support. + + + + + + + PQsetSSLKeyPassHook_nssPQsetSSLKeyPassHook_nss + + + PQsetSSLKeyPassHook_nss lets an application override + libpq's default handling of password protected + objects in the NSS database using + or interactive prompting. + + +void PQsetSSLKeyPassHook_nss(PQsslKeyPassHook_nss_type hook); + + + The application passes a pointer to a callback function with signature: + +char *callback_fn(PK11SlotInfo *slot, PRBool retry, void *arg); + + which libpq will call + instead of its default + PQdefaultSSLKeyPassHook_nss password handler. The + callback should determine the password for the token and return a + pointer to it. The returned pointer should be allocated with the NSS + PORT_Strdup function. The token for which the + password is requested is recorded in the slot anc can be identified by + calling PK11_GetTokenName. If no password is + known, the callback should return NULL. The memory + will be owned by NSS and should not be + freed. + + + + PQsetSSLKeyPassHook_nss has no effect unless + the server was compiled with NSS support. + + + + + + PQgetSSLKeyPassHook_nssPQgetSSLKeyPassHook_nss + + + PQgetSSLKeyPassHook_nss returns the current + NSS password hook, or NULL + if none has been set. + + +PQsslKeyPassHook_nss_type PQgetSSLKeyPassHook_nss(void); + + + + + PQgetSSLKeyPassHook_nss has no effect unless the + server was compiled with NSS support. + + @@ -1643,23 +1713,25 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname If set to 1, data sent over SSL connections will be compressed. If set to 0, compression will be disabled. The default is 0. This parameter is ignored if a connection without SSL is made. - - - SSL compression is nowadays considered insecure and its use is no - longer recommended. OpenSSL 1.1.0 disables - compression by default, and many operating system distributions - disable it in prior versions as well, so setting this parameter to on - will not have any effect if the server does not accept compression. - PostgreSQL 14 disables compression - completely in the backend. - + longer recommended. + + + + OpenSSL: 1.1.0 disables compression by + default, and many operating system distributions disable it in prior + versions as well, so setting this parameter to on will not have any + effect if the server does not accept compression. + + - - If security is not a primary concern, compression can improve - throughput if the network is the bottleneck. Disabling compression - can improve response time and throughput if CPU performance is the - limiting factor. + + + NSS: SSL compression is not supported in + NSS, this parameter has no effect. + + + @@ -1668,10 +1740,24 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname sslcert - This parameter specifies the file name of the client SSL - certificate, replacing the default - ~/.postgresql/postgresql.crt. - This parameter is ignored if an SSL connection is not made. + This parameter specifies the name or location of the client SSL + certificate. This parameter is ignored if an SSL connection is not + made. + + + + OpenSSL: can replace the default + ~/.postgresql/postgresql.crt. + + + + + + NSS: the nickname of the client SSL + certificate. + + + @@ -1680,15 +1766,30 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname sslkey - This parameter specifies the location for the secret key used for - the client certificate. It can either specify a file name that will - be used instead of the default - ~/.postgresql/postgresql.key, or it can specify a key - obtained from an external engine (engines are - OpenSSL loadable modules). An external engine - specification should consist of a colon-separated engine name and - an engine-specific key identifier. This parameter is ignored if an - SSL connection is not made. + This parameter specifies the name or location for the secret key used + for the client certificate. This parameter is ignored if an SSL + connection is not made. + + + + OpenSSL: can either specify a file name + that will be used instead of the default + ~/.postgresql/postgresql.key, or it can specify + a key obtained from an external engine (engines are + OpenSSL loadable modules). An external + engine specification should consist of a colon-separated engine name + and an engine-specific key identifier. + + + + + + NSS: this parameter has no effect. Keys + should be loaded into the NSS + database. + + + @@ -1699,28 +1800,44 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname This parameter specifies the password for the secret key specified in sslkey, allowing client certificate private keys - to be stored in encrypted form on disk even when interactive passphrase + to be stored in encrypted form even when interactive passphrase input is not practical. - - - Specifying this parameter with any non-empty value suppresses the - Enter PEM pass phrase: - prompt that OpenSSL will emit by default - when an encrypted client certificate key is provided to - libpq. - - - If the key is not encrypted this parameter is ignored. The parameter - has no effect on keys specified by OpenSSL - engines unless the engine uses the OpenSSL - password callback mechanism for prompts. - - - There is no environment variable equivalent to this option, and no - facility for looking it up in .pgpass. It can be - used in a service file connection definition. Users with - more sophisticated uses should consider using OpenSSL engines and - tools like PKCS#11 or USB crypto offload devices. + + + + OpenSSL: specifying this parameter with + any non-empty value suppresses the + Enter PEM pass phrase: prompt that + OpenSSL will emit by default when an + encrypted client certificate key is provided to + libpq. + + + If the key is not encrypted this parameter is ignored. The parameter + has no effect on keys specified by OpenSSL + engines unless the engine uses the OpenSSL + password callback mechanism for prompts. + + + There is no environment variable equivalent to this option, and no + facility for looking it up in .pgpass. It can be + used in a service file connection definition. Users with + more sophisticated uses should consider using + OpenSSL engines and tools like PKCS#11 or + USB crypto offload devices. + + + + + + NSS: specifying the parameter is required + in case any password protected items are referenced in the + NSS database, or if the database itself + is password protected. All attempts to decrypt objects which are + password protected in the database will use this password. + + + @@ -1729,11 +1846,27 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname sslrootcert - This parameter specifies the name of a file containing SSL - certificate authority (CA) certificate(s). - If the file exists, the server's certificate will be verified - to be signed by one of these authorities. The default is - ~/.postgresql/root.crt. + This parameter specifies the name of SSL certificate authority + (CA) certificate(s). + + + + OpenSSL: specifies the name of a file + containing SSL certificate authority (CA) + certificate(s). If the file exists, the server's certificate will + be verified to be signed by one of these authorities. The default is + ~/.postgresql/root.crt. + + + + + + NSS: this parameter has no effect. CA + certificates should be loaded into the NSS + database using the certutil tool. + + + @@ -1743,13 +1876,29 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname This parameter specifies the file name of the SSL certificate - revocation list (CRL). Certificates listed in this file, if it - exists, will be rejected while attempting to authenticate the - server's certificate. If neither - nor - is set, this setting is - taken as - ~/.postgresql/root.crl. + revocation list (CRL). + + + + + OpenSSL: Certificates listed in this file, + if it exists, will be rejected while attempting to authenticate the + server's certificate. If neither + nor + is set, this setting is + taken as ~/.postgresql/root.crl. + + + + + + NSS: This parameter has no effect. CRL + files should be loaded into the NSS + database using the crlutil tool. + + + + @@ -1762,19 +1911,31 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname revocation list (CRL). Certificates listed in the files in this directory, if it exists, will be rejected while attempting to authenticate the server's certificate. - - - The directory needs to be prepared with the - OpenSSL command - openssl rehash or c_rehash. See - its documentation for details. - + + + + OpenSSL: the directory needs to be + prepared with the OpenSSL command + openssl rehash or c_rehash. + See its documentation for details. + + + Both sslcrl and sslcrldir can + be specified together. + + - - Both sslcrl and sslcrldir can be - specified together. + + + NSS: This parameter has no effect. CRL + files should be loaded into the NSS + database using the crlutil tool. + + + + @@ -1829,8 +1990,8 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname for the connection. Valid values are TLSv1, TLSv1.1, TLSv1.2 and TLSv1.3. The supported protocols depend on the - version of OpenSSL used, older versions - not supporting the most modern protocol versions. If not specified, + version of the SSL library used, older versions may + not support the most modern protocol versions. If not specified, the default is TLSv1.2, which satisfies industry best practices as of this writing. @@ -1845,8 +2006,8 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname for the connection. Valid values are TLSv1, TLSv1.1, TLSv1.2 and TLSv1.3. The supported protocols depend on the - version of OpenSSL used, older versions - not supporting the most modern protocol versions. If not set, this + version of the SSL library used, older versions + may not support the most modern protocol versions. If not set, this parameter is ignored and the connection will use the maximum bound defined by the backend, if set. Setting the maximum protocol version is mainly useful for testing or if some component has issues working @@ -2608,6 +2769,8 @@ void *PQsslStruct(const PGconn *conn, const char *struct_name); The struct(s) available depend on the SSL implementation in use. + + For OpenSSL, there is one struct, available under the name "OpenSSL", and it returns a pointer to the OpenSSL SSL struct. @@ -2631,9 +2794,15 @@ void *PQsslStruct(const PGconn *conn, const char *struct_name); ]]> - This structure can be used to verify encryption levels, check server - certificates, and more. Refer to the OpenSSL - documentation for information about this structure. + For NSS, there is one struct available under + the name "NSS", and it returns a pointer to the + NSS SSL + PRFileDesc associated with the connection. + + + These structures can be used to verify encryption levels, check server + certificates, and more. Refer to the SSL library + documentation for information about these structures. @@ -2660,6 +2829,10 @@ void *PQgetssl(const PGconn *conn); instead, and for more details about the connection, use . + + This function returns NULL when SSL + librariaes other than OpenSSL are used. + @@ -8708,6 +8881,12 @@ void PQinitOpenSSL(int do_ssl, int do_crypto); before first opening a database connection. Also be sure that you have done that initialization before opening a database connection. + + + This function does nothing when using NSS as + the SSL library, no special initialization is + required for NSS. + @@ -8734,6 +8913,12 @@ void PQinitSSL(int do_ssl); might be preferable for applications that need to work with older versions of libpq. + + + This function does nothing when using NSS as + the SSL library, no special initialization is + required for NSS. + diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index d74d1ed7af..6318daa07f 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -2182,15 +2182,21 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433 SSL + TLS PostgreSQL has native support for using SSL connections to encrypt client/server communications for increased security. This requires that - OpenSSL is installed on both client and + a supported TLS library is installed on both client and server systems and that support in PostgreSQL is enabled at build time (see ). + Supported libraries are OpenSSL and + NSS. The terms SSL and + TLS are often used interchangeably to mean a secure + connection using a TLS protocol, even though + SSL protocols are no longer supported. @@ -2210,8 +2216,13 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433 - To start in SSL mode, files containing the server certificate - and private key must exist. By default, these files are expected to be + To start in SSL mode, a server certificate + and private key must exist. The below sections on the different libraries + will discuss how to configure these. + + + + By default, these files are expected to be named server.crt and server.key, respectively, in the server's data directory, but other names and locations can be specified using the configuration parameters @@ -2301,6 +2312,18 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433 + + NSS Configuration + + + PostgreSQL will look for certificates and keys + in the NSS database specified by the parameter + in postgresql.conf. + The parameters for certificate and key filenames are used to identify the + nicknames in the database. + + + Using Client Certificates @@ -2375,7 +2398,7 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433 - SSL Server File Usage + SSL Server File Parameter Usage summarizes the files that are @@ -2422,6 +2445,14 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433 client certificate must not be on this list + + + certificate database + contains server certificates, keys and revocation lists; only + used when PostgreSQL is built with support + for NSS. + + @@ -2445,7 +2476,7 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433 - Creating Certificates + Creating Certificates with OpenSSL To create a simple self-signed certificate for the server, valid for 365 @@ -2549,6 +2580,89 @@ openssl x509 -req -in server.csr -text -days 365 \ + + NSS Certificate Databases + + + When using NSS, all certificates and keys must + be loaded into an NSS certificate database. + + + + To create a new NSS certificate database and + load the certificates created in , + use the following NSS commands: + +certutil -d "sql:server.db" -N --empty-password +certutil -d "sql:server.db" -A -n server.crt -i server.crt -t "CT,C,C" +certutil -d "sql:server.db" -A -n root.crt -i root.crt -t "CT,C,C" + + This will give the certificate the filename as the nickname identifier in + the database which is created as server.db. + + + Then load the server key, which requires converting it to + PKCS#12 format using the + OpenSSL tools: + +openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt \ + -certfile root.crt -passout pass: +pk12util -i server.pfx -d server.db -W '' + + + + Finally a certificate revocation list can be loaded with the following + commands: + +crlutil -I -i server.crl -d server.db -B + + + + + + Creating Certificates with NSS + + + To create a simple self-signed CA and certificate for the server, use the + following NSS commands. Replace + *.yourdomain.com with the server's host + name. Remove --empty-password in order to set + a password protecting the databases. The password can be passed to + certutil with the -f parameter. + First create a self-signed CA. To use a different certificate validity + time than the default, use -v to specify the + number of months of validity. + +mkdir root_ca.db +certutil -N -d "sql:root_ca.db/" --empty-password +certutil -S -d "sql:root_ca.db/" -n root_ca -s "CN=ca.yourdomain.com" \ + -x -k rsa -g 2048 -m 5432 -t CTu,CTu,CTu \ + --keyUsage certSigning -2 --nsCertType sslCA,smimeCA,objectSigningCA \ + -Z SHA256 +certutil -L -d "sql:root_ca.db/" -n root_ca -a > root_ca.pem + + Now create a server certificate database, and create a certificate signing + request for the CA. Then sign the request with the already created CA and + insert the certificate chain into the certificate database. + +mkdir server_cert.db +certutil -N -d "sql:server_cert.db/" --empty-password +certutil -R -d "sql:server_cert.db/" -s "CN=dbhost.yourdomain.com" \ + -o server_cert.csr -g 2048 -Z SHA256 + +certutil -C -d "sql:root_ca.db/" -c root_ca -i server_cert.csr \ + -o server_cert.der -m 5433 \ + --keyUsage keyEncipherment,dataEncipherment,digitalSignature \ + --nsCertType sslServer -Z SHA256 + +certutil -A -d "sql:server_cert.db/" -n root_ca -t CTu,CTu,CTu -a -i root_ca.pem +certutil -A -d "sql:server_cert.db/" -n server_cert -t CTu,CTu,CTu -i server_cert.der + + The server certificate is loaded into the certificate database as well as + the CA certificate in order to provide the chain of certificates. + + + diff --git a/src/backend/libpq/README.SSL b/src/backend/libpq/README.SSL index d84a434a6e..c0722b558d 100644 --- a/src/backend/libpq/README.SSL +++ b/src/backend/libpq/README.SSL @@ -80,3 +80,31 @@ are unacceptable. The downside to EDH is that it makes it impossible to use ssldump(1) if there's a problem establishing an SSL session. In this case you'll need to temporarily disable EDH (see initialize_dh()). + + +Supporting a new TLS backend +============================ + +TLS support in PostgreSQL is implemented with an API which abstracts any +knowledge about the library used from core server backend and frontend code. +Adding support for a new TLS library can be done almost without changing any +core PostgreSQL code. The modules which needs to be implemented are briefly +described below. + +Each supported TLS library is implemented in its own file for the libpq +frontend and backend. The API is defined in be-secure.c and fe-secure.c +respectively. Each library can add relevant connection structures to the +Port and PGConn objects. + +pg_cryptohash is an internal API for invoking cryptographic hash algorithms +on data. Each supported TLS library implements the API defined in the header +common/cryptohash.h, with the implementation used decided at build-time. + +pg_strong_random provide the backend with a source of cryptographically secure +random numbers. + +contrib/sslinfo provide similar information to pg_stat_ssl, with a few library +specific extensions. + +contrib/pgcrypto provide a larger selection of digest and hash algorithms +when compiled against a TLS library. -- 2.24.3 (Apple Git-128)