Greetings Robbie, * Robbie Harwood (rharw...@redhat.com) wrote: > Attached please find version 20 of the GSSAPI encryption support. This > has been rebased onto master (thanks Stephen for calling out ab69ea9). > Other changes since v19 from Stephen's review: > > - About 100 lines of new comments
Thanks for that. > - pgindent run over code (only the stuff I'm changing; it reports other > problems on master, but if I understand correctly, that's not on me to > fix here) That's correct. > Thanks for the feedback! And speaking of feedback, this patch is in the > "Needs Review" state so if people have additional feedback, that would > be appreciated. I've CC'd people who I can remember reviewing before; > they should of course feel no obligation to review again if time > commitments/interests do not allow. I've looked over this again and have been playing with it off-and-on for a while now. One thing I was actually looking at implementing before we push to commit this was to have similar information to what SSL provides on connection, specifically what printSSLInfo() prints by way of cipher, bits, etc for the client-side and then something like pg_stat_ssl for the server side. I went ahead and added a printGSSENCInfo(), and then PQgetgssSASLSSF(), which calls down into gss_inquire_sec_context_by_oid() for GSS_C_SEC_CONTEXT_SASL_SSF to get the bits (which also required including gssapi_ext.h), and now have psql producing: --- psql (12devel) GSS Encrypted connection (bits: 256) Type "help" for help. --- I was curious though- is there a good way to get at the encryption type used..? I haven't had much luck in reading the RFPs and poking around, but perhaps I'm just not looking in the right place. Also, what information do you think would be particularly useful on the server side? I was thinking that the princ used to authenticate, the encryption type/cipher, and bits used, at least, would be meaningful. I'm also guessing that we may need to add something to make these functions not fail on older systems which don't provide the SASL SSF OID..? I haven't looked into that yet but we should. I don't think these things are absolutely required to push the patch forward, just to be clear, but it's helping my confidence level, at least, and would make it closer to on-par with our current SSL implementation. They also seem, well, reasonably straight-forward to add and quite useful. I've attached my WIP patch for adding the bits, patched over-top of your v20 (would be neat if there was a way to tell cfbot to ignore it...). Thoughts? Thanks! Stephen
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c new file mode 100644 index ab259c4..2599330 *** a/src/bin/psql/command.c --- b/src/bin/psql/command.c *************** static void print_with_linenumbers(FILE *** 159,164 **** --- 159,165 ---- static void minimal_error_message(PGresult *res); static void printSSLInfo(void); + static void printGSSENCInfo(void); static bool printPsetInfo(const char *param, struct printQueryOpt *popt); static char *pset_value_string(const char *param, struct printQueryOpt *popt); *************** exec_command_conninfo(PsqlScanState scan *** 621,626 **** --- 622,628 ---- db, PQuser(pset.db), host, PQport(pset.db)); } printSSLInfo(); + printGSSENCInfo(); } } *************** connection_warnings(bool in_startup) *** 3184,3189 **** --- 3186,3192 ---- checkWin32Codepage(); #endif printSSLInfo(); + printGSSENCInfo(); } } *************** printSSLInfo(void) *** 3216,3221 **** --- 3219,3244 ---- (compression && strcmp(compression, "off") != 0) ? _("on") : _("off")); } + /* + * printGSSENCInfo + * + * Prints information about the current GSS-Encrypted connection, if GSS + * encryption is in use. + */ + static void + printGSSENCInfo(void) + { + const char *bits; + + if (!PQgssEncInUse(pset.db)) + return; /* no GSS Encryption */ + + bits = PQgetgssSASLSSF(pset.db); + + printf(_("GSS Encrypted connection (bits: %s)\n"), + bits ? bits : _("unknown")); + } + /* * checkWin32Codepage diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt new file mode 100644 index cc9ee9c..3db936f *** a/src/interfaces/libpq/exports.txt --- b/src/interfaces/libpq/exports.txt *************** PQresultVerboseErrorMessage 171 *** 174,176 **** --- 174,179 ---- PQencryptPasswordConn 172 PQresultMemorySize 173 PQhostaddr 174 + PQgssEncInUse 175 + PQgetgssctx 176 + PQgetgssSASLSSF 177 diff --git a/src/interfaces/libpq/fe-secure-gssapi.c b/src/interfaces/libpq/fe-secure-gssapi.c new file mode 100644 index 5d9c1f8..df63882 *** a/src/interfaces/libpq/fe-secure-gssapi.c --- b/src/interfaces/libpq/fe-secure-gssapi.c *************** *** 17,22 **** --- 17,24 ---- #include "libpq-int.h" #include "fe-gssapi-common.h" + #include "port/pg_bswap.h" + /* * Require encryption support, as well as mutual authentication and * tamperproofing measures. *************** *** 24,29 **** --- 26,36 ---- #define GSS_REQUIRED_FLAGS GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | \ GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG + static ssize_t send_buffered_data(PGconn *conn, size_t len); + static ssize_t read_from_buffer(PGconn *conn, void *ptr, size_t len); + static ssize_t load_packet_length(PGconn *conn); + static ssize_t load_packet(PGconn *conn, size_t len); + /* * Helper function to write any pending data. Returns len when it has all * been written; otherwise, sets errno appropriately. Assumes there is data *************** pqsecure_open_gss(PGconn *conn) *** 392,394 **** --- 399,465 ---- gss_release_buffer(&minor, &output); return PGRES_POLLING_WRITING; } + + /* + * GSSAPI Information functions. + */ + + /* + * Return the GSSAPI Context itself + */ + void * + PQgetgssctx(PGconn *conn) + { + if (!conn) + return NULL; + + return conn->gctx; + } + + /* + * Return a string which represents the SASL SSF code. + * + * This is essentially the number of bits in the encryption key, or zero for + * no encryption or integrity, or 1 for integrity but no encryption. + * + * On error, NULL is returned. + */ + const char * + PQgetgssSASLSSF(PGconn *conn) + { + uint32 tmp4, + result; + OM_uint32 major, + minor; + gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET; + gss_OID ssf_oid = GSS_C_SEC_CONTEXT_SASL_SSF; + static char ssf[5] = "\0\0\0\0\0"; + + if (!conn) + return NULL; + + /* Query the SSF value and range-check the result. */ + major = gss_inquire_sec_context_by_oid(&minor, conn->gctx, ssf_oid, &bufset); + + if (major != GSS_S_COMPLETE) + { + pg_GSS_error(libpq_gettext("GSSAPI inquire security context error"), conn, major, minor); + return NULL; + } + + if (bufset->elements[0].length != 4) + return NULL; + + /* + * gss_inquire_sec_context_by_oid() for GSS_C_SEC_CONTEXT_SASL_SSF returns a 32bit integer in network byte-order, + * so we need to adjust for that and then print the integer into our text string. + */ + memcpy(&tmp4, bufset->elements[0].value, 4); + result = pg_ntoh32(tmp4); + + snprintf(ssf,5,"%d",result); + + (void)gss_release_buffer_set(&minor, &bufset); + + return ssf; + } diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c new file mode 100644 index f8e24ee..c26a237 *** a/src/interfaces/libpq/fe-secure.c --- b/src/interfaces/libpq/fe-secure.c *************** PQsslInUse(PGconn *conn) *** 137,142 **** --- 137,150 ---- return conn->ssl_in_use; } + int + PQgssEncInUse(PGconn *conn) + { + if (!conn) + return 0; + return conn->gssenc; + } + /* * Exported function to allow application to tell us it's already * initialized OpenSSL. *************** PQsslAttributeNames(PGconn *conn) *** 434,439 **** --- 442,464 ---- } #endif /* USE_SSL */ + /* Dummy versions of GSSAPI info functions, when built without GSS support */ + #ifndef ENABLE_GSS + + void * + PQgetgssctx(PGconn *conn) + { + return NULL; + } + + const char * + PQgetgssSASLSSF(PGconn *conn) + { + return NULL; + } + + #endif /* ENABLE_GSS */ + #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32) diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h new file mode 100644 index a6f928a..4980835 *** a/src/interfaces/libpq/libpq-fe.h --- b/src/interfaces/libpq/libpq-fe.h *************** extern void PQinitSSL(int do_init); *** 347,352 **** --- 347,357 ---- /* More detailed way to tell libpq whether it needs to initialize OpenSSL */ extern void PQinitOpenSSL(int do_ssl, int do_crypto); + /* GSSAPI information functions */ + extern int PQgssEncInUse(PGconn *conn); + extern void *PQgetgssctx(PGconn *conn); + extern const char *PQgetgssSASLSSF(PGconn *conn); + /* Set verbosity for PQerrorMessage and PQresultErrorMessage */ extern PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity); diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h new file mode 100644 index aa95a80..cc39f33 *** a/src/interfaces/libpq/libpq-int.h --- b/src/interfaces/libpq/libpq-int.h *************** *** 47,54 **** --- 47,56 ---- #ifdef ENABLE_GSS #if defined(HAVE_GSSAPI_H) #include <gssapi.h> + #include <gssapi_ext.h> #else #include <gssapi/gssapi.h> + #include <gssapi/gssapi_ext.h> #endif #endif
signature.asc
Description: PGP signature