aboutsummaryrefslogtreecommitdiff
path: root/src/backend/libpq/be-gssapi-common.c
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/backend/libpq/be-gssapi-common.c
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/backend/libpq/be-gssapi-common.c')
-rw-r--r--src/backend/libpq/be-gssapi-common.c51
1 files changed, 35 insertions, 16 deletions
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)));
}