Skip to content

Commit 0a46f6e

Browse files
authored
Adding support for HMAC-SHA256 for signed_tokens (see #3648) (#3658)
1 parent eb04207 commit 0a46f6e

5 files changed

Lines changed: 37 additions & 11 deletions

File tree

conf/janus.jcfg.sample.in

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,12 @@ general: {
6363
# a valid token in all requests. Useful if
6464
# you want to authenticate requests from web
6565
# users.
66-
#token_auth_secret = "janus" # Use HMAC-SHA1 signed tokens (with token_auth). Note that
66+
#token_auth_secret = "janus" # Use HMAC signed tokens (with token_auth). Note that
6767
# without this, the Admin API MUST
6868
# be enabled, as tokens are added and removed
6969
# through messages sent there.
70+
#token_auth_hash = "sha1" # Hash function used for signed-token authentication.
71+
# Defaults to sha1. Supported values: sha1, sha256.
7072
admin_secret = "janusoverlord" # String that all Janus requests must contain
7173
# to be accepted/authorized by the admin/monitor.
7274
# only needed if you enabled the admin API

src/auth.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,27 +38,38 @@ static GHashTable *tokens = NULL, *allowed_plugins = NULL;
3838
static gboolean auth_enabled = FALSE;
3939
static janus_mutex mutex = JANUS_MUTEX_INITIALIZER;
4040
static char *auth_secret = NULL;
41+
static const EVP_MD *auth_hash = NULL;
4142

4243
static void janus_auth_free_token(char *token) {
4344
g_free(token);
4445
}
4546

4647
/* Setup */
47-
void janus_auth_init(gboolean enabled, const char *secret) {
48+
int janus_auth_init(gboolean enabled, const char *secret, const char *hash) {
4849
if(enabled) {
4950
if(secret == NULL) {
5051
JANUS_LOG(LOG_INFO, "Stored-Token based authentication enabled\n");
5152
tokens = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)janus_auth_free_token, NULL);
5253
allowed_plugins = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)janus_auth_free_token, NULL);
5354
auth_enabled = TRUE;
5455
} else {
55-
JANUS_LOG(LOG_INFO, "Signed-Token based authentication enabled\n");
56+
if(hash == NULL || !strcasecmp(hash, "sha1")) {
57+
auth_hash = EVP_sha1();
58+
} else if(!strcasecmp(hash, "sha256")) {
59+
auth_hash = EVP_sha256();
60+
} else {
61+
JANUS_LOG(LOG_ERR, "Unsupported token_auth_hash '%s' (supported values: sha1, sha256)\n", hash);
62+
return -1;
63+
}
64+
JANUS_LOG(LOG_INFO, "Signed-Token based authentication enabled (HMAC-%s)\n",
65+
auth_hash == EVP_sha256() ? "SHA256" : "SHA1");
5666
auth_secret = g_strdup(secret);
5767
auth_enabled = TRUE;
5868
}
5969
} else {
6070
JANUS_LOG(LOG_INFO, "Token based authentication disabled\n");
6171
}
72+
return 0;
6273
}
6374

6475
gboolean janus_auth_is_enabled(void) {
@@ -106,10 +117,10 @@ gboolean janus_auth_check_signature(const char *token, const char *realm) {
106117
/* Verify realm */
107118
if(strcmp(data[1], realm))
108119
goto fail;
109-
/* Verify HMAC-SHA1 */
120+
/* Verify HMAC signature */
110121
unsigned char signature[EVP_MAX_MD_SIZE] = "";
111122
unsigned int len;
112-
HMAC(EVP_sha1(), auth_secret, strlen(auth_secret), (const unsigned char*)parts[0], strlen(parts[0]), signature, &len);
123+
HMAC(auth_hash, auth_secret, strlen(auth_secret), (const unsigned char*)parts[0], strlen(parts[0]), signature, &len);
113124
gchar *base64 = g_base64_encode(signature, len);
114125
gboolean result = janus_strcmp_const_time(parts[1], base64);
115126
g_strfreev(data);
@@ -157,10 +168,10 @@ gboolean janus_auth_check_signature_contains(const char *token, const char *real
157168
}
158169
if (!result)
159170
goto fail;
160-
/* Verify HMAC-SHA1 */
171+
/* Verify HMAC signature */
161172
unsigned char signature[EVP_MAX_MD_SIZE] = "";
162173
unsigned int len;
163-
HMAC(EVP_sha1(), auth_secret, strlen(auth_secret), (const unsigned char*)parts[0], strlen(parts[0]), signature, &len);
174+
HMAC(auth_hash, auth_secret, strlen(auth_secret), (const unsigned char*)parts[0], strlen(parts[0]), signature, &len);
164175
gchar *base64 = g_base64_encode(signature, len);
165176
result = janus_strcmp_const_time(parts[1], base64);
166177
g_strfreev(data);

src/auth.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@
2424

2525
/*! \brief Method to initializing the token based authentication
2626
* @param[in] enabled Whether the authentication mechanism should be enabled or not
27-
* @param[in] secret the secret to validate signed tokens against, or NULL to use stored tokens */
28-
void janus_auth_init(gboolean enabled, const char *secret);
27+
* @param[in] secret the secret to validate signed tokens against, or NULL to use stored tokens
28+
* @param[in] hash the hash function to use for signed tokens (sha1 or sha256), or NULL for the default sha1;
29+
* @returns 0 on success, or a negative integer otherwise */
30+
int janus_auth_init(gboolean enabled, const char *secret, const char *hash);
2931
/*! \brief Method to check whether the mechanism is enabled or not */
3032
gboolean janus_auth_is_enabled(void);
3133
/*! \brief Method to check whether the mechanism is in stored-token mode or not */

src/janus.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5126,7 +5126,14 @@ gint main(int argc, char *argv[]) {
51265126
const char *auth_secret = NULL;
51275127
if (item && item->value)
51285128
auth_secret = item->value;
5129-
janus_auth_init(auth_enabled, auth_secret);
5129+
item = janus_config_get(config, config_general, janus_config_type_item, "token_auth_hash");
5130+
const char *auth_hash = NULL;
5131+
if (item && item->value)
5132+
auth_hash = item->value;
5133+
if(janus_auth_init(auth_enabled, auth_secret, auth_hash) < 0) {
5134+
janus_options_destroy();
5135+
exit(1);
5136+
}
51305137

51315138
/* Check if opaque IDs should be sent back in the Janus API too */
51325139
item = janus_config_get(config, config_general, janus_config_type_item, "opaqueid_in_api");

src/mainpage.dox

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2183,9 +2183,13 @@ var websocket = new WebSocket('ws://1.2.3.4:8188', 'janus-protocol');
21832183
* Where \c timestamp is a UNIX timestamp (seconds since 0:00 UTC, 1.1.1970)
21842184
* that marks the point in time at which the token expires;
21852185
* \c plugin1 etc. are the \c bundle names of plugins (such as \c janus.plugin.videoroom);
2186-
* and \c signature is the base64-encoded HMAC-SHA1 signature of the expiry
2186+
* and \c signature is the base64-encoded HMAC signature of the expiry
21872187
* timestamp in ASCII format, hashed using the \c --token-auth-secret as a key.
21882188
*
2189+
* Signed tokens use HMAC-SHA1 by default. The hash function can be changed
2190+
* with \c token_auth_hash in the \c general section of \c janus.jcfg;
2191+
* supported values are \c sha1 and \c sha256.
2192+
*
21892193
* The following function can be used to sign tokens using the node.js crypto library:
21902194
*
21912195
\verbatim

0 commit comments

Comments
 (0)