aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2020-12-28 17:44:17 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2020-12-28 17:44:17 -0500
commit622ae4621ece72a9f64b5602c74d7aaf373c1631 (patch)
tree467f643f181e5784f01ef02694a4452e69a611a0 /src
parentff6ce9a3a691a96e8e47ed449bc51c5a178e6931 (diff)
downloadpostgresql-622ae4621ece72a9f64b5602c74d7aaf373c1631.tar.gz
postgresql-622ae4621ece72a9f64b5602c74d7aaf373c1631.zip
Fix assorted issues in backend's GSSAPI encryption support.
Unrecoverable errors detected by GSSAPI encryption can't just be reported with elog(ERROR) or elog(FATAL), because attempting to send the error report to the client is likely to lead to infinite recursion or loss of protocol sync. Instead make this code do what the SSL encryption code has long done, which is to just report any such failure to the server log (with elevel COMMERROR), then pretend we've lost the connection by returning errno = ECONNRESET. Along the way, fix confusion about whether message translation is done by pg_GSS_error() or its callers (the latter should do it), and make the backend version of that function work more like the frontend version. Avoid allocating the port->gss struct until it's needed; we surely don't need to allocate it in the postmaster. Improve logging of "connection authorized" messages with GSS enabled. (As part of this, I back-patched the code changes from dc11f31a1.) Make BackendStatusShmemSize() account for the GSS-related space that will be allocated by CreateSharedBackendStatus(). This omission could possibly cause out-of-shared-memory problems with very high max_connections settings. Remove arbitrary, pointless restriction that only GSS authentication can be used on a GSS-encrypted connection. Improve documentation; notably, document the fact that libpq now prefers GSS encryption over SSL encryption if both are possible. Per report from Mikael Gustavsson. Back-patch to v12 where this code was introduced. Discussion: https://postgr.es/m/e5b0b6ed05764324a2f3fe7acfc766d5@smhi.se
Diffstat (limited to 'src')
-rw-r--r--src/backend/libpq/auth.c35
-rw-r--r--src/backend/libpq/be-gssapi-common.c51
-rw-r--r--src/backend/libpq/be-secure-gssapi.c98
-rw-r--r--src/backend/libpq/be-secure.c4
-rw-r--r--src/backend/libpq/hba.c19
-rw-r--r--src/backend/libpq/pqcomm.c27
-rw-r--r--src/backend/postmaster/pgstat.c12
-rw-r--r--src/backend/postmaster/postmaster.c37
-rw-r--r--src/backend/utils/init/postinit.c21
-rw-r--r--src/include/libpq/be-gssapi-common.h2
-rw-r--r--src/include/libpq/libpq-be.h5
11 files changed, 178 insertions, 133 deletions
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 3d809309685..d4ec965934a 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -382,17 +382,6 @@ ClientAuthentication(Port *port)
errmsg("connection requires a valid client certificate")));
}
-#ifdef ENABLE_GSS
- if (port->gss->enc && port->hba->auth_method != uaReject &&
- port->hba->auth_method != uaImplicitReject &&
- port->hba->auth_method != uaTrust &&
- port->hba->auth_method != uaGSS)
- {
- ereport(FATAL, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
- errmsg("GSSAPI encryption can only be used with gss, trust, or reject authentication methods")));
- }
-#endif
-
/*
* Now proceed to do the actual authentication check
*/
@@ -533,7 +522,17 @@ ClientAuthentication(Port *port)
case uaGSS:
#ifdef ENABLE_GSS
+ /* We might or might not have the gss workspace already */
+ if (port->gss == NULL)
+ port->gss = (pg_gssinfo *)
+ MemoryContextAllocZero(TopMemoryContext,
+ sizeof(pg_gssinfo));
port->gss->auth = true;
+
+ /*
+ * If GSS state was set up while enabling encryption, we can just
+ * check the client's principal. Otherwise, ask for it.
+ */
if (port->gss->enc)
status = pg_GSS_checkauth(port);
else
@@ -548,6 +547,10 @@ ClientAuthentication(Port *port)
case uaSSPI:
#ifdef ENABLE_SSPI
+ if (port->gss == NULL)
+ port->gss = (pg_gssinfo *)
+ MemoryContextAllocZero(TopMemoryContext,
+ sizeof(pg_gssinfo));
sendAuthRequest(port, AUTH_REQ_SSPI, NULL, 0);
status = pg_SSPI_recvauth(port);
#else
@@ -1185,9 +1188,9 @@ pg_GSS_recvauth(Port *port)
if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
{
gss_delete_sec_context(&lmin_s, &port->gss->ctx, GSS_C_NO_BUFFER);
- pg_GSS_error(ERROR,
- _("accepting GSS security context failed"),
+ pg_GSS_error(_("accepting GSS security context failed"),
maj_stat, min_stat);
+ return STATUS_ERROR;
}
if (maj_stat == GSS_S_CONTINUE_NEEDED)
@@ -1224,9 +1227,11 @@ pg_GSS_checkauth(Port *port)
*/
maj_stat = gss_display_name(&min_stat, port->gss->name, &gbuf, NULL);
if (maj_stat != GSS_S_COMPLETE)
- pg_GSS_error(ERROR,
- _("retrieving GSS user name failed"),
+ {
+ pg_GSS_error(_("retrieving GSS user name failed"),
maj_stat, min_stat);
+ return STATUS_ERROR;
+ }
/*
* Copy the original name of the authenticated principal into our backend
diff --git a/src/backend/libpq/be-gssapi-common.c b/src/backend/libpq/be-gssapi-common.c
index ef9b8ebd6d4..be5d051c202 100644
--- a/src/backend/libpq/be-gssapi-common.c
+++ b/src/backend/libpq/be-gssapi-common.c
@@ -17,8 +17,9 @@
#include "libpq/be-gssapi-common.h"
/*
- * Helper function for getting all strings of a GSSAPI error (of specified
- * stat). Call once for GSS_CODE and once for MECH_CODE.
+ * Fetch all errors of a specific type and append to "s" (buffer of size len).
+ * If we obtain more than one string, separate them with spaces.
+ * Call once for GSS_CODE and once for MECH_CODE.
*/
static void
pg_GSS_error_int(char *s, size_t len, OM_uint32 stat, int type)
@@ -28,31 +29,49 @@ pg_GSS_error_int(char *s, size_t len, OM_uint32 stat, int type)
OM_uint32 lmin_s,
msg_ctx = 0;
- gmsg.value = NULL;
- gmsg.length = 0;
+ s[0] = '\0'; /* just in case gss_display_status fails */
do
{
- gss_display_status(&lmin_s, stat, type,
- GSS_C_NO_OID, &msg_ctx, &gmsg);
- strlcpy(s + i, gmsg.value, len - i);
+ if (gss_display_status(&lmin_s, stat, type, GSS_C_NO_OID,
+ &msg_ctx, &gmsg) != GSS_S_COMPLETE)
+ break;
+ if (i > 0)
+ {
+ if (i < len)
+ s[i] = ' ';
+ i++;
+ }
+ if (i < len)
+ strlcpy(s + i, gmsg.value, len - i);
i += gmsg.length;
gss_release_buffer(&lmin_s, &gmsg);
}
- while (msg_ctx && i < len);
+ while (msg_ctx);
- if (msg_ctx || i == len)
- ereport(WARNING,
- (errmsg_internal("incomplete GSS error report")));
+ if (i >= len)
+ {
+ elog(COMMERROR, "incomplete GSS error report");
+ s[len - 1] = '\0'; /* ensure string is nul-terminated */
+ }
}
/*
- * Fetch and report all error messages from GSSAPI. To avoid allocation,
- * total error size is capped (at 128 bytes for each of major and minor). No
- * known mechanisms will produce error messages beyond this cap.
+ * Report the GSSAPI error described by maj_stat/min_stat.
+ *
+ * errmsg should be an already-translated primary error message.
+ * The GSSAPI info is appended as errdetail.
+ *
+ * The error is always reported with elevel COMMERROR; we daren't try to
+ * send it to the client, as that'd likely lead to infinite recursion
+ * when elog.c tries to write to the client.
+ *
+ * To avoid memory allocation, total error size is capped (at 128 bytes for
+ * each of major and minor). No known mechanisms will produce error messages
+ * beyond this cap.
*/
void
-pg_GSS_error(int severity, const char *errmsg,
+pg_GSS_error(const char *errmsg,
OM_uint32 maj_stat, OM_uint32 min_stat)
{
char msg_major[128],
@@ -68,7 +87,7 @@ pg_GSS_error(int severity, const char *errmsg,
* errmsg_internal, since translation of the first part must be done
* before calling this function anyway.
*/
- ereport(severity,
+ ereport(COMMERROR,
(errmsg_internal("%s", errmsg),
errdetail_internal("%s: %s", msg_major, msg_minor)));
}
diff --git a/src/backend/libpq/be-secure-gssapi.c b/src/backend/libpq/be-secure-gssapi.c
index 5a73302b7b9..1747fccb143 100644
--- a/src/backend/libpq/be-secure-gssapi.c
+++ b/src/backend/libpq/be-secure-gssapi.c
@@ -21,6 +21,7 @@
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "pgstat.h"
+#include "utils/memutils.h"
/*
@@ -81,10 +82,14 @@ static uint32 PqGSSMaxPktSize; /* Maximum size we can encrypt and fit the
* transport negotiation is complete).
*
* On success, returns the number of data bytes consumed (possibly less than
- * len). On failure, returns -1 with errno set appropriately. (For fatal
- * errors, we may just elog and exit, if errno wouldn't be sufficient to
- * describe the error.) For retryable errors, caller should call again
- * (passing the same data) once the socket is ready.
+ * len). On failure, returns -1 with errno set appropriately. For retryable
+ * errors, caller should call again (passing the same data) once the socket
+ * is ready.
+ *
+ * Dealing with fatal errors here is a bit tricky: we can't invoke elog(FATAL)
+ * since it would try to write to the client, probably resulting in infinite
+ * recursion. Instead, use elog(COMMERROR) to log extra info about the
+ * failure if necessary, and then return an errno indicating connection loss.
*/
ssize_t
be_gssapi_write(Port *port, void *ptr, size_t len)
@@ -108,8 +113,11 @@ be_gssapi_write(Port *port, void *ptr, size_t len)
* again, so if it offers a len less than that, something is wrong.
*/
if (len < PqGSSSendConsumed)
- elog(FATAL, "GSSAPI caller failed to retransmit all data needing to be retried");
-
+ {
+ elog(COMMERROR, "GSSAPI caller failed to retransmit all data needing to be retried");
+ errno = ECONNRESET;
+ return -1;
+ }
/* Discount whatever source data we already encrypted. */
bytes_to_encrypt = len - PqGSSSendConsumed;
bytes_encrypted = PqGSSSendConsumed;
@@ -192,17 +200,27 @@ be_gssapi_write(Port *port, void *ptr, size_t len)
major = gss_wrap(&minor, gctx, 1, GSS_C_QOP_DEFAULT,
&input, &conf_state, &output);
if (major != GSS_S_COMPLETE)
- pg_GSS_error(FATAL, gettext_noop("GSSAPI wrap error"), major, minor);
-
+ {
+ pg_GSS_error(_("GSSAPI wrap error"), major, minor);
+ errno = ECONNRESET;
+ return -1;
+ }
if (conf_state == 0)
- ereport(FATAL,
+ {
+ ereport(COMMERROR,
(errmsg("outgoing GSSAPI message would not use confidentiality")));
-
+ errno = ECONNRESET;
+ return -1;
+ }
if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))
- ereport(FATAL,
+ {
+ ereport(COMMERROR,
(errmsg("server tried to send oversize GSSAPI packet (%zu > %zu)",
(size_t) output.length,
PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))));
+ errno = ECONNRESET;
+ return -1;
+ }
bytes_encrypted += input.length;
bytes_to_encrypt -= input.length;
@@ -234,9 +252,11 @@ be_gssapi_write(Port *port, void *ptr, size_t len)
* transport negotiation is complete).
*
* Returns the number of data bytes read, or on failure, returns -1
- * with errno set appropriately. (For fatal errors, we may just elog and
- * exit, if errno wouldn't be sufficient to describe the error.) For
- * retryable errors, caller should call again once the socket is ready.
+ * with errno set appropriately. For retryable errors, caller should call
+ * again once the socket is ready.
+ *
+ * We treat fatal errors the same as in be_gssapi_write(), even though the
+ * argument about infinite recursion doesn't apply here.
*/
ssize_t
be_gssapi_read(Port *port, void *ptr, size_t len)
@@ -326,10 +346,14 @@ be_gssapi_read(Port *port, void *ptr, size_t len)
input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer);
if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32))
- ereport(FATAL,
+ {
+ ereport(COMMERROR,
(errmsg("oversize GSSAPI packet sent by the client (%zu > %zu)",
(size_t) input.length,
PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32))));
+ errno = ECONNRESET;
+ return -1;
+ }
/*
* Read as much of the packet as we are able to on this call into
@@ -361,12 +385,18 @@ be_gssapi_read(Port *port, void *ptr, size_t len)
major = gss_unwrap(&minor, gctx, &input, &output, &conf_state, NULL);
if (major != GSS_S_COMPLETE)
- pg_GSS_error(FATAL, gettext_noop("GSSAPI unwrap error"),
- major, minor);
-
+ {
+ pg_GSS_error(_("GSSAPI unwrap error"), major, minor);
+ errno = ECONNRESET;
+ return -1;
+ }
if (conf_state == 0)
- ereport(FATAL,
+ {
+ ereport(COMMERROR,
(errmsg("incoming GSSAPI message did not use confidentiality")));
+ errno = ECONNRESET;
+ return -1;
+ }
memcpy(PqGSSResultBuffer, output.value, output.length);
PqGSSResultLength = output.length;
@@ -469,6 +499,12 @@ secure_open_gssapi(Port *port)
minor;
/*
+ * Allocate subsidiary Port data for GSSAPI operations.
+ */
+ port->gss = (pg_gssinfo *)
+ MemoryContextAllocZero(TopMemoryContext, sizeof(pg_gssinfo));
+
+ /*
* Allocate buffers and initialize state variables. By malloc'ing the
* buffers at this point, we avoid wasting static data space in processes
* that will never use them, and we ensure that the buffers are
@@ -521,10 +557,13 @@ secure_open_gssapi(Port *port)
* Verify on our side that the client doesn't do something funny.
*/
if (input.length > PQ_GSS_RECV_BUFFER_SIZE)
- ereport(FATAL,
+ {
+ ereport(COMMERROR,
(errmsg("oversize GSSAPI packet sent by the client (%zu > %d)",
(size_t) input.length,
PQ_GSS_RECV_BUFFER_SIZE)));
+ return -1;
+ }
/*
* Get the rest of the packet so we can pass it to GSSAPI to accept
@@ -544,7 +583,7 @@ secure_open_gssapi(Port *port)
NULL, NULL);
if (GSS_ERROR(major))
{
- pg_GSS_error(ERROR, gettext_noop("could not accept GSSAPI security context"),
+ pg_GSS_error(_("could not accept GSSAPI security context"),
major, minor);
gss_release_buffer(&minor, &output);
return -1;
@@ -570,10 +609,14 @@ secure_open_gssapi(Port *port)
uint32 netlen = pg_hton32(output.length);
if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))
- ereport(FATAL,
+ {
+ ereport(COMMERROR,
(errmsg("server tried to send oversize GSSAPI packet (%zu > %zu)",
(size_t) output.length,
PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))));
+ gss_release_buffer(&minor, &output);
+ return -1;
+ }
memcpy(PqGSSSendBuffer, (char *) &netlen, sizeof(uint32));
PqGSSSendLength += sizeof(uint32);
@@ -634,8 +677,10 @@ secure_open_gssapi(Port *port)
&PqGSSMaxPktSize);
if (GSS_ERROR(major))
- pg_GSS_error(FATAL, gettext_noop("GSSAPI size check error"),
- major, minor);
+ {
+ pg_GSS_error(_("GSSAPI size check error"), major, minor);
+ return -1;
+ }
port->gss->enc = true;
@@ -667,12 +712,13 @@ be_gssapi_get_enc(Port *port)
}
/*
- * Return the GSSAPI principal used for authentication on this connection.
+ * Return the GSSAPI principal used for authentication on this connection
+ * (NULL if we did not perform GSSAPI authentication).
*/
const char *
be_gssapi_get_princ(Port *port)
{
- if (!port || !port->gss->auth)
+ if (!port || !port->gss)
return NULL;
return port->gss->princ;
diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c
index 2ae507a9025..59bc02e79c6 100644
--- a/src/backend/libpq/be-secure.c
+++ b/src/backend/libpq/be-secure.c
@@ -160,7 +160,7 @@ retry:
else
#endif
#ifdef ENABLE_GSS
- if (port->gss->enc)
+ if (port->gss && port->gss->enc)
{
n = be_gssapi_read(port, ptr, len);
waitfor = WL_SOCKET_READABLE;
@@ -273,7 +273,7 @@ retry:
else
#endif
#ifdef ENABLE_GSS
- if (port->gss->enc)
+ if (port->gss && port->gss->enc)
{
n = be_gssapi_write(port, ptr, len);
waitfor = WL_SOCKET_WRITEABLE;
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 0cc43977691..99319b273aa 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -1447,19 +1447,6 @@ parse_hba_line(TokenizedLine *tok_line, int elevel)
*err_msg = "gssapi authentication is not supported on local sockets";
return NULL;
}
- if (parsedline->conntype == ctHostGSS &&
- parsedline->auth_method != uaGSS &&
- parsedline->auth_method != uaReject &&
- parsedline->auth_method != uaTrust)
- {
- ereport(elevel,
- (errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("GSSAPI encryption only supports gss, trust, or reject authentication"),
- errcontext("line %d of configuration file \"%s\"",
- line_num, HbaFileName)));
- *err_msg = "GSSAPI encryption only supports gss, trust, or reject authentication";
- return NULL;
- }
if (parsedline->conntype != ctLocal &&
parsedline->auth_method == uaPeer)
@@ -2134,9 +2121,11 @@ check_hba(hbaPort *port)
/* Check GSSAPI state */
#ifdef ENABLE_GSS
- if (port->gss->enc && hba->conntype == ctHostNoGSS)
+ if (port->gss && port->gss->enc &&
+ hba->conntype == ctHostNoGSS)
continue;
- else if (!port->gss->enc && hba->conntype == ctHostGSS)
+ else if (!(port->gss && port->gss->enc) &&
+ hba->conntype == ctHostGSS)
continue;
#else
if (hba->conntype == ctHostGSS)
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 0b511008fc8..3ea7c6167eb 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -256,29 +256,26 @@ socket_close(int code, Datum arg)
/* Nothing to do in a standalone backend, where MyProcPort is NULL. */
if (MyProcPort != NULL)
{
-#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
#ifdef ENABLE_GSS
- OM_uint32 min_s;
-
/*
* Shutdown GSSAPI layer. This section does nothing when interrupting
* BackendInitialize(), because pg_GSS_recvauth() makes first use of
* "ctx" and "cred".
+ *
+ * Note that we don't bother to free MyProcPort->gss, since we're
+ * about to exit anyway.
*/
- if (MyProcPort->gss->ctx != GSS_C_NO_CONTEXT)
- gss_delete_sec_context(&min_s, &MyProcPort->gss->ctx, NULL);
+ if (MyProcPort->gss)
+ {
+ OM_uint32 min_s;
- if (MyProcPort->gss->cred != GSS_C_NO_CREDENTIAL)
- gss_release_cred(&min_s, &MyProcPort->gss->cred);
-#endif /* ENABLE_GSS */
+ if (MyProcPort->gss->ctx != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context(&min_s, &MyProcPort->gss->ctx, NULL);
- /*
- * GSS and SSPI share the port->gss struct. Since nowhere else does a
- * postmaster child free this, doing so is safe when interrupting
- * BackendInitialize().
- */
- free(MyProcPort->gss);
-#endif /* ENABLE_GSS || ENABLE_SSPI */
+ if (MyProcPort->gss->cred != GSS_C_NO_CREDENTIAL)
+ gss_release_cred(&min_s, &MyProcPort->gss->cred);
+ }
+#endif /* ENABLE_GSS */
/*
* Cleanly shut down SSL layer. Nowhere else does a postmaster child
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index d87d9d06ee2..123369f4faf 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -2889,6 +2889,11 @@ BackendStatusShmemSize(void)
size = add_size(size,
mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots));
#endif
+#ifdef ENABLE_GSS
+ /* BackendGssStatusBuffer: */
+ size = add_size(size,
+ mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots));
+#endif
return size;
}
@@ -3172,12 +3177,13 @@ pgstat_bestart(void)
#ifdef ENABLE_GSS
if (MyProcPort && MyProcPort->gss != NULL)
{
+ const char *princ = be_gssapi_get_princ(MyProcPort);
+
lbeentry.st_gss = true;
lgssstatus.gss_auth = be_gssapi_get_auth(MyProcPort);
lgssstatus.gss_enc = be_gssapi_get_enc(MyProcPort);
-
- if (lgssstatus.gss_auth)
- strlcpy(lgssstatus.gss_princ, be_gssapi_get_princ(MyProcPort), NAMEDATALEN);
+ if (princ)
+ strlcpy(lgssstatus.gss_princ, princ, NAMEDATALEN);
}
else
{
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index fff4227e0b6..b3ccd18cda6 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -2052,6 +2052,7 @@ retry1:
else if (proto == NEGOTIATE_GSS_CODE && !gss_done)
{
char GSSok = 'N';
+
#ifdef ENABLE_GSS
/* No GSSAPI encryption when on Unix socket */
if (!IS_AF_UNIX(port->laddr.addr.ss_family))
@@ -2520,37 +2521,19 @@ ConnCreate(int serverFd)
return NULL;
}
- /*
- * Allocate GSSAPI specific state struct
- */
-#ifndef EXEC_BACKEND
-#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
- port->gss = (pg_gssinfo *) calloc(1, sizeof(pg_gssinfo));
- if (!port->gss)
- {
- ereport(LOG,
- (errcode(ERRCODE_OUT_OF_MEMORY),
- errmsg("out of memory")));
- ExitPostmaster(1);
- }
-#endif
-#endif
-
return port;
}
/*
* ConnFree -- free a local connection data structure
+ *
+ * Caller has already closed the socket if any, so there's not much
+ * to do here.
*/
static void
ConnFree(Port *conn)
{
-#ifdef USE_SSL
- secure_close(conn);
-#endif
- if (conn->gss)
- free(conn->gss);
free(conn);
}
@@ -4907,18 +4890,6 @@ SubPostmasterMain(int argc, char *argv[])
InitPostmasterChild();
/*
- * Set up memory area for GSS information. Mirrors the code in ConnCreate
- * for the non-exec case.
- */
-#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
- port.gss = (pg_gssinfo *) calloc(1, sizeof(pg_gssinfo));
- if (!port.gss)
- ereport(FATAL,
- (errcode(ERRCODE_OUT_OF_MEMORY),
- errmsg("out of memory")));
-#endif
-
- /*
* If appropriate, physically re-attach to shared memory segment. We want
* to do this before going any further to ensure that we can attach at the
* same address the postmaster used. On the other hand, if we choose not
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 82d451569d6..9723e457ce9 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -270,11 +270,22 @@ PerformAuthentication(Port *port)
be_tls_get_compression(port) ? _("on") : _("off"));
#endif
#ifdef ENABLE_GSS
- if (be_gssapi_get_princ(port))
- appendStringInfo(&logmsg, _(" GSS (authenticated=%s, encrypted=%s, principal=%s)"),
- be_gssapi_get_auth(port) ? _("yes") : _("no"),
- be_gssapi_get_enc(port) ? _("yes") : _("no"),
- be_gssapi_get_princ(port));
+ if (port->gss)
+ {
+ const char *princ = be_gssapi_get_princ(port);
+
+ if (princ)
+ appendStringInfo(&logmsg,
+ _(" GSS (authenticated=%s, encrypted=%s, principal=%s)"),
+ be_gssapi_get_auth(port) ? _("yes") : _("no"),
+ be_gssapi_get_enc(port) ? _("yes") : _("no"),
+ princ);
+ else
+ appendStringInfo(&logmsg,
+ _(" GSS (authenticated=%s, encrypted=%s)"),
+ be_gssapi_get_auth(port) ? _("yes") : _("no"),
+ be_gssapi_get_enc(port) ? _("yes") : _("no"));
+ }
#endif
ereport(LOG, errmsg_internal("%s", logmsg.data));
diff --git a/src/include/libpq/be-gssapi-common.h b/src/include/libpq/be-gssapi-common.h
index edf89675cf7..e1c23ac5459 100644
--- a/src/include/libpq/be-gssapi-common.h
+++ b/src/include/libpq/be-gssapi-common.h
@@ -20,7 +20,7 @@
#include <gssapi/gssapi.h>
#endif
-void pg_GSS_error(int severity, const char *errmsg,
+extern void pg_GSS_error(const char *errmsg,
OM_uint32 maj_stat, OM_uint32 min_stat);
#endif /* BE_GSSAPI_COMMON_H */
diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h
index 0a23281ad59..fa778e11921 100644
--- a/src/include/libpq/libpq-be.h
+++ b/src/include/libpq/libpq-be.h
@@ -176,8 +176,9 @@ typedef struct Port
#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
/*
- * If GSSAPI is supported, store GSSAPI information. Otherwise, store a
- * NULL pointer to make sure offsets in the struct remain the same.
+ * If GSSAPI is supported and used on this connection, store GSSAPI
+ * information. Even when GSSAPI is not compiled in, store a NULL pointer
+ * to keep struct offsets the same (for extension ABI compatibility).
*/
pg_gssinfo *gss;
#else