Hi.

This is a revised patch for the sslmode functionality. It fixes bugs in 
both documentation and code, and adds a few more tests. Please discard my 
previous patch.

Thanks,
Jon

Attachment: sslmode.tar.gz
Description: Binary data

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     11 Jul 2003 16:08:30 -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 "disable". (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       11 Jul 2003 16:08:31 -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     11 Jul 2003 16:08:33 -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: <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>
!         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 the server (equivalent to <literal>sslmode</> <literal>prefer</>).
        This option is only available if
        <productname>PostgreSQL</> is compiled with SSL support.
       </para>
***************
*** 3141,3154 ****
  <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>
  </listitem>
--- 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: <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>
  <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 <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>
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    11 Jul 2003 16:08:33 -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,437 ----
                                        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,
! #ifdef USE_SSL
!                                       port->ssl ? "on" : "off"
! #else
!                                       "off"
! #endif
!                                       );
                                break;
                        }
  
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     11 Jul 2003 16:08:33 -0000
***************
*** 590,599 ****
                if (port->raddr.addr.ss_family != AF_UNIX)
                        return;
        }
!       else if (strcmp(token, "host") == 0 || strcmp(token, "hostssl") == 0)
        {
  
!               if (strcmp(token, "hostssl") == 0)
                {
  #ifdef USE_SSL
                        /* Record does not match if we are not on an SSL connection */
--- 590,601 ----
                if (port->raddr.addr.ss_family != AF_UNIX)
                        return;
        }
!       else if (strcmp(token, "host") == 0
!                       || strcmp(token, "hostssl") == 0
!                       || strcmp(token, "hostnossl") == 0)
        {
  
!               if (token[4] == 's')  /* "hostssl" */
                {
  #ifdef USE_SSL
                        /* Record does not match if we are not on an SSL connection */
***************
*** 609,614 ****
--- 611,624 ----
                        goto hba_syntax;
  #endif
                }
+ #ifdef USE_SSL
+               else if (token[4] == 'n')  /* "hostnossl" */
+               {
+                       /* Record does not match if we are on an SSL connection */
+                       if (port->ssl)
+                               return;
+               }
+ #endif
  
                /* Get the database. */
                line = lnext(line);
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   11 Jul 2003 16:08:39 -0000
***************
*** 60,65 ****
--- 60,70 ----
  #define DefaultOption ""
  #define DefaultAuthtype                 ""
  #define DefaultPassword                 ""
+ #ifdef USE_SSL
+ #define DefaultSSLMode        "prefer"
+ #else
+ #define DefaultSSLMode        "disable"
+ #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 "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}
***************
*** 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,481 ----
        }
  #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;
  }
  
***************
*** 865,870 ****
--- 929,942 ----
                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.
         */
***************
*** 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;
  
--- 1341,1349 ----
                                {
                                        /* 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;
--- 1447,1468 ----
                                        }
                                        else if (SSLok == 'N')
                                        {
!                                               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;
***************
*** 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 */
--- 1473,1494 ----
                                                /* Received error - probably protocol 
mismatch */
                                                if (conn->Pfdebug)
                                                        fprintf(conn->Pfdebug, 
"Postmaster reports error, attempting fallback to pre-7.0.\n");
!                                               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 */
***************
*** 1586,1591 ****
--- 1675,1719 ----
                                        }
                                        /* 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;
                                }
  
***************
*** 1637,1642 ****
--- 1765,1808 ----
                                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;
                                }
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    11 Jul 2003 16:08:39 -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 */
---------------------------(end of broadcast)---------------------------
TIP 4: Don't 'kill -9' the postmaster

Reply via email to