From b32190b69479a46291088b9ef15208d47975bcba Mon Sep 17 00:00:00 2001
From: "Robbie Harwood (frozencemetery)" <rharwood@redhat.com>
Date: Mon, 15 Jun 2015 19:54:29 -0400
Subject: client: gss_enc_require parameter to force GSS encryption

---
 src/interfaces/libpq/fe-connect.c | 27 ++++++++++++++++++++++-----
 src/interfaces/libpq/libpq-int.h  |  1 +
 2 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 8fb0a90..115a52c 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -297,6 +297,12 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
 	offsetof(struct pg_conn, gsslib)},
 #endif
 
+#if defined(ENABLE_GSS)
+	{"gss_enc_require", "GSS_ENC_REQUIRE", "0", NULL,
+		"Require-GSS-encryption", "", 1, /* should be '0' or '1' */
+	offsetof(struct pg_conn, gss_enc_require)},
+#endif
+
 	{"replication", NULL, NULL, NULL,
 		"Replication", "D", 5,
 	offsetof(struct pg_conn, replication)},
@@ -2559,14 +2565,16 @@ keep_going:						/* We will come back to here until there is
 						appendPQExpBufferStr(&conn->errorMessage,
 											 libpq_gettext("unexpected message from server during startup\n"));
 #ifdef ENABLE_GSS
-					else if (!conn->gss_disable_enc)
+					else if (!conn->gss_disable_enc &&
+							 *conn->gss_enc_require != '1')
 					{
 						/*
 						 * We tried to request GSS encryption, but the server
-						 * doesn't support it.  Hang up and try again.  A
-						 * connection that doesn't support appname will also
-						 * not support GSSAPI encryption, so this check goes
-						 * before that check.  See comment below.
+						 * doesn't support it.  Retries are permitted here, so
+						 * hang up and try again.  A connection that doesn't
+						 * support appname will also not support GSSAPI
+						 * encryption, so this check goes before that check.
+						 * See comment below.
 						 */
 						const char *sqlstate;
 
@@ -2614,6 +2622,15 @@ keep_going:						/* We will come back to here until there is
 							goto keep_going;
 						}
 					}
+#ifdef ENABLE_GSS
+					else if (*conn->gss_enc_require == '1')
+						/*
+						 * It has been determined that appname was not the
+						 * cause of connection failure, so give up.
+						 */
+						appendPQExpBufferStr(&conn->errorMessage,
+											 libpq_gettext("Server does not support required GSS encryption\n"));
+#endif
 
 					/*
 					 * if the resultStatus is FATAL, then conn->errorMessage
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 7a3ebcd..3140c7f 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -448,6 +448,7 @@ struct pg_conn
 	bool gss_disable_enc;		/* Does server recognize gss_encrypt? */
 	bool gss_auth_done;			/* Did we finish the AUTH step? */
 	bool gss_decrypted_cur;		/* Is first message in buffer decrypted? */
+	char *gss_enc_require;		/* Can we downgrade to plaintext? */
 #endif
 
 #ifdef ENABLE_SSPI
-- 
2.1.4

