Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.80) (envelope-from ) id 1ZAj7z-0004wE-Aa for pgsql-hackers@arkaria.postgresql.org; Thu, 02 Jul 2015 18:22:27 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.84) (envelope-from ) id 1ZAj7x-00047O-Qm for pgsql-hackers@arkaria.postgresql.org; Thu, 02 Jul 2015 18:22:25 +0000 Received: from makus.postgresql.org ([2001:4800:1501:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84) (envelope-from ) id 1ZAj7v-00046s-HV for pgsql-hackers@postgresql.org; Thu, 02 Jul 2015 18:22:23 +0000 Received: from mx1.redhat.com ([209.132.183.28]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84) (envelope-from ) id 1ZAj7r-0003wW-53 for pgsql-hackers@postgresql.org; Thu, 02 Jul 2015 18:22:22 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id 961452C76EA for ; Thu, 2 Jul 2015 18:22:17 +0000 (UTC) Received: from localhost (vpn-48-192.rdu2.redhat.com [10.10.48.192]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t62IMGJh016932 for ; Thu, 2 Jul 2015 14:22:17 -0400 From: Robbie Harwood To: pgsql-hackers@postgresql.org Subject: [PATCH v1] GSSAPI encryption support User-Agent: Notmuch/0.18.2 (http://notmuchmail.org) Emacs/24.4.1 (x86_64-pc-linux-gnu) Date: Thu, 02 Jul 2015 14:22:13 -0400 Message-ID: MIME-Version: 1.0 Content-Type: multipart/signed; boundary="==-=-="; micalg=pgp-sha1; protocol="application/pgp-signature" X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Pg-Spam-Score: -7.5 (-------) List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-hackers Precedence: bulk Sender: pgsql-hackers-owner@postgresql.org --==-=-= Content-Type: multipart/mixed; boundary="=-=-=" --=-=-= Content-Type: text/plain Hello -hackers, As previously discussed on this list, I have coded up GSSAPI encryption support. If it is easier for anyone, this code is also available for viewing on my github: https://github.com/postgres/postgres/compare/master...frozencemetery:feature/gssencrypt Fallback support is present in both directions for talking to old client and old servers; GSSAPI encryption is by default auto-upgraded to where available (for compatibility), but both client and server contain settings for requiring it. There are 8 commits in this series; I have tried to err on the side of creating too much separation rather than too little. A patch for each is attached. This is v1 of the series. Thanks! --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=v1-1-build-Define-with_gssapi-for-use-in-Makefiles.patch Content-Transfer-Encoding: quoted-printable From=20f506ba6ab6755f56c8aadba7d72a8839d5fbc0d9 Mon Sep 17 00:00:00 2001 From: "Robbie Harwood (frozencemetery)" Date: Mon, 8 Jun 2015 19:27:45 -0400 Subject: build: Define with_gssapi for use in Makefiles This is needed in order to control build of GSSAPI components. =2D-- configure | 2 ++ configure.in | 1 + src/Makefile.global.in | 1 + 3 files changed, 4 insertions(+) diff --git a/configure b/configure index 0407c4f..b9bab06 100755 =2D-- a/configure +++ b/configure @@ -711,6 +711,7 @@ with_uuid with_selinux with_openssl krb_srvtab +with_gssapi with_python with_perl with_tcl @@ -5452,6 +5453,7 @@ $as_echo "$with_gssapi" >&6; } =20 =20 =20 + # # Kerberos configuration parameters # diff --git a/configure.in b/configure.in index 1de41a2..113bd65 100644 =2D-- a/configure.in +++ b/configure.in @@ -635,6 +635,7 @@ PGAC_ARG_BOOL(with, gssapi, no, [build with GSSAPI supp= ort], krb_srvtab=3D"FILE:\$(sysconfdir)/krb5.keytab" ]) AC_MSG_RESULT([$with_gssapi]) +AC_SUBST(with_gssapi) =20 =20 AC_SUBST(krb_srvtab) diff --git a/src/Makefile.global.in b/src/Makefile.global.in index c583b44..e50c87d 100644 =2D-- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -167,6 +167,7 @@ with_perl =3D @with_perl@ with_python =3D @with_python@ with_tcl =3D @with_tcl@ with_openssl =3D @with_openssl@ +with_gssapi =3D @with_gssapi@ with_selinux =3D @with_selinux@ with_libxml =3D @with_libxml@ with_libxslt =3D @with_libxslt@ =2D-=20 2.1.4 --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=v1-2-client-Disable-GSS-encryption-on-old-servers.patch Content-Transfer-Encoding: quoted-printable From=20d5b973752968f87c9bb2ff9434d523657eb4ba67 Mon Sep 17 00:00:00 2001 From: "Robbie Harwood (frozencemetery)" Date: Mon, 8 Jun 2015 20:16:42 -0400 Subject: client: Disable GSS encryption on old servers =2D-- src/interfaces/libpq/fe-connect.c | 34 ++++++++++++++++++++++++++++++++-- src/interfaces/libpq/fe-protocol3.c | 5 +++++ src/interfaces/libpq/libpq-int.h | 1 + 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-co= nnect.c index a45f4cb..c6c551a 100644 =2D-- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -91,8 +91,9 @@ static int ldapServiceLookup(const char *purl, PQconninfo= Option *options, * application_name in a startup packet. We hard-wire the value rather * than looking into errcodes.h since it reflects historical behavior * rather than that of the current code. + * Servers that do not support GSS encryption will also return this error. */ =2D#define ERRCODE_APPNAME_UNKNOWN "42704" +#define ERRCODE_UNKNOWN_PARAM "42704" =20 /* This is part of the protocol so just define it */ #define ERRCODE_INVALID_PASSWORD "28P01" @@ -2552,6 +2553,35 @@ keep_going: /* We will come back to here until = there is if (res->resultStatus !=3D PGRES_FATAL_ERROR) appendPQExpBufferStr(&conn->errorMessage, libpq_gettext("unexpected message from server during startup\n= ")); +#ifdef ENABLE_GSS + else if (!conn->gss_disable_enc) + { + /* + * 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. + */ + const char *sqlstate; + + sqlstate =3D PQresultErrorField(res, PG_DIAG_SQLSTATE); + if (sqlstate && + strcmp(sqlstate, ERRCODE_UNKNOWN_PARAM) =3D=3D 0) + { + OM_uint32 minor; + + PQclear(res); + conn->gss_disable_enc =3D true; + /* Must drop the old connection */ + pqDropConnection(conn); + conn->status =3D CONNECTION_NEEDED; + gss_delete_sec_context(&minor, &conn->gctx, + GSS_C_NO_BUFFER); + goto keep_going; + } + } +#endif else if (conn->send_appname && (conn->appname || conn->fbappname)) { @@ -2569,7 +2599,7 @@ keep_going: /* We will come back to here until t= here is =20 sqlstate =3D PQresultErrorField(res, PG_DIAG_SQLSTATE); if (sqlstate && =2D strcmp(sqlstate, ERRCODE_APPNAME_UNKNOWN) =3D=3D 0) + strcmp(sqlstate, ERRCODE_UNKNOWN_PARAM) =3D=3D 0) { PQclear(res); conn->send_appname =3D false; diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-= protocol3.c index a847f08..0deaa0f 100644 =2D-- a/src/interfaces/libpq/fe-protocol3.c +++ b/src/interfaces/libpq/fe-protocol3.c @@ -2051,6 +2051,11 @@ build_startup_packet(const PGconn *conn, char *packe= t, if (conn->client_encoding_initial && conn->client_encoding_initial[0]) ADD_STARTUP_OPTION("client_encoding", conn->client_encoding_initial); =20 +#ifdef ENABLE_GSS + if (!conn->gss_disable_enc) + ADD_STARTUP_OPTION("gss_encrypt", "on"); +#endif + /* Add any environment-driven GUC settings needed */ for (next_eo =3D options; next_eo->envName; next_eo++) { diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-= int.h index 2175957..1578d76 100644 =2D-- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -445,6 +445,7 @@ struct pg_conn gss_name_t gtarg_nam; /* GSS target name */ gss_buffer_desc ginbuf; /* GSS input token */ gss_buffer_desc goutbuf; /* GSS output token */ + bool gss_disable_enc; /* Does server recognize gss_encrypt? */ #endif =20 #ifdef ENABLE_SSPI =2D-=20 2.1.4 --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=v1-3-client-GSSAPI-encryption-and-decryption.patch Content-Transfer-Encoding: quoted-printable From=2036bd232742eb2b920d2cd88dd06176cde7e26cb2 Mon Sep 17 00:00:00 2001 From: "Robbie Harwood (frozencemetery)" Date: Mon, 8 Jun 2015 21:20:23 -0400 Subject: client: GSSAPI encryption and decryption =2D-- src/interfaces/libpq/Makefile | 4 ++ src/interfaces/libpq/fe-auth.c | 2 +- src/interfaces/libpq/fe-auth.h | 5 ++ src/interfaces/libpq/fe-connect.c | 5 ++ src/interfaces/libpq/fe-misc.c | 5 ++ src/interfaces/libpq/fe-protocol3.c | 27 +++++++++++ src/interfaces/libpq/fe-secure-gss.c | 92 ++++++++++++++++++++++++++++++++= ++++ src/interfaces/libpq/libpq-int.h | 7 +++ 8 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/interfaces/libpq/fe-secure-gss.c diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile index c2105f1..a9fb194 100644 =2D-- a/src/interfaces/libpq/Makefile +++ b/src/interfaces/libpq/Makefile @@ -48,6 +48,10 @@ ifeq ($(with_openssl),yes) OBJS +=3D fe-secure-openssl.o endif =20 +ifeq ($(with_gssapi),yes) +OBJS +=3D fe-secure-gss.o +endif + ifeq ($(PORTNAME), cygwin) override shlib =3D cyg$(NAME)$(DLSUFFIX) endif diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c index 5891c75..af6dfff 100644 =2D-- a/src/interfaces/libpq/fe-auth.c +++ b/src/interfaces/libpq/fe-auth.c @@ -82,7 +82,7 @@ pg_GSS_error_int(PQExpBuffer str, const char *mprefix, /* * GSSAPI errors contain two parts; put both into conn->errorMessage. */ =2Dstatic void +void pg_GSS_error(const char *mprefix, PGconn *conn, OM_uint32 maj_stat, OM_uint32 min_stat) { diff --git a/src/interfaces/libpq/fe-auth.h b/src/interfaces/libpq/fe-auth.h index 8d35767..5702a2d 100644 =2D-- a/src/interfaces/libpq/fe-auth.h +++ b/src/interfaces/libpq/fe-auth.h @@ -21,4 +21,9 @@ extern int pg_fe_sendauth(AuthRequest areq, PGconn *conn); extern char *pg_fe_getauthname(PQExpBuffer errorMessage); =20 +#ifdef ENABLE_GSS +void pg_GSS_error(const char *mprefix, PGconn *conn, OM_uint32 maj_stat, + OM_uint32 min_stat); +#endif + #endif /* FE_AUTH_H */ diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-co= nnect.c index c6c551a..8fb0a90 100644 =2D-- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -2513,6 +2513,11 @@ keep_going: /* We will come back to here until = there is /* We are done with authentication exchange */ conn->status =3D CONNECTION_AUTH_OK; =20 +#ifdef ENABLE_GSS + if (conn->gctx !=3D 0) + conn->gss_auth_done =3D true; +#endif + /* * Set asyncStatus so that PQgetResult will think that * what comes back next is the result of a query. See diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c index 0dbcf73..2379aff 100644 =2D-- a/src/interfaces/libpq/fe-misc.c +++ b/src/interfaces/libpq/fe-misc.c @@ -604,6 +604,11 @@ pqPutMsgEnd(PGconn *conn) memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4); } =20 +#ifdef ENABLE_GSS + if (pggss_encrypt(conn) < 0) + return EOF; +#endif + /* Make message eligible to send */ conn->outCount =3D conn->outMsgEnd; =20 diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-= protocol3.c index 0deaa0f..65acfd1 100644 =2D-- a/src/interfaces/libpq/fe-protocol3.c +++ b/src/interfaces/libpq/fe-protocol3.c @@ -129,6 +129,33 @@ pqParseInput3(PGconn *conn) return; } =20 +#ifdef ENABLE_GSS + /* We want to be ready in both IDLE and BUSY states for encryption */ + if (id =3D=3D 'g') + { + ssize_t encEnd, next; + + encEnd =3D pggss_inplace_decrypt(conn, msgLength); + if (encEnd <=3D 0) + { + /* error message placed by pggss_inplace_decrypt() */ + pqSaveErrorResult(conn); + conn->asyncStatus =3D PGASYNC_READY; + pqDropConnection(conn); + conn->status =3D CONNECTION_BAD; + return; + } + + /* shift contents of buffer to account for slack */ + encEnd +=3D conn->inStart; + next =3D conn->inStart + msgLength + 5; + memmove(conn->inBuffer + encEnd, conn->inBuffer + next, + conn->inEnd - next); + conn->inEnd =3D (conn->inEnd - next) + encEnd; + continue; + } +#endif + /* * NOTIFY and NOTICE messages can happen in any state; always process * them right away. diff --git a/src/interfaces/libpq/fe-secure-gss.c b/src/interfaces/libpq/fe= -secure-gss.c new file mode 100644 index 0000000..afea9c3 =2D-- /dev/null +++ b/src/interfaces/libpq/fe-secure-gss.c @@ -0,0 +1,92 @@ +#include + +#include "libpq-fe.h" +#include "postgres_fe.h" +#include "fe-auth.h" +#include "libpq-int.h" + +ssize_t +pggss_inplace_decrypt(PGconn *conn, int gsslen) +{ + OM_uint32 major, minor; + gss_buffer_desc input, output; + ssize_t n; + int conf; + + input.length =3D gsslen; + input.value =3D conn->inBuffer + conn->inCursor; + output.length =3D 0; + output.value =3D NULL; + + major =3D gss_unwrap(&minor, conn->gctx, &input, &output, &conf, NULL); + if (GSS_ERROR(major)) + { + pg_GSS_error("GSSAPI unwrap error", conn, major, minor); + return -1; + } + else if (conf =3D=3D 0) + { + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext( + "received GSSAPI message without confidentiality\n")); + return -1; + } + + memcpy(conn->inBuffer + conn->inStart, output.value, output.length); + n =3D output.length; + gss_release_buffer(&minor, &output); + return n; +} + +int +pggss_encrypt(PGconn *conn) +{ + OM_uint32 major, minor; + gss_buffer_desc input, output; + int msgLen, conf; + uint32 len_n; + + if (conn->gss_disable_enc || !conn->gctx || !conn->gss_auth_done) + return 0; + assert(conn->outMsgStart > 0); + + /* We need to encrypt message type as well */ + conn->outMsgStart -=3D 1; + msgLen =3D conn->outMsgEnd - conn->outMsgStart; + + input.value =3D conn->outBuffer + conn->outMsgStart; + input.length =3D msgLen; + output.length =3D 0; + output.value =3D NULL; + + major =3D gss_wrap(&minor, conn->gctx, 1, GSS_C_QOP_DEFAULT, &input, &con= f, + &output); + if (GSS_ERROR(major)) + { + pg_GSS_error("GSSAPI wrap error", conn, major, minor); + return -1; + } + else if (conf =3D=3D 0) + { + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext( + "Failed to obtain confidentiality for outgoing GSSAPI message\n")= ); + return -1; + } + + msgLen =3D output.length + 4; + if (pqCheckOutBufferSpace(conn->outMsgStart + msgLen + 1, conn)) + return -1; +=09 + conn->outBuffer[conn->outMsgStart] =3D 'g'; /* GSSAPI message */ + + len_n =3D htonl(msgLen); + memcpy(conn->outBuffer + conn->outMsgStart + 1, &len_n, 4); + + memcpy(conn->outBuffer + conn->outMsgStart + 1 + 4, + output.value, output.length); + conn->outMsgEnd =3D conn->outMsgStart + msgLen + 1; + + gss_release_buffer(&minor, &output); + return msgLen + 1; +} diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-= int.h index 1578d76..ff2e39d 100644 =2D-- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -446,6 +446,7 @@ struct pg_conn gss_buffer_desc ginbuf; /* GSS input token */ gss_buffer_desc goutbuf; /* GSS output token */ bool gss_disable_enc; /* Does server recognize gss_encrypt? */ + bool gss_auth_done; /* Did we finish the AUTH step? */ #endif =20 #ifdef ENABLE_SSPI @@ -643,6 +644,12 @@ extern bool pgtls_read_pending(PGconn *conn); extern ssize_t pgtls_write(PGconn *conn, const void *ptr, size_t len); =20 /* + * GSSAPI encryption functions defined in fe-secure-gss.c + */ +extern ssize_t pggss_inplace_decrypt(PGconn *conn, int gsslen); +extern int pggss_encrypt(PGconn *conn); + +/* * this is so that we can check if a connection is non-blocking internally * without the overhead of a function call */ =2D-=20 2.1.4 --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=v1-4-server-GSSAPI-encryption-and-decryption.patch Content-Transfer-Encoding: quoted-printable From=200991d42173394e68e989d84e6574476d6a98e571 Mon Sep 17 00:00:00 2001 From: "Robbie Harwood (frozencemetery)" Date: Tue, 9 Jun 2015 14:38:26 -0400 Subject: server: GSSAPI encryption and decryption =2D-- src/backend/libpq/Makefile | 4 ++ src/backend/libpq/auth.c | 2 +- src/backend/libpq/be-secure-gss.c | 101 ++++++++++++++++++++++++++++++++++= ++++ src/backend/libpq/pqcomm.c | 39 +++++++++++++++ src/backend/tcop/postgres.c | 18 ++++++- src/backend/utils/misc/guc.c | 19 +++++++ src/include/libpq/auth.h | 5 ++ src/include/libpq/libpq-be.h | 9 ++++ src/include/libpq/libpq.h | 4 ++ 9 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 src/backend/libpq/be-secure-gss.c diff --git a/src/backend/libpq/Makefile b/src/backend/libpq/Makefile index 09410c4..359e9d5 100644 =2D-- a/src/backend/libpq/Makefile +++ b/src/backend/libpq/Makefile @@ -21,4 +21,8 @@ ifeq ($(with_openssl),yes) OBJS +=3D be-secure-openssl.o endif =20 +ifeq ($(with_gssapi),yes) +OBJS +=3D be-secure-gss.o +endif + include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 4699efa..913d356 100644 =2D-- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -728,7 +728,7 @@ static GSS_DLLIMP gss_OID GSS_C_NT_USER_NAME =3D &GSS_C= _NT_USER_NAME_desc; #endif =20 =20 =2Dstatic void +void pg_GSS_error(int severity, char *errmsg, OM_uint32 maj_stat, OM_uint32 min= _stat) { gss_buffer_desc gmsg; diff --git a/src/backend/libpq/be-secure-gss.c b/src/backend/libpq/be-secur= e-gss.c new file mode 100644 index 0000000..64a4ed7 =2D-- /dev/null +++ b/src/backend/libpq/be-secure-gss.c @@ -0,0 +1,101 @@ +#include + +#include "postgres.h" + +#include "libpq/libpq.h" +#include "libpq/auth.h" +#include "miscadmin.h" + +/* GUC value */ +bool gss_encrypt; + +size_t +be_gss_encrypt(Port *port, char msgtype, const char **msgptr, size_t len) +{ + OM_uint32 major, minor; + gss_buffer_desc input, output; + uint32 len_n; + int conf; + char *ptr =3D *((char **)msgptr); + char *newbuf =3D palloc(len + 5); + + len +=3D 4; + len_n =3D htonl(len); + + newbuf[0] =3D msgtype; + memcpy(newbuf + 1, &len_n, 4); + memcpy(newbuf + 5, ptr, len - 4); + + input.length =3D len + 1; /* include type */ + input.value =3D newbuf; + output.length =3D 0; + output.value =3D NULL; + + major =3D gss_wrap(&minor, port->gss->ctx, 1, GSS_C_QOP_DEFAULT, &input, + &conf, &output); + if (GSS_ERROR(major)) + { + pg_GSS_error(ERROR, gettext_noop("unwrapping GSS message failed"), + major, minor); + return -1; + } + assert(conf); + + newbuf =3D repalloc(newbuf, output.length); + memcpy(newbuf, output.value, output.length); + + len =3D output.length; + *msgptr =3D newbuf; + gss_release_buffer(&minor, &output); + + return len; +} + +int +be_gss_inplace_decrypt(StringInfo inBuf) +{ + OM_uint32 major, minor; + gss_buffer_desc input, output; + int qtype, conf; + size_t msglen =3D 0; + + input.length =3D inBuf->len; + input.value =3D inBuf->data; + output.length =3D 0; + output.value =3D NULL; + + major =3D gss_unwrap(&minor, MyProcPort->gss->ctx, &input, &output, + &conf, NULL); + if (GSS_ERROR(major)) + { + pg_GSS_error(ERROR, gettext_noop("wrapping GSS message failed"), + major, minor); + return -1; + } + else if (conf =3D=3D 0) + { + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("Expected GSSAPI confidentiality but it was not received"))); + return -1; + } + + qtype =3D ((char *)output.value)[0]; /* first byte is message type */ + inBuf->len =3D output.length - 5; /* message starts */ + + memcpy((char *)&msglen, ((char *)output.value) + 1, 4); + msglen =3D ntohl(msglen); + if (msglen - 4 !=3D inBuf->len) + { + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("Length value inside GSSAPI-encrypted packet was malformed"))); + return -1; + } + + memcpy(inBuf->data, ((char *)output.value) + 5, inBuf->len); + inBuf->data[inBuf->len] =3D '\0'; /* invariant */ + gss_release_buffer(&minor, &output); + + return qtype; +} diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index a4b37ed..5a929a8 100644 =2D-- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -1485,6 +1485,19 @@ socket_putmessage(char msgtype, const char *s, size_= t len) { if (DoingCopyOut || PqCommBusy) return 0; + +#ifdef ENABLE_GSS + /* Do not wrap auth requests. */ + if (MyProcPort->hba->auth_method =3D=3D uaGSS && gss_encrypt && + msgtype !=3D 'R' && msgtype !=3D 'g') + { + len =3D be_gss_encrypt(MyProcPort, msgtype, &s, len); + if (len < 0) + goto fail; + msgtype =3D 'g'; + } +#endif + PqCommBusy =3D true; if (msgtype) if (internal_putbytes(&msgtype, 1)) @@ -1500,10 +1513,20 @@ socket_putmessage(char msgtype, const char *s, size= _t len) if (internal_putbytes(s, len)) goto fail; PqCommBusy =3D false; +#ifdef ENABLE_GSS + /* if we're GSSAPI encrypting, s was allocated in be_gss_encrypt */ + if (msgtype =3D=3D 'g') + pfree((char *)s); +#endif return 0; =20 fail: PqCommBusy =3D false; +#ifdef ENABLE_GSS + /* if we're GSSAPI encrypting, s was allocated in be_gss_encrypt */ + if (msgtype =3D=3D 'g') + pfree((char *)s); +#endif return EOF; } =20 @@ -1519,6 +1542,22 @@ socket_putmessage_noblock(char msgtype, const char *= s, size_t len) int res PG_USED_FOR_ASSERTS_ONLY; int required; =20 +#ifdef ENABLE_GSS + /* + * Because socket_putmessage is also a front-facing function, we need the + * ability to GSSAPI encrypt from either. Since socket_putmessage_noblock + * calls into socket_putmessage, socket_putmessage will handle freeing the + * allocated string. + */ + if (gss_encrypt && msgtype !=3D 'R' && msgtype !=3D 'g') + { + len =3D be_gss_encrypt(MyProcPort, msgtype, &s, len); + if (len < 0) + return; + msgtype =3D 'g'; + } +#endif + /* * Ensure we have enough space in the output buffer for the message header * as well as the message itself. diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index ce4bdaf..8510908 100644 =2D-- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -336,6 +336,7 @@ static int SocketBackend(StringInfo inBuf) { int qtype; + bool msg_got =3D false; =20 /* * Get message type code from the frontend. @@ -365,6 +366,21 @@ SocketBackend(StringInfo inBuf) return qtype; } =20 +#ifdef ENABLE_GSS + else if (qtype =3D=3D 'g' && gss_encrypt && + MyProcPort->hba->auth_method =3D=3D uaGSS) + { + /* GSSAPI wrapping implies protocol >=3D 3 */ + if (pq_getmessage(inBuf, 0)) + return EOF; + msg_got =3D true; + + qtype =3D be_gss_inplace_decrypt(inBuf); + if (qtype < 0) + return EOF; + } +#endif + /* * Validate message type code before trying to read body; if we have lost * sync, better to say "command unknown" than to run out of memory because @@ -490,7 +506,7 @@ SocketBackend(StringInfo inBuf) * after the type code; we can read the message contents independently of * the type. */ =2D if (PG_PROTOCOL_MAJOR(FrontendProtocol) >=3D 3) + if (PG_PROTOCOL_MAJOR(FrontendProtocol) >=3D 3 && !msg_got) { if (pq_getmessage(inBuf, 0)) return EOF; /* suitable message already logged */ diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 0356ecb..a978af0 100644 =2D-- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -186,6 +186,10 @@ static const char *show_log_file_mode(void); static ConfigVariable *ProcessConfigFileInternal(GucContext context, bool applySettings, int elevel); =20 +#ifdef ENABLE_GSS +static void assign_gss_encrypt(bool newval, void *extra); +#endif + =20 /* * Options for enum values defined in this module. @@ -1618,6 +1622,15 @@ static struct config_bool ConfigureNamesBool[] =3D NULL, NULL, NULL }, =20 + { + {"gss_encrypt", PGC_USERSET, CONN_AUTH_SECURITY, + gettext_noop("Whether client wants encryption for this connection."), + NULL, + GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE + }, + &gss_encrypt, false, NULL, assign_gss_encrypt, NULL + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL @@ -10114,4 +10127,10 @@ show_log_file_mode(void) return buf; } =20 +static void +assign_gss_encrypt(bool newval, void *extra) +{ + gss_encrypt =3D newval; +} + #include "guc-file.c" diff --git a/src/include/libpq/auth.h b/src/include/libpq/auth.h index 80f26a8..e98f560 100644 =2D-- a/src/include/libpq/auth.h +++ b/src/include/libpq/auth.h @@ -26,4 +26,9 @@ extern void ClientAuthentication(Port *port); typedef void (*ClientAuthentication_hook_type) (Port *, int); extern PGDLLIMPORT ClientAuthentication_hook_type ClientAuthentication_hoo= k; =20 +#ifdef ENABLE_GSS +void pg_GSS_error(int severity, char *errmsg, OM_uint32 maj_stat, + OM_uint32 min_stat); +#endif + #endif /* AUTH_H */ diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h index 6171ef3..58712fc 100644 =2D-- a/src/include/libpq/libpq-be.h +++ b/src/include/libpq/libpq-be.h @@ -30,6 +30,8 @@ #endif =20 #ifdef ENABLE_GSS +#include "lib/stringinfo.h" + #if defined(HAVE_GSSAPI_H) #include #else @@ -219,6 +221,13 @@ extern void be_tls_get_cipher(Port *port, char *ptr, s= ize_t len); extern void be_tls_get_peerdn_name(Port *port, char *ptr, size_t len); #endif =20 +#ifdef ENABLE_GSS +/* These functions are implemented in be-secure-gss.c */ +extern size_t +be_gss_encrypt(Port *port, char msgtype, const char **msgptr, size_t len); +extern int be_gss_inplace_decrypt(StringInfo inBuf); +#endif + extern ProtocolVersion FrontendProtocol; =20 /* TCP keepalives configuration. These are no-ops on an AF_UNIX socket. */ diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h index c408e5b..e788cc8 100644 =2D-- a/src/include/libpq/libpq.h +++ b/src/include/libpq/libpq.h @@ -99,4 +99,8 @@ extern char *SSLCipherSuites; extern char *SSLECDHCurve; extern bool SSLPreferServerCiphers; =20 +#ifdef ENABLE_GSS +extern bool gss_encrypt; +#endif + #endif /* LIBPQ_H */ =2D-=20 2.1.4 --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=v1-5-Error-when-receiving-plaintext-on-GSS-encrypted-conn.patch Content-Transfer-Encoding: quoted-printable From=20e55795e0638ca37447ef200f21f74db80b07ebf4 Mon Sep 17 00:00:00 2001 From: "Robbie Harwood (frozencemetery)" Date: Fri, 12 Jun 2015 13:27:50 -0400 Subject: Error when receiving plaintext on GSS-encrypted connections =2D-- src/backend/tcop/postgres.c | 12 ++++++++++++ src/interfaces/libpq/fe-protocol3.c | 32 ++++++++++++++++++++++++++++++-- src/interfaces/libpq/libpq-int.h | 1 + 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 8510908..ba8ed4e 100644 =2D-- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -379,6 +379,18 @@ SocketBackend(StringInfo inBuf) if (qtype < 0) return EOF; } + else if (gss_encrypt && MyProcPort->hba->auth_method =3D=3D uaGSS && + qtype !=3D 'g' && qtype !=3D 'R' ) + { + /* + * Either something malicious is occuring, or we have lost + * synchronization. + */ + ereport(FATAL, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid frontend message type %d", qtype))); + return EOF; + } #endif =20 /* diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-= protocol3.c index 65acfd1..d5fb461 100644 =2D-- a/src/interfaces/libpq/fe-protocol3.c +++ b/src/interfaces/libpq/fe-protocol3.c @@ -131,7 +131,7 @@ pqParseInput3(PGconn *conn) =20 #ifdef ENABLE_GSS /* We want to be ready in both IDLE and BUSY states for encryption */ =2D if (id =3D=3D 'g') + if (id =3D=3D 'g' && !conn->gss_disable_enc && conn->gctx) { ssize_t encEnd, next; =20 @@ -152,8 +152,33 @@ pqParseInput3(PGconn *conn) memmove(conn->inBuffer + encEnd, conn->inBuffer + next, conn->inEnd - next); conn->inEnd =3D (conn->inEnd - next) + encEnd; =2D continue; + + conn->inCursor =3D conn->inStart; + (void) pqGetc(&id, conn); + (void) pqGetInt(&msgLength, 4, conn); + msgLength -=3D 4; + if (msgLength !=3D encEnd - conn->inCursor) + { + /* This isn't a sync error because decrypt was successful */ + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext( + "server lied about message length: got message length %ld, but = expected legnth %d\n"), + encEnd - conn->inCursor, msgLength); + /* build an error result holding the error message */ + pqSaveErrorResult(conn); + /* drop out of GetResult wait loop */ + conn->asyncStatus =3D PGASYNC_READY; + + pqDropConnection(conn); + /* No more connection to backend */ + conn->status =3D CONNECTION_BAD; + } + conn->gss_decrypted_cur =3D true; } + else if (!conn->gss_disable_enc && conn->gss_auth_done && + !conn->gss_decrypted_cur && id !=3D 'E') + /* This could be a sync error, so let's handle it as such. */ + handleSyncLoss(conn, id, msgLength); #endif =20 /* @@ -425,6 +450,9 @@ pqParseInput3(PGconn *conn) { /* Normal case: parsing agrees with specified length */ conn->inStart =3D conn->inCursor; +#ifdef ENABLE_GSS + conn->gss_decrypted_cur =3D false; +#endif } else { diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-= int.h index ff2e39d..7a3ebcd 100644 =2D-- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -447,6 +447,7 @@ struct pg_conn gss_buffer_desc goutbuf; /* GSS output token */ 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? */ #endif =20 #ifdef ENABLE_SSPI =2D-=20 2.1.4 --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=v1-6-server-hba-option-for-requiring-GSSAPI-encryption.patch Content-Transfer-Encoding: quoted-printable From=20dcba977f9e37e80fafc7deb89b8856738f20928d Mon Sep 17 00:00:00 2001 From: "Robbie Harwood (frozencemetery)" 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. =2D-- 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 =2D-- 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 *h= baline, int line_num) else hbaline->include_realm =3D false; } + else if (strcmp(name, "require_encrypt") =3D=3D 0) + { + if (hbaline->auth_method !=3D uaGSS) + INVALID_AUTH_OPTION("require_encrypt", "gssapi"); + if (strcmp(val, "1") =3D=3D 0) + hbaline->require_encrypt =3D true; + else + hbaline->require_encrypt =3D false; + } else if (strcmp(name, "radiusserver") =3D=3D 0) { struct addrinfo *gai_result; diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/pos= tinit.c index 0f04f28..cc5c9af 100644 =2D-- 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" =2D#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_superuse= r) =20 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))); } =20 /* diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index a978af0..3a8ba61 100644 =2D-- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -188,6 +188,7 @@ static ConfigVariable *ProcessConfigFileInternal(GucCon= text context, =20 #ifdef ENABLE_GSS static void assign_gss_encrypt(bool newval, void *extra); +static bool check_gss_encrypt(bool *newval, void **extra, GucSource source= ); #endif =20 =20 @@ -1628,7 +1629,7 @@ static struct config_bool ConfigureNamesBool[] =3D NULL, GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE }, =2D &gss_encrypt, false, NULL, assign_gss_encrypt, NULL + &gss_encrypt, false, check_gss_encrypt, assign_gss_encrypt, NULL }, =20 /* End-of-list marker */ @@ -10133,4 +10134,13 @@ assign_gss_encrypt(bool newval, void *extra) gss_encrypt =3D newval; } =20 +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 =2D-- 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; =2D-=20 2.1.4 --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=v1-7-client-gss_enc_require-parameter-to-force-GSS-encryp.patch Content-Transfer-Encoding: quoted-printable From=20b32190b69479a46291088b9ef15208d47975bcba Mon Sep 17 00:00:00 2001 From: "Robbie Harwood (frozencemetery)" Date: Mon, 15 Jun 2015 19:54:29 -0400 Subject: client: gss_enc_require parameter to force GSS encryption =2D-- 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-co= nnect.c index 8fb0a90..115a52c 100644 =2D-- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -297,6 +297,12 @@ static const internalPQconninfoOption PQconninfoOption= s[] =3D { offsetof(struct pg_conn, gsslib)}, #endif =20 +#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 =2D else if (!conn->gss_disable_enc) + else if (!conn->gss_disable_enc && + *conn->gss_enc_require !=3D '1') { /* * We tried to request GSS encryption, but the server =2D * doesn't support it. Hang up and try again. A =2D * connection that doesn't support appname will also =2D * not support GSSAPI encryption, so this check goes =2D * 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; =20 @@ -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 =3D=3D '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 =20 /* * 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 =2D-- 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 =20 #ifdef ENABLE_SSPI =2D-=20 2.1.4 --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=v1-8-Document-GSSAPI-encryption.patch Content-Transfer-Encoding: quoted-printable From=20d5b374d0a466c4bf642d806168d973d4aad638e8 Mon Sep 17 00:00:00 2001 From: "Robbie Harwood (frozencemetery)" Date: Mon, 29 Jun 2015 15:29:36 -0400 Subject: Document GSSAPI encryption =2D-- doc/src/sgml/client-auth.sgml | 19 ++++++++++++++++--- doc/src/sgml/libpq.sgml | 12 ++++++++++++ doc/src/sgml/protocol.sgml | 40 ++++++++++++++++++++++++++++++++++++++++ doc/src/sgml/runtime.sgml | 20 +++++++++++++++++++- 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index 5f72beb..3c49612 100644 =2D-- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -913,9 +913,10 @@ omicron bryanh guest1 GSSAPI with Kerberos authentication according to RFC 1964. GSSAPI provides automatic authentication (single sign-on) for systems =2D that support it. The authentication itself is secure, but the =2D data sent over the database connection will be sent unencrypted unle= ss =2D SSL is used. + that support it. The authentication itself is secure, and GSSAPI can be + used for connection encryption as well (see the + require_encrypt parameter below); SSL + can also be used for connection security. =20 @@ -1046,6 +1047,18 @@ omicron bryanh guest1 + + + require_encrypt + + + Whether to require GSSAPI encryption. Default is off, which causes + GSSAPI encryption to be enabled if available and requested for + compatability with old clients. It is recommended to set this unl= ess + old clients are present. + + + diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index de6b3ad..db2340c 100644 =2D-- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1356,6 +1356,18 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname =20 + + gss_enc_require + + + If set, whether to require GSSAPI encryption support from the remo= te + server. Defaults to unset, which will cause the client to fall bac= k to + not using GSSAPI encryption if the server does not support encrypt= ion + through GSSAPI. + + + + service diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml index 42e9497..8355e54 100644 =2D-- a/doc/src/sgml/protocol.sgml +++ b/doc/src/sgml/protocol.sgml @@ -1295,6 +1295,46 @@ of authentication checking. + + + <acronym>GSSAPI</acronym> Session Encryption + + + If PostgreSQL was built with + GSSAPI and GSSAPI support, traff= ic + can also be encrypted using GSSAPI. To force encryp= tion + using GSSAPI, set require_encrypt in + pg_hba.conf. + + + + In order to probe for GSSAPI support, the client wi= ll + include in their StartupMessage the parameter gss_encrypt. If the serv= er + does not support GSSAPI or GSSAPI + encryption, the server will error the connection; otherwise, it contin= ues + as normal. The client may retry the connection + without GSSAPI encryption support depending on its + settings. If the client does not probe support, depending on settings + in pg_hba.conf, the server may drop + GSSAPI-authenticated connections without encryption. + + + + If the client has probed GSSAPI encryption support = and + the connection is GSSAPI-authenticated, then after = the + server sends AuthenticationOk, all traffic between the client and serv= er + will be GSSAPI-encrypted. Because + GSSAPI does not provide framing, + GSSAPI-encrypted messages are modeled after protoco= l-3 + messages: the first byte is the caracter g, then four bytes of length,= and + then an encrypted message. + + + + It is valid to use GSSAPI encryption over + SSL-encrypted connections. + + =20 diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 547567e..0b1b009 100644 =2D-- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -1833,7 +1833,7 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433 =20 =2D To prevent spoofing on TCP connections, the best solution is to use + To prevent spoofing on TCP connections, one possible solution is to use SSL certificates and make sure that clients check the server's certific= ate. To do that, the server must be configured to accept only hostssl connections (verify-full and have the appropriate root certificate file installed (). + + + Another way of preventing spoofing on TCP connections is to use GSSAPI + encryption. In order to force all GSSAPI connections to be encrypted, o= ne + should set require_encrypt in pg_hba.conf on G= SS + connections. Then, using Kerberos, the client and server will mutually + authenticate, and the connection will be encrypted once the authenticat= ion + step is complete. + =20 @@ -1958,6 +1967,15 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433 connect to servers only via SSL. Stunnel or SSH can also be used to encrypt transmissions. + + + GSSAPI connections can also encrypt all data sent across the + network. In the pg_hba.conf file, the GSS authenticaion + method has a parameter to require encryption; otherwise, connections + will be encrypted if available and requiested by the client. On the + client side, there is also a parameter to require GSSAPI encryption + support from the server. + =20 =2D-=20 2.1.4 --=-=-=-- --==-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAEBAgAGBQJVlYFWAAoJECUy+RdqlaRC9/sP/RcHr7bi4GyV4AnTHP0qTx7a emSlxb03+wybO4jyA0pyIjbRkZG/K3SelqIc6hSsUhQN1n5Inw3gKCFzvQLT3qN+ AkAbzOFohpy/h6EmO2p9orbLfyc0q607gQPmdRHFy/hPiGylptyMywbdCzmX2q8Z ttKo9hSstV8SWZoKlm2VUK+LPAzCZpQ/wa80yBhCUlbRfFet4dRKQjNC1FXQZsj4 w0V73F23L8t6OmKfBZ6SVCzPZW6hUPxK7e2xfhK4O1qVkIBaOYsQwNuZGGfp93c9 q0Bp72BOu4D0k1NCGZpPaqm9gDCKqbq2PHEW5hI8nYKCiAxV0NwyppE7NCrNjSWL S0Rsl6O1DE2u4k+SllLuguF7RoKGKPNIiQc8V+/7a8EdD93iTN2ReEQmmdO+aZyD ZLRcdE7ENvYF38uj3tAU8eKlvHs8Stxkw3BYb5lfXpgqPFisNPCgx2Yi6uYVO9aq 8vd/2rwOzt7hYjwZakr794koRwl1bPHZyyRCm+dXccuTmjwimP0NNXwL+DHqtMCp ue3pJDms82cQu3Hn4l234uyEbLPVUFvAGtZ0UlSpCdqzi04XTE3K9v32OmcemQJo ZeC9BSn4oLhzEvnvMP0w6iXnTsMd1buhjXGGPbrjhH9yZD9SeaJbrdqZyYkqKvqB GT9RbKzYRogCz578p0f7 =nGHv -----END PGP SIGNATURE----- --==-=-=--