From dcba977f9e37e80fafc7deb89b8856738f20928d Mon Sep 17 00:00:00 2001
From: "Robbie Harwood (frozencemetery)" <rharwood@redhat.com>
Date: Mon, 15 Jun 2015 16:52:10 -0400
Subject: server: hba option for requiring GSSAPI encryption

Also includes logic for failing clients that do not request encryption
in the startup packet when encryption is required.
---
 src/backend/libpq/hba.c           |  9 +++++++++
 src/backend/utils/init/postinit.c |  7 ++++++-
 src/backend/utils/misc/guc.c      | 12 +++++++++++-
 src/include/libpq/hba.h           |  1 +
 4 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 23c8b5d..90fe57f 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -1570,6 +1570,15 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
 		else
 			hbaline->include_realm = false;
 	}
+	else if (strcmp(name, "require_encrypt") == 0)
+	{
+		if (hbaline->auth_method != uaGSS)
+			INVALID_AUTH_OPTION("require_encrypt", "gssapi");
+		if (strcmp(val, "1") == 0)
+			hbaline->require_encrypt = true;
+		else
+			hbaline->require_encrypt = false;
+	}
 	else if (strcmp(name, "radiusserver") == 0)
 	{
 		struct addrinfo *gai_result;
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 0f04f28..cc5c9af 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -32,7 +32,7 @@
 #include "catalog/pg_db_role_setting.h"
 #include "catalog/pg_tablespace.h"
 #include "libpq/auth.h"
-#include "libpq/libpq-be.h"
+#include "libpq/libpq.h"
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
 #include "pgstat.h"
@@ -1085,6 +1085,11 @@ process_startup_options(Port *port, bool am_superuser)
 
 		SetConfigOption(name, value, gucctx, PGC_S_CLIENT);
 	}
+
+	if (!gss_encrypt && port->hba->require_encrypt)
+		ereport(FATAL, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
+						errmsg("GSSAPI encryption required from user \"%s\"",
+							   port->user_name)));
 }
 
 /*
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index a978af0..3a8ba61 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -188,6 +188,7 @@ static ConfigVariable *ProcessConfigFileInternal(GucContext context,
 
 #ifdef ENABLE_GSS
 static void assign_gss_encrypt(bool newval, void *extra);
+static bool check_gss_encrypt(bool *newval, void **extra, GucSource source);
 #endif
 
 
@@ -1628,7 +1629,7 @@ static struct config_bool ConfigureNamesBool[] =
 		 NULL,
 		 GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
-		&gss_encrypt, false, NULL, assign_gss_encrypt, NULL
+		&gss_encrypt, false, check_gss_encrypt, assign_gss_encrypt, NULL
 	},
 
 	/* End-of-list marker */
@@ -10133,4 +10134,13 @@ assign_gss_encrypt(bool newval, void *extra)
 	gss_encrypt = newval;
 }
 
+static bool
+check_gss_encrypt(bool *newval, void **extra, GucSource source)
+{
+	if (MyProcPort && MyProcPort->hba && MyProcPort->hba->require_encrypt &&
+		!*newval)
+		return false;
+	return true;
+}
+
 #include "guc-file.c"
diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h
index 68a953a..3435674 100644
--- a/src/include/libpq/hba.h
+++ b/src/include/libpq/hba.h
@@ -77,6 +77,7 @@ typedef struct HbaLine
 	bool		clientcert;
 	char	   *krb_realm;
 	bool		include_realm;
+	bool		require_encrypt;
 	char	   *radiusserver;
 	char	   *radiussecret;
 	char	   *radiusidentifier;
-- 
2.1.4

