]> granicus.if.org Git - postgresql/commitdiff
Improve libpq's error reporting for SSL failures.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 24 Jul 2011 20:29:24 +0000 (16:29 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 24 Jul 2011 20:29:24 +0000 (16:29 -0400)
In many cases, pqsecure_read/pqsecure_write set up useful error messages,
which were then overwritten with useless ones by their callers.  Fix this
by defining the responsibility to set an error message to be entirely that
of the lower-level function when using SSL.

Back-patch to 8.3; the code is too different in 8.2 to be worth the
trouble.

src/interfaces/libpq/fe-misc.c
src/interfaces/libpq/fe-secure.c

index 561d95736e5a553a8ab69c5f261a21a000a56e03..51da84a02a7fe04fdafeedeb793fa878b3bef2ce 100644 (file)
@@ -639,7 +639,9 @@ retry3:
                if (SOCK_ERRNO == ECONNRESET)
                        goto definitelyFailed;
 #endif
-               printfPQExpBuffer(&conn->errorMessage,
+               /* in SSL mode, pqsecure_read set the error message */
+               if (conn->ssl == NULL)
+                       printfPQExpBuffer(&conn->errorMessage,
                                   libpq_gettext("could not receive data from server: %s\n"),
                                                  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                return -1;
@@ -729,7 +731,9 @@ retry4:
                if (SOCK_ERRNO == ECONNRESET)
                        goto definitelyFailed;
 #endif
-               printfPQExpBuffer(&conn->errorMessage,
+               /* in SSL mode, pqsecure_read set the error message */
+               if (conn->ssl == NULL)
+                       printfPQExpBuffer(&conn->errorMessage,
                                   libpq_gettext("could not receive data from server: %s\n"),
                                                  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                return -1;
@@ -745,8 +749,10 @@ retry4:
         * means the connection has been closed.  Cope.
         */
 definitelyFailed:
-       printfPQExpBuffer(&conn->errorMessage,
-                                         libpq_gettext(
+       /* in SSL mode, pqsecure_read set the error message */
+       if (conn->ssl == NULL)
+               printfPQExpBuffer(&conn->errorMessage,
+                                                 libpq_gettext(
                                                                "server closed the connection unexpectedly\n"
                                   "\tThis probably means the server terminated abnormally\n"
                                                         "\tbefore or while processing the request.\n"));
@@ -823,8 +829,10 @@ pqSendSome(PGconn *conn, int len)
 #ifdef ECONNRESET
                                case ECONNRESET:
 #endif
-                                       printfPQExpBuffer(&conn->errorMessage,
-                                                                         libpq_gettext(
+                                       /* in SSL mode, pqsecure_write set the error message */
+                                       if (conn->ssl == NULL)
+                                               printfPQExpBuffer(&conn->errorMessage,
+                                                                                 libpq_gettext(
                                                                "server closed the connection unexpectedly\n"
                                        "\tThis probably means the server terminated abnormally\n"
                                                         "\tbefore or while processing the request.\n"));
@@ -841,7 +849,9 @@ pqSendSome(PGconn *conn, int len)
                                        return -1;
 
                                default:
-                                       printfPQExpBuffer(&conn->errorMessage,
+                                       /* in SSL mode, pqsecure_write set the error message */
+                                       if (conn->ssl == NULL)
+                                               printfPQExpBuffer(&conn->errorMessage,
                                                libpq_gettext("could not send data to server: %s\n"),
                                                        SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                                        /* We don't assume it's a fatal error... */
index 422ef1f1090c194bd9e8e69a0152f1c36a3dca0c..9a98e72fd7f7a6eef5b79332ad1d3060cf3a19e9 100644 (file)
@@ -273,6 +273,11 @@ pqsecure_close(PGconn *conn)
 
 /*
  *     Read data from a secure connection.
+ *
+ * If SSL is in use, this function is responsible for putting a suitable
+ * message into conn->errorMessage upon error; but the caller does that
+ * when not using SSL.  In either case, caller uses the returned errno
+ * to decide whether to continue/retry after error.
  */
 ssize_t
 pqsecure_read(PGconn *conn, void *ptr, size_t len)
@@ -294,6 +299,13 @@ rloop:
                switch (err)
                {
                        case SSL_ERROR_NONE:
+                               if (n < 0)
+                               {
+                                       printfPQExpBuffer(&conn->errorMessage,
+                                                                         libpq_gettext("SSL_read failed but did not provide error information\n"));
+                                       /* assume the connection is broken */
+                                       SOCK_ERRNO_SET(ECONNRESET);
+                               }
                                break;
                        case SSL_ERROR_WANT_READ:
                                n = 0;
@@ -311,7 +323,7 @@ rloop:
                                {
                                        char            sebuf[256];
 
-                                       if (n == -1)
+                                       if (n < 0)
                                        {
                                                REMEMBER_EPIPE(SOCK_ERRNO == EPIPE);
                                                printfPQExpBuffer(&conn->errorMessage,
@@ -322,7 +334,7 @@ rloop:
                                        {
                                                printfPQExpBuffer(&conn->errorMessage,
                                                 libpq_gettext("SSL SYSCALL error: EOF detected\n"));
-
+                                               /* assume the connection is broken */
                                                SOCK_ERRNO_SET(ECONNRESET);
                                                n = -1;
                                        }
@@ -330,14 +342,19 @@ rloop:
                                }
                        case SSL_ERROR_SSL:
                                {
-                                       char       *err = SSLerrmessage();
+                                       char       *errm = SSLerrmessage();
 
                                        printfPQExpBuffer(&conn->errorMessage,
-                                                                         libpq_gettext("SSL error: %s\n"), err);
-                                       SSLerrfree(err);
+                                                                         libpq_gettext("SSL error: %s\n"), errm);
+                                       SSLerrfree(errm);
+                                       /* assume the connection is broken */
+                                       SOCK_ERRNO_SET(ECONNRESET);
+                                       n = -1;
+                                       break;
                                }
-                               /* fall through */
                        case SSL_ERROR_ZERO_RETURN:
+                               printfPQExpBuffer(&conn->errorMessage,
+                                                                 libpq_gettext("SSL connection has been closed unexpectedly\n"));
                                SOCK_ERRNO_SET(ECONNRESET);
                                n = -1;
                                break;
@@ -345,6 +362,8 @@ rloop:
                                printfPQExpBuffer(&conn->errorMessage,
                                                  libpq_gettext("unrecognized SSL error code: %d\n"),
                                                                  err);
+                               /* assume the connection is broken */
+                               SOCK_ERRNO_SET(ECONNRESET);
                                n = -1;
                                break;
                }
@@ -360,6 +379,11 @@ rloop:
 
 /*
  *     Write data to a secure connection.
+ *
+ * If SSL is in use, this function is responsible for putting a suitable
+ * message into conn->errorMessage upon error; but the caller does that
+ * when not using SSL.  In either case, caller uses the returned errno
+ * to decide whether to continue/retry after error.
  */
 ssize_t
 pqsecure_write(PGconn *conn, const void *ptr, size_t len)
@@ -379,6 +403,13 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
                switch (err)
                {
                        case SSL_ERROR_NONE:
+                               if (n < 0)
+                               {
+                                       printfPQExpBuffer(&conn->errorMessage,
+                                                                         libpq_gettext("SSL_write failed but did not provide error information\n"));
+                                       /* assume the connection is broken */
+                                       SOCK_ERRNO_SET(ECONNRESET);
+                               }
                                break;
                        case SSL_ERROR_WANT_READ:
 
@@ -396,7 +427,7 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
                                {
                                        char            sebuf[256];
 
-                                       if (n == -1)
+                                       if (n < 0)
                                        {
                                                REMEMBER_EPIPE(SOCK_ERRNO == EPIPE);
                                                printfPQExpBuffer(&conn->errorMessage,
@@ -407,6 +438,7 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
                                        {
                                                printfPQExpBuffer(&conn->errorMessage,
                                                 libpq_gettext("SSL SYSCALL error: EOF detected\n"));
+                                               /* assume the connection is broken */
                                                SOCK_ERRNO_SET(ECONNRESET);
                                                n = -1;
                                        }
@@ -414,14 +446,19 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
                                }
                        case SSL_ERROR_SSL:
                                {
-                                       char       *err = SSLerrmessage();
+                                       char       *errm = SSLerrmessage();
 
                                        printfPQExpBuffer(&conn->errorMessage,
-                                                                         libpq_gettext("SSL error: %s\n"), err);
-                                       SSLerrfree(err);
+                                                                         libpq_gettext("SSL error: %s\n"), errm);
+                                       SSLerrfree(errm);
+                                       /* assume the connection is broken */
+                                       SOCK_ERRNO_SET(ECONNRESET);
+                                       n = -1;
+                                       break;
                                }
-                               /* fall through */
                        case SSL_ERROR_ZERO_RETURN:
+                               printfPQExpBuffer(&conn->errorMessage,
+                                                                 libpq_gettext("SSL connection has been closed unexpectedly\n"));
                                SOCK_ERRNO_SET(ECONNRESET);
                                n = -1;
                                break;
@@ -429,6 +466,8 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
                                printfPQExpBuffer(&conn->errorMessage,
                                                  libpq_gettext("unrecognized SSL error code: %d\n"),
                                                                  err);
+                               /* assume the connection is broken */
+                               SOCK_ERRNO_SET(ECONNRESET);
                                n = -1;
                                break;
                }