Commit e883d0b5 authored by Magnus Hagander's avatar Magnus Hagander

Remove sslverify parameter again, replacing it with two new sslmode values:

"verify-ca" and "verify-full".

Since "prefer" remains the default, this will make certificate validation
off by default, which should lead to less upgrade issues.
parent 420ea688
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.285 2009/04/15 13:03:11 momjian Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.286 2009/04/24 09:43:09 mha Exp $ -->
<chapter id="libpq">
<title><application>libpq</application> - C Library</title>
......@@ -292,7 +292,21 @@
<entry><literal>require</></entry>
<entry>only try an <acronym>SSL</> connection</entry>
</row>
<row>
<entry><literal>verify-ca</></entry>
<entry>only try an <acronym>SSL</> connection, and verify that
the server certificate is issued by a trusted <acronym>CA</>.
</entry>
</row>
<row>
<entry><literal>verify-full</></entry>
<entry>only try an <acronym>SSL</> connection, verify that
the server certificate is issued by a trusted <acronym>CA</> and
that the server hostname matches that in the certificate.</entry>
</row>
</tbody>
</tgroup>
</table>
......@@ -311,43 +325,6 @@
</listitem>
</varlistentry>
<varlistentry id="libpq-connect-sslverify" xreflabel="sslverify">
<term><literal>sslverify</literal></term>
<listitem>
<para>
This option controls how libpq verifies the certificate on the
server when performing an <acronym>SSL</> connection. There are
three options: <literal>none</> disables verification completely
(not recommended); <literal>cert</> enables verification that
the server certificate chains to a known certificate
authority (CA); <literal>cn</> will both verify that the
certificate chains to a known CA and that the <literal>cn</>
attribute of the server certificate matches the server's
hostname (default).
</para>
<para>
It is always recommended to use the <literal>cn</> value for
this parameter, since this is the only option that prevents
man-in-the-middle attacks. Note that this requires the server
name on the certificate to match exactly with the host name
used for the connection, and therefore does not support connections
to aliased names. It can be used with pure IP address connections
only if the certificate also has just the IP address in the
<literal>cn</> field.
</para>
<para>
If the <literal>cn</> attribute in the certificate sent by the
server starts with an asterisk (<literal>*</>), it will be treated
as a wildcard. This wildcard can only be present at the start of
the value, and will match all characters <emphasis>except</> a
dot (<literal>.</>). This means the certificate will not match
subdomains.
</para>
</listitem>
</varlistentry>
<varlistentry id="libpq-connect-requiressl" xreflabel="requiressl">
<term><literal>requiressl</literal></term>
<listitem>
......@@ -5800,16 +5777,6 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary><envar>PGSSLVERIFY</envar></primary>
</indexterm>
<envar>PGSSLVERIFY</envar> behaves the same as <xref
linkend="libpq-connect-sslverify"> connection parameter.
</para>
</listitem>
<listitem>
<para>
<indexterm>
......@@ -6162,25 +6129,60 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
file.
</para>
<sect2 id="libq-ssl-certificates">
<title>Certificate verification</title>
<para>
By default, <productname>PostgreSQL</> will not perform any validation of
the server certificate. This means that it is possible to spoof the server
identity (for example by modifying a DNS record or by taking over the server
IP address) without the client knowing. In order to prevent this,
<acronym>SSL</> certificate validation must be used.
</para>
<para>
If the parameter <literal>sslmode</> is set to <literal>verify-ca</>
libpq will verify that the server is trustworthy by checking the certificate
chain up to a trusted <acronym>CA</>. If <literal>sslmode</> is set to
<literal>verify-full</>, libpq will <emphasis>also</> verify that the server
hostname matches that of the certificate. The SSL connection will fail if
the server certificate cannot be verified. <literal>verify-full</> is
recommended in most security sensitive environments.
</para>
<para>
When the <literal>sslverify</> parameter is set to <literal>cn</> or
<literal>cert</>, libpq requires a trustworthy server certificate by
checking the certificate chain up to a <acronym>CA</>.
To allow verification, place the certificate of a trusted <acronym>CA</>
in the file <filename>~/.postgresql/root.crt</> in the user's home directory.
(On Microsoft Windows the file is named
In <literal>verify-full</> mode, the <literal>cn</> attribute of the
certificate is matched against the hostname. If the <literal>cn</>
attribute starts with an asterisk (<literal>*</>), it will be treated as
a wildcard, and will match all characters <emphasis>except</> a dot
(<literal>.</>). This means the certificate will not match subdomains.
If the connection is made using an IP address instead of a hostname, the
IP address will be matched (without doing any DNS lookups).
</para>
<para>
To allow verification, the certificate of a trusted <acronym>CA</> must be
placed in the file <filename>~/.postgresql/root.crt</> in the user's home
directory. (On Microsoft Windows the file is named
<filename>%APPDATA%\postgresql\root.crt</filename>.)
<application>libpq</application> will then verify that the server's
certificate is signed by one of the trusted certificate authorities.
The SSL connection will fail if the server certificate cannot be verified.
</para>
<para>
Certificate Revocation List (CRL) entries are also checked
if the file <filename>~/.postgresql/root.crl</filename> exists
(<filename>%APPDATA%\postgresql\root.crl</filename> on Microsoft
Windows).
</para>
<para>
The location of the root certificate store and the CRL can be overridden
by the connection parameters <literal>sslrootcert</> and <literal>sslcrl</>
or the environment variables <envar>PGSSLROOTCERT</> and <envar>PGSSLCRL</>.
</para>
</sect2>
<sect2 id="libpq-ssl-clientcert">
<title>Client certificates</title>
<para>
If the server requests a trusted client certificate,
......@@ -6201,6 +6203,9 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
environment variables <envar>PGSSLCERT</> and <envar>PGSSLKEY</>.
</para>
</sect2>
<sect2 id="libpq-ssl-fileusage">
<title>SSL File Usage</title>
<table id="libpq-ssl-file-usage">
<title>Libpq/Client SSL File Usage</title>
<tgroup cols="3">
......@@ -6243,6 +6248,10 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
</tbody>
</tgroup>
</table>
</sect2>
<sect2 id="libpq-ssl-initialize">
<title>SSL library initialization</title>
<para>
If your application initializes <literal>libssl</> and/or
......@@ -6330,6 +6339,7 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
</varlistentry>
</variablelist>
</para>
</sect2>
</sect1>
......
<!-- $PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.425 2009/01/09 13:37:18 petere Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.426 2009/04/24 09:43:09 mha Exp $ -->
<chapter Id="runtime">
<title>Server Setup and Operation</title>
......@@ -1422,8 +1422,8 @@ $ <userinput>kill -INT `head -1 /usr/local/pgsql/data/postmaster.pid`</userinput
<filename>server.key</filename> (key) and
<filename>server.crt</filename> (certificate) files (<xref
linkend="ssl-tcp">). The TCP client must connect using
<literal>sslmode='require'</>, specify <literal>sslverify='cn'</>
or <literal>sslverify='cert'</> and have the required certificate
<literal>sslmode='verify-ca'</> or
<literal>'verify-full'</> and have the required certificate
files present (<xref linkend="libpq-connect">).
</para>
</sect1>
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.372 2009/01/01 17:24:03 momjian Exp $
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.373 2009/04/24 09:43:10 mha Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -91,11 +91,9 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
#define DefaultAuthtype ""
#define DefaultPassword ""
#ifdef USE_SSL
#define DefaultSSLMode "prefer"
#define DefaultSSLVerify "cn"
#define DefaultSSLMode "prefer"
#else
#define DefaultSSLMode "disable"
#define DefaultSSLVerify "none"
#endif
/* ----------
......@@ -185,9 +183,6 @@ static const PQconninfoOption PQconninfoOptions[] = {
{"sslmode", "PGSSLMODE", DefaultSSLMode, NULL,
"SSL-Mode", "", 8}, /* sizeof("disable") == 8 */
{"sslverify", "PGSSLVERIFY", DefaultSSLVerify, NULL,
"SSL-Verify", "", 5}, /* sizeof("chain") == 5 */
{"sslcert", "PGSSLCERT", NULL, NULL,
"SSL-Client-Cert", "", 64},
......@@ -431,8 +426,6 @@ connectOptions1(PGconn *conn, const char *conninfo)
conn->connect_timeout = tmp ? strdup(tmp) : NULL;
tmp = conninfo_getval(connOptions, "sslmode");
conn->sslmode = tmp ? strdup(tmp) : NULL;
tmp = conninfo_getval(connOptions, "sslverify");
conn->sslverify = tmp ? strdup(tmp) : NULL;
tmp = conninfo_getval(connOptions, "sslkey");
conn->sslkey = tmp ? strdup(tmp) : NULL;
tmp = conninfo_getval(connOptions, "sslcert");
......@@ -522,7 +515,9 @@ connectOptions2(PGconn *conn)
if (strcmp(conn->sslmode, "disable") != 0
&& strcmp(conn->sslmode, "allow") != 0
&& strcmp(conn->sslmode, "prefer") != 0
&& strcmp(conn->sslmode, "require") != 0)
&& strcmp(conn->sslmode, "require") != 0
&& strcmp(conn->sslmode, "verify-ca") != 0
&& strcmp(conn->sslmode, "verify-full") != 0)
{
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
......@@ -544,6 +539,7 @@ connectOptions2(PGconn *conn)
break;
case 'r': /* "require" */
case 'v': /* "verify-ca" or "verify-full" */
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("sslmode value \"%s\" invalid when SSL support is not compiled in\n"),
......@@ -555,24 +551,6 @@ connectOptions2(PGconn *conn)
else
conn->sslmode = strdup(DefaultSSLMode);
/*
* Validate sslverify option
*/
if (conn->sslverify)
{
if (strcmp(conn->sslverify, "none") != 0
&& strcmp(conn->sslverify, "cert") != 0
&& strcmp(conn->sslverify, "cn") != 0)
{
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid sslverify value: \"%s\"\n"),
conn->sslverify);
return false;
}
}
/*
* Only if we get this far is it appropriate to try to connect. (We need a
* state flag, rather than just the boolean result of this function, in
......@@ -1428,7 +1406,8 @@ keep_going: /* We will come back to here until there is
}
else if (SSLok == 'N')
{
if (conn->sslmode[0] == 'r') /* "require" */
if (conn->sslmode[0] == 'r' || /* "require" */
conn->sslmode[0] == 'v') /* "verify-ca" or "verify-full" */
{
/* Require SSL, but server does not want it */
appendPQExpBuffer(&conn->errorMessage,
......@@ -1445,7 +1424,8 @@ keep_going: /* We will come back to here until there is
/* Received error - probably protocol mismatch */
if (conn->Pfdebug)
fprintf(conn->Pfdebug, "received error from server, attempting fallback to pre-7.0\n");
if (conn->sslmode[0] == 'r') /* "require" */
if (conn->sslmode[0] == 'r' || /* "require" */
conn->sslmode[0] == 'v') /* "verify-ca" or "verify-full" */
{
/* Require SSL, but server is too old */
appendPQExpBuffer(&conn->errorMessage,
......@@ -2052,8 +2032,6 @@ freePGconn(PGconn *conn)
free(conn->pgpass);
if (conn->sslmode)
free(conn->sslmode);
if (conn->sslverify)
free(conn->sslverify);
if (conn->sslcert)
free(conn->sslcert);
if (conn->sslkey)
......
......@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.123 2009/04/14 17:30:16 momjian Exp $
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.124 2009/04/24 09:43:10 mha Exp $
*
* NOTES
*
......@@ -523,7 +523,7 @@ verify_peer_name_matches_certificate(PGconn *conn)
* If told not to verify the peer name, don't do it. Return
* 0 indicating that the verification was successful.
*/
if(strcmp(conn->sslverify, "cn") != 0)
if (strcmp(conn->sslmode, "verify-full") != 0)
return true;
if (conn->pghostaddr)
......@@ -987,9 +987,9 @@ initialize_SSL(PGconn *conn)
return -1;
/*
* If sslverify is set to anything other than "none", perform certificate
* verification. If set to "cn" we will also do further verifications after
* the connection has been completed.
* If sslmode is set to one of the verify options, perform certificate
* verification. If set to "verify-full" we will also do further
* verification after the connection has been completed.
*
* If we are going to look for either root certificate or CRL in the home directory,
* we need pqGetHomeDirectory() to succeed. In other cases, we don't need to
......@@ -999,7 +999,7 @@ initialize_SSL(PGconn *conn)
{
if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
{
if (strcmp(conn->sslverify, "none") != 0)
if (conn->sslmode[0] == 'v') /* "verify-ca" or "verify-full" */
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get home directory to locate root certificate file"));
......@@ -1064,7 +1064,7 @@ initialize_SSL(PGconn *conn)
else
{
/* stat() failed; assume cert file doesn't exist */
if (strcmp(conn->sslverify, "none") != 0)
if (conn->sslmode[0] == 'v') /* "verify-ca" or "verify-full" */
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("root certificate file \"%s\" does not exist\n"
......
......@@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.140 2009/04/19 22:37:13 tgl Exp $
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.141 2009/04/24 09:43:10 mha Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -294,7 +294,6 @@ struct pg_conn
char *pguser; /* Postgres username and password, if any */
char *pgpass;
char *sslmode; /* SSL mode (require,prefer,allow,disable) */
char *sslverify; /* Verify server SSL certificate (none,chain,cn) */
char *sslkey; /* client key filename */
char *sslcert; /* client certificate filename */
char *sslrootcert; /* root certificate filename */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment