Skip to content

Commit

Permalink
working on multi-tenant server based upon oauth
Browse files Browse the repository at this point in the history
  • Loading branch information
mom040267 committed Sep 14, 2015
1 parent a8ba79f commit dbc9dee
Show file tree
Hide file tree
Showing 24 changed files with 124 additions and 74 deletions.
7 changes: 4 additions & 3 deletions ChangeLog
@@ -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>
Expand Down
3 changes: 3 additions & 0 deletions INSTALL
Expand Up @@ -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)
);

Expand All @@ -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
Expand Down
3 changes: 3 additions & 0 deletions STATUS
Expand Up @@ -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 modified examples/var/db/turndb
Binary file not shown.
2 changes: 1 addition & 1 deletion man/man1/turnadmin.1
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion man/man1/turnserver.1
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion man/man1/turnutils.1
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion rpm/build.settings.sh
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions rpm/turnserver.spec
@@ -1,5 +1,5 @@
Name: turnserver
Version: 4.4.5.5
Version: 4.5.0.0
Release: 0%{dist}
Summary: Coturn TURN Server

Expand Down Expand Up @@ -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>
Expand Down
1 change: 1 addition & 0 deletions src/apps/common/apputils.h
Expand Up @@ -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;
Expand Down
16 changes: 13 additions & 3 deletions src/apps/relay/dbdrivers/dbd_mongo.c
Expand Up @@ -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;
Expand All @@ -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));
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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));
}
Expand All @@ -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);
Expand All @@ -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);
Expand Down
33 changes: 20 additions & 13 deletions src/apps/relay/dbdrivers/dbd_mysql.c
Expand Up @@ -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) {
Expand All @@ -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);
Expand All @@ -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;
}
}
Expand All @@ -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) {
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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));
Expand Down
23 changes: 13 additions & 10 deletions src/apps/relay/dbdrivers/dbd_pgsql.c
Expand Up @@ -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) {
Expand All @@ -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;
}
Expand All @@ -185,15 +186,15 @@ 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_;

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) {
Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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));
Expand Down

0 comments on commit dbc9dee

Please sign in to comment.