0
0
mirror of https://github.com/OpenVPN/openvpn.git synced 2024-09-20 12:02:28 +02:00

Added "management-external-key" option. This option can be used

instead of "key" in client mode, and allows the client to run
without the need to load the actual private key.  When the SSL
protocol needs to perform an RSA sign operation, the data to
be signed will be sent to the management interface via a
notification as follows:

  >RSA_SIGN:[BASE64_DATA]

The management interface client should then sign BASE64_DATA
using the private key and return the signature as follows:

  rsa-sig
  [BASE64_SIG_LINE]
  .
  .
  .
  END

This capability is intended to allow the use of arbitrary
cryptographic service providers with OpenVPN via the
management interface.


git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@6708 e7ae566f-a301-0410-adde-c780ea21d3b5
This commit is contained in:
James Yonan 2010-12-09 11:21:04 +00:00
parent 2d12eb12cf
commit 2a3d17ed18
10 changed files with 484 additions and 110 deletions

View File

@ -33,7 +33,7 @@
#include "syshead.h"
#if defined(ENABLE_HTTP_PROXY) || defined(ENABLE_PKCS11) || defined(ENABLE_CLIENT_CR)
#if defined(ENABLE_HTTP_PROXY) || defined(ENABLE_PKCS11) || defined(ENABLE_CLIENT_CR) || defined(MANAGMENT_EXTERNAL_KEY)
#include "base64.h"
@ -115,22 +115,35 @@ token_decode(const char *token)
}
int
base64_decode(const char *str, void *data)
base64_decode(const char *str, void *data, int size)
{
const char *p;
unsigned char *q;
unsigned char *e = NULL;
q = data;
if (size >= 0)
e = q + size;
for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4) {
unsigned int val = token_decode(p);
unsigned int marker = (val >> 24) & 0xff;
if (val == DECODE_ERROR)
return -1;
if (e && q >= e)
return -1;
*q++ = (val >> 16) & 0xff;
if (marker < 2)
{
if (e && q >= e)
return -1;
*q++ = (val >> 8) & 0xff;
}
if (marker < 1)
{
if (e && q >= e)
return -1;
*q++ = val & 0xff;
}
}
return q - (unsigned char *) data;
}

View File

@ -34,10 +34,10 @@
#ifndef _BASE64_H_
#define _BASE64_H_
#if defined(ENABLE_HTTP_PROXY) || defined(ENABLE_PKCS11) || defined(ENABLE_CLIENT_CR)
#if defined(ENABLE_HTTP_PROXY) || defined(ENABLE_PKCS11) || defined(ENABLE_CLIENT_CR) || defined(MANAGMENT_EXTERNAL_KEY)
int base64_encode(const void *data, int size, char **str);
int base64_decode(const char *str, void *data);
int base64_decode(const char *str, void *data, int size);
#endif

View File

@ -906,7 +906,7 @@ buffer_list_free (struct buffer_list *ol)
bool
buffer_list_defined (const struct buffer_list *ol)
{
return ol->head != NULL;
return ol && ol->head != NULL;
}
void

306
manage.c
View File

@ -101,6 +101,10 @@ man_help ()
#ifdef MANAGEMENT_PF
msg (M_CLIENT, "client-pf CID : Define packet filter for client CID (MULTILINE)");
#endif
#endif
#ifdef MANAGMENT_EXTERNAL_KEY
msg (M_CLIENT, "rsa-sig : Enter an RSA signature in response to >RSA_SIGN challenge");
msg (M_CLIENT, " Enter signature base64 on subsequent lines followed by END");
#endif
msg (M_CLIENT, "signal s : Send signal s to daemon,");
msg (M_CLIENT, " s = SIGHUP|SIGTERM|SIGUSR1|SIGUSR2.");
@ -768,6 +772,103 @@ man_hold (struct management *man, const char *cmd)
msg (M_CLIENT, "SUCCESS: hold=%d", BOOL_CAST(man->settings.flags & MF_HOLD));
}
#ifdef MANAGEMENT_IN_EXTRA
#define IER_RESET 0
#define IER_NEW 1
#define IER_CONDRESET 2
static void
in_extra_reset (struct man_connection *mc, const int mode)
{
if (mc && (mc->in_extra_cmd < IEC_STATEFUL_BASE || mode != IER_CONDRESET))
{
if (mode != IER_NEW)
{
mc->in_extra_cmd = IEC_UNDEF;
#ifdef MANAGEMENT_DEF_AUTH
mc->in_extra_cid = 0;
mc->in_extra_kid = 0;
#endif
}
if (mc->in_extra)
{
buffer_list_free (mc->in_extra);
mc->in_extra = NULL;
}
if (mode == IER_NEW)
mc->in_extra = buffer_list_new (0);
}
}
static void
in_extra_dispatch (struct management *man)
{
switch (man->connection.in_extra_cmd)
{
#ifdef MANAGEMENT_DEF_AUTH
case IEC_CLIENT_AUTH:
if (man->persist.callback.client_auth)
{
const bool status = (*man->persist.callback.client_auth)
(man->persist.callback.arg,
man->connection.in_extra_cid,
man->connection.in_extra_kid,
true,
NULL,
NULL,
man->connection.in_extra);
man->connection.in_extra = NULL;
if (status)
{
msg (M_CLIENT, "SUCCESS: client-auth command succeeded");
}
else
{
msg (M_CLIENT, "ERROR: client-auth command failed");
}
}
else
{
msg (M_CLIENT, "ERROR: The client-auth command is not supported by the current daemon mode");
}
break;
#endif
#ifdef MANAGEMENT_PF
case IEC_CLIENT_PF:
if (man->persist.callback.client_pf)
{
const bool status = (*man->persist.callback.client_pf)
(man->persist.callback.arg,
man->connection.in_extra_cid,
man->connection.in_extra);
man->connection.in_extra = NULL;
if (status)
{
msg (M_CLIENT, "SUCCESS: client-pf command succeeded");
}
else
{
msg (M_CLIENT, "ERROR: client-pf command failed");
}
}
else
{
msg (M_CLIENT, "ERROR: The client-pf command is not supported by the current daemon mode");
}
break;
#endif
#ifdef MANAGMENT_EXTERNAL_KEY
case IEC_RSA_SIGN:
man->connection.in_extra_cmd = IEC_RSA_SIGN_FINAL;
return;
#endif
}
in_extra_reset (&man->connection, IER_RESET);
}
#endif /* MANAGEMENT_IN_EXTRA */
#ifdef MANAGEMENT_DEF_AUTH
static bool
@ -794,86 +895,6 @@ parse_kid (const char *str, unsigned int *kid)
}
}
static void
in_extra_reset (struct man_connection *mc, const bool new)
{
if (mc)
{
if (!new)
{
mc->in_extra_cmd = IEC_UNDEF;
mc->in_extra_cid = 0;
mc->in_extra_kid = 0;
}
if (mc->in_extra)
{
buffer_list_free (mc->in_extra);
mc->in_extra = NULL;
}
if (new)
mc->in_extra = buffer_list_new (0);
}
}
static void
in_extra_dispatch (struct management *man)
{
switch (man->connection.in_extra_cmd)
{
case IEC_CLIENT_AUTH:
if (man->persist.callback.client_auth)
{
const bool status = (*man->persist.callback.client_auth)
(man->persist.callback.arg,
man->connection.in_extra_cid,
man->connection.in_extra_kid,
true,
NULL,
NULL,
man->connection.in_extra);
man->connection.in_extra = NULL;
if (status)
{
msg (M_CLIENT, "SUCCESS: client-auth command succeeded");
}
else
{
msg (M_CLIENT, "ERROR: client-auth command failed");
}
}
else
{
msg (M_CLIENT, "ERROR: The client-auth command is not supported by the current daemon mode");
}
break;
#ifdef MANAGEMENT_PF
case IEC_CLIENT_PF:
if (man->persist.callback.client_pf)
{
const bool status = (*man->persist.callback.client_pf)
(man->persist.callback.arg,
man->connection.in_extra_cid,
man->connection.in_extra);
man->connection.in_extra = NULL;
if (status)
{
msg (M_CLIENT, "SUCCESS: client-pf command succeeded");
}
else
{
msg (M_CLIENT, "ERROR: client-pf command failed");
}
}
else
{
msg (M_CLIENT, "ERROR: The client-pf command is not supported by the current daemon mode");
}
break;
#endif
}
in_extra_reset (&man->connection, false);
}
static void
man_client_auth (struct management *man, const char *cid_str, const char *kid_str, const bool extra)
{
@ -884,7 +905,7 @@ man_client_auth (struct management *man, const char *cid_str, const char *kid_st
&& parse_kid (kid_str, &mc->in_extra_kid))
{
mc->in_extra_cmd = IEC_CLIENT_AUTH;
in_extra_reset (mc, true);
in_extra_reset (mc, IER_NEW);
if (!extra)
in_extra_dispatch (man);
}
@ -980,11 +1001,28 @@ man_client_pf (struct management *man, const char *cid_str)
if (parse_cid (cid_str, &mc->in_extra_cid))
{
mc->in_extra_cmd = IEC_CLIENT_PF;
in_extra_reset (mc, true);
in_extra_reset (mc, IER_NEW);
}
}
#endif
#endif /* MANAGEMENT_PF */
#endif /* MANAGEMENT_DEF_AUTH */
#ifdef MANAGMENT_EXTERNAL_KEY
static void
man_rsa_sig (struct management *man)
{
struct man_connection *mc = &man->connection;
if (mc->in_extra_cmd == IEC_RSA_SIGN_PRE)
{
in_extra_reset (&man->connection, IER_NEW);
mc->in_extra_cmd = IEC_RSA_SIGN;
}
else
msg (M_CLIENT, "ERROR: The rsa-sig command is not currently available");
}
#endif
static void
@ -1250,6 +1288,12 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
}
#endif
#endif
#ifdef MANAGMENT_EXTERNAL_KEY
else if (streq (p[0], "rsa-sig"))
{
man_rsa_sig (man);
}
#endif
#ifdef ENABLE_PKCS11
else if (streq (p[0], "pkcs11-id-count"))
{
@ -1626,8 +1670,8 @@ man_reset_client_socket (struct management *man, const bool exiting)
man->connection.state = MS_INITIAL;
command_line_reset (man->connection.in);
buffer_list_reset (man->connection.out);
#ifdef MANAGEMENT_DEF_AUTH
in_extra_reset (&man->connection, false);
#ifdef MANAGEMENT_IN_EXTRA
in_extra_reset (&man->connection, IER_RESET);
#endif
msg (D_MANAGEMENT, "MANAGEMENT: Client disconnected");
}
@ -1666,8 +1710,8 @@ man_process_command (struct management *man, const char *line)
CLEAR (parms);
so = status_open (NULL, 0, -1, &man->persist.vout, 0);
#ifdef MANAGEMENT_DEF_AUTH
in_extra_reset (&man->connection, false);
#ifdef MANAGEMENT_IN_EXTRA
in_extra_reset (&man->connection, IER_CONDRESET);
#endif
if (man_password_needed (man))
@ -1751,18 +1795,13 @@ man_read (struct management *man)
const unsigned char *line;
while ((line = command_line_get (man->connection.in)))
{
#ifdef MANAGEMENT_DEF_AUTH
#ifdef MANAGEMENT_IN_EXTRA
if (man->connection.in_extra)
{
if (!strcmp ((char *)line, "END"))
{
in_extra_dispatch (man);
in_extra_reset (&man->connection, false);
}
in_extra_dispatch (man);
else
{
buffer_list_push (man->connection.in_extra, line);
}
buffer_list_push (man->connection.in_extra, line);
}
else
#endif
@ -2063,8 +2102,8 @@ man_connection_close (struct management *man)
command_line_free (mc->in);
if (mc->out)
buffer_list_free (mc->out);
#ifdef MANAGEMENT_DEF_AUTH
in_extra_reset (&man->connection, false);
#ifdef MANAGEMENT_IN_EXTRA
in_extra_reset (&man->connection, IER_RESET);
#endif
man_connection_clear (mc);
}
@ -2387,7 +2426,7 @@ management_learn_addr (struct management *management,
gc_free (&gc);
}
#endif
#endif /* MANAGEMENT_DEF_AUTH */
void
management_echo (struct management *man, const char *string, const bool pull)
@ -2693,6 +2732,7 @@ man_standalone_event_loop (struct management *man, volatile int *signal_received
#define MWCC_PASSWORD_WAIT (1<<0)
#define MWCC_HOLD_WAIT (1<<1)
#define MWCC_OTHER_WAIT (1<<2)
/*
* Block until client connects
@ -2710,6 +2750,8 @@ man_wait_for_client_connection (struct management *man,
msg (D_MANAGEMENT, "Need password(s) from management interface, waiting...");
if (flags & MWCC_HOLD_WAIT)
msg (D_MANAGEMENT, "Need hold release from management interface, waiting...");
if (flags & MWCC_OTHER_WAIT)
msg (D_MANAGEMENT, "Need information from management interface, waiting...");
do {
man_standalone_event_loop (man, signal_received, expire);
if (signal_received && *signal_received)
@ -2873,6 +2915,74 @@ management_query_user_pass (struct management *man,
return ret;
}
#ifdef MANAGMENT_EXTERNAL_KEY
char * /* returns allocated base64 signature */
management_query_rsa_sig (struct management *man,
const char *b64_data)
{
struct gc_arena gc = gc_new ();
char *ret = NULL;
volatile int signal_received = 0;
struct buffer alert_msg = clear_buf();
struct buffer *buf;
const bool standalone_disabled_save = man->persist.standalone_disabled;
if (man_standalone_ok (man))
{
man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */
man->persist.special_state_msg = NULL;
in_extra_reset (&man->connection, IER_RESET);
man->connection.in_extra_cmd = IEC_RSA_SIGN_PRE;
alert_msg = alloc_buf_gc (strlen(b64_data)+64, &gc);
buf_printf (&alert_msg, ">RSA_SIGN:%s", b64_data);
man_wait_for_client_connection (man, &signal_received, 0, MWCC_OTHER_WAIT);
if (signal_received)
goto done;
man->persist.special_state_msg = BSTR (&alert_msg);
msg (M_CLIENT, "%s", man->persist.special_state_msg);
/* run command processing event loop until we get our signature */
do
{
man_standalone_event_loop (man, &signal_received, 0);
if (!signal_received)
man_check_for_signals (&signal_received);
if (signal_received)
goto done;
} while (man->connection.in_extra_cmd != IEC_RSA_SIGN_FINAL);
if (buffer_list_defined(man->connection.in_extra))
{
buffer_list_aggregate (man->connection.in_extra, 2000);
buf = buffer_list_peek (man->connection.in_extra);
if (buf && BLEN(buf) > 0)
{
ret = (char *) malloc(BLEN(buf)+1);
check_malloc_return(ret);
memcpy(ret, buf->data, BLEN(buf));
ret[BLEN(buf)] = '\0';
}
}
}
done:
/* revert state */
man->persist.standalone_disabled = standalone_disabled_save;
man->persist.special_state_msg = NULL;
in_extra_reset (&man->connection, IER_RESET);
gc_free (&gc);
return ret;
}
#endif
/*
* Return true if management_hold() would block
*/

View File

@ -264,15 +264,22 @@ struct man_connection {
struct command_line *in;
struct buffer_list *out;
#ifdef MANAGEMENT_DEF_AUTH
#ifdef MANAGEMENT_IN_EXTRA
# define IEC_UNDEF 0
# define IEC_CLIENT_AUTH 1
# define IEC_CLIENT_PF 2
# define IEC_STATEFUL_BASE 16
# define IEC_RSA_SIGN_PRE 16
# define IEC_RSA_SIGN 17
# define IEC_RSA_SIGN_FINAL 18
int in_extra_cmd;
struct buffer_list *in_extra;
#ifdef MANAGEMENT_DEF_AUTH
unsigned long in_extra_cid;
unsigned int in_extra_kid;
struct buffer_list *in_extra;
int env_filter_level;
#endif
#endif
struct event_set *es;
@ -285,6 +292,10 @@ struct man_connection {
const char *up_query_type;
int up_query_mode;
struct user_pass up_query;
#ifdef MANAGMENT_EXTERNAL_KEY
struct buffer_list *rsa_sig;
#endif
};
struct management
@ -314,6 +325,9 @@ struct management *management_init (void);
# define MF_CLIENT_PF (1<<7)
#endif
# define MF_UNIX_SOCK (1<<8)
#ifdef MANAGMENT_EXTERNAL_KEY
# define MF_EXTERNAL_KEY (1<<9)
#endif
bool management_open (struct management *man,
const char *addr,
@ -374,6 +388,12 @@ void management_learn_addr (struct management *management,
const bool primary);
#endif
#ifdef MANAGMENT_EXTERNAL_KEY
char *management_query_rsa_sig (struct management *man, const char *b64_data);
#endif
static inline bool
management_connected (const struct management *man)
{

2
misc.c
View File

@ -1607,7 +1607,7 @@ get_auth_challenge (const char *auth_challenge, struct gc_arena *gc)
if (!buf_parse(&b, ':', work, len))
return NULL;
ac->user = (char *) gc_malloc (strlen(work)+1, true, gc);
base64_decode(work, (void*)ac->user);
base64_decode(work, (void*)ac->user, -1);
/* parse challenge text */
ac->challenge_text = string_alloc(BSTR(&b), gc);

2
ntlm.c
View File

@ -242,7 +242,7 @@ ntlm_phase_3 (const struct http_proxy_info *p, const char *phase_2, struct gc_ar
/* pad to 21 bytes */
memset (md4_hash + 16, 0, 5);
ret_val = base64_decode( phase_2, (void *)buf2);
ret_val = base64_decode( phase_2, (void *)buf2, -1);
if (ret_val < 0)
return NULL;

View File

@ -3636,6 +3636,14 @@ add_option (struct options *options,
options->management_flags |= MF_CONNECT_AS_CLIENT;
options->management_write_peer_info_file = p[1];
}
#ifdef MANAGMENT_EXTERNAL_KEY
else if (streq (p[0], "management-external-key"))
{
VERIFY_PERMISSION (OPT_P_GENERAL);
options->management_flags |= MF_EXTERNAL_KEY;
options->priv_key_file = "EXTERNAL_PRIVATE_KEY";
}
#endif
#ifdef MANAGEMENT_DEF_AUTH
else if (streq (p[0], "management-client-auth"))
{

214
ssl.c
View File

@ -48,6 +48,7 @@
#include "gremlin.h"
#include "pkcs11.h"
#include "list.h"
#include "base64.h"
#ifdef WIN32
#include "cryptoapi.h"
@ -1315,6 +1316,195 @@ info_callback (INFO_CALLBACK_SSL_CONST SSL * s, int where, int ret)
}
}
#ifdef MANAGMENT_EXTERNAL_KEY
/* encrypt */
static int
rsa_pub_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
{
ASSERT(0);
return -1;
}
/* verify arbitrary data */
static int
rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
{
ASSERT(0);
return -1;
}
/* decrypt */
static int
rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
{
ASSERT(0);
return -1;
}
/* called at RSA_free */
static int
rsa_finish(RSA *rsa)
{
free ((void*)rsa->meth);
rsa->meth = NULL;
return 1;
}
/* sign arbitrary data */
static int
rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
{
/* optional app data in rsa->meth->app_data; */
char *in_b64 = NULL;
char *out_b64 = NULL;
int ret = -1;
int len;
if (padding != RSA_PKCS1_PADDING)
{
RSAerr (RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
goto done;
}
/* convert 'from' to base64 */
if (base64_encode (from, flen, &in_b64) <= 0)
goto done;
/* call MI for signature */
if (management)
out_b64 = management_query_rsa_sig (management, in_b64);
if (!out_b64)
goto done;
/* decode base64 signature to binary */
len = RSA_size(rsa);
ret = base64_decode (out_b64, to, len);
/* verify length */
if (ret != len)
ret = -1;
done:
if (in_b64)
free (in_b64);
if (out_b64)
free (out_b64);
return ret;
}
static int
use_external_private_key (SSL_CTX *ssl_ctx, X509 *cert)
{
RSA *rsa = NULL;
RSA *pub_rsa;
RSA_METHOD *rsa_meth;
/* allocate custom RSA method object */
ALLOC_OBJ_CLEAR (rsa_meth, RSA_METHOD);
rsa_meth->name = "OpenVPN external private key RSA Method";
rsa_meth->rsa_pub_enc = rsa_pub_enc;
rsa_meth->rsa_pub_dec = rsa_pub_dec;
rsa_meth->rsa_priv_enc = rsa_priv_enc;
rsa_meth->rsa_priv_dec = rsa_priv_dec;
rsa_meth->init = NULL;
rsa_meth->finish = rsa_finish;
rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK;
rsa_meth->app_data = NULL;
/* allocate RSA object */
rsa = RSA_new();
if (rsa == NULL)
{
SSLerr(SSL_F_SSL_USE_PRIVATEKEY, ERR_R_MALLOC_FAILURE);
goto err;
}
/* get the public key */
ASSERT(cert->cert_info->key->pkey); /* NULL before SSL_CTX_use_certificate() is called */
pub_rsa = cert->cert_info->key->pkey->pkey.rsa;
/* initialize RSA object */
rsa->n = BN_dup(pub_rsa->n);
rsa->flags |= RSA_FLAG_EXT_PKEY;
if (!RSA_set_method(rsa, rsa_meth))
goto err;
/* bind our custom RSA object to ssl_ctx */
if (!SSL_CTX_use_RSAPrivateKey(ssl_ctx, rsa))
goto err;
RSA_free(rsa); /* doesn't necessarily free, just decrements refcount */
return 1;
err:
if (rsa)
RSA_free(rsa);
else
{
if (rsa_meth)
free(rsa_meth);
}
return 0;
}
/*
* Basically a clone of SSL_CTX_use_certificate_file, but also return
* the x509 object.
*/
static int
use_certificate_file(SSL_CTX *ctx, const char *file, int type, X509 **x509)
{
int j;
BIO *in;
int ret=0;
X509 *x=NULL;
in=BIO_new(BIO_s_file_internal());
if (in == NULL)
{
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,ERR_R_BUF_LIB);
goto end;
}
if (BIO_read_filename(in,file) <= 0)
{
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,ERR_R_SYS_LIB);
goto end;
}
if (type == SSL_FILETYPE_ASN1)
{
j=ERR_R_ASN1_LIB;
x=d2i_X509_bio(in,NULL);
}
else if (type == SSL_FILETYPE_PEM)
{
j=ERR_R_PEM_LIB;
x=PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata);
}
else
{
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,SSL_R_BAD_SSL_FILETYPE);
goto end;
}
if (x == NULL)
{
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,j);
goto end;
}
ret=SSL_CTX_use_certificate(ctx,x);
end:
if (in != NULL)
BIO_free(in);
if (x509)
*x509 = x;
return(ret);
}
#endif
#if ENABLE_INLINE_FILES
static int
@ -1422,7 +1612,7 @@ use_inline_load_client_CA_file (SSL_CTX *ctx, const char *ca_string)
}
static int
use_inline_certificate_file (SSL_CTX *ctx, const char *cert_string)
use_inline_certificate_file (SSL_CTX *ctx, const char *cert_string, X509 **x509)
{
BIO *in = NULL;
X509 *x = NULL;
@ -1446,6 +1636,8 @@ use_inline_certificate_file (SSL_CTX *ctx, const char *cert_string)
X509_free (x);
if (in)
BIO_free (in);
if (x509)
*x509 = x;
return ret;
}
@ -1490,6 +1682,7 @@ init_ssl (const struct options *options)
DH *dh;
BIO *bio;
bool using_cert_file = false;
X509 *my_cert = NULL;
ERR_clear_error ();
@ -1589,7 +1782,6 @@ init_ssl (const struct options *options)
management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL);
#endif
PKCS12_free(p12);
msg (M_INFO, "OpenSSL ERROR code: %d", (ERR_GET_REASON (ERR_peek_error()))); // fixme
goto err;
}
}
@ -1657,18 +1849,32 @@ init_ssl (const struct options *options)
#if ENABLE_INLINE_FILES
if (!strcmp (options->cert_file, INLINE_FILE_TAG) && options->cert_file_inline)
{
if (!use_inline_certificate_file (ctx, options->cert_file_inline))
if (!use_inline_certificate_file (ctx, options->cert_file_inline, &my_cert))
msg (M_SSLERR, "Cannot load inline certificate file");
}
else
#endif
{
#ifdef MANAGMENT_EXTERNAL_KEY
if (!use_certificate_file (ctx, options->cert_file, SSL_FILETYPE_PEM, &my_cert))
#else
if (!SSL_CTX_use_certificate_file (ctx, options->cert_file, SSL_FILETYPE_PEM))
#endif
msg (M_SSLERR, "Cannot load certificate file %s", options->cert_file);
using_cert_file = true;
}
}
#ifdef MANAGMENT_EXTERNAL_KEY
if (options->management_flags & MF_EXTERNAL_KEY)
{
ASSERT (my_cert);
if (!use_external_private_key(ctx, my_cert))
msg (M_SSLERR, "Cannot enable SSL external private key capability");
}
else
#endif
/* Load Private Key */
if (options->priv_key_file)
{
@ -1795,6 +2001,8 @@ init_ssl (const struct options *options)
err:
ERR_clear_error ();
if (my_cert)
X509_free(my_cert);
if (ctx)
SSL_CTX_free (ctx);
return NULL;

View File

@ -508,6 +508,21 @@ socket_defined (const socket_descriptor_t sd)
#define ENABLE_DEF_AUTH
#endif
/*
* Enable external private key
*/
#if defined(ENABLE_MANAGEMENT) && defined(USE_SSL)
#define MANAGMENT_EXTERNAL_KEY
#endif
/*
* MANAGEMENT_IN_EXTRA allows the management interface to
* read multi-line inputs from clients.
*/
#if defined(MANAGEMENT_DEF_AUTH) || defined(MANAGMENT_EXTERNAL_KEY)
#define MANAGEMENT_IN_EXTRA
#endif
/*
* Enable packet filter?
*/