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
  

Attachment: signature.asc
Description: PGP signature

Reply via email to