aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/man-sections/client-options.rst7
-rw-r--r--src/openvpn/crypto.h5
-rw-r--r--src/openvpn/forward.c4
-rw-r--r--src/openvpn/multi.c7
-rw-r--r--src/openvpn/options.c30
-rw-r--r--src/openvpn/options.h2
-rw-r--r--src/openvpn/push.c37
-rw-r--r--src/openvpn/push.h2
-rw-r--r--src/openvpn/sig.c30
-rw-r--r--src/openvpn/ssl.c5
-rw-r--r--src/openvpn/ssl.h4
-rw-r--r--src/openvpn/ssl_ncp.c5
12 files changed, 129 insertions, 9 deletions
diff --git a/doc/man-sections/client-options.rst b/doc/man-sections/client-options.rst
index 8e0e4f1..5a90689 100644
--- a/doc/man-sections/client-options.rst
+++ b/doc/man-sections/client-options.rst
@@ -220,9 +220,14 @@ configuration.
immediately close its client instance object rather than waiting for a
timeout.
+ If both server and client support sending this message using the control
+ channel, the message will be sent as control-channel message. Otherwise
+ the message is sent as data-channel message, which will be ignored by
+ data-channel offloaded peers.
+
The **n** parameter (default :code:`1` if not present) controls the
maximum number of attempts that the client will try to resend the exit
- notification message.
+ notification message if messages are sent in data-channel mode.
In UDP server mode, send :code:`RESTART` control channel command to
connected clients. The ``n`` parameter (default :code:`1` if not present)
diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h
index 98e2c76..5ea8890 100644
--- a/src/openvpn/crypto.h
+++ b/src/openvpn/crypto.h
@@ -264,6 +264,11 @@ struct crypto_options
/**< Bit-flag indicating that we do not allow clients that do
* not support resending the wrapped client key (WKc) with the
* third packet of the three-way handshake */
+#define CO_USE_CC_EXIT_NOTIFY (1<<6)
+ /**< Bit-flag indicating that explicit exit notifies should be
+ * sent via the control channel instead of using an OCC message
+ */
+
unsigned int flags; /**< Bit-flags determining behavior of
* security operation functions. */
};
diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c
index 468eeee..6a45b9e 100644
--- a/src/openvpn/forward.c
+++ b/src/openvpn/forward.c
@@ -260,6 +260,10 @@ check_incoming_control_channel(struct context *c)
{
receive_auth_pending(c, &buf);
}
+ else if (buf_string_match_head_str(&buf, "EXIT"))
+ {
+ receive_exit_message(c);
+ }
else
{
msg(D_PUSH_ERRORS, "WARNING: Received unknown control message: %s", BSTR(&buf));
diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c
index 1bbeab7..b9b087e 100644
--- a/src/openvpn/multi.c
+++ b/src/openvpn/multi.c
@@ -1801,10 +1801,15 @@ multi_client_set_protocol_options(struct context *c)
#ifdef HAVE_EXPORT_KEYING_MATERIAL
if (proto & IV_PROTO_TLS_KEY_EXPORT)
{
- o->data_channel_crypto_flags |= CO_USE_TLS_KEY_MATERIAL_EXPORT;
+ o->imported_protocol_flags |= CO_USE_TLS_KEY_MATERIAL_EXPORT;
}
#endif
+ if (proto & IV_PROTO_CC_EXIT_NOTIFY)
+ {
+ o->imported_protocol_flags |= CO_USE_CC_EXIT_NOTIFY;
+ }
+
/* Select cipher if client supports Negotiable Crypto Parameters */
/* if we have already created our key, we cannot *change* our own
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 45fbb63..e44993c 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -3341,7 +3341,7 @@ pre_connect_restore(struct options *o, struct gc_arena *gc)
o->push_continuation = 0;
o->push_option_types_found = 0;
- o->data_channel_crypto_flags = 0;
+ o->imported_protocol_flags = 0;
}
static void
@@ -8496,11 +8496,13 @@ add_option(struct options *options,
}
else if (streq(p[0], "key-derivation") && p[1])
{
+ /* NCP only option that is pushed by the server to enable EKM,
+ * should not be used by normal users in config files*/
VERIFY_PERMISSION(OPT_P_NCP)
#ifdef HAVE_EXPORT_KEYING_MATERIAL
if (streq(p[1], "tls-ekm"))
{
- options->data_channel_crypto_flags |= CO_USE_TLS_KEY_MATERIAL_EXPORT;
+ options->imported_protocol_flags |= CO_USE_TLS_KEY_MATERIAL_EXPORT;
}
else
#endif
@@ -8508,6 +8510,30 @@ add_option(struct options *options,
msg(msglevel, "Unknown key-derivation method %s", p[1]);
}
}
+ else if (streq(p[0], "protocol-flags") && p[1])
+ {
+ /* NCP only option that is pushed by the server to enable protocol
+ * features that are negotiated, should not be used by normal users
+ * in config files */
+ VERIFY_PERMISSION(OPT_P_NCP)
+ for (size_t j = 1; j < MAX_PARMS && p[j] != NULL; j++)
+ {
+ if (streq(p[j], "cc-exit"))
+ {
+ options->imported_protocol_flags |= CO_USE_CC_EXIT_NOTIFY;
+ }
+#ifdef HAVE_EXPORT_KEYING_MATERIAL
+ else if (streq(p[j], "tls-ekm"))
+ {
+ options->imported_protocol_flags |= CO_USE_TLS_KEY_MATERIAL_EXPORT;
+ }
+#endif
+ else
+ {
+ msg(msglevel, "Unknown protocol-flags flag: %s", p[j]);
+ }
+ }
+ }
else if (streq(p[0], "prng") && p[1] && !p[3])
{
msg(M_WARN, "NOTICE: --prng option ignored (SSL library PRNG is used)");
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index b70cd42..f438cd2 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -681,7 +681,7 @@ struct options
bool allow_recursive_routing;
/* data channel crypto flags set by push/pull. Reuses the CO_* crypto_flags */
- unsigned int data_channel_crypto_flags;
+ unsigned int imported_protocol_flags;
};
#define streq(x, y) (!strcmp((x), (y)))
diff --git a/src/openvpn/push.c b/src/openvpn/push.c
index 4cbc89e..47a7992 100644
--- a/src/openvpn/push.c
+++ b/src/openvpn/push.c
@@ -180,6 +180,21 @@ server_pushed_signal(struct context *c, const struct buffer *buffer, const bool
}
void
+receive_exit_message(struct context *c)
+{
+ dmsg(D_STREAM_ERRORS, "Exit message received by peer");
+ c->sig->signal_received = SIGTERM;
+ c->sig->signal_text = "remote-exit";
+#ifdef ENABLE_MANAGEMENT
+ if (management)
+ {
+ management_notify(management, "info", c->sig->signal_text, "EXIT");
+ }
+#endif
+}
+
+
+void
server_pushed_info(struct context *c, const struct buffer *buffer,
const int adv)
{
@@ -606,10 +621,30 @@ prepare_push_reply(struct context *c, struct gc_arena *gc,
{
push_option_fmt(gc, push_list, M_USAGE, "cipher %s", o->ciphername);
}
- if (o->data_channel_crypto_flags & CO_USE_TLS_KEY_MATERIAL_EXPORT)
+
+ struct buffer proto_flags = alloc_buf_gc(128, gc);
+
+ if (o->imported_protocol_flags & CO_USE_CC_EXIT_NOTIFY)
+ {
+ buf_printf(&proto_flags, " cc-exit");
+
+ /* if the cc exit flag is supported, pushing tls-ekm via protocol-flags
+ * is also supported */
+ if (o->imported_protocol_flags & CO_USE_TLS_KEY_MATERIAL_EXPORT)
+ {
+ buf_printf(&proto_flags, " tls-ekm");
+ }
+ }
+ else if (o->imported_protocol_flags & CO_USE_TLS_KEY_MATERIAL_EXPORT)
{
push_option_fmt(gc, push_list, M_USAGE, "key-derivation tls-ekm");
}
+
+ if (buf_len(&proto_flags) > 0)
+ {
+ push_option_fmt(gc, push_list, M_USAGE, "protocol-flags%s", buf_str(&proto_flags));
+ }
+
return true;
}
diff --git a/src/openvpn/push.h b/src/openvpn/push.h
index 62fad4a..7138055 100644
--- a/src/openvpn/push.h
+++ b/src/openvpn/push.h
@@ -48,6 +48,8 @@ void receive_auth_failed(struct context *c, const struct buffer *buffer);
void server_pushed_signal(struct context *c, const struct buffer *buffer, const bool restart, const int adv);
+void receive_exit_message(struct context *c);
+
void server_pushed_info(struct context *c, const struct buffer *buffer,
const int adv);
diff --git a/src/openvpn/sig.c b/src/openvpn/sig.c
index e06edd2..65cd25c 100644
--- a/src/openvpn/sig.c
+++ b/src/openvpn/sig.c
@@ -321,20 +321,46 @@ print_status(const struct context *c, struct status_output *so)
gc_free(&gc);
}
+
+/* Small helper function to determine if we should send the exit notification
+ * via control channel */
+static inline bool
+cc_exit_notify_enabled(struct context *c)
+{
+ /* Check if we have TLS active at all */
+ if (!c->c2.tls_multi)
+ {
+ return false;
+ }
+
+ const struct key_state *ks = get_primary_key(c->c2.tls_multi);
+ return (ks->crypto_options.flags & CO_USE_CC_EXIT_NOTIFY);
+}
+
/*
* Handle the triggering and time-wait of explicit
* exit notification.
*/
-
static void
process_explicit_exit_notification_init(struct context *c)
{
msg(M_INFO, "SIGTERM received, sending exit notification to peer");
+ /* init the timeout to send the OCC_EXIT messages if cc exit is not
+ * enabled and also to exit after waiting for retries of resending of
+ * exit messages */
event_timeout_init(&c->c2.explicit_exit_notification_interval, 1, 0);
reset_coarse_timers(c);
+
signal_reset(c->sig);
halt_non_edge_triggered_signals();
c->c2.explicit_exit_notification_time_wait = now;
+
+ /* Check if we are in TLS mode and should send the notification via data
+ * channel */
+ if (cc_exit_notify_enabled(c))
+ {
+ send_control_channel_string(c, "EXIT", D_PUSH);
+ }
}
void
@@ -351,7 +377,7 @@ process_explicit_exit_notification_timer_wakeup(struct context *c)
c->sig->signal_received = SIGTERM;
c->sig->signal_text = "exit-with-notification";
}
- else
+ else if (!cc_exit_notify_enabled(c))
{
c->c2.occ_op = OCC_EXIT;
}
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index 33e145b..d3f7a02 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -1719,7 +1719,7 @@ tls_session_update_crypto_params(struct tls_multi *multi,
}
/* Import crypto settings that might be set by pull/push */
- session->opt->crypto_flags |= options->data_channel_crypto_flags;
+ session->opt->crypto_flags |= options->imported_protocol_flags;
return tls_session_update_crypto_params_do_work(multi, session, options,
frame, frame_fragment, lsi);
@@ -1969,6 +1969,9 @@ push_peer_info(struct buffer *buf, struct tls_session *session)
/* support for the --dns option */
iv_proto |= IV_PROTO_DNS_OPTION;
+ /* support for exit notify via control channel */
+ iv_proto |= IV_PROTO_CC_EXIT_NOTIFY;
+
/* support for receiving push_reply before sending
* push request, also signal that the client wants
* to get push-reply messages without without requiring a round
diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h
index 76b1b67..12ffd44 100644
--- a/src/openvpn/ssl.h
+++ b/src/openvpn/ssl.h
@@ -96,6 +96,10 @@
/** Supports the --dns option introduced in version 2.6 */
#define IV_PROTO_DNS_OPTION (1<<6)
+/** Support for explicit exit notify via control channel
+ * This also includes support for the protocol-flags pushed option */
+#define IV_PROTO_CC_EXIT_NOTIFY (1<<7)
+
/* Default field in X509 to be username */
#define X509_USERNAME_FIELD_DEFAULT "CN"
diff --git a/src/openvpn/ssl_ncp.c b/src/openvpn/ssl_ncp.c
index a58ced5..fe84919 100644
--- a/src/openvpn/ssl_ncp.c
+++ b/src/openvpn/ssl_ncp.c
@@ -419,6 +419,11 @@ p2p_ncp_set_options(struct tls_multi *multi, struct tls_session *session)
multi->peer_id = 0x76706e; /* 'v' 'p' 'n' */
}
+ if (iv_proto_peer & IV_PROTO_CC_EXIT_NOTIFY)
+ {
+ session->opt->crypto_flags |= CO_USE_CC_EXIT_NOTIFY;
+ }
+
#if defined(HAVE_EXPORT_KEYING_MATERIAL)
if (iv_proto_peer & IV_PROTO_TLS_KEY_EXPORT)
{