Imported Upstream version 4.5.0.1

upstream/latest upstream/4.5.0.1
Oleg Moskalenko 10 years ago
parent c5f9e2b8c1
commit d4bc5ecf23
  1. 8
      ChangeLog
  2. 37
      INSTALL
  3. 11
      README.md
  4. 2
      README.turnserver
  5. 3
      STATUS
  6. BIN
      examples/var/db/turndb
  7. 2
      man/man1/turnadmin.1
  8. 4
      man/man1/turnserver.1
  9. 2
      man/man1/turnutils.1
  10. 2
      rpm/build.settings.sh
  11. 4
      rpm/turnserver.spec
  12. 1
      src/apps/common/apputils.h
  13. 10
      src/apps/common/ns_turn_utils.c
  14. 16
      src/apps/relay/dbdrivers/dbd_mongo.c
  15. 33
      src/apps/relay/dbdrivers/dbd_mysql.c
  16. 23
      src/apps/relay/dbdrivers/dbd_pgsql.c
  17. 13
      src/apps/relay/dbdrivers/dbd_redis.c
  18. 17
      src/apps/relay/dbdrivers/dbd_sqlite.c
  19. 2
      src/apps/relay/dbdrivers/dbdriver.h
  20. 2
      src/apps/relay/netengine.c
  21. 38
      src/apps/relay/ns_ioalib_engine_impl.c
  22. 2
      src/apps/relay/ns_ioalib_impl.h
  23. 44
      src/apps/relay/turn_admin_server.c
  24. 4
      src/apps/relay/userdb.c
  25. 8
      src/apps/uclient/mainuclient.c
  26. 6
      src/client/ns_turn_msg_defs.h
  27. 5
      src/client/ns_turn_msg_defs_experimental.h
  28. 4
      src/ns_turn_defs.h
  29. 4
      src/server/ns_turn_ioalib.h
  30. 4
      src/server/ns_turn_maps.c
  31. 8
      src/server/ns_turn_maps_rtcp.c
  32. 2
      src/server/ns_turn_maps_rtcp.h
  33. 31
      src/server/ns_turn_server.c
  34. 2
      src/server/ns_turn_server.h
  35. 1
      turndb/schema.sql
  36. 27
      turndb/schema.userdb.redis
  37. 10
      turndb/testmongosetup.sh
  38. 4
      turndb/testredisdbsetup.sh
  39. 6
      turndb/testsqldbsetup.sql

@ -1,3 +1,11 @@
9/13/2015 Oleg Moskalenko <mom040267@gmail.com>
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 <mom040267@gmail.com>
Version 4.4.5.4 'Ardee West':
- moved to github.

@ -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):

@ -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. ###
### Volunteers are welcome, too. ###

@ -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.

@ -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 "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

@ -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

@ -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

@ -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

@ -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 <mom040267@gmail.com>
- Sync to 4.5.0.1
* 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;

@ -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) {

@ -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);

@ -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;

@ -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
*/

@ -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;

@ -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(&lts);
dbd->list_oauth_keys(&kids,&teas,&tss,&lts);
init_secrets_list(&realms);
dbd->list_oauth_keys(&kids,&teas,&tss,&lts,&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,"<td>");
str_buffer_append(sb,get_secrets_list_elem(&teas,i));
str_buffer_append(sb,"</td>");
str_buffer_append(sb,"<td>");
str_buffer_append(sb,get_secrets_list_elem(&realms,i));
str_buffer_append(sb,"</td>");
{
str_buffer_append(sb,"<td> <a href=\"");
@ -2824,6 +2829,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(&lts);
clean_secrets_list(&realms);
}
return ret;
@ -2889,9 +2897,13 @@ static void write_https_oauth_show_keys(ioa_socket_handle s, const char* kid)
}
}
static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, const char* add_ikm,
static void write_https_oauth_page(ioa_socket_handle s,
const char* add_kid,
const char* add_ikm,
const char* add_tea,
const char *add_ts, const char* add_lt,
const char *add_ts,
const char* add_lt,
const char* add_realm,
const char* msg)
{
if(s && !ioa_socket_tobeclosed(s)) {
@ -2956,12 +2968,12 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con
str_buffer_append(sb,"</td></tr>\r\n");
str_buffer_append(sb,"<tr><td colspan=\"2\">");
str_buffer_append(sb,"<tr><td colspan=\"1\">");
{
if(!add_ikm) add_ikm = "";
str_buffer_append(sb," <br>Base64-encoded input keying material (required):<br><textarea wrap=\"soft\" cols=70 rows=4 name=\"");
str_buffer_append(sb," <br>Base64-encoded input keying material (required):<br><textarea wrap=\"soft\" cols=40 rows=4 name=\"");
str_buffer_append(sb,HR_ADD_OAUTH_IKM);
str_buffer_append(sb,"\" maxLength=256 >");
str_buffer_append(sb,(const char*)add_ikm);
@ -2971,6 +2983,18 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con
str_buffer_append(sb,"</td><td>");
{
if(!add_realm) add_realm = "";
str_buffer_append(sb," <br>Realm (optional): <input type=\"text\" name=\"");
str_buffer_append(sb,HR_ADD_OAUTH_REALM);
str_buffer_append(sb,"\" value=\"");
str_buffer_append(sb,(const char*)add_realm);
str_buffer_append(sb,"\"><br>\r\n");
}
str_buffer_append(sb,"</td><td>");
{
str_buffer_append(sb,"<br>Token encryption algorithm (required):<br>\r\n");
@ -3008,6 +3032,7 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con
str_buffer_append(sb,"<th>Timestamp, secs</th>");
str_buffer_append(sb,"<th>Lifetime,secs</th>");
str_buffer_append(sb,"<th>Token encryption algorithm</th>");
str_buffer_append(sb,"<th>Realm</th>");
str_buffer_append(sb,"<th> </th>");
str_buffer_append(sb,"</tr>\r\n");
@ -3495,6 +3520,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh)
const char* add_lt = "0";
const char* add_ikm = "";
const char* add_tea = "";
const char* add_realm = "";
const char* msg = "";
add_kid = get_http_header_value(hr,HR_ADD_OAUTH_KID,"");
@ -3503,6 +3529,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh)
add_ts = get_http_header_value(hr,HR_ADD_OAUTH_TS,"");
add_lt = get_http_header_value(hr,HR_ADD_OAUTH_LT,"");
add_tea = get_http_header_value(hr,HR_ADD_OAUTH_TEA,"");
add_realm = get_http_header_value(hr,HR_ADD_OAUTH_REALM,"");
int keys_ok = (add_ikm[0] != 0);
if(!keys_ok) {
@ -3526,6 +3553,8 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh)
key.timestamp = (u64bits)strtoull(add_ts,NULL,10);
}
if(add_realm && add_realm[0]) STRCPY(key.realm,add_realm);
STRCPY(key.ikm_key,add_ikm);
STRCPY(key.as_rs_alg,add_tea);
@ -3539,12 +3568,13 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh)
add_lt = "0";
add_ikm = "";
add_tea = "";
add_realm = "";
}
}
}
}
write_https_oauth_page(s,add_kid,add_ikm,add_tea,add_ts,add_lt,msg);
write_https_oauth_page(s,add_kid,add_ikm,add_tea,add_ts,add_lt,add_realm,msg);
}
break;
}

@ -517,6 +517,10 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u
ns_bcopy(dot.enc_block.mac_key,key,dot.enc_block.key_length);
if(rawKey.realm[0]) {
ns_bcopy(rawKey.realm,realm,sizeof(rawKey.realm));
}
ret = 0;
}
}

@ -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"

@ -148,12 +148,6 @@
#define STUN_ATTRIBUTE_TRANSPORT_DTLS_VALUE (250)
/* <<== RFC 6062 */
/* Mobility ==>> */
#define STUN_ATTRIBUTE_MOBILITY_TICKET (0x802E)
#define STUN_ATTRIBUTE_MOBILITY_EVENT (0x802)
#define STUN_ATTRIBUTE_MOBILITY_SUPPORT (0x8000)
/* <<== Mobility */
/* SHA ==>> */
#define SHA1SIZEBYTES (20)

@ -38,6 +38,11 @@
#define STUN_ATTRIBUTE_ORIGIN (0x802F)
/* <<== Origin */
/* Mobility ==>> */
/* conflicts with third-party authorization ! 0x802E is used for third-party authorization now */
#define STUN_ATTRIBUTE_MOBILITY_TICKET (0x8030)
/* <<== Mobility */
/* Bandwidth */
#define STUN_ATTRIBUTE_NEW_BANDWIDTH (0x8000 + STUN_ATTRIBUTE_BANDWIDTH)

@ -31,8 +31,8 @@
#ifndef __IOADEFS__
#define __IOADEFS__
#define TURN_SERVER_VERSION "4.4.5.4"
#define TURN_SERVER_VERSION_NAME "Ardee West"
#define TURN_SERVER_VERSION "4.5.0.1"
#define TURN_SERVER_VERSION_NAME "dan Eider"
#define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'"
#if (defined(__unix__) || defined(unix)) && !defined(USG)

@ -227,7 +227,7 @@ int create_relay_ioa_sockets(ioa_engine_handle e, ioa_socket_handle client_s,
ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, ioa_addr *peer_addr, connect_cb cb, void *arg);
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);
int get_ioa_socket_address_family(ioa_socket_handle s);
int is_stream_socket(int st);
@ -260,8 +260,6 @@ void set_do_not_use_df(ioa_socket_handle s);
int ioa_socket_tobeclosed(ioa_socket_handle s);
void set_ioa_socket_tobeclosed(ioa_socket_handle s);
void close_ioa_socket_after_processing_if_necessary(ioa_socket_handle s);
int check_realm_hash(ioa_socket_handle s, u08bits *realm);
void set_realm_hash(ioa_socket_handle s, u08bits *realm);
////////////////// Base64 /////////////////////////////

@ -1029,11 +1029,11 @@ struct _ur_string_map {
TURN_MUTEX_DECLARE(mutex)
};
static unsigned long string_hash(const ur_string_map_key_type key) {
static u32bits string_hash(const ur_string_map_key_type key) {
u08bits *str=(u08bits*)key;
unsigned long hash = 0;
u32bits hash = 0;
int c = 0;
while ((c = *str++))

@ -214,7 +214,7 @@ int rtcp_map_put(rtcp_map* map, rtcp_token_type token, ioa_socket_handle s) {
* >=0 - success
* <0 - not found
*/
ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token, u08bits *realm) {
ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token) {
ioa_socket_handle s = NULL;
if (rtcp_map_valid(map)) {
ur_map_value_type value;
@ -224,11 +224,7 @@ ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token, u08bits *re
rtcp_alloc_type* rval = (rtcp_alloc_type*) value;
if (rval) {
s = rval->s;
if(!check_realm_hash(s,realm)) {
s = NULL;
} else {
rtcp_map_del_savefd(map, token);
}
rtcp_map_del_savefd(map, token);
}
}
TURN_MUTEX_UNLOCK(&map->mutex);

@ -61,7 +61,7 @@ int rtcp_map_put(rtcp_map* map, rtcp_token_type key, ioa_socket_handle s);
* >=0 - success
* <0 - not found
*/
ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token, u08bits *realm);
ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token);
/**
* @ret:

@ -77,7 +77,7 @@ static inline void log_method(ts_ur_super_session* ss, const char *method, int e
(unsigned long long)(ss->id), (const char*)(ss->realm_options.name),(const char*)(ss->username),method);
}
} else {
if(!reason) reason=(const u08bits*)"Unknown error";
if(!reason) reason=get_default_reason(err_code);
if(ss->origin[0]) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
"session %018llu: origin <%s> realm <%s> user <%s>: incoming packet %s processed, error %d: %s\n",
@ -3191,7 +3191,7 @@ static int create_challenge_response(ts_ur_super_session *ss, stun_tid *tid, int
#define min(a,b) ((a)<=(b) ? (a) : (b))
#endif
static void resume_processing_after_username_check(int success, int oauth, int max_session_time, hmackey_t hmackey, password_t pwd, turn_turnserver *server, u64bits ctxkey, ioa_net_data *in_buffer)
static void resume_processing_after_username_check(int success, int oauth, int max_session_time, hmackey_t hmackey, password_t pwd, turn_turnserver *server, u64bits ctxkey, ioa_net_data *in_buffer, u08bits *realm)
{
if(server && in_buffer && in_buffer->nbh) {
@ -3206,6 +3206,11 @@ static void resume_processing_after_username_check(int success, int oauth, int
ss->oauth = oauth;
ss->max_session_time_auth = (turn_time_t)max_session_time;
ns_bcopy(pwd,ss->pwd,sizeof(password_t));
if(realm && realm[0] && strcmp((char*)realm,ss->realm_options.name)) {
dec_quota(ss);
get_realm_options_by_name((char*)realm, &(ss->realm_options));
inc_quota(ss,ss->username);
}
}
read_client_connection(server,ss,in_buffer,0,0);
@ -3318,14 +3323,18 @@ static int check_stun_auth(turn_turnserver *server,
get_realm_options_by_name((char *)realm, &(ss->realm_options));
} else if(strcmp((char*)realm, (char*)(ss->realm_options.name))) {
if(method == STUN_METHOD_ALLOCATE) {
*err_code = 437;
*reason = (const u08bits*)"Allocation mismatch: wrong credentials: the realm value is incorrect";
if(!(ss->oauth)){
if(method == STUN_METHOD_ALLOCATE) {
*err_code = 437;
*reason = (const u08bits*)"Allocation mismatch: wrong credentials: the realm value is incorrect";
} else {
*err_code = 441;
*reason = (const u08bits*)"Wrong credentials: the realm value is incorrect";
}
return -1;
} else {
*err_code = 441;
*reason = (const u08bits*)"Wrong credentials: the realm value is incorrect";
ns_bcopy(ss->realm_options.name,realm,sizeof(ss->realm_options.name));
}
return -1;
}
}
@ -3366,7 +3375,6 @@ static int check_stun_auth(turn_turnserver *server,
}
} else {
STRCPY(ss->username,usname);
set_realm_hash(ss->client_socket,(u08bits*)ss->realm_options.name);
}
{
@ -4261,7 +4269,7 @@ static int create_relay_connection(turn_turnserver* server,
ioa_socket_handle s = NULL;
if ((get_ioa_socket_from_reservation(server->e, in_reservation_token,&s,(u08bits*)ss->realm_options.name) < 0)||
if ((get_ioa_socket_from_reservation(server->e, in_reservation_token,&s) < 0)||
!s ||
ioa_socket_tobeclosed(s)) {
@ -4317,11 +4325,8 @@ static int create_relay_connection(turn_turnserver* server,
return -1;
}
set_realm_hash(newelem->s,(u08bits*)ss->realm_options.name);
if (rtcp_s) {
if (out_reservation_token && *out_reservation_token) {
set_realm_hash(rtcp_s,(u08bits*)ss->realm_options.name);
/* OK */
} else {
IOA_CLOSE_SOCKET(newelem->s);

@ -90,7 +90,7 @@ typedef enum {
struct _turn_turnserver;
typedef struct _turn_turnserver turn_turnserver;
typedef void (*get_username_resume_cb)(int success, int oauth, int max_session_time, hmackey_t hmackey, password_t pwd, turn_turnserver *server, u64bits ctxkey, ioa_net_data *in_buffer);
typedef void (*get_username_resume_cb)(int success, int oauth, int max_session_time, hmackey_t hmackey, password_t pwd, turn_turnserver *server, u64bits ctxkey, ioa_net_data *in_buffer, u08bits* realm);
typedef u08bits *(*get_user_key_cb)(turnserver_id id, turn_credential_type ct, int in_oauth, int *out_oauth, u08bits *uname, u08bits *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, u64bits ctxkey, int *postpone_reply);
typedef int (*check_new_allocation_quota_cb)(u08bits *username, int oauth, u08bits *realm);
typedef void (*release_allocation_quota_cb)(u08bits *username, int oauth, u08bits *realm);

@ -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…
Cancel
Save