Skip to content

Commit 7506677

Browse files
committed
Improve error reporting for SSL connection failures. Remove redundant
free operations in client_cert_cb --- openssl will also attempt to free these structures, resulting in core dumps.
1 parent 88969ea commit 7506677

File tree

2 files changed

+69
-50
lines changed

2 files changed

+69
-50
lines changed

src/backend/libpq/be-secure.c

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.53 2004/11/17 04:05:42 neilc Exp $
14+
* $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.54 2004/11/20 00:18:13 tgl Exp $
1515
*
1616
* Since the server static private key ($DataDir/server.key)
1717
* will normally be stored unencrypted so that the database
@@ -727,37 +727,6 @@ initialize_SSL(void)
727727
return 0;
728728
}
729729

730-
#ifdef WIN32
731-
/*
732-
* Win32 socket code uses nonblocking sockets. We ned to deal with that
733-
* by waiting on the socket if the SSL accept operation didn't complete
734-
* right away.
735-
*/
736-
static int pgwin32_SSL_accept(SSL *ssl)
737-
{
738-
int r;
739-
740-
while (1)
741-
{
742-
int rc;
743-
int waitfor;
744-
745-
r = SSL_accept(ssl);
746-
if (r == 1)
747-
return 1;
748-
749-
rc = SSL_get_error(ssl, r);
750-
if (rc != SSL_ERROR_WANT_READ && rc != SSL_ERROR_WANT_WRITE)
751-
return r;
752-
753-
waitfor = (rc == SSL_ERROR_WANT_READ)?FD_READ|FD_CLOSE|FD_ACCEPT:FD_WRITE|FD_CLOSE;
754-
if (pgwin32_waitforsinglesocket(SSL_get_fd(ssl), waitfor) == 0)
755-
return -1;
756-
}
757-
}
758-
#define SSL_accept(ssl) pgwin32_SSL_accept(ssl)
759-
#endif
760-
761730
/*
762731
* Destroy global SSL context.
763732
*/
@@ -777,7 +746,9 @@ destroy_SSL(void)
777746
static int
778747
open_server_SSL(Port *port)
779748
{
780-
int r;
749+
int r;
750+
int err;
751+
781752
Assert(!port->ssl);
782753
Assert(!port->peer);
783754

@@ -799,12 +770,50 @@ open_server_SSL(Port *port)
799770
close_SSL(port);
800771
return -1;
801772
}
802-
if ((r=SSL_accept(port->ssl)) <= 0)
773+
774+
aloop:
775+
r = SSL_accept(port->ssl);
776+
if (r <= 0)
803777
{
804-
ereport(COMMERROR,
805-
(errcode(ERRCODE_PROTOCOL_VIOLATION),
806-
errmsg("could not accept SSL connection: %i",
807-
SSL_get_error(port->ssl,r))));
778+
err = SSL_get_error(port->ssl, r);
779+
switch (err)
780+
{
781+
case SSL_ERROR_WANT_READ:
782+
case SSL_ERROR_WANT_WRITE:
783+
#ifdef WIN32
784+
pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
785+
(err==SSL_ERROR_WANT_READ) ?
786+
FD_READ|FD_CLOSE|FD_ACCEPT : FD_WRITE|FD_CLOSE);
787+
#endif
788+
goto aloop;
789+
case SSL_ERROR_SYSCALL:
790+
if (r < 0)
791+
ereport(COMMERROR,
792+
(errcode_for_socket_access(),
793+
errmsg("could not accept SSL connection: %m")));
794+
else
795+
ereport(COMMERROR,
796+
(errcode(ERRCODE_PROTOCOL_VIOLATION),
797+
errmsg("could not accept SSL connection: EOF detected")));
798+
break;
799+
case SSL_ERROR_SSL:
800+
ereport(COMMERROR,
801+
(errcode(ERRCODE_PROTOCOL_VIOLATION),
802+
errmsg("could not accept SSL connection: %s",
803+
SSLerrmessage())));
804+
break;
805+
case SSL_ERROR_ZERO_RETURN:
806+
ereport(COMMERROR,
807+
(errcode(ERRCODE_PROTOCOL_VIOLATION),
808+
errmsg("could not accept SSL connection: EOF detected")));
809+
break;
810+
default:
811+
ereport(COMMERROR,
812+
(errcode(ERRCODE_PROTOCOL_VIOLATION),
813+
errmsg("unrecognized SSL error code: %d",
814+
err)));
815+
break;
816+
}
808817
close_SSL(port);
809818
return -1;
810819
}

src/interfaces/libpq/fe-secure.c

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.55 2004/10/16 03:26:43 momjian Exp $
14+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.56 2004/11/20 00:18:18 tgl Exp $
1515
*
1616
* NOTES
1717
* [ Most of these notes are wrong/obsolete, but perhaps not all ]
@@ -267,6 +267,11 @@ pqsecure_open_client(PGconn *conn)
267267
close_SSL(conn);
268268
return PGRES_POLLING_FAILED;
269269
}
270+
/*
271+
* Initialize errorMessage to empty. This allows open_client_SSL()
272+
* to detect whether client_cert_cb() has stored a message.
273+
*/
274+
resetPQExpBuffer(&conn->errorMessage);
270275
}
271276
/* Begin or continue the actual handshake */
272277
return open_client_SSL(conn);
@@ -797,7 +802,6 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
797802
printfPQExpBuffer(&conn->errorMessage,
798803
libpq_gettext("certificate present, but not private key file \"%s\"\n"),
799804
fnbuf);
800-
X509_free(*x509);
801805
return 0;
802806
}
803807
if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) ||
@@ -806,23 +810,20 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
806810
printfPQExpBuffer(&conn->errorMessage,
807811
libpq_gettext("private key file \"%s\" has wrong permissions\n"),
808812
fnbuf);
809-
X509_free(*x509);
810813
return 0;
811814
}
812815
if ((fp = fopen(fnbuf, "r")) == NULL)
813816
{
814817
printfPQExpBuffer(&conn->errorMessage,
815818
libpq_gettext("could not open private key file \"%s\": %s\n"),
816819
fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
817-
X509_free(*x509);
818820
return 0;
819821
}
820822
if (fstat(fileno(fp), &buf2) == -1 ||
821823
buf.st_dev != buf2.st_dev || buf.st_ino != buf2.st_ino)
822824
{
823825
printfPQExpBuffer(&conn->errorMessage,
824826
libpq_gettext("private key file \"%s\" changed during execution\n"), fnbuf);
825-
X509_free(*x509);
826827
return 0;
827828
}
828829
if (PEM_read_PrivateKey(fp, pkey, cb, NULL) == NULL)
@@ -833,7 +834,6 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
833834
libpq_gettext("could not read private key file \"%s\": %s\n"),
834835
fnbuf, err);
835836
SSLerrfree(err);
836-
X509_free(*x509);
837837
fclose(fp);
838838
return 0;
839839
}
@@ -848,8 +848,6 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
848848
libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
849849
fnbuf, err);
850850
SSLerrfree(err);
851-
X509_free(*x509);
852-
EVP_PKEY_free(*pkey);
853851
return 0;
854852
}
855853

@@ -1045,11 +1043,23 @@ open_client_SSL(PGconn *conn)
10451043
}
10461044
case SSL_ERROR_SSL:
10471045
{
1048-
char *err = SSLerrmessage();
1046+
/*
1047+
* If there are problems with the local certificate files,
1048+
* these will be detected by client_cert_cb() which is
1049+
* called from SSL_connect(). We want to return that
1050+
* error message and not the rather unhelpful error that
1051+
* OpenSSL itself returns. So check to see if an error
1052+
* message was already stored.
1053+
*/
1054+
if (conn->errorMessage.len == 0)
1055+
{
1056+
char *err = SSLerrmessage();
10491057

1050-
printfPQExpBuffer(&conn->errorMessage,
1051-
libpq_gettext("SSL error: %s\n"), err);
1052-
SSLerrfree(err);
1058+
printfPQExpBuffer(&conn->errorMessage,
1059+
libpq_gettext("SSL error: %s\n"),
1060+
err);
1061+
SSLerrfree(err);
1062+
}
10531063
close_SSL(conn);
10541064
return PGRES_POLLING_FAILED;
10551065
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy