1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +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

@ -108,6 +108,8 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
host <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional>
hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional>
hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional>
hostgssenc <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional>
hostnogssenc <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional>
</synopsis>
The meaning of the fields is as follows:
@ -128,9 +130,10 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
<listitem>
<para>
This record matches connection attempts made using TCP/IP.
<literal>host</literal> records match either
<literal>host</literal> records match
<acronym>SSL</acronym> or non-<acronym>SSL</acronym> connection
attempts.
attempts as well as <acronym>GSSAPI</acronym> encrypted or
non-<acronym>GSSAPI</acronym> encrypted connection attempts.
</para>
<note>
<para>
@ -176,6 +179,42 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>hostgssenc</literal></term>
<listitem>
<para>
This record matches connection attempts made using TCP/IP,
but only when the connection is made with <acronym>GSSAPI</acronym>
encryption.
</para>
<para>
To make use of this option the server must be built with
<acronym>GSSAPI</acronym> support. Otherwise,
the <literal>hostgssenc</literal> record is ignored except for logging
a warning that it cannot match any connections.
</para>
<para>
Note that the only supported <xref linkend="auth-methods"/> for use
with <acronym>GSSAPI</acronym> encryption
are <literal>gss</literal>, <literal>reject</literal>,
and <literal>trust</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>hostnogssenc</literal></term>
<listitem>
<para>
This record type has the opposite behavior of <literal>hostgssenc</literal>;
it only matches connection attempts made over
TCP/IP that do not use <acronym>GSSAPI</acronym> encryption.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable>database</replaceable></term>
<listitem>
@ -450,8 +489,9 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
<listitem>
<para>
Use GSSAPI to authenticate the user. This is only
available for TCP/IP connections. See <xref
linkend="gssapi-auth"/> for details.
available for TCP/IP connections . See <xref
linkend="gssapi-auth"/> for details. It can be used in conjunction
with GSSAPI encryption.
</para>
</listitem>
</varlistentry>
@ -703,15 +743,18 @@ host postgres all 192.168.12.10/32 scram-sha-256
host all mike .example.com md5
host all all .example.com scram-sha-256
# In the absence of preceding "host" lines, these two lines will
# In the absence of preceding "host" lines, these three lines will
# reject all connections from 192.168.54.1 (since that entry will be
# matched first), but allow GSSAPI connections from anywhere else
# on the Internet. The zero mask causes no bits of the host IP
# address to be considered, so it matches any host.
# matched first), but allow GSSAPI-encrypted connections from anywhere else
# on the Internet. The zero mask causes no bits of the host IP address to
# be considered, so it matches any host. Unencrypted GSSAPI connections
# (which "fall through" to the third line since "hostgssenc" only matches
# encrypted GSSAPI connections) are allowed, but only from 192.168.12.10.
#
# TYPE DATABASE USER ADDRESS METHOD
host all all 192.168.54.1/32 reject
host all all 0.0.0.0/0 gss
hostgssenc all all 0.0.0.0/0 gss
host all all 192.168.12.10/32 gss
# Allow users from 192.168.x.x hosts to connect to any database, if
# they pass the ident check. If, for example, ident says the user is
@ -1058,13 +1101,16 @@ omicron bryanh guest1
<para>
<productname>GSSAPI</productname> is an industry-standard protocol
for secure authentication defined in RFC 2743.
<productname>PostgreSQL</productname> supports
<productname>GSSAPI</productname> with <productname>Kerberos</productname>
authentication according to RFC 1964. <productname>GSSAPI</productname>
provides automatic authentication (single sign-on) for systems
that support it. The authentication itself is secure, but the
data sent over the database connection will be sent unencrypted unless
<acronym>SSL</acronym> is used.
<productname>PostgreSQL</productname>
supports <productname>GSSAPI</productname> for use as either an encrypted,
authenticated layer, or for authentication only.
<productname>GSSAPI</productname> provides automatic authentication
(single sign-on) for systems that support it. The authentication itself is
secure. If <productname>GSSAPI</productname> encryption
(see <literal>hostgssenc</literal>) or <acronym>SSL</acronym> encryption are
used, the data sent along the database connection will be encrypted;
otherwise, it will not.
</para>
<para>

View File

@ -1316,6 +1316,63 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
</listitem>
</varlistentry>
<varlistentry id="libpq-connect-gssencmode" xreflabel="gssencmode">
<term><literal>gssencmode</literal></term>
<listitem>
<para>
This option determines whether or with what priority a secure
<acronym>GSS</acronym> TCP/IP connection will be negotiated with the
server. There are three modes:
<variablelist>
<varlistentry>
<term><literal>disable</literal></term>
<listitem>
<para>
only try a non-<acronym>GSSAPI</acronym>-encrypted connection
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>prefer</literal> (default)</term>
<listitem>
<para>
if there are <acronym>GSSAPI</acronym> credentials present (i.e.,
in a credentials cache), first try
a <acronym>GSSAPI</acronym>-encrypted connection; if that fails or
there are no credentials, try a
non-<acronym>GSSAPI</acronym>-encrypted connection. This is the
default when <productname>PostgreSQL</productname> has been
compiled with <acronym>GSSAPI</acronym> support.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>require</literal></term>
<listitem>
<para>
only try a <acronym>GSSAPI</acronym>-encrypted connection
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
<literal>gssencmode</literal> is ignored for Unix domain socket
communication. If <productname>PostgreSQL</productname> is compiled
without GSSAPI support, using the <literal>require</literal> option
will cause an error, while <literal>prefer</literal> will be accepted
but <application>libpq</application> will not actually attempt
a <acronym>GSSAPI</acronym>-encrypted
connection.<indexterm><primary>GSSAPI</primary><secondary sortas="libpq">with
libpq</secondary></indexterm>
</para>
</listitem>
</varlistentry>
<varlistentry id="libpq-connect-sslmode" xreflabel="sslmode">
<term><literal>sslmode</literal></term>
<listitem>
@ -7948,7 +8005,7 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*)
</para>
<para>
For a connection to be known secure, SSL usage must be configured
For a connection to be known SSL-secured, SSL usage must be configured
on <emphasis>both the client and the server</emphasis> before the connection
is made. If it is only configured on the server, the client may end up
sending sensitive information (e.g. passwords) before

View File

@ -336,6 +336,14 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
</entry>
</row>
<row>
<entry><structname>pg_stat_gssapi</structname><indexterm><primary>pg_stat_gssapi</primary></indexterm></entry>
<entry>One row per connection (regular and replication), showing information about
GSSAPI authentication and encryption used on this connection.
See <xref linkend="pg-stat-gssapi-view"/> for details.
</entry>
</row>
<row>
<entry><structname>pg_stat_progress_create_index</structname><indexterm><primary>pg_stat_progress_create_index</primary></indexterm></entry>
<entry>One row for each backend running <command>CREATE INDEX</command>, showing
@ -2281,6 +2289,55 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
connection.
</para>
<table id="pg-stat-gssapi-view" xreflabel="pg_stat_gssapi">
<title><structname>pg_stat_gssapi</structname> View</title>
<tgroup cols="3">
<thead>
<row>
<entry>Column</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><structfield>pid</structfield></entry>
<entry><type>integer</type></entry>
<entry>Process ID of a backend</entry>
</row>
<row>
<entry><structfield>gss_authenticated</structfield></entry>
<entry><type>boolean</type></entry>
<entry>True if GSSAPI authentication was used for this connection</entry>
</row>
<row>
<entry><structfield>principal</structfield></entry>
<entry><type>text</type></entry>
<entry>Principal used to authenticate this connection, or NULL
if GSSAPI was not used to authenticate this connection. This
field is truncated if the principal is longer than
<symbol>NAMEDATALEN</symbol> (64 characters in a standard build).
</entry>
</row>
<row>
<entry><structfield>encrypted</structfield></entry>
<entry><type>boolean</type></entry>
<entry>True if GSSAPI encryption is in use on this connection</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
The <structname>pg_stat_gssapi</structname> view will contain one row per
backend, showing information about GSSAPI usage on this connection. It can
be joined to <structname>pg_stat_activity</structname> or
<structname>pg_stat_replication</structname> on the
<structfield>pid</structfield> column to get more details about the
connection.
</para>
<table id="pg-stat-archiver-view" xreflabel="pg_stat_archiver">
<title><structname>pg_stat_archiver</structname> View</title>

View File

@ -2037,9 +2037,13 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
</para>
<para>
To prevent spoofing on TCP connections, the best solution is to use
SSL certificates and make sure that clients check the server's certificate.
To do that, the server
To prevent spoofing on TCP connections, either use
SSL certificates and make sure that clients check the server's certificate,
or use GSSAPI encryption (or both, if they're on separate connections).
</para>
<para>
To prevent spoofing with SSL, the server
must be configured to accept only <literal>hostssl</literal> connections (<xref
linkend="auth-pg-hba-conf"/>) and have SSL key and certificate files
(<xref linkend="ssl-tcp"/>). The TCP client must connect using
@ -2047,6 +2051,14 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
<literal>verify-full</literal> and have the appropriate root certificate
file installed (<xref linkend="libq-ssl-certificates"/>).
</para>
<para>
To prevent spoofing with GSSAPI, the server must be configured to accept
only <literal>hostgssenc</literal> connections
(<xref linkend="auth-pg-hba-conf"/>) and use <literal>gss</literal>
authentication with them. The TCP client must connect
using <literal>gssencmode=require</literal>.
</para>
</sect1>
<sect1 id="encryption-options">
@ -2143,8 +2155,24 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
which hosts can use non-encrypted connections (<literal>host</literal>)
and which require SSL-encrypted connections
(<literal>hostssl</literal>). Also, clients can specify that they
connect to servers only via SSL. <application>Stunnel</application> or
<application>SSH</application> can also be used to encrypt transmissions.
connect to servers only via SSL.
</para>
<para>
GSSAPI-encrypted connections encrypt all data sent across the network,
including queries and data returned. (No password is sent across the
network.) The <filename>pg_hba.conf</filename> file allows
administrators to specify which hosts can use non-encrypted connections
(<literal>host</literal>) and which require GSSAPI-encrypted connections
(<literal>hostgssenc</literal>). Also, clients can specify that they
connect to servers only on GSSAPI-encrypted connections
(<literal>gssencmode=require</literal>).
</para>
<para>
<application>Stunnel</application> or
<application>SSH</application> can also be used to encrypt
transmissions.
</para>
</listitem>
</varlistentry>
@ -2561,6 +2589,45 @@ openssl x509 -req -in server.csr -text -days 365 \
</sect1>
<sect1 id="gssapi-enc">
<title>Secure TCP/IP Connections with GSSAPI encryption</title>
<indexterm zone="gssapi-enc">
<primary>gssapi</primary>
</indexterm>
<para>
<productname>PostgreSQL</productname> also has native support for
using <acronym>GSSAPI</acronym> to encrypt client/server communications for
increased security. Support requires that a <acronym>GSSAPI</acronym>
implementation (such as MIT krb5) is installed on both client and server
systems, and that support in <productname>PostgreSQL</productname> is
enabled at build time (see <xref linkend="installation"/>).
</para>
<sect2 id="gssapi-setup">
<title>Basic Setup</title>
<para>
The <productname>PostgreSQL</productname> server will listen for both
normal and <acronym>GSSAPI</acronym>-encrypted connections on the same TCP
port, and will negotiate with any connecting client on whether to
use <acronym>GSSAPI</acronym> for encryption (and for authentication). By
default, this decision is up to the client (which means it can be
downgraded by an attacker); see <xref linkend="auth-pg-hba-conf"/> about
setting up the server to require the use of <acronym>GSSAPI</acronym> for
some or all conections.
</para>
<para>
Other than configuration of the negotiation
behavior, <acronym>GSSAPI</acronym> encryption requires no setup beyond
that which is necessary for GSSAPI authentication. (For more information
on configuring that, see <xref linkend="gssapi-auth"/>.)
</para>
</sect2>
</sect1>
<sect1 id="ssh-tunnels">
<title>Secure TCP/IP Connections with <application>SSH</application> Tunnels</title>