]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Use SOCK_ERRNO[_SET] in fe-secure-gssapi.c. REL_13_STABLE github/REL_13_STABLE
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 5 Oct 2025 20:27:47 +0000 (16:27 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 5 Oct 2025 20:27:47 +0000 (16:27 -0400)
On Windows, this code did not handle error conditions correctly at
all, since it looked at "errno" which is not used for socket-related
errors on that platform.  This resulted, for example, in failure
to connect to a PostgreSQL server with GSSAPI enabled.

We have a convention for dealing with this within libpq, which is to
use SOCK_ERRNO and SOCK_ERRNO_SET rather than touching errno directly;
but the GSSAPI code is a relative latecomer and did not get that memo.
(The equivalent backend code continues to use errno, because the
backend does this differently.  Maybe libpq's approach should be
rethought someday.)

Apparently nobody tries to build libpq with GSSAPI support on Windows,
or we'd have heard about this before, because it's been broken all
along.  Back-patch to all supported branches.

Author: Ning Wu <ning94803@gmail.com>
Co-authored-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAFGqpvg-pRw=cdsUpKYfwY6D3d-m9tw8WMcAEE7HHWfm-oYWvw@mail.gmail.com
Backpatch-through: 13

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

index 44d43b7b0eead7a21d9dfe04644cc4f66662dee9..b64332f28cfff5d2a27c78d52f0bedb6c999d709 100644 (file)
@@ -121,7 +121,7 @@ pg_GSS_write(PGconn *conn, const void *ptr, size_t len)
        {
                printfPQExpBuffer(&conn->errorMessage,
                                                  "GSSAPI caller failed to retransmit all data needing to be retried\n");
-               errno = EINVAL;
+               SOCK_ERRNO_SET(EINVAL);
                return -1;
        }
 
@@ -199,7 +199,7 @@ pg_GSS_write(PGconn *conn, const void *ptr, size_t len)
                if (major != GSS_S_COMPLETE)
                {
                        pg_GSS_error(libpq_gettext("GSSAPI wrap error"), conn, major, minor);
-                       errno = EIO;            /* for lack of a better idea */
+                       SOCK_ERRNO_SET(EIO);    /* for lack of a better idea */
                        goto cleanup;
                }
 
@@ -207,7 +207,7 @@ pg_GSS_write(PGconn *conn, const void *ptr, size_t len)
                {
                        printfPQExpBuffer(&conn->errorMessage,
                                                          libpq_gettext("outgoing GSSAPI message would not use confidentiality\n"));
-                       errno = EIO;            /* for lack of a better idea */
+                       SOCK_ERRNO_SET(EIO);    /* for lack of a better idea */
                        goto cleanup;
                }
 
@@ -217,7 +217,7 @@ pg_GSS_write(PGconn *conn, const void *ptr, size_t len)
                                                          libpq_gettext("client tried to send oversize GSSAPI packet (%zu > %zu)\n"),
                                                          (size_t) output.length,
                                                          PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32));
-                       errno = EIO;            /* for lack of a better idea */
+                       SOCK_ERRNO_SET(EIO);    /* for lack of a better idea */
                        goto cleanup;
                }
 
@@ -343,7 +343,7 @@ pg_GSS_read(PGconn *conn, void *ptr, size_t len)
                        /* If we still haven't got the length, return to the caller */
                        if (PqGSSRecvLength < sizeof(uint32))
                        {
-                               errno = EWOULDBLOCK;
+                               SOCK_ERRNO_SET(EWOULDBLOCK);
                                return -1;
                        }
                }
@@ -357,7 +357,7 @@ pg_GSS_read(PGconn *conn, void *ptr, size_t len)
                                                          libpq_gettext("oversize GSSAPI packet sent by the server (%zu > %zu)\n"),
                                                          (size_t) input.length,
                                                          PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32));
-                       errno = EIO;            /* for lack of a better idea */
+                       SOCK_ERRNO_SET(EIO);    /* for lack of a better idea */
                        return -1;
                }
 
@@ -376,7 +376,7 @@ pg_GSS_read(PGconn *conn, void *ptr, size_t len)
                /* If we don't yet have the whole packet, return to the caller */
                if (PqGSSRecvLength - sizeof(uint32) < input.length)
                {
-                       errno = EWOULDBLOCK;
+                       SOCK_ERRNO_SET(EWOULDBLOCK);
                        return -1;
                }
 
@@ -396,7 +396,7 @@ pg_GSS_read(PGconn *conn, void *ptr, size_t len)
                        pg_GSS_error(libpq_gettext("GSSAPI unwrap error"), conn,
                                                 major, minor);
                        ret = -1;
-                       errno = EIO;            /* for lack of a better idea */
+                       SOCK_ERRNO_SET(EIO);    /* for lack of a better idea */
                        goto cleanup;
                }
 
@@ -405,7 +405,7 @@ pg_GSS_read(PGconn *conn, void *ptr, size_t len)
                        printfPQExpBuffer(&conn->errorMessage,
                                                          libpq_gettext("incoming GSSAPI message did not use confidentiality\n"));
                        ret = -1;
-                       errno = EIO;            /* for lack of a better idea */
+                       SOCK_ERRNO_SET(EIO);    /* for lack of a better idea */
                        goto cleanup;
                }
 
@@ -441,7 +441,8 @@ gss_read(PGconn *conn, void *recv_buffer, size_t length, ssize_t *ret)
        *ret = pqsecure_raw_read(conn, recv_buffer, length);
        if (*ret < 0)
        {
-               if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
+               if (SOCK_ERRNO == EAGAIN || SOCK_ERRNO == EWOULDBLOCK ||
+                       SOCK_ERRNO == EINTR)
                        return PGRES_POLLING_READING;
                else
                        return PGRES_POLLING_FAILED;
@@ -461,7 +462,8 @@ gss_read(PGconn *conn, void *recv_buffer, size_t length, ssize_t *ret)
                *ret = pqsecure_raw_read(conn, recv_buffer, length);
                if (*ret < 0)
                {
-                       if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
+                       if (SOCK_ERRNO == EAGAIN || SOCK_ERRNO == EWOULDBLOCK ||
+                               SOCK_ERRNO == EINTR)
                                return PGRES_POLLING_READING;
                        else
                                return PGRES_POLLING_FAILED;
@@ -524,7 +526,8 @@ pqsecure_open_gss(PGconn *conn)
                ret = pqsecure_raw_write(conn, PqGSSSendBuffer + PqGSSSendNext, amount);
                if (ret < 0)
                {
-                       if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
+                       if (SOCK_ERRNO == EAGAIN || SOCK_ERRNO == EWOULDBLOCK ||
+                               SOCK_ERRNO == EINTR)
                                return PGRES_POLLING_WRITING;
                        else
                                return PGRES_POLLING_FAILED;