]> granicus.if.org Git - postgresql/commitdiff
Add PQinitOpenSSL() function to support applications that use libcrypto
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 31 Mar 2009 01:41:27 +0000 (01:41 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 31 Mar 2009 01:41:27 +0000 (01:41 +0000)
but not OpenSSL (or perhaps vice versa, if that's possible).

Andrew Chernow, with minor editorialization by me.

doc/src/sgml/libpq.sgml
src/interfaces/libpq/exports.txt
src/interfaces/libpq/fe-secure.c
src/interfaces/libpq/libpq-fe.h

index 2c2b53911dee9216f4199eb3816bdcd2115bf971..1540ed6269356a175e24998912213096b39042ad 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.280 2009/03/28 01:36:11 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.281 2009/03/31 01:41:27 tgl Exp $ -->
 
 <chapter id="libpq">
  <title><application>libpq</application> - C Library</title>
@@ -63,7 +63,7 @@
    The <function>PQstatus</> function should be called to check
    whether a connection was successfully made before queries are sent
    via the connection object.
-  
+
    <note>
     <para>
      On Windows, there is a way to improve performance if a single
@@ -6168,20 +6168,6 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
    environment variables <envar>PGSSLCERT</> and <envar>PGSSLKEY</>.
   </para>
 
-  <para>
-   If your application initializes <literal>libssl</> or
-   <literal>libcrypto</> libraries and <application>libpq</application>
-   is built with <acronym>SSL</> support, you should call
-   <function>PQinitSSL(0)</> to tell <application>libpq</application>
-   that the <literal>libssl</> and <literal>libcrypto</> libraries
-   have been initialized by your application so
-   <application>libpq</application> will not initialize those libraries.
-   <!-- If this URL changes replace it with a URL to www.archive.org. -->
-   See <ulink
-   url="http://h71000.www7.hp.com/doc/83final/BA554_90007/ch04.html"></ulink>
-   for details on the SSL API.
-  </para>
-
   <table id="libpq-ssl-file-usage">
    <title>Libpq/Client SSL File Usage</title>
    <tgroup cols="3">
@@ -6225,6 +6211,93 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
    </tgroup>
   </table>
 
+  <para>
+   If your application initializes <literal>libssl</> and/or
+   <literal>libcrypto</> libraries and <application>libpq</application>
+   is built with <acronym>SSL</> support, you should call
+   <function>PQinitOpenSSL</> to tell <application>libpq</application>
+   that the <literal>libssl</> and/or <literal>libcrypto</> libraries
+   have been initialized by your application, so that
+   <application>libpq</application> will not also initialize those libraries.
+   <!-- If this URL changes replace it with a URL to www.archive.org. -->
+   See <ulink
+   url="http://h71000.www7.hp.com/doc/83final/BA554_90007/ch04.html"></ulink>
+   for details on the SSL API.
+  </para>
+
+  <para>
+   <variablelist>
+    <varlistentry>
+     <term>
+      <function>PQinitOpenSSL</function>
+      <indexterm>
+       <primary>PQinitOpenSSL</primary>
+      </indexterm>
+     </term>
+
+     <listitem>
+      <para>
+       Allows applications to select which security libraries to initialize.
+       <synopsis>
+        void PQinitOpenSSL(int do_ssl, init do_crypto);
+       </synopsis>
+      </para>
+
+      <para>
+       When <parameter>do_ssl</> is non-zero, <application>libpq</application>
+       will initialize the <application>OpenSSL</> library before first
+       opening a database connection.  When <parameter>do_crypto</> is
+       non-zero, the <literal>libcrypto</> library will be initialized.  By
+       default (if <function>PQinitOpenSSL</> is not called), both libraries
+       are initialized.  When SSL support is not compiled in, this function is
+       present but does nothing.
+      </para>
+
+      <para>
+       If your application uses and initializes either <application>OpenSSL</>
+       or its underlying <literal>libcrypto</> library, you <emphasis>must</>
+       call this function with zeroes for the appropriate parameter(s)
+       before first opening a database connection.  Also be sure that you
+       have done that initialization before opening a database connection.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term>
+      <function>PQinitSSL</function>
+      <indexterm>
+       <primary>PQinitSSL</primary>
+      </indexterm>
+     </term>
+
+     <listitem>
+      <para>
+       Allows applications to select which security libraries to initialize.
+       <synopsis>
+        void PQinitSSL(int do_ssl);
+       </synopsis>
+      </para>
+
+      <para>
+       This function is equivalent to
+       <literal>PQinitOpenSSL(do_ssl, do_ssl)</>.
+       It is sufficient for applications that initialize both or neither
+       of <application>OpenSSL</> and <literal>libcrypto</>.
+      </para>
+
+      <para>
+       <function>PQinitSSL</> has been present since
+       <productname>PostgreSQL</> 8.0, while <function>PQinitOpenSSL</>
+       was added in <productname>PostgreSQL</> 8.4, so <function>PQinitSSL</>
+       might be preferable for applications that need to work with older
+       versions of <application>libpq</application>.
+      </para>
+     </listitem>
+    </varlistentry>
+   </variablelist>
+  </para>
+
  </sect1>
 
 
index 655968e5f32cce6eead37d0d4c039de89dd1eabb..f08fc58109e0b347eed8d14d4a5ee22b09105e4c 100644 (file)
@@ -1,4 +1,4 @@
-# $PostgreSQL: pgsql/src/interfaces/libpq/exports.txt,v 1.22 2008/09/22 13:55:14 tgl Exp $
+# $PostgreSQL: pgsql/src/interfaces/libpq/exports.txt,v 1.23 2009/03/31 01:41:27 tgl Exp $
 # Functions to be exported by libpq DLLs
 PQconnectdb               1
 PQsetdbLogin              2
@@ -152,3 +152,4 @@ PQresultInstanceData      149
 PQresultSetInstanceData   150
 PQfireResultCreateEvents  151
 PQconninfoParse           152
+PQinitOpenSSL             153
index e29ee227bf9dc82ac44b2f03e2a9cd01cdcfc1f9..a876793baf436a98bdae6d77559a915f4a6bb37f 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.121 2009/03/28 18:48:55 momjian Exp $
+ *       $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.122 2009/03/31 01:41:27 tgl Exp $
  *
  * NOTES
  *
@@ -99,10 +99,11 @@ static char *SSLerrmessage(void);
 static void SSLerrfree(char *buf);
 
 static bool pq_init_ssl_lib = true;
+static bool pq_init_crypto_lib = true;
 static SSL_CTX *SSL_context = NULL;
 
 #ifdef ENABLE_THREAD_SAFETY
-static int ssl_open_connections = 0;
+static long ssl_open_connections = 0;
 
 #ifndef WIN32
 static pthread_mutex_t ssl_config_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -171,9 +172,29 @@ static long win32_ssl_create_mutex = 0;
  */
 void
 PQinitSSL(int do_init)
+{
+       PQinitOpenSSL(do_init, do_init);
+}
+
+/*
+ *     Exported function to allow application to tell us it's already
+ *     initialized OpenSSL and/or libcrypto.
+ */
+void 
+PQinitOpenSSL(int do_ssl, int do_crypto)
 {
 #ifdef USE_SSL
-       pq_init_ssl_lib = do_init;
+#ifdef ENABLE_THREAD_SAFETY
+       /*
+        * Disallow changing the flags while we have open connections, else
+        * we'd get completely confused.
+        */
+       if (ssl_open_connections != 0)
+               return;
+#endif
+
+       pq_init_ssl_lib = do_ssl;
+       pq_init_crypto_lib = do_crypto;
 #endif
 }
 
@@ -810,10 +831,10 @@ pq_lockingcallback(int mode, int n, const char *file, int line)
 
 /*
  * Initialize SSL system. In threadsafe mode, this includes setting
- * up OpenSSL callback functions to do thread locking.
+ * up libcrypto callback functions to do thread locking.
  *
- * If the caller has told us (through PQinitSSL) that he's taking care
- * of SSL, we expect that callbacks are already set, and won't try to
+ * If the caller has told us (through PQinitOpenSSL) that he's taking care
+ * of libcrypto, we expect that callbacks are already set, and won't try to
  * override it.
  *
  * The conn parameter is only used to be able to pass back an error
@@ -840,11 +861,11 @@ init_ssl_system(PGconn *conn)
        if (pthread_mutex_lock(&ssl_config_mutex))
                return -1;
 
-       if (pq_init_ssl_lib)
+       if (pq_init_crypto_lib)
        {
                /*
-                * If necessary, set up an array to hold locks for OpenSSL. OpenSSL will
-                * tell us how big to make this array.
+                * If necessary, set up an array to hold locks for libcrypto.
+                * libcrypto will tell us how big to make this array.
                 */
                if (pq_lockarray == NULL)
                {
@@ -870,8 +891,7 @@ init_ssl_system(PGconn *conn)
 
                if (ssl_open_connections++ == 0)
                {
-                       /* This is actually libcrypto, not libssl. */
-                       /* These are only required for threaded SSL applications */
+                       /* These are only required for threaded libcrypto applications */
                        CRYPTO_set_id_callback(pq_threadidcallback);
                        CRYPTO_set_locking_callback(pq_lockingcallback);
                }
@@ -913,9 +933,10 @@ init_ssl_system(PGconn *conn)
 /*
  *     This function is needed because if the libpq library is unloaded
  *     from the application, the callback functions will no longer exist when
- *     SSL used by other parts of the system.  For this reason,
- *     we unregister the SSL callback functions when the last libpq
- *     connection is closed.
+ *     libcrypto is used by other parts of the system.  For this reason,
+ *     we unregister the callback functions when the last libpq
+ *     connection is closed.  (The same would apply for OpenSSL callbacks
+ *     if we had any.)
  *
  *     Callbacks are only set when we're compiled in threadsafe mode, so
  *     we only need to remove them in this case.
@@ -928,27 +949,23 @@ destroy_ssl_system(void)
        if (pthread_mutex_lock(&ssl_config_mutex))
                return;
 
-       if (pq_init_ssl_lib)
+       if (pq_init_crypto_lib && ssl_open_connections > 0)
+               --ssl_open_connections;
+
+       if (pq_init_crypto_lib && ssl_open_connections == 0)
        {
-               if (ssl_open_connections > 0)
-                       --ssl_open_connections;
+               /* No connections left, unregister libcrypto callbacks */
+               CRYPTO_set_locking_callback(NULL);
+               CRYPTO_set_id_callback(NULL);
 
-               if (ssl_open_connections == 0)
-               {
-                       /* This is actually libcrypto, not libssl. */
-                       /* No connections left, unregister all callbacks */
-                       CRYPTO_set_locking_callback(NULL);
-                       CRYPTO_set_id_callback(NULL);
-
-                       /*
-                        * We don't free the lock array. If we get another connection
-                        * from the same caller, we will just re-use it with the existing
-                        * mutexes.
-                        *
-                        * This means we leak a little memory on repeated load/unload
-                        * of the library.
-                        */
-               }
+               /*
+                * We don't free the lock array. If we get another connection
+                * in this process, we will just re-use it with the existing
+                * mutexes.
+                *
+                * This means we leak a little memory on repeated load/unload
+                * of the library.
+                */
        }
 
        pthread_mutex_unlock(&ssl_config_mutex);
@@ -995,8 +1012,6 @@ initialize_SSL(PGconn *conn)
                homedir[0] = '\0';
        }
 
-
-
        if (conn->sslrootcert)
                strncpy(fnbuf, conn->sslrootcert, sizeof(fnbuf));
        else
index df756fde21c5b0ce4fb50ca572cc3a98ab4f0416..bef0908707101f18a43e9ebd4302c4082e7d1226 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.145 2009/01/01 17:24:03 momjian Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.146 2009/03/31 01:41:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -302,6 +302,9 @@ extern void *PQgetssl(PGconn *conn);
 /* Tell libpq whether it needs to initialize OpenSSL */
 extern void PQinitSSL(int do_init);
 
+/* More detailed way to tell libpq whether it needs to initialize OpenSSL */
+extern void PQinitOpenSSL(int do_ssl, int do_crypto);
+
 /* Set verbosity for PQerrorMessage and PQresultErrorMessage */
 extern PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity);