]> granicus.if.org Git - postgresql/commitdiff
SSL patch from Magnus
authorBruce Momjian <bruce@momjian.us>
Wed, 30 Aug 2000 14:54:24 +0000 (14:54 +0000)
committerBruce Momjian <bruce@momjian.us>
Wed, 30 Aug 2000 14:54:24 +0000 (14:54 +0000)
src/backend/postmaster/postmaster.c
src/bin/psql/startup.c
src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/libpq-fe.h
src/interfaces/libpq/libpq-int.h

index 986e0e038cba25be2a3de46291fbee0387446398..223b5bbe24c498feacb91ce53f012509feca2119 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.163 2000/08/29 16:40:19 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.164 2000/08/30 14:54:22 momjian Exp $
  *
  * NOTES
  *
@@ -195,10 +195,7 @@ static int SendStop = false;
 bool NetServer = false;        /* listen on TCP/IP */
 
 #ifdef USE_SSL
-static bool SecureNetServer = false;   /* if not zero, postmaster listens
-                                                                                * for only SSL non-local
-                                                                                * connections */
-
+static bool DisableSSL = false; /* Completely disable SSL, even if compiled in */
 #endif
 
 static pid_t StartupPID = 0,
@@ -455,7 +452,7 @@ PostmasterMain(int argc, char *argv[])
                                break;
 #ifdef USE_SSL
                        case 'l':
-                               SecureNetServer = true;
+                               DisableSSL = true;
                                break;
 #endif
                        case 'm':
@@ -566,13 +563,14 @@ PostmasterMain(int argc, char *argv[])
        }
 
 #ifdef USE_SSL
-       if (!NetServer && SecureNetServer)
+       if (!NetServer && !DisableSSL)
        {
-               fprintf(stderr, "%s: For SSL, you must enable TCP/IP connections.\n",
+               fprintf(stderr, "%s: For SSL, you must enable TCP/IP connections. Use -l to disable SSL\n",
                                progname);
                exit(1);
        }
-       InitSSL();
+       if (!DisableSSL)
+               InitSSL();
 #endif
 
        if (NetServer)
@@ -754,7 +752,7 @@ usage(const char *progname)
        printf("  -F              turn fsync off\n");
        printf("  -i              listen on TCP/IP sockets\n");
 #ifdef USE_SSL
-       printf("  -l              listen only on SSL connections (EXPERIMENTAL)\n");
+       printf("  -l              disable SSL\n");
 #endif
        printf("  -N <number>     maximum number of allowed connections (1..%d, default %d)\n",
                        MAXBACKENDS, DEF_MAXBACKENDS);
@@ -1062,7 +1060,11 @@ readStartupPacket(void *arg, PacketLen len, void *pkt)
                char            SSLok;
 
 #ifdef USE_SSL
-               SSLok = 'S';                    /* Support for SSL */
+                if (DisableSSL || port->laddr.sa.sa_family != AF_INET)
+                       /* No SSL when disabled or on Unix sockets */
+                       SSLok = 'N';
+               else
+                       SSLok = 'S';            /* Support for SSL */
 #else
                SSLok = 'N';                    /* No support for SSL */
 #endif
@@ -1073,13 +1075,15 @@ readStartupPacket(void *arg, PacketLen len, void *pkt)
                }
 
 #ifdef USE_SSL
-               if (!(port->ssl = SSL_new(SSL_context)) ||
-                       !SSL_set_fd(port->ssl, port->sock) ||
-                       SSL_accept(port->ssl) <= 0)
-               {
-                       fprintf(stderr, "Failed to initialize SSL connection: %s, errno: %d (%s)\n",
-                                       ERR_reason_error_string(ERR_get_error()), errno, strerror(errno));
-                       return STATUS_ERROR;
+               if (SSLok == 'S') {
+                 if (!(port->ssl = SSL_new(SSL_context)) ||
+                     !SSL_set_fd(port->ssl, port->sock) ||
+                     SSL_accept(port->ssl) <= 0)
+                   {
+                     fprintf(stderr, "Failed to initialize SSL connection: %s, errno: %d (%s)\n",
+                             ERR_reason_error_string(ERR_get_error()), errno, strerror(errno));
+                     return STATUS_ERROR;
+                   }
                }
 #endif
                /* ready for the normal startup packet */
@@ -1091,18 +1095,6 @@ readStartupPacket(void *arg, PacketLen len, void *pkt)
 
        /* Could add additional special packet types here */
 
-#ifdef USE_SSL
-
-       /*
-        * Any SSL negotiation must have taken place here, so drop the
-        * connection ASAP if we require SSL
-        */
-       if (SecureNetServer && !port->ssl)
-       {
-               PacketSendError(&port->pktInfo, "Backend requires secure connection.");
-               return STATUS_OK;
-       }
-#endif
 
        /* Check we can handle the protocol the frontend is using. */
 
index 88ef5865afd204f82594a385bf108ed2499ecddb..0f36e30ef8c455648a99e5aef154251551658f34 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.34 2000/07/02 15:21:17 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.35 2000/08/30 14:54:23 momjian Exp $
  */
 #include "postgres.h"
 
@@ -81,6 +81,10 @@ static void
 static void
                        showVersion(void);
 
+#ifdef USE_SSL
+static void
+            printSSLInfo(void);
+#endif
 
 
 /*
@@ -263,7 +267,9 @@ main(int argc, char *argv[])
                          "       \\g or terminate with semicolon to execute query\n"
                                   "       \\q to quit\n\n", pset.progname);
                }
-
+#ifdef USE_SSL
+               printSSLInfo();
+#endif
                SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
                SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
                SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
@@ -639,3 +645,27 @@ showVersion(void)
        puts("Read the file COPYRIGHT or use the command \\copyright to see the");
        puts("usage and distribution terms.");
 }
+
+
+
+/*
+ * printSSLInfo
+ *
+ * Prints information about the current SSL connection, if SSL is in use
+ */
+#ifdef USE_SSL
+static void 
+printSSLInfo(void)
+{
+       int sslbits = -1;
+       SSL *ssl;
+
+       ssl = PQgetssl(pset.db);
+       if (!ssl)
+               return; /* no SSL */
+
+       SSL_get_cipher_bits(ssl, &sslbits);
+       printf("SSL enabled connection. Chiper: %s, bits: %i\n\n",
+                  SSL_get_cipher(ssl),sslbits);
+}
+#endif
index 1db218e12be9f83c05d22af8c89e143c281cd323..7349be6645950c1274432f614c9eca636eb7eb40 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.132 2000/08/20 10:55:35 petere Exp $
+ *       $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.133 2000/08/30 14:54:23 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -63,7 +63,6 @@ inet_aton(const char *cp, struct in_addr * inp)
 
 #ifdef USE_SSL
 static SSL_CTX *SSL_context = NULL;
-
 #endif
 
 #define NOTIFYLIST_INITIAL_SIZE 10
@@ -131,6 +130,11 @@ static const PQconninfoOption PQconninfoOptions[] = {
        {"options", "PGOPTIONS", DefaultOption, NULL,
        "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}
@@ -303,6 +307,10 @@ PQconnectStart(const char *conninfo)
        conn->pguser = tmp ? strdup(tmp) : NULL;
        tmp = conninfo_getval(connOptions, "password");
        conn->pgpass = tmp ? strdup(tmp) : NULL;
+#ifdef USE_SSL
+       tmp = conninfo_getval(connOptions, "requiressl");
+       conn->require_ssl = tmp ? (tmp[0]=='1'?true:false) : false;
+#endif
 
        /* ----------
         * Free the option info - all is in conn now
@@ -475,6 +483,14 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
        else
                conn->dbName = strdup(dbName);
 
+
+#ifdef USE_SSL
+       if ((tmp = getenv("PGREQUIRESSL")) != NULL)
+               conn->require_ssl = (tmp[0]=='1')?true:false;
+       else
+               conn->require_ssl = 0;
+#endif
+
        if (error)
                conn->status = CONNECTION_BAD;
        else
@@ -781,13 +797,55 @@ connectDBStart(PGconn *conn)
                goto connect_errReturn;
 #endif
 
-#ifdef USE_SSL
-
-       /*
-        * This needs to be done before we set into nonblocking, since SSL
-        * negotiation does not like that mode
+       /* ----------
+        * Start / make connection.  We are hopefully in non-blocking mode
+        * now, but it is possible that:
+        *       1. Older systems will still block on connect, despite the
+        *              non-blocking flag. (Anyone know if this is true?)
+        *       2. We are running under Windows, and aren't even trying
+        *              to be non-blocking (see above).
+        *       3. We are using SSL.
+        * Thus, we have make arrangements for all eventualities.
+        * ----------
         */
+       if (connect(conn->sock, &conn->raddr.sa, conn->raddr_len) < 0)
+       {
+#ifndef WIN32
+               if (errno == EINPROGRESS || errno == 0)
+#else
+               if (WSAGetLastError() == WSAEINPROGRESS)
+#endif
+               {
 
+                       /*
+                        * This is fine - we're in non-blocking mode, and the
+                        * connection is in progress.
+                        */
+                       conn->status = CONNECTION_STARTED;
+               }
+               else
+               {
+                       /* Something's gone wrong */
+                       printfPQExpBuffer(&conn->errorMessage,
+                                                         "connectDBStart() -- connect() failed: %s\n"
+                                                         "\tIs the postmaster running%s at '%s'\n"
+                                                         "\tand accepting connections on %s '%s'?\n",
+                                                         strerror(errno),
+                                                         (family == AF_INET) ? " (with -i)" : "",
+                                                         conn->pghost ? conn->pghost : "localhost",
+                                                         (family == AF_INET) ?
+                                                         "TCP/IP port" : "Unix socket",
+                                                         conn->pgport);
+                       goto connect_errReturn;
+               }
+       }
+       else
+       {
+               /* We're connected already */
+               conn->status = CONNECTION_MADE;
+       }
+
+#ifdef USE_SSL
        /* Attempt to negotiate SSL usage */
        if (conn->allow_ssl_try)
        {
@@ -837,7 +895,7 @@ connectDBStart(PGconn *conn)
                {
                        /* Received error - probably protocol mismatch */
                        if (conn->Pfdebug)
-                               fprintf(conn->Pfdebug, "Postmaster reports error, attempting fallback to pre-6.6.\n");
+                               fprintf(conn->Pfdebug, "Postmaster reports error, attempting fallback to pre-7.0.\n");
                        close(conn->sock);
                        conn->allow_ssl_try = FALSE;
                        return connectDBStart(conn);
@@ -849,55 +907,15 @@ connectDBStart(PGconn *conn)
                        goto connect_errReturn;
                }
        }
-#endif
-
-       /* ----------
-        * Start / make connection.  We are hopefully in non-blocking mode
-        * now, but it is possible that:
-        *       1. Older systems will still block on connect, despite the
-        *              non-blocking flag. (Anyone know if this is true?)
-        *       2. We are running under Windows, and aren't even trying
-        *              to be non-blocking (see above).
-        *       3. We are using SSL.
-        * Thus, we have make arrangements for all eventualities.
-        * ----------
-        */
-       if (connect(conn->sock, &conn->raddr.sa, conn->raddr_len) < 0)
+       if (conn->require_ssl && !conn->ssl) 
        {
-#ifndef WIN32
-               if (errno == EINPROGRESS || errno == 0)
-#else
-               if (WSAGetLastError() == WSAEINPROGRESS)
+               /* Require SSL, but server does not support/want it */
+               printfPQExpBuffer(&conn->errorMessage,
+                                                 "Server does not support SSL when SSL was required.\n");
+               goto connect_errReturn;
+       }
 #endif
-               {
 
-                       /*
-                        * This is fine - we're in non-blocking mode, and the
-                        * connection is in progress.
-                        */
-                       conn->status = CONNECTION_STARTED;
-               }
-               else
-               {
-                       /* Something's gone wrong */
-                       printfPQExpBuffer(&conn->errorMessage,
-                                                         "connectDBStart() -- connect() failed: %s\n"
-                                                         "\tIs the postmaster running%s at '%s'\n"
-                                                         "\tand accepting connections on %s '%s'?\n",
-                                                         strerror(errno),
-                                                         (family == AF_INET) ? " (with -i)" : "",
-                                                         conn->pghost ? conn->pghost : "localhost",
-                                                         (family == AF_INET) ?
-                                                         "TCP/IP port" : "Unix socket",
-                                                         conn->pgport);
-                       goto connect_errReturn;
-               }
-       }
-       else
-       {
-               /* We're connected already */
-               conn->status = CONNECTION_MADE;
-       }
 
        /*
         * This makes the connection non-blocking, for all those cases which
@@ -2485,6 +2503,15 @@ PQsetClientEncoding(PGconn *conn, const char *encoding)
 
 #endif
 
+#ifdef USE_SSL
+SSL *PQgetssl(PGconn *conn)
+{
+       if (!conn)
+               return NULL;
+       return conn->ssl;
+}
+#endif
+
 void
 PQtrace(PGconn *conn, FILE *debug_port)
 {
index 3c9a311eafaa9c36fd24ca154da0db812a2e2164..cfca1984604d838f963f3a930a1f173a187edba7 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq-fe.h,v 1.66 2000/04/14 00:24:52 tgl Exp $
+ * $Id: libpq-fe.h,v 1.67 2000/08/30 14:54:23 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -25,6 +25,9 @@ extern                "C"
  * such as Oid.
  */
 #include "postgres_ext.h"
+#ifdef USE_SSL
+#include <openssl/ssl.h>
+#endif
 
 /* Application-visible enum types */
 
@@ -222,6 +225,11 @@ extern             "C"
        extern int      PQbackendPID(const PGconn *conn);
        extern int      PQclientEncoding(const PGconn *conn);
        extern int      PQsetClientEncoding(PGconn *conn, const char *encoding);
+#ifdef USE_SSL
+       /* Get the SSL structure associated with a connection */
+       extern SSL  *PQgetssl(PGconn *conn);
+#endif
+
 
        /* Enable/disable tracing */
        extern void PQtrace(PGconn *conn, FILE *debug_port);
index b7d16d6d3903bde50b731dff02ddcccde4bd8c57..c640b6df9f2c1090e186ec6fea8529f7051800ae 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq-int.h,v 1.26 2000/05/27 04:13:05 momjian Exp $
+ * $Id: libpq-int.h,v 1.27 2000/08/30 14:54:24 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -263,6 +263,7 @@ struct pg_conn
 
 #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 */
 #endif