diff options
author | Magnus Hagander | 2009-04-24 09:43:10 +0000 |
---|---|---|
committer | Magnus Hagander | 2009-04-24 09:43:10 +0000 |
commit | e6efc1210de4666d609c7b3c3543613c502649a1 (patch) | |
tree | 49cf76289931551b9282bf711fd6654fe8021e3b | |
parent | 7e9bf5ac6759e42403a4b812b9f061fcbed4fb60 (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.sgml | 124 | ||||
-rw-r--r-- | doc/src/sgml/runtime.sgml | 4 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-connect.c | 40 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-secure.c | 12 | ||||
-rw-r--r-- | src/interfaces/libpq/libpq-int.h | 1 |
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 */ |