Skip to content

Commit 97503a5

Browse files
committed
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.
1 parent c9aa8a6 commit 97503a5

File tree

4 files changed

+145
-53
lines changed

4 files changed

+145
-53
lines changed

doc/src/sgml/libpq.sgml

Lines changed: 89 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.280 2009/03/28 01:36:11 momjian Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.281 2009/03/31 01:41:27 tgl Exp $ -->
22

33
<chapter id="libpq">
44
<title><application>libpq</application> - C Library</title>
@@ -63,7 +63,7 @@
6363
The <function>PQstatus</> function should be called to check
6464
whether a connection was successfully made before queries are sent
6565
via the connection object.
66-
66+
6767
<note>
6868
<para>
6969
On Windows, there is a way to improve performance if a single
@@ -6168,20 +6168,6 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
61686168
environment variables <envar>PGSSLCERT</> and <envar>PGSSLKEY</>.
61696169
</para>
61706170

6171-
<para>
6172-
If your application initializes <literal>libssl</> or
6173-
<literal>libcrypto</> libraries and <application>libpq</application>
6174-
is built with <acronym>SSL</> support, you should call
6175-
<function>PQinitSSL(0)</> to tell <application>libpq</application>
6176-
that the <literal>libssl</> and <literal>libcrypto</> libraries
6177-
have been initialized by your application so
6178-
<application>libpq</application> will not initialize those libraries.
6179-
<!-- If this URL changes replace it with a URL to www.archive.org. -->
6180-
See <ulink
6181-
url="http://h71000.www7.hp.com/doc/83final/BA554_90007/ch04.html"></ulink>
6182-
for details on the SSL API.
6183-
</para>
6184-
61856171
<table id="libpq-ssl-file-usage">
61866172
<title>Libpq/Client SSL File Usage</title>
61876173
<tgroup cols="3">
@@ -6225,6 +6211,93 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
62256211
</tgroup>
62266212
</table>
62276213

6214+
<para>
6215+
If your application initializes <literal>libssl</> and/or
6216+
<literal>libcrypto</> libraries and <application>libpq</application>
6217+
is built with <acronym>SSL</> support, you should call
6218+
<function>PQinitOpenSSL</> to tell <application>libpq</application>
6219+
that the <literal>libssl</> and/or <literal>libcrypto</> libraries
6220+
have been initialized by your application, so that
6221+
<application>libpq</application> will not also initialize those libraries.
6222+
<!-- If this URL changes replace it with a URL to www.archive.org. -->
6223+
See <ulink
6224+
url="http://h71000.www7.hp.com/doc/83final/BA554_90007/ch04.html"></ulink>
6225+
for details on the SSL API.
6226+
</para>
6227+
6228+
<para>
6229+
<variablelist>
6230+
<varlistentry>
6231+
<term>
6232+
<function>PQinitOpenSSL</function>
6233+
<indexterm>
6234+
<primary>PQinitOpenSSL</primary>
6235+
</indexterm>
6236+
</term>
6237+
6238+
<listitem>
6239+
<para>
6240+
Allows applications to select which security libraries to initialize.
6241+
<synopsis>
6242+
void PQinitOpenSSL(int do_ssl, init do_crypto);
6243+
</synopsis>
6244+
</para>
6245+
6246+
<para>
6247+
When <parameter>do_ssl</> is non-zero, <application>libpq</application>
6248+
will initialize the <application>OpenSSL</> library before first
6249+
opening a database connection. When <parameter>do_crypto</> is
6250+
non-zero, the <literal>libcrypto</> library will be initialized. By
6251+
default (if <function>PQinitOpenSSL</> is not called), both libraries
6252+
are initialized. When SSL support is not compiled in, this function is
6253+
present but does nothing.
6254+
</para>
6255+
6256+
<para>
6257+
If your application uses and initializes either <application>OpenSSL</>
6258+
or its underlying <literal>libcrypto</> library, you <emphasis>must</>
6259+
call this function with zeroes for the appropriate parameter(s)
6260+
before first opening a database connection. Also be sure that you
6261+
have done that initialization before opening a database connection.
6262+
</para>
6263+
</listitem>
6264+
</varlistentry>
6265+
6266+
<varlistentry>
6267+
<term>
6268+
<function>PQinitSSL</function>
6269+
<indexterm>
6270+
<primary>PQinitSSL</primary>
6271+
</indexterm>
6272+
</term>
6273+
6274+
<listitem>
6275+
<para>
6276+
Allows applications to select which security libraries to initialize.
6277+
<synopsis>
6278+
void PQinitSSL(int do_ssl);
6279+
</synopsis>
6280+
</para>
6281+
6282+
<para>
6283+
This function is equivalent to
6284+
<literal>PQinitOpenSSL(do_ssl, do_ssl)</>.
6285+
It is sufficient for applications that initialize both or neither
6286+
of <application>OpenSSL</> and <literal>libcrypto</>.
6287+
</para>
6288+
6289+
<para>
6290+
<function>PQinitSSL</> has been present since
6291+
<productname>PostgreSQL</> 8.0, while <function>PQinitOpenSSL</>
6292+
was added in <productname>PostgreSQL</> 8.4, so <function>PQinitSSL</>
6293+
might be preferable for applications that need to work with older
6294+
versions of <application>libpq</application>.
6295+
</para>
6296+
</listitem>
6297+
</varlistentry>
6298+
</variablelist>
6299+
</para>
6300+
62286301
</sect1>
62296302

62306303

src/interfaces/libpq/exports.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $PostgreSQL: pgsql/src/interfaces/libpq/exports.txt,v 1.22 2008/09/22 13:55:14 tgl Exp $
1+
# $PostgreSQL: pgsql/src/interfaces/libpq/exports.txt,v 1.23 2009/03/31 01:41:27 tgl Exp $
22
# Functions to be exported by libpq DLLs
33
PQconnectdb 1
44
PQsetdbLogin 2
@@ -152,3 +152,4 @@ PQresultInstanceData 149
152152
PQresultSetInstanceData 150
153153
PQfireResultCreateEvents 151
154154
PQconninfoParse 152
155+
PQinitOpenSSL 153

src/interfaces/libpq/fe-secure.c

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.121 2009/03/28 18:48:55 momjian Exp $
14+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.122 2009/03/31 01:41:27 tgl Exp $
1515
*
1616
* NOTES
1717
*
@@ -99,10 +99,11 @@ static char *SSLerrmessage(void);
9999
static void SSLerrfree(char *buf);
100100

101101
static bool pq_init_ssl_lib = true;
102+
static bool pq_init_crypto_lib = true;
102103
static SSL_CTX *SSL_context = NULL;
103104

104105
#ifdef ENABLE_THREAD_SAFETY
105-
static int ssl_open_connections = 0;
106+
static long ssl_open_connections = 0;
106107

107108
#ifndef WIN32
108109
static pthread_mutex_t ssl_config_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -171,9 +172,29 @@ static long win32_ssl_create_mutex = 0;
171172
*/
172173
void
173174
PQinitSSL(int do_init)
175+
{
176+
PQinitOpenSSL(do_init, do_init);
177+
}
178+
179+
/*
180+
* Exported function to allow application to tell us it's already
181+
* initialized OpenSSL and/or libcrypto.
182+
*/
183+
void
184+
PQinitOpenSSL(int do_ssl, int do_crypto)
174185
{
175186
#ifdef USE_SSL
176-
pq_init_ssl_lib = do_init;
187+
#ifdef ENABLE_THREAD_SAFETY
188+
/*
189+
* Disallow changing the flags while we have open connections, else
190+
* we'd get completely confused.
191+
*/
192+
if (ssl_open_connections != 0)
193+
return;
194+
#endif
195+
196+
pq_init_ssl_lib = do_ssl;
197+
pq_init_crypto_lib = do_crypto;
177198
#endif
178199
}
179200

@@ -810,10 +831,10 @@ pq_lockingcallback(int mode, int n, const char *file, int line)
810831

811832
/*
812833
* Initialize SSL system. In threadsafe mode, this includes setting
813-
* up OpenSSL callback functions to do thread locking.
834+
* up libcrypto callback functions to do thread locking.
814835
*
815-
* If the caller has told us (through PQinitSSL) that he's taking care
816-
* of SSL, we expect that callbacks are already set, and won't try to
836+
* If the caller has told us (through PQinitOpenSSL) that he's taking care
837+
* of libcrypto, we expect that callbacks are already set, and won't try to
817838
* override it.
818839
*
819840
* The conn parameter is only used to be able to pass back an error
@@ -840,11 +861,11 @@ init_ssl_system(PGconn *conn)
840861
if (pthread_mutex_lock(&ssl_config_mutex))
841862
return -1;
842863

843-
if (pq_init_ssl_lib)
864+
if (pq_init_crypto_lib)
844865
{
845866
/*
846-
* If necessary, set up an array to hold locks for OpenSSL. OpenSSL will
847-
* tell us how big to make this array.
867+
* If necessary, set up an array to hold locks for libcrypto.
868+
* libcrypto will tell us how big to make this array.
848869
*/
849870
if (pq_lockarray == NULL)
850871
{
@@ -870,8 +891,7 @@ init_ssl_system(PGconn *conn)
870891

871892
if (ssl_open_connections++ == 0)
872893
{
873-
/* This is actually libcrypto, not libssl. */
874-
/* These are only required for threaded SSL applications */
894+
/* These are only required for threaded libcrypto applications */
875895
CRYPTO_set_id_callback(pq_threadidcallback);
876896
CRYPTO_set_locking_callback(pq_lockingcallback);
877897
}
@@ -913,9 +933,10 @@ init_ssl_system(PGconn *conn)
913933
/*
914934
* This function is needed because if the libpq library is unloaded
915935
* from the application, the callback functions will no longer exist when
916-
* SSL used by other parts of the system. For this reason,
917-
* we unregister the SSL callback functions when the last libpq
918-
* connection is closed.
936+
* libcrypto is used by other parts of the system. For this reason,
937+
* we unregister the callback functions when the last libpq
938+
* connection is closed. (The same would apply for OpenSSL callbacks
939+
* if we had any.)
919940
*
920941
* Callbacks are only set when we're compiled in threadsafe mode, so
921942
* we only need to remove them in this case.
@@ -928,27 +949,23 @@ destroy_ssl_system(void)
928949
if (pthread_mutex_lock(&ssl_config_mutex))
929950
return;
930951

931-
if (pq_init_ssl_lib)
952+
if (pq_init_crypto_lib && ssl_open_connections > 0)
953+
--ssl_open_connections;
954+
955+
if (pq_init_crypto_lib && ssl_open_connections == 0)
932956
{
933-
if (ssl_open_connections > 0)
934-
--ssl_open_connections;
957+
/* No connections left, unregister libcrypto callbacks */
958+
CRYPTO_set_locking_callback(NULL);
959+
CRYPTO_set_id_callback(NULL);
935960

936-
if (ssl_open_connections == 0)
937-
{
938-
/* This is actually libcrypto, not libssl. */
939-
/* No connections left, unregister all callbacks */
940-
CRYPTO_set_locking_callback(NULL);
941-
CRYPTO_set_id_callback(NULL);
942-
943-
/*
944-
* We don't free the lock array. If we get another connection
945-
* from the same caller, we will just re-use it with the existing
946-
* mutexes.
947-
*
948-
* This means we leak a little memory on repeated load/unload
949-
* of the library.
950-
*/
951-
}
961+
/*
962+
* We don't free the lock array. If we get another connection
963+
* in this process, we will just re-use it with the existing
964+
* mutexes.
965+
*
966+
* This means we leak a little memory on repeated load/unload
967+
* of the library.
968+
*/
952969
}
953970

954971
pthread_mutex_unlock(&ssl_config_mutex);
@@ -995,8 +1012,6 @@ initialize_SSL(PGconn *conn)
9951012
homedir[0] = '\0';
9961013
}
9971014

998-
999-
10001015
if (conn->sslrootcert)
10011016
strncpy(fnbuf, conn->sslrootcert, sizeof(fnbuf));
10021017
else

src/interfaces/libpq/libpq-fe.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.145 2009/01/01 17:24:03 momjian Exp $
10+
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.146 2009/03/31 01:41:27 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -302,6 +302,9 @@ extern void *PQgetssl(PGconn *conn);
302302
/* Tell libpq whether it needs to initialize OpenSSL */
303303
extern void PQinitSSL(int do_init);
304304

305+
/* More detailed way to tell libpq whether it needs to initialize OpenSSL */
306+
extern void PQinitOpenSSL(int do_ssl, int do_crypto);
307+
305308
/* Set verbosity for PQerrorMessage and PQresultErrorMessage */
306309
extern PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity);
307310

0 commit comments

Comments
 (0)