<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.52 2003/06/25 01:20:50 momjian Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.53 2003/07/26 13:50:01 momjian Exp $
-->
<chapter id="client-authentication">
</para>
<para>
- A record may have one of the five formats
+ A record may have one of the seven formats
<synopsis>
local <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>authentication-method</replaceable> <optional><replaceable>authentication-option</replaceable></optional>
host <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>authentication-method</replaceable> <optional><replaceable>authentication-option</replaceable></optional>
hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>authentication-method</replaceable> <optional><replaceable>authentication-option</replaceable></optional>
+hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>authentication-method</replaceable> <optional><replaceable>authentication-option</replaceable></optional>
host <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable>/<replaceable>CIDR-mask</replaceable> <replaceable>authentication-method</replaceable> <optional><replaceable>authentication-option</replaceable></optional>
hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable>/<replaceable>CIDR-mask</replaceable> <replaceable>authentication-method</replaceable> <optional><replaceable>authentication-option</replaceable></optional>
+hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable>/<replaceable>CIDR-mask</replaceable> <replaceable>authentication-method</replaceable> <optional><replaceable>authentication-option</replaceable></optional>
</synopsis>
The meaning of the fields is as follows:
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal>hostnossl</literal></term>
+ <listitem>
+ <para>
+ This record is similar to <literal>hostssl</> but with the
+ opposite logic: it matches only regular connection attempts not
+ using SSL.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><replaceable>database</replaceable></term>
<listitem>
</para>
<para>
- These fields only apply to <literal>host</literal> and
- <literal>hostssl</literal> records.
+ These fields only apply to <literal>host</literal>,
+ <literal>hostssl</literal>, and <literal>hostnossl</> records.
</para>
</listitem>
</varlistentry>
</para>
<para>
- This field only applies to <literal>host</literal> and
- <literal>hostssl</literal> records.
+ This field only applies to <literal>host</literal>,
+ <literal>hostssl</literal>, and <literal>hostnossl</> records.
</para>
</listitem>
</varlistentry>
<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.128 2003/07/23 17:27:28 momjian Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.129 2003/07/26 13:50:01 momjian Exp $
-->
<chapter id="libpq">
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal>sslmode</literal></term>
+ <listitem>
+ <para>
+ This option determines whether or with what priority an <acronym>SSL</>
+ connection will be negotiated with the server. There are four
+ modes: <literal>disable</> will attempt only an unencrypted
+ <acronym>SSL</> connection; <literal>allow</> will negotiate,
+ trying first a non-<acronym>SSL</> connection, then if that fails,
+ trying an <acronym>SSL</> connection; <literal>prefer</>
+ (the default) will negotiate, trying first an <acronym>SSL</> connection,
+ then if that fails, trying a regular non-<acronym>SSL</> connection;
+ <literal>require</> will try only an <acronym>SSL</> connection.
+ </para>
+ <para>
+ If <productname>PostgreSQL</> is compiled without SSL support,
+ using option <literal>require</> will cause an error, and options
+ <literal>allow</> and <literal>prefer</> will be tolerated but
+ <application>libpq</> will be unable to negotiate an <acronym>SSL</>
+ connection.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><literal>requiressl</literal></term>
<listitem>
<para>
- If set to 1, an <acronym>SSL</acronym> connection to the server is required.
+ This option is deprecated in favor of the <literal>sslmode</>
+ setting.
+ </para>
+ <para>
+ If set to 1, an <acronym>SSL</acronym> connection to the server is required
+ (this is equivalent to <literal>sslmode</> <literal>require</>).
<application>libpq</> will then refuse to connect if the server does not
accept an <acronym>SSL</acronym> connection.
- If set to 0 (default), <application>libpq</> will negotiate the connection type with server.
+ If set to 0 (default), <application>libpq</> will negotiate the connection
+ type with the server (equivalent to <literal>sslmode</> <literal>prefer</>).
This option is only available if
<productname>PostgreSQL</> is compiled with SSL support.
</para>
</listitem>
<listitem>
<para>
+<indexterm>
+ <primary><envar>PGSSLMODE</envar></primary>
+</indexterm>
+<envar>PGSSLMODE</envar> determines whether and with what priority an
+<acronym>SSL</> connection will be negotiated with the server. There are
+four modes: <literal>disable</> will attempt only an unencrypted
+<acronym>SSL</> connection; <literal>allow</> will negotiate,
+trying first a non-<acronym>SSL</> connection, then if that fails,
+trying an <acronym>SSL</> connection; <literal>prefer</>
+(the default) will negotiate, trying first an <acronym>SSL</>
+connection, then if that fails, trying a regular non-<acronym>SSL</>
+connection; <literal>require</> will try only an <acronym>SSL</>
+connection. If <productname>PostgreSQL</> is compiled without SSL support,
+using option <literal>require</> will cause an error, and options
+<literal>allow</> and <literal>prefer</> will be tolerated but
+<application>libpq</> will be unable to negotiate an <acronym>SSL</>
+connection.
+</para>
+</listitem>
+<listitem>
+<para>
<indexterm>
<primary><envar>PGREQUIRESSL</envar></primary>
</indexterm>
made over <acronym>SSL</acronym>. If set to
<quote>1</quote>, <application>libpq</>
will refuse to connect if the server does not accept
-an <acronym>SSL</acronym> connection.
-This option is only available if
+an <acronym>SSL</acronym> connection (equivalent to <literal>sslmode</>
+<literal>prefer</>).
+This option is deprecated in favor of the <literal>sslmode</>
+setting, and is only available if
<productname>PostgreSQL</> is compiled with SSL support.
</para>
</listitem>
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.253 2003/07/23 23:30:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.254 2003/07/26 13:50:02 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#define DefaultOption ""
#define DefaultAuthtype ""
#define DefaultPassword ""
+#ifdef USE_SSL
+#define DefaultSSLMode "prefer"
+#else
+#define DefaultSSLMode "disable"
+#endif
/* ----------
"Backend-Debug-Options", "D", 40},
#ifdef USE_SSL
+ /*
+ * "requiressl" is deprecated, its purpose having been taken over
+ * by "sslmode". It remains for backwards compatibility.
+ */
{"requiressl", "PGREQUIRESSL", "0", NULL,
- "Require-SSL", "", 1},
+ "Require-SSL", "D", 1},
#endif
+ /*
+ * "sslmode" option is allowed even without client SSL support
+ * because the client can still handle SSL modes "disable" and
+ * "allow".
+ */
+ {"sslmode", "PGSSLMODE", DefaultSSLMode, NULL,
+ "SSL-Mode", "", 8}, /* sizeof("disable") == 8 */
+
/* Terminating entry --- MUST BE LAST */
{NULL, NULL, NULL, NULL,
NULL, NULL, 0}
conn->pgpass = tmp ? strdup(tmp) : NULL;
tmp = conninfo_getval(connOptions, "connect_timeout");
conn->connect_timeout = tmp ? strdup(tmp) : NULL;
+ tmp = conninfo_getval(connOptions, "sslmode");
+ conn->sslmode = tmp ? strdup(tmp) : NULL;
#ifdef USE_SSL
tmp = conninfo_getval(connOptions, "requiressl");
if (tmp && tmp[0] == '1')
- conn->require_ssl = true;
+ {
+ /* here warn that the requiressl option is deprecated? */
+ if (conn->sslmode)
+ free(conn->sslmode);
+ conn->sslmode = "require";
+ }
#endif
/*
}
#endif
+ /*
+ * validate sslmode option
+ */
+ if (conn->sslmode)
+ {
+ if (strcmp(conn->sslmode, "disable") != 0
+ && strcmp(conn->sslmode, "allow") != 0
+ && strcmp(conn->sslmode, "prefer") != 0
+ && strcmp(conn->sslmode, "require") != 0)
+ {
+ conn->status = CONNECTION_BAD;
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("unknown sslmode \"%s\" requested\n"),
+ conn->sslmode);
+ return false;
+ }
+
+#ifndef USE_SSL
+ switch (conn->sslmode[0]) {
+ case 'a': /* "allow" */
+ case 'p': /* "prefer" */
+ /*
+ * warn user that an SSL connection will never be
+ * negotiated since SSL was not compiled in?
+ */
+ break;
+
+ case 'r': /* "require" */
+ conn->status = CONNECTION_BAD;
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("sslmode \"%s\" invalid when SSL "
+ "support is not compiled in\n"),
+ conn->sslmode);
+ return false;
+ }
+#endif
+ }
+ else
+ conn->sslmode = DefaultSSLMode;
+
return true;
}
goto connect_errReturn;
}
+#ifdef USE_SSL
+ /* setup values based on SSL mode */
+ if (conn->sslmode[0] == 'd') /* "disable" */
+ conn->allow_ssl_try = false;
+ else if (conn->sslmode[0] == 'a') /* "allow" */
+ conn->wait_ssl_try = true;
+#endif
+
/*
* Set up to try to connect, with protocol 3.0 as the first attempt.
*/
{
/* Don't bother requesting SSL over a Unix socket */
conn->allow_ssl_try = false;
- conn->require_ssl = false;
}
- if (conn->allow_ssl_try && conn->ssl == NULL)
+ if (conn->allow_ssl_try && !conn->wait_ssl_try && conn->ssl == NULL)
{
ProtocolVersion pv;
}
else if (SSLok == 'N')
{
- if (conn->require_ssl)
- {
- /* Require SSL, but server does not want it */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("server does not support SSL, but SSL was required\n"));
- goto error_return;
+ switch (conn->sslmode[0]) {
+ case 'r': /* "require" */
+ /* Require SSL, but server does not want it */
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("server does not support SSL, but SSL was required\n"));
+ goto error_return;
+ case 'a': /* "allow" */
+ /*
+ * normal startup already failed,
+ * so SSL failure means the end
+ */
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("server does not support SSL, and previous non-SSL attempt failed\n"));
+ goto error_return;
}
+
/* Otherwise, proceed with normal startup */
conn->allow_ssl_try = false;
conn->status = CONNECTION_MADE;
/* Received error - probably protocol mismatch */
if (conn->Pfdebug)
fprintf(conn->Pfdebug, "Postmaster reports error, attempting fallback to pre-7.0.\n");
- if (conn->require_ssl)
- {
- /* Require SSL, but server is too old */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("server does not support SSL, but SSL was required\n"));
- goto error_return;
+ switch (conn->sslmode[0]) {
+ case 'r': /* "require" */
+ /* Require SSL, but server is too old */
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("server does not support SSL, but SSL was required\n"));
+ goto error_return;
+ case 'a': /* "allow" */
+ /*
+ * normal startup already failed,
+ * so SSL failure means the end
+ */
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("server does not support SSL, and previous non-SSL attempt failed\n"));
+ goto error_return;
}
+
/* Otherwise, try again without SSL */
conn->allow_ssl_try = false;
/* Assume it ain't gonna handle protocol 3, either */
}
/* OK, we read the message; mark data consumed */
conn->inStart = conn->inCursor;
+
+#ifdef USE_SSL
+ /*
+ * if sslmode is "allow" and we haven't tried an
+ * SSL connection already, then retry with an SSL connection
+ */
+ if (conn->wait_ssl_try
+ && conn->ssl == NULL
+ && conn->allow_ssl_try)
+ {
+ conn->wait_ssl_try = false;
+ /* Must drop the old connection */
+ closesocket(conn->sock);
+ conn->sock = -1;
+ conn->status = CONNECTION_NEEDED;
+ goto keep_going;
+ }
+
+ /*
+ * if sslmode is "prefer" and we're in an SSL
+ * connection and we haven't already tried a non-SSL
+ * for "allow", then do a non-SSL retry
+ */
+ if (!conn->wait_ssl_try
+ && conn->ssl
+ && conn->allow_ssl_try
+ && conn->sslmode[0] == 'p') /* "prefer" */
+ {
+ conn->allow_ssl_try = false;
+ /* Must drop the old connection */
+ pqsecure_close(conn);
+ closesocket(conn->sock);
+ conn->sock = -1;
+ free(conn->ssl);
+ conn->status = CONNECTION_NEEDED;
+ goto keep_going;
+ }
+#endif
+
goto error_return;
}
if (fe_sendauth(areq, conn, conn->pghost, conn->pgpass,
conn->errorMessage.data) != STATUS_OK)
{
+#ifdef USE_SSL
+ /*
+ * if sslmode is "allow" and we haven't tried an
+ * SSL connection already, then retry with an SSL connection
+ */
+ if (conn->wait_ssl_try
+ && conn->ssl == NULL
+ && conn->allow_ssl_try)
+ {
+ conn->wait_ssl_try = false;
+ /* Must drop the old connection */
+ closesocket(conn->sock);
+ conn->sock = -1;
+ conn->status = CONNECTION_NEEDED;
+ goto keep_going;
+ }
+
+ /*
+ * if sslmode is "prefer" and we're in an SSL
+ * connection and we haven't already tried a non-SSL
+ * for "allow", then do a non-SSL retry
+ */
+ if (!conn->wait_ssl_try
+ && conn->ssl
+ && conn->allow_ssl_try
+ && conn->sslmode[0] == 'p') /* "prefer" */
+ {
+ conn->allow_ssl_try = false;
+ /* Must drop the old connection */
+ pqsecure_close(conn);
+ closesocket(conn->sock);
+ conn->sock = -1;
+ free(conn->ssl);
+ conn->status = CONNECTION_NEEDED;
+ goto keep_going;
+ }
+#endif
+
conn->errorMessage.len = strlen(conn->errorMessage.data);
goto error_return;
}