From d4bc5ecf232498fce2596e388c2cbf568ce6de69 Mon Sep 17 00:00:00 2001 From: Oleg Moskalenko Date: Sun, 20 Sep 2015 21:57:38 -0700 Subject: [PATCH] Imported Upstream version 4.5.0.1 --- ChangeLog | 8 ++++ INSTALL | 37 ++++++++++++----- README.md | 11 ++++-- README.turnserver | 2 +- STATUS | 3 ++ examples/var/db/turndb | Bin 22528 -> 22528 bytes man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 4 +- man/man1/turnutils.1 | 2 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +- src/apps/common/apputils.h | 1 + src/apps/common/ns_turn_utils.c | 10 ++++- src/apps/relay/dbdrivers/dbd_mongo.c | 16 ++++++-- src/apps/relay/dbdrivers/dbd_mysql.c | 33 ++++++++++------ src/apps/relay/dbdrivers/dbd_pgsql.c | 23 ++++++----- src/apps/relay/dbdrivers/dbd_redis.c | 13 +++--- src/apps/relay/dbdrivers/dbd_sqlite.c | 17 ++++---- src/apps/relay/dbdrivers/dbdriver.h | 2 +- src/apps/relay/netengine.c | 2 +- src/apps/relay/ns_ioalib_engine_impl.c | 38 +----------------- src/apps/relay/ns_ioalib_impl.h | 2 - src/apps/relay/turn_admin_server.c | 44 +++++++++++++++++---- src/apps/relay/userdb.c | 4 ++ src/apps/uclient/mainuclient.c | 8 ++-- src/client/ns_turn_msg_defs.h | 6 --- src/client/ns_turn_msg_defs_experimental.h | 5 +++ src/ns_turn_defs.h | 4 +- src/server/ns_turn_ioalib.h | 4 +- src/server/ns_turn_maps.c | 4 +- src/server/ns_turn_maps_rtcp.c | 8 +--- src/server/ns_turn_maps_rtcp.h | 2 +- src/server/ns_turn_server.c | 31 +++++++++------ src/server/ns_turn_server.h | 2 +- turndb/schema.sql | 1 + turndb/schema.userdb.redis | 27 ++++++++----- turndb/testmongosetup.sh | 10 +++-- turndb/testredisdbsetup.sh | 4 +- turndb/testsqldbsetup.sql | 6 +-- 39 files changed, 239 insertions(+), 163 deletions(-) diff --git a/ChangeLog b/ChangeLog index 819173ef..d6988ed9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +9/13/2015 Oleg Moskalenko +Version 4.5.0.1 'dan Eider': + - multiple realms based on oAuth (third-party authorization); + - STUN attributes conflict resolution; + - SIGHUP handler fixed; + - error message logging improved; + - mongo test db files fixed. + 7/18/2015 Oleg Moskalenko Version 4.4.5.4 'Ardee West': - moved to github. diff --git a/INSTALL b/INSTALL index 0500d54e..0326a165 100644 --- a/INSTALL +++ b/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 @@ -852,6 +855,9 @@ may be located in different places. $ sudo /etc/init.d/postgresql stop $ sudo /etc/init.d/postgresql start + + The scripts may also be in /usr/local/etc/init.d, or in /etc/rc.d/, or + in /usr/local/etc/rc.d/ . 5) Check /etc/passwd file to find out which user account is used for the PostgreSQL admin access on your system (it may be "pgsql", or "postgres", @@ -859,10 +865,10 @@ or "postgresql"). Let's assume that this is "postgres" account. 6) Create a database for the TURN purposes, with name, say, "turn": - $ createdb -U postgres turn + $ createdb -U postgres coturn 7) Create a user for the TURN with name, say, "turn": - $ psql -U postgres turn + $ psql -U postgres coturn turn=# create user turn with password 'turn'; turn=# Ctrl-D @@ -873,13 +879,17 @@ The database schema for the TURN server is very minimalistic and is located in project's turndb/schema.sql file, or in the system's PREFIX/share/turnserver/schema.sql file after the turnserver installation: -$ cat turndb/schema.sql | psql -U turn -d turn +$ cat turndb/schema.sql | psql -U turn -d coturn NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "turnusers_lt_pkey" for table "turnusers_lt" CREATE TABLE CREATE TABLE See the SQLite section for the detailed database schema explanation. +To fill the database with test data: + +cat turndb/testsqldbsetup.sql | psql -U turn -d coturn + You can use turnadmin program to manage the database - you can either use turnadmin to add/modify/delete users, or you can use turnadmin to produce the hmac keys and modify the database with your favorite tools. @@ -930,13 +940,13 @@ Fill in users, for example: XVII. MySQL (MariaDB) setup -The MySQL setup is similar to PostgreSQL (same idea), and is well documented +The MySQL setup is similar to PostgreSQL (the same idea), and is well documented on their site http://www.mysql.org. The TURN Server database schema is the same as for PostgreSQL and you can find it in turndb/schema.sql file, or in the system's PREFIX/share/turnserver/schema.sql file after the turnserver installation. -The general setup idea is the same as for PostgreSQL: +The general setup is similar to PostgreSQL setup procedure: 1) Check that the mysql server access is OK. Immediately after the MySQL server installation, it must be accessible, at the very minimum, at the localhost with @@ -945,25 +955,32 @@ the root account. 2) Login into mysql console from root account: $ sudo bash - # mysql -p mysql + # mysql mysql + +(or mysql -p mysql if mysql account password set) 3) Add 'turn' user with 'turn' password (for example): > create user 'turn'@'localhost' identified by 'turn'; -4) Create database 'turn' (for example) and grant privileges to user 'turn': +4) Create database 'coturn' (for example) and grant privileges to user 'turn': - > create database turn; - > grant all on turn.* to 'turn'@'localhost'; + > create database coturn; + > grant all on coturn.* to 'turn'@'localhost'; > flush privileges; Ctrl-D 5) Create database schema: - $ mysql -p -u turn turn < turndb/schema.sql + $ mysql -p -u turn coturn < turndb/schema.sql Enter password: turn $ + Fill in test database data, if this is a test database + (not a production database): + + $ mysql -p -u turn coturn < turndb/testsqldbsetup.sql + 6) Fill in users, for example: Shared secret for the TURN REST API (realm north.gov): diff --git a/README.md b/README.md index d2d69c40..bc6ab665 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ **_This project evolved from rfc5766-turn-server project (https://code.google.com/p/rfc5766-turn-server/). There are many new advanced TURN specs which are going far beyond the original RFC 5766 document. This project takes the code of rfc5766-turn-server as the starter, and adds new advanced features to it._** +[Downloads page](https://github.com/coturn/coturn/wiki/Downloads) + +[Wiki pages](https://github.com/coturn/coturn/wiki/) + # Free open source implementation of TURN and STUN Server # The TURN Server is a VoIP media traffic NAT traversal server and gateway. It can be used as a general-purpose network traffic TURN server and gateway, too. @@ -16,13 +20,13 @@ TURN specs: * RFC 6062 - TCP relaying TURN extension * RFC 6156 - IPv6 extension for TURN * RFC 7443 - ALPN support for STUN & TURN + * RFC 7635 - oAuth third-party TURN/STUN authorization * DTLS support (http://tools.ietf.org/html/draft-petithuguenin-tram-turn-dtls-00). * Mobile ICE (MICE) support (http://tools.ietf.org/html/draft-wing-tram-turn-mobility-02). * TURN REST API (http://tools.ietf.org/html/draft-uberti-behave-turn-rest-00) * Origin field in TURN (Multi-tenant TURN Server) (https://tools.ietf.org/html/draft-ietf-tram-stun-origin-05) * TURN Bandwidth draft specs (http://tools.ietf.org/html/draft-thomson-tram-turn-bandwidth-01) - * TURN-bis (with dual allocation) draft specs (http://tools.ietf.org/html/draft-ietf-tram-turnbis-04) - * Third-party authorization support (http://tools.ietf.org/html/draft-ietf-tram-turn-third-party-authz-16). + * TURN-bis (with dual allocation) draft specs (http://tools.ietf.org/html/draft-ietf-tram-turnbis-04). STUN specs: @@ -31,6 +35,7 @@ STUN specs: * RFC 5769 - test vectors for STUN protocol testing * RFC 5780 - NAT behavior discovery support * RFC 7443 - ALPN support for STUN & TURN + * RFC 7635 - oAuth third-party TURN/STUN authorization Supported ICE and related specs: @@ -116,4 +121,4 @@ email:mom040267@gmail.com ### Feedback is very welcome (bugs, issues, suggestions, stories, questions). ### -### Volunteers are welcome, too. ### \ No newline at end of file +### Volunteers are welcome, too. ### diff --git a/README.turnserver b/README.turnserver index 3b2bf8ca..88a9b562 100644 --- a/README.turnserver +++ b/README.turnserver @@ -181,7 +181,7 @@ Flags: The actual value of the secret is defined either by option static-auth-secret, or can be found in the turn_secret table in the database. ---oauth Support oAuth authentication, as in the third-party TURN specs document. +--oauth Support oAuth authentication, as in the third-party STUN/TURN RFC 7635. --dh566 Use 566 bits predefined DH TLS key. Default size of the key is 1066. diff --git a/STATUS b/STATUS index 6afe79d5..8f088d2e 100644 --- a/STATUS +++ b/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. diff --git a/examples/var/db/turndb b/examples/var/db/turndb index ad8e8cbd8a0ab35ba5cacdc7d6da2d87d0461666..f6316d84c741616718257c49f9ec5c7ef26ddf7b 100644 GIT binary patch delta 177 zcmZqJz}T>Xae}nqRR#tIF(76IVkRJ#o2X;VdX+)<8P~>?MdDmm49r`Z>zS>XMK(5S zF>^XIv&*M)a7gn`j*zzDG+|;Fw*~U#C(n^q5z5OiD#_4G&oA?2WETf1Qk;B3+JY;& zC^IiFQ7^wJeUr>B?TG=boA0}uurR-5K0C3oU~`+#4MxVkiH!l1*ZWy_uo8ufv@P~|2{mMkNaD4001d)GHd_< delta 161 zcmZqJz}T>Xae}nq83qOhF(76IVkRJ#nW$sTdWJ#wk=n+TMdDlm49o|Zr!WUF{odI4 zj)^gJVq+kO6EmB9DhG%3WM^p`4lO1&aa$0lLt2Hyj*(3qEVEDAVw21*ZAOmGx7{sR znEx`Lo!D5gxy|PWBjcipjRBL_`&ms4;1RkFv=9UueMQ;D<>eWhGADob+q`*~zZ(Yt D^_MK8 diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index c178c735..a63ecbbc 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "19 July 2015" "" "" +.TH TURN 1 "13 September 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index ed076044..17bad32d 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "19 July 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 @@ -265,7 +265,7 @@ or can be found in the turn_secret table in the database. .TP .B \fB\-\-oauth\fP -Support oAuth authentication, as in the third\-party TURN specs document. +Support oAuth authentication, as in the third\-party STUN/TURN RFC 7635. .TP .B \fB\-\-dh566\fP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 80bc36eb..bf0f4cae 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "19 July 2015" "" "" +.TH TURN 1 "13 September 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 1e9afd3d..58fdcb19 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.4.5.4 +TURNVERSION=4.5.0.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_GIT_URL=https://github.com/coturn/coturn.git diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 79d05108..82fd70bd 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.4.5.4 +Version: 4.5.0.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -289,6 +289,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Sun Sep 13 2015 Oleg Moskalenko + - Sync to 4.5.0.1 * Sat Jul 18 2015 Oleg Moskalenko - Sync to 4.4.5.4 * Sat Jun 20 2015 Oleg Moskalenko diff --git a/src/apps/common/apputils.h b/src/apps/common/apputils.h index 6ff61bfd..a0f0ac5c 100644 --- a/src/apps/common/apputils.h +++ b/src/apps/common/apputils.h @@ -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; diff --git a/src/apps/common/ns_turn_utils.c b/src/apps/common/ns_turn_utils.c index bc25d0db..375c9c96 100644 --- a/src/apps/common/ns_turn_utils.c +++ b/src/apps/common/ns_turn_utils.c @@ -236,6 +236,7 @@ static int to_syslog = 0; static int simple_log = 0; static char log_fn[FILE_STR_LEN]="\0"; static char log_fn_base[FILE_STR_LEN]="\0"; +static volatile int to_reset_log_file = 0; static turn_mutex log_mutex; static int log_mutex_inited = 0; @@ -344,13 +345,18 @@ static void set_log_file_name_func(char *base, char *f, size_t fsz) static void sighup_callback_handler(int signum) { if(signum == SIGHUP) { - printf("%s: resetting the log file\n",__FUNCTION__); - reset_rtpprintf(); + to_reset_log_file = 1; } } static void set_rtpfile(void) { + if(to_reset_log_file) { + printf("%s: resetting the log file\n",__FUNCTION__); + reset_rtpprintf(); + to_reset_log_file = 0; + } + if(to_syslog) { return; } else if (!_rtpfile) { diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index e06127e8..95ba28dd 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -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); diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index b8bb30fa..2e5543dd 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -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)); diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index b7b72718..2393e984 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -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)); diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index 3619f816..3b0f6322 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -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); } } } diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 26f32b16..28f236d8 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -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); diff --git a/src/apps/relay/dbdrivers/dbdriver.h b/src/apps/relay/dbdrivers/dbdriver.h index d013e165..b6ad537d 100644 --- a/src/apps/relay/dbdrivers/dbdriver.h +++ b/src/apps/relay/dbdrivers/dbdriver.h @@ -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); diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 71350d0c..6f8e3fd0 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -805,7 +805,7 @@ static int handle_relay_message(relay_server_handle rs, struct message_to_relay static void handle_relay_auth_message(struct relay_server *rs, struct auth_message *am) { am->resume_func(am->success, am->out_oauth, am->max_session_time, am->key, am->pwd, - &(rs->server), am->ctxkey, &(am->in_buffer)); + &(rs->server), am->ctxkey, &(am->in_buffer), am->realm); if (am->in_buffer.nbh) { ioa_network_buffer_delete(rs->ioa_eng, am->in_buffer.nbh); am->in_buffer.nbh = NULL; diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 4fa84a85..f88a2e7a 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -708,10 +708,10 @@ int ioa_socket_check_bandwidth(ioa_socket_handle s, ioa_network_buffer_handle nb return 1; } -int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_token, ioa_socket_handle *s, u08bits *realm) +int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_token, ioa_socket_handle *s) { if (e && in_reservation_token && s) { - *s = rtcp_map_get(e->map_rtcp, in_reservation_token, realm); + *s = rtcp_map_get(e->map_rtcp, in_reservation_token); if (*s) { return 0; } @@ -1652,8 +1652,6 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s) ret->magic = SOCKET_MAGIC; - ret->realm_hash = s->realm_hash; - SSL* ssl = s->ssl; set_socket_ssl(s,NULL); set_socket_ssl(ret,ssl); @@ -3417,38 +3415,6 @@ void set_ioa_socket_tobeclosed(ioa_socket_handle s) s->tobeclosed = 1; } -static u32bits string_hash(const u08bits *str) { - - u32bits hash = 0; - int c = 0; - - while ((c = *str++)) - hash = c + (hash << 6) + (hash << 16) - hash; - - return hash; -} - -int check_realm_hash(ioa_socket_handle s, u08bits *realm) -{ - if(s) { - if(realm && realm[0]) { - if(s->realm_hash != string_hash(realm)) { - return 0; - } - } - } - return 1; -} - -void set_realm_hash(ioa_socket_handle s, u08bits *realm) -{ - if(s) { - if(realm && realm[0]) { - s->realm_hash = string_hash(realm); - } - } -} - /* * Network buffer functions */ diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index f2e2cee8..4f373d78 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -221,8 +221,6 @@ struct _ioa_socket struct bufferevent *conn_bev; connect_cb conn_cb; void *conn_arg; - //Transferable sockets user data - u32bits realm_hash; //Accept: struct evconnlistener *list_ev; accept_cb acb; diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 4de1d6fe..f9916bf8 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1369,6 +1369,7 @@ typedef enum _AS_FORM AS_FORM; #define HR_ADD_IP_KIND "aipk" #define HR_UPDATE_PARAMETER "togglepar" #define HR_ADD_OAUTH_KID "oauth_kid" +#define HR_ADD_OAUTH_REALM "oauth_realm" #define HR_ADD_OAUTH_TS "oauth_ts" #define HR_ADD_OAUTH_LT "oauth_lt" #define HR_ADD_OAUTH_IKM "oauth_ikm" @@ -2773,12 +2774,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; @@ -2807,6 +2809,9 @@ static size_t https_print_oauth_keys(struct str_buffer* sb) str_buffer_append(sb,""); str_buffer_append(sb,get_secrets_list_elem(&teas,i)); str_buffer_append(sb,""); + str_buffer_append(sb,""); + str_buffer_append(sb,get_secrets_list_elem(&realms,i)); + str_buffer_append(sb,""); { str_buffer_append(sb," \r\n"); - str_buffer_append(sb,""); + str_buffer_append(sb,""); { if(!add_ikm) add_ikm = ""; - str_buffer_append(sb,"
Base64-encoded input keying material (required):