Fix error recovery for SSL_read/SSL_write calls.

This commit is contained in:
Tom Lane 2003-04-10 23:03:08 +00:00
parent 76b45c9842
commit 5674460bb0
2 changed files with 47 additions and 23 deletions

View File

@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/be-secure.c,v 1.28 2003/03/29 05:00:15 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/libpq/be-secure.c,v 1.29 2003/04/10 23:03:08 tgl Exp $
*
* Since the server static private key ($DataDir/server.key)
* will normally be stored unencrypted so that the database
@ -276,6 +276,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))
{
@ -283,14 +284,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());
@ -300,6 +300,9 @@ secure_read(Port *port, void *ptr, size_t len)
errno = ECONNRESET;
n = -1;
break;
default:
elog(COMMERROR, "Unknown SSL error code");
break;
}
}
else
@ -322,18 +325,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))
{
@ -341,14 +345,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());
@ -358,6 +361,9 @@ secure_write(Port *port, void *ptr, size_t len)
errno = ECONNRESET;
n = -1;
break;
default:
elog(COMMERROR, "Unknown SSL error code");
break;
}
}
else

View File

@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-secure.c,v 1.21 2003/02/03 22:33:51 tgl Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-secure.c,v 1.22 2003/04/10 23:03:08 tgl Exp $
*
* NOTES
* The client *requires* a valid server certificate. Since
@ -266,19 +266,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:
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,
@ -289,6 +294,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
@ -313,19 +322,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:
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,
@ -336,6 +350,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