mirror of
https://github.com/coturn/coturn.git
synced 2025-10-24 12:31:00 +02:00
working on multi-tenant server based upon oauth
This commit is contained in:
parent
a8ba79ff60
commit
dbc9dee42b
@ -1,6 +1,7 @@
|
||||
8/26/2015 Oleg Moskalenko <mom040267@gmail.com>
|
||||
Version 4.4.5.5 'Ardee West':
|
||||
- STUN attributes conflict resolution.
|
||||
9/13/2015 Oleg Moskalenko <mom040267@gmail.com>
|
||||
Version 4.5.0.0 'Ardee West':
|
||||
- multiple realms based on oAuth (third-party authorization);
|
||||
- STUN attributes conflict resolution;
|
||||
- SIGHUP handler fixed.
|
||||
|
||||
7/18/2015 Oleg Moskalenko <mom040267@gmail.com>
|
||||
|
||||
3
INSTALL
3
INSTALL
@ -744,6 +744,7 @@ CREATE TABLE oauth_key (
|
||||
timestamp bigint default 0,
|
||||
lifetime integer default 0,
|
||||
as_rs_alg varchar(64) default '',
|
||||
realm varchar(127) default '',
|
||||
primary key (kid)
|
||||
);
|
||||
|
||||
@ -763,6 +764,8 @@ The oauth_key table fields meanings are:
|
||||
"A256GCM", "A128GCM" (see
|
||||
http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#section-5.1).
|
||||
The default value is "A256GCM";
|
||||
|
||||
realm - (optional) can be used to set the user realm (if the field is not empty).
|
||||
|
||||
# Https access admin users.
|
||||
# Leave this table empty if you do not want
|
||||
|
||||
3
STATUS
3
STATUS
@ -123,6 +123,9 @@ supported in the client library).
|
||||
53) SHA384 and SHA512 support added (experimental).
|
||||
|
||||
54) native SCTP experimental support.
|
||||
|
||||
55) Multi-tenant implementation based upon third-party authorization
|
||||
(oAuth).
|
||||
|
||||
Things to be implemented in future (the development roadmap)
|
||||
are described in the TODO file.
|
||||
|
||||
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
.\" Text automatically generated by txt2man
|
||||
.TH TURN 1 "01 September 2015" "" ""
|
||||
.TH TURN 1 "13 September 2015" "" ""
|
||||
.SH GENERAL INFORMATION
|
||||
|
||||
\fIturnadmin\fP is a TURN administration tool. This tool can be used to manage
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
.\" Text automatically generated by txt2man
|
||||
.TH TURN 1 "01 September 2015" "" ""
|
||||
.TH TURN 1 "13 September 2015" "" ""
|
||||
.SH GENERAL INFORMATION
|
||||
|
||||
The \fBTURN Server\fP project contains the source code of a TURN server and TURN client
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
.\" Text automatically generated by txt2man
|
||||
.TH TURN 1 "01 September 2015" "" ""
|
||||
.TH TURN 1 "13 September 2015" "" ""
|
||||
.SH GENERAL INFORMATION
|
||||
|
||||
A set of turnutils_* programs provides some utility functionality to be used
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
# Common settings script.
|
||||
|
||||
TURNVERSION=4.4.5.5
|
||||
TURNVERSION=4.5.0.0
|
||||
BUILDDIR=~/rpmbuild
|
||||
ARCH=`uname -p`
|
||||
TURNSERVER_GIT_URL=https://github.com/coturn/coturn.git
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
Name: turnserver
|
||||
Version: 4.4.5.5
|
||||
Version: 4.5.0.0
|
||||
Release: 0%{dist}
|
||||
Summary: Coturn TURN Server
|
||||
|
||||
@ -289,8 +289,8 @@ fi
|
||||
%{_includedir}/turn/client/TurnMsgLib.h
|
||||
|
||||
%changelog
|
||||
* Wed Aug 26 2015 Oleg Moskalenko <mom040267@gmail.com>
|
||||
- Sync to 4.4.5.5
|
||||
* Sun Sep 13 2015 Oleg Moskalenko <mom040267@gmail.com>
|
||||
- Sync to 4.5.0.0
|
||||
* Sat Jul 18 2015 Oleg Moskalenko <mom040267@gmail.com>
|
||||
- Sync to 4.4.5.4
|
||||
* Sat Jun 20 2015 Oleg Moskalenko <mom040267@gmail.com>
|
||||
|
||||
@ -142,6 +142,7 @@ struct _oauth_key_data_raw {
|
||||
u64bits timestamp;
|
||||
u32bits lifetime;
|
||||
char as_rs_alg[OAUTH_ALG_SIZE+1];
|
||||
char realm[STUN_MAX_REALM_SIZE+1];
|
||||
};
|
||||
|
||||
typedef struct _oauth_key_data_raw oauth_key_data_raw;
|
||||
|
||||
@ -255,6 +255,7 @@ static int mongo_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
BSON_APPEND_INT32(&fields, "lifetime", 1);
|
||||
BSON_APPEND_INT32(&fields, "timestamp", 1);
|
||||
BSON_APPEND_INT32(&fields, "as_rs_alg", 1);
|
||||
BSON_APPEND_INT32(&fields, "realm", 1);
|
||||
BSON_APPEND_INT32(&fields, "ikm_key", 1);
|
||||
|
||||
mongoc_cursor_t * cursor;
|
||||
@ -277,6 +278,9 @@ static int mongo_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "as_rs_alg") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||
STRCPY(key->as_rs_alg,bson_iter_utf8(&iter, &length));
|
||||
}
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "realm") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||
STRCPY(key->realm,bson_iter_utf8(&iter, &length));
|
||||
}
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "ikm_key") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||
STRCPY(key->ikm_key,bson_iter_utf8(&iter, &length));
|
||||
}
|
||||
@ -341,6 +345,7 @@ static int mongo_set_oauth_key(oauth_key_data_raw *key) {
|
||||
bson_init(&doc);
|
||||
BSON_APPEND_UTF8(&doc, "kid", (const char *)key->kid);
|
||||
BSON_APPEND_UTF8(&doc, "as_rs_alg", (const char *)key->as_rs_alg);
|
||||
BSON_APPEND_UTF8(&doc, "realm", (const char *)key->realm);
|
||||
BSON_APPEND_UTF8(&doc, "ikm_key", (const char *)key->ikm_key);
|
||||
BSON_APPEND_INT64(&doc, "timestamp", (int64_t)key->timestamp);
|
||||
BSON_APPEND_INT32(&doc, "lifetime", (int32_t)key->lifetime);
|
||||
@ -477,7 +482,7 @@ static int mongo_list_users(u08bits *realm, secrets_list_t *users, secrets_list_
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts) {
|
||||
static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts,secrets_list_t *realms) {
|
||||
|
||||
const char * collection_name = "oauth_key";
|
||||
mongoc_collection_t * collection = mongo_get_collection(collection_name);
|
||||
@ -501,6 +506,7 @@ static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre
|
||||
BSON_APPEND_INT32(&fields, "lifetime", 1);
|
||||
BSON_APPEND_INT32(&fields, "timestamp", 1);
|
||||
BSON_APPEND_INT32(&fields, "as_rs_alg", 1);
|
||||
BSON_APPEND_INT32(&fields, "realm", 1);
|
||||
BSON_APPEND_INT32(&fields, "ikm_key", 1);
|
||||
|
||||
mongoc_cursor_t * cursor;
|
||||
@ -525,6 +531,9 @@ static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "as_rs_alg") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||
STRCPY(key->as_rs_alg,bson_iter_utf8(&iter, &length));
|
||||
}
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "realm") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||
STRCPY(key->realm,bson_iter_utf8(&iter, &length));
|
||||
}
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "ikm_key") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||
STRCPY(key->ikm_key,bson_iter_utf8(&iter, &length));
|
||||
}
|
||||
@ -537,6 +546,7 @@ static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre
|
||||
if(kids) {
|
||||
add_to_secrets_list(kids,key->kid);
|
||||
add_to_secrets_list(teas,key->as_rs_alg);
|
||||
add_to_secrets_list(realms,key->realm);
|
||||
{
|
||||
char ts[256];
|
||||
snprintf(ts,sizeof(ts)-1,"%llu",(unsigned long long)key->timestamp);
|
||||
@ -548,9 +558,9 @@ static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre
|
||||
add_to_secrets_list(lts,lt);
|
||||
}
|
||||
} else {
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s\n",
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, realm=%s\n",
|
||||
key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime,
|
||||
key->as_rs_alg);
|
||||
key->as_rs_alg, key->realm);
|
||||
}
|
||||
}
|
||||
mongoc_cursor_destroy(cursor);
|
||||
|
||||
@ -345,7 +345,7 @@ static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
/* direct user input eliminated - there is no SQL injection problem (since version 4.4.5.3) */
|
||||
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg from oauth_key where kid='%s'",(const char*)kid);
|
||||
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,realm from oauth_key where kid='%s'",(const char*)kid);
|
||||
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if(myc) {
|
||||
@ -356,7 +356,7 @@ static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
MYSQL_RES *mres = mysql_store_result(myc);
|
||||
if(!mres) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||
} else if(mysql_field_count(myc)!=4) {
|
||||
} else if(mysql_field_count(myc)!=5) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement);
|
||||
} else {
|
||||
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||
@ -380,6 +380,9 @@ static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
ns_bcopy(row[3],key->as_rs_alg,lengths[3]);
|
||||
key->as_rs_alg[lengths[3]]=0;
|
||||
|
||||
ns_bcopy(row[4],key->realm,lengths[4]);
|
||||
key->realm[lengths[4]]=0;
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
@ -392,13 +395,13 @@ static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts) {
|
||||
static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts,secrets_list_t *realms) {
|
||||
|
||||
oauth_key_data_raw key_;
|
||||
oauth_key_data_raw *key=&key_;
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,kid from oauth_key order by kid");
|
||||
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,realm,kid from oauth_key order by kid");
|
||||
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if(myc) {
|
||||
@ -409,7 +412,7 @@ static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre
|
||||
MYSQL_RES *mres = mysql_store_result(myc);
|
||||
if(!mres) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||
} else if(mysql_field_count(myc)!=5) {
|
||||
} else if(mysql_field_count(myc)!=6) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement);
|
||||
} else {
|
||||
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||
@ -433,12 +436,16 @@ static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre
|
||||
ns_bcopy(row[3],key->as_rs_alg,lengths[3]);
|
||||
key->as_rs_alg[lengths[3]]=0;
|
||||
|
||||
ns_bcopy(row[4],key->kid,lengths[4]);
|
||||
key->kid[lengths[4]]=0;
|
||||
ns_bcopy(row[4],key->realm,lengths[4]);
|
||||
key->realm[lengths[4]]=0;
|
||||
|
||||
ns_bcopy(row[5],key->kid,lengths[5]);
|
||||
key->kid[lengths[5]]=0;
|
||||
|
||||
if(kids) {
|
||||
add_to_secrets_list(kids,key->kid);
|
||||
add_to_secrets_list(teas,key->as_rs_alg);
|
||||
add_to_secrets_list(realms,key->realm);
|
||||
{
|
||||
char ts[256];
|
||||
snprintf(ts,sizeof(ts)-1,"%llu",(unsigned long long)key->timestamp);
|
||||
@ -450,9 +457,9 @@ static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre
|
||||
add_to_secrets_list(lts,lt);
|
||||
}
|
||||
} else {
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s\n",
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, realm=%s\n",
|
||||
key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime,
|
||||
key->as_rs_alg);
|
||||
key->as_rs_alg,key->realm);
|
||||
}
|
||||
}
|
||||
row = mysql_fetch_row(mres);
|
||||
@ -496,13 +503,13 @@ static int mysql_set_oauth_key(oauth_key_data_raw *key)
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if(myc) {
|
||||
snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg) values('%s','%s',%llu,%lu,'%s')",
|
||||
snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,realm) values('%s','%s',%llu,%lu,'%s','%s')",
|
||||
key->kid,key->ikm_key,(unsigned long long)key->timestamp,(unsigned long)key->lifetime,
|
||||
key->as_rs_alg);
|
||||
key->as_rs_alg,key->realm);
|
||||
int res = mysql_query(myc, statement);
|
||||
if(res) {
|
||||
snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, as_rs_alg='%s' where kid='%s'",key->ikm_key,(unsigned long)key->timestamp,(unsigned long)key->lifetime,
|
||||
key->as_rs_alg,key->kid);
|
||||
snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, as_rs_alg='%s', realm='%s' where kid='%s'",key->ikm_key,(unsigned long)key->timestamp,(unsigned long)key->lifetime,
|
||||
key->as_rs_alg,key->realm,key->kid);
|
||||
res = mysql_query(myc, statement);
|
||||
if(res) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating oauth key information: %s\n",mysql_error(myc));
|
||||
|
||||
@ -160,7 +160,7 @@ static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
/* direct user input eliminated - there is no SQL injection problem (since version 4.4.5.3) */
|
||||
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg from oauth_key where kid='%s'",(const char*)kid);
|
||||
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,realm from oauth_key where kid='%s'",(const char*)kid);
|
||||
|
||||
PGconn * pqc = get_pqdb_connection();
|
||||
if(pqc) {
|
||||
@ -173,6 +173,7 @@ static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
key->timestamp = (u64bits)strtoll(PQgetvalue(res,0,1),NULL,10);
|
||||
key->lifetime = (u32bits)strtol(PQgetvalue(res,0,2),NULL,10);
|
||||
STRCPY(key->as_rs_alg,PQgetvalue(res,0,3));
|
||||
STRCPY(key->realm,PQgetvalue(res,0,4));
|
||||
STRCPY(key->kid,kid);
|
||||
ret = 0;
|
||||
}
|
||||
@ -185,7 +186,7 @@ static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts) {
|
||||
static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts,secrets_list_t *realms) {
|
||||
|
||||
oauth_key_data_raw key_;
|
||||
oauth_key_data_raw *key=&key_;
|
||||
@ -193,7 +194,7 @@ static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre
|
||||
int ret = -1;
|
||||
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,kid from oauth_key order by kid");
|
||||
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,realm,kid from oauth_key order by kid");
|
||||
|
||||
PGconn * pqc = get_pqdb_connection();
|
||||
if(pqc) {
|
||||
@ -209,11 +210,13 @@ static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre
|
||||
key->timestamp = (u64bits)strtoll(PQgetvalue(res,i,1),NULL,10);
|
||||
key->lifetime = (u32bits)strtol(PQgetvalue(res,i,2),NULL,10);
|
||||
STRCPY(key->as_rs_alg,PQgetvalue(res,i,3));
|
||||
STRCPY(key->kid,PQgetvalue(res,i,4));
|
||||
STRCPY(key->realm,PQgetvalue(res,i,4));
|
||||
STRCPY(key->kid,PQgetvalue(res,i,5));
|
||||
|
||||
if(kids) {
|
||||
add_to_secrets_list(kids,key->kid);
|
||||
add_to_secrets_list(teas,key->as_rs_alg);
|
||||
add_to_secrets_list(realms,key->realm);
|
||||
{
|
||||
char ts[256];
|
||||
snprintf(ts,sizeof(ts)-1,"%llu",(unsigned long long)key->timestamp);
|
||||
@ -225,9 +228,9 @@ static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre
|
||||
add_to_secrets_list(lts,lt);
|
||||
}
|
||||
} else {
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s\n",
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, realm=%s\n",
|
||||
key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime,
|
||||
key->as_rs_alg);
|
||||
key->as_rs_alg,key->realm);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
@ -275,17 +278,17 @@ static int pgsql_set_oauth_key(oauth_key_data_raw *key) {
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
PGconn *pqc = get_pqdb_connection();
|
||||
if(pqc) {
|
||||
snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg) values('%s','%s',%llu,%lu,'%s')",
|
||||
snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,realm) values('%s','%s',%llu,%lu,'%s','%s')",
|
||||
key->kid,key->ikm_key,(unsigned long long)key->timestamp,(unsigned long)key->lifetime,
|
||||
key->as_rs_alg);
|
||||
key->as_rs_alg,key->realm);
|
||||
|
||||
PGresult *res = PQexec(pqc, statement);
|
||||
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||
if(res) {
|
||||
PQclear(res);
|
||||
}
|
||||
snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, as_rs_alg='%s' where kid='%s'",key->ikm_key,(unsigned long)key->timestamp,(unsigned long)key->lifetime,
|
||||
key->as_rs_alg,key->kid);
|
||||
snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, as_rs_alg='%s', realm='%s' where kid='%s'",key->ikm_key,(unsigned long)key->timestamp,(unsigned long)key->lifetime,
|
||||
key->as_rs_alg,key->realm,key->kid);
|
||||
res = PQexec(pqc, statement);
|
||||
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating oauth_key information: %s\n",PQerrorMessage(pqc));
|
||||
|
||||
@ -477,6 +477,8 @@ static int redis_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
if(kw) {
|
||||
if(!strcmp(kw,"as_rs_alg")) {
|
||||
STRCPY(key->as_rs_alg,val);
|
||||
} else if(!strcmp(kw,"realm")) {
|
||||
STRCPY(key->realm,val);
|
||||
} else if(!strcmp(kw,"ikm_key")) {
|
||||
STRCPY(key->ikm_key,val);
|
||||
} else if(!strcmp(kw,"timestamp")) {
|
||||
@ -512,8 +514,8 @@ static int redis_set_oauth_key(oauth_key_data_raw *key) {
|
||||
redisContext *rc = get_redis_connection();
|
||||
if(rc) {
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
snprintf(statement,sizeof(statement),"hmset turn/oauth/kid/%s ikm_key %s as_rs_alg %s timestamp %llu lifetime %lu",
|
||||
key->kid,key->ikm_key,key->as_rs_alg,(unsigned long long)key->timestamp,(unsigned long)key->lifetime);
|
||||
snprintf(statement,sizeof(statement),"hmset turn/oauth/kid/%s ikm_key %s as_rs_alg %s timestamp %llu lifetime %lu realm %s",
|
||||
key->kid,key->ikm_key,key->as_rs_alg,(unsigned long long)key->timestamp,(unsigned long)key->lifetime,key->realm);
|
||||
turnFreeRedisReply(redisCommand(rc, statement));
|
||||
turnFreeRedisReply(redisCommand(rc, "save"));
|
||||
ret = 0;
|
||||
@ -629,7 +631,7 @@ static int redis_list_users(u08bits *realm, secrets_list_t *users, secrets_list_
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int redis_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts) {
|
||||
static int redis_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts,secrets_list_t *realms) {
|
||||
int ret = -1;
|
||||
redisContext *rc = get_redis_connection();
|
||||
secrets_list_t keys;
|
||||
@ -668,6 +670,7 @@ static int redis_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre
|
||||
if(kids) {
|
||||
add_to_secrets_list(kids,key->kid);
|
||||
add_to_secrets_list(teas,key->as_rs_alg);
|
||||
add_to_secrets_list(realms,key->realm);
|
||||
{
|
||||
char ts[256];
|
||||
snprintf(ts,sizeof(ts)-1,"%llu",(unsigned long long)key->timestamp);
|
||||
@ -679,9 +682,9 @@ static int redis_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre
|
||||
add_to_secrets_list(lts,lt);
|
||||
}
|
||||
} else {
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s\n",
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, realm=%s\n",
|
||||
key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime,
|
||||
key->as_rs_alg);
|
||||
key->as_rs_alg,key->realm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,7 +157,7 @@ static void init_sqlite_database(sqlite3 *sqliteconnection) {
|
||||
"CREATE TABLE denied_peer_ip (realm varchar(127) default '', ip_range varchar(256), primary key (realm,ip_range))",
|
||||
"CREATE TABLE turn_origin_to_realm (origin varchar(127),realm varchar(127),primary key (origin))",
|
||||
"CREATE TABLE turn_realm_option (realm varchar(127) default '', opt varchar(32), value varchar(128), primary key (realm,opt))",
|
||||
"CREATE TABLE oauth_key (kid varchar(128),ikm_key varchar(256),timestamp bigint default 0,lifetime integer default 0,as_rs_alg varchar(64) default '',primary key (kid))",
|
||||
"CREATE TABLE oauth_key (kid varchar(128),ikm_key varchar(256),timestamp bigint default 0,lifetime integer default 0,as_rs_alg varchar(64) default '',realm varchar(127) default '',primary key (kid))",
|
||||
"CREATE TABLE admin_user (name varchar(32), realm varchar(127), password varchar(127), primary key (name))",
|
||||
NULL
|
||||
};
|
||||
@ -299,7 +299,7 @@ static int sqlite_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
int rc = 0;
|
||||
|
||||
/* direct user input eliminated - there is no SQL injection problem (since version 4.4.5.3) */
|
||||
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg from oauth_key where kid='%s'",(const char*)kid);
|
||||
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,realm from oauth_key where kid='%s'",(const char*)kid);
|
||||
|
||||
sqlite3 *sqliteconnection = get_sqlite_connection();
|
||||
if(sqliteconnection) {
|
||||
@ -315,6 +315,7 @@ static int sqlite_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
key->timestamp = (u64bits)strtoll((const char*)sqlite3_column_text(st, 1),NULL,10);
|
||||
key->lifetime = (u32bits)strtol((const char*)sqlite3_column_text(st, 2),NULL,10);
|
||||
STRCPY(key->as_rs_alg,sqlite3_column_text(st, 3));
|
||||
STRCPY(key->realm,sqlite3_column_text(st, 4));
|
||||
STRCPY(key->kid,kid);
|
||||
ret = 0;
|
||||
}
|
||||
@ -331,7 +332,7 @@ static int sqlite_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sqlite_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts) {
|
||||
static int sqlite_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts,secrets_list_t *realms) {
|
||||
|
||||
oauth_key_data_raw key_;
|
||||
oauth_key_data_raw *key=&key_;
|
||||
@ -343,7 +344,7 @@ static int sqlite_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secr
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
sqlite3_stmt *st = NULL;
|
||||
int rc = 0;
|
||||
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,kid from oauth_key order by kid");
|
||||
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,realm,kid from oauth_key order by kid");
|
||||
|
||||
sqlite3 *sqliteconnection = get_sqlite_connection();
|
||||
if(sqliteconnection) {
|
||||
@ -361,11 +362,13 @@ static int sqlite_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secr
|
||||
key->timestamp = (u64bits)strtoll((const char*)sqlite3_column_text(st, 1),NULL,10);
|
||||
key->lifetime = (u32bits)strtol((const char*)sqlite3_column_text(st, 2),NULL,10);
|
||||
STRCPY(key->as_rs_alg,sqlite3_column_text(st, 3));
|
||||
STRCPY(key->kid,sqlite3_column_text(st, 4));
|
||||
STRCPY(key->realm,sqlite3_column_text(st, 4));
|
||||
STRCPY(key->kid,sqlite3_column_text(st, 5));
|
||||
|
||||
if(kids) {
|
||||
add_to_secrets_list(kids,key->kid);
|
||||
add_to_secrets_list(teas,key->as_rs_alg);
|
||||
add_to_secrets_list(realms,key->realm);
|
||||
{
|
||||
char ts[256];
|
||||
snprintf(ts,sizeof(ts)-1,"%llu",(unsigned long long)key->timestamp);
|
||||
@ -449,8 +452,8 @@ static int sqlite_set_oauth_key(oauth_key_data_raw *key)
|
||||
snprintf(
|
||||
statement,
|
||||
sizeof(statement),
|
||||
"insert or replace into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg) values('%s','%s',%llu,%lu,'%s')",
|
||||
key->kid, key->ikm_key, (unsigned long long) key->timestamp, (unsigned long) key->lifetime, key->as_rs_alg);
|
||||
"insert or replace into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,realm) values('%s','%s',%llu,%lu,'%s','%s')",
|
||||
key->kid, key->ikm_key, (unsigned long long) key->timestamp, (unsigned long) key->lifetime, key->as_rs_alg, key->realm);
|
||||
|
||||
sqlite_lock(1);
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@ typedef struct _turn_dbdriver_t {
|
||||
int (*set_oauth_key)(oauth_key_data_raw *key);
|
||||
int (*get_oauth_key)(const u08bits *kid, oauth_key_data_raw *key);
|
||||
int (*del_oauth_key)(const u08bits *kid);
|
||||
int (*list_oauth_keys)(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts);
|
||||
int (*list_oauth_keys)(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts,secrets_list_t *realms);
|
||||
int (*get_admin_user)(const u08bits *usname, u08bits *realm, password_t pwd);
|
||||
int (*set_admin_user)(const u08bits *usname, const u08bits *realm, const password_t pwd);
|
||||
int (*del_admin_user)(const u08bits *usname);
|
||||
|
||||
@ -2773,12 +2773,13 @@ static size_t https_print_oauth_keys(struct str_buffer* sb)
|
||||
size_t ret = 0;
|
||||
const turn_dbdriver_t * dbd = get_dbdriver();
|
||||
if (dbd && dbd->list_oauth_keys) {
|
||||
secrets_list_t kids,teas,tss,lts;
|
||||
secrets_list_t kids,teas,tss,lts,realms;
|
||||
init_secrets_list(&kids);
|
||||
init_secrets_list(&teas);
|
||||
init_secrets_list(&tss);
|
||||
init_secrets_list(<s);
|
||||
dbd->list_oauth_keys(&kids,&teas,&tss,<s);
|
||||
init_secrets_list(&realms);
|
||||
dbd->list_oauth_keys(&kids,&teas,&tss,<s,&realms);
|
||||
|
||||
size_t sz = get_secrets_list_size(&kids);
|
||||
size_t i;
|
||||
@ -2824,6 +2825,9 @@ static size_t https_print_oauth_keys(struct str_buffer* sb)
|
||||
|
||||
clean_secrets_list(&kids);
|
||||
clean_secrets_list(&teas);
|
||||
clean_secrets_list(&tss);
|
||||
clean_secrets_list(<s);
|
||||
clean_secrets_list(&realms);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@ -102,9 +102,9 @@ int oauth = 0;
|
||||
oauth_key okey_array[3];
|
||||
|
||||
static oauth_key_data_raw okdr_array[3] = {
|
||||
{"north","MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEK",0,0,"A256GCM"},
|
||||
{"union","MTIzNDU2Nzg5MDEyMzQ1Ngo=",0,0,"A128GCM"},
|
||||
{"oldempire","MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIK",0,0,"A256GCM"}
|
||||
{"north","MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEK",0,0,"A256GCM","crinna.org"},
|
||||
{"union","MTIzNDU2Nzg5MDEyMzQ1Ngo=",0,0,"A128GCM","north.gov"},
|
||||
{"oldempire","MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIK",0,0,"A256GCM",""}
|
||||
};
|
||||
|
||||
//////////////// local definitions /////////////////
|
||||
@ -137,7 +137,7 @@ static char Usage[] =
|
||||
" -G Generate extra requests (create permissions, channel bind).\n"
|
||||
" -B Random disconnect after a few initial packets.\n"
|
||||
" -Z Dual allocation (implies -c).\n"
|
||||
" -J Use oAuth with default test key kid='north' or 'oldempire'.\n"
|
||||
" -J Use oAuth with default test keys kid='north', 'union' or 'oldempire'.\n"
|
||||
"Options:\n"
|
||||
" -l Message length (Default: 100 Bytes).\n"
|
||||
" -i Certificate file (for secure connections only, optional).\n"
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
#ifndef __IOADEFS__
|
||||
#define __IOADEFS__
|
||||
|
||||
#define TURN_SERVER_VERSION "4.4.5.5"
|
||||
#define TURN_SERVER_VERSION "4.5.0.0"
|
||||
#define TURN_SERVER_VERSION_NAME "Ardee West"
|
||||
#define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'"
|
||||
|
||||
|
||||
@ -43,6 +43,7 @@ CREATE TABLE oauth_key (
|
||||
timestamp bigint default 0,
|
||||
lifetime integer default 0,
|
||||
as_rs_alg varchar(64) default '',
|
||||
realm varchar(127),
|
||||
primary key (kid)
|
||||
);
|
||||
|
||||
|
||||
@ -46,6 +46,9 @@ and they will be almost immediately "seen" by the turnserver process.
|
||||
"A256GCM", "A128GCM" (see
|
||||
http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#section-5.1).
|
||||
The default value is "A256GCM".
|
||||
|
||||
realm - optionally, a kid can be assigned to a realm that is different
|
||||
from the default realm.
|
||||
|
||||
5) admin users (over https interface) are maintained as keys of form:
|
||||
"turn/admin_user/<username> with hash members "password" and,
|
||||
@ -54,15 +57,21 @@ optionally, "realm".
|
||||
II. Extra realms data in the database
|
||||
|
||||
We can use more than one realm with the same instance of the TURN server.
|
||||
This is done through the ORIGIN mechanism - users with different ORIGINS
|
||||
are placed into different realms. The database includes information about the
|
||||
relationships between the ORIGIN and realms, and about the extra realms
|
||||
database numbers.
|
||||
This is done in two ways:
|
||||
|
||||
1) through the third-party authentication option. An oAuth kid can be optionally
|
||||
assigned to a realm. When the user provides kid, and the database record
|
||||
for that kid contains a non-empty non-default realm, then the user is treated
|
||||
as belonging to that realm.
|
||||
2) the ORIGIN mechanism - users with different ORIGINS
|
||||
are placed into different realms. The database includes information about the
|
||||
relationships between the ORIGIN and realms, and about the extra realms
|
||||
database numbers.
|
||||
The relationship between ORIGIN and realm is set as keys of form:
|
||||
"turn/origin/<origin>" with the realm-names as the value. Many different
|
||||
ORIGIN keys may have the same realm. If the ORIGIN value is not found in
|
||||
the database or the ORIGIN field is missed in the initial allocate
|
||||
request, then the default realm is assumed.
|
||||
"turn/origin/<origin>" with the realm-names as the value. Many different
|
||||
ORIGIN keys may have the same realm. If the ORIGIN value is not found in
|
||||
the database or the ORIGIN field is missed in the initial allocate
|
||||
request, then the default realm is assumed.
|
||||
|
||||
III) Example of a Redis default user database setup.
|
||||
|
||||
@ -82,7 +91,7 @@ This example sets user database for:
|
||||
"total_quota" and "user_quota" (same names as the turnserver
|
||||
configuration options, with the same meanings).
|
||||
* The oAuth data for the key with kid "oldempire" and key value
|
||||
"12345678901234567890123456789012".
|
||||
"12345678901234567890123456789012", and default realm.
|
||||
* The admin user 'skarling', realm 'north.gov', with password 'hoodless';
|
||||
* The global admin user 'bayaz' with password 'magi';
|
||||
|
||||
|
||||
@ -28,8 +28,8 @@ db.turn_secret.insert({ realm: 'north.gov', value: 'bloody9' });
|
||||
db.turn_secret.insert({ realm: 'crinna.org', value: 'north' });
|
||||
db.turn_secret.insert({ realm: 'crinna.org', value: 'library' });
|
||||
|
||||
db.admin_user.insert({ name: 'skarling', realm: 'north.gov', password: '$5$6fc35c3b0c7d4633$27fca7574f9b79d0cb93ae03e45379470cbbdfcacdd6401f97ebc620f31f54f2' });
|
||||
db.admin_user.insert({ name: 'bayaz', realm: '', password: '$5$e018513e9de69e73$5cbdd2e29e04ca46aeb022268a7460d3a3468de193dcb2b95f064901769f455f' });
|
||||
db.admin_user.insert({ name: 'skarling', realm: 'north.gov', password: '\$5\$6fc35c3b0c7d4633\$27fca7574f9b79d0cb93ae03e45379470cbbdfcacdd6401f97ebc620f31f54f2' });
|
||||
db.admin_user.insert({ name: 'bayaz', realm: '', password: '\$5\$e018513e9de69e73\$5cbdd2e29e04ca46aeb022268a7460d3a3468de193dcb2b95f064901769f455f' });
|
||||
|
||||
db.realm.insert({
|
||||
realm: 'north.gov',
|
||||
@ -56,10 +56,12 @@ db.realm.insert({
|
||||
|
||||
db.oauth_key.insert({ kid: 'north',
|
||||
ikm_key: 'MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEK',
|
||||
as_rs_alg: 'A256GCM'});
|
||||
as_rs_alg: 'A256GCM',
|
||||
realm: 'crinna.org'});
|
||||
db.oauth_key.insert({ kid: 'union',
|
||||
ikm_key: 'MTIzNDU2Nzg5MDEyMzQ1Ngo=',
|
||||
as_rs_alg: 'A128GCM'});
|
||||
as_rs_alg: 'A128GCM',
|
||||
realm: 'north.gov'});
|
||||
db.oauth_key.insert({ kid: 'oldempire',
|
||||
ikm_key: 'MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIK',
|
||||
as_rs_alg: 'A256GCM'});
|
||||
|
||||
@ -38,8 +38,8 @@ sadd turn/realm/crinna.org/allowed-peer-ip "172.17.13.202"
|
||||
sadd turn/realm/north.gov/denied-peer-ip "172.17.13.133-172.17.14.56" "172.17.17.133-172.17.19.56" "123::45"
|
||||
sadd turn/realm/crinna.org/denied-peer-ip "123::77"
|
||||
|
||||
hmset turn/oauth/kid/north ikm_key 'MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEK' as_rs_alg 'A256GCM'
|
||||
hmset turn/oauth/kid/union ikm_key 'MTIzNDU2Nzg5MDEyMzQ1Ngo=' as_rs_alg 'A128GCM'
|
||||
hmset turn/oauth/kid/north ikm_key 'MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEK' as_rs_alg 'A256GCM' realm 'crinna.org'
|
||||
hmset turn/oauth/kid/union ikm_key 'MTIzNDU2Nzg5MDEyMzQ1Ngo=' as_rs_alg 'A128GCM' realm 'north.gov'
|
||||
hmset turn/oauth/kid/oldempire ikm_key 'MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIK' as_rs_alg 'A256GCM'
|
||||
|
||||
hmset turn/admin_user/skarling realm 'north.gov' password '\$5\$6fc35c3b0c7d4633\$27fca7574f9b79d0cb93ae03e45379470cbbdfcacdd6401f97ebc620f31f54f2'
|
||||
|
||||
@ -31,6 +31,6 @@ insert into denied_peer_ip (ip_range) values('123::45');
|
||||
insert into denied_peer_ip (realm,ip_range) values('north.gov','172.17.17.133-172.17.19.56');
|
||||
insert into denied_peer_ip (realm,ip_range) values('crinna.org','123::77');
|
||||
|
||||
insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg) values('north','MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEK',0,0,'A256GCM');
|
||||
insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg) values('union','MTIzNDU2Nzg5MDEyMzQ1Ngo=',0,0,'A128GCM');
|
||||
insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg) values('oldempire','MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIK',0,0,'A256GCM');
|
||||
insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,realm) values('north','MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEK',0,0,'A256GCM','crinna.org');
|
||||
insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,realm) values('union','MTIzNDU2Nzg5MDEyMzQ1Ngo=',0,0,'A128GCM','north.gov');
|
||||
insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,realm) values('oldempire','MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIK',0,0,'A256GCM','');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user