Properly initialize SSL engines when used from libpq. This is required for

most external engines.

Per report and initial code from Lars Kanis
This commit is contained in:
Magnus Hagander 2009-06-23 18:13:23 +00:00
parent b087b018a1
commit a93e7432cf
2 changed files with 46 additions and 8 deletions

View File

@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* *
@ -31,6 +31,7 @@
#include "libpq-fe.h" #include "libpq-fe.h"
#include "fe-auth.h" #include "fe-auth.h"
#include "pqsignal.h" #include "pqsignal.h"
#include "libpq-int.h"
#ifdef WIN32 #ifdef WIN32
#include "win32.h" #include "win32.h"
@ -62,7 +63,7 @@
#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) #if (SSLEAY_VERSION_NUMBER >= 0x00907000L)
#include <openssl/conf.h> #include <openssl/conf.h>
#endif #endif
#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) #ifdef USE_SSL_ENGINE
#include <openssl/engine.h> #include <openssl/engine.h>
#endif #endif
@ -661,7 +662,7 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
*/ */
if (conn->sslkey && strlen(conn->sslkey) > 0) if (conn->sslkey && strlen(conn->sslkey) > 0)
{ {
#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) #ifdef USE_SSL_ENGINE
if (strchr(conn->sslkey, ':') if (strchr(conn->sslkey, ':')
#ifdef WIN32 #ifdef WIN32
&& conn->sslkey[1] != ':' && 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 */ /* Colon, but not in second character, treat as engine:key */
ENGINE *engine_ptr;
char *engine_str = strdup(conn->sslkey); char *engine_str = strdup(conn->sslkey);
char *engine_colon = strchr(engine_str, ':'); char *engine_colon = strchr(engine_str, ':');
*engine_colon = '\0'; /* engine_str now has engine name */ *engine_colon = '\0'; /* engine_str now has engine name */
engine_colon++; /* engine_colon now has key name */ engine_colon++; /* engine_colon now has key name */
engine_ptr = ENGINE_by_id(engine_str); conn->engine = ENGINE_by_id(engine_str);
if (engine_ptr == NULL) if (conn->engine == NULL)
{ {
char *err = SSLerrmessage(); char *err = SSLerrmessage();
@ -690,7 +690,22 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
return 0; 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); NULL, NULL);
if (*pkey == 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"), libpq_gettext("could not read private SSL key \"%s\" from engine \"%s\": %s\n"),
engine_colon, engine_str, err); engine_colon, engine_str, err);
SSLerrfree(err); SSLerrfree(err);
ENGINE_finish(conn->engine);
ENGINE_free(conn->engine);
conn->engine = NULL;
free(engine_str); free(engine_str);
ERR_pop_to_mark(); ERR_pop_to_mark();
return 0; return 0;
@ -1217,6 +1235,15 @@ close_SSL(PGconn *conn)
X509_free(conn->peer); X509_free(conn->peer);
conn->peer = NULL; conn->peer = NULL;
} }
#ifdef USE_SSL_ENGINE
if (conn->engine)
{
ENGINE_finish(conn->engine);
ENGINE_free(conn->engine);
conn->engine = NULL;
}
#endif
} }
/* /*

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 #ifdef USE_SSL
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/err.h> #include <openssl/err.h>
#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE)
#define USE_SSL_ENGINE
#endif #endif
#endif /* USE_SSL */
/* /*
* POSTGRES backend dependent Constants. * POSTGRES backend dependent Constants.
*/ */
@ -383,7 +388,13 @@ struct pg_conn
X509 *peer; /* X509 cert of server */ X509 *peer; /* X509 cert of server */
char peer_dn[256 + 1]; /* peer distinguished name */ char peer_dn[256 + 1]; /* peer distinguished name */
char peer_cn[SM_USER + 1]; /* peer common 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
#endif /* USE_SSL */
#ifdef ENABLE_GSS #ifdef ENABLE_GSS
gss_ctx_id_t gctx; /* GSS context */ gss_ctx_id_t gctx; /* GSS context */