]> granicus.if.org Git - postgresql/commitdiff
Fix error recovery for SSL_read/SSL_write calls.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 10 Apr 2003 23:03:08 +0000 (23:03 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 10 Apr 2003 23:03:08 +0000 (23:03 +0000)
src/backend/libpq/be-secure.c
src/interfaces/libpq/fe-secure.c

index d854c6c07ceea302750583619d5ffcf784788b58..923f38a98c9b505140107d01af2e045401e2e9e4 100644 (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
index 62ac69d0b4a17d04883c1264d1b924619cac0ef7..beed00b425a8f297d78291b8179981179653565c 100644 (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