diff options
author | James Yonan <james@openvpn.net> | 2010-12-09 11:21:04 +0000 |
---|---|---|
committer | David Sommerseth <davids@redhat.com> | 2011-03-25 09:38:28 +0100 |
commit | cf69617bbea45a15423c4188daa9386debcbe1ec (patch) | |
tree | c3786b3116633d98e037c76f3ced6378e05edcad | |
parent | 98c6662472adf7228e4265328aa8d067aa41695f (diff) | |
download | openvpn-cf69617bbea45a15423c4188daa9386debcbe1ec.tar.gz openvpn-cf69617bbea45a15423c4188daa9386debcbe1ec.tar.xz openvpn-cf69617bbea45a15423c4188daa9386debcbe1ec.zip |
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
-rw-r--r-- | base64.c | 17 | ||||
-rw-r--r-- | base64.h | 4 | ||||
-rw-r--r-- | buffer.c | 2 | ||||
-rw-r--r-- | manage.c | 204 | ||||
-rw-r--r-- | manage.h | 24 | ||||
-rw-r--r-- | misc.c | 2 | ||||
-rw-r--r-- | ntlm.c | 2 | ||||
-rw-r--r-- | options.c | 8 | ||||
-rw-r--r-- | ssl.c | 214 | ||||
-rw-r--r-- | syshead.h | 15 |
10 files changed, 433 insertions, 59 deletions
@@ -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; } @@ -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 @@ -901,7 +901,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 @@ -102,6 +102,10 @@ man_help () 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."); msg (M_CLIENT, "state [on|off] [N|all] : Like log, but show state history."); @@ -768,49 +772,31 @@ man_hold (struct management *man, const char *cmd) msg (M_CLIENT, "SUCCESS: hold=%d", BOOL_CAST(man->settings.flags & MF_HOLD)); } -#ifdef MANAGEMENT_DEF_AUTH - -static bool -parse_cid (const char *str, unsigned long *cid) -{ - if (sscanf (str, "%lu", cid) == 1) - return true; - else - { - msg (M_CLIENT, "ERROR: cannot parse CID"); - return false; - } -} +#ifdef MANAGEMENT_IN_EXTRA -static bool -parse_kid (const char *str, unsigned int *kid) -{ - if (sscanf (str, "%u", kid) == 1) - return true; - else - { - msg (M_CLIENT, "ERROR: cannot parse KID"); - return false; - } -} +#define IER_RESET 0 +#define IER_NEW 1 +#define IER_CONDRESET 2 static void -in_extra_reset (struct man_connection *mc, const bool new) +in_extra_reset (struct man_connection *mc, const int mode) { - if (mc) + if (mc && (mc->in_extra_cmd < IEC_STATEFUL_BASE || mode != IER_CONDRESET)) { - if (!new) + 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 (new) + if (mode == IER_NEW) mc->in_extra = buffer_list_new (0); } } @@ -820,6 +806,7 @@ 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) { @@ -846,6 +833,7 @@ in_extra_dispatch (struct management *man) 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) @@ -870,8 +858,41 @@ in_extra_dispatch (struct management *man) } 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 +parse_cid (const char *str, unsigned long *cid) +{ + if (sscanf (str, "%lu", cid) == 1) + return true; + else + { + msg (M_CLIENT, "ERROR: cannot parse CID"); + return false; + } +} + +static bool +parse_kid (const char *str, unsigned int *kid) +{ + if (sscanf (str, "%u", kid) == 1) + return true; + else + { + msg (M_CLIENT, "ERROR: cannot parse KID"); + return false; } - in_extra_reset (&man->connection, false); } static void @@ -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 */ @@ -264,16 +264,23 @@ 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; bool state_realtime; @@ -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) { @@ -1618,7 +1618,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); @@ -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; @@ -3663,6 +3663,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")) { @@ -51,6 +51,7 @@ #include "gremlin.h" #include "pkcs11.h" #include "list.h" +#include "base64.h" #ifdef WIN32 #include "cryptoapi.h" @@ -1482,6 +1483,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 @@ -1589,7 +1779,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; @@ -1613,6 +1803,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; } @@ -1657,6 +1849,7 @@ init_ssl (const struct options *options) DH *dh; BIO *bio; bool using_cert_file = false; + X509 *my_cert = NULL; ERR_clear_error (); @@ -1756,7 +1949,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; } } @@ -1824,18 +2016,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) { @@ -1967,6 +2173,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; @@ -510,6 +510,21 @@ socket_defined (const socket_descriptor_t sd) #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? */ #if defined(CONFIGURE_PF) && P2MP_SERVER && defined(ENABLE_PLUGIN) && defined(HAVE_STAT) |