Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* be-secure-openssl.c
|
|
|
|
* functions for OpenSSL support in the backend.
|
|
|
|
*
|
|
|
|
*
|
2023-01-02 21:00:37 +01:00
|
|
|
* Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
|
|
|
* src/backend/libpq/be-secure-openssl.c
|
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/tcp.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
2022-09-13 16:10:50 +02:00
|
|
|
#include "common/string.h"
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
#include "libpq/libpq.h"
|
2015-02-03 22:03:48 +01:00
|
|
|
#include "miscadmin.h"
|
2016-10-04 16:50:13 +02:00
|
|
|
#include "pgstat.h"
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
#include "storage/fd.h"
|
2015-02-03 22:03:48 +01:00
|
|
|
#include "storage/latch.h"
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
#include "tcop/tcopprot.h"
|
2022-09-13 16:10:50 +02:00
|
|
|
#include "utils/builtins.h"
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
#include "utils/memutils.h"
|
|
|
|
|
2021-11-06 17:43:18 +01:00
|
|
|
/*
|
|
|
|
* These SSL-related #includes must come after all system-provided headers.
|
|
|
|
* This ensures that OpenSSL can take care of conflicts with Windows'
|
|
|
|
* <wincrypt.h> by #undef'ing the conflicting macros. (We don't directly
|
|
|
|
* include <wincrypt.h>, but some other Windows headers do.)
|
|
|
|
*/
|
|
|
|
#include "common/openssl.h"
|
|
|
|
#include <openssl/conf.h>
|
|
|
|
#include <openssl/dh.h>
|
|
|
|
#ifndef OPENSSL_NO_ECDH
|
|
|
|
#include <openssl/ec.h>
|
|
|
|
#endif
|
|
|
|
#include <openssl/x509v3.h>
|
|
|
|
|
|
|
|
|
2020-03-25 22:13:17 +01:00
|
|
|
/* default init hook can be overridden by a shared library */
|
|
|
|
static void default_openssl_tls_init(SSL_CTX *context, bool isServerStart);
|
|
|
|
openssl_tls_init_hook_typ openssl_tls_init_hook = default_openssl_tls_init;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
static int my_sock_read(BIO *h, char *buf, int size);
|
|
|
|
static int my_sock_write(BIO *h, const char *buf, int size);
|
|
|
|
static BIO_METHOD *my_BIO_s_socket(void);
|
|
|
|
static int my_SSL_set_fd(Port *port, int fd);
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
static DH *load_dh_file(char *filename, bool isServerStart);
|
2022-09-20 22:09:30 +02:00
|
|
|
static DH *load_dh_buffer(const char *buffer, size_t len);
|
2018-02-26 19:28:38 +01:00
|
|
|
static int ssl_external_passwd_cb(char *buf, int size, int rwflag, void *userdata);
|
|
|
|
static int dummy_ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata);
|
2022-09-20 22:09:30 +02:00
|
|
|
static int verify_cb(int ok, X509_STORE_CTX *ctx);
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
static void info_cb(const SSL *ssl, int type, int args);
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
static bool initialize_dh(SSL_CTX *context, bool isServerStart);
|
2017-01-04 18:43:52 +01:00
|
|
|
static bool initialize_ecdh(SSL_CTX *context, bool isServerStart);
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
static const char *SSLerrmessage(unsigned long ecode);
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2015-04-12 19:07:46 +02:00
|
|
|
static char *X509_NAME_to_cstring(X509_NAME *name);
|
|
|
|
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
static SSL_CTX *SSL_context = NULL;
|
2017-01-03 03:37:12 +01:00
|
|
|
static bool SSL_initialized = false;
|
2018-02-26 19:28:38 +01:00
|
|
|
static bool dummy_ssl_passwd_cb_called = false;
|
|
|
|
static bool ssl_is_server_start;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2020-03-23 03:01:41 +01:00
|
|
|
static int ssl_protocol_version_to_openssl(int v);
|
2020-06-27 18:47:58 +02:00
|
|
|
static const char *ssl_protocol_version_to_string(int v);
|
2014-08-18 12:04:47 +02:00
|
|
|
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
/* for passing data back from verify_cb() */
|
|
|
|
static const char *cert_errdetail;
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
/* ------------------------------------------------------------ */
|
|
|
|
/* Public interface */
|
|
|
|
/* ------------------------------------------------------------ */
|
|
|
|
|
2017-01-03 03:37:12 +01:00
|
|
|
int
|
2017-01-04 18:43:52 +01:00
|
|
|
be_tls_init(bool isServerStart)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2017-01-03 03:37:12 +01:00
|
|
|
SSL_CTX *context;
|
2020-03-23 03:01:41 +01:00
|
|
|
int ssl_ver_min = -1;
|
|
|
|
int ssl_ver_max = -1;
|
2014-08-18 12:04:47 +02:00
|
|
|
|
2017-01-03 03:37:12 +01:00
|
|
|
/* This stuff need be done only once. */
|
|
|
|
if (!SSL_initialized)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2016-09-15 21:29:39 +02:00
|
|
|
#ifdef HAVE_OPENSSL_INIT_SSL
|
Support OpenSSL 1.1.0.
Changes needed to build at all:
- Check for SSL_new in configure, now that SSL_library_init is a macro.
- Do not access struct members directly. This includes some new code in
pgcrypto, to use the resource owner mechanism to ensure that we don't
leak OpenSSL handles, now that we can't embed them in other structs
anymore.
- RAND_SSLeay() -> RAND_OpenSSL()
Changes that were needed to silence deprecation warnings, but were not
strictly necessary:
- RAND_pseudo_bytes() -> RAND_bytes().
- SSL_library_init() and OpenSSL_config() -> OPENSSL_init_ssl()
- ASN1_STRING_data() -> ASN1_STRING_get0_data()
- DH_generate_parameters() -> DH_generate_parameters()
- Locking callbacks are not needed with OpenSSL 1.1.0 anymore. (Good
riddance!)
Also change references to SSLEAY_VERSION_NUMBER with OPENSSL_VERSION_NUMBER,
for the sake of consistency. OPENSSL_VERSION_NUMBER has existed since time
immemorial.
Fix SSL test suite to work with OpenSSL 1.1.0. CA certificates must have
the "CA:true" basic constraint extension now, or OpenSSL will refuse them.
Regenerate the test certificates with that. The "openssl" binary, used to
generate the certificates, is also now more picky, and throws an error
if an X509 extension is specified in "req_extensions", but that section
is empty.
Backpatch to all supported branches, per popular demand. In back-branches,
we still support OpenSSL 0.9.7 and above. OpenSSL 0.9.6 should still work
too, but I didn't test it. In master, we only support 0.9.8 and above.
Patch by Andreas Karlsson, with additional changes by me.
Discussion: <20160627151604.GD1051@msg.df7cb.de>
2016-09-15 11:36:21 +02:00
|
|
|
OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
|
|
|
|
#else
|
2014-08-18 12:04:47 +02:00
|
|
|
OPENSSL_config(NULL);
|
|
|
|
SSL_library_init();
|
|
|
|
SSL_load_error_strings();
|
Support OpenSSL 1.1.0.
Changes needed to build at all:
- Check for SSL_new in configure, now that SSL_library_init is a macro.
- Do not access struct members directly. This includes some new code in
pgcrypto, to use the resource owner mechanism to ensure that we don't
leak OpenSSL handles, now that we can't embed them in other structs
anymore.
- RAND_SSLeay() -> RAND_OpenSSL()
Changes that were needed to silence deprecation warnings, but were not
strictly necessary:
- RAND_pseudo_bytes() -> RAND_bytes().
- SSL_library_init() and OpenSSL_config() -> OPENSSL_init_ssl()
- ASN1_STRING_data() -> ASN1_STRING_get0_data()
- DH_generate_parameters() -> DH_generate_parameters()
- Locking callbacks are not needed with OpenSSL 1.1.0 anymore. (Good
riddance!)
Also change references to SSLEAY_VERSION_NUMBER with OPENSSL_VERSION_NUMBER,
for the sake of consistency. OPENSSL_VERSION_NUMBER has existed since time
immemorial.
Fix SSL test suite to work with OpenSSL 1.1.0. CA certificates must have
the "CA:true" basic constraint extension now, or OpenSSL will refuse them.
Regenerate the test certificates with that. The "openssl" binary, used to
generate the certificates, is also now more picky, and throws an error
if an X509 extension is specified in "req_extensions", but that section
is empty.
Backpatch to all supported branches, per popular demand. In back-branches,
we still support OpenSSL 0.9.7 and above. OpenSSL 0.9.6 should still work
too, but I didn't test it. In master, we only support 0.9.8 and above.
Patch by Andreas Karlsson, with additional changes by me.
Discussion: <20160627151604.GD1051@msg.df7cb.de>
2016-09-15 11:36:21 +02:00
|
|
|
#endif
|
2017-01-03 03:37:12 +01:00
|
|
|
SSL_initialized = true;
|
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2017-01-03 03:37:12 +01:00
|
|
|
/*
|
2021-03-16 21:02:49 +01:00
|
|
|
* Create a new SSL context into which we'll load all the configuration
|
|
|
|
* settings. If we fail partway through, we can avoid memory leakage by
|
|
|
|
* freeing this context; we don't install it as active until the end.
|
|
|
|
*
|
2017-01-03 03:37:12 +01:00
|
|
|
* We use SSLv23_method() because it can negotiate use of the highest
|
|
|
|
* mutually supported protocol version, while alternatives like
|
|
|
|
* TLSv1_2_method() permit only one specific version. Note that we don't
|
|
|
|
* actually allow SSL v2 or v3, only TLS protocols (see below).
|
|
|
|
*/
|
|
|
|
context = SSL_CTX_new(SSLv23_method());
|
|
|
|
if (!context)
|
|
|
|
{
|
2017-01-04 18:43:52 +01:00
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
2017-01-03 03:37:12 +01:00
|
|
|
(errmsg("could not create SSL context: %s",
|
|
|
|
SSLerrmessage(ERR_get_error()))));
|
|
|
|
goto error;
|
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2017-01-03 03:37:12 +01:00
|
|
|
/*
|
|
|
|
* Disable OpenSSL's moving-write-buffer sanity check, because it causes
|
|
|
|
* unnecessary failures in nonblocking send cases.
|
|
|
|
*/
|
|
|
|
SSL_CTX_set_mode(context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2017-01-03 18:33:29 +01:00
|
|
|
/*
|
2020-03-25 22:13:17 +01:00
|
|
|
* Call init hook (usually to set password callback)
|
2017-01-03 18:33:29 +01:00
|
|
|
*/
|
2020-03-25 22:13:17 +01:00
|
|
|
(*openssl_tls_init_hook) (context, isServerStart);
|
2018-04-26 20:47:16 +02:00
|
|
|
|
2018-02-26 19:28:38 +01:00
|
|
|
/* used by the callback */
|
|
|
|
ssl_is_server_start = isServerStart;
|
2017-01-03 18:33:29 +01:00
|
|
|
|
2017-01-03 03:37:12 +01:00
|
|
|
/*
|
|
|
|
* Load and verify server's certificate and private key
|
|
|
|
*/
|
|
|
|
if (SSL_CTX_use_certificate_chain_file(context, ssl_cert_file) != 1)
|
|
|
|
{
|
2017-01-04 18:43:52 +01:00
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
2017-01-03 03:37:12 +01:00
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("could not load server certificate file \"%s\": %s",
|
|
|
|
ssl_cert_file, SSLerrmessage(ERR_get_error()))));
|
|
|
|
goto error;
|
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2018-01-19 16:17:56 +01:00
|
|
|
if (!check_ssl_key_file_permissions(ssl_key_file, isServerStart))
|
2017-01-03 03:37:12 +01:00
|
|
|
goto error;
|
2014-08-18 12:04:47 +02:00
|
|
|
|
2017-01-04 18:43:52 +01:00
|
|
|
/*
|
|
|
|
* OK, try to load the private key file.
|
|
|
|
*/
|
2018-02-26 19:28:38 +01:00
|
|
|
dummy_ssl_passwd_cb_called = false;
|
2017-01-04 18:43:52 +01:00
|
|
|
|
2017-01-03 03:37:12 +01:00
|
|
|
if (SSL_CTX_use_PrivateKey_file(context,
|
|
|
|
ssl_key_file,
|
|
|
|
SSL_FILETYPE_PEM) != 1)
|
|
|
|
{
|
2018-02-26 19:28:38 +01:00
|
|
|
if (dummy_ssl_passwd_cb_called)
|
2017-01-04 18:43:52 +01:00
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("private key file \"%s\" cannot be reloaded because it requires a passphrase",
|
|
|
|
ssl_key_file)));
|
|
|
|
else
|
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("could not load private key file \"%s\": %s",
|
|
|
|
ssl_key_file, SSLerrmessage(ERR_get_error()))));
|
2017-01-03 03:37:12 +01:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SSL_CTX_check_private_key(context) != 1)
|
|
|
|
{
|
2017-01-04 18:43:52 +01:00
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
2017-01-03 03:37:12 +01:00
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("check of private key failed: %s",
|
|
|
|
SSLerrmessage(ERR_get_error()))));
|
|
|
|
goto error;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
|
2018-11-20 21:49:01 +01:00
|
|
|
if (ssl_min_protocol_version)
|
2019-02-08 11:58:19 +01:00
|
|
|
{
|
2020-03-23 03:01:41 +01:00
|
|
|
ssl_ver_min = ssl_protocol_version_to_openssl(ssl_min_protocol_version);
|
2019-05-22 18:55:34 +02:00
|
|
|
|
2020-03-23 03:01:41 +01:00
|
|
|
if (ssl_ver_min == -1)
|
|
|
|
{
|
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
2020-11-07 23:33:43 +01:00
|
|
|
/*- translator: first %s is a GUC option name, second %s is its value */
|
2020-03-23 03:01:41 +01:00
|
|
|
(errmsg("\"%s\" setting \"%s\" not supported by this build",
|
|
|
|
"ssl_min_protocol_version",
|
|
|
|
GetConfigOption("ssl_min_protocol_version",
|
|
|
|
false, false))));
|
2019-02-08 11:58:19 +01:00
|
|
|
goto error;
|
2020-03-23 03:01:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!SSL_CTX_set_min_proto_version(context, ssl_ver_min))
|
2019-09-28 15:54:02 +02:00
|
|
|
{
|
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
|
|
|
(errmsg("could not set minimum SSL protocol version")));
|
|
|
|
goto error;
|
|
|
|
}
|
2019-02-08 11:58:19 +01:00
|
|
|
}
|
|
|
|
|
2018-11-20 21:49:01 +01:00
|
|
|
if (ssl_max_protocol_version)
|
2019-02-08 11:58:19 +01:00
|
|
|
{
|
2020-03-23 03:01:41 +01:00
|
|
|
ssl_ver_max = ssl_protocol_version_to_openssl(ssl_max_protocol_version);
|
2019-05-22 18:55:34 +02:00
|
|
|
|
2020-03-23 03:01:41 +01:00
|
|
|
if (ssl_ver_max == -1)
|
|
|
|
{
|
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
2020-11-07 23:33:43 +01:00
|
|
|
/*- translator: first %s is a GUC option name, second %s is its value */
|
2020-03-23 03:01:41 +01:00
|
|
|
(errmsg("\"%s\" setting \"%s\" not supported by this build",
|
|
|
|
"ssl_max_protocol_version",
|
|
|
|
GetConfigOption("ssl_max_protocol_version",
|
|
|
|
false, false))));
|
2019-02-08 11:58:19 +01:00
|
|
|
goto error;
|
2020-03-23 03:01:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!SSL_CTX_set_max_proto_version(context, ssl_ver_max))
|
2019-09-28 15:54:02 +02:00
|
|
|
{
|
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
|
|
|
(errmsg("could not set maximum SSL protocol version")));
|
|
|
|
goto error;
|
|
|
|
}
|
2019-02-08 11:58:19 +01:00
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2020-03-23 03:01:41 +01:00
|
|
|
/* Check compatibility of min/max protocols */
|
|
|
|
if (ssl_min_protocol_version &&
|
|
|
|
ssl_max_protocol_version)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* No need to check for invalid values (-1) for each protocol number
|
|
|
|
* as the code above would have already generated an error.
|
|
|
|
*/
|
|
|
|
if (ssl_ver_min > ssl_ver_max)
|
2020-04-30 01:14:02 +02:00
|
|
|
{
|
2020-03-23 03:01:41 +01:00
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
|
|
|
(errmsg("could not set SSL protocol version range"),
|
|
|
|
errdetail("\"%s\" cannot be higher than \"%s\"",
|
|
|
|
"ssl_min_protocol_version",
|
|
|
|
"ssl_max_protocol_version")));
|
2020-04-30 01:14:02 +02:00
|
|
|
goto error;
|
|
|
|
}
|
2020-03-23 03:01:41 +01:00
|
|
|
}
|
|
|
|
|
Disallow SSL session tickets.
We don't actually support session tickets, since we do not create an SSL
session identifier. But it seems that OpenSSL will issue a session ticket
on-demand anyway, which will then fail when used. This results in
reconnection failures when using ticket-aware client-side SSL libraries
(such as the Npgsql .NET driver), as reported by Shay Rojansky.
To fix, just tell OpenSSL not to issue tickets. At some point in the
far future, we might consider enabling tickets instead. But the security
implications of that aren't entirely clear; and besides it would have
little benefit except for very short-lived database connections, which is
Something We're Bad At anyhow. It would take a lot of other work to get
to a point where that would really be an exciting thing to do.
While at it, also tell OpenSSL not to use a session cache. This doesn't
really do anything, since a backend would never populate the cache anyway,
but it might gain some micro-efficiencies and/or reduce security
exposures.
Patch by me, per discussion with Heikki Linnakangas and Shay Rojansky.
Back-patch to all supported versions.
Discussion: https://postgr.es/m/CADT4RqBU8N-csyZuzaook-c795dt22Zcwg1aHWB6tfVdAkodZA@mail.gmail.com
2017-08-04 17:07:10 +02:00
|
|
|
/* disallow SSL session tickets */
|
|
|
|
SSL_CTX_set_options(context, SSL_OP_NO_TICKET);
|
|
|
|
|
|
|
|
/* disallow SSL session caching, too */
|
|
|
|
SSL_CTX_set_session_cache_mode(context, SSL_SESS_CACHE_OFF);
|
|
|
|
|
Remove support for SSL compression
PostgreSQL disabled compression as of e3bdb2d and the documentation
recommends against using it since. Additionally, SSL compression has
been disabled in OpenSSL since version 1.1.0, and was disabled in many
distributions long before that. The most recent TLS version, TLSv1.3,
disallows compression at the protocol level.
This commit removes the feature itself, removing support for the libpq
parameter sslcompression (parameter still listed for compatibility
reasons with existing connection strings, just ignored), and removes
the equivalent field in pg_stat_ssl and de facto PgBackendSSLStatus.
Note that, on top of removing the ability to activate compression by
configuration, compression is actively disabled in both frontend and
backend to avoid overrides from local configurations.
A TAP test is added for deprecated SSL parameters to check after
backwards compatibility.
Bump catalog version.
Author: Daniel Gustafsson
Reviewed-by: Peter Eisentraut, Magnus Hagander, Michael Paquier
Discussion: https://postgr.es/m/7E384D48-11C5-441B-9EC3-F7DB1F8518F6@yesql.se
2021-03-09 03:16:47 +01:00
|
|
|
/* disallow SSL compression */
|
|
|
|
SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
|
|
|
|
|
2021-05-25 03:10:09 +02:00
|
|
|
#ifdef SSL_OP_NO_RENEGOTIATION
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Disallow SSL renegotiation, option available since 1.1.0h. This
|
|
|
|
* concerns only TLSv1.2 and older protocol versions, as TLSv1.3 has no
|
|
|
|
* support for renegotiation.
|
|
|
|
*/
|
|
|
|
SSL_CTX_set_options(context, SSL_OP_NO_RENEGOTIATION);
|
|
|
|
#endif
|
|
|
|
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
/* set up ephemeral DH and ECDH keys */
|
|
|
|
if (!initialize_dh(context, isServerStart))
|
|
|
|
goto error;
|
2017-01-04 18:43:52 +01:00
|
|
|
if (!initialize_ecdh(context, isServerStart))
|
2017-01-03 03:37:12 +01:00
|
|
|
goto error;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
/* set up the allowed cipher list */
|
2017-01-03 03:37:12 +01:00
|
|
|
if (SSL_CTX_set_cipher_list(context, SSLCipherSuites) != 1)
|
|
|
|
{
|
2017-01-04 18:43:52 +01:00
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
2017-01-03 03:37:12 +01:00
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("could not set the cipher list (no valid ciphers available)")));
|
|
|
|
goto error;
|
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
/* Let server choose order */
|
|
|
|
if (SSLPreferServerCiphers)
|
2017-01-03 03:37:12 +01:00
|
|
|
SSL_CTX_set_options(context, SSL_OP_CIPHER_SERVER_PREFERENCE);
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
/*
|
|
|
|
* Load CA store, so we can verify client certificates if needed.
|
|
|
|
*/
|
|
|
|
if (ssl_ca_file[0])
|
|
|
|
{
|
2021-03-16 21:02:49 +01:00
|
|
|
STACK_OF(X509_NAME) * root_cert_list;
|
|
|
|
|
2017-01-03 03:37:12 +01:00
|
|
|
if (SSL_CTX_load_verify_locations(context, ssl_ca_file, NULL) != 1 ||
|
2014-08-18 12:04:47 +02:00
|
|
|
(root_cert_list = SSL_load_client_CA_file(ssl_ca_file)) == NULL)
|
2017-01-03 03:37:12 +01:00
|
|
|
{
|
2017-01-04 18:43:52 +01:00
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
2017-01-03 03:37:12 +01:00
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("could not load root certificate file \"%s\": %s",
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
ssl_ca_file, SSLerrmessage(ERR_get_error()))));
|
2017-01-03 03:37:12 +01:00
|
|
|
goto error;
|
|
|
|
}
|
2021-03-16 21:02:49 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Tell OpenSSL to send the list of root certs we trust to clients in
|
|
|
|
* CertificateRequests. This lets a client with a keystore select the
|
|
|
|
* appropriate client certificate to send to us. Also, this ensures
|
|
|
|
* that the SSL context will "own" the root_cert_list and remember to
|
|
|
|
* free it when no longer needed.
|
|
|
|
*/
|
|
|
|
SSL_CTX_set_client_CA_list(context, root_cert_list);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Always ask for SSL client cert, but don't fail if it's not
|
|
|
|
* presented. We might fail such connections later, depending on what
|
|
|
|
* we find in pg_hba.conf.
|
|
|
|
*/
|
|
|
|
SSL_CTX_set_verify(context,
|
|
|
|
(SSL_VERIFY_PEER |
|
|
|
|
SSL_VERIFY_CLIENT_ONCE),
|
|
|
|
verify_cb);
|
2014-08-18 12:04:47 +02:00
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
/*----------
|
|
|
|
* Load the Certificate Revocation List (CRL).
|
|
|
|
* http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html
|
|
|
|
*----------
|
|
|
|
*/
|
2021-02-18 07:59:10 +01:00
|
|
|
if (ssl_crl_file[0] || ssl_crl_dir[0])
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2017-01-03 03:37:12 +01:00
|
|
|
X509_STORE *cvstore = SSL_CTX_get_cert_store(context);
|
2014-08-18 12:04:47 +02:00
|
|
|
|
|
|
|
if (cvstore)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
/* Set the flags to check against the complete CRL chain */
|
2021-02-18 07:59:10 +01:00
|
|
|
if (X509_STORE_load_locations(cvstore,
|
|
|
|
ssl_crl_file[0] ? ssl_crl_file : NULL,
|
2021-03-16 21:02:49 +01:00
|
|
|
ssl_crl_dir[0] ? ssl_crl_dir : NULL)
|
2021-02-18 07:59:10 +01:00
|
|
|
== 1)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
X509_STORE_set_flags(cvstore,
|
|
|
|
X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
2021-02-18 07:59:10 +01:00
|
|
|
else if (ssl_crl_dir[0] == 0)
|
2017-01-03 03:37:12 +01:00
|
|
|
{
|
2017-01-04 18:43:52 +01:00
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
2017-01-03 03:37:12 +01:00
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("could not load SSL certificate revocation list file \"%s\": %s",
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
ssl_crl_file, SSLerrmessage(ERR_get_error()))));
|
2017-01-03 03:37:12 +01:00
|
|
|
goto error;
|
|
|
|
}
|
2021-02-18 07:59:10 +01:00
|
|
|
else if (ssl_crl_file[0] == 0)
|
|
|
|
{
|
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("could not load SSL certificate revocation list directory \"%s\": %s",
|
|
|
|
ssl_crl_dir, SSLerrmessage(ERR_get_error()))));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("could not load SSL certificate revocation list file \"%s\" or directory \"%s\": %s",
|
|
|
|
ssl_crl_file, ssl_crl_dir,
|
|
|
|
SSLerrmessage(ERR_get_error()))));
|
|
|
|
goto error;
|
|
|
|
}
|
2014-08-18 12:04:47 +02:00
|
|
|
}
|
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2017-01-03 03:37:12 +01:00
|
|
|
/*
|
|
|
|
* Success! Replace any existing SSL_context.
|
|
|
|
*/
|
|
|
|
if (SSL_context)
|
|
|
|
SSL_CTX_free(SSL_context);
|
|
|
|
|
|
|
|
SSL_context = context;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set flag to remember whether CA store has been loaded into SSL_context.
|
|
|
|
*/
|
|
|
|
if (ssl_ca_file[0])
|
|
|
|
ssl_loaded_verify_locations = true;
|
|
|
|
else
|
|
|
|
ssl_loaded_verify_locations = false;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2021-03-16 21:02:49 +01:00
|
|
|
/* Clean up by releasing working context. */
|
2017-01-03 03:37:12 +01:00
|
|
|
error:
|
|
|
|
if (context)
|
|
|
|
SSL_CTX_free(context);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
be_tls_destroy(void)
|
|
|
|
{
|
|
|
|
if (SSL_context)
|
|
|
|
SSL_CTX_free(SSL_context);
|
|
|
|
SSL_context = NULL;
|
|
|
|
ssl_loaded_verify_locations = false;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
int
|
|
|
|
be_tls_open_server(Port *port)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
int r;
|
|
|
|
int err;
|
2015-02-03 22:03:48 +01:00
|
|
|
int waitfor;
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
unsigned long ecode;
|
2020-06-27 18:47:58 +02:00
|
|
|
bool give_proto_hint;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
Assert(!port->ssl);
|
|
|
|
Assert(!port->peer);
|
|
|
|
|
2017-01-03 03:37:12 +01:00
|
|
|
if (!SSL_context)
|
|
|
|
{
|
|
|
|
ereport(COMMERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("could not initialize SSL connection: SSL context not set up")));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-01-22 01:26:27 +01:00
|
|
|
/* set up debugging/info callback */
|
|
|
|
SSL_CTX_set_info_callback(SSL_context, info_cb);
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
if (!(port->ssl = SSL_new(SSL_context)))
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
ereport(COMMERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("could not initialize SSL connection: %s",
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
SSLerrmessage(ERR_get_error()))));
|
2014-08-18 12:04:47 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (!my_SSL_set_fd(port, port->sock))
|
|
|
|
{
|
|
|
|
ereport(COMMERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("could not set SSL socket: %s",
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
SSLerrmessage(ERR_get_error()))));
|
2014-08-18 12:04:47 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
port->ssl_in_use = true;
|
|
|
|
|
|
|
|
aloop:
|
2016-06-10 00:02:36 +02:00
|
|
|
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
/*
|
|
|
|
* Prepare to call SSL_get_error() by clearing thread's OpenSSL error
|
|
|
|
* queue. In general, the current thread's error queue must be empty
|
|
|
|
* before the TLS/SSL I/O operation is attempted, or SSL_get_error() will
|
|
|
|
* not work reliably. An extension may have failed to clear the
|
|
|
|
* per-thread error queue following another call to an OpenSSL I/O
|
|
|
|
* routine.
|
|
|
|
*/
|
|
|
|
ERR_clear_error();
|
2014-08-18 12:04:47 +02:00
|
|
|
r = SSL_accept(port->ssl);
|
|
|
|
if (r <= 0)
|
|
|
|
{
|
|
|
|
err = SSL_get_error(port->ssl, r);
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Other clients of OpenSSL in the backend may fail to call
|
|
|
|
* ERR_get_error(), but we always do, so as to not cause problems for
|
|
|
|
* OpenSSL clients that don't call ERR_clear_error() defensively. Be
|
|
|
|
* sure that this happens by calling now. SSL_get_error() relies on
|
|
|
|
* the OpenSSL per-thread error queue being intact, so this is the
|
|
|
|
* earliest possible point ERR_get_error() may be called.
|
|
|
|
*/
|
|
|
|
ecode = ERR_get_error();
|
2014-08-18 12:04:47 +02:00
|
|
|
switch (err)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
case SSL_ERROR_WANT_READ:
|
|
|
|
case SSL_ERROR_WANT_WRITE:
|
2015-02-03 22:03:48 +01:00
|
|
|
/* not allowed during connection establishment */
|
|
|
|
Assert(!port->noblock);
|
|
|
|
|
2015-02-03 22:54:48 +01:00
|
|
|
/*
|
|
|
|
* No need to care about timeouts/interrupts here. At this
|
|
|
|
* point authentication_timeout still employs
|
|
|
|
* StartupPacketTimeoutHandler() which directly exits.
|
|
|
|
*/
|
2015-02-03 22:03:48 +01:00
|
|
|
if (err == SSL_ERROR_WANT_READ)
|
2018-11-25 04:21:41 +01:00
|
|
|
waitfor = WL_SOCKET_READABLE | WL_EXIT_ON_PM_DEATH;
|
2015-02-03 22:03:48 +01:00
|
|
|
else
|
2018-11-25 04:21:41 +01:00
|
|
|
waitfor = WL_SOCKET_WRITEABLE | WL_EXIT_ON_PM_DEATH;
|
2015-02-03 22:03:48 +01:00
|
|
|
|
Add WL_EXIT_ON_PM_DEATH pseudo-event.
Users of the WaitEventSet and WaitLatch() APIs can now choose between
asking for WL_POSTMASTER_DEATH and then handling it explicitly, or asking
for WL_EXIT_ON_PM_DEATH to trigger immediate exit on postmaster death.
This reduces code duplication, since almost all callers want the latter.
Repair all code that was previously ignoring postmaster death completely,
or requesting the event but ignoring it, or requesting the event but then
doing an unconditional PostmasterIsAlive() call every time through its
event loop (which is an expensive syscall on platforms for which we don't
have USE_POSTMASTER_DEATH_SIGNAL support).
Assert that callers of WaitLatchXXX() under the postmaster remember to
ask for either WL_POSTMASTER_DEATH or WL_EXIT_ON_PM_DEATH, to prevent
future bugs.
The only process that doesn't handle postmaster death is syslogger. It
waits until all backends holding the write end of the syslog pipe
(including the postmaster) have closed it by exiting, to be sure to
capture any parting messages. By using the WaitEventSet API directly
it avoids the new assertion, and as a by-product it may be slightly
more efficient on platforms that have epoll().
Author: Thomas Munro
Reviewed-by: Kyotaro Horiguchi, Heikki Linnakangas, Tom Lane
Discussion: https://postgr.es/m/CAEepm%3D1TCviRykkUb69ppWLr_V697rzd1j3eZsRMmbXvETfqbQ%40mail.gmail.com,
https://postgr.es/m/CAEepm=2LqHzizbe7muD7-2yHUbTOoF7Q+qkSD5Q41kuhttRTwA@mail.gmail.com
2018-11-23 08:16:41 +01:00
|
|
|
(void) WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0,
|
|
|
|
WAIT_EVENT_SSL_OPEN_SERVER);
|
2014-08-18 12:04:47 +02:00
|
|
|
goto aloop;
|
|
|
|
case SSL_ERROR_SYSCALL:
|
|
|
|
if (r < 0)
|
|
|
|
ereport(COMMERROR,
|
|
|
|
(errcode_for_socket_access(),
|
|
|
|
errmsg("could not accept SSL connection: %m")));
|
|
|
|
else
|
|
|
|
ereport(COMMERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("could not accept SSL connection: EOF detected")));
|
|
|
|
break;
|
|
|
|
case SSL_ERROR_SSL:
|
2020-06-27 18:47:58 +02:00
|
|
|
switch (ERR_GET_REASON(ecode))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* UNSUPPORTED_PROTOCOL, WRONG_VERSION_NUMBER, and
|
|
|
|
* TLSV1_ALERT_PROTOCOL_VERSION have been observed
|
|
|
|
* when trying to communicate with an old OpenSSL
|
|
|
|
* library, or when the client and server specify
|
|
|
|
* disjoint protocol ranges. NO_PROTOCOLS_AVAILABLE
|
|
|
|
* occurs if there's a local misconfiguration (which
|
|
|
|
* can happen despite our checks, if openssl.cnf
|
|
|
|
* injects a limit we didn't account for). It's not
|
|
|
|
* very clear what would make OpenSSL return the other
|
|
|
|
* codes listed here, but a hint about protocol
|
|
|
|
* versions seems like it's appropriate for all.
|
|
|
|
*/
|
|
|
|
case SSL_R_NO_PROTOCOLS_AVAILABLE:
|
|
|
|
case SSL_R_UNSUPPORTED_PROTOCOL:
|
|
|
|
case SSL_R_BAD_PROTOCOL_VERSION_NUMBER:
|
|
|
|
case SSL_R_UNKNOWN_PROTOCOL:
|
|
|
|
case SSL_R_UNKNOWN_SSL_VERSION:
|
|
|
|
case SSL_R_UNSUPPORTED_SSL_VERSION:
|
|
|
|
case SSL_R_WRONG_SSL_VERSION:
|
|
|
|
case SSL_R_WRONG_VERSION_NUMBER:
|
|
|
|
case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
|
2020-06-27 19:26:17 +02:00
|
|
|
#ifdef SSL_R_VERSION_TOO_HIGH
|
|
|
|
case SSL_R_VERSION_TOO_HIGH:
|
|
|
|
case SSL_R_VERSION_TOO_LOW:
|
|
|
|
#endif
|
2020-06-27 18:47:58 +02:00
|
|
|
give_proto_hint = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
give_proto_hint = false;
|
|
|
|
break;
|
|
|
|
}
|
2014-08-18 12:04:47 +02:00
|
|
|
ereport(COMMERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("could not accept SSL connection: %s",
|
2020-06-27 18:47:58 +02:00
|
|
|
SSLerrmessage(ecode)),
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
cert_errdetail ? errdetail_internal("%s", cert_errdetail) : 0,
|
2020-06-27 18:47:58 +02:00
|
|
|
give_proto_hint ?
|
|
|
|
errhint("This may indicate that the client does not support any SSL protocol version between %s and %s.",
|
|
|
|
ssl_min_protocol_version ?
|
|
|
|
ssl_protocol_version_to_string(ssl_min_protocol_version) :
|
|
|
|
MIN_OPENSSL_TLS_VERSION,
|
|
|
|
ssl_max_protocol_version ?
|
|
|
|
ssl_protocol_version_to_string(ssl_max_protocol_version) :
|
|
|
|
MAX_OPENSSL_TLS_VERSION) : 0));
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
cert_errdetail = NULL;
|
2014-08-18 12:04:47 +02:00
|
|
|
break;
|
|
|
|
case SSL_ERROR_ZERO_RETURN:
|
|
|
|
ereport(COMMERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("could not accept SSL connection: EOF detected")));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ereport(COMMERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("unrecognized SSL error code: %d",
|
|
|
|
err)));
|
|
|
|
break;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
2014-08-18 12:04:47 +02:00
|
|
|
return -1;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
/* Get client certificate, if available. */
|
|
|
|
port->peer = SSL_get_peer_certificate(port->ssl);
|
|
|
|
|
2021-03-29 21:31:22 +02:00
|
|
|
/* and extract the Common Name and Distinguished Name from it. */
|
2014-08-18 12:04:47 +02:00
|
|
|
port->peer_cn = NULL;
|
2021-03-29 21:31:22 +02:00
|
|
|
port->peer_dn = NULL;
|
2014-08-18 12:04:47 +02:00
|
|
|
port->peer_cert_valid = false;
|
|
|
|
if (port->peer != NULL)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
int len;
|
2021-03-29 21:31:22 +02:00
|
|
|
X509_NAME *x509name = X509_get_subject_name(port->peer);
|
|
|
|
char *peer_dn;
|
|
|
|
BIO *bio = NULL;
|
|
|
|
BUF_MEM *bio_buf = NULL;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2021-03-29 21:31:22 +02:00
|
|
|
len = X509_NAME_get_text_by_NID(x509name, NID_commonName, NULL, 0);
|
2014-08-18 12:04:47 +02:00
|
|
|
if (len != -1)
|
|
|
|
{
|
|
|
|
char *peer_cn;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
peer_cn = MemoryContextAlloc(TopMemoryContext, len + 1);
|
2021-03-29 21:31:22 +02:00
|
|
|
r = X509_NAME_get_text_by_NID(x509name, NID_commonName, peer_cn,
|
|
|
|
len + 1);
|
2014-08-18 12:04:47 +02:00
|
|
|
peer_cn[len] = '\0';
|
|
|
|
if (r != len)
|
|
|
|
{
|
|
|
|
/* shouldn't happen */
|
|
|
|
pfree(peer_cn);
|
|
|
|
return -1;
|
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
/*
|
|
|
|
* Reject embedded NULLs in certificate common name to prevent
|
|
|
|
* attacks like CVE-2009-4034.
|
|
|
|
*/
|
|
|
|
if (len != strlen(peer_cn))
|
|
|
|
{
|
|
|
|
ereport(COMMERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("SSL certificate's common name contains embedded null")));
|
|
|
|
pfree(peer_cn);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
port->peer_cn = peer_cn;
|
|
|
|
}
|
2021-03-29 21:31:22 +02:00
|
|
|
|
|
|
|
bio = BIO_new(BIO_s_mem());
|
|
|
|
if (!bio)
|
|
|
|
{
|
|
|
|
pfree(port->peer_cn);
|
|
|
|
port->peer_cn = NULL;
|
|
|
|
return -1;
|
|
|
|
}
|
2021-05-12 19:14:10 +02:00
|
|
|
|
2021-03-29 21:31:22 +02:00
|
|
|
/*
|
|
|
|
* RFC2253 is the closest thing to an accepted standard format for
|
|
|
|
* DNs. We have documented how to produce this format from a
|
|
|
|
* certificate. It uses commas instead of slashes for delimiters,
|
|
|
|
* which make regular expression matching a bit easier. Also note that
|
|
|
|
* it prints the Subject fields in reverse order.
|
|
|
|
*/
|
|
|
|
X509_NAME_print_ex(bio, x509name, 0, XN_FLAG_RFC2253);
|
|
|
|
if (BIO_get_mem_ptr(bio, &bio_buf) <= 0)
|
|
|
|
{
|
|
|
|
BIO_free(bio);
|
|
|
|
pfree(port->peer_cn);
|
|
|
|
port->peer_cn = NULL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
peer_dn = MemoryContextAlloc(TopMemoryContext, bio_buf->length + 1);
|
|
|
|
memcpy(peer_dn, bio_buf->data, bio_buf->length);
|
|
|
|
len = bio_buf->length;
|
|
|
|
BIO_free(bio);
|
|
|
|
peer_dn[len] = '\0';
|
|
|
|
if (len != strlen(peer_dn))
|
|
|
|
{
|
|
|
|
ereport(COMMERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("SSL certificate's distinguished name contains embedded null")));
|
|
|
|
pfree(peer_dn);
|
|
|
|
pfree(port->peer_cn);
|
|
|
|
port->peer_cn = NULL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
port->peer_dn = peer_dn;
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
port->peer_cert_valid = true;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
return 0;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
void
|
|
|
|
be_tls_close(Port *port)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
if (port->ssl)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
SSL_shutdown(port->ssl);
|
|
|
|
SSL_free(port->ssl);
|
|
|
|
port->ssl = NULL;
|
|
|
|
port->ssl_in_use = false;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
if (port->peer)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
X509_free(port->peer);
|
|
|
|
port->peer = NULL;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
if (port->peer_cn)
|
|
|
|
{
|
|
|
|
pfree(port->peer_cn);
|
|
|
|
port->peer_cn = NULL;
|
|
|
|
}
|
2021-03-29 21:31:22 +02:00
|
|
|
|
|
|
|
if (port->peer_dn)
|
|
|
|
{
|
|
|
|
pfree(port->peer_dn);
|
|
|
|
port->peer_dn = NULL;
|
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
ssize_t
|
2015-02-13 20:46:14 +01:00
|
|
|
be_tls_read(Port *port, void *ptr, size_t len, int *waitfor)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
ssize_t n;
|
|
|
|
int err;
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
unsigned long ecode;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
errno = 0;
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
ERR_clear_error();
|
2014-08-18 12:04:47 +02:00
|
|
|
n = SSL_read(port->ssl, ptr, len);
|
|
|
|
err = SSL_get_error(port->ssl, n);
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
|
2014-08-18 12:04:47 +02:00
|
|
|
switch (err)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
case SSL_ERROR_NONE:
|
2016-08-31 15:24:19 +02:00
|
|
|
/* a-ok */
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
break;
|
2014-08-18 12:04:47 +02:00
|
|
|
case SSL_ERROR_WANT_READ:
|
2015-02-13 20:46:14 +01:00
|
|
|
*waitfor = WL_SOCKET_READABLE;
|
|
|
|
errno = EWOULDBLOCK;
|
|
|
|
n = -1;
|
|
|
|
break;
|
2014-08-18 12:04:47 +02:00
|
|
|
case SSL_ERROR_WANT_WRITE:
|
2015-02-13 20:46:14 +01:00
|
|
|
*waitfor = WL_SOCKET_WRITEABLE;
|
|
|
|
errno = EWOULDBLOCK;
|
|
|
|
n = -1;
|
|
|
|
break;
|
2014-08-18 12:04:47 +02:00
|
|
|
case SSL_ERROR_SYSCALL:
|
|
|
|
/* leave it to caller to ereport the value of errno */
|
|
|
|
if (n != -1)
|
|
|
|
{
|
|
|
|
errno = ECONNRESET;
|
|
|
|
n = -1;
|
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
break;
|
2014-08-18 12:04:47 +02:00
|
|
|
case SSL_ERROR_SSL:
|
|
|
|
ereport(COMMERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
errmsg("SSL error: %s", SSLerrmessage(ecode))));
|
2014-08-18 12:04:47 +02:00
|
|
|
errno = ECONNRESET;
|
|
|
|
n = -1;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
break;
|
2017-07-03 13:51:51 +02:00
|
|
|
case SSL_ERROR_ZERO_RETURN:
|
|
|
|
/* connection was cleanly shut down by peer */
|
|
|
|
n = 0;
|
|
|
|
break;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
default:
|
2014-08-18 12:04:47 +02:00
|
|
|
ereport(COMMERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("unrecognized SSL error code: %d",
|
|
|
|
err)));
|
|
|
|
errno = ECONNRESET;
|
|
|
|
n = -1;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
return n;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
ssize_t
|
2015-02-13 20:46:14 +01:00
|
|
|
be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
ssize_t n;
|
|
|
|
int err;
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
unsigned long ecode;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
errno = 0;
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
ERR_clear_error();
|
2014-08-18 12:04:47 +02:00
|
|
|
n = SSL_write(port->ssl, ptr, len);
|
|
|
|
err = SSL_get_error(port->ssl, n);
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
|
2014-08-18 12:04:47 +02:00
|
|
|
switch (err)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
case SSL_ERROR_NONE:
|
2016-08-31 15:24:19 +02:00
|
|
|
/* a-ok */
|
2014-08-18 12:04:47 +02:00
|
|
|
break;
|
|
|
|
case SSL_ERROR_WANT_READ:
|
2015-02-13 20:46:14 +01:00
|
|
|
*waitfor = WL_SOCKET_READABLE;
|
|
|
|
errno = EWOULDBLOCK;
|
|
|
|
n = -1;
|
|
|
|
break;
|
2014-08-18 12:04:47 +02:00
|
|
|
case SSL_ERROR_WANT_WRITE:
|
2015-02-13 20:46:14 +01:00
|
|
|
*waitfor = WL_SOCKET_WRITEABLE;
|
|
|
|
errno = EWOULDBLOCK;
|
|
|
|
n = -1;
|
|
|
|
break;
|
2014-08-18 12:04:47 +02:00
|
|
|
case SSL_ERROR_SYSCALL:
|
|
|
|
/* leave it to caller to ereport the value of errno */
|
|
|
|
if (n != -1)
|
|
|
|
{
|
|
|
|
errno = ECONNRESET;
|
|
|
|
n = -1;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
2014-08-18 12:04:47 +02:00
|
|
|
break;
|
|
|
|
case SSL_ERROR_SSL:
|
|
|
|
ereport(COMMERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
errmsg("SSL error: %s", SSLerrmessage(ecode))));
|
2017-07-03 13:51:51 +02:00
|
|
|
errno = ECONNRESET;
|
|
|
|
n = -1;
|
|
|
|
break;
|
2014-08-18 12:04:47 +02:00
|
|
|
case SSL_ERROR_ZERO_RETURN:
|
2017-08-14 23:29:33 +02:00
|
|
|
|
2017-07-03 13:51:51 +02:00
|
|
|
/*
|
2018-03-19 10:45:44 +01:00
|
|
|
* the SSL connection was closed, leave it to the caller to
|
2017-07-03 13:51:51 +02:00
|
|
|
* ereport it
|
|
|
|
*/
|
2014-08-18 12:04:47 +02:00
|
|
|
errno = ECONNRESET;
|
|
|
|
n = -1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ereport(COMMERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("unrecognized SSL error code: %d",
|
|
|
|
err)));
|
|
|
|
errno = ECONNRESET;
|
|
|
|
n = -1;
|
|
|
|
break;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
return n;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
/* ------------------------------------------------------------ */
|
|
|
|
/* Internal functions */
|
|
|
|
/* ------------------------------------------------------------ */
|
|
|
|
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
/*
|
2014-08-18 12:04:47 +02:00
|
|
|
* Private substitute BIO: this does the sending and receiving using send() and
|
|
|
|
* recv() instead. This is so that we can enable and disable interrupts
|
|
|
|
* just while calling recv(). We cannot have interrupts occurring while
|
2018-06-29 02:45:44 +02:00
|
|
|
* the bulk of OpenSSL runs, because it uses malloc() and possibly other
|
2014-08-18 12:04:47 +02:00
|
|
|
* non-reentrant libc facilities. We also need to call send() and recv()
|
|
|
|
* directly so it gets passed through the socket/signals layer on Win32.
|
|
|
|
*
|
|
|
|
* These functions are closely modelled on the standard socket BIO in OpenSSL;
|
|
|
|
* see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
|
|
|
|
* XXX OpenSSL 1.0.1e considers many more errcodes than just EINTR as reasons
|
|
|
|
* to retry; do we need to adopt their logic for that?
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
*/
|
|
|
|
|
2016-09-15 21:29:39 +02:00
|
|
|
#ifndef HAVE_BIO_GET_DATA
|
Support OpenSSL 1.1.0.
Changes needed to build at all:
- Check for SSL_new in configure, now that SSL_library_init is a macro.
- Do not access struct members directly. This includes some new code in
pgcrypto, to use the resource owner mechanism to ensure that we don't
leak OpenSSL handles, now that we can't embed them in other structs
anymore.
- RAND_SSLeay() -> RAND_OpenSSL()
Changes that were needed to silence deprecation warnings, but were not
strictly necessary:
- RAND_pseudo_bytes() -> RAND_bytes().
- SSL_library_init() and OpenSSL_config() -> OPENSSL_init_ssl()
- ASN1_STRING_data() -> ASN1_STRING_get0_data()
- DH_generate_parameters() -> DH_generate_parameters()
- Locking callbacks are not needed with OpenSSL 1.1.0 anymore. (Good
riddance!)
Also change references to SSLEAY_VERSION_NUMBER with OPENSSL_VERSION_NUMBER,
for the sake of consistency. OPENSSL_VERSION_NUMBER has existed since time
immemorial.
Fix SSL test suite to work with OpenSSL 1.1.0. CA certificates must have
the "CA:true" basic constraint extension now, or OpenSSL will refuse them.
Regenerate the test certificates with that. The "openssl" binary, used to
generate the certificates, is also now more picky, and throws an error
if an X509 extension is specified in "req_extensions", but that section
is empty.
Backpatch to all supported branches, per popular demand. In back-branches,
we still support OpenSSL 0.9.7 and above. OpenSSL 0.9.6 should still work
too, but I didn't test it. In master, we only support 0.9.8 and above.
Patch by Andreas Karlsson, with additional changes by me.
Discussion: <20160627151604.GD1051@msg.df7cb.de>
2016-09-15 11:36:21 +02:00
|
|
|
#define BIO_get_data(bio) (bio->ptr)
|
|
|
|
#define BIO_set_data(bio, data) (bio->ptr = data)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static BIO_METHOD *my_bio_methods = NULL;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
static int
|
|
|
|
my_sock_read(BIO *h, char *buf, int size)
|
|
|
|
{
|
|
|
|
int res = 0;
|
|
|
|
|
|
|
|
if (buf != NULL)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
Support OpenSSL 1.1.0.
Changes needed to build at all:
- Check for SSL_new in configure, now that SSL_library_init is a macro.
- Do not access struct members directly. This includes some new code in
pgcrypto, to use the resource owner mechanism to ensure that we don't
leak OpenSSL handles, now that we can't embed them in other structs
anymore.
- RAND_SSLeay() -> RAND_OpenSSL()
Changes that were needed to silence deprecation warnings, but were not
strictly necessary:
- RAND_pseudo_bytes() -> RAND_bytes().
- SSL_library_init() and OpenSSL_config() -> OPENSSL_init_ssl()
- ASN1_STRING_data() -> ASN1_STRING_get0_data()
- DH_generate_parameters() -> DH_generate_parameters()
- Locking callbacks are not needed with OpenSSL 1.1.0 anymore. (Good
riddance!)
Also change references to SSLEAY_VERSION_NUMBER with OPENSSL_VERSION_NUMBER,
for the sake of consistency. OPENSSL_VERSION_NUMBER has existed since time
immemorial.
Fix SSL test suite to work with OpenSSL 1.1.0. CA certificates must have
the "CA:true" basic constraint extension now, or OpenSSL will refuse them.
Regenerate the test certificates with that. The "openssl" binary, used to
generate the certificates, is also now more picky, and throws an error
if an X509 extension is specified in "req_extensions", but that section
is empty.
Backpatch to all supported branches, per popular demand. In back-branches,
we still support OpenSSL 0.9.7 and above. OpenSSL 0.9.6 should still work
too, but I didn't test it. In master, we only support 0.9.8 and above.
Patch by Andreas Karlsson, with additional changes by me.
Discussion: <20160627151604.GD1051@msg.df7cb.de>
2016-09-15 11:36:21 +02:00
|
|
|
res = secure_raw_read(((Port *) BIO_get_data(h)), buf, size);
|
2014-08-18 12:04:47 +02:00
|
|
|
BIO_clear_retry_flags(h);
|
|
|
|
if (res <= 0)
|
|
|
|
{
|
|
|
|
/* If we were interrupted, tell caller to retry */
|
2015-02-03 22:03:48 +01:00
|
|
|
if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
|
2014-08-18 12:04:47 +02:00
|
|
|
{
|
|
|
|
BIO_set_retry_read(h);
|
|
|
|
}
|
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
my_sock_write(BIO *h, const char *buf, int size)
|
|
|
|
{
|
|
|
|
int res = 0;
|
|
|
|
|
Support OpenSSL 1.1.0.
Changes needed to build at all:
- Check for SSL_new in configure, now that SSL_library_init is a macro.
- Do not access struct members directly. This includes some new code in
pgcrypto, to use the resource owner mechanism to ensure that we don't
leak OpenSSL handles, now that we can't embed them in other structs
anymore.
- RAND_SSLeay() -> RAND_OpenSSL()
Changes that were needed to silence deprecation warnings, but were not
strictly necessary:
- RAND_pseudo_bytes() -> RAND_bytes().
- SSL_library_init() and OpenSSL_config() -> OPENSSL_init_ssl()
- ASN1_STRING_data() -> ASN1_STRING_get0_data()
- DH_generate_parameters() -> DH_generate_parameters()
- Locking callbacks are not needed with OpenSSL 1.1.0 anymore. (Good
riddance!)
Also change references to SSLEAY_VERSION_NUMBER with OPENSSL_VERSION_NUMBER,
for the sake of consistency. OPENSSL_VERSION_NUMBER has existed since time
immemorial.
Fix SSL test suite to work with OpenSSL 1.1.0. CA certificates must have
the "CA:true" basic constraint extension now, or OpenSSL will refuse them.
Regenerate the test certificates with that. The "openssl" binary, used to
generate the certificates, is also now more picky, and throws an error
if an X509 extension is specified in "req_extensions", but that section
is empty.
Backpatch to all supported branches, per popular demand. In back-branches,
we still support OpenSSL 0.9.7 and above. OpenSSL 0.9.6 should still work
too, but I didn't test it. In master, we only support 0.9.8 and above.
Patch by Andreas Karlsson, with additional changes by me.
Discussion: <20160627151604.GD1051@msg.df7cb.de>
2016-09-15 11:36:21 +02:00
|
|
|
res = secure_raw_write(((Port *) BIO_get_data(h)), buf, size);
|
2014-08-18 12:04:47 +02:00
|
|
|
BIO_clear_retry_flags(h);
|
|
|
|
if (res <= 0)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2015-02-03 22:03:48 +01:00
|
|
|
/* If we were interrupted, tell caller to retry */
|
|
|
|
if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
BIO_set_retry_write(h);
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
return res;
|
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
static BIO_METHOD *
|
|
|
|
my_BIO_s_socket(void)
|
|
|
|
{
|
Support OpenSSL 1.1.0.
Changes needed to build at all:
- Check for SSL_new in configure, now that SSL_library_init is a macro.
- Do not access struct members directly. This includes some new code in
pgcrypto, to use the resource owner mechanism to ensure that we don't
leak OpenSSL handles, now that we can't embed them in other structs
anymore.
- RAND_SSLeay() -> RAND_OpenSSL()
Changes that were needed to silence deprecation warnings, but were not
strictly necessary:
- RAND_pseudo_bytes() -> RAND_bytes().
- SSL_library_init() and OpenSSL_config() -> OPENSSL_init_ssl()
- ASN1_STRING_data() -> ASN1_STRING_get0_data()
- DH_generate_parameters() -> DH_generate_parameters()
- Locking callbacks are not needed with OpenSSL 1.1.0 anymore. (Good
riddance!)
Also change references to SSLEAY_VERSION_NUMBER with OPENSSL_VERSION_NUMBER,
for the sake of consistency. OPENSSL_VERSION_NUMBER has existed since time
immemorial.
Fix SSL test suite to work with OpenSSL 1.1.0. CA certificates must have
the "CA:true" basic constraint extension now, or OpenSSL will refuse them.
Regenerate the test certificates with that. The "openssl" binary, used to
generate the certificates, is also now more picky, and throws an error
if an X509 extension is specified in "req_extensions", but that section
is empty.
Backpatch to all supported branches, per popular demand. In back-branches,
we still support OpenSSL 0.9.7 and above. OpenSSL 0.9.6 should still work
too, but I didn't test it. In master, we only support 0.9.8 and above.
Patch by Andreas Karlsson, with additional changes by me.
Discussion: <20160627151604.GD1051@msg.df7cb.de>
2016-09-15 11:36:21 +02:00
|
|
|
if (!my_bio_methods)
|
2014-08-18 12:04:47 +02:00
|
|
|
{
|
Support OpenSSL 1.1.0.
Changes needed to build at all:
- Check for SSL_new in configure, now that SSL_library_init is a macro.
- Do not access struct members directly. This includes some new code in
pgcrypto, to use the resource owner mechanism to ensure that we don't
leak OpenSSL handles, now that we can't embed them in other structs
anymore.
- RAND_SSLeay() -> RAND_OpenSSL()
Changes that were needed to silence deprecation warnings, but were not
strictly necessary:
- RAND_pseudo_bytes() -> RAND_bytes().
- SSL_library_init() and OpenSSL_config() -> OPENSSL_init_ssl()
- ASN1_STRING_data() -> ASN1_STRING_get0_data()
- DH_generate_parameters() -> DH_generate_parameters()
- Locking callbacks are not needed with OpenSSL 1.1.0 anymore. (Good
riddance!)
Also change references to SSLEAY_VERSION_NUMBER with OPENSSL_VERSION_NUMBER,
for the sake of consistency. OPENSSL_VERSION_NUMBER has existed since time
immemorial.
Fix SSL test suite to work with OpenSSL 1.1.0. CA certificates must have
the "CA:true" basic constraint extension now, or OpenSSL will refuse them.
Regenerate the test certificates with that. The "openssl" binary, used to
generate the certificates, is also now more picky, and throws an error
if an X509 extension is specified in "req_extensions", but that section
is empty.
Backpatch to all supported branches, per popular demand. In back-branches,
we still support OpenSSL 0.9.7 and above. OpenSSL 0.9.6 should still work
too, but I didn't test it. In master, we only support 0.9.8 and above.
Patch by Andreas Karlsson, with additional changes by me.
Discussion: <20160627151604.GD1051@msg.df7cb.de>
2016-09-15 11:36:21 +02:00
|
|
|
BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
|
2016-09-15 21:29:39 +02:00
|
|
|
#ifdef HAVE_BIO_METH_NEW
|
Support OpenSSL 1.1.0.
Changes needed to build at all:
- Check for SSL_new in configure, now that SSL_library_init is a macro.
- Do not access struct members directly. This includes some new code in
pgcrypto, to use the resource owner mechanism to ensure that we don't
leak OpenSSL handles, now that we can't embed them in other structs
anymore.
- RAND_SSLeay() -> RAND_OpenSSL()
Changes that were needed to silence deprecation warnings, but were not
strictly necessary:
- RAND_pseudo_bytes() -> RAND_bytes().
- SSL_library_init() and OpenSSL_config() -> OPENSSL_init_ssl()
- ASN1_STRING_data() -> ASN1_STRING_get0_data()
- DH_generate_parameters() -> DH_generate_parameters()
- Locking callbacks are not needed with OpenSSL 1.1.0 anymore. (Good
riddance!)
Also change references to SSLEAY_VERSION_NUMBER with OPENSSL_VERSION_NUMBER,
for the sake of consistency. OPENSSL_VERSION_NUMBER has existed since time
immemorial.
Fix SSL test suite to work with OpenSSL 1.1.0. CA certificates must have
the "CA:true" basic constraint extension now, or OpenSSL will refuse them.
Regenerate the test certificates with that. The "openssl" binary, used to
generate the certificates, is also now more picky, and throws an error
if an X509 extension is specified in "req_extensions", but that section
is empty.
Backpatch to all supported branches, per popular demand. In back-branches,
we still support OpenSSL 0.9.7 and above. OpenSSL 0.9.6 should still work
too, but I didn't test it. In master, we only support 0.9.8 and above.
Patch by Andreas Karlsson, with additional changes by me.
Discussion: <20160627151604.GD1051@msg.df7cb.de>
2016-09-15 11:36:21 +02:00
|
|
|
int my_bio_index;
|
|
|
|
|
|
|
|
my_bio_index = BIO_get_new_index();
|
|
|
|
if (my_bio_index == -1)
|
|
|
|
return NULL;
|
2021-08-17 14:27:37 +02:00
|
|
|
my_bio_index |= (BIO_TYPE_DESCRIPTOR | BIO_TYPE_SOURCE_SINK);
|
Support OpenSSL 1.1.0.
Changes needed to build at all:
- Check for SSL_new in configure, now that SSL_library_init is a macro.
- Do not access struct members directly. This includes some new code in
pgcrypto, to use the resource owner mechanism to ensure that we don't
leak OpenSSL handles, now that we can't embed them in other structs
anymore.
- RAND_SSLeay() -> RAND_OpenSSL()
Changes that were needed to silence deprecation warnings, but were not
strictly necessary:
- RAND_pseudo_bytes() -> RAND_bytes().
- SSL_library_init() and OpenSSL_config() -> OPENSSL_init_ssl()
- ASN1_STRING_data() -> ASN1_STRING_get0_data()
- DH_generate_parameters() -> DH_generate_parameters()
- Locking callbacks are not needed with OpenSSL 1.1.0 anymore. (Good
riddance!)
Also change references to SSLEAY_VERSION_NUMBER with OPENSSL_VERSION_NUMBER,
for the sake of consistency. OPENSSL_VERSION_NUMBER has existed since time
immemorial.
Fix SSL test suite to work with OpenSSL 1.1.0. CA certificates must have
the "CA:true" basic constraint extension now, or OpenSSL will refuse them.
Regenerate the test certificates with that. The "openssl" binary, used to
generate the certificates, is also now more picky, and throws an error
if an X509 extension is specified in "req_extensions", but that section
is empty.
Backpatch to all supported branches, per popular demand. In back-branches,
we still support OpenSSL 0.9.7 and above. OpenSSL 0.9.6 should still work
too, but I didn't test it. In master, we only support 0.9.8 and above.
Patch by Andreas Karlsson, with additional changes by me.
Discussion: <20160627151604.GD1051@msg.df7cb.de>
2016-09-15 11:36:21 +02:00
|
|
|
my_bio_methods = BIO_meth_new(my_bio_index, "PostgreSQL backend socket");
|
|
|
|
if (!my_bio_methods)
|
|
|
|
return NULL;
|
|
|
|
if (!BIO_meth_set_write(my_bio_methods, my_sock_write) ||
|
|
|
|
!BIO_meth_set_read(my_bio_methods, my_sock_read) ||
|
|
|
|
!BIO_meth_set_gets(my_bio_methods, BIO_meth_get_gets(biom)) ||
|
|
|
|
!BIO_meth_set_puts(my_bio_methods, BIO_meth_get_puts(biom)) ||
|
|
|
|
!BIO_meth_set_ctrl(my_bio_methods, BIO_meth_get_ctrl(biom)) ||
|
|
|
|
!BIO_meth_set_create(my_bio_methods, BIO_meth_get_create(biom)) ||
|
2017-01-03 03:37:12 +01:00
|
|
|
!BIO_meth_set_destroy(my_bio_methods, BIO_meth_get_destroy(biom)) ||
|
Support OpenSSL 1.1.0.
Changes needed to build at all:
- Check for SSL_new in configure, now that SSL_library_init is a macro.
- Do not access struct members directly. This includes some new code in
pgcrypto, to use the resource owner mechanism to ensure that we don't
leak OpenSSL handles, now that we can't embed them in other structs
anymore.
- RAND_SSLeay() -> RAND_OpenSSL()
Changes that were needed to silence deprecation warnings, but were not
strictly necessary:
- RAND_pseudo_bytes() -> RAND_bytes().
- SSL_library_init() and OpenSSL_config() -> OPENSSL_init_ssl()
- ASN1_STRING_data() -> ASN1_STRING_get0_data()
- DH_generate_parameters() -> DH_generate_parameters()
- Locking callbacks are not needed with OpenSSL 1.1.0 anymore. (Good
riddance!)
Also change references to SSLEAY_VERSION_NUMBER with OPENSSL_VERSION_NUMBER,
for the sake of consistency. OPENSSL_VERSION_NUMBER has existed since time
immemorial.
Fix SSL test suite to work with OpenSSL 1.1.0. CA certificates must have
the "CA:true" basic constraint extension now, or OpenSSL will refuse them.
Regenerate the test certificates with that. The "openssl" binary, used to
generate the certificates, is also now more picky, and throws an error
if an X509 extension is specified in "req_extensions", but that section
is empty.
Backpatch to all supported branches, per popular demand. In back-branches,
we still support OpenSSL 0.9.7 and above. OpenSSL 0.9.6 should still work
too, but I didn't test it. In master, we only support 0.9.8 and above.
Patch by Andreas Karlsson, with additional changes by me.
Discussion: <20160627151604.GD1051@msg.df7cb.de>
2016-09-15 11:36:21 +02:00
|
|
|
!BIO_meth_set_callback_ctrl(my_bio_methods, BIO_meth_get_callback_ctrl(biom)))
|
|
|
|
{
|
|
|
|
BIO_meth_free(my_bio_methods);
|
|
|
|
my_bio_methods = NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
my_bio_methods = malloc(sizeof(BIO_METHOD));
|
|
|
|
if (!my_bio_methods)
|
|
|
|
return NULL;
|
|
|
|
memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
|
|
|
|
my_bio_methods->bread = my_sock_read;
|
|
|
|
my_bio_methods->bwrite = my_sock_write;
|
|
|
|
#endif
|
2014-08-18 12:04:47 +02:00
|
|
|
}
|
Support OpenSSL 1.1.0.
Changes needed to build at all:
- Check for SSL_new in configure, now that SSL_library_init is a macro.
- Do not access struct members directly. This includes some new code in
pgcrypto, to use the resource owner mechanism to ensure that we don't
leak OpenSSL handles, now that we can't embed them in other structs
anymore.
- RAND_SSLeay() -> RAND_OpenSSL()
Changes that were needed to silence deprecation warnings, but were not
strictly necessary:
- RAND_pseudo_bytes() -> RAND_bytes().
- SSL_library_init() and OpenSSL_config() -> OPENSSL_init_ssl()
- ASN1_STRING_data() -> ASN1_STRING_get0_data()
- DH_generate_parameters() -> DH_generate_parameters()
- Locking callbacks are not needed with OpenSSL 1.1.0 anymore. (Good
riddance!)
Also change references to SSLEAY_VERSION_NUMBER with OPENSSL_VERSION_NUMBER,
for the sake of consistency. OPENSSL_VERSION_NUMBER has existed since time
immemorial.
Fix SSL test suite to work with OpenSSL 1.1.0. CA certificates must have
the "CA:true" basic constraint extension now, or OpenSSL will refuse them.
Regenerate the test certificates with that. The "openssl" binary, used to
generate the certificates, is also now more picky, and throws an error
if an X509 extension is specified in "req_extensions", but that section
is empty.
Backpatch to all supported branches, per popular demand. In back-branches,
we still support OpenSSL 0.9.7 and above. OpenSSL 0.9.6 should still work
too, but I didn't test it. In master, we only support 0.9.8 and above.
Patch by Andreas Karlsson, with additional changes by me.
Discussion: <20160627151604.GD1051@msg.df7cb.de>
2016-09-15 11:36:21 +02:00
|
|
|
return my_bio_methods;
|
2014-08-18 12:04:47 +02:00
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2018-06-29 02:45:44 +02:00
|
|
|
/* This should exactly match OpenSSL's SSL_set_fd except for using my BIO */
|
2014-08-18 12:04:47 +02:00
|
|
|
static int
|
|
|
|
my_SSL_set_fd(Port *port, int fd)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
Support OpenSSL 1.1.0.
Changes needed to build at all:
- Check for SSL_new in configure, now that SSL_library_init is a macro.
- Do not access struct members directly. This includes some new code in
pgcrypto, to use the resource owner mechanism to ensure that we don't
leak OpenSSL handles, now that we can't embed them in other structs
anymore.
- RAND_SSLeay() -> RAND_OpenSSL()
Changes that were needed to silence deprecation warnings, but were not
strictly necessary:
- RAND_pseudo_bytes() -> RAND_bytes().
- SSL_library_init() and OpenSSL_config() -> OPENSSL_init_ssl()
- ASN1_STRING_data() -> ASN1_STRING_get0_data()
- DH_generate_parameters() -> DH_generate_parameters()
- Locking callbacks are not needed with OpenSSL 1.1.0 anymore. (Good
riddance!)
Also change references to SSLEAY_VERSION_NUMBER with OPENSSL_VERSION_NUMBER,
for the sake of consistency. OPENSSL_VERSION_NUMBER has existed since time
immemorial.
Fix SSL test suite to work with OpenSSL 1.1.0. CA certificates must have
the "CA:true" basic constraint extension now, or OpenSSL will refuse them.
Regenerate the test certificates with that. The "openssl" binary, used to
generate the certificates, is also now more picky, and throws an error
if an X509 extension is specified in "req_extensions", but that section
is empty.
Backpatch to all supported branches, per popular demand. In back-branches,
we still support OpenSSL 0.9.7 and above. OpenSSL 0.9.6 should still work
too, but I didn't test it. In master, we only support 0.9.8 and above.
Patch by Andreas Karlsson, with additional changes by me.
Discussion: <20160627151604.GD1051@msg.df7cb.de>
2016-09-15 11:36:21 +02:00
|
|
|
BIO *bio;
|
|
|
|
BIO_METHOD *bio_method;
|
2014-08-18 12:04:47 +02:00
|
|
|
|
Support OpenSSL 1.1.0.
Changes needed to build at all:
- Check for SSL_new in configure, now that SSL_library_init is a macro.
- Do not access struct members directly. This includes some new code in
pgcrypto, to use the resource owner mechanism to ensure that we don't
leak OpenSSL handles, now that we can't embed them in other structs
anymore.
- RAND_SSLeay() -> RAND_OpenSSL()
Changes that were needed to silence deprecation warnings, but were not
strictly necessary:
- RAND_pseudo_bytes() -> RAND_bytes().
- SSL_library_init() and OpenSSL_config() -> OPENSSL_init_ssl()
- ASN1_STRING_data() -> ASN1_STRING_get0_data()
- DH_generate_parameters() -> DH_generate_parameters()
- Locking callbacks are not needed with OpenSSL 1.1.0 anymore. (Good
riddance!)
Also change references to SSLEAY_VERSION_NUMBER with OPENSSL_VERSION_NUMBER,
for the sake of consistency. OPENSSL_VERSION_NUMBER has existed since time
immemorial.
Fix SSL test suite to work with OpenSSL 1.1.0. CA certificates must have
the "CA:true" basic constraint extension now, or OpenSSL will refuse them.
Regenerate the test certificates with that. The "openssl" binary, used to
generate the certificates, is also now more picky, and throws an error
if an X509 extension is specified in "req_extensions", but that section
is empty.
Backpatch to all supported branches, per popular demand. In back-branches,
we still support OpenSSL 0.9.7 and above. OpenSSL 0.9.6 should still work
too, but I didn't test it. In master, we only support 0.9.8 and above.
Patch by Andreas Karlsson, with additional changes by me.
Discussion: <20160627151604.GD1051@msg.df7cb.de>
2016-09-15 11:36:21 +02:00
|
|
|
bio_method = my_BIO_s_socket();
|
|
|
|
if (bio_method == NULL)
|
|
|
|
{
|
|
|
|
SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
bio = BIO_new(bio_method);
|
2014-08-18 12:04:47 +02:00
|
|
|
|
|
|
|
if (bio == NULL)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
|
|
|
|
goto err;
|
|
|
|
}
|
Support OpenSSL 1.1.0.
Changes needed to build at all:
- Check for SSL_new in configure, now that SSL_library_init is a macro.
- Do not access struct members directly. This includes some new code in
pgcrypto, to use the resource owner mechanism to ensure that we don't
leak OpenSSL handles, now that we can't embed them in other structs
anymore.
- RAND_SSLeay() -> RAND_OpenSSL()
Changes that were needed to silence deprecation warnings, but were not
strictly necessary:
- RAND_pseudo_bytes() -> RAND_bytes().
- SSL_library_init() and OpenSSL_config() -> OPENSSL_init_ssl()
- ASN1_STRING_data() -> ASN1_STRING_get0_data()
- DH_generate_parameters() -> DH_generate_parameters()
- Locking callbacks are not needed with OpenSSL 1.1.0 anymore. (Good
riddance!)
Also change references to SSLEAY_VERSION_NUMBER with OPENSSL_VERSION_NUMBER,
for the sake of consistency. OPENSSL_VERSION_NUMBER has existed since time
immemorial.
Fix SSL test suite to work with OpenSSL 1.1.0. CA certificates must have
the "CA:true" basic constraint extension now, or OpenSSL will refuse them.
Regenerate the test certificates with that. The "openssl" binary, used to
generate the certificates, is also now more picky, and throws an error
if an X509 extension is specified in "req_extensions", but that section
is empty.
Backpatch to all supported branches, per popular demand. In back-branches,
we still support OpenSSL 0.9.7 and above. OpenSSL 0.9.6 should still work
too, but I didn't test it. In master, we only support 0.9.8 and above.
Patch by Andreas Karlsson, with additional changes by me.
Discussion: <20160627151604.GD1051@msg.df7cb.de>
2016-09-15 11:36:21 +02:00
|
|
|
BIO_set_data(bio, port);
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
BIO_set_fd(bio, fd, BIO_NOCLOSE);
|
|
|
|
SSL_set_bio(port->ssl, bio, bio);
|
|
|
|
ret = 1;
|
|
|
|
err:
|
|
|
|
return ret;
|
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
/*
|
|
|
|
* Load precomputed DH parameters.
|
|
|
|
*
|
|
|
|
* To prevent "downgrade" attacks, we perform a number of checks
|
|
|
|
* to verify that the DBA-generated DH parameters file contains
|
|
|
|
* what we expect it to contain.
|
|
|
|
*/
|
|
|
|
static DH *
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
load_dh_file(char *filename, bool isServerStart)
|
2014-08-18 12:04:47 +02:00
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
DH *dh = NULL;
|
|
|
|
int codes;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
/* attempt to open file. It's not an error if it doesn't exist. */
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
if ((fp = AllocateFile(filename, "r")) == NULL)
|
|
|
|
{
|
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
|
|
|
(errcode_for_file_access(),
|
|
|
|
errmsg("could not open DH parameters file \"%s\": %m",
|
|
|
|
filename)));
|
2014-08-18 12:04:47 +02:00
|
|
|
return NULL;
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
}
|
2014-08-18 12:04:47 +02:00
|
|
|
|
|
|
|
dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
FreeFile(fp);
|
2014-08-18 12:04:47 +02:00
|
|
|
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
if (dh == NULL)
|
2014-08-18 12:04:47 +02:00
|
|
|
{
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("could not load DH parameters file: %s",
|
|
|
|
SSLerrmessage(ERR_get_error()))));
|
|
|
|
return NULL;
|
2014-08-18 12:04:47 +02:00
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
/* make sure the DH parameters are usable */
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
if (DH_check(dh, &codes) == 0)
|
2014-08-18 12:04:47 +02:00
|
|
|
{
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("invalid DH parameters: %s",
|
|
|
|
SSLerrmessage(ERR_get_error()))));
|
2021-03-20 17:47:21 +01:00
|
|
|
DH_free(dh);
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (codes & DH_CHECK_P_NOT_PRIME)
|
|
|
|
{
|
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("invalid DH parameters: p is not prime")));
|
2021-03-20 17:47:21 +01:00
|
|
|
DH_free(dh);
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if ((codes & DH_NOT_SUITABLE_GENERATOR) &&
|
|
|
|
(codes & DH_CHECK_P_NOT_SAFE_PRIME))
|
|
|
|
{
|
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("invalid DH parameters: neither suitable generator or safe prime")));
|
2021-03-20 17:47:21 +01:00
|
|
|
DH_free(dh);
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
return NULL;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
return dh;
|
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
/*
|
|
|
|
* Load hardcoded DH parameters.
|
|
|
|
*
|
2020-06-04 06:02:59 +02:00
|
|
|
* If DH parameters cannot be loaded from a specified file, we can load
|
2023-05-19 15:57:38 +02:00
|
|
|
* the hardcoded DH parameters supplied with the backend to prevent
|
2020-06-04 06:02:59 +02:00
|
|
|
* problems.
|
2014-08-18 12:04:47 +02:00
|
|
|
*/
|
|
|
|
static DH *
|
|
|
|
load_dh_buffer(const char *buffer, size_t len)
|
|
|
|
{
|
|
|
|
BIO *bio;
|
|
|
|
DH *dh = NULL;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2019-01-29 01:16:24 +01:00
|
|
|
bio = BIO_new_mem_buf(unconstify(char *, buffer), len);
|
2014-08-18 12:04:47 +02:00
|
|
|
if (bio == NULL)
|
|
|
|
return NULL;
|
|
|
|
dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
|
|
|
|
if (dh == NULL)
|
|
|
|
ereport(DEBUG2,
|
|
|
|
(errmsg_internal("DH load buffer: %s",
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
SSLerrmessage(ERR_get_error()))));
|
2014-08-18 12:04:47 +02:00
|
|
|
BIO_free(bio);
|
|
|
|
|
|
|
|
return dh;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
|
2017-01-03 18:33:29 +01:00
|
|
|
/*
|
2018-02-26 19:28:38 +01:00
|
|
|
* Passphrase collection callback using ssl_passphrase_command
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
ssl_external_passwd_cb(char *buf, int size, int rwflag, void *userdata)
|
|
|
|
{
|
|
|
|
/* same prompt as OpenSSL uses internally */
|
|
|
|
const char *prompt = "Enter PEM pass phrase:";
|
|
|
|
|
|
|
|
Assert(rwflag == 0);
|
|
|
|
|
|
|
|
return run_ssl_passphrase_command(prompt, ssl_is_server_start, buf, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Dummy passphrase callback
|
2017-01-03 18:33:29 +01:00
|
|
|
*
|
|
|
|
* If OpenSSL is told to use a passphrase-protected server key, by default
|
|
|
|
* it will issue a prompt on /dev/tty and try to read a key from there.
|
2017-01-04 18:43:52 +01:00
|
|
|
* That's no good during a postmaster SIGHUP cycle, not to mention SSL context
|
|
|
|
* reload in an EXEC_BACKEND postmaster child. So override it with this dummy
|
|
|
|
* function that just returns an empty passphrase, guaranteeing failure.
|
2017-01-03 18:33:29 +01:00
|
|
|
*/
|
|
|
|
static int
|
2018-02-26 19:28:38 +01:00
|
|
|
dummy_ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata)
|
2017-01-03 18:33:29 +01:00
|
|
|
{
|
2017-01-04 18:43:52 +01:00
|
|
|
/* Set flag to change the error message we'll report */
|
2018-02-26 19:28:38 +01:00
|
|
|
dummy_ssl_passwd_cb_called = true;
|
2017-01-04 18:43:52 +01:00
|
|
|
/* And return empty string */
|
2017-01-03 18:33:29 +01:00
|
|
|
Assert(size > 0);
|
|
|
|
buf[0] = '\0';
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
/*
|
2022-09-13 16:10:50 +02:00
|
|
|
* Examines the provided certificate name, and if it's too long to log or
|
|
|
|
* contains unprintable ASCII, escapes and truncates it. The return value is
|
|
|
|
* always a new palloc'd string. (The input string is still modified in place,
|
|
|
|
* for ease of implementation.)
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
*/
|
|
|
|
static char *
|
2022-09-13 16:10:50 +02:00
|
|
|
prepare_cert_name(char *name)
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
{
|
|
|
|
size_t namelen = strlen(name);
|
2022-09-13 16:10:50 +02:00
|
|
|
char *truncated = name;
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Common Names are 64 chars max, so for a common case where the CN is the
|
|
|
|
* last field, we can still print the longest possible CN with a
|
|
|
|
* 7-character prefix (".../CN=[64 chars]"), for a reasonable limit of 71
|
|
|
|
* characters.
|
|
|
|
*/
|
|
|
|
#define MAXLEN 71
|
|
|
|
|
2022-09-13 16:10:50 +02:00
|
|
|
if (namelen > MAXLEN)
|
|
|
|
{
|
|
|
|
/*
|
2023-05-19 23:24:48 +02:00
|
|
|
* Keep the end of the name, not the beginning, since the most
|
|
|
|
* specific field is likely to give users the most information.
|
2022-09-13 16:10:50 +02:00
|
|
|
*/
|
|
|
|
truncated = name + namelen - MAXLEN;
|
|
|
|
truncated[0] = truncated[1] = truncated[2] = '.';
|
|
|
|
namelen = MAXLEN;
|
|
|
|
}
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
|
|
|
|
#undef MAXLEN
|
|
|
|
|
2022-09-13 16:10:50 +02:00
|
|
|
return pg_clean_ascii(truncated, 0);
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
}
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
/*
|
|
|
|
* Certificate verification callback
|
|
|
|
*
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
* This callback allows us to examine intermediate problems during
|
|
|
|
* verification, for later logging.
|
2014-08-18 12:04:47 +02:00
|
|
|
*
|
|
|
|
* This callback also allows us to override the default acceptance
|
|
|
|
* criteria (e.g., accepting self-signed or expired certs), but
|
|
|
|
* for now we accept the default checks.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
verify_cb(int ok, X509_STORE_CTX *ctx)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
int depth;
|
|
|
|
int errcode;
|
|
|
|
const char *errstring;
|
|
|
|
StringInfoData str;
|
|
|
|
X509 *cert;
|
|
|
|
|
|
|
|
if (ok)
|
|
|
|
{
|
|
|
|
/* Nothing to do for the successful case. */
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Pull all the information we have on the verification failure. */
|
|
|
|
depth = X509_STORE_CTX_get_error_depth(ctx);
|
|
|
|
errcode = X509_STORE_CTX_get_error(ctx);
|
|
|
|
errstring = X509_verify_cert_error_string(errcode);
|
|
|
|
|
|
|
|
initStringInfo(&str);
|
|
|
|
appendStringInfo(&str,
|
|
|
|
_("Client certificate verification failed at depth %d: %s."),
|
|
|
|
depth, errstring);
|
|
|
|
|
|
|
|
cert = X509_STORE_CTX_get_current_cert(ctx);
|
|
|
|
if (cert)
|
|
|
|
{
|
|
|
|
char *subject,
|
|
|
|
*issuer;
|
2022-09-13 16:10:50 +02:00
|
|
|
char *sub_prepared,
|
|
|
|
*iss_prepared;
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
char *serialno;
|
|
|
|
ASN1_INTEGER *sn;
|
|
|
|
BIGNUM *b;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the Subject and Issuer for logging, but don't let maliciously
|
2023-05-19 23:24:48 +02:00
|
|
|
* huge certs flood the logs, and don't reflect non-ASCII bytes into
|
|
|
|
* it either.
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
*/
|
|
|
|
subject = X509_NAME_to_cstring(X509_get_subject_name(cert));
|
2022-09-13 16:10:50 +02:00
|
|
|
sub_prepared = prepare_cert_name(subject);
|
|
|
|
pfree(subject);
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
|
|
|
|
issuer = X509_NAME_to_cstring(X509_get_issuer_name(cert));
|
2022-09-13 16:10:50 +02:00
|
|
|
iss_prepared = prepare_cert_name(issuer);
|
|
|
|
pfree(issuer);
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Pull the serial number, too, in case a Subject is still ambiguous.
|
|
|
|
* This mirrors be_tls_get_peer_serial().
|
|
|
|
*/
|
|
|
|
sn = X509_get_serialNumber(cert);
|
|
|
|
b = ASN1_INTEGER_to_BN(sn, NULL);
|
|
|
|
serialno = BN_bn2dec(b);
|
|
|
|
|
|
|
|
appendStringInfoChar(&str, '\n');
|
|
|
|
appendStringInfo(&str,
|
|
|
|
_("Failed certificate data (unverified): subject \"%s\", serial number %s, issuer \"%s\"."),
|
2022-09-13 16:10:50 +02:00
|
|
|
sub_prepared, serialno ? serialno : _("unknown"),
|
|
|
|
iss_prepared);
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
|
|
|
|
BN_free(b);
|
|
|
|
OPENSSL_free(serialno);
|
2022-09-13 16:10:50 +02:00
|
|
|
pfree(iss_prepared);
|
|
|
|
pfree(sub_prepared);
|
Log details for client certificate failures
Currently, debugging client certificate verification failures is
mostly limited to looking at the TLS alert code on the client side.
For simple deployments, sometimes it's enough to see "sslv3 alert
certificate revoked" and know exactly what needs to be fixed, but if
you add any more complexity (multiple CA layers, misconfigured CA
certificates, etc.), trying to debug what happened based on the TLS
alert alone can be an exercise in frustration.
Luckily, the server has more information about exactly what failed in
the chain, and we already have the requisite callback implemented as a
stub. We fill that in, collect the data, and pass the constructed
error message back to the main code via a static variable. This lets
us add our error details directly to the final "could not accept SSL
connection" log message, as opposed to issuing intermediate LOGs.
It ends up looking like
LOG: connection received: host=localhost port=43112
LOG: could not accept SSL connection: certificate verify failed
DETAIL: Client certificate verification failed at depth 1: unable to get local issuer certificate.
Failed certificate data (unverified): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite".
The length of the Subject and Issuer strings is limited to prevent
malicious client certs from spamming the logs. In case the truncation
makes things ambiguous, the certificate's serial number is also
logged.
Author: Jacob Champion <pchampion@vmware.com>
Discussion: https://www.postgresql.org/message-id/flat/d13c4a5787c2a3f83705124f0391e0738c796751.camel@vmware.com
2022-07-15 16:18:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Store our detail message to be logged later. */
|
|
|
|
cert_errdetail = str.data;
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
return ok;
|
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
/*
|
|
|
|
* This callback is used to copy SSL information messages
|
|
|
|
* into the PostgreSQL log.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
info_cb(const SSL *ssl, int type, int args)
|
|
|
|
{
|
2021-01-22 01:26:27 +01:00
|
|
|
const char *desc;
|
|
|
|
|
|
|
|
desc = SSL_state_string_long(ssl);
|
|
|
|
|
2014-08-18 12:04:47 +02:00
|
|
|
switch (type)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
2014-08-18 12:04:47 +02:00
|
|
|
case SSL_CB_HANDSHAKE_START:
|
|
|
|
ereport(DEBUG4,
|
2021-01-22 01:26:27 +01:00
|
|
|
(errmsg_internal("SSL: handshake start: \"%s\"", desc)));
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
break;
|
2014-08-18 12:04:47 +02:00
|
|
|
case SSL_CB_HANDSHAKE_DONE:
|
|
|
|
ereport(DEBUG4,
|
2021-01-22 01:26:27 +01:00
|
|
|
(errmsg_internal("SSL: handshake done: \"%s\"", desc)));
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
break;
|
2014-08-18 12:04:47 +02:00
|
|
|
case SSL_CB_ACCEPT_LOOP:
|
|
|
|
ereport(DEBUG4,
|
2021-01-22 01:26:27 +01:00
|
|
|
(errmsg_internal("SSL: accept loop: \"%s\"", desc)));
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
break;
|
2014-08-18 12:04:47 +02:00
|
|
|
case SSL_CB_ACCEPT_EXIT:
|
|
|
|
ereport(DEBUG4,
|
2021-01-22 01:26:27 +01:00
|
|
|
(errmsg_internal("SSL: accept exit (%d): \"%s\"", args, desc)));
|
2014-08-18 12:04:47 +02:00
|
|
|
break;
|
|
|
|
case SSL_CB_CONNECT_LOOP:
|
|
|
|
ereport(DEBUG4,
|
2021-01-22 01:26:27 +01:00
|
|
|
(errmsg_internal("SSL: connect loop: \"%s\"", desc)));
|
2014-08-18 12:04:47 +02:00
|
|
|
break;
|
|
|
|
case SSL_CB_CONNECT_EXIT:
|
|
|
|
ereport(DEBUG4,
|
2021-01-22 01:26:27 +01:00
|
|
|
(errmsg_internal("SSL: connect exit (%d): \"%s\"", args, desc)));
|
2014-08-18 12:04:47 +02:00
|
|
|
break;
|
|
|
|
case SSL_CB_READ_ALERT:
|
|
|
|
ereport(DEBUG4,
|
2021-01-22 01:26:27 +01:00
|
|
|
(errmsg_internal("SSL: read alert (0x%04x): \"%s\"", args, desc)));
|
2014-08-18 12:04:47 +02:00
|
|
|
break;
|
|
|
|
case SSL_CB_WRITE_ALERT:
|
|
|
|
ereport(DEBUG4,
|
2021-01-22 01:26:27 +01:00
|
|
|
(errmsg_internal("SSL: write alert (0x%04x): \"%s\"", args, desc)));
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
break;
|
|
|
|
}
|
2014-08-18 12:04:47 +02:00
|
|
|
}
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
/*
|
|
|
|
* Set DH parameters for generating ephemeral DH keys. The
|
|
|
|
* DH parameters can take a long time to compute, so they must be
|
|
|
|
* precomputed.
|
|
|
|
*
|
|
|
|
* Since few sites will bother to create a parameter file, we also
|
2018-09-08 21:24:19 +02:00
|
|
|
* provide a fallback to the parameters provided by the OpenSSL
|
|
|
|
* project.
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
*
|
|
|
|
* These values can be static (once loaded or computed) since the
|
|
|
|
* OpenSSL library can efficiently generate random keys from the
|
|
|
|
* information provided.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
initialize_dh(SSL_CTX *context, bool isServerStart)
|
|
|
|
{
|
|
|
|
DH *dh = NULL;
|
|
|
|
|
|
|
|
SSL_CTX_set_options(context, SSL_OP_SINGLE_DH_USE);
|
|
|
|
|
|
|
|
if (ssl_dh_params_file[0])
|
|
|
|
dh = load_dh_file(ssl_dh_params_file, isServerStart);
|
|
|
|
if (!dh)
|
2018-01-19 18:18:42 +01:00
|
|
|
dh = load_dh_buffer(FILE_DH2048, sizeof(FILE_DH2048));
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
if (!dh)
|
|
|
|
{
|
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
2020-01-30 17:32:04 +01:00
|
|
|
errmsg("DH: could not load DH parameters")));
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SSL_CTX_set_tmp_dh(context, dh) != 1)
|
|
|
|
{
|
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
2020-01-30 17:32:04 +01:00
|
|
|
errmsg("DH: could not set DH parameters: %s",
|
|
|
|
SSLerrmessage(ERR_get_error()))));
|
2019-12-14 10:17:31 +01:00
|
|
|
DH_free(dh);
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
return false;
|
|
|
|
}
|
2019-12-14 10:17:31 +01:00
|
|
|
|
|
|
|
DH_free(dh);
|
Always use 2048 bit DH parameters for OpenSSL ephemeral DH ciphers.
1024 bits is considered weak these days, but OpenSSL always passes 1024 as
the key length to the tmp_dh callback. All the code to handle other key
lengths is, in fact, dead.
To remedy those issues:
* Only include hard-coded 2048-bit parameters.
* Set the parameters directly with SSL_CTX_set_tmp_dh(), without the
callback
* The name of the file containing the DH parameters is now a GUC. This
replaces the old hardcoded "dh1024.pem" filename. (The files for other
key lengths, dh512.pem, dh2048.pem, etc. were never actually used.)
This is not a new problem, but it doesn't seem worth the risk and churn to
backport. If you care enough about the strength of the DH parameters on
old versions, you can create custom DH parameters, with as many bits as you
wish, and put them in the "dh1024.pem" file.
Per report by Nicolas Guini and Damian Quiroga. Reviewed by Michael Paquier.
Discussion: https://www.postgresql.org/message-id/CAMxBoUyjOOautVozN6ofzym828aNrDjuCcOTcCquxjwS-L2hGQ@mail.gmail.com
2017-07-31 21:36:09 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set ECDH parameters for generating ephemeral Elliptic Curve DH
|
|
|
|
* keys. This is much simpler than the DH parameters, as we just
|
|
|
|
* need to provide the name of the curve to OpenSSL.
|
|
|
|
*/
|
2017-01-03 03:37:12 +01:00
|
|
|
static bool
|
2017-01-04 18:43:52 +01:00
|
|
|
initialize_ecdh(SSL_CTX *context, bool isServerStart)
|
2014-08-18 12:04:47 +02:00
|
|
|
{
|
2016-08-29 19:16:02 +02:00
|
|
|
#ifndef OPENSSL_NO_ECDH
|
2014-08-18 12:04:47 +02:00
|
|
|
EC_KEY *ecdh;
|
|
|
|
int nid;
|
|
|
|
|
|
|
|
nid = OBJ_sn2nid(SSLECDHCurve);
|
|
|
|
if (!nid)
|
2017-01-03 03:37:12 +01:00
|
|
|
{
|
2017-01-04 18:43:52 +01:00
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
2017-01-03 03:37:12 +01:00
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("ECDH: unrecognized curve name: %s", SSLECDHCurve)));
|
|
|
|
return false;
|
|
|
|
}
|
2014-08-18 12:04:47 +02:00
|
|
|
|
|
|
|
ecdh = EC_KEY_new_by_curve_name(nid);
|
|
|
|
if (!ecdh)
|
2017-01-03 03:37:12 +01:00
|
|
|
{
|
2017-01-04 18:43:52 +01:00
|
|
|
ereport(isServerStart ? FATAL : LOG,
|
2017-01-03 03:37:12 +01:00
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("ECDH: could not create key")));
|
|
|
|
return false;
|
|
|
|
}
|
2014-08-18 12:04:47 +02:00
|
|
|
|
2017-01-03 03:37:12 +01:00
|
|
|
SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
|
|
|
|
SSL_CTX_set_tmp_ecdh(context, ecdh);
|
2014-08-18 12:04:47 +02:00
|
|
|
EC_KEY_free(ecdh);
|
|
|
|
#endif
|
2017-01-03 03:37:12 +01:00
|
|
|
|
|
|
|
return true;
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
* Obtain reason string for passed SSL errcode
|
|
|
|
*
|
|
|
|
* ERR_get_error() is used by caller to get errcode to pass here.
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
*
|
|
|
|
* Some caution is needed here since ERR_reason_error_string will
|
|
|
|
* return NULL if it doesn't recognize the error code. We don't
|
|
|
|
* want to return NULL ever.
|
|
|
|
*/
|
|
|
|
static const char *
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
SSLerrmessage(unsigned long ecode)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
{
|
|
|
|
const char *errreason;
|
2018-03-15 16:10:41 +01:00
|
|
|
static char errbuf[36];
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
if (ecode == 0)
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
return _("no SSL error reported");
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
errreason = ERR_reason_error_string(ecode);
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
if (errreason != NULL)
|
|
|
|
return errreason;
|
Distrust external OpenSSL clients; clear err queue
OpenSSL has an unfortunate tendency to mix per-session state error
handling with per-thread error handling. This can cause problems when
programs that link to libpq with OpenSSL enabled have some other use of
OpenSSL; without care, one caller of OpenSSL may cause problems for the
other caller. Backend code might similarly be affected, for example
when a third party extension independently uses OpenSSL without taking
the appropriate precautions.
To fix, don't trust other users of OpenSSL to clear the per-thread error
queue. Instead, clear the entire per-thread queue ahead of certain I/O
operations when it appears that there might be trouble (these I/O
operations mostly need to call SSL_get_error() to check for success,
which relies on the queue being empty). This is slightly aggressive,
but it's pretty clear that the other callers have a very dubious claim
to ownership of the per-thread queue. Do this is both frontend and
backend code.
Finally, be more careful about clearing our own error queue, so as to
not cause these problems ourself. It's possibly that control previously
did not always reach SSLerrmessage(), where ERR_get_error() was supposed
to be called to clear the queue's earliest code. Make sure
ERR_get_error() is always called, so as to spare other users of OpenSSL
the possibility of similar problems caused by libpq (as opposed to
problems caused by a third party OpenSSL library like PHP's OpenSSL
extension). Again, do this is both frontend and backend code.
See bug #12799 and https://bugs.php.net/bug.php?id=68276
Based on patches by Dave Vitek and Peter Eisentraut.
From: Peter Geoghegan <pg@bowt.ie>
2016-04-08 19:48:14 +02:00
|
|
|
snprintf(errbuf, sizeof(errbuf), _("SSL error code %lu"), ecode);
|
Break out OpenSSL-specific code to separate files.
This refactoring is in preparation for adding support for other SSL
implementations, with no user-visible effects. There are now two #defines,
USE_OPENSSL which is defined when building with OpenSSL, and USE_SSL which
is defined when building with any SSL implementation. Currently, OpenSSL is
the only implementation so the two #defines go together, but USE_SSL is
supposed to be used for implementation-independent code.
The libpq SSL code is changed to use a custom BIO, which does all the raw
I/O, like we've been doing in the backend for a long time. That makes it
possible to use MSG_NOSIGNAL to block SIGPIPE when using SSL, which avoids
a couple of syscall for each send(). Probably doesn't make much performance
difference in practice - the SSL encryption is expensive enough to mask the
effect - but it was a natural result of this refactoring.
Based on a patch by Martijn van Oosterhout from 2006. Briefly reviewed by
Alvaro Herrera, Andreas Karlsson, Jeff Janes.
2014-08-11 10:54:19 +02:00
|
|
|
return errbuf;
|
|
|
|
}
|
2015-04-12 19:07:46 +02:00
|
|
|
|
|
|
|
int
|
|
|
|
be_tls_get_cipher_bits(Port *port)
|
|
|
|
{
|
|
|
|
int bits;
|
|
|
|
|
|
|
|
if (port->ssl)
|
|
|
|
{
|
|
|
|
SSL_get_cipher_bits(port->ssl, &bits);
|
|
|
|
return bits;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-01-25 14:58:00 +01:00
|
|
|
const char *
|
|
|
|
be_tls_get_version(Port *port)
|
2015-04-12 19:07:46 +02:00
|
|
|
{
|
|
|
|
if (port->ssl)
|
2018-01-25 14:58:00 +01:00
|
|
|
return SSL_get_version(port->ssl);
|
2015-04-12 19:07:46 +02:00
|
|
|
else
|
2018-01-25 14:58:00 +01:00
|
|
|
return NULL;
|
2015-04-12 19:07:46 +02:00
|
|
|
}
|
|
|
|
|
2018-01-25 14:58:00 +01:00
|
|
|
const char *
|
|
|
|
be_tls_get_cipher(Port *port)
|
2015-04-12 19:07:46 +02:00
|
|
|
{
|
|
|
|
if (port->ssl)
|
2018-01-25 14:58:00 +01:00
|
|
|
return SSL_get_cipher(port->ssl);
|
2015-04-12 19:07:46 +02:00
|
|
|
else
|
2018-01-25 14:58:00 +01:00
|
|
|
return NULL;
|
2015-04-12 19:07:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-02-01 00:17:45 +01:00
|
|
|
be_tls_get_peer_subject_name(Port *port, char *ptr, size_t len)
|
2015-04-12 19:07:46 +02:00
|
|
|
{
|
|
|
|
if (port->peer)
|
|
|
|
strlcpy(ptr, X509_NAME_to_cstring(X509_get_subject_name(port->peer)), len);
|
|
|
|
else
|
|
|
|
ptr[0] = '\0';
|
|
|
|
}
|
|
|
|
|
2019-02-01 00:17:45 +01:00
|
|
|
void
|
|
|
|
be_tls_get_peer_issuer_name(Port *port, char *ptr, size_t len)
|
|
|
|
{
|
|
|
|
if (port->peer)
|
|
|
|
strlcpy(ptr, X509_NAME_to_cstring(X509_get_issuer_name(port->peer)), len);
|
|
|
|
else
|
|
|
|
ptr[0] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
be_tls_get_peer_serial(Port *port, char *ptr, size_t len)
|
|
|
|
{
|
|
|
|
if (port->peer)
|
|
|
|
{
|
|
|
|
ASN1_INTEGER *serial;
|
|
|
|
BIGNUM *b;
|
|
|
|
char *decimal;
|
|
|
|
|
|
|
|
serial = X509_get_serialNumber(port->peer);
|
|
|
|
b = ASN1_INTEGER_to_BN(serial, NULL);
|
|
|
|
decimal = BN_bn2dec(b);
|
2019-05-22 18:55:34 +02:00
|
|
|
|
2019-02-01 00:17:45 +01:00
|
|
|
BN_free(b);
|
|
|
|
strlcpy(ptr, decimal, len);
|
|
|
|
OPENSSL_free(decimal);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ptr[0] = '\0';
|
|
|
|
}
|
|
|
|
|
Fix handling of SCRAM-SHA-256's channel binding with RSA-PSS certificates
OpenSSL 1.1.1 and newer versions have added support for RSA-PSS
certificates, which requires the use of a specific routine in OpenSSL to
determine which hash function to use when compiling it when using
channel binding in SCRAM-SHA-256. X509_get_signature_nid(), that is the
original routine the channel binding code has relied on, is not able to
determine which hash algorithm to use for such certificates. However,
X509_get_signature_info(), new to OpenSSL 1.1.1, is able to do it. This
commit switches the channel binding logic to rely on
X509_get_signature_info() over X509_get_signature_nid(), which would be
the choice when building with 1.1.1 or newer.
The error could have been triggered on the client or the server, hence
libpq and the backend need to have their related code paths patched.
Note that attempting to load an RSA-PSS certificate with OpenSSL 1.1.0
or older leads to a failure due to an unsupported algorithm.
The discovery of relying on X509_get_signature_info() comes from Jacob,
the tests have been written by Heikki (with few tweaks from me), while I
have bundled the whole together while adding the bits needed for MSVC
and meson.
This issue exists since channel binding exists, so backpatch all the way
down. Some tests are added in 15~, triggered if compiling with OpenSSL
1.1.1 or newer, where the certificate and key files can easily be
generated for RSA-PSS.
Reported-by: Gunnar "Nick" Bluth
Author: Jacob Champion, Heikki Linnakangas
Discussion: https://postgr.es/m/17760-b6c61e752ec07060@postgresql.org
Backpatch-through: 11
2023-02-15 02:12:16 +01:00
|
|
|
#if defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO)
|
2018-01-04 21:18:39 +01:00
|
|
|
char *
|
|
|
|
be_tls_get_certificate_hash(Port *port, size_t *len)
|
|
|
|
{
|
|
|
|
X509 *server_cert;
|
|
|
|
char *cert_hash;
|
|
|
|
const EVP_MD *algo_type = NULL;
|
|
|
|
unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */
|
|
|
|
unsigned int hash_size;
|
|
|
|
int algo_nid;
|
|
|
|
|
|
|
|
*len = 0;
|
|
|
|
server_cert = SSL_get_certificate(port->ssl);
|
|
|
|
if (server_cert == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the signature algorithm of the certificate to determine the hash
|
Fix handling of SCRAM-SHA-256's channel binding with RSA-PSS certificates
OpenSSL 1.1.1 and newer versions have added support for RSA-PSS
certificates, which requires the use of a specific routine in OpenSSL to
determine which hash function to use when compiling it when using
channel binding in SCRAM-SHA-256. X509_get_signature_nid(), that is the
original routine the channel binding code has relied on, is not able to
determine which hash algorithm to use for such certificates. However,
X509_get_signature_info(), new to OpenSSL 1.1.1, is able to do it. This
commit switches the channel binding logic to rely on
X509_get_signature_info() over X509_get_signature_nid(), which would be
the choice when building with 1.1.1 or newer.
The error could have been triggered on the client or the server, hence
libpq and the backend need to have their related code paths patched.
Note that attempting to load an RSA-PSS certificate with OpenSSL 1.1.0
or older leads to a failure due to an unsupported algorithm.
The discovery of relying on X509_get_signature_info() comes from Jacob,
the tests have been written by Heikki (with few tweaks from me), while I
have bundled the whole together while adding the bits needed for MSVC
and meson.
This issue exists since channel binding exists, so backpatch all the way
down. Some tests are added in 15~, triggered if compiling with OpenSSL
1.1.1 or newer, where the certificate and key files can easily be
generated for RSA-PSS.
Reported-by: Gunnar "Nick" Bluth
Author: Jacob Champion, Heikki Linnakangas
Discussion: https://postgr.es/m/17760-b6c61e752ec07060@postgresql.org
Backpatch-through: 11
2023-02-15 02:12:16 +01:00
|
|
|
* algorithm to use for the result. Prefer X509_get_signature_info(),
|
|
|
|
* introduced in OpenSSL 1.1.1, which can handle RSA-PSS signatures.
|
2018-01-04 21:18:39 +01:00
|
|
|
*/
|
Fix handling of SCRAM-SHA-256's channel binding with RSA-PSS certificates
OpenSSL 1.1.1 and newer versions have added support for RSA-PSS
certificates, which requires the use of a specific routine in OpenSSL to
determine which hash function to use when compiling it when using
channel binding in SCRAM-SHA-256. X509_get_signature_nid(), that is the
original routine the channel binding code has relied on, is not able to
determine which hash algorithm to use for such certificates. However,
X509_get_signature_info(), new to OpenSSL 1.1.1, is able to do it. This
commit switches the channel binding logic to rely on
X509_get_signature_info() over X509_get_signature_nid(), which would be
the choice when building with 1.1.1 or newer.
The error could have been triggered on the client or the server, hence
libpq and the backend need to have their related code paths patched.
Note that attempting to load an RSA-PSS certificate with OpenSSL 1.1.0
or older leads to a failure due to an unsupported algorithm.
The discovery of relying on X509_get_signature_info() comes from Jacob,
the tests have been written by Heikki (with few tweaks from me), while I
have bundled the whole together while adding the bits needed for MSVC
and meson.
This issue exists since channel binding exists, so backpatch all the way
down. Some tests are added in 15~, triggered if compiling with OpenSSL
1.1.1 or newer, where the certificate and key files can easily be
generated for RSA-PSS.
Reported-by: Gunnar "Nick" Bluth
Author: Jacob Champion, Heikki Linnakangas
Discussion: https://postgr.es/m/17760-b6c61e752ec07060@postgresql.org
Backpatch-through: 11
2023-02-15 02:12:16 +01:00
|
|
|
#if HAVE_X509_GET_SIGNATURE_INFO
|
|
|
|
if (!X509_get_signature_info(server_cert, &algo_nid, NULL, NULL, NULL))
|
|
|
|
#else
|
2018-01-05 01:09:27 +01:00
|
|
|
if (!OBJ_find_sigid_algs(X509_get_signature_nid(server_cert),
|
2018-01-04 21:18:39 +01:00
|
|
|
&algo_nid, NULL))
|
Fix handling of SCRAM-SHA-256's channel binding with RSA-PSS certificates
OpenSSL 1.1.1 and newer versions have added support for RSA-PSS
certificates, which requires the use of a specific routine in OpenSSL to
determine which hash function to use when compiling it when using
channel binding in SCRAM-SHA-256. X509_get_signature_nid(), that is the
original routine the channel binding code has relied on, is not able to
determine which hash algorithm to use for such certificates. However,
X509_get_signature_info(), new to OpenSSL 1.1.1, is able to do it. This
commit switches the channel binding logic to rely on
X509_get_signature_info() over X509_get_signature_nid(), which would be
the choice when building with 1.1.1 or newer.
The error could have been triggered on the client or the server, hence
libpq and the backend need to have their related code paths patched.
Note that attempting to load an RSA-PSS certificate with OpenSSL 1.1.0
or older leads to a failure due to an unsupported algorithm.
The discovery of relying on X509_get_signature_info() comes from Jacob,
the tests have been written by Heikki (with few tweaks from me), while I
have bundled the whole together while adding the bits needed for MSVC
and meson.
This issue exists since channel binding exists, so backpatch all the way
down. Some tests are added in 15~, triggered if compiling with OpenSSL
1.1.1 or newer, where the certificate and key files can easily be
generated for RSA-PSS.
Reported-by: Gunnar "Nick" Bluth
Author: Jacob Champion, Heikki Linnakangas
Discussion: https://postgr.es/m/17760-b6c61e752ec07060@postgresql.org
Backpatch-through: 11
2023-02-15 02:12:16 +01:00
|
|
|
#endif
|
2018-01-04 21:18:39 +01:00
|
|
|
elog(ERROR, "could not determine server certificate signature algorithm");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The TLS server's certificate bytes need to be hashed with SHA-256 if
|
|
|
|
* its signature algorithm is MD5 or SHA-1 as per RFC 5929
|
|
|
|
* (https://tools.ietf.org/html/rfc5929#section-4.1). If something else
|
|
|
|
* is used, the same hash as the signature algorithm is used.
|
|
|
|
*/
|
|
|
|
switch (algo_nid)
|
|
|
|
{
|
|
|
|
case NID_md5:
|
|
|
|
case NID_sha1:
|
|
|
|
algo_type = EVP_sha256();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
algo_type = EVP_get_digestbynid(algo_nid);
|
|
|
|
if (algo_type == NULL)
|
|
|
|
elog(ERROR, "could not find digest for NID %s",
|
|
|
|
OBJ_nid2sn(algo_nid));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* generate and save the certificate hash */
|
|
|
|
if (!X509_digest(server_cert, algo_type, hash, &hash_size))
|
|
|
|
elog(ERROR, "could not generate server certificate hash");
|
|
|
|
|
|
|
|
cert_hash = palloc(hash_size);
|
|
|
|
memcpy(cert_hash, hash, hash_size);
|
|
|
|
*len = hash_size;
|
|
|
|
|
|
|
|
return cert_hash;
|
|
|
|
}
|
Remove support for tls-unique channel binding.
There are some problems with the tls-unique channel binding type. It's not
supported by all SSL libraries, and strictly speaking it's not defined for
TLS 1.3 at all, even though at least in OpenSSL, the functions used for it
still seem to work with TLS 1.3 connections. And since we had no
mechanism to negotiate what channel binding type to use, there would be
awkward interoperability issues if a server only supported some channel
binding types. tls-server-end-point seems feasible to support with any SSL
library, so let's just stick to that.
This removes the scram_channel_binding libpq option altogether, since there
is now only one supported channel binding type.
This also removes all the channel binding tests from the SSL test suite.
They were really just testing the scram_channel_binding option, which
is now gone. Channel binding is used if both client and server support it,
so it is used in the existing tests. It would be good to have some tests
specifically for channel binding, to make sure it really is used, and the
different combinations of a client and a server that support or doesn't
support it. The current set of settings we have make it hard to write such
tests, but I did test those things manually, by disabling
HAVE_BE_TLS_GET_CERTIFICATE_HASH and/or
HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH.
I also removed the SCRAM_CHANNEL_BINDING_TLS_END_POINT constant. This is a
matter of taste, but IMO it's more readable to just use the
"tls-server-end-point" string.
Refactor the checks on whether the SSL library supports the functions
needed for tls-server-end-point channel binding. Now the server won't
advertise, and the client won't choose, the SCRAM-SHA-256-PLUS variant, if
compiled with an OpenSSL version too old to support it.
In the passing, add some sanity checks to check that the chosen SASL
mechanism, SCRAM-SHA-256 or SCRAM-SHA-256-PLUS, matches whether the SCRAM
exchange used channel binding or not. For example, if the client selects
the non-channel-binding variant SCRAM-SHA-256, but in the SCRAM message
uses channel binding anyway. It's harmless from a security point of view,
I believe, and I'm not sure if there are some other conditions that would
cause the connection to fail, but it seems better to be strict about these
things and check explicitly.
Discussion: https://www.postgresql.org/message-id/ec787074-2305-c6f4-86aa-6902f98485a4%40iki.fi
2018-08-05 12:44:21 +02:00
|
|
|
#endif
|
2018-01-04 21:18:39 +01:00
|
|
|
|
2015-04-12 19:07:46 +02:00
|
|
|
/*
|
|
|
|
* Convert an X509 subject name to a cstring.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
X509_NAME_to_cstring(X509_NAME *name)
|
|
|
|
{
|
|
|
|
BIO *membuf = BIO_new(BIO_s_mem());
|
|
|
|
int i,
|
|
|
|
nid,
|
|
|
|
count = X509_NAME_entry_count(name);
|
|
|
|
X509_NAME_ENTRY *e;
|
|
|
|
ASN1_STRING *v;
|
|
|
|
const char *field_name;
|
|
|
|
size_t size;
|
|
|
|
char nullterm;
|
|
|
|
char *sp;
|
|
|
|
char *dp;
|
|
|
|
char *result;
|
|
|
|
|
2020-11-03 09:55:51 +01:00
|
|
|
if (membuf == NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
2021-09-16 14:48:52 +02:00
|
|
|
errmsg("could not create BIO")));
|
2020-11-03 09:55:51 +01:00
|
|
|
|
2015-04-12 19:07:46 +02:00
|
|
|
(void) BIO_set_close(membuf, BIO_CLOSE);
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
e = X509_NAME_get_entry(name, i);
|
|
|
|
nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(e));
|
2020-11-03 09:55:51 +01:00
|
|
|
if (nid == NID_undef)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("could not get NID for ASN1_OBJECT object")));
|
2015-04-12 19:07:46 +02:00
|
|
|
v = X509_NAME_ENTRY_get_data(e);
|
|
|
|
field_name = OBJ_nid2sn(nid);
|
2020-11-03 09:55:51 +01:00
|
|
|
if (field_name == NULL)
|
2015-04-12 19:07:46 +02:00
|
|
|
field_name = OBJ_nid2ln(nid);
|
2020-11-03 09:55:51 +01:00
|
|
|
if (field_name == NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("could not convert NID %d to an ASN1_OBJECT structure", nid)));
|
2015-04-12 19:07:46 +02:00
|
|
|
BIO_printf(membuf, "/%s=", field_name);
|
|
|
|
ASN1_STRING_print_ex(membuf, v,
|
|
|
|
((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB)
|
|
|
|
| ASN1_STRFLGS_UTF8_CONVERT));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ensure null termination of the BIO's content */
|
|
|
|
nullterm = '\0';
|
|
|
|
BIO_write(membuf, &nullterm, 1);
|
|
|
|
size = BIO_get_mem_data(membuf, &sp);
|
|
|
|
dp = pg_any_to_server(sp, size - 1, PG_UTF8);
|
|
|
|
|
|
|
|
result = pstrdup(dp);
|
|
|
|
if (dp != sp)
|
|
|
|
pfree(dp);
|
2020-11-03 09:55:51 +01:00
|
|
|
if (BIO_free(membuf) != 1)
|
|
|
|
elog(ERROR, "could not free OpenSSL BIO structure");
|
2015-04-12 19:07:46 +02:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2018-11-20 21:49:01 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert TLS protocol version GUC enum to OpenSSL values
|
|
|
|
*
|
|
|
|
* This is a straightforward one-to-one mapping, but doing it this way makes
|
2023-03-02 13:49:39 +01:00
|
|
|
* the definitions of ssl_min_protocol_version and ssl_max_protocol_version
|
|
|
|
* independent of OpenSSL availability and version.
|
2018-11-20 21:49:01 +01:00
|
|
|
*
|
|
|
|
* If a version is passed that is not supported by the current OpenSSL
|
2020-03-23 03:01:41 +01:00
|
|
|
* version, then we return -1. If a nonnegative value is returned,
|
|
|
|
* subsequent code can assume it's working with a supported version.
|
2020-01-28 02:40:48 +01:00
|
|
|
*
|
|
|
|
* Note: this is rather similar to libpq's routine in fe-secure-openssl.c,
|
|
|
|
* so make sure to update both routines if changing this one.
|
2018-11-20 21:49:01 +01:00
|
|
|
*/
|
|
|
|
static int
|
2020-03-23 03:01:41 +01:00
|
|
|
ssl_protocol_version_to_openssl(int v)
|
2018-11-20 21:49:01 +01:00
|
|
|
{
|
|
|
|
switch (v)
|
|
|
|
{
|
|
|
|
case PG_TLS_ANY:
|
|
|
|
return 0;
|
|
|
|
case PG_TLS1_VERSION:
|
|
|
|
return TLS1_VERSION;
|
|
|
|
case PG_TLS1_1_VERSION:
|
|
|
|
#ifdef TLS1_1_VERSION
|
|
|
|
return TLS1_1_VERSION;
|
|
|
|
#else
|
2019-04-28 18:45:55 +02:00
|
|
|
break;
|
2018-11-20 21:49:01 +01:00
|
|
|
#endif
|
|
|
|
case PG_TLS1_2_VERSION:
|
|
|
|
#ifdef TLS1_2_VERSION
|
|
|
|
return TLS1_2_VERSION;
|
|
|
|
#else
|
2019-04-28 18:45:55 +02:00
|
|
|
break;
|
2018-11-20 21:49:01 +01:00
|
|
|
#endif
|
|
|
|
case PG_TLS1_3_VERSION:
|
|
|
|
#ifdef TLS1_3_VERSION
|
|
|
|
return TLS1_3_VERSION;
|
|
|
|
#else
|
2019-04-28 18:45:55 +02:00
|
|
|
break;
|
2018-11-20 21:49:01 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
2020-03-25 22:13:17 +01:00
|
|
|
|
2020-06-27 18:47:58 +02:00
|
|
|
/*
|
|
|
|
* Likewise provide a mapping to strings.
|
|
|
|
*/
|
|
|
|
static const char *
|
|
|
|
ssl_protocol_version_to_string(int v)
|
|
|
|
{
|
|
|
|
switch (v)
|
|
|
|
{
|
|
|
|
case PG_TLS_ANY:
|
|
|
|
return "any";
|
|
|
|
case PG_TLS1_VERSION:
|
|
|
|
return "TLSv1";
|
|
|
|
case PG_TLS1_1_VERSION:
|
|
|
|
return "TLSv1.1";
|
|
|
|
case PG_TLS1_2_VERSION:
|
|
|
|
return "TLSv1.2";
|
|
|
|
case PG_TLS1_3_VERSION:
|
|
|
|
return "TLSv1.3";
|
|
|
|
}
|
|
|
|
|
|
|
|
return "(unrecognized)";
|
|
|
|
}
|
|
|
|
|
2020-03-25 22:13:17 +01:00
|
|
|
|
|
|
|
static void
|
|
|
|
default_openssl_tls_init(SSL_CTX *context, bool isServerStart)
|
|
|
|
{
|
|
|
|
if (isServerStart)
|
|
|
|
{
|
|
|
|
if (ssl_passphrase_command[0])
|
|
|
|
SSL_CTX_set_default_passwd_cb(context, ssl_external_passwd_cb);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (ssl_passphrase_command[0] && ssl_passphrase_command_supports_reload)
|
|
|
|
SSL_CTX_set_default_passwd_cb(context, ssl_external_passwd_cb);
|
|
|
|
else
|
2020-05-14 19:06:38 +02:00
|
|
|
|
2020-03-25 22:13:17 +01:00
|
|
|
/*
|
|
|
|
* If reloading and no external command is configured, override
|
|
|
|
* OpenSSL's default handling of passphrase-protected files,
|
|
|
|
* because we don't want to prompt for a passphrase in an
|
|
|
|
* already-running server.
|
|
|
|
*/
|
|
|
|
SSL_CTX_set_default_passwd_cb(context, dummy_ssl_passwd_cb);
|
|
|
|
}
|
|
|
|
}
|