From 15c21bf8e1228abe770a1e7d10b137f05d075a81 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 11 Nov 2001 02:09:05 +0000 Subject: [PATCH] Defend against possibility that SSL error reporting mechanism returns a NULL pointer. Per report from Stephen Pillinger 8-Nov-01. --- src/backend/postmaster/postmaster.c | 43 ++++++++++++++++++++++------ src/interfaces/libpq/fe-connect.c | 44 +++++++++++++++++++++++++++-- 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 67f066515b..0c5d2d1581 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.259 2001/11/10 23:06:12 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.260 2001/11/11 02:09:05 tgl Exp $ * * NOTES * @@ -271,6 +271,7 @@ __attribute__((format(printf, 1, 2))); #ifdef USE_SSL static void InitSSL(void); +static const char *SSLerrmessage(void); #endif @@ -1108,8 +1109,8 @@ ProcessStartupPacket(Port *port, bool SSLdone) !SSL_set_fd(port->ssl, port->sock) || SSL_accept(port->ssl) <= 0) { - elog(DEBUG, "failed to initialize SSL connection: %s (%s)", - ERR_reason_error_string(ERR_get_error()), strerror(errno)); + elog(DEBUG, "failed to initialize SSL connection: %s (%m)", + SSLerrmessage()); return STATUS_ERROR; } } @@ -2379,6 +2380,7 @@ CountChildren(void) } #ifdef USE_SSL + /* * Initialize SSL library and structures */ @@ -2393,31 +2395,56 @@ InitSSL(void) if (!SSL_context) { postmaster_error("failed to create SSL context: %s", - ERR_reason_error_string(ERR_get_error())); + SSLerrmessage()); ExitPostmaster(1); } snprintf(fnbuf, sizeof(fnbuf), "%s/server.crt", DataDir); if (!SSL_CTX_use_certificate_file(SSL_context, fnbuf, SSL_FILETYPE_PEM)) { postmaster_error("failed to load server certificate (%s): %s", - fnbuf, ERR_reason_error_string(ERR_get_error())); + fnbuf, SSLerrmessage()); ExitPostmaster(1); } snprintf(fnbuf, sizeof(fnbuf), "%s/server.key", DataDir); if (!SSL_CTX_use_PrivateKey_file(SSL_context, fnbuf, SSL_FILETYPE_PEM)) { postmaster_error("failed to load private key file (%s): %s", - fnbuf, ERR_reason_error_string(ERR_get_error())); + fnbuf, SSLerrmessage()); ExitPostmaster(1); } if (!SSL_CTX_check_private_key(SSL_context)) { postmaster_error("check of private key failed: %s", - ERR_reason_error_string(ERR_get_error())); + SSLerrmessage()); ExitPostmaster(1); } } -#endif + +/* + * Obtain reason string for last SSL error + * + * 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 * +SSLerrmessage(void) +{ + unsigned long errcode; + const char *errreason; + static char errbuf[32]; + + errcode = ERR_get_error(); + if (errcode == 0) + return "No SSL error reported"; + errreason = ERR_reason_error_string(errcode); + if (errreason != NULL) + return errreason; + snprintf(errbuf, sizeof(errbuf), "SSL error code %lu", errcode); + return errbuf; +} + +#endif /* USE_SSL */ /* * Fire off a subprocess for startup/shutdown/checkpoint. diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index b6d40303d7..28eced2e9b 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.180 2001/11/05 17:46:37 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.181 2001/11/11 02:09:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -186,6 +186,9 @@ static char *conninfo_getval(PQconninfoOption *connOptions, static void defaultNoticeProcessor(void *arg, const char *message); static int parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage); +#ifdef USE_SSL +static const char *SSLerrmessage(void); +#endif /* @@ -961,7 +964,7 @@ connectDBStart(PGconn *conn) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not create SSL context: %s\n"), - ERR_reason_error_string(ERR_get_error())); + SSLerrmessage()); goto connect_errReturn; } } @@ -971,7 +974,7 @@ connectDBStart(PGconn *conn) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not establish SSL connection: %s\n"), - ERR_reason_error_string(ERR_get_error())); + SSLerrmessage()); goto connect_errReturn; } /* SSL connection finished. Continue to send startup packet */ @@ -981,7 +984,12 @@ connectDBStart(PGconn *conn) /* Received error - probably protocol mismatch */ if (conn->Pfdebug) fprintf(conn->Pfdebug, "Postmaster reports error, attempting fallback to pre-7.0.\n"); +#ifdef WIN32 + closesocket(conn->sock); +#else close(conn->sock); +#endif + conn->sock = -1; conn->allow_ssl_try = FALSE; return connectDBStart(conn); } @@ -2610,6 +2618,36 @@ PQconninfoFree(PQconninfoOption *connOptions) free(connOptions); } + +#ifdef USE_SSL + +/* + * Obtain reason string for last SSL error + * + * 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 * +SSLerrmessage(void) +{ + unsigned long errcode; + const char *errreason; + static char errbuf[32]; + + errcode = ERR_get_error(); + if (errcode == 0) + return "No SSL error reported"; + errreason = ERR_reason_error_string(errcode); + if (errreason != NULL) + return errreason; + snprintf(errbuf, sizeof(errbuf), "SSL error code %lu", errcode); + return errbuf; +} + +#endif /* USE_SSL */ + + /* =========== accessor functions for PGconn ========= */ char * PQdb(const PGconn *conn)