From a93e7432cff306dad75dcd242ced9f80436cecc1 Mon Sep 17 00:00:00 2001 From: Magnus Hagander Date: Tue, 23 Jun 2009 18:13:23 +0000 Subject: [PATCH] Properly initialize SSL engines when used from libpq. This is required for most external engines. Per report and initial code from Lars Kanis --- src/interfaces/libpq/fe-secure.c | 41 ++++++++++++++++++++++++++------ src/interfaces/libpq/libpq-int.h | 13 +++++++++- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c index 9ecf55e39b..c6e6414787 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.126 2009/06/11 14:49:14 momjian Exp $ + * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.127 2009/06/23 18:13:23 mha Exp $ * * NOTES * @@ -31,6 +31,7 @@ #include "libpq-fe.h" #include "fe-auth.h" #include "pqsignal.h" +#include "libpq-int.h" #ifdef WIN32 #include "win32.h" @@ -62,7 +63,7 @@ #if (SSLEAY_VERSION_NUMBER >= 0x00907000L) #include #endif -#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) +#ifdef USE_SSL_ENGINE #include #endif @@ -661,7 +662,7 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) */ if (conn->sslkey && strlen(conn->sslkey) > 0) { -#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) +#ifdef USE_SSL_ENGINE if (strchr(conn->sslkey, ':') #ifdef WIN32 && conn->sslkey[1] != ':' @@ -669,15 +670,14 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) ) { /* Colon, but not in second character, treat as engine:key */ - ENGINE *engine_ptr; char *engine_str = strdup(conn->sslkey); char *engine_colon = strchr(engine_str, ':'); *engine_colon = '\0'; /* engine_str now has engine name */ engine_colon++; /* engine_colon now has key name */ - engine_ptr = ENGINE_by_id(engine_str); - if (engine_ptr == NULL) + conn->engine = ENGINE_by_id(engine_str); + if (conn->engine == NULL) { char *err = SSLerrmessage(); @@ -690,7 +690,22 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) return 0; } - *pkey = ENGINE_load_private_key(engine_ptr, engine_colon, + if (ENGINE_init(conn->engine) == 0) + { + char *err = SSLerrmessage(); + + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("could not initialize SSL engine \"%s\": %s\n"), + engine_str, err); + SSLerrfree(err); + ENGINE_free(conn->engine); + conn->engine = NULL; + free(engine_str); + ERR_pop_to_mark(); + return 0; + } + + *pkey = ENGINE_load_private_key(conn->engine, engine_colon, NULL, NULL); if (*pkey == NULL) { @@ -700,6 +715,9 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) libpq_gettext("could not read private SSL key \"%s\" from engine \"%s\": %s\n"), engine_colon, engine_str, err); SSLerrfree(err); + ENGINE_finish(conn->engine); + ENGINE_free(conn->engine); + conn->engine = NULL; free(engine_str); ERR_pop_to_mark(); return 0; @@ -1217,6 +1235,15 @@ close_SSL(PGconn *conn) X509_free(conn->peer); conn->peer = NULL; } + +#ifdef USE_SSL_ENGINE + if (conn->engine) + { + ENGINE_finish(conn->engine); + ENGINE_free(conn->engine); + conn->engine = NULL; + } +#endif } /* diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index f4d6315a56..51b7128b86 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -12,7 +12,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-int.h,v 1.142 2009/06/11 14:49:14 momjian Exp $ + * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.143 2009/06/23 18:13:23 mha Exp $ * *------------------------------------------------------------------------- */ @@ -76,8 +76,13 @@ typedef struct #ifdef USE_SSL #include #include + +#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) +#define USE_SSL_ENGINE #endif +#endif /* USE_SSL */ + /* * POSTGRES backend dependent Constants. */ @@ -383,7 +388,13 @@ struct pg_conn X509 *peer; /* X509 cert of server */ char peer_dn[256 + 1]; /* peer distinguished name */ char peer_cn[SM_USER + 1]; /* peer common name */ +#ifdef USE_SSL_ENGINE + ENGINE *engine; /* SSL engine, if any */ +#else + void *engine; /* dummy field to keep struct the same + if OpenSSL version changes */ #endif +#endif /* USE_SSL */ #ifdef ENABLE_GSS gss_ctx_id_t gctx; /* GSS context */