diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 2c2b53911d..1540ed6269 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1,4 +1,4 @@ - + <application>libpq</application> - C Library @@ -63,7 +63,7 @@ The PQstatus function should be called to check whether a connection was successfully made before queries are sent via the connection object. - + 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 PGSSLCERT and PGSSLKEY. - - If your application initializes libssl or - libcrypto libraries and libpq - is built with SSL support, you should call - PQinitSSL(0) to tell libpq - that the libssl and libcrypto libraries - have been initialized by your application so - libpq will not initialize those libraries. - - See - for details on the SSL API. - - Libpq/Client SSL File Usage @@ -6225,6 +6211,93 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
+ + If your application initializes libssl and/or + libcrypto libraries and libpq + is built with SSL support, you should call + PQinitOpenSSL to tell libpq + that the libssl and/or libcrypto libraries + have been initialized by your application, so that + libpq will not also initialize those libraries. + + See + for details on the SSL API. + + + + + + + PQinitOpenSSL + + PQinitOpenSSL + + + + + + Allows applications to select which security libraries to initialize. + + void PQinitOpenSSL(int do_ssl, init do_crypto); + + + + + When do_ssl is non-zero, libpq + will initialize the OpenSSL library before first + opening a database connection. When do_crypto is + non-zero, the libcrypto library will be initialized. By + default (if PQinitOpenSSL is not called), both libraries + are initialized. When SSL support is not compiled in, this function is + present but does nothing. + + + + If your application uses and initializes either OpenSSL + or its underlying libcrypto library, you 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. + + + + + + + PQinitSSL + + PQinitSSL + + + + + + Allows applications to select which security libraries to initialize. + + void PQinitSSL(int do_ssl); + + + + + This function is equivalent to + PQinitOpenSSL(do_ssl, do_ssl). + It is sufficient for applications that initialize both or neither + of OpenSSL and libcrypto. + + + + PQinitSSL has been present since + PostgreSQL 8.0, while PQinitOpenSSL + was added in PostgreSQL 8.4, so PQinitSSL + might be preferable for applications that need to work with older + versions of libpq. + + + + + + diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt index 655968e5f3..f08fc58109 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 e29ee227bf..a876793baf 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; @@ -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 diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h index df756fde21..bef0908707 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);