mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-24 18:55:04 +08:00
Use BIO functions to avoid passing FILE * pointers to OpenSSL functions.
This fixes potential crashes on old versions of OpenSSL and the requirement on "Applink" in new versions when building with MSVC and using different runtimes. Dave Page with fixes from me.
This commit is contained in:
parent
c2862e3cad
commit
ec4b6a81f6
@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.94 2007/02/16 17:07:00 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.95 2007/10/01 20:30:06 mha Exp $
|
||||
*
|
||||
* NOTES
|
||||
* [ Most of these notes are wrong/obsolete, but perhaps not all ]
|
||||
@ -111,6 +111,7 @@
|
||||
|
||||
#ifdef USE_SSL
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/bio.h>
|
||||
#if (SSLEAY_VERSION_NUMBER >= 0x00907000L)
|
||||
#include <openssl/conf.h>
|
||||
#endif
|
||||
@ -567,6 +568,10 @@ verify_peer(PGconn *conn)
|
||||
* This callback is only called when the server wants a
|
||||
* client cert.
|
||||
*
|
||||
* Since BIO functions can set OpenSSL error codes, we must
|
||||
* reset the OpenSSL error stack on *every* exit from this
|
||||
* function once we've started using BIO.
|
||||
*
|
||||
* Must return 1 on success, 0 on no data or error.
|
||||
*/
|
||||
static int
|
||||
@ -579,8 +584,9 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
||||
struct stat buf2;
|
||||
#endif
|
||||
char fnbuf[MAXPGPATH];
|
||||
FILE *fp;
|
||||
PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
|
||||
FILE *fp;
|
||||
BIO *bio;
|
||||
PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
|
||||
char sebuf[256];
|
||||
|
||||
if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
|
||||
@ -590,16 +596,21 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* save OpenSSL error stack */
|
||||
ERR_set_mark();
|
||||
|
||||
/* read the user certificate */
|
||||
snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
|
||||
if ((fp = fopen(fnbuf, "r")) == NULL)
|
||||
if ((bio = BIO_new_file(fnbuf, "r")) == NULL)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not open certificate file \"%s\": %s\n"),
|
||||
fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||
ERR_pop_to_mark();
|
||||
return 0;
|
||||
}
|
||||
if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
|
||||
|
||||
if (PEM_read_bio_X509(bio, x509, NULL, NULL) == NULL)
|
||||
{
|
||||
char *err = SSLerrmessage();
|
||||
|
||||
@ -607,10 +618,12 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
||||
libpq_gettext("could not read certificate file \"%s\": %s\n"),
|
||||
fnbuf, err);
|
||||
SSLerrfree(err);
|
||||
fclose(fp);
|
||||
BIO_free(bio);
|
||||
ERR_pop_to_mark();
|
||||
return 0;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
BIO_free(bio);
|
||||
|
||||
#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE)
|
||||
if (getenv("PGSSLKEY"))
|
||||
@ -625,6 +638,7 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("invalid value of PGSSLKEY environment variable\n"));
|
||||
ERR_pop_to_mark();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -640,8 +654,9 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
||||
engine_str, err);
|
||||
SSLerrfree(err);
|
||||
free(engine_str);
|
||||
ERR_pop_to_mark();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*pkey = ENGINE_load_private_key(engine_ptr, engine_colon + 1,
|
||||
NULL, NULL);
|
||||
@ -654,8 +669,9 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
||||
engine_colon + 1, engine_str, err);
|
||||
SSLerrfree(err);
|
||||
free(engine_str);
|
||||
ERR_pop_to_mark();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
free(engine_str);
|
||||
}
|
||||
else
|
||||
@ -668,6 +684,7 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("certificate present, but not private key file \"%s\"\n"),
|
||||
fnbuf);
|
||||
ERR_pop_to_mark();
|
||||
return 0;
|
||||
}
|
||||
#ifndef WIN32
|
||||
@ -677,26 +694,32 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("private key file \"%s\" has wrong permissions\n"),
|
||||
fnbuf);
|
||||
ERR_pop_to_mark();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if ((fp = fopen(fnbuf, "r")) == NULL)
|
||||
|
||||
if ((bio = BIO_new_file(fnbuf, "r")) == NULL)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not open private key file \"%s\": %s\n"),
|
||||
fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||
ERR_pop_to_mark();
|
||||
return 0;
|
||||
}
|
||||
#ifndef WIN32
|
||||
BIO_get_fp(bio, &fp);
|
||||
if (fstat(fileno(fp), &buf2) == -1 ||
|
||||
buf.st_dev != buf2.st_dev || buf.st_ino != buf2.st_ino)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("private key file \"%s\" changed during execution\n"), fnbuf);
|
||||
ERR_pop_to_mark();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (PEM_read_PrivateKey(fp, pkey, NULL, NULL) == NULL)
|
||||
|
||||
if (PEM_read_bio_PrivateKey(bio, pkey, NULL, NULL) == NULL)
|
||||
{
|
||||
char *err = SSLerrmessage();
|
||||
|
||||
@ -704,10 +727,13 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
||||
libpq_gettext("could not read private key file \"%s\": %s\n"),
|
||||
fnbuf, err);
|
||||
SSLerrfree(err);
|
||||
fclose(fp);
|
||||
|
||||
BIO_free(bio);
|
||||
ERR_pop_to_mark();
|
||||
return 0;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
BIO_free(bio);
|
||||
}
|
||||
|
||||
/* verify that the cert and key go together */
|
||||
@ -719,9 +745,12 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
||||
libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
|
||||
fnbuf, err);
|
||||
SSLerrfree(err);
|
||||
ERR_pop_to_mark();
|
||||
return 0;
|
||||
}
|
||||
|
||||
ERR_pop_to_mark();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user