summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus Hagander2009-04-24 09:43:10 +0000
committerMagnus Hagander2009-04-24 09:43:10 +0000
commite6efc1210de4666d609c7b3c3543613c502649a1 (patch)
tree49cf76289931551b9282bf711fd6654fe8021e3b
parent7e9bf5ac6759e42403a4b812b9f061fcbed4fb60 (diff)
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.
-rw-r--r--doc/src/sgml/libpq.sgml124
-rw-r--r--doc/src/sgml/runtime.sgml4
-rw-r--r--src/interfaces/libpq/fe-connect.c40
-rw-r--r--src/interfaces/libpq/fe-secure.c12
-rw-r--r--src/interfaces/libpq/libpq-int.h1
5 files changed, 84 insertions, 97 deletions
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index c98dbb3297..6f9bc5df55 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -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>
@@ -5803,16 +5780,6 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
<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>
<primary><envar>PGREQUIRESSL</envar></primary>
</indexterm>
<envar>PGREQUIRESSL</envar> behaves the same as <xref
@@ -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>
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 065455a389..366b7b05f1 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -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>
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 0833603dae..fec387f59a 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -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"),
@@ -556,24 +552,6 @@ connectOptions2(PGconn *conn)
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
* case someone tries to PQreset() the PGconn.)
@@ -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)
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index eb579cfaa7..222bc5c948 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -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"
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 08201c5b00..2340347f48 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -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 */