From f9906da03e011d6ac457d49a3b5473c320b01e6e Mon Sep 17 00:00:00 2001 From: Lorenzo Miniero Date: Tue, 7 Dec 2021 16:03:08 +0100 Subject: [PATCH] Allow VideoRoom to choose whether signed tokens should be used (#2825) --- auth.c | 6 ++++++ auth.h | 2 ++ conf/janus.plugin.videoroom.jcfg.sample | 2 ++ janus.c | 6 ++++++ plugins/janus_videoroom.c | 26 ++++++++++++++++++++++--- plugins/plugin.h | 5 ++++- 6 files changed, 43 insertions(+), 4 deletions(-) diff --git a/auth.c b/auth.c index 6f063b62c8..ab62ea44b8 100644 --- a/auth.c +++ b/auth.c @@ -70,6 +70,10 @@ gboolean janus_auth_is_stored_mode(void) { return auth_enabled && tokens != NULL; } +gboolean janus_auth_is_signed_mode(void) { + return auth_enabled && auth_secret != NULL; +} + void janus_auth_deinit(void) { janus_mutex_lock(&mutex); if(tokens != NULL) @@ -124,6 +128,8 @@ gboolean janus_auth_check_signature_contains(const char *token, const char *real if (!auth_enabled || auth_secret == NULL) { return TRUE; } + if(token == NULL) + return FALSE; gchar **parts = g_strsplit(token, ":", 2); gchar **data = NULL; /* Token should have exactly one data and one hash part */ diff --git a/auth.h b/auth.h index 0055cdc6d7..cfb2e1b428 100644 --- a/auth.h +++ b/auth.h @@ -30,6 +30,8 @@ void janus_auth_init(gboolean enabled, const char *secret); gboolean janus_auth_is_enabled(void); /*! \brief Method to check whether the mechanism is in stored-token mode or not */ gboolean janus_auth_is_stored_mode(void); +/*! \brief Method to check whether the mechanism is in signed-token mode or not */ +gboolean janus_auth_is_signed_mode(void); /*! \brief Method to de-initialize the mechanism */ void janus_auth_deinit(void); diff --git a/conf/janus.plugin.videoroom.jcfg.sample b/conf/janus.plugin.videoroom.jcfg.sample index e0f8a54ec0..17d7050469 100644 --- a/conf/janus.plugin.videoroom.jcfg.sample +++ b/conf/janus.plugin.videoroom.jcfg.sample @@ -5,6 +5,8 @@ # pin = # require_pvtid = true|false (whether subscriptions are required to provide a valid private_id # to associate with a publisher, default=false) +# signed_tokens = true|false (whether access to the room requires signed tokens; default=false, + only works if signed tokens are used in the core as well) # publishers = (e.g., 6 for a video # conference or 1 for a webinar) # bitrate = (e.g., 128000) diff --git a/janus.c b/janus.c index d7f57b3da7..cb7e5cd556 100644 --- a/janus.c +++ b/janus.c @@ -607,6 +607,7 @@ void janus_plugin_send_remb(janus_plugin_session *plugin_session, uint32_t bitra void janus_plugin_close_pc(janus_plugin_session *plugin_session); void janus_plugin_end_session(janus_plugin_session *plugin_session); void janus_plugin_notify_event(janus_plugin *plugin, janus_plugin_session *plugin_session, json_t *event); +gboolean janus_plugin_auth_is_signed(void); gboolean janus_plugin_auth_is_signature_valid(janus_plugin *plugin, const char *token); gboolean janus_plugin_auth_signature_contains(janus_plugin *plugin, const char *token, const char *desc); static janus_callbacks janus_handler_plugin = @@ -621,6 +622,7 @@ static janus_callbacks janus_handler_plugin = .end_session = janus_plugin_end_session, .events_is_enabled = janus_events_is_enabled, .notify_event = janus_plugin_notify_event, + .auth_is_signed = janus_plugin_auth_is_signed, .auth_is_signature_valid = janus_plugin_auth_is_signature_valid, .auth_signature_contains = janus_plugin_auth_signature_contains, }; @@ -4102,6 +4104,10 @@ void janus_plugin_notify_event(janus_plugin *plugin, janus_plugin_session *plugi } } +gboolean janus_plugin_auth_is_signed() { + return janus_auth_is_signed_mode(); +} + gboolean janus_plugin_auth_is_signature_valid(janus_plugin *plugin, const char *token) { return janus_auth_check_signature(token, plugin->get_package()); } diff --git a/plugins/janus_videoroom.c b/plugins/janus_videoroom.c index 6b8ff65429..4495f2882f 100644 --- a/plugins/janus_videoroom.c +++ b/plugins/janus_videoroom.c @@ -56,6 +56,8 @@ room-: { pin = require_pvtid = true|false (whether subscriptions are required to provide a valid private_id to associate with a publisher, default=false) + signed_tokens = true|false (whether access to the room requires signed tokens; default=false, + only works if signed tokens are used in the core as well) publishers = (e.g., 6 for a video conference or 1 for a webinar, default=3) bitrate = (e.g., 128000) @@ -1260,6 +1262,7 @@ static struct janus_json_parameter create_parameters[] = { {"secret", JSON_STRING, 0}, {"pin", JSON_STRING, 0}, {"require_pvtid", JANUS_JSON_BOOL, 0}, + {"signed_tokens", JANUS_JSON_BOOL, 0}, {"bitrate", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE}, {"bitrate_cap", JANUS_JSON_BOOL, 0}, {"fir_freq", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE}, @@ -1484,6 +1487,7 @@ typedef struct janus_videoroom { gchar *room_pin; /* Password needed to join this room, if any */ gboolean is_private; /* Whether this room is 'private' (as in hidden) or not */ gboolean require_pvtid; /* Whether subscriptions in this room require a private_id */ + gboolean signed_tokens; /* Whether signed tokens are required (assuming they're enabled in the core) */ gboolean require_e2ee; /* Whether end-to-end encrypted publishers are required */ int max_publishers; /* Maximum number of concurrent publishers */ uint32_t bitrate; /* Global bitrate limit */ @@ -2250,6 +2254,7 @@ int janus_videoroom_init(janus_callbacks *callback, const char *config_path) { janus_config_item *secret = janus_config_get(config, cat, janus_config_type_item, "secret"); janus_config_item *pin = janus_config_get(config, cat, janus_config_type_item, "pin"); janus_config_item *req_pvtid = janus_config_get(config, cat, janus_config_type_item, "require_pvtid"); + janus_config_item *signed_tokens = janus_config_get(config, cat, janus_config_type_item, "signed_tokens"); janus_config_item *bitrate = janus_config_get(config, cat, janus_config_type_item, "bitrate"); janus_config_item *bitrate_cap = janus_config_get(config, cat, janus_config_type_item, "bitrate_cap"); janus_config_item *maxp = janus_config_get(config, cat, janus_config_type_item, "publishers"); @@ -2322,6 +2327,13 @@ int janus_videoroom_init(janus_callbacks *callback, const char *config_path) { } videoroom->is_private = priv && priv->value && janus_is_true(priv->value); videoroom->require_pvtid = req_pvtid && req_pvtid->value && janus_is_true(req_pvtid->value); + if(signed_tokens && signed_tokens->value && janus_is_true(signed_tokens->value)) { + if(!gateway->auth_is_signed()) { + JANUS_LOG(LOG_WARN, "Can't enforce signed tokens for this room, signed-mode not in use in the core\n"); + } else { + videoroom->signed_tokens = TRUE; + } + } videoroom->require_e2ee = req_e2ee && req_e2ee->value && janus_is_true(req_e2ee->value); videoroom->max_publishers = 3; /* FIXME How should we choose a default? */ if(maxp != NULL && maxp->value != NULL) @@ -2994,9 +3006,9 @@ static int janus_videoroom_access_room(json_t *root, gboolean check_modify, gboo } if(check_join) { char error_cause2[100]; - /* signed tokens bypass pin validation */ - json_t *token = json_object_get(root, "token"); - if(token) { + /* Signed tokens are enforced, so they precede any pin validation */ + if(gateway->auth_is_signed() && (*videoroom)->signed_tokens) { + json_t *token = json_object_get(root, "token"); char room_descriptor[100]; g_snprintf(room_descriptor, sizeof(room_descriptor), "room=%s", room_id_str); if(!gateway->auth_signature_contains(&janus_videoroom_plugin, json_string_value(token), room_descriptor)) { @@ -3061,6 +3073,7 @@ static json_t *janus_videoroom_process_synchronous_request(janus_videoroom_sessi json_t *desc = json_object_get(root, "description"); json_t *is_private = json_object_get(root, "is_private"); json_t *req_pvtid = json_object_get(root, "require_pvtid"); + json_t *signed_tokens = json_object_get(root, "signed_tokens"); json_t *req_e2ee = json_object_get(root, "require_e2ee"); json_t *secret = json_object_get(root, "secret"); json_t *pin = json_object_get(root, "pin"); @@ -3223,6 +3236,13 @@ static json_t *janus_videoroom_process_synchronous_request(janus_videoroom_sessi videoroom->room_name = description; videoroom->is_private = is_private ? json_is_true(is_private) : FALSE; videoroom->require_pvtid = req_pvtid ? json_is_true(req_pvtid) : FALSE; + if(signed_tokens && json_is_true(signed_tokens)) { + if(!gateway->auth_is_signed()) { + JANUS_LOG(LOG_WARN, "Can't enforce signed tokens for this room, signed-mode not in use in the core\n"); + } else { + videoroom->signed_tokens = TRUE; + } + } videoroom->require_e2ee = req_e2ee ? json_is_true(req_e2ee) : FALSE; if(secret) videoroom->room_secret = g_strdup(json_string_value(secret)); diff --git a/plugins/plugin.h b/plugins/plugin.h index 7794dd4923..70c5a1b61d 100644 --- a/plugins/plugin.h +++ b/plugins/plugin.h @@ -171,7 +171,7 @@ janus_plugin *create(void) { * Janus instance or it will crash. * */ -#define JANUS_PLUGIN_API_VERSION 15 +#define JANUS_PLUGIN_API_VERSION 16 /*! \brief Initialization of all plugin properties to NULL * @@ -412,6 +412,9 @@ struct janus_callbacks { * @param[in] event The event to notify as a Jansson json_t object */ void (* const notify_event)(janus_plugin *plugin, janus_plugin_session *handle, json_t *event); + /*! \brief Method to check whether the core is using signed tokens + * @returns TRUE if signed tokens are in use, FALSE otherwise */ + gboolean (* const auth_is_signed)(void); /*! \brief Method to check whether a signed token is valid * \note accepts only tokens with the plugin identifier as realm * @param[in] token The token to validate