]> granicus.if.org Git - postgresql/commitdiff
Properly initialize SSL engines when used from libpq. This is required for
authorMagnus Hagander <magnus@hagander.net>
Tue, 23 Jun 2009 18:13:23 +0000 (18:13 +0000)
committerMagnus Hagander <magnus@hagander.net>
Tue, 23 Jun 2009 18:13:23 +0000 (18:13 +0000)
most external engines.

Per report and initial code from Lars Kanis

src/interfaces/libpq/fe-secure.c
src/interfaces/libpq/libpq-int.h

index 9ecf55e39b0a3896d107e10af6e63dd6cd639818..c6e64147872ad45232c46c7d30513845d75d705c 100644 (file)
@@ -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 <openssl/conf.h>
 #endif
-#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE)
+#ifdef USE_SSL_ENGINE
 #include <openssl/engine.h>
 #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
 }
 
 /*
index f4d6315a569b58d749f15dbbfcb70eb47780074f..51b7128b862c292bddf09c69a559ef28b13efeb8 100644 (file)
@@ -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 <openssl/ssl.h>
 #include <openssl/err.h>
+
+#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 */