sslmode.patch

text/plain

Filename: sslmode.patch
Type: text/plain
Part: 1
Message: sslmode patch

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: context
File+
doc/FAQ 6 2
doc/src/sgml/client-auth.sgml 18 5
doc/src/sgml/libpq.sgml 57 3
src/backend/libpq/auth.c 3 2
src/backend/libpq/be-secure.c 1 1
src/backend/libpq/hba.c 9 1
src/interfaces/libpq/fe-connect.c 175 6
src/interfaces/libpq/libpq-int.h 3 1
Index: doc/FAQ
===================================================================
RCS file: /projects/cvsroot/pgsql-server/doc/FAQ,v
retrieving revision 1.221
diff -c -r1.221 FAQ
*** doc/FAQ	6 Jun 2003 22:20:40 -0000	1.221
--- doc/FAQ	1 Jul 2003 02:33:19 -0000
***************
*** 1111,1118 ****
      
       * contrib/pgcrypto contains many encryption functions for use in SQL
         queries.
!      * The only way to encrypt transmission from the client to the server
!        is by using hostssl in pg_hba.conf.
       * Database user passwords are automatically encrypted when stored in
         version 7.3. In previous versions, you must enable the option
         PASSWORD_ENCRYPTION in postgresql.conf.
--- 1111,1122 ----
      
       * contrib/pgcrypto contains many encryption functions for use in SQL
         queries.
!      * To encrypt transmission from the client to the server, the server
!        must have the "ssl" option set to true in postgresql.conf, and an
!        applicable host or hostssl record must exist in pg_hba.conf, and the
!        client "sslmode" must not be "prevent". (Note that it is also
!        possible to use a third-party encrypted transport, such as stunnel
!        or ssh, rather than PostgreSQL's native SSL connections.)
       * Database user passwords are automatically encrypted when stored in
         version 7.3. In previous versions, you must enable the option
         PASSWORD_ENCRYPTION in postgresql.conf.
Index: doc/src/sgml/client-auth.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/client-auth.sgml,v
retrieving revision 1.52
diff -c -r1.52 client-auth.sgml
*** doc/src/sgml/client-auth.sgml	25 Jun 2003 01:20:50 -0000	1.52
--- doc/src/sgml/client-auth.sgml	1 Jul 2003 02:33:20 -0000
***************
*** 83,95 ****
    </para>
  
    <para>
!    A record may have one of the five 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>
  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>
  </synopsis>
     The meaning of the fields is as follows:
  
--- 83,97 ----
    </para>
  
    <para>
!    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:
  
***************
*** 137,142 ****
--- 139,155 ----
      </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>
***************
*** 196,203 ****
        </para>
  
        <para>
!        These fields only apply to <literal>host</literal> and
!        <literal>hostssl</literal> records.
        </para>
       </listitem>
      </varlistentry>
--- 209,216 ----
        </para>
  
        <para>
!        These fields only apply to <literal>host</literal>,
!        <literal>hostssl</literal>, and <literal>hostnossl</> records.
        </para>
       </listitem>
      </varlistentry>
***************
*** 224,231 ****
        </para>
  
        <para>
!        This field only applies to <literal>host</literal> and
!        <literal>hostssl</literal> records.
        </para>
       </listitem>
      </varlistentry>  
--- 237,244 ----
        </para>
  
        <para>
!        This field only applies to <literal>host</literal>,
!        <literal>hostssl</literal>, and <literal>hostnossl</> records.
        </para>
       </listitem>
      </varlistentry>  
Index: doc/src/sgml/libpq.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/libpq.sgml,v
retrieving revision 1.127
diff -c -r1.127 libpq.sgml
*** doc/src/sgml/libpq.sgml	27 Jun 2003 19:08:37 -0000	1.127
--- doc/src/sgml/libpq.sgml	1 Jul 2003 02:33:21 -0000
***************
*** 207,219 ****
      </varlistentry>
  
      <varlistentry>
       <term><literal>requiressl</literal></term>
       <listitem>
       <para>
!       If set to 1, an <acronym>SSL</acronym> connection to the server is required.
        <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.
        This option is only available if
        <productname>PostgreSQL</> is compiled with SSL support.
       </para>
--- 207,249 ----
      </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: <term><literal>prevent</></> will attempt only an unencrypted
+       <acronym>SSL</> connection; <term><literal>allow</></> will negotiate,
+       trying first a non-<acronym>SSL</> connection, then if that fails,
+       then trying an <acronym>SSL</> connection; <term><literal>prefer</></>
+ 	  (the default) will negotiate, trying first an <acronym>SSL</> connection,
+ 	  then if that fails, trying a regular non-<acronym>SSL</> connection;
+       <term><literal>require</></> will try only an <acronym>SSL</> connection.
+ 	 </para>
+ 	 <para>
+       Option <term><literal>require</></> is only available if
+       <productname>PostgreSQL</> is compiled with SSL support. If it is not,
+       options <term><literal>allow</></> and <term><literal>prefer</></> will
+       not be able to try to negotiate an <acronym>SSL</> connection.
+      </para>
+      </listitem>
+     </varlistentry>
+ 
+     <varlistentry>
       <term><literal>requiressl</literal></term>
       <listitem>
       <para>
! 	  This option is deprecated in favor of the <term><literal>sslmode</></>
! 	  setting.
! 	 </para>
! 	 <para>
!       If set to 1, an <acronym>SSL</acronym> connection to the server is required
! 	  (this is equivalent to <term><literal>sslmode</></> <term><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 (equivalent to <term><literal>sslmode</></>
! 	  <term><literal>prefer</></>).
        This option is only available if
        <productname>PostgreSQL</> is compiled with SSL support.
       </para>
***************
*** 3141,3153 ****
  <listitem>
  <para>
  <indexterm>
   <primary><envar>PGREQUIRESSL</envar></primary>
  </indexterm>
  <envar>PGREQUIRESSL</envar> sets whether or not the connection must be
  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
  <productname>PostgreSQL</> is compiled with SSL support.
  </para>
--- 3171,3207 ----
  <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: <term><literal>prevent</></> will attempt only an unencrypted
+ <acronym>SSL</> connection; <term><literal>allow</></> will negotiate,
+ trying first a non-<acronym>SSL</> connection, then if that fails,
+ then trying an <acronym>SSL</> connection; <term><literal>prefer</></>
+ (the default) will negotiate, trying first an <acronym>SSL</>
+ connection, then if that fails, trying a regular non-<acronym>SSL</>
+ connection; <term><literal>require</></> will try only an <acronym>SSL</>
+ connection. Option <term><literal>require</></> is only available if
+ <productname>PostgreSQL</> is compiled with SSL support. If it is not,
+ options <term><literal>allow</></> and <term><literal>prefer</></>
+ will not be able to try to negotiate an <acronym>SSL</> connection.
+ </para>
+ </listitem>
+ <listitem>
+ <listitem>
+ <para>
+ <indexterm>
   <primary><envar>PGREQUIRESSL</envar></primary>
  </indexterm>
+ This option is deprecated in favor of the <term><literal>sslmode</></>
+ setting.
  <envar>PGREQUIRESSL</envar> sets whether or not the connection must be
  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 (equivalent to <term><literal>sslmode</></>
! <term><literal>prefer</></>).
  This option is only available if
  <productname>PostgreSQL</> is compiled with SSL support.
  </para>
Index: src/backend/libpq/auth.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/libpq/auth.c,v
retrieving revision 1.103
diff -c -r1.103 auth.c
*** src/backend/libpq/auth.c	25 Jun 2003 01:19:47 -0000	1.103
--- src/backend/libpq/auth.c	1 Jul 2003 02:33:22 -0000
***************
*** 424,431 ****
  					NULL, 0, NI_NUMERICHOST);
  
  				elog(FATAL,
! 					"No pg_hba.conf entry for host %s, user %s, database %s",
! 					hostinfo, port->user_name, port->database_name);
  				break;
  			}
  
--- 424,432 ----
  					NULL, 0, NI_NUMERICHOST);
  
  				elog(FATAL,
! 					"No pg_hba.conf entry for host %s, user %s, database %s, SSL %s",
! 					hostinfo, port->user_name, port->database_name,
! 					port->ssl ? "on" : "off");
  				break;
  			}
  
Index: src/backend/libpq/be-secure.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/libpq/be-secure.c,v
retrieving revision 1.34
diff -c -r1.34 be-secure.c
*** src/backend/libpq/be-secure.c	11 Jun 2003 15:05:50 -0000	1.34
--- src/backend/libpq/be-secure.c	1 Jul 2003 02:33:22 -0000
***************
*** 643,649 ****
  	SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2);
  
  	/* setup the allowed cipher list */
! 	if (SSL_CTX_set_cipher_list(SSL_context, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGH") != 1)
  	{
  		postmaster_error("unable to set the cipher list (no valid ciphers available)");
  		ExitPostmaster(1);
--- 643,649 ----
  	SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2);
  
  	/* setup the allowed cipher list */
! 	if (SSL_CTX_set_cipher_list(SSL_context, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH") != 1)
  	{
  		postmaster_error("unable to set the cipher list (no valid ciphers available)");
  		ExitPostmaster(1);
Index: src/backend/libpq/hba.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/libpq/hba.c,v
retrieving revision 1.104
diff -c -r1.104 hba.c
*** src/backend/libpq/hba.c	15 Jun 2003 16:21:39 -0000	1.104
--- src/backend/libpq/hba.c	1 Jul 2003 02:33:22 -0000
***************
*** 590,596 ****
  		if (port->raddr.addr.ss_family != AF_UNIX)
  			return;
  	}
! 	else if (strcmp(token, "host") == 0 || strcmp(token, "hostssl") == 0)
  	{
  
  		if (strcmp(token, "hostssl") == 0)
--- 590,598 ----
  		if (port->raddr.addr.ss_family != AF_UNIX)
  			return;
  	}
! 	else if (strcmp(token, "host") == 0
! 			|| strcmp(token, "hostssl") == 0
! 			|| strcmp(token, "hostnossl") == 0)
  	{
  
  		if (strcmp(token, "hostssl") == 0)
***************
*** 608,613 ****
--- 610,621 ----
  			/* We don't accept this keyword at all if no SSL support */
  			goto hba_syntax;
  #endif
+ 		}
+ 		else if (strcmp(token, "hostnossl") == 0)
+ 		{
+ 			/* Record does not match if we are on an SSL connection */
+ 			if (port->ssl)
+ 				return;
  		}
  
  		/* Get the database. */
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.252
diff -c -r1.252 fe-connect.c
*** src/interfaces/libpq/fe-connect.c	23 Jun 2003 19:20:24 -0000	1.252
--- src/interfaces/libpq/fe-connect.c	1 Jul 2003 02:33:28 -0000
***************
*** 60,65 ****
--- 60,70 ----
  #define DefaultOption	""
  #define DefaultAuthtype		  ""
  #define DefaultPassword		  ""
+ #ifdef USE_SSL
+ #define DefaultSSLMode	"prefer"
+ #else
+ #define DefaultSSLMode	"prevent"
+ #endif
  
  
  /* ----------
***************
*** 131,140 ****
  	"Backend-Debug-Options", "D", 40},
  
  #ifdef USE_SSL
  	{"requiressl", "PGREQUIRESSL", "0", NULL,
! 	"Require-SSL", "", 1},
  #endif
  
  	/* Terminating entry --- MUST BE LAST */
  	{NULL, NULL, NULL, NULL,
  	NULL, NULL, 0}
--- 136,157 ----
  	"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", "D", 1},
  #endif
  
+ 	/*
+ 	 * "sslmode" option is allowed even without client SSL support
+ 	 * because the client can still handle SSL modes "prevent" and
+ 	 * "allow".
+ 	 */
+ 	{"sslmode", "PGSSLMODE", DefaultSSLMode, NULL,
+ 	"SSL-Mode", "", 8}, /* sizeof("prevent") == 8 */
+ 
  	/* Terminating entry --- MUST BE LAST */
  	{NULL, NULL, NULL, NULL,
  	NULL, NULL, 0}
***************
*** 340,349 ****
  	conn->pgpass = tmp ? strdup(tmp) : NULL;
  	tmp = conninfo_getval(connOptions, "connect_timeout");
  	conn->connect_timeout = tmp ? strdup(tmp) : NULL;
  #ifdef USE_SSL
  	tmp = conninfo_getval(connOptions, "requiressl");
  	if (tmp && tmp[0] == '1')
! 		conn->require_ssl = true;
  #endif
  
  	/*
--- 357,373 ----
  	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')
! 	{
! 		/* here warn that the requiressl option is deprecated? */
! 		if (conn->sslmode)
! 			free(conn->sslmode);
! 		conn->sslmode = "require";
! 	}
  #endif
  
  	/*
***************
*** 412,417 ****
--- 436,482 ----
  	}
  #endif
  
+ 	/*
+ 	 * validate sslmode option
+ 	 */
+ 	if (conn->sslmode)
+ 	{
+ 		if (strcmp(conn->sslmode, "prevent") != 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;
+ 		}
+ 
+ #ifdef USE_SSL
+ 		if (strcmp(conn->sslmode, "allow") == 0
+ 			|| strcmp(conn->sslmode, "prefer") == 0)
+ 		{
+ 			/*
+ 			 * warn user that an SSL connection will never be
+ 			 * negotiated since SSL was not compiled in?
+ 			 */
+ 		}
+ #else
+ 		if (strcmp(conn->sslmode, "require") == 0)
+ 		{
+ 			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;
  }
  
***************
*** 865,870 ****
--- 930,941 ----
  		goto connect_errReturn;
  	}
  
+ 	/* setup values based on SSL mode */
+ 	if (strcmp(conn->sslmode, "prevent") == 0)
+ 		conn->allow_ssl_try = false;
+ 	else if (strcmp(conn->sslmode, "allow") == 0)
+ 		conn->wait_ssl_try = true;
+ 
  	/*
  	 * Set up to try to connect, with protocol 3.0 as the first attempt.
  	 */
***************
*** 1269,1278 ****
  				{
  					/* Don't bother requesting SSL over a Unix socket */
  					conn->allow_ssl_try = false;
- 					conn->require_ssl = false;
  				}
  #endif
! 				if (conn->allow_ssl_try && conn->ssl == NULL)
  				{
  					ProtocolVersion pv;
  
--- 1340,1348 ----
  				{
  					/* Don't bother requesting SSL over a Unix socket */
  					conn->allow_ssl_try = false;
  				}
  #endif
! 				if (conn->allow_ssl_try && ! conn->wait_ssl_try && conn->ssl == NULL)
  				{
  					ProtocolVersion pv;
  
***************
*** 1376,1388 ****
  					}
  					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;
  						}
  						/* Otherwise, proceed with normal startup */
  						conn->allow_ssl_try = false;
  						conn->status = CONNECTION_MADE;
--- 1446,1470 ----
  					}
  					else if (SSLok == 'N')
  					{
! 						if (strcmp(conn->sslmode, "require") == 0)
  						{
  							/* 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;
  						}
+ 						else if (conn->wait_ssl_try)
+ 						{
+ 							/*
+ 							 * normal startup already failed, so SSL failure
+ 							 * means the end
+ 							 */
+ 							printfPQExpBuffer(&conn->errorMessage,
+ 											  libpq_gettext("server does not support normal or SSL connections\n"));
+ 							goto error_return;
+ 						}
+ 
+ 
  						/* Otherwise, proceed with normal startup */
  						conn->allow_ssl_try = false;
  						conn->status = CONNECTION_MADE;
***************
*** 1393,1405 ****
  						/* 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;
  						}
  						/* Otherwise, try again without SSL */
  						conn->allow_ssl_try = false;
  						/* Assume it ain't gonna handle protocol 3, either */
--- 1475,1497 ----
  						/* Received error - probably protocol mismatch */
  						if (conn->Pfdebug)
  							fprintf(conn->Pfdebug, "Postmaster reports error, attempting fallback to pre-7.0.\n");
! 						if (strcmp(conn->sslmode, "require") == 0)
  						{
  							/* 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;
  						}
+ 						else if (conn->wait_ssl_try)
+ 						{
+ 							/*
+ 							 * normal startup already failed, so SSL failure
+ 							 * means the end
+ 							 */
+ 							printfPQExpBuffer(&conn->errorMessage,
+ 											  libpq_gettext("server does not support normal or SSL connections\n"));
+ 							goto error_return;
+ 						}
  						/* Otherwise, try again without SSL */
  						conn->allow_ssl_try = false;
  						/* Assume it ain't gonna handle protocol 3, either */
***************
*** 1586,1591 ****
--- 1678,1722 ----
  					}
  					/* 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 not "require" 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
+ 						&& strcmp(conn->sslmode, "require") != 0
+ 						&& strcmp(conn->sslmode, "allow") != 0)
+ 					{
+ 						conn->allow_ssl_try = false;
+ 						/* Must drop the old connection */
+ 						closesocket(conn->sock);
+ 						conn->sock = -1;
+ 						free(conn->ssl);
+ 						conn->status = CONNECTION_NEEDED;
+ 						goto keep_going;
+ 					}
+ #endif
+ 
  					goto error_return;
  				}
  
***************
*** 1637,1642 ****
--- 1768,1811 ----
  				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 not "require" 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
+ 						&& strcmp(conn->sslmode, "require") != 0
+ 						&& strcmp(conn->sslmode, "allow") != 0)
+ 					{
+ 						conn->allow_ssl_try = false;
+ 						/* Must drop the old connection */
+ 						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;
  				}
Index: src/interfaces/libpq/libpq-int.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/libpq-int.h,v
retrieving revision 1.76
diff -c -r1.76 libpq-int.h
*** src/interfaces/libpq/libpq-int.h	23 Jun 2003 19:20:25 -0000	1.76
--- src/interfaces/libpq/libpq-int.h	1 Jul 2003 02:33:28 -0000
***************
*** 316,324 ****
  	PGresult   *result;			/* result being constructed */
  	PGresAttValue *curTuple;	/* tuple currently being read */
  
  #ifdef USE_SSL
  	bool		allow_ssl_try;	/* Allowed to try SSL negotiation */
! 	bool		require_ssl;	/* Require SSL to make connection */
  	SSL		   *ssl;			/* SSL status, if have SSL connection */
  	X509	   *peer;			/* X509 cert of server */
  	char		peer_dn[256 + 1];		/* peer distinguished name */
--- 316,326 ----
  	PGresult   *result;			/* result being constructed */
  	PGresAttValue *curTuple;	/* tuple currently being read */
  
+ 	char	   *sslmode;		/* SSL mode option string */
  #ifdef USE_SSL
  	bool		allow_ssl_try;	/* Allowed to try SSL negotiation */
! 	bool		wait_ssl_try;	/* Delay SSL negotiation until after
! 								   attempting normal connection */
  	SSL		   *ssl;			/* SSL status, if have SSL connection */
  	X509	   *peer;			/* X509 cert of server */
  	char		peer_dn[256 + 1];		/* peer distinguished name */