1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-14 10:13:05 +02:00

OpenSSL 3 support.

There are two changes:

* Suppress deprecation warnings so we can build with -Werror and -Wfatal-errors. At some point we'll need to migrate to the new APIs but there does not seem to be a good reason to support two sets of code right now.

* Update the handling for unexpected EOF to handle EOF or error. The error code for EOF has changed and become harder to identify, but we probably don't care whether it is an error or EOF.
This commit is contained in:
David Steele 2022-06-06 14:47:47 -04:00 committed by GitHub
parent f92ce674f7
commit 08242ee6ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 111 additions and 41 deletions
doc/xml
src/common/io/tls
test/src/module/common

View File

@ -21,6 +21,17 @@
</text>
<release-improvement-list>
<release-item>
<github-pull-request id="1767"/>
<release-item-contributor-list>
<release-item-contributor id="david.steele"/>
<release-item-reviewer id="stephen.frost"/>
</release-item-contributor-list>
<p><proper>OpenSSL 3</proper> support.</p>
</release-item>
<release-item>
<github-pull-request id="1758"/>

View File

@ -107,7 +107,10 @@ tlsServerDh(SSL_CTX *const context)
TRY_BEGIN()
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
DH *const dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
#pragma GCC diagnostic pop
TRY_BEGIN()
{
@ -115,7 +118,10 @@ tlsServerDh(SSL_CTX *const context)
}
FINALLY()
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
DH_free(dh);
#pragma GCC diagnostic pop
}
TRY_END();
}
@ -145,7 +151,10 @@ tlsServerEcdh(SSL_CTX *const context)
const int nid = OBJ_sn2nid(ECHD_CURVE);
cryptoError(nid == NID_undef, "unrecognized ECDH curve " ECHD_CURVE);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
EC_KEY *const ecdh = EC_KEY_new_by_curve_name(nid);
#pragma GCC diagnostic pop
cryptoError(ecdh == NULL, "could not create ecdh key");
SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
@ -156,7 +165,10 @@ tlsServerEcdh(SSL_CTX *const context)
}
FINALLY()
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
EC_KEY_free(ecdh);
#pragma GCC diagnostic pop
}
TRY_END();

View File

@ -126,29 +126,6 @@ tlsSessionResultProcess(TlsSession *this, int errorTls, long unsigned int errorT
switch (errorTls)
{
// The connection was closed
case SSL_ERROR_ZERO_RETURN:
// A syscall failed (this usually indicates unexpected eof)
case SSL_ERROR_SYSCALL:
{
// Error on SSL_ERROR_SYSCALL if unexpected EOF is not allowed
if (errorTls == SSL_ERROR_SYSCALL && !this->ignoreUnexpectedEof)
{
THROW_SYS_ERROR_CODE(errorSys, KernelError, "TLS syscall error");
}
// Else close the connection if we are in a state where it is allowed, e.g. not connecting
else
{
if (!closeOk)
THROW(ProtocolError, "unexpected TLS eof");
this->shutdownOnClose = false;
tlsSessionClose(this);
}
break;
}
// Try again after waiting for read ready
case SSL_ERROR_WANT_READ:
ioReadReadyP(ioSessionIoReadP(this->ioSession), .error = true);
@ -161,15 +138,30 @@ tlsSessionResultProcess(TlsSession *this, int errorTls, long unsigned int errorT
result = 0;
break;
// Any other error that we cannot handle
// Handle graceful termination by the server or unexpected EOF/error
default:
{
// Get detailed error message when available
const char *errorTlsDetailMessage = ERR_reason_error_string(errorTlsDetail);
// Close connection on graceful termination by the server or unexpected EOF/error when allowed
if (errorTls == SSL_ERROR_ZERO_RETURN || this->ignoreUnexpectedEof)
{
if (!closeOk)
THROW(ProtocolError, "unexpected TLS eof");
THROW_FMT(
ServiceError, "TLS error [%d:%lu] %s", errorTls, errorTlsDetail,
errorTlsDetailMessage == NULL ? "no details available" : errorTlsDetailMessage);
this->shutdownOnClose = false;
tlsSessionClose(this);
}
// Else error
else
{
// Get detailed error message when available
const char *errorTlsDetailMessage = ERR_reason_error_string(errorTlsDetail);
THROW_FMT(
ServiceError, "TLS error [%d:%lu] %s", errorTls, errorTlsDetail,
errorTlsDetailMessage == NULL ? "no details available" : errorTlsDetailMessage);
}
break;
}
}

View File

@ -40,7 +40,13 @@ testRun(void)
EVP_MD_CTX *context = EVP_MD_CTX_create();
TEST_ERROR(
cryptoError(EVP_DigestInit_ex(context, NULL, NULL) != 1, "unable to initialize hash context"), CryptoError,
"unable to initialize hash context: [101187723] no digest set");
"unable to initialize hash context: "
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
"[50331787]"
#else
"[101187723]"
#endif
" no digest set");
EVP_MD_CTX_destroy(context);
TEST_ERROR(cryptoError(true, "no error"), CryptoError, "no error: [0] no details available");

View File

@ -398,7 +398,12 @@ testRun(void)
tlsClientNewP(
sckClientNew(STRDEF("localhost"), hrnServerPort(0), 5000, 5000), STRDEF("X"), 0, 0, true,
.caFile = STRDEF("bogus.crt"), .caPath = STRDEF("/bogus"))),
CryptoError, "unable to set user-defined CA certificate location: [33558530] No such file or directory");
CryptoError, "unable to set user-defined CA certificate location: "
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
"[2147483650] no details available");
#else
"[33558530] No such file or directory");
#endif
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("missing client cert");
@ -408,7 +413,12 @@ testRun(void)
tlsClientNewP(
sckClientNew(STRDEF("localhost"), hrnServerPort(0), 5000, 5000), STRDEF("X"), 0, 0, true,
.certFile = STRDEF("/bogus"), .keyFile = STRDEF("/bogus"))),
CryptoError, "unable to load cert file '/bogus': [33558530] No such file or directory");
CryptoError, "unable to load cert file '/bogus': "
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
"[2147483650] no details available");
#else
"[33558530] No such file or directory");
#endif
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("missing client key");
@ -418,7 +428,12 @@ testRun(void)
tlsClientNewP(
sckClientNew(STRDEF("localhost"), hrnServerPort(0), 5000, 5000), STRDEF("X"), 0, 0, true,
.certFile = STRDEF(HRN_SERVER_CLIENT_CERT), .keyFile = STRDEF("/bogus"))),
CryptoError, "unable to load key file '/bogus': [33558530] No such file or directory");
CryptoError, "unable to load key file '/bogus': "
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
"[2147483650] no details available");
#else
"[33558530] No such file or directory");
#endif
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("client cert and key do not match");
@ -428,9 +443,13 @@ testRun(void)
tlsClientNewP(
sckClientNew(STRDEF("localhost"), hrnServerPort(0), 5000, 5000), STRDEF("X"), 0, 0, true,
.certFile = STRDEF(HRN_SERVER_CLIENT_CERT), .keyFile = STRDEF(HRN_SERVER_KEY))),
CryptoError,
"unable to load key file '" HRN_PATH_REPO "/test/certificate/pgbackrest-test-server.key': [185073780] key values"
" mismatch");
CryptoError, "unable to load key file '" HRN_PATH_REPO "/test/certificate/pgbackrest-test-server.key': "
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
"[92274804]"
#else
"[185073780]"
#endif
" key values mismatch");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("client cert with passphrase");
@ -443,7 +462,13 @@ testRun(void)
tlsClientNewP(
sckClientNew(STRDEF("localhost"), hrnServerPort(0), 5000, 5000), STRDEF("X"), 0, 0, true,
.certFile = STRDEF(HRN_SERVER_CLIENT_CERT), .keyFile = STRDEF(TEST_PATH "/client-pwd.key")),
CryptoError, "unable to load key file '" TEST_PATH "/client-pwd.key': [101077092] bad decrypt");
CryptoError, "unable to load key file '" TEST_PATH "/client-pwd.key': "
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
"[478150756]"
#else
"[101077092]"
#endif
" bad decrypt");
}
CATCH(TestError)
{
@ -653,7 +678,13 @@ testRun(void)
TEST_ERROR(
ioServerAccept(tlsServer, socketSession), ServiceError,
"TLS error [1:337100934] certificate verify failed");
"TLS error "
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
"[1:167772294]"
#else
"[1:337100934]"
#endif
" certificate verify failed");
// Valid client cert
socketSession = ioServerAccept(socketServer, NULL);
@ -699,7 +730,13 @@ testRun(void)
TEST_ERROR(
ioRead(ioSessionIoReadP(clientSession), bufNew(1)), ServiceError,
"TLS error [1:336151576] tlsv1 alert unknown ca");
"TLS error "
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
"[1:167773208]"
#else
"[1:336151576]"
#endif
" tlsv1 alert unknown ca");
TEST_RESULT_VOID(ioSessionFree(clientSession), "free client session");
@ -784,7 +821,12 @@ testRun(void)
TEST_RESULT_INT(tlsSessionResultProcess(tlsSession, SSL_ERROR_WANT_WRITE, 0, 0, false), 0, "write ready");
TEST_ERROR(
tlsSessionResultProcess(tlsSession, SSL_ERROR_WANT_X509_LOOKUP, 336031996, 0, false), ServiceError,
"TLS error [4:336031996] unknown protocol");
"TLS error [4:336031996] "
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
"no details available");
#else
"unknown protocol");
#endif
TEST_ERROR(
tlsSessionResultProcess(tlsSession, SSL_ERROR_WANT_X509_LOOKUP, 0, 0, false), ServiceError,
"TLS error [4:0] no details available");
@ -867,7 +909,14 @@ testRun(void)
socketLocal.block = false;
output = bufNew(13);
TEST_ERROR(ioRead(ioSessionIoReadP(session), output), KernelError, "TLS syscall error");
TEST_ERROR(
ioRead(ioSessionIoReadP(session), output), ServiceError,
"TLS error "
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
"[1:167772454] unexpected eof while reading");
#else
"[5:0] no details available");
#endif
// -----------------------------------------------------------------------------------------------------------------
TEST_TITLE("aborted connection ignored and read complete (non-blocking socket)");