diff --git a/src/backend/libpq/be-secure-gssapi.c b/src/backend/libpq/be-secure-gssapi.c
index 717ba9824f9..910c7f22711 100644
--- a/src/backend/libpq/be-secure-gssapi.c
+++ b/src/backend/libpq/be-secure-gssapi.c
@@ -46,11 +46,19 @@
  * don't want the other side to send arbitrarily huge packets as we
  * would have to allocate memory for them to then pass them to GSSAPI.
  *
- * Therefore, these two #define's are effectively part of the protocol
+ * Therefore, this #define is effectively part of the protocol
  * spec and can't ever be changed.
  */
-#define PQ_GSS_SEND_BUFFER_SIZE 16384
-#define PQ_GSS_RECV_BUFFER_SIZE 16384
+#define PQ_GSS_MAX_PACKET_SIZE 16384
+
+/*
+ * However, during the authentication exchange we must cope with whatever
+ * message size the GSSAPI library wants to send (because our protocol
+ * doesn't support splitting those messages).  Depending on configuration
+ * those messages might be as much as 64kB.  To provide some safety margin
+ * we use 128kB buffers during transport negotiation.
+ */
+#define PQ_GSS_AUTH_BUFFER_SIZE 131072
 
 /*
  * Since we manage at most one GSS-encrypted connection per backend,
@@ -210,12 +218,12 @@ be_gssapi_write(Port *port, const void *ptr, size_t len)
 			errno = ECONNRESET;
 			return -1;
 		}
-		if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))
+		if (output.length > PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32))
 		{
 			ereport(COMMERROR,
 					(errmsg("server tried to send oversize GSSAPI packet (%zu > %zu)",
 							(size_t) output.length,
-							PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))));
+							PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32))));
 			errno = ECONNRESET;
 			return -1;
 		}
@@ -346,12 +354,12 @@ be_gssapi_read(Port *port, void *ptr, size_t len)
 		/* Decode the packet length and check for overlength packet */
 		input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer);
 
-		if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32))
+		if (input.length > PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32))
 		{
 			ereport(COMMERROR,
 					(errmsg("oversize GSSAPI packet sent by the client (%zu > %zu)",
 							(size_t) input.length,
-							PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32))));
+							PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32))));
 			errno = ECONNRESET;
 			return -1;
 		}
@@ -517,10 +525,13 @@ secure_open_gssapi(Port *port)
 	 * that will never use them, and we ensure that the buffers are
 	 * sufficiently aligned for the length-word accesses that we do in some
 	 * places in this file.
+	 *
+	 * We'll use PQ_GSS_AUTH_BUFFER_SIZE-sized buffers until transport
+	 * negotiation is complete, then switch to PQ_GSS_MAX_PACKET_SIZE.
 	 */
-	PqGSSSendBuffer = malloc(PQ_GSS_SEND_BUFFER_SIZE);
-	PqGSSRecvBuffer = malloc(PQ_GSS_RECV_BUFFER_SIZE);
-	PqGSSResultBuffer = malloc(PQ_GSS_RECV_BUFFER_SIZE);
+	PqGSSSendBuffer = malloc(PQ_GSS_AUTH_BUFFER_SIZE);
+	PqGSSRecvBuffer = malloc(PQ_GSS_AUTH_BUFFER_SIZE);
+	PqGSSResultBuffer = malloc(PQ_GSS_AUTH_BUFFER_SIZE);
 	if (!PqGSSSendBuffer || !PqGSSRecvBuffer || !PqGSSResultBuffer)
 		ereport(FATAL,
 				(errcode(ERRCODE_OUT_OF_MEMORY),
@@ -568,16 +579,16 @@ secure_open_gssapi(Port *port)
 
 		/*
 		 * During initialization, packets are always fully consumed and
-		 * shouldn't ever be over PQ_GSS_RECV_BUFFER_SIZE in length.
+		 * shouldn't ever be over PQ_GSS_AUTH_BUFFER_SIZE in total length.
 		 *
 		 * Verify on our side that the client doesn't do something funny.
 		 */
-		if (input.length > PQ_GSS_RECV_BUFFER_SIZE)
+		if (input.length > PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32))
 		{
 			ereport(COMMERROR,
-					(errmsg("oversize GSSAPI packet sent by the client (%zu > %d)",
+					(errmsg("oversize GSSAPI packet sent by the client (%zu > %zu)",
 							(size_t) input.length,
-							PQ_GSS_RECV_BUFFER_SIZE)));
+							PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32))));
 			return -1;
 		}
 
@@ -631,12 +642,12 @@ secure_open_gssapi(Port *port)
 		{
 			uint32		netlen = pg_hton32(output.length);
 
-			if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))
+			if (output.length > PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32))
 			{
 				ereport(COMMERROR,
 						(errmsg("server tried to send oversize GSSAPI packet (%zu > %zu)",
 								(size_t) output.length,
-								PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))));
+								PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32))));
 				gss_release_buffer(&minor, &output);
 				return -1;
 			}
@@ -691,12 +702,29 @@ secure_open_gssapi(Port *port)
 			break;
 	}
 
+	/*
+	 * Release the large authentication buffers and allocate the ones we want
+	 * for normal operation.
+	 */
+	free(PqGSSSendBuffer);
+	free(PqGSSRecvBuffer);
+	free(PqGSSResultBuffer);
+	PqGSSSendBuffer = malloc(PQ_GSS_MAX_PACKET_SIZE);
+	PqGSSRecvBuffer = malloc(PQ_GSS_MAX_PACKET_SIZE);
+	PqGSSResultBuffer = malloc(PQ_GSS_MAX_PACKET_SIZE);
+	if (!PqGSSSendBuffer || !PqGSSRecvBuffer || !PqGSSResultBuffer)
+		ereport(FATAL,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory")));
+	PqGSSSendLength = PqGSSSendNext = PqGSSSendConsumed = 0;
+	PqGSSRecvLength = PqGSSResultLength = PqGSSResultNext = 0;
+
 	/*
 	 * Determine the max packet size which will fit in our buffer, after
 	 * accounting for the length.  be_gssapi_write will need this.
 	 */
 	major = gss_wrap_size_limit(&minor, port->gss->ctx, 1, GSS_C_QOP_DEFAULT,
-								PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32),
+								PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32),
 								&PqGSSMaxPktSize);
 
 	if (GSS_ERROR(major))
diff --git a/src/interfaces/libpq/fe-secure-gssapi.c b/src/interfaces/libpq/fe-secure-gssapi.c
index ce183bc04b4..9bdf0192f1e 100644
--- a/src/interfaces/libpq/fe-secure-gssapi.c
+++ b/src/interfaces/libpq/fe-secure-gssapi.c
@@ -47,11 +47,19 @@
  * don't want the other side to send arbitrarily huge packets as we
  * would have to allocate memory for them to then pass them to GSSAPI.
  *
- * Therefore, these two #define's are effectively part of the protocol
+ * Therefore, this #define is effectively part of the protocol
  * spec and can't ever be changed.
  */
-#define PQ_GSS_SEND_BUFFER_SIZE 16384
-#define PQ_GSS_RECV_BUFFER_SIZE 16384
+#define PQ_GSS_MAX_PACKET_SIZE 16384
+
+/*
+ * However, during the authentication exchange we must cope with whatever
+ * message size the GSSAPI library wants to send (because our protocol
+ * doesn't support splitting those messages).  Depending on configuration
+ * those messages might be as much as 64kB.  To provide some safety margin
+ * we use 128kB buffers during transport negotiation.
+ */
+#define PQ_GSS_AUTH_BUFFER_SIZE 131072
 
 /*
  * We need these state variables per-connection.  To allow the functions
@@ -203,11 +211,11 @@ pg_GSS_write(PGconn *conn, const void *ptr, size_t len)
 			goto cleanup;
 		}
 
-		if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))
+		if (output.length > PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32))
 		{
 			libpq_append_conn_error(conn, "client tried to send oversize GSSAPI packet (%zu > %zu)",
 									(size_t) output.length,
-									PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32));
+									PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32));
 			errno = EIO;		/* for lack of a better idea */
 			goto cleanup;
 		}
@@ -342,11 +350,11 @@ pg_GSS_read(PGconn *conn, void *ptr, size_t len)
 		/* Decode the packet length and check for overlength packet */
 		input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer);
 
-		if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32))
+		if (input.length > PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32))
 		{
 			libpq_append_conn_error(conn, "oversize GSSAPI packet sent by the server (%zu > %zu)",
 									(size_t) input.length,
-									PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32));
+									PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32));
 			errno = EIO;		/* for lack of a better idea */
 			return -1;
 		}
@@ -485,12 +493,15 @@ pqsecure_open_gss(PGconn *conn)
 	 * initialize state variables.  By malloc'ing the buffers separately, we
 	 * ensure that they are sufficiently aligned for the length-word accesses
 	 * that we do in some places in this file.
+	 *
+	 * We'll use PQ_GSS_AUTH_BUFFER_SIZE-sized buffers until transport
+	 * negotiation is complete, then switch to PQ_GSS_MAX_PACKET_SIZE.
 	 */
 	if (PqGSSSendBuffer == NULL)
 	{
-		PqGSSSendBuffer = malloc(PQ_GSS_SEND_BUFFER_SIZE);
-		PqGSSRecvBuffer = malloc(PQ_GSS_RECV_BUFFER_SIZE);
-		PqGSSResultBuffer = malloc(PQ_GSS_RECV_BUFFER_SIZE);
+		PqGSSSendBuffer = malloc(PQ_GSS_AUTH_BUFFER_SIZE);
+		PqGSSRecvBuffer = malloc(PQ_GSS_AUTH_BUFFER_SIZE);
+		PqGSSResultBuffer = malloc(PQ_GSS_AUTH_BUFFER_SIZE);
 		if (!PqGSSSendBuffer || !PqGSSRecvBuffer || !PqGSSResultBuffer)
 		{
 			libpq_append_conn_error(conn, "out of memory");
@@ -564,13 +575,13 @@ pqsecure_open_gss(PGconn *conn)
 			 * so leave a spot at the end for a NULL byte too) and report that
 			 * back to the caller.
 			 */
-			result = gss_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, PQ_GSS_RECV_BUFFER_SIZE - PqGSSRecvLength - 1, &ret);
+			result = gss_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, PQ_GSS_AUTH_BUFFER_SIZE - PqGSSRecvLength - 1, &ret);
 			if (result != PGRES_POLLING_OK)
 				return result;
 
 			PqGSSRecvLength += ret;
 
-			Assert(PqGSSRecvLength < PQ_GSS_RECV_BUFFER_SIZE);
+			Assert(PqGSSRecvLength < PQ_GSS_AUTH_BUFFER_SIZE);
 			PqGSSRecvBuffer[PqGSSRecvLength] = '\0';
 			appendPQExpBuffer(&conn->errorMessage, "%s\n", PqGSSRecvBuffer + 1);
 
@@ -584,11 +595,11 @@ pqsecure_open_gss(PGconn *conn)
 
 		/* Get the length and check for over-length packet */
 		input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer);
-		if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32))
+		if (input.length > PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32))
 		{
 			libpq_append_conn_error(conn, "oversize GSSAPI packet sent by the server (%zu > %zu)",
 									(size_t) input.length,
-									PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32));
+									PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32));
 			return PGRES_POLLING_FAILED;
 		}
 
@@ -668,12 +679,33 @@ pqsecure_open_gss(PGconn *conn)
 		conn->gcred = GSS_C_NO_CREDENTIAL;
 		gss_release_buffer(&minor, &output);
 
+		/*
+		 * Release the large authentication buffers and allocate the ones we
+		 * want for normal operation.  (This maneuver is safe only because
+		 * pqDropConnection will drop the buffers; otherwise, during a
+		 * reconnection we'd be at risk of using undersized buffers during
+		 * negotiation.)
+		 */
+		free(PqGSSSendBuffer);
+		free(PqGSSRecvBuffer);
+		free(PqGSSResultBuffer);
+		PqGSSSendBuffer = malloc(PQ_GSS_MAX_PACKET_SIZE);
+		PqGSSRecvBuffer = malloc(PQ_GSS_MAX_PACKET_SIZE);
+		PqGSSResultBuffer = malloc(PQ_GSS_MAX_PACKET_SIZE);
+		if (!PqGSSSendBuffer || !PqGSSRecvBuffer || !PqGSSResultBuffer)
+		{
+			libpq_append_conn_error(conn, "out of memory");
+			return PGRES_POLLING_FAILED;
+		}
+		PqGSSSendLength = PqGSSSendNext = PqGSSSendConsumed = 0;
+		PqGSSRecvLength = PqGSSResultLength = PqGSSResultNext = 0;
+
 		/*
 		 * Determine the max packet size which will fit in our buffer, after
 		 * accounting for the length.  pg_GSS_write will need this.
 		 */
 		major = gss_wrap_size_limit(&minor, conn->gctx, 1, GSS_C_QOP_DEFAULT,
-									PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32),
+									PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32),
 									&PqGSSMaxPktSize);
 
 		if (GSS_ERROR(major))
@@ -687,10 +719,11 @@ pqsecure_open_gss(PGconn *conn)
 	}
 
 	/* Must have output.length > 0 */
-	if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))
+	if (output.length > PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32))
 	{
-		pg_GSS_error(libpq_gettext("GSSAPI context establishment error"),
-					 conn, major, minor);
+		libpq_append_conn_error(conn, "client tried to send oversize GSSAPI packet (%zu > %zu)",
+								(size_t) output.length,
+								PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32));
 		gss_release_buffer(&minor, &output);
 		return PGRES_POLLING_FAILED;
 	}
