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)
/**< 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. */
};
{
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));
#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
o->push_continuation = 0;
o->push_option_types_found = 0;
- o->data_channel_crypto_flags = 0;
+ o->imported_protocol_flags = 0;
}
static void
}
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
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)");
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)))
}
}
+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)
{
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;
}
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);
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
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;
}
}
/* 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);
/* 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
/** 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"
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)
{