From: Tom Lane Date: Thu, 10 Apr 2003 23:03:13 +0000 (+0000) Subject: Fix error recovery for SSL_read/SSL_write calls. X-Git-Tag: REL7_3_3~36 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8d477bd33a6e1a49f1c72c09a5c4afd317e2b79d;p=postgresql Fix error recovery for SSL_read/SSL_write calls. --- diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c index 2763eb4616..42e5fbdc21 100644 --- a/src/backend/libpq/be-secure.c +++ b/src/backend/libpq/be-secure.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/be-secure.c,v 1.15.2.10 2003/03/30 21:36:44 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/be-secure.c,v 1.15.2.11 2003/04/10 23:03:13 tgl Exp $ * * Since the server static private key ($DataDir/server.key) * will normally be stored unencrypted so that the database @@ -273,6 +273,7 @@ secure_read(Port *port, void *ptr, size_t len) #ifdef USE_SSL if (port->ssl) { + rloop: n = SSL_read(port->ssl, ptr, len); switch (SSL_get_error(port->ssl, n)) { @@ -280,14 +281,13 @@ secure_read(Port *port, void *ptr, size_t len) port->count += n; break; case SSL_ERROR_WANT_READ: - n = secure_read(port, ptr, len); - break; case SSL_ERROR_WANT_WRITE: - n = secure_write(port, ptr, len); - break; + goto rloop; case SSL_ERROR_SYSCALL: if (n == -1) - elog(COMMERROR, "SSL SYSCALL error: %s", strerror(errno)); + elog(COMMERROR, "SSL SYSCALL error: %m"); + else + elog(COMMERROR, "SSL SYSCALL error: EOF detected"); break; case SSL_ERROR_SSL: elog(COMMERROR, "SSL error: %s", SSLerrmessage()); @@ -297,6 +297,9 @@ secure_read(Port *port, void *ptr, size_t len) errno = ECONNRESET; n = -1; break; + default: + elog(COMMERROR, "Unknown SSL error code"); + break; } } else @@ -323,18 +326,19 @@ secure_write(Port *port, void *ptr, size_t len) { if (port->count > RENEGOTIATION_LIMIT) { - SSL_set_session_id_context(port->ssl, (void *)&SSL_context, sizeof(SSL_context)); - - if (SSL_renegotiate(port->ssl) <= 0) - elog(COMMERROR, "SSL renegotiation failure"); + SSL_set_session_id_context(port->ssl, (void *) &SSL_context, + sizeof(SSL_context)); + if (SSL_renegotiate(port->ssl) <= 0) + elog(COMMERROR, "SSL renegotiation failure"); if (SSL_do_handshake(port->ssl) <= 0) - elog(COMMERROR, "SSL renegotiation failure"); - port->ssl->state=SSL_ST_ACCEPT; + elog(COMMERROR, "SSL renegotiation failure"); + port->ssl->state = SSL_ST_ACCEPT; if (SSL_do_handshake(port->ssl) <= 0) - elog(COMMERROR, "SSL renegotiation failure"); + elog(COMMERROR, "SSL renegotiation failure"); port->count = 0; } + wloop: n = SSL_write(port->ssl, ptr, len); switch (SSL_get_error(port->ssl, n)) { @@ -342,14 +346,13 @@ secure_write(Port *port, void *ptr, size_t len) port->count += n; break; case SSL_ERROR_WANT_READ: - n = secure_read(port, ptr, len); - break; case SSL_ERROR_WANT_WRITE: - n = secure_write(port, ptr, len); - break; + goto wloop; case SSL_ERROR_SYSCALL: if (n == -1) - elog(COMMERROR, "SSL SYSCALL error: %s", strerror(errno)); + elog(COMMERROR, "SSL SYSCALL error: %m"); + else + elog(COMMERROR, "SSL SYSCALL error: EOF detected"); break; case SSL_ERROR_SSL: elog(COMMERROR, "SSL error: %s", SSLerrmessage()); @@ -359,6 +362,9 @@ secure_write(Port *port, void *ptr, size_t len) errno = ECONNRESET; n = -1; break; + default: + elog(COMMERROR, "Unknown SSL error code"); + break; } } else diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c index 9c239253ef..2a4d394187 100644 --- a/src/interfaces/libpq/fe-secure.c +++ b/src/interfaces/libpq/fe-secure.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-secure.c,v 1.15.2.4 2003/01/08 23:18:35 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-secure.c,v 1.15.2.5 2003/04/10 23:03:13 tgl Exp $ * * NOTES * The client *requires* a valid server certificate. Since @@ -262,18 +262,24 @@ pqsecure_read(PGconn *conn, void *ptr, size_t len) #ifdef USE_SSL if (conn->ssl) { + rloop: n = SSL_read(conn->ssl, ptr, len); switch (SSL_get_error(conn->ssl, n)) { case SSL_ERROR_NONE: break; case SSL_ERROR_WANT_READ: - n = pqsecure_read(conn, ptr, len); - break; + case SSL_ERROR_WANT_WRITE: + /* XXX to support nonblock I/O, we should return 0 here */ + goto rloop; case SSL_ERROR_SYSCALL: - printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("SSL SYSCALL error: %s\n"), - SOCK_STRERROR(SOCK_ERRNO)); + if (n == -1) + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("SSL SYSCALL error: %s\n"), + SOCK_STRERROR(SOCK_ERRNO)); + else + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("SSL SYSCALL error: EOF detected\n")); break; case SSL_ERROR_SSL: printfPQExpBuffer(&conn->errorMessage, @@ -284,6 +290,10 @@ pqsecure_read(PGconn *conn, void *ptr, size_t len) SOCK_ERRNO = ECONNRESET; n = -1; break; + default: + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("Unknown SSL error code\n")); + break; } } else @@ -308,18 +318,24 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len) #ifdef USE_SSL if (conn->ssl) { + wloop: n = SSL_write(conn->ssl, ptr, len); switch (SSL_get_error(conn->ssl, n)) { case SSL_ERROR_NONE: break; + case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: - n = pqsecure_write(conn, ptr, len); - break; + /* XXX to support nonblock I/O, we should return 0 here */ + goto wloop; case SSL_ERROR_SYSCALL: - printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("SSL SYSCALL error: %s\n"), - SOCK_STRERROR(SOCK_ERRNO)); + if (n == -1) + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("SSL SYSCALL error: %s\n"), + SOCK_STRERROR(SOCK_ERRNO)); + else + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("SSL SYSCALL error: EOF detected\n")); break; case SSL_ERROR_SSL: printfPQExpBuffer(&conn->errorMessage, @@ -330,6 +346,10 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len) SOCK_ERRNO = ECONNRESET; n = -1; break; + default: + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("Unknown SSL error code\n")); + break; } } else