aboutsummaryrefslogtreecommitdiff
path: root/src/backend/libpq/auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/libpq/auth.c')
-rw-r--r--src/backend/libpq/auth.c115
1 files changed, 43 insertions, 72 deletions
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 6f03c7c2a5e..62466be7023 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -36,6 +36,7 @@
#include "port/pg_bswap.h"
#include "replication/walsender.h"
#include "storage/ipc.h"
+#include "utils/memutils.h"
#include "utils/timestamp.h"
@@ -172,12 +173,9 @@ bool pg_krb_caseins_users;
*----------------------------------------------------------------
*/
#ifdef ENABLE_GSS
-#if defined(HAVE_GSSAPI_H)
-#include <gssapi.h>
-#else
-#include <gssapi/gssapi.h>
-#endif
+#include "be-gssapi-common.h"
+static int pg_GSS_checkauth(Port *port);
static int pg_GSS_recvauth(Port *port);
#endif /* ENABLE_GSS */
@@ -383,6 +381,17 @@ 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
*/
@@ -523,8 +532,14 @@ ClientAuthentication(Port *port)
case uaGSS:
#ifdef ENABLE_GSS
- sendAuthRequest(port, AUTH_REQ_GSS, NULL, 0);
- status = pg_GSS_recvauth(port);
+ port->gss->auth = true;
+ if (port->gss->enc)
+ status = pg_GSS_checkauth(port);
+ else
+ {
+ sendAuthRequest(port, AUTH_REQ_GSS, NULL, 0);
+ status = pg_GSS_recvauth(port);
+ }
#else
Assert(false);
#endif
@@ -1031,68 +1046,6 @@ CheckSCRAMAuth(Port *port, char *shadow_pass, char **logdetail)
*----------------------------------------------------------------
*/
#ifdef ENABLE_GSS
-
-#if defined(WIN32) && !defined(_MSC_VER)
-/*
- * MIT Kerberos GSSAPI DLL doesn't properly export the symbols for MingW
- * that contain the OIDs required. Redefine here, values copied
- * from src/athena/auth/krb5/src/lib/gssapi/generic/gssapi_generic.c
- */
-static const gss_OID_desc GSS_C_NT_USER_NAME_desc =
-{10, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"};
-static GSS_DLLIMP gss_OID GSS_C_NT_USER_NAME = &GSS_C_NT_USER_NAME_desc;
-#endif
-
-
-/*
- * Generate an error for GSSAPI authentication. The caller should apply
- * _() to errmsg to make it translatable.
- */
-static void
-pg_GSS_error(int severity, const char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)
-{
- gss_buffer_desc gmsg;
- OM_uint32 lmin_s,
- msg_ctx;
- char msg_major[128],
- msg_minor[128];
-
- /* Fetch major status message */
- msg_ctx = 0;
- gss_display_status(&lmin_s, maj_stat, GSS_C_GSS_CODE,
- GSS_C_NO_OID, &msg_ctx, &gmsg);
- strlcpy(msg_major, gmsg.value, sizeof(msg_major));
- gss_release_buffer(&lmin_s, &gmsg);
-
- if (msg_ctx)
-
- /*
- * More than one message available. XXX: Should we loop and read all
- * messages? (same below)
- */
- ereport(WARNING,
- (errmsg_internal("incomplete GSS error report")));
-
- /* Fetch mechanism minor status message */
- msg_ctx = 0;
- gss_display_status(&lmin_s, min_stat, GSS_C_MECH_CODE,
- GSS_C_NO_OID, &msg_ctx, &gmsg);
- strlcpy(msg_minor, gmsg.value, sizeof(msg_minor));
- gss_release_buffer(&lmin_s, &gmsg);
-
- if (msg_ctx)
- ereport(WARNING,
- (errmsg_internal("incomplete GSS minor error report")));
-
- /*
- * errmsg_internal, since translation of the first part must be done
- * before calling this function anyway.
- */
- ereport(severity,
- (errmsg_internal("%s", errmsg),
- errdetail_internal("%s: %s", msg_major, msg_minor)));
-}
-
static int
pg_GSS_recvauth(Port *port)
{
@@ -1101,7 +1054,6 @@ pg_GSS_recvauth(Port *port)
lmin_s,
gflags;
int mtype;
- int ret;
StringInfoData buf;
gss_buffer_desc gbuf;
@@ -1254,10 +1206,23 @@ pg_GSS_recvauth(Port *port)
*/
gss_release_cred(&min_stat, &port->gss->cred);
}
+ return pg_GSS_checkauth(port);
+}
+
+/*
+ * Check whether the GSSAPI-authenticated user is allowed to connect as the
+ * claimed username.
+ */
+static int
+pg_GSS_checkauth(Port *port)
+{
+ int ret;
+ OM_uint32 maj_stat,
+ min_stat,
+ lmin_s;
+ gss_buffer_desc gbuf;
/*
- * GSS_S_COMPLETE indicates that authentication is now complete.
- *
* Get the name of the user that authenticated, and compare it to the pg
* username that was specified for the connection.
*/
@@ -1268,6 +1233,12 @@ pg_GSS_recvauth(Port *port)
maj_stat, min_stat);
/*
+ * Copy the original name of the authenticated principal into our backend
+ * memory for display later.
+ */
+ port->gss->princ = MemoryContextStrdup(TopMemoryContext, gbuf.value);
+
+ /*
* Split the username at the realm separator
*/
if (strchr(gbuf.value, '@'))