aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2009-03-31 01:41:27 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2009-03-31 01:41:27 +0000
commit97503a5200289b3fa3319ecc06ca74f197f0bcf0 (patch)
tree9cde5b4608cdf45db24d9da79655af2d147bde59
parentc9aa8a62c026e6ac35ad286f7be77d21c04a7a48 (diff)
downloadpostgresql-97503a5200289b3fa3319ecc06ca74f197f0bcf0.tar.gz
postgresql-97503a5200289b3fa3319ecc06ca74f197f0bcf0.zip
Add PQinitOpenSSL() function to support applications that use libcrypto
but not OpenSSL (or perhaps vice versa, if that's possible). Andrew Chernow, with minor editorialization by me.
-rw-r--r--doc/src/sgml/libpq.sgml105
-rw-r--r--src/interfaces/libpq/exports.txt3
-rw-r--r--src/interfaces/libpq/fe-secure.c85
-rw-r--r--src/interfaces/libpq/libpq-fe.h5
4 files changed, 145 insertions, 53 deletions
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 2c2b53911de..1540ed62693 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -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>
diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index 655968e5f32..f08fc58109e 100644
--- a/src/interfaces/libpq/exports.txt
+++ b/src/interfaces/libpq/exports.txt
@@ -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
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index e29ee227bf9..a876793baf4 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -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;
@@ -172,8 +173,28 @@ 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
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index df756fde21c..bef09087071 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -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);