diff options
-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) |