1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-02 04:21:28 +03:00

GSSAPI encryption support

On both the frontend and backend, prepare for GSSAPI encryption
support by moving common code for error handling into a separate file.
Fix a TODO for handling multiple status messages in the process.
Eliminate the OIDs, which have not been needed for some time.

Add frontend and backend encryption support functions.  Keep the
context initiation for authentication-only separate on both the
frontend and backend in order to avoid concerns about changing the
requested flags to include encryption support.

In postmaster, pull GSSAPI authorization checking into a shared
function.  Also share the initiator name between the encryption and
non-encryption codepaths.

For HBA, add "hostgssenc" and "hostnogssenc" entries that behave
similarly to their SSL counterparts.  "hostgssenc" requires either
"gss", "trust", or "reject" for its authentication.

Similarly, add a "gssencmode" parameter to libpq.  Supported values are
"disable", "require", and "prefer".  Notably, negotiation will only be
attempted if credentials can be acquired.  Move credential acquisition
into its own function to support this behavior.

Add a simple pg_stat_gssapi view similar to pg_stat_ssl, for monitoring
if GSSAPI authentication was used, what principal was used, and if
encryption is being used on the connection.

Finally, add documentation for everything new, and update existing
documentation on connection security.

Thanks to Michael Paquier for the Windows fixes.

Author: Robbie Harwood, with changes to the read/write functions by me.
Reviewed in various forms and at different times by: Michael Paquier,
   Andres Freund, David Steele.
Discussion: https://www.postgresql.org/message-id/flat/jlg1tgq1ktm.fsf@thriss.redhat.com
This commit is contained in:
Stephen Frost
2019-04-03 15:02:33 -04:00
parent 5f6fc34af5
commit b0b39f72b9
35 changed files with 2575 additions and 197 deletions

View File

@@ -5117,9 +5117,9 @@
proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
proretset => 't', provolatile => 's', proparallel => 'r',
prorettype => 'record', proargtypes => 'int4',
proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,bool,text,numeric,text}',
proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,sslcompression,ssl_client_dn,ssl_client_serial,ssl_issuer_dn}',
proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,bool,text,numeric,text,bool,text,bool}',
proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,sslcompression,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc}',
prosrc => 'pg_stat_get_activity' },
{ oid => '3318',
descr => 'statistics: information about progress of backends running maintenance command',

View File

@@ -55,7 +55,9 @@ typedef enum ConnType
ctLocal,
ctHost,
ctHostSSL,
ctHostNoSSL
ctHostNoSSL,
ctHostGSS,
ctHostNoGSS,
} ConnType;
typedef enum ClientCertMode

View File

@@ -86,6 +86,10 @@ typedef struct
gss_cred_id_t cred; /* GSSAPI connection cred's */
gss_ctx_id_t ctx; /* GSSAPI connection context */
gss_name_t name; /* GSSAPI client name */
char *princ; /* GSSAPI Principal used for auth, NULL if
* GSSAPI auth was not used */
bool auth; /* GSSAPI Authentication used */
bool enc; /* GSSAPI encryption in use */
#endif
} pg_gssinfo;
#endif
@@ -164,6 +168,9 @@ typedef struct Port
int keepalives_interval;
int keepalives_count;
/*
* GSSAPI structures.
*/
#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
/*
@@ -262,6 +269,13 @@ extern void be_tls_get_peer_subject_name(Port *port, char *ptr, size_t len);
extern void be_tls_get_peer_issuer_name(Port *port, char *ptr, size_t len);
extern void be_tls_get_peer_serial(Port *port, char *ptr, size_t len);
/*
* Return information about the GSSAPI authenticated connection
*/
extern bool be_gssapi_get_auth(Port *port);
extern bool be_gssapi_get_enc(Port *port);
extern const char *be_gssapi_get_princ(Port *port);
/*
* Get the server certificate hash for SCRAM channel binding type
* tls-server-end-point.
@@ -279,6 +293,12 @@ extern char *be_tls_get_certificate_hash(Port *port, size_t *len);
#endif /* USE_SSL */
#ifdef ENABLE_GSS
/* Read and write to a GSSAPI-encrypted connection. */
extern ssize_t be_gssapi_read(Port *port, void *ptr, size_t len);
extern ssize_t be_gssapi_write(Port *port, void *ptr, size_t len);
#endif /* ENABLE_GSS */
extern ProtocolVersion FrontendProtocol;
/* TCP keepalives configuration. These are no-ops on an AF_UNIX socket. */

View File

@@ -93,6 +93,9 @@ extern ssize_t secure_read(Port *port, void *ptr, size_t len);
extern ssize_t secure_write(Port *port, void *ptr, size_t len);
extern ssize_t secure_raw_read(Port *port, void *ptr, size_t len);
extern ssize_t secure_raw_write(Port *port, const void *ptr, size_t len);
#ifdef ENABLE_GSS
extern ssize_t secure_open_gssapi(Port *port);
#endif
extern bool ssl_loaded_verify_locations;

View File

@@ -199,9 +199,10 @@ typedef struct CancelRequestPacket
/*
* A client can also start by sending a SSL negotiation request, to get a
* secure channel.
* A client can also start by sending a SSL or GSSAPI negotiation request to
* get a secure channel.
*/
#define NEGOTIATE_SSL_CODE PG_PROTOCOL(1234,5679)
#define NEGOTIATE_GSS_CODE PG_PROTOCOL(1234,5680)
#endif /* PQCOMM_H */

View File

@@ -801,7 +801,8 @@ typedef enum
WAIT_EVENT_SSL_OPEN_SERVER,
WAIT_EVENT_WAL_RECEIVER_WAIT_START,
WAIT_EVENT_WAL_SENDER_WAIT_WAL,
WAIT_EVENT_WAL_SENDER_WRITE_DATA
WAIT_EVENT_WAL_SENDER_WRITE_DATA,
WAIT_EVENT_GSS_OPEN_SERVER,
} WaitEventClient;
/* ----------
@@ -989,6 +990,23 @@ typedef struct PgBackendSSLStatus
char ssl_issuer_dn[NAMEDATALEN];
} PgBackendSSLStatus;
/*
* PgBackendGSSStatus
*
* For each backend, we keep the GSS status in a separate struct, that
* is only filled in if GSS is enabled.
*
* All char arrays must be null-terminated.
*/
typedef struct PgBackendGSSStatus
{
/* Information about GSSAPI connection */
char gss_princ[NAMEDATALEN]; /* GSSAPI Principal used to auth */
bool gss_auth; /* If GSSAPI authentication was used */
bool gss_enc; /* If encryption is being used */
} PgBackendGSSStatus;
/* ----------
* PgBackendStatus
@@ -1043,6 +1061,10 @@ typedef struct PgBackendStatus
bool st_ssl;
PgBackendSSLStatus *st_sslstatus;
/* Information about GSSAPI connection */
bool st_gss;
PgBackendGSSStatus *st_gssstatus;
/* current state */
BackendState st_state;