mirror of
https://github.com/coturn/coturn.git
synced 2026-05-12 09:40:35 +00:00
Imported Upstream version 4.4.1.1
This commit is contained in:
@@ -1,3 +1,12 @@
|
||||
1/24/2015 Oleg Moskalenko <mom040267@gmail.com>
|
||||
Version 4.4.1.1 'Ardee West':
|
||||
- https admin server;
|
||||
- SSLv2 support cancelled (security concern fixed);
|
||||
- The server-side short-term credentials mechanism support cancelled;
|
||||
- OpenSSL 1.1.0 supported;
|
||||
- shared secrets fixed in MongoDB: multiple secrets per realm allowed;
|
||||
- shared secrets admin fixed in Redis;
|
||||
|
||||
12/24/2014 Oleg Moskalenko <mom040267@gmail.com>
|
||||
Version 4.3.3.1 'Tolomei':
|
||||
- multiple authentication threads;
|
||||
@@ -458,9 +467,9 @@ Version 2.6.1.1 'Harding Grim':
|
||||
= In REST API timestamp, we are now using
|
||||
the expiration time (Issue 31).
|
||||
* Configurable cipher suite in the TURN server.
|
||||
* SSL3 support.
|
||||
* SSLv3 support.
|
||||
* TLS 1.1 and 1.2 support.
|
||||
* SSL2 "encapsulation" mode support.
|
||||
* SSLv2 "encapsulation" mode support.
|
||||
* NULL OpenSSL cipher is allowed to be negotiated between
|
||||
server and client.
|
||||
* -U option (NULL cipher) added to the test client.
|
||||
|
||||
@@ -669,7 +669,7 @@ The schema description:
|
||||
# Table for long-term credentials mechanism authorization:
|
||||
#
|
||||
CREATE TABLE turnusers_lt (
|
||||
realm varchar(512) default '',
|
||||
realm varchar(127) default '',
|
||||
name varchar(512),
|
||||
hmackey char(128),
|
||||
PRIMARY KEY (realm,name)
|
||||
@@ -684,27 +684,20 @@ used for the HMAC key generation.
|
||||
The key must be 32 characters (HEX representation of 16 bytes) for SHA1,
|
||||
or 64 characters (HEX representation of 32 bytes) for SHA256.
|
||||
|
||||
# Table for short-term credentials mechanism authorisation:
|
||||
#
|
||||
CREATE TABLE turnusers_st (
|
||||
name varchar(512) PRIMARY KEY,
|
||||
password varchar(512)
|
||||
);
|
||||
|
||||
# Table holding shared secrets for secret-based authorization
|
||||
# (REST API). It can only be used together with the long-term
|
||||
# mechanism:
|
||||
#
|
||||
CREATE TABLE turn_secret (
|
||||
realm varchar(512) default '',
|
||||
value varchar(512),
|
||||
realm varchar(127) default '',
|
||||
value varchar(127),
|
||||
primary key (realm,value)
|
||||
);
|
||||
|
||||
# Table holding "white" allowed peer IP ranges.
|
||||
#
|
||||
CREATE TABLE allowed_peer_ip (
|
||||
realm varchar(512) default '',
|
||||
realm varchar(127) default '',
|
||||
ip_range varchar(256),
|
||||
primary key (realm,ip_range)
|
||||
);
|
||||
@@ -712,7 +705,7 @@ CREATE TABLE allowed_peer_ip (
|
||||
# Table holding "black" denied peer IP ranges.
|
||||
#
|
||||
CREATE TABLE denied_peer_ip (
|
||||
realm varchar(512) default '',
|
||||
realm varchar(127) default '',
|
||||
ip_range varchar(256),
|
||||
primary key (realm,ip_range)
|
||||
);
|
||||
@@ -723,8 +716,8 @@ CREATE TABLE denied_peer_ip (
|
||||
# then the default realm is used.
|
||||
#
|
||||
CREATE TABLE turn_origin_to_realm (
|
||||
origin varchar(512),
|
||||
realm varchar(512),
|
||||
origin varchar(127),
|
||||
realm varchar(127),
|
||||
primary key (origin,realm)
|
||||
);
|
||||
|
||||
@@ -734,7 +727,7 @@ CREATE TABLE turn_origin_to_realm (
|
||||
# Values for them are integers (in text form).
|
||||
#
|
||||
CREATE TABLE turn_realm_option (
|
||||
realm varchar(512) default '',
|
||||
realm varchar(127) default '',
|
||||
opt varchar(32),
|
||||
value varchar(128),
|
||||
primary key (realm,opt)
|
||||
@@ -753,7 +746,7 @@ CREATE TABLE oauth_key (
|
||||
auth_alg varchar(64) default '',
|
||||
auth_key varchar(256) default '',
|
||||
primary key (kid)
|
||||
);
|
||||
);
|
||||
|
||||
The oauth_key table fields meanings are:
|
||||
|
||||
@@ -764,7 +757,7 @@ The oauth_key table fields meanings are:
|
||||
explicitly in the database;
|
||||
|
||||
timestamp - (optional) the timestamp (in seconds) when the key
|
||||
lifetime started;
|
||||
lifetime starts;
|
||||
|
||||
lifetime - (optional) the key lifetime in seconds; the default value
|
||||
is 0 - unlimited lifetime.
|
||||
@@ -791,6 +784,17 @@ The oauth_key table fields meanings are:
|
||||
calculated with ikm_key and hkdf_hash_func. The auth_key length
|
||||
is defined by auth_alg.
|
||||
|
||||
# Https access admin users.
|
||||
# Leave this table empty if you do not want
|
||||
# remote https access to the admin functions.
|
||||
#
|
||||
CREATE TABLE admin_user (
|
||||
name varchar(32),
|
||||
realm varchar(127),
|
||||
password varchar(127),
|
||||
primary key (name)
|
||||
);
|
||||
|
||||
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.
|
||||
@@ -816,10 +820,10 @@ Fill in users, for example:
|
||||
Long-term credentials mechanism with SHA256 extension:
|
||||
$ bin/turnadmin -a -b "/var/db/turndb" -u bethod -r north.gov -p king-of-north --sha256
|
||||
|
||||
Short-term credentials mechanism:
|
||||
Admin users:
|
||||
|
||||
$ bin/turnadmin -A -b "/var/db/turndb" -u gorst -p hero
|
||||
$ bin/turnadmin -A -b "/var/db/turndb" -u ninefingers -p youhavetoberealistic
|
||||
$ bin/turnadmin -A -b "/var/db/turndb" -u ninefingers -p youhavetoberealistic -r north.gov
|
||||
|
||||
XVI. PostgreSQL setup
|
||||
|
||||
@@ -888,8 +892,6 @@ PREFIX/share/turnserver/schema.sql file after the turnserver installation:
|
||||
$ cat turndb/schema.sql | psql -U turn turn
|
||||
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "turnusers_lt_pkey" for table "turnusers_lt"
|
||||
CREATE TABLE
|
||||
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "turnusers_st_pkey" for table "turnusers_st"
|
||||
CREATE TABLE
|
||||
CREATE TABLE
|
||||
|
||||
See the SQLite section for the detailed database schema explanation.
|
||||
@@ -940,10 +942,10 @@ Fill in users, for example:
|
||||
Long-term credentials mechanism with SHA256 extension:
|
||||
$ bin/turnadmin -a -e "host=localhost dbname=coturn user=turn password=turn" -u bethod -r north.gov -p king-of-north --sha256
|
||||
|
||||
Short-term credentials mechanism:
|
||||
Admin users:
|
||||
|
||||
$ bin/turnadmin -A -e "host=localhost dbname=coturn user=turn password=turn" -u gorst -p hero
|
||||
$ bin/turnadmin -A -e "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -p youhavetoberealistic
|
||||
$ bin/turnadmin -A -e "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -p youhavetoberealistic -r north.gov
|
||||
|
||||
XVII. MySQL (MariaDB) setup
|
||||
|
||||
@@ -995,10 +997,10 @@ the root account.
|
||||
Long-term credentials mechanism with SHA256 extension:
|
||||
$ bin/turnadmin -a -M "host=localhost dbname=coturn user=turn password=turn" -u bethod -r north.gov -p king-of-north --sha256
|
||||
|
||||
Short-term credentials mechanism:
|
||||
Admin users:
|
||||
|
||||
$ bin/turnadmin -A -M "host=localhost dbname=coturn user=turn password=turn" -u gorst -p hero
|
||||
$ bin/turnadmin -A -M "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -p youhavetoberealistic
|
||||
$ bin/turnadmin -A -M "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -p youhavetoberealistic -r north.gov
|
||||
|
||||
7) Now we can use mysql in the turnserver.
|
||||
|
||||
@@ -1124,10 +1126,10 @@ Redis TURN admin commands:
|
||||
Long-term credentials mechanism with SHA256 extension:
|
||||
$ bin/turnadmin -a -N "host=localhost dbname=2 user=turn password=turn" -u bethod -r north.gov -p king-of-north --sha256
|
||||
|
||||
Short-term credentials mechanism:
|
||||
Admin users:
|
||||
|
||||
$ bin/turnadmin -A -N "host=localhost dbname=2 user=turn password=turn" -u gorst -p hero
|
||||
$ bin/turnadmin -A -N "host=localhost dbname=2 user=turn password=turn" -u ninefingers -p youhavetoberealistic
|
||||
$ bin/turnadmin -A -N "host=localhost dbname=2 user=turn password=turn" -u ninefingers -p youhavetoberealistic -r north.gov
|
||||
|
||||
See the file testredisdbsetup.sh for the data structure examples.
|
||||
|
||||
@@ -1144,7 +1146,19 @@ Read the project wiki pages: http://code.google.com/p/coturn/w/list
|
||||
Also, check the project from page links to the TURN/WebRTC configuration examples.
|
||||
It may give you an idea how it can be done.
|
||||
|
||||
XXII. Management interface
|
||||
XXII. HTTPS Management Interface
|
||||
|
||||
The turnserver process provides an HTTPS Web access as statistics and basic management
|
||||
interface. The turnserver listens to incoming HTTPS admin connections on the same ports
|
||||
as the main TURN/STUN listener. The Web admin pages are basic and self-explanatory.
|
||||
|
||||
To make the HTTPS interface active, the database table admin_user must be
|
||||
populated with the admin user account(s). An admin user can be a superuser
|
||||
(if not assigned to a particular realm) or a restricted user (if assigned to
|
||||
a realm). The restricted admin users can perform only limited actions, within
|
||||
their corresponding realms.
|
||||
|
||||
XXIII. Telnet CLI management interface
|
||||
|
||||
You have a telnet interface (enabled by default) to access the turnserver process,
|
||||
to view its state, to gather some statistical information, and to make some changes
|
||||
@@ -1152,7 +1166,7 @@ on-the-fly.
|
||||
|
||||
You can access that CLI interface with telnet or putty program (in telnet mode).
|
||||
The process by default listens to port 5766 on IP address 127.0.0.1 for the telnet
|
||||
connections.
|
||||
connections.
|
||||
|
||||
WARNING: all telnet communications are going unencrypted over the network. For
|
||||
security reasons, we advise using the loopback IP addresses for CLI (127.0.0.1
|
||||
@@ -1161,7 +1175,7 @@ transferred over the network unencrypted, too. So sticking to the local system
|
||||
CLI access, and accessing the turnserver system terminal with ssh only, would
|
||||
be a wise decision.
|
||||
|
||||
XXIII. ALPN support.
|
||||
XXIV. ALPN support.
|
||||
|
||||
Starting with version 4.3.2.1, the TURN server supports the ALPN STUN
|
||||
specifications (http://tools.ietf.org/html/draft-ietf-tram-alpn-08).
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@ HIREDIS_MODS = src/apps/common/hiredis_libevent2.c
|
||||
USERDB_HEADERS = src/apps/relay/dbdrivers/dbdriver.h src/apps/relay/dbdrivers/dbd_sqlite.h src/apps/relay/dbdrivers/dbd_pgsql.h src/apps/relay/dbdrivers/dbd_mysql.h src/apps/relay/dbdrivers/dbd_mongo.h src/apps/relay/dbdrivers/dbd_redis.h
|
||||
USERDB_MODS = src/apps/relay/dbdrivers/dbdriver.c src/apps/relay/dbdrivers/dbd_sqlite.c src/apps/relay/dbdrivers/dbd_pgsql.c src/apps/relay/dbdrivers/dbd_mysql.c src/apps/relay/dbdrivers/dbd_mongo.c src/apps/relay/dbdrivers/dbd_redis.c
|
||||
|
||||
SERVERAPP_HEADERS = src/apps/relay/userdb.h src/apps/relay/tls_listener.h src/apps/relay/mainrelay.h src/apps/relay/turncli.h src/apps/relay/dtls_listener.h src/apps/relay/libtelnet.h ${HIREDIS_HEADERS} ${USERDB_HEADERS}
|
||||
SERVERAPP_MODS = src/apps/relay/mainrelay.c src/apps/relay/netengine.c src/apps/relay/libtelnet.c src/apps/relay/turncli.c src/apps/relay/userdb.c src/apps/relay/tls_listener.c src/apps/relay/dtls_listener.c ${HIREDIS_MODS} ${USERDB_MODS}
|
||||
SERVERAPP_HEADERS = src/apps/relay/userdb.h src/apps/relay/tls_listener.h src/apps/relay/mainrelay.h src/apps/relay/turn_admin_server.h src/apps/relay/dtls_listener.h src/apps/relay/libtelnet.h ${HIREDIS_HEADERS} ${USERDB_HEADERS}
|
||||
SERVERAPP_MODS = src/apps/relay/mainrelay.c src/apps/relay/netengine.c src/apps/relay/libtelnet.c src/apps/relay/turn_admin_server.c src/apps/relay/userdb.c src/apps/relay/tls_listener.c src/apps/relay/dtls_listener.c ${HIREDIS_MODS} ${USERDB_MODS}
|
||||
SERVERAPP_DEPS = ${SERVERTURN_MODS} ${SERVERTURN_DEPS} ${SERVERAPP_MODS} ${SERVERAPP_HEADERS} ${COMMON_DEPS} ${IMPL_DEPS} lib/libturnclient.a
|
||||
|
||||
TURN_BUILD_RESULTS = bin/turnutils_stunclient bin/turnutils_rfc5769check bin/turnutils_uclient bin/turnserver bin/turnutils_peer lib/libturnclient.a include/turn/ns_turn_defs.h sqlite_empty_db
|
||||
|
||||
+6
-6
@@ -51,15 +51,15 @@ Commands:
|
||||
|
||||
-a, --add Add or update a long-term user.
|
||||
|
||||
-A, --add-st Add or update a short-term credentials mechanism user.
|
||||
-A, --add-admin Add or update an admin user.
|
||||
|
||||
-d, --delete Delete a long-term user.
|
||||
|
||||
-D, --delete-st Delete a short-term user.
|
||||
-D, --delete-admin Delete an admin user.
|
||||
|
||||
-l, --list List long-term users in the database.
|
||||
|
||||
-L, --list-st List short-term users in the database.
|
||||
-L, --list-admin List admin users in the database.
|
||||
|
||||
-s, --set-secret=<value> Add shared secret for TURN RESP API
|
||||
|
||||
@@ -92,7 +92,7 @@ Options with required values:
|
||||
-N, --redis-userdb Redis user database connection string.
|
||||
See the --redis-userdb option in the turnserver section.
|
||||
-u, --user User name.
|
||||
-r, --realm Realm, for long-term credentials mechanism only.
|
||||
-r, --realm Realm.
|
||||
-p, --password Password.
|
||||
-o, --origin Origin
|
||||
-H, --sha256 Use SHA256 as the keys hash function (a non-standard feature).
|
||||
@@ -119,7 +119,7 @@ List all long-term users in MySQL database:
|
||||
|
||||
$ turnadmin -l --mysql-userdb="<db-connection-string>" -r <realm>
|
||||
|
||||
List all short-term users in Redis database:
|
||||
List all admin users in Redis database:
|
||||
|
||||
$ turnadmin -L --redis-userdb="<db-connection-string>"
|
||||
|
||||
@@ -233,7 +233,7 @@ to see the man page.
|
||||
|
||||
Po-sheng Lin <personlin118@gmail.com>
|
||||
|
||||
Peter Dunkley <peter.dunkley@crocodilertc.net>
|
||||
Peter Dunkley <peter.dunkley@acision.com>
|
||||
|
||||
Mutsutoshi Yoshimoto <mutsutoshi.yoshimoto@mixi.co.jp>
|
||||
|
||||
|
||||
+32
-26
@@ -85,8 +85,8 @@ User database settings:
|
||||
/usr/local/var/db/turndb or /var/lib/turn/turndb).
|
||||
|
||||
-e, --psql-userdb User database connection string for PostgreSQL.
|
||||
This database can be used for long-term and short-term
|
||||
credentials mechanisms, and it can store the secret value
|
||||
This database can be used for long-term credentials mechanism,
|
||||
and it can store the secret value
|
||||
for secret-based timed authentication in TURN RESP API.
|
||||
The connection string format is like that:
|
||||
|
||||
@@ -103,8 +103,8 @@ User database settings:
|
||||
Also, see http://www.PostgreSQL.org for full PostgreSQL documentation.
|
||||
|
||||
-M, --mysql-userdb User database connection string for MySQL or MariaDB.
|
||||
This database can be used for long-term and short-term
|
||||
credentials mechanisms, and it can store the secret value for
|
||||
This database can be used for long-term credentials mechanism,
|
||||
and it can store the secret value for
|
||||
secret-based timed authentication in TURN RESP API.
|
||||
The connection string format is like that:
|
||||
|
||||
@@ -121,8 +121,8 @@ User database settings:
|
||||
command options description).
|
||||
|
||||
-J, --mongo-userdb User database connection string for MongoDB.
|
||||
This database can be used for long-term and short-term
|
||||
credentials mechanisms, and it can store the secret value
|
||||
This database can be used for long-term credentials mechanism,
|
||||
and it can store the secret value
|
||||
for secret-based timed authentication in TURN RESP API.
|
||||
The connection string format is like that:
|
||||
|
||||
@@ -134,8 +134,8 @@ User database settings:
|
||||
for full MongoDB documentation.
|
||||
|
||||
-N, --redis-userdb User database connection string for Redis.
|
||||
This database can be used for long-term and short-term
|
||||
credentials mechanisms, and it can store the secret
|
||||
This database can be used for long-term credentials mechanism,
|
||||
and it can store the secret
|
||||
value for secret-based timed authentication in TURN RESP API.
|
||||
The connection string format is like that:
|
||||
|
||||
@@ -160,8 +160,6 @@ Flags:
|
||||
|
||||
-a, --lt-cred-mech Use long-term credentials mechanism (this one you need for WebRTC usage).
|
||||
|
||||
-A, --st-cred-mech Use the short-term credentials mechanism.
|
||||
|
||||
-z, --no-auth Do not use any credentials mechanism, allow anonymous access.
|
||||
Opposite to -a and -A options. This is default option when no
|
||||
authentication-related options are set.
|
||||
@@ -182,8 +180,6 @@ Flags:
|
||||
This option is just turns on secret-based authentication.
|
||||
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.
|
||||
This option can be used with long-term credentials mechanisms only -
|
||||
it does not make much sense with the short-term mechanism.
|
||||
|
||||
--oauth Support oAuth authentication, as in the third-party TURN specs document.
|
||||
|
||||
@@ -191,8 +187,6 @@ Flags:
|
||||
|
||||
--dh2066 Use 2066 bits predefined DH TLS key. Default size of the key is 1066.
|
||||
|
||||
--no-sslv2 Do not allow SSLv2 protocol.
|
||||
|
||||
--no-sslv3 Do not allow SSLv3 protocol.
|
||||
|
||||
--no-tlsv1 Do not allow TLSv1/DTLSv1 protocol.
|
||||
@@ -300,7 +294,7 @@ Options with required values:
|
||||
endpoints (the "plain" one and the "tls" one) are equivalent in terms of
|
||||
functionality; but we keep both endpoints to satisfy the RFC 5766 specs.
|
||||
For secure TCP connections, we currently support SSL version 3 and
|
||||
TLS versions 1.0, 1.1, 1.2. SSL2 "encapsulation mode" is also supported.
|
||||
TLS versions 1.0, 1.1, 1.2.
|
||||
For secure UDP connections, we support DTLS version 1.
|
||||
|
||||
--alt-listening-port Alternative listening port for UDP and TCP listeners;
|
||||
@@ -382,8 +376,7 @@ Options with required values:
|
||||
the key must be prepended with 0x symbols.
|
||||
The key is calculated over the user name,
|
||||
the user realm, and the user password.
|
||||
This setting may not be used with TURN REST API or
|
||||
with short-term credentials mechanism.
|
||||
This setting may not be used with TURN REST API.
|
||||
|
||||
-r, --realm The default realm to be used for the users when no explicit
|
||||
origin/realm relationship was found in the database, or if the TURN
|
||||
@@ -560,8 +553,8 @@ WEBRTC USAGE
|
||||
This is a set of notes for the WebRTC users:
|
||||
|
||||
1) WebRTC uses long-term authentication mechanism, so you have to use -a
|
||||
option (or --lt-cred-mech). WebRTC relaying will not work with anonymous access
|
||||
or with short-term authentication. With -a option, do not forget to set the
|
||||
option (or --lt-cred-mech). WebRTC relaying will not work with anonymous
|
||||
access. With -a option, do not forget to set the
|
||||
default realm (-r option). You will also have to set up the user accounts,
|
||||
for that you have a number of options:
|
||||
|
||||
@@ -733,9 +726,7 @@ For long-term credentials, you have to set the "keys" for the users; the "keys"
|
||||
by the turnadmin utility. For the key generation, you need username, password and the realm.
|
||||
All users in the database must use the same realm value; if down the road you will decide
|
||||
to change the realm name, then you will have to re-generate all user keys (that can be done
|
||||
in a batch script). If you are using short-term credentials, then you use open passwords
|
||||
in the database; you will have to make sure that nobody can access the database outside of
|
||||
the TURN server box. See the file turndb/testsqldbsetup.sql as an example.
|
||||
in a batch script). See the file turndb/testsqldbsetup.sql as an example.
|
||||
|
||||
4) The same is true for MySQL database. The same schema file is applicable.
|
||||
The same considerations are applicable.
|
||||
@@ -744,8 +735,7 @@ The same considerations are applicable.
|
||||
it can be found (in the form of explanation) in schema.userdb.redis.
|
||||
Also, in Redis you can store both "keys" and open passwords (for long term credentials) -
|
||||
the "open password" option is less secure but more convenient for low-security environments.
|
||||
For short-term credentials, you will use open passwords only. See the file
|
||||
turndb/testredisdbsetup.sh as an example.
|
||||
See the file turndb/testredisdbsetup.sh as an example.
|
||||
|
||||
6) If a database is used, then users can be divided into multiple independent realms. Each realm
|
||||
can be administered separately, and each realm can have its own set of users and its own
|
||||
@@ -832,7 +822,23 @@ in the following directories:
|
||||
If all efforts failed (due to the system permission settings) then all
|
||||
log messages are sent only to the standard output of the process.
|
||||
|
||||
This behavior can be controlled by --log-file, --syslog and --no-stdout-log options.
|
||||
This behavior can be controlled by --log-file, --syslog and --no-stdout-log
|
||||
options.
|
||||
|
||||
=================================
|
||||
|
||||
HTTPS MANAGEMENT INTERFACE
|
||||
|
||||
The turnserver process provides an HTTPS Web access as statistics and basic
|
||||
management interface. The turnserver listens to incoming HTTPS admin
|
||||
connections on the same ports as the main TURN/STUN listener. The Web admin
|
||||
pages are basic and self-explanatory.
|
||||
|
||||
To make the HTTPS interface active, the database table admin_user must be
|
||||
populated with the admin user account(s). An admin user can be a superuser
|
||||
(if not assigned to a particular realm) or a restricted user (if assigned to
|
||||
a realm). The restricted admin users can perform only limited actions, within
|
||||
their corresponding realms.
|
||||
|
||||
=================================
|
||||
|
||||
@@ -941,7 +947,7 @@ https://groups.google.com/forum/?fromgroups=#!forum/turn-server-project-rfc5766-
|
||||
|
||||
Po-sheng Lin <personlin118@gmail.com>
|
||||
|
||||
Peter Dunkley <peter.dunkley@crocodilertc.net>
|
||||
Peter Dunkley <peter.dunkley@acision.com>
|
||||
|
||||
Mutsutoshi Yoshimoto <mutsutoshi.yoshimoto@mixi.co.jp>
|
||||
|
||||
|
||||
+1
-5
@@ -84,10 +84,6 @@ Flags:
|
||||
|
||||
-g Set DONT_FRAGMENT parameter in TURN requests.
|
||||
|
||||
-A use short-term credentials mechanism for authentication.
|
||||
By default, the program uses the long-term credentials mechanism
|
||||
if authentication is required.
|
||||
|
||||
-D Do mandatory channel padding even for UDP (like pjnath).
|
||||
|
||||
-N do negative tests (some limited cases only).
|
||||
@@ -329,7 +325,7 @@ SEE ALSO
|
||||
|
||||
Po-sheng Lin <personlin118@gmail.com>
|
||||
|
||||
Peter Dunkley <peter.dunkley@crocodilertc.net>
|
||||
Peter Dunkley <peter.dunkley@acision.com>
|
||||
|
||||
Mutsutoshi Yoshimoto <mutsutoshi.yoshimoto@mixi.co.jp>
|
||||
|
||||
|
||||
@@ -112,6 +112,13 @@ compatibility.
|
||||
48) DTLS1.2 supported.
|
||||
|
||||
49) ALPN stun.turn and stun.nat-discovery supported.
|
||||
|
||||
50) SSLv2 support cancelled.
|
||||
|
||||
51) The short-term credentials server-side support cancelled (still
|
||||
supported in the client library).
|
||||
|
||||
52) Web HTTPS admin interface implemented.
|
||||
|
||||
Things to be implemented in future (the development roadmap)
|
||||
are described in the TODO file.
|
||||
|
||||
@@ -75,23 +75,14 @@
|
||||
deeply "hidden" in the network infrastructure that the
|
||||
significant code complication may be unjustified.
|
||||
|
||||
2) HTTP or GUI status monitor and management.
|
||||
|
||||
For enterprise users, a management (configuration, status
|
||||
and statistics) GUI has to be implemented. Currently, all
|
||||
these features are available through the shell command
|
||||
line, telnet client and through Redis command line.
|
||||
|
||||
3) Traffic recording (for selected allocations).
|
||||
2) Traffic recording (for selected allocations).
|
||||
|
||||
That would be a helpful feature for a large enterprise
|
||||
(for testing and security purposes).
|
||||
|
||||
4) Ganglia monitoring.
|
||||
3) Ganglia monitoring.
|
||||
|
||||
5) Web API to the database (oAuth keys, for example).
|
||||
|
||||
6) Key exchange mechanism for oAuth.
|
||||
4) Key exchange mechanism for oAuth.
|
||||
|
||||
==================================================================
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
# endpoints (the "plain" one and the "tls" one) are equivalent in terms of
|
||||
# functionality; but we keep both endpoints to satisfy the RFC 5766 specs.
|
||||
# For secure TCP connections, we currently support SSL version 3 and
|
||||
# TLS version 1.0, 1.1 and 1.2. SSL2 "encapculation mode" is also supported.
|
||||
# TLS version 1.0, 1.1 and 1.2.
|
||||
# For secure UDP connections, we support DTLS version 1.
|
||||
#
|
||||
#tls-listening-port=5349
|
||||
@@ -169,11 +169,6 @@
|
||||
#
|
||||
#lt-cred-mech
|
||||
|
||||
# Uncomment to use short-term credential mechanism.
|
||||
# By default no credentials mechanism is used (any user allowed).
|
||||
#
|
||||
#st-cred-mech
|
||||
|
||||
# This option is opposite to lt-cred-mech or st-cred-mech.
|
||||
# (TURN Server with no-auth option allows anonymous access).
|
||||
# If neither option is defined, and no users are defined,
|
||||
@@ -218,13 +213,12 @@
|
||||
#
|
||||
#server-name=blackdow.carleon.gov
|
||||
|
||||
# Flag to support oAuth authentication.
|
||||
# Flag that allows oAuth authentication.
|
||||
#
|
||||
#oauth
|
||||
|
||||
# 'Static' user accounts for long term credentials mechanism, only.
|
||||
# This option cannot be used with TURN REST API or with short-term credentials
|
||||
# mechanism.
|
||||
# This option cannot be used with TURN REST API.
|
||||
# 'Static' user accounts are NOT dynamically checked by the turnserver process,
|
||||
# so that they can NOT be changed while the turnserver is running.
|
||||
#
|
||||
@@ -259,7 +253,7 @@
|
||||
|
||||
# PostgreSQL database connection string in the case that we are using PostgreSQL
|
||||
# as the user database.
|
||||
# This database can be used for long-term and short-term credential mechanisms
|
||||
# This database can be used for long-term credential mechanism
|
||||
# and it can store the secret value for secret-based timed authentication in TURN RESP API.
|
||||
# See http://www.postgresql.org/docs/8.4/static/libpq-connect.html for 8.x PostgreSQL
|
||||
# versions connection string format, see
|
||||
@@ -270,7 +264,7 @@
|
||||
|
||||
# MySQL database connection string in the case that we are using MySQL
|
||||
# as the user database.
|
||||
# This database can be used for long-term and short-term credential mechanisms
|
||||
# This database can be used for long-term credential mechanism
|
||||
# and it can store the secret value for secret-based timed authentication in TURN RESP API.
|
||||
#
|
||||
# Optional connection string parameters for the secure communications (SSL):
|
||||
@@ -284,7 +278,7 @@
|
||||
|
||||
# MongoDB database connection string in the case that we are using MongoDB
|
||||
# as the user database.
|
||||
# This database can be used for long-term and short-term credential mechanisms
|
||||
# This database can be used for long-term credential mechanism
|
||||
# and it can store the secret value for secret-based timed authentication in TURN RESP API.
|
||||
# Use string format is described at http://hergert.me/docs/mongo-c-driver/mongoc_uri.html
|
||||
#
|
||||
@@ -292,7 +286,7 @@
|
||||
|
||||
# Redis database connection string in the case that we are using Redis
|
||||
# as the user database.
|
||||
# This database can be used for long-term and short-term credential mechanisms
|
||||
# This database can be used for long-term credential mechanism
|
||||
# and it can store the secret value for secret-based timed authentication in TURN RESP API.
|
||||
# Use string format as below (space separated parameters, all optional):
|
||||
#
|
||||
@@ -625,7 +619,6 @@
|
||||
|
||||
# Do not allow an SSL/TLS/DTLS version of protocol
|
||||
#
|
||||
#no-sslv2
|
||||
#no-sslv3
|
||||
#no-tlsv1
|
||||
#no-tlsv1_1
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
# 9) "--pkey=turn_server_pkey.pem" sets the OpenSSL private key name.
|
||||
# 10) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 11) "-v" means normal verbose mode (with some moderate logging).
|
||||
# 12) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2
|
||||
# 12) --cipher-list=ALL means that we support all OpenSSL ciphers
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -32,4 +32,4 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 10 --min-port=32355 --max-port=65535 --user=ninefingers:youhavetoberealistic --user=gorst:hero -r north.gov --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout -v --cipher-list=ALL:SSLv2 $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 10 --min-port=32355 --max-port=65535 --user=ninefingers:youhavetoberealistic --user=gorst:hero -r north.gov --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout -v --cipher-list=ALL $@
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
# 10) --CA-file sets the CA file for client certificate check.
|
||||
# 11) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 12) "-v" means normal verbose mode (with some moderate logging).
|
||||
# 13) --cipher-list="ALL:SSLv2:!eNULL:!aNULL:!NULL" measn "all ciphers, except anonymous".
|
||||
# 13) --cipher-list="ALL:!eNULL:!aNULL:!NULL" measn "all ciphers, except anonymous".
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -35,4 +35,4 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 10 --min-port=32355 --max-port=65535 --user=ninefingers:youhavetoberealistic --user=bolt:kwyjibo -r bolt.co --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --CA-file=turn_server_cert.pem --log-file=stdout -v --cipher-list="ALL:SSLv2:!eNULL:!aNULL:!NULL" $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 10 --min-port=32355 --max-port=65535 --user=ninefingers:youhavetoberealistic --user=bolt:kwyjibo -r bolt.co --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --CA-file=turn_server_cert.pem --log-file=stdout -v --cipher-list="ALL:!eNULL:!aNULL:!NULL" $@
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
# 7) "--cert=example_turn_server_cert.pem" sets the OpenSSL certificate file name.
|
||||
# 8) "--pkey=example_turn_server_pkey.pem" sets the OpenSSL private key name.
|
||||
# 9) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 10) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2
|
||||
# 11) --oauth - accept oAuth security dialog
|
||||
# 10) --cipher-list=ALL means that we support all OpenSSL ciphers
|
||||
# 11) --oauth - mandate oAuth security dialog
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -31,4 +31,4 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --mongo-userdb="mongodb://localhost/coturn" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 --oauth $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --mongo-userdb="mongodb://localhost/coturn" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL --oauth $@
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
# 7) "--cert=example_turn_server_cert.pem" sets the OpenSSL certificate file name.
|
||||
# 8) "--pkey=example_turn_server_pkey.pem" sets the OpenSSL private key name.
|
||||
# 9) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 10) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2
|
||||
# 11) --oauth - accept oAuth security dialog
|
||||
# 10) --cipher-list=ALL means that we support all OpenSSL ciphers
|
||||
# 11) --oauth - mandate oAuth security dialog
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -32,4 +32,4 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 --oauth $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL --oauth $@
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
# 7) "--cert=example_turn_server_cert.pem" sets the OpenSSL certificate file name.
|
||||
# 8) "--pkey=example_turn_server_pkey.pem" sets the OpenSSL private key name.
|
||||
# 9) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 10) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2
|
||||
# 11) --oauth - accept oAuth security dialog
|
||||
# 10) --cipher-list=ALL means that we support all OpenSSL ciphers
|
||||
# 11) --oauth - mandate oAuth security dialog
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -33,4 +33,4 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --mysql-userdb="host=localhost dbname=coturn user=turn password=turn cipher=DHE-RSA-AES256-SHA connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 --oauth $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --mysql-userdb="host=localhost dbname=coturn user=turn password=turn cipher=DHE-RSA-AES256-SHA connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL --oauth $@
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
# 7) "--cert=example_turn_server_cert.pem" sets the OpenSSL certificate file name.
|
||||
# 8) "--pkey=example_turn_server_pkey.pem" sets the OpenSSL private key name.
|
||||
# 9) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 10) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2
|
||||
# 11) --oauth - accept oAuth security dialog
|
||||
# 10) --cipher-list=ALL means that we support all OpenSSL ciphers
|
||||
# 11) --oauth - mandate oAuth security dialog
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -32,7 +32,7 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --psql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 --oauth $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --psql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL --oauth $@
|
||||
|
||||
# Newer PostgreSQL style connection string example:
|
||||
# PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --psql-userdb=postgresql://turn:turn@/turn --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 --oauth $@
|
||||
# PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --psql-userdb=postgresql://turn:turn@/turn --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL --oauth $@
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
# 8) "--cert=example_turn_server_cert.pem" sets the OpenSSL certificate file name.
|
||||
# 9) "--pkey=example_turn_server_pkey.pem" sets the OpenSSL private key name.
|
||||
# 10) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 11) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2
|
||||
# 12) --oauth - accept oAuth security dialog
|
||||
# 11) --cipher-list=ALL means that we support all OpenSSL ciphers
|
||||
# 12) --oauth - mandate oAuth security dialog
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -35,4 +35,4 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --redis-userdb="ip=127.0.0.1 dbname=2 password=turn connect_timeout=30" --redis-statsdb="ip=127.0.0.1 dbname=3 password=turn connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 --oauth $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --redis-userdb="ip=127.0.0.1 dbname=2 password=turn connect_timeout=30" --redis-statsdb="ip=127.0.0.1 dbname=3 password=turn connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL --oauth $@
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
# 7) "--cert=example_turn_server_cert.pem" sets the OpenSSL certificate file name.
|
||||
# 8) "--pkey=example_turn_server_pkey.pem" sets the OpenSSL private key name.
|
||||
# 9) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 10) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2
|
||||
# 11) --oauth - accept oAuth security dialog
|
||||
# 10) --cipher-list=ALL means that we support all OpenSSL ciphers
|
||||
# 11) --oauth - mandate oAuth security dialog
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -31,5 +31,5 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --db="var/db/turndb" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 --oauth $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --db="var/db/turndb" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL --oauth $@
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
# 10) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 11) "-v" means normal verbose mode (with some moderate logging).
|
||||
# 12) "--mobility" turns on the Mobile ICE TURN functionality.
|
||||
# 13) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2
|
||||
# 13) --cipher-list=ALL means that we support all OpenSSL ciphers
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -33,4 +33,4 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 10 --min-port=32355 --max-port=65535 --user=ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee --user=gorst:hero -r north.gov --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout -v --mobility --cipher-list=ALL:SSLv2 $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 10 --min-port=32355 --max-port=65535 --user=ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee --user=gorst:hero -r north.gov --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout -v --mobility --cipher-list=ALL $@
|
||||
|
||||
@@ -6,8 +6,8 @@ functionality illustration.
|
||||
2) "basic" directory contains set of scripts which works together to demonstrate
|
||||
very basic anynymous functionality of the TURN server. The "peer.sh" must be used, too.
|
||||
|
||||
3) "longtermsecure" directory contains set of scripts demonstrating the long-term authentication
|
||||
mechanism (peer.sh to be used, too).
|
||||
3) "longtermsecure" directory contains set of scripts demonstrating the long-term
|
||||
authentication mechanism (peer.sh to be used, too).
|
||||
|
||||
4) "longtermsecuredb" shows how to start TURN server with database. The clients from the
|
||||
directory "longtermsecure" can be used with the relay scripts in the "longtermsecuredb"
|
||||
@@ -16,11 +16,13 @@ be set for these scripts to work correctly.
|
||||
|
||||
5) "restapi" shows how to use TURN REST API.
|
||||
|
||||
6) "shorttermsecure" shows how to use the short-term authentication mechanism. The short term
|
||||
mechanism is always used with the database.
|
||||
|
||||
7) "loadbalance" shows how to use the simple load-balancing mechanism based upon the
|
||||
6) "loadbalance" shows how to use the simple load-balancing mechanism based upon the
|
||||
ALTERNATE-SERVER functionality.
|
||||
|
||||
7) "selfloadbalance" shows how to use the "self-load-balance" TURN server capabilities.
|
||||
|
||||
8) "mobile" shows the "mobile" connections - how the TURN session can change its client
|
||||
address.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
# 10) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 11) "-q 100" means that single user can create no more than 100 sessions
|
||||
# 12) "-Q 300" means that there may be no more than 300 sessions totally
|
||||
# 13) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2.
|
||||
# 13) --cipher-list=ALL means that we support all OpenSSL ciphers
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -32,5 +32,5 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --use-auth-secret --static-auth-secret=logen --realm=north.gov --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout -q 100 -Q 300 --cipher-list=ALL:SSLv2 $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --use-auth-secret --static-auth-secret=logen --realm=north.gov --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout -q 100 -Q 300 --cipher-list=ALL $@
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
# 8) "--cert=example_turn_server_cert.pem" sets the OpenSSL certificate file name.
|
||||
# 9) "--pkey=example_turn_server_pkey.pem" sets the OpenSSL private key name.
|
||||
# 10) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 11) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2
|
||||
# 11) --cipher-list=ALL means that we support all OpenSSL ciphers
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -34,4 +34,4 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --use-auth-secret --realm=north.gov --mongo-userdb="mongodb://localhost/coturn" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --use-auth-secret --realm=north.gov --mongo-userdb="mongodb://localhost/coturn" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL $@
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
# 8) "--cert=example_turn_server_cert.pem" sets the OpenSSL certificate file name.
|
||||
# 9) "--pkey=example_turn_server_pkey.pem" sets the OpenSSL private key name.
|
||||
# 10) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 11) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2
|
||||
# 11) --cipher-list=ALL means that we support all OpenSSL ciphers
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -35,4 +35,4 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --use-auth-secret --realm=north.gov --mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --use-auth-secret --realm=north.gov --mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL $@
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
# 8) "--cert=example_turn_server_cert.pem" sets the OpenSSL certificate file name.
|
||||
# 9) "--pkey=example_turn_server_pkey.pem" sets the OpenSSL private key name.
|
||||
# 10) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 11) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2.
|
||||
# 11) --cipher-list=ALL means that we support all OpenSSL ciphers
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -35,4 +35,4 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --use-auth-secret --realm=north.gov --psql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --use-auth-secret --realm=north.gov --psql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL $@
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
# 8) "--cert=example_turn_server_cert.pem" sets the OpenSSL certificate file name.
|
||||
# 9) "--pkey=example_turn_server_pkey.pem" sets the OpenSSL private key name.
|
||||
# 10) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 11) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2.
|
||||
# 11) --cipher-list=ALL means that we support all OpenSSL ciphers
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -35,4 +35,4 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --use-auth-secret --realm=north.gov --redis-userdb="ip=127.0.0.1 dbname=2 password=turn connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --redis-statsdb="ip=127.0.0.1 dbname=3 password=turn connect_timeout=30" --cipher-list=ALL:SSLv2 $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --use-auth-secret --realm=north.gov --redis-userdb="ip=127.0.0.1 dbname=2 password=turn connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --redis-statsdb="ip=127.0.0.1 dbname=3 password=turn connect_timeout=30" --cipher-list=ALL $@
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
# 8) "--cert=example_turn_server_cert.pem" sets the OpenSSL certificate file name.
|
||||
# 9) "--pkey=example_turn_server_pkey.pem" sets the OpenSSL private key name.
|
||||
# 10) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 11) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2
|
||||
# 11) --cipher-list=ALL means that we support all OpenSSL ciphers
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -34,4 +34,4 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --use-auth-secret --realm=north.gov --db="var/db/turndb" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --use-auth-secret --realm=north.gov --db="var/db/turndb" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL $@
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
# 11) "--pkey=example_turn_server_pkey.pem" sets the OpenSSL private key name.
|
||||
# 12) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 13) "-v" means normal verbose mode (with some moderate logging).
|
||||
# 14) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2.
|
||||
# 14) --cipher-list=ALL means that we support all OpenSSL ciphers
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
@@ -39,4 +39,4 @@ fi
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --aux-server=127.0.0.1:12345 --aux-server=[::1]:12345 --aux-server=127.0.0.1:12346 --aux-server=[::1]:12346 --udp-self-balance --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 10 --min-port=32355 --max-port=65535 --user=ninefingers:youhavetoberealistic --user=gorst:hero -r north.gov --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 $@
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --aux-server=127.0.0.1:12345 --aux-server=[::1]:12345 --aux-server=127.0.0.1:12346 --aux-server=[::1]:12346 --udp-self-balance --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 10 --min-port=32355 --max-port=65535 --user=ninefingers:youhavetoberealistic --user=gorst:hero -r north.gov --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL $@
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# This is an example how to start a TURN Server in
|
||||
# secure mode with short-term security mechanism - see option -A
|
||||
# that means "use short-term credential mechanism".
|
||||
#
|
||||
# The user credentials are stored in the database.
|
||||
#
|
||||
# We listen on available interfaces here, and we use the "external" IPs
|
||||
# for relay endpoints allocation.
|
||||
#
|
||||
# Other options:
|
||||
#
|
||||
# 1) set bandwidth limit on client session 3000000 bytes per second (--max-bps).
|
||||
# 2) use fingerprints (-f)
|
||||
# 3) use 3 relay threads (-m 3)
|
||||
# 4) use min UDP relay port 32355 and max UDP relay port 65535
|
||||
# 5) --db="var/db/turndb" means that SQLite database "var/db/turndb" will be used.
|
||||
# 6) "--cert=example_turn_server_cert.pem" sets the OpenSSL certificate file name.
|
||||
# 7) "--pkey=example_turn_server_pkey.pem" sets the OpenSSL private key name.
|
||||
# 8) "--log-file=stdout" means that all log output will go to the stdout.
|
||||
# 9) -E 127.0.0.1 and -E :;1 sets the relay addresses, in this case for loopback
|
||||
# communications only.
|
||||
# 10) --cipher-list=ALL:SSLv2 means that we support all OpenSSL ciphers, including SSLv2.
|
||||
# Other parameters (config file name, etc) are default.
|
||||
|
||||
if [ -d examples ] ; then
|
||||
cd examples
|
||||
fi
|
||||
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
|
||||
|
||||
PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -A --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --db="var/db/turndb" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout -E 127.0.0.1 -E ::1 --cipher-list=ALL:SSLv2 $@
|
||||
@@ -1,31 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# This is an example of a script to run a "secure" TURN TCP client
|
||||
# with the short-term credentials mechanism and with
|
||||
# TCP relay endpoints (RFC 6062).
|
||||
#
|
||||
# Options:
|
||||
#
|
||||
# 1) -T is present, it means that TCP networking is used, with TCP relay endpoints (RFC 6062).
|
||||
# 5) -n 1000 means 1000 messages per single emulated client. Messages
|
||||
# are sent with interval of 20 milliseconds, to emulate an RTP stream.
|
||||
# 6) -m 10 means that 10 clients are emulated.
|
||||
# 7) -l 170 means that the payload size of the packets is 170 bytes
|
||||
# (like average audio RTP packet).
|
||||
# 8) -y means that the clients will connect to the 'neighbor' clients, no peer app will be used.
|
||||
# 9) -g means "set DONT_FRAGMENT parameter in TURN requests".
|
||||
# 10) -A sets the short-term credentials mechanism.
|
||||
# 11) -u gorst sets the client user name.
|
||||
# 12) -w hero sets the password for the account as "hero".
|
||||
# 13) ::1 (the last parameter) is the TURN Server IP address. We use IPv6 here
|
||||
# to illustrate how the TURN Server convert the traffic from IPv6 to IPv4 and back.
|
||||
#
|
||||
|
||||
if [ -d examples ] ; then
|
||||
cd examples
|
||||
fi
|
||||
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/
|
||||
|
||||
PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -T -n 1000 -m 10 -l 170 -y -g -A -u gorst -w hero $@ ::1
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# This is an example of a script to run a "secure" TURN UDP client
|
||||
# with short-term credential mechanism.
|
||||
#
|
||||
# Options:
|
||||
#
|
||||
# 1) -t is absent, it means that UDP networking is used.
|
||||
# 5) -n 1000 means 1000 messages per single emulated client. Messages
|
||||
# are sent with interval of 20 milliseconds, to emulate an RTP stream.
|
||||
# 6) -m 10 means that 10 clients are emulated.
|
||||
# 7) -l 170 means that the payload size of the packets is 170 bytes
|
||||
# (like average audio RTP packet).
|
||||
# 8) -e 127.0.0.1 means that the clients will use peer address 127.0.0.1.
|
||||
# 9) -g means "set DONT_FRAGMENT parameter in TURN requests".
|
||||
# 10) -A means that the short-term credentials mechanism is used.
|
||||
# 11) -u ninefingers sets the client user name.
|
||||
# 12) -w youhavetoberealistic sets the password for the user account as "youhavetoberealistic".
|
||||
# 13) -s option means that the client will be using "send" indication for data trasfer.
|
||||
# 14) ::1 (the last parameter) is the TURN Server IP address. We use IPv6 here
|
||||
# to illustrate how the TURN Server convert the traffic from IPv6 to IPv4 and back.
|
||||
#
|
||||
|
||||
if [ -d examples ] ; then
|
||||
cd examples
|
||||
fi
|
||||
|
||||
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/
|
||||
|
||||
PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -n 1000 -m 10 -l 170 -e 127.0.0.1 -X -g -A -u ninefingers -w youhavetoberealistic -s $@ ::1
|
||||
Binary file not shown.
+10
-10
@@ -1,5 +1,5 @@
|
||||
.\" Text automatically generated by txt2man
|
||||
.TH TURN 1 "14 December 2014" "" ""
|
||||
.TH TURN 1 "24 January 2015" "" ""
|
||||
.SH GENERAL INFORMATION
|
||||
|
||||
\fIturnadmin\fP is a TURN administration tool. This tool can be used to manage
|
||||
@@ -74,24 +74,24 @@ Generate key for a long\-term credentials mechanism user.
|
||||
Add or update a long\-term user.
|
||||
.TP
|
||||
.B
|
||||
\fB\-A\fP, \fB\-\-add\-st\fP
|
||||
Add or update a short\-term credentials mechanism user.
|
||||
\fB\-A\fP, \fB\-\-add\-admin\fP
|
||||
Add or update an admin user.
|
||||
.TP
|
||||
.B
|
||||
\fB\-d\fP, \fB\-\-delete\fP
|
||||
Delete a long\-term user.
|
||||
.TP
|
||||
.B
|
||||
\fB\-D\fP, \fB\-\-delete\-st\fP
|
||||
Delete a short\-term user.
|
||||
\fB\-D\fP, \fB\-\-delete\-admin\fP
|
||||
Delete an admin user.
|
||||
.TP
|
||||
.B
|
||||
\fB\-l\fP, \fB\-\-list\fP
|
||||
List long\-term users in the database.
|
||||
.TP
|
||||
.B
|
||||
\fB\-L\fP, \fB\-\-list\-st\fP
|
||||
List short\-term users in the database.
|
||||
\fB\-L\fP, \fB\-\-list\-admin\fP
|
||||
List admin users in the database.
|
||||
.PP
|
||||
\fB\-s\fP, \fB\-\-set\-secret\fP=<value> Add shared secret for TURN RESP API
|
||||
.TP
|
||||
@@ -162,7 +162,7 @@ User name.
|
||||
.TP
|
||||
.B
|
||||
\fB\-r\fP, \fB\-\-realm\fP
|
||||
Realm, for long\-term credentials mechanism only.
|
||||
Realm.
|
||||
.TP
|
||||
.B
|
||||
\fB\-p\fP, \fB\-\-password\fP
|
||||
@@ -211,7 +211,7 @@ List all long\-term users in MySQL database:
|
||||
.PP
|
||||
$ \fIturnadmin\fP \fB\-l\fP \fB\-\-mysql\-userdb\fP="<db\-connection\-string>" \fB\-r\fP <realm>
|
||||
.PP
|
||||
List all short\-term users in Redis database:
|
||||
List all admin users in Redis database:
|
||||
.PP
|
||||
$ \fIturnadmin\fP \fB\-L\fP \fB\-\-redis\-userdb\fP="<db\-connection\-string>"
|
||||
.PP
|
||||
@@ -322,7 +322,7 @@ Vladimir Tsanev <tsachev@gmail.com>
|
||||
.PP
|
||||
Po\-sheng Lin <personlin118@gmail.com>
|
||||
.PP
|
||||
Peter Dunkley <peter.dunkley@crocodilertc.net>
|
||||
Peter Dunkley <peter.dunkley@acision.com>
|
||||
.PP
|
||||
Mutsutoshi Yoshimoto <mutsutoshi.yoshimoto@mixi.co.jp>
|
||||
.PP
|
||||
|
||||
+32
-31
@@ -1,5 +1,5 @@
|
||||
.\" Text automatically generated by txt2man
|
||||
.TH TURN 1 "14 December 2014" "" ""
|
||||
.TH TURN 1 "24 January 2015" "" ""
|
||||
.SH GENERAL INFORMATION
|
||||
|
||||
The \fBTURN Server\fP project contains the source code of a TURN server and TURN client
|
||||
@@ -138,8 +138,8 @@ SQLite user database file name (default \- /var/db/turndb or
|
||||
.B
|
||||
\fB\-e\fP, \fB\-\-psql\-userdb\fP
|
||||
User database connection string for PostgreSQL.
|
||||
This database can be used for long\-term and short\-term
|
||||
credentials mechanisms, and it can store the secret value
|
||||
This database can be used for long\-term credentials mechanism,
|
||||
and it can store the secret value
|
||||
for secret\-based timed authentication in TURN RESP API.
|
||||
The connection string format is like that:
|
||||
.RS
|
||||
@@ -160,8 +160,8 @@ Also, see http://www.PostgreSQL.org for full PostgreSQL documentation.
|
||||
.B
|
||||
\fB\-M\fP, \fB\-\-mysql\-userdb\fP
|
||||
User database connection string for MySQL or MariaDB.
|
||||
This database can be used for long\-term and short\-term
|
||||
credentials mechanisms, and it can store the secret value for
|
||||
This database can be used for long\-term credentials mechanism,
|
||||
and it can store the secret value for
|
||||
secret\-based timed authentication in TURN RESP API.
|
||||
The connection string format is like that:
|
||||
.RS
|
||||
@@ -182,8 +182,8 @@ command \fIoptions\fP description).
|
||||
.B
|
||||
\fB\-J\fP, \fB\-\-mongo\-userdb\fP
|
||||
User database connection string for MongoDB.
|
||||
This database can be used for long\-term and short\-term
|
||||
credentials mechanisms, and it can store the secret value
|
||||
This database can be used for long\-term credentials mechanism,
|
||||
and it can store the secret value
|
||||
for secret\-based timed authentication in TURN RESP API.
|
||||
The connection string format is like that:
|
||||
.RS
|
||||
@@ -199,8 +199,8 @@ for full MongoDB documentation.
|
||||
.B
|
||||
\fB\-N\fP, \fB\-\-redis\-userdb\fP
|
||||
User database connection string for Redis.
|
||||
This database can be used for long\-term and short\-term
|
||||
credentials mechanisms, and it can store the secret
|
||||
This database can be used for long\-term credentials mechanism,
|
||||
and it can store the secret
|
||||
value for secret\-based timed authentication in TURN RESP API.
|
||||
The connection string format is like that:
|
||||
.RS
|
||||
@@ -239,10 +239,6 @@ per\-server setting.
|
||||
Use long\-term credentials mechanism (this one you need for WebRTC usage).
|
||||
.TP
|
||||
.B
|
||||
\fB\-A\fP, \fB\-\-st\-cred\-mech\fP
|
||||
Use the short\-term credentials mechanism.
|
||||
.TP
|
||||
.B
|
||||
\fB\-z\fP, \fB\-\-no\-auth\fP
|
||||
Do not use any credentials mechanism, allow anonymous access.
|
||||
Opposite to \fB\-a\fP and \fB\-A\fP \fIoptions\fP. This is default option when no
|
||||
@@ -266,8 +262,6 @@ If you don't have a suitable id, the timestamp alone can be used.
|
||||
This option is just turns on secret\-based authentication.
|
||||
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.
|
||||
This option can be used with long\-term credentials mechanisms only \-
|
||||
it does not make much sense with the short\-term mechanism.
|
||||
.TP
|
||||
.B
|
||||
\fB\-\-oauth\fP
|
||||
@@ -282,10 +276,6 @@ Use 566 bits predefined DH TLS key. Default size of the key is 1066.
|
||||
Use 2066 bits predefined DH TLS key. Default size of the key is 1066.
|
||||
.TP
|
||||
.B
|
||||
\fB\-\-no\-sslv2\fP
|
||||
Do not allow SSLv2 protocol.
|
||||
.TP
|
||||
.B
|
||||
\fB\-\-no\-sslv3\fP
|
||||
Do not allow SSLv3 protocol.
|
||||
.TP
|
||||
@@ -453,7 +443,7 @@ Note: actually, "plain" TCP & UDP sessions can connect to the TLS & DTLS
|
||||
endpoints (the "plain" one and the "tls" one) are equivalent in terms of
|
||||
functionality; but we keep both endpoints to satisfy the RFC 5766 specs.
|
||||
For secure TCP connections, we currently support SSL version 3 and
|
||||
TLS versions 1.0, 1.1, 1.2. SSL2 "encapsulation mode" is also supported.
|
||||
TLS versions 1.0, 1.1, 1.2.
|
||||
For secure UDP connections, we support DTLS version 1.
|
||||
.TP
|
||||
.B
|
||||
@@ -559,8 +549,7 @@ by \fIturnadmin\fP command. In the second case,
|
||||
the key must be prepended with 0x symbols.
|
||||
The key is calculated over the user name,
|
||||
the user realm, and the user password.
|
||||
This setting may not be used with TURN REST API or
|
||||
with short\-term credentials mechanism.
|
||||
This setting may not be used with TURN REST API.
|
||||
.TP
|
||||
.B
|
||||
\fB\-r\fP, \fB\-\-realm\fP
|
||||
@@ -796,8 +785,8 @@ http://code.google.com/p/coturn/wiki/turn_performance_and_load_balance
|
||||
This is a set of notes for the WebRTC users:
|
||||
.IP 1) 4
|
||||
WebRTC uses long\-term authentication mechanism, so you have to use \fB\-a\fP
|
||||
option (or \fB\-\-lt\-cred\-mech\fP). WebRTC relaying will not work with anonymous access
|
||||
or with short\-term authentication. With \fB\-a\fP option, do not forget to set the
|
||||
option (or \fB\-\-lt\-cred\-mech\fP). WebRTC relaying will not work with anonymous
|
||||
access. With \fB\-a\fP option, do not forget to set the
|
||||
default realm (\fB\-r\fP option). You will also have to set up the user accounts,
|
||||
for that you have a number of \fIoptions\fP:
|
||||
.PP
|
||||
@@ -988,9 +977,7 @@ For long\-term credentials, you have to set the "keys" for the users; the "keys"
|
||||
by the \fIturnadmin\fP utility. For the key generation, you need username, password and the realm.
|
||||
All users in the database must use the same realm value; if down the road you will decide
|
||||
to change the realm name, then you will have to re\-generate all user keys (that can be done
|
||||
in a batch script). If you are using short\-term credentials, then you use open passwords
|
||||
in the database; you will have to make sure that nobody can access the database outside of
|
||||
the TURN server box. See the file turndb/testsqldbsetup.sql as an example.
|
||||
in a batch script). See the file turndb/testsqldbsetup.sql as an example.
|
||||
.IP 4) 4
|
||||
The same is true for MySQL database. The same schema file is applicable.
|
||||
The same considerations are applicable.
|
||||
@@ -999,8 +986,7 @@ The same is true for the Redis database, but the Redis database has aa different
|
||||
it can be found (in the form of explanation) in schema.userdb.redis.
|
||||
Also, in Redis you can store both "keys" and open passwords (for long term credentials) \-
|
||||
the "open password" option is less secure but more convenient for low\-security environments.
|
||||
For short\-term credentials, you will use open passwords only. See the file
|
||||
turndb/testredisdbsetup.sh as an example.
|
||||
See the file turndb/testredisdbsetup.sh as an example.
|
||||
.IP 6) 4
|
||||
If a database is used, then users can be divided into multiple independent realms. Each realm
|
||||
can be administered separately, and each realm can have its own set of users and its own
|
||||
@@ -1089,7 +1075,22 @@ current directory
|
||||
If all efforts failed (due to the system permission settings) then all
|
||||
log messages are sent only to the standard output of the process.
|
||||
.PP
|
||||
This behavior can be controlled by \fB\-\-log\-file\fP, \fB\-\-syslog\fP and \fB\-\-no\-stdout\-log\fP \fIoptions\fP.
|
||||
This behavior can be controlled by \fB\-\-log\-file\fP, \fB\-\-syslog\fP and \fB\-\-no\-stdout\-log\fP
|
||||
\fIoptions\fP.
|
||||
.PP
|
||||
=================================
|
||||
.SH HTTPS MANAGEMENT INTERFACE
|
||||
|
||||
The \fIturnserver\fP process provides an HTTPS Web access as statistics and basic
|
||||
management interface. The \fIturnserver\fP listens to incoming HTTPS admin
|
||||
connections on the same ports as the main TURN/STUN listener. The Web admin
|
||||
pages are basic and self\-explanatory.
|
||||
.PP
|
||||
To make the HTTPS interface active, the database table admin_user must be
|
||||
populated with the admin user \fBaccount\fP(s). An admin user can be a superuser
|
||||
(if not assigned to a particular realm) or a restricted user (if assigned to
|
||||
a realm). The restricted admin users can perform only limited actions, within
|
||||
their corresponding realms.
|
||||
.PP
|
||||
=================================
|
||||
.SH TELNET CLI
|
||||
@@ -1191,7 +1192,7 @@ Vladimir Tsanev <tsachev@gmail.com>
|
||||
.PP
|
||||
Po\-sheng Lin <personlin118@gmail.com>
|
||||
.PP
|
||||
Peter Dunkley <peter.dunkley@crocodilertc.net>
|
||||
Peter Dunkley <peter.dunkley@acision.com>
|
||||
.PP
|
||||
Mutsutoshi Yoshimoto <mutsutoshi.yoshimoto@mixi.co.jp>
|
||||
.PP
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.\" Text automatically generated by txt2man
|
||||
.TH TURN 1 "14 December 2014" "" ""
|
||||
.TH TURN 1 "24 January 2015" "" ""
|
||||
.SH GENERAL INFORMATION
|
||||
|
||||
A set of turnutils_* programs provides some utility functionality to be used
|
||||
@@ -122,12 +122,6 @@ IPv4 relay address explicitly requested.
|
||||
Set DONT_FRAGMENT parameter in TURN requests.
|
||||
.TP
|
||||
.B
|
||||
\fB\-A\fP
|
||||
use short\-term credentials mechanism for authentication.
|
||||
By default, the program uses the long\-term credentials mechanism
|
||||
if authentication is required.
|
||||
.TP
|
||||
.B
|
||||
\fB\-D\fP
|
||||
Do mandatory channel padding even for UDP (like pjnath).
|
||||
.TP
|
||||
@@ -449,7 +443,7 @@ Vladimir Tsanev <tsachev@gmail.com>
|
||||
.PP
|
||||
Po\-sheng Lin <personlin118@gmail.com>
|
||||
.PP
|
||||
Peter Dunkley <peter.dunkley@crocodilertc.net>
|
||||
Peter Dunkley <peter.dunkley@acision.com>
|
||||
.PP
|
||||
Mutsutoshi Yoshimoto <mutsutoshi.yoshimoto@mixi.co.jp>
|
||||
.PP
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# Common settings script.
|
||||
|
||||
TURNVERSION=4.3.3.1
|
||||
TURNVERSION=4.4.1.1
|
||||
BUILDDIR=~/rpmbuild
|
||||
ARCH=`uname -p`
|
||||
TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn
|
||||
|
||||
+4
-8
@@ -1,5 +1,5 @@
|
||||
Name: turnserver
|
||||
Version: 4.3.3.1
|
||||
Version: 4.4.1.1
|
||||
Release: 0%{dist}
|
||||
Summary: Coturn TURN Server
|
||||
|
||||
@@ -44,8 +44,7 @@ STUN specs:
|
||||
The implementation fully supports the following client-to-TURN-server protocols:
|
||||
- UDP (per RFC 5766)
|
||||
- TCP (per RFC 5766 and RFC 6062)
|
||||
- TLS (per RFC 5766 and RFC 6062); SSL3/TLS1.0/TLS1.1/TLS1.2; SSL2 wrapping
|
||||
supported
|
||||
- TLS (per RFC 5766 and RFC 6062); SSL3/TLS1.0/TLS1.1/TLS1.2
|
||||
- DTLS (experimental non-standard feature)
|
||||
|
||||
Supported relay protocols:
|
||||
@@ -62,7 +61,6 @@ authentication is required):
|
||||
Redis can also be used for status and statistics storage and notification.
|
||||
|
||||
Supported TURN authentication mechanisms:
|
||||
- short-term
|
||||
- long-term
|
||||
- TURN REST API (a modification of the long-term mechanism, for time-limited
|
||||
secret-based authentication, for WebRTC applications)
|
||||
@@ -249,10 +247,6 @@ fi
|
||||
%dir %{_datadir}/%{name}/scripts/selfloadbalance
|
||||
%{_datadir}/%{name}/scripts/selfloadbalance/secure_dos_attack.sh
|
||||
%{_datadir}/%{name}/scripts/selfloadbalance/secure_relay.sh
|
||||
%dir %{_datadir}/%{name}/scripts/shorttermsecure
|
||||
%{_datadir}/%{name}/scripts/shorttermsecure/secure_relay_short_term_mech.sh
|
||||
%{_datadir}/%{name}/scripts/shorttermsecure/secure_tcp_client_c2c_tcp_relay_short_term.sh
|
||||
%{_datadir}/%{name}/scripts/shorttermsecure/secure_udp_client_short_term.sh
|
||||
%dir %{_datadir}/%{name}/scripts/mobile
|
||||
%{_datadir}/%{name}/scripts/mobile/mobile_relay.sh
|
||||
%{_datadir}/%{name}/scripts/mobile/mobile_dtls_client.sh
|
||||
@@ -294,6 +288,8 @@ fi
|
||||
%{_includedir}/turn/client/TurnMsgLib.h
|
||||
|
||||
%changelog
|
||||
* Sat Jan 24 2015 Oleg Moskalenko <mom040267@gmail.com>
|
||||
- Sync to 4.4.1.1
|
||||
* Wed Dec 24 2014 Oleg Moskalenko <mom040267@gmail.com>
|
||||
- Sync to 4.3.3.1
|
||||
* Sun Dec 14 2014 Oleg Moskalenko <mom040267@gmail.com>
|
||||
|
||||
@@ -827,14 +827,6 @@ static const char* turn_get_method(const SSL_METHOD *method, const char* mdefaul
|
||||
return mdefault;
|
||||
else {
|
||||
|
||||
#ifndef OPENSSL_NO_SSL2
|
||||
if(method == SSLv2_server_method()) {
|
||||
return "SSLv2";
|
||||
} else if(method == SSLv2_client_method()) {
|
||||
return "SSLv2";
|
||||
} else
|
||||
#endif
|
||||
|
||||
if(method == SSLv3_server_method()) {
|
||||
return "SSLv3";
|
||||
} else if(method == SSLv3_client_method()) {
|
||||
|
||||
@@ -312,53 +312,6 @@ static int mongo_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_get_user_pwd(u08bits *usname, st_password_t pwd) {
|
||||
mongoc_collection_t * collection = mongo_get_collection("turnusers_st");
|
||||
|
||||
if(!collection)
|
||||
return -1;
|
||||
|
||||
bson_t query;
|
||||
bson_init(&query);
|
||||
BSON_APPEND_UTF8(&query, "name", (const char *)usname);
|
||||
|
||||
bson_t fields;
|
||||
bson_init(&fields);
|
||||
BSON_APPEND_INT32(&fields, "password", 1);
|
||||
|
||||
mongoc_cursor_t * cursor;
|
||||
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 1, 0, &query, &fields, NULL);
|
||||
|
||||
int ret = -1;
|
||||
|
||||
if (!cursor) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection 'turnusers_st'\n");
|
||||
} else {
|
||||
const bson_t * item;
|
||||
uint32_t length;
|
||||
bson_iter_t iter;
|
||||
const char * value;
|
||||
if (mongoc_cursor_next(cursor, &item)) {
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "password") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||
value = bson_iter_utf8(&iter, &length);
|
||||
|
||||
if(length < 1) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong password data for user %s, size in MongoDB is zero(0)\n", usname);
|
||||
} else {
|
||||
ns_bcopy(value, pwd, length);
|
||||
pwd[length] = 0;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
mongoc_cursor_destroy(cursor);
|
||||
}
|
||||
mongoc_collection_destroy(collection);
|
||||
bson_destroy(&query);
|
||||
bson_destroy(&fields);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_set_user_key(u08bits *usname, u08bits *realm, const char *key) {
|
||||
mongoc_collection_t * collection = mongo_get_collection("turnusers_lt");
|
||||
|
||||
@@ -425,8 +378,8 @@ static int mongo_set_oauth_key(oauth_key_data_raw *key) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_set_user_pwd(u08bits *usname, st_password_t pwd) {
|
||||
mongoc_collection_t * collection = mongo_get_collection("turnusers_st");
|
||||
static int mongo_del_user(u08bits *usname, u08bits *realm) {
|
||||
mongoc_collection_t * collection = mongo_get_collection("turnusers_lt");
|
||||
|
||||
if(!collection)
|
||||
return -1;
|
||||
@@ -434,37 +387,7 @@ static int mongo_set_user_pwd(u08bits *usname, st_password_t pwd) {
|
||||
bson_t query;
|
||||
bson_init(&query);
|
||||
BSON_APPEND_UTF8(&query, "name", (const char *)usname);
|
||||
|
||||
bson_t doc;
|
||||
bson_init(&doc);
|
||||
BSON_APPEND_UTF8(&doc, "name", (const char *)usname);
|
||||
BSON_APPEND_UTF8(&doc, "password", (const char *)pwd);
|
||||
|
||||
int ret = -1;
|
||||
|
||||
if (!mongoc_collection_update(collection, MONGOC_UPDATE_UPSERT, &query, &doc, NULL, NULL)) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating secret key information\n");
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
mongoc_collection_destroy(collection);
|
||||
bson_destroy(&doc);
|
||||
bson_destroy(&query);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_del_user(u08bits *usname, int is_st, u08bits *realm) {
|
||||
mongoc_collection_t * collection = mongo_get_collection(is_st ? "turnusers_st" : "turnusers_lt");
|
||||
|
||||
if(!collection)
|
||||
return -1;
|
||||
|
||||
bson_t query;
|
||||
bson_init(&query);
|
||||
BSON_APPEND_UTF8(&query, "name", (const char *)usname);
|
||||
if(!is_st) {
|
||||
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||
}
|
||||
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||
|
||||
int ret = -1;
|
||||
|
||||
@@ -501,20 +424,25 @@ static int mongo_del_oauth_key(const u08bits *kid) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_list_users(int is_st, u08bits *realm) {
|
||||
const char * collection_name = is_st ? "turnusers_st" : "turnusers_lt";
|
||||
mongoc_collection_t * collection = mongo_get_collection(collection_name);
|
||||
static int mongo_list_users(u08bits *realm, secrets_list_t *users, secrets_list_t *realms)
|
||||
{
|
||||
const char * collection_name = "turnusers_lt";
|
||||
mongoc_collection_t * collection = mongo_get_collection(collection_name);
|
||||
|
||||
if(!collection)
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
if(!collection)
|
||||
return -1;
|
||||
|
||||
bson_t query, child;
|
||||
bson_init(&query);
|
||||
bson_append_document_begin(&query, "$orderby", -1, &child);
|
||||
bson_append_int32(&child, "realm", -1, 1);
|
||||
bson_append_int32(&child, "name", -1, 1);
|
||||
bson_append_document_end(&query, &child);
|
||||
bson_append_document_begin(&query, "$query", -1, &child);
|
||||
if (!is_st && realm && realm[0]) {
|
||||
if (realm && realm[0]) {
|
||||
BSON_APPEND_UTF8(&child, "realm", (const char *)realm);
|
||||
}
|
||||
bson_append_document_end(&query, &child);
|
||||
@@ -522,7 +450,7 @@ static int mongo_list_users(int is_st, u08bits *realm) {
|
||||
bson_t fields;
|
||||
bson_init(&fields);
|
||||
BSON_APPEND_INT32(&fields, "name", 1);
|
||||
if(!is_st) BSON_APPEND_INT32(&fields, "realm", 1);
|
||||
BSON_APPEND_INT32(&fields, "realm", 1);
|
||||
|
||||
mongoc_cursor_t * cursor;
|
||||
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL);
|
||||
@@ -541,14 +469,21 @@ static int mongo_list_users(int is_st, u08bits *realm) {
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "name") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||
value = bson_iter_utf8(&iter, &length);
|
||||
if (length) {
|
||||
const char *realm = "";
|
||||
if (!is_st && bson_iter_init(&iter_realm, item) && bson_iter_find(&iter_realm, "realm") && BSON_ITER_HOLDS_UTF8(&iter_realm)) {
|
||||
realm = bson_iter_utf8(&iter_realm, &length);
|
||||
const char *rval = "";
|
||||
if (bson_iter_init(&iter_realm, item) && bson_iter_find(&iter_realm, "realm") && BSON_ITER_HOLDS_UTF8(&iter_realm)) {
|
||||
rval = bson_iter_utf8(&iter_realm, &length);
|
||||
}
|
||||
if(realm && *realm) {
|
||||
printf("%s[%s]\n", value, realm);
|
||||
if(users) {
|
||||
add_to_secrets_list(users,value);
|
||||
if(realms) {
|
||||
if(rval && *rval) {
|
||||
add_to_secrets_list(realms,rval);
|
||||
} else {
|
||||
add_to_secrets_list(realms,(char*)realm);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("%s\n", value);
|
||||
printf("%s[%s]\n", value, rval);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -562,7 +497,7 @@ static int mongo_list_users(int is_st, u08bits *realm) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_list_oauth_keys(void) {
|
||||
static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas,secrets_list_t *tss,secrets_list_t *lts) {
|
||||
|
||||
const char * collection_name = "oauth_key";
|
||||
mongoc_collection_t * collection = mongo_get_collection(collection_name);
|
||||
@@ -635,9 +570,26 @@ static int mongo_list_oauth_keys(void) {
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "lifetime") && BSON_ITER_HOLDS_INT32(&iter)) {
|
||||
key->lifetime = (u32bits)bson_iter_int32(&iter);
|
||||
}
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, hkdf_hash_func=%s, as_rs_alg=%s, as_rs_key=%s, auth_alg=%s, auth_key=%s\n",
|
||||
key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, key->hkdf_hash_func,
|
||||
key->as_rs_alg, key->as_rs_key, key->auth_alg, key->auth_key);
|
||||
if(kids) {
|
||||
add_to_secrets_list(kids,key->kid);
|
||||
add_to_secrets_list(hkdfs,key->hkdf_hash_func);
|
||||
add_to_secrets_list(teas,key->as_rs_alg);
|
||||
add_to_secrets_list(aas,key->auth_alg);
|
||||
{
|
||||
char ts[256];
|
||||
snprintf(ts,sizeof(ts)-1,"%llu",(unsigned long long)key->timestamp);
|
||||
add_to_secrets_list(tss,ts);
|
||||
}
|
||||
{
|
||||
char lt[256];
|
||||
snprintf(lt,sizeof(lt)-1,"%lu",(unsigned long)key->lifetime);
|
||||
add_to_secrets_list(lts,lt);
|
||||
}
|
||||
} else {
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, hkdf_hash_func=%s, as_rs_alg=%s, as_rs_key=%s, auth_alg=%s, auth_key=%s\n",
|
||||
key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, key->hkdf_hash_func,
|
||||
key->as_rs_alg, key->as_rs_key, key->auth_alg, key->auth_key);
|
||||
}
|
||||
}
|
||||
mongoc_cursor_destroy(cursor);
|
||||
ret = 0;
|
||||
@@ -648,47 +600,76 @@ static int mongo_list_oauth_keys(void) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_show_secret(u08bits *realm) {
|
||||
mongoc_collection_t * collection = mongo_get_collection("turn_secret");
|
||||
static int mongo_list_secrets(u08bits *realm, secrets_list_t *secrets, secrets_list_t *realms)
|
||||
{
|
||||
mongoc_collection_t * collection = mongo_get_collection("turn_secret");
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
if(!collection)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
bson_t query;
|
||||
bson_init(&query);
|
||||
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||
bson_t query, child;
|
||||
bson_init(&query);
|
||||
bson_append_document_begin(&query, "$orderby", -1, &child);
|
||||
bson_append_int32(&child, "realm", -1, 1);
|
||||
bson_append_int32(&child, "value", -1, 1);
|
||||
bson_append_document_end(&query, &child);
|
||||
bson_append_document_begin(&query, "$query", -1, &child);
|
||||
if (realm && realm[0]) {
|
||||
BSON_APPEND_UTF8(&child, "realm", (const char *)realm);
|
||||
}
|
||||
bson_append_document_end(&query, &child);
|
||||
|
||||
bson_t fields;
|
||||
bson_init(&fields);
|
||||
BSON_APPEND_INT32(&fields, "value", 1);
|
||||
bson_t fields;
|
||||
bson_init(&fields);
|
||||
BSON_APPEND_INT32(&fields, "value", 1);
|
||||
BSON_APPEND_INT32(&fields, "realm", 1);
|
||||
|
||||
mongoc_cursor_t * cursor;
|
||||
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL);
|
||||
mongoc_cursor_t * cursor;
|
||||
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL);
|
||||
|
||||
int ret = -1;
|
||||
int ret = -1;
|
||||
|
||||
if (!cursor) {
|
||||
if (!cursor) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection 'turn_secret'\n");
|
||||
} else {
|
||||
const bson_t * item;
|
||||
uint32_t length;
|
||||
bson_iter_t iter;
|
||||
const char * value;
|
||||
while (mongoc_cursor_next(cursor, &item)) {
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "value") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||
value = bson_iter_utf8(&iter, &length);
|
||||
if (length) {
|
||||
printf("%s\n", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
mongoc_cursor_destroy(cursor);
|
||||
ret = 0;
|
||||
}
|
||||
mongoc_collection_destroy(collection);
|
||||
bson_destroy(&query);
|
||||
bson_destroy(&fields);
|
||||
return ret;
|
||||
} else {
|
||||
const bson_t * item;
|
||||
uint32_t length;
|
||||
bson_iter_t iter;
|
||||
bson_iter_t iter_realm;
|
||||
const char * value;
|
||||
while (mongoc_cursor_next(cursor, &item)) {
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "value") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||
value = bson_iter_utf8(&iter, &length);
|
||||
if (length) {
|
||||
const char *rval = "";
|
||||
if (bson_iter_init(&iter_realm, item) && bson_iter_find(&iter_realm, "realm") && BSON_ITER_HOLDS_UTF8(&iter_realm)) {
|
||||
rval = bson_iter_utf8(&iter_realm, &length);
|
||||
}
|
||||
if(secrets) {
|
||||
add_to_secrets_list(secrets,value);
|
||||
if(realms) {
|
||||
if(rval && *rval) {
|
||||
add_to_secrets_list(realms,rval);
|
||||
} else {
|
||||
add_to_secrets_list(realms,(char*)realm);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("%s[%s]\n", value, rval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mongoc_cursor_destroy(cursor);
|
||||
ret = 0;
|
||||
}
|
||||
mongoc_collection_destroy(collection);
|
||||
bson_destroy(&query);
|
||||
bson_destroy(&fields);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_del_secret(u08bits *secret, u08bits *realm) {
|
||||
@@ -702,7 +683,7 @@ static int mongo_del_secret(u08bits *secret, u08bits *realm) {
|
||||
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||
if(secret && (secret[0]!=0)) {
|
||||
BSON_APPEND_UTF8(&query, "value", (const char *)secret);
|
||||
}
|
||||
}
|
||||
|
||||
mongoc_collection_delete(collection, MONGOC_DELETE_NONE, &query, NULL, NULL);
|
||||
mongoc_collection_destroy(collection);
|
||||
@@ -732,38 +713,89 @@ static int mongo_set_secret(u08bits *secret, u08bits *realm) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int mongo_add_origin(u08bits *origin, u08bits *realm) {
|
||||
mongoc_collection_t * collection = mongo_get_collection("realm");
|
||||
|
||||
static int mongo_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int del)
|
||||
{
|
||||
char sub_collection_name[129];
|
||||
snprintf(sub_collection_name,sizeof(sub_collection_name)-1,"%s_peer_ip",kind);
|
||||
|
||||
mongoc_collection_t * collection = mongo_get_collection("realm");
|
||||
|
||||
if(!collection)
|
||||
return -1;
|
||||
|
||||
int ret = -1;
|
||||
|
||||
bson_t query, doc, child;
|
||||
bson_init(&query);
|
||||
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||
bson_init(&doc);
|
||||
bson_append_document_begin(&doc, "$addToSet", -1, &child);
|
||||
BSON_APPEND_UTF8(&child, "origin", (const char *)origin);
|
||||
bson_append_document_end(&doc, &child);
|
||||
return -1;
|
||||
|
||||
if (!mongoc_collection_update(collection, MONGOC_UPDATE_UPSERT, &query, &doc, NULL, NULL)) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating realm origin information\n");
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
mongoc_collection_destroy(collection);
|
||||
bson_destroy(&query);
|
||||
bson_destroy(&doc);
|
||||
return ret;
|
||||
int ret = -1;
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
bson_t query, doc, child;
|
||||
bson_init(&query);
|
||||
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||
bson_init(&doc);
|
||||
if(del) {
|
||||
bson_append_document_begin(&doc, "$pull", -1, &child);
|
||||
} else {
|
||||
bson_append_document_begin(&doc, "$addToSet", -1, &child);
|
||||
}
|
||||
BSON_APPEND_UTF8(&child, sub_collection_name, (const char *)ip);
|
||||
bson_append_document_end(&doc, &child);
|
||||
|
||||
mongoc_update_flags_t flags = MONGOC_UPDATE_NONE;
|
||||
|
||||
if(del) {
|
||||
flags = MONGOC_UPDATE_MULTI_UPDATE;
|
||||
} else {
|
||||
flags = MONGOC_UPDATE_UPSERT;
|
||||
}
|
||||
|
||||
if (!mongoc_collection_update(collection, flags, &query, &doc, NULL, NULL)) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting permission ip information\n");
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
mongoc_collection_destroy(collection);
|
||||
bson_destroy(&query);
|
||||
bson_destroy(&doc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_del_origin(u08bits *origin) {
|
||||
mongoc_collection_t * collection = mongo_get_collection("realm");
|
||||
static int mongo_add_origin(u08bits *origin, u08bits *realm)
|
||||
{
|
||||
mongoc_collection_t * collection = mongo_get_collection("realm");
|
||||
|
||||
if(!collection)
|
||||
return -1;
|
||||
|
||||
int ret = -1;
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
bson_t query, doc, child;
|
||||
bson_init(&query);
|
||||
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||
bson_init(&doc);
|
||||
bson_append_document_begin(&doc, "$addToSet", -1, &child);
|
||||
BSON_APPEND_UTF8(&child, "origin", (const char *)origin);
|
||||
bson_append_document_end(&doc, &child);
|
||||
|
||||
if (!mongoc_collection_update(collection, MONGOC_UPDATE_UPSERT, &query, &doc, NULL, NULL)) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating realm origin information\n");
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
mongoc_collection_destroy(collection);
|
||||
bson_destroy(&query);
|
||||
bson_destroy(&doc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_del_origin(u08bits *origin)
|
||||
{
|
||||
mongoc_collection_t * collection = mongo_get_collection("realm");
|
||||
|
||||
if(!collection)
|
||||
return -1;
|
||||
|
||||
int ret = -1;
|
||||
@@ -786,71 +818,82 @@ static int mongo_del_origin(u08bits *origin) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_list_origins(u08bits *realm) {
|
||||
mongoc_collection_t * collection = mongo_get_collection("realm");
|
||||
static int mongo_list_origins(u08bits *realm, secrets_list_t *origins, secrets_list_t *realms)
|
||||
{
|
||||
mongoc_collection_t * collection = mongo_get_collection("realm");
|
||||
|
||||
if(!collection)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
bson_t query, child;
|
||||
bson_init(&query);
|
||||
bson_append_document_begin(&query, "$orderby", -1, &child);
|
||||
BSON_APPEND_INT32(&child, "realm", 1);
|
||||
bson_append_document_end(&query, &child);
|
||||
bson_append_document_begin(&query, "$query", -1, &child);
|
||||
if (realm && realm[0]) {
|
||||
BSON_APPEND_UTF8(&child, "realm", (const char *)realm);
|
||||
}
|
||||
bson_append_document_end(&query, &child);
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
bson_t fields;
|
||||
bson_init(&fields);
|
||||
BSON_APPEND_INT32(&fields, "origin", 1);
|
||||
BSON_APPEND_INT32(&fields, "realm", 1);
|
||||
bson_t query, child;
|
||||
bson_init(&query);
|
||||
bson_append_document_begin(&query, "$orderby", -1, &child);
|
||||
BSON_APPEND_INT32(&child, "realm", 1);
|
||||
bson_append_document_end(&query, &child);
|
||||
bson_append_document_begin(&query, "$query", -1, &child);
|
||||
if (realm && realm[0]) {
|
||||
BSON_APPEND_UTF8(&child, "realm", (const char *)realm);
|
||||
}
|
||||
bson_append_document_end(&query, &child);
|
||||
|
||||
bson_t fields;
|
||||
bson_init(&fields);
|
||||
BSON_APPEND_INT32(&fields, "origin", 1);
|
||||
BSON_APPEND_INT32(&fields, "realm", 1);
|
||||
|
||||
mongoc_cursor_t * cursor;
|
||||
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL);
|
||||
mongoc_cursor_t * cursor;
|
||||
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL);
|
||||
|
||||
int ret = -1;
|
||||
int ret = -1;
|
||||
|
||||
if (!cursor) {
|
||||
if (!cursor) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection 'realm'\n");
|
||||
} else {
|
||||
const bson_t * item;
|
||||
uint32_t length;
|
||||
bson_iter_t iter;
|
||||
} else {
|
||||
const bson_t * item;
|
||||
uint32_t length;
|
||||
bson_iter_t iter;
|
||||
|
||||
while (mongoc_cursor_next(cursor, &item)) {
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "realm") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||
const char * _realm = bson_iter_utf8(&iter, &length);
|
||||
while (mongoc_cursor_next(cursor, &item)) {
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "realm") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||
const char * _realm = bson_iter_utf8(&iter, &length);
|
||||
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "origin") && BSON_ITER_HOLDS_ARRAY(&iter)) {
|
||||
const uint8_t *docbuf = NULL;
|
||||
uint32_t doclen = 0;
|
||||
bson_t origin_array;
|
||||
bson_iter_t origin_iter;
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "origin") && BSON_ITER_HOLDS_ARRAY(&iter)) {
|
||||
const uint8_t *docbuf = NULL;
|
||||
uint32_t doclen = 0;
|
||||
bson_t origin_array;
|
||||
bson_iter_t origin_iter;
|
||||
|
||||
bson_iter_array(&iter, &doclen, &docbuf);
|
||||
bson_init_static(&origin_array, docbuf, doclen);
|
||||
bson_iter_array(&iter, &doclen, &docbuf);
|
||||
bson_init_static(&origin_array, docbuf, doclen);
|
||||
|
||||
if (bson_iter_init(&origin_iter, &origin_array)) {
|
||||
while(bson_iter_next(&origin_iter)) {
|
||||
if (BSON_ITER_HOLDS_UTF8(&origin_iter)) {
|
||||
const char * _origin = bson_iter_utf8(&origin_iter, &length);
|
||||
printf("%s ==>> %s\n", _realm, _origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mongoc_cursor_destroy(cursor);
|
||||
ret = 0;
|
||||
}
|
||||
mongoc_collection_destroy(collection);
|
||||
bson_destroy(&query);
|
||||
bson_destroy(&fields);
|
||||
return ret;
|
||||
if (bson_iter_init(&origin_iter, &origin_array)) {
|
||||
while(bson_iter_next(&origin_iter)) {
|
||||
if (BSON_ITER_HOLDS_UTF8(&origin_iter)) {
|
||||
const char * _origin = bson_iter_utf8(&origin_iter, &length);
|
||||
if(origins) {
|
||||
add_to_secrets_list(origins,_origin);
|
||||
if(realms) {
|
||||
add_to_secrets_list(realms,_realm);
|
||||
}
|
||||
} else {
|
||||
printf("%s ==>> %s\n", _realm, _origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mongoc_cursor_destroy(cursor);
|
||||
ret = 0;
|
||||
}
|
||||
mongoc_collection_destroy(collection);
|
||||
bson_destroy(&query);
|
||||
bson_destroy(&fields);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) {
|
||||
@@ -1172,17 +1215,180 @@ static void mongo_reread_realms(secrets_list_t * realms_list) {
|
||||
bson_destroy(&fields);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
static int mongo_get_admin_user(const u08bits *usname, u08bits *realm, password_t pwd)
|
||||
{
|
||||
mongoc_collection_t * collection = mongo_get_collection("admin_user");
|
||||
|
||||
if(!collection)
|
||||
return -1;
|
||||
|
||||
realm[0]=0;
|
||||
pwd[0]=0;
|
||||
|
||||
bson_t query;
|
||||
bson_init(&query);
|
||||
BSON_APPEND_UTF8(&query, "name", (const char *)usname);
|
||||
|
||||
bson_t fields;
|
||||
bson_init(&fields);
|
||||
BSON_APPEND_INT32(&fields, "realm", 1);
|
||||
BSON_APPEND_INT32(&fields, "password", 1);
|
||||
|
||||
mongoc_cursor_t * cursor;
|
||||
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 1, 0, &query, &fields, NULL);
|
||||
|
||||
int ret = -1;
|
||||
|
||||
if (!cursor) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection 'admin_user'\n");
|
||||
} else {
|
||||
const bson_t * item;
|
||||
uint32_t length;
|
||||
bson_iter_t iter;
|
||||
if (mongoc_cursor_next(cursor, &item)) {
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "realm") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||
strncpy((char*)realm,bson_iter_utf8(&iter, &length),STUN_MAX_REALM_SIZE);
|
||||
ret = 0;
|
||||
}
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "password") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||
strncpy((char*)pwd,bson_iter_utf8(&iter, &length),STUN_MAX_PWD_SIZE);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
mongoc_cursor_destroy(cursor);
|
||||
}
|
||||
mongoc_collection_destroy(collection);
|
||||
bson_destroy(&query);
|
||||
bson_destroy(&fields);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_set_admin_user(const u08bits *usname, const u08bits *realm, const password_t pwd)
|
||||
{
|
||||
mongoc_collection_t * collection = mongo_get_collection("admin_user");
|
||||
|
||||
if(!collection)
|
||||
return -1;
|
||||
|
||||
bson_t query;
|
||||
bson_init(&query);
|
||||
BSON_APPEND_UTF8(&query, "name", (const char *)usname);
|
||||
|
||||
bson_t doc;
|
||||
bson_init(&doc);
|
||||
BSON_APPEND_UTF8(&doc, "name", (const char *)usname);
|
||||
BSON_APPEND_UTF8(&doc, "realm", (const char *)realm);
|
||||
BSON_APPEND_UTF8(&doc, "password", (const char *)pwd);
|
||||
|
||||
int ret = -1;
|
||||
|
||||
if (!mongoc_collection_update(collection, MONGOC_UPDATE_UPSERT, &query, &doc, NULL, NULL)) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating admin user information\n");
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
mongoc_collection_destroy(collection);
|
||||
bson_destroy(&doc);
|
||||
bson_destroy(&query);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_del_admin_user(const u08bits *usname)
|
||||
{
|
||||
mongoc_collection_t * collection = mongo_get_collection("admin_user");
|
||||
|
||||
if(!collection)
|
||||
return -1;
|
||||
|
||||
bson_t query;
|
||||
bson_init(&query);
|
||||
BSON_APPEND_UTF8(&query, "name", (const char *)usname);
|
||||
|
||||
int ret = -1;
|
||||
|
||||
if (!mongoc_collection_delete(collection, MONGOC_DELETE_SINGLE_REMOVE, &query, NULL, NULL)) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting admin user information\n");
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
mongoc_collection_destroy(collection);
|
||||
bson_destroy(&query);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mongo_list_admin_users(int no_print)
|
||||
{
|
||||
const char * collection_name = "admin_user";
|
||||
mongoc_collection_t * collection = mongo_get_collection(collection_name);
|
||||
|
||||
if(!collection)
|
||||
return -1;
|
||||
|
||||
bson_t query, child;
|
||||
bson_init(&query);
|
||||
bson_append_document_begin(&query, "$orderby", -1, &child);
|
||||
bson_append_int32(&child, "name", -1, 1);
|
||||
bson_append_document_end(&query, &child);
|
||||
bson_append_document_begin(&query, "$query", -1, &child);
|
||||
bson_append_document_end(&query, &child);
|
||||
|
||||
bson_t fields;
|
||||
bson_init(&fields);
|
||||
BSON_APPEND_INT32(&fields, "name", 1);
|
||||
BSON_APPEND_INT32(&fields, "realm", 1);
|
||||
|
||||
mongoc_cursor_t * cursor;
|
||||
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL);
|
||||
|
||||
int ret = -1;
|
||||
|
||||
if (!cursor) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection '%s'\n", collection_name);
|
||||
} else {
|
||||
const bson_t * item;
|
||||
uint32_t length;
|
||||
bson_iter_t iter;
|
||||
bson_iter_t iter_realm;
|
||||
const char * value;
|
||||
ret = 0;
|
||||
while (mongoc_cursor_next(cursor, &item)) {
|
||||
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "name") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||
value = bson_iter_utf8(&iter, &length);
|
||||
if (length) {
|
||||
const char *realm = "";
|
||||
if (bson_iter_init(&iter_realm, item) && bson_iter_find(&iter_realm, "realm") && BSON_ITER_HOLDS_UTF8(&iter_realm)) {
|
||||
realm = bson_iter_utf8(&iter_realm, &length);
|
||||
}
|
||||
++ret;
|
||||
if(!no_print) {
|
||||
if(realm && *realm) {
|
||||
printf("%s[%s]\n", value, realm);
|
||||
} else {
|
||||
printf("%s\n", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mongoc_cursor_destroy(cursor);
|
||||
}
|
||||
mongoc_collection_destroy(collection);
|
||||
bson_destroy(&query);
|
||||
bson_destroy(&fields);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
static const turn_dbdriver_t driver = {
|
||||
&mongo_get_auth_secrets,
|
||||
&mongo_get_user_key,
|
||||
&mongo_get_user_pwd,
|
||||
&mongo_set_user_key,
|
||||
&mongo_set_user_pwd,
|
||||
&mongo_del_user,
|
||||
&mongo_list_users,
|
||||
&mongo_show_secret,
|
||||
&mongo_list_secrets,
|
||||
&mongo_del_secret,
|
||||
&mongo_set_secret,
|
||||
&mongo_add_origin,
|
||||
@@ -1192,11 +1398,16 @@ static const turn_dbdriver_t driver = {
|
||||
&mongo_list_realm_options,
|
||||
&mongo_auth_ping,
|
||||
&mongo_get_ip_list,
|
||||
&mongo_set_permission_ip,
|
||||
&mongo_reread_realms,
|
||||
&mongo_set_oauth_key,
|
||||
&mongo_get_oauth_key,
|
||||
&mongo_del_oauth_key,
|
||||
&mongo_list_oauth_keys
|
||||
&mongo_list_oauth_keys,
|
||||
&mongo_get_admin_user,
|
||||
&mongo_set_admin_user,
|
||||
&mongo_del_admin_user,
|
||||
&mongo_list_admin_users
|
||||
};
|
||||
|
||||
const turn_dbdriver_t * get_mongo_dbdriver(void) {
|
||||
|
||||
@@ -338,47 +338,6 @@ static int mysql_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_get_user_pwd(u08bits *usname, st_password_t pwd) {
|
||||
|
||||
int ret = -1;
|
||||
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
snprintf(statement,sizeof(statement),"select password from turnusers_st where name='%s'",usname);
|
||||
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if(myc) {
|
||||
int res = mysql_query(myc, statement);
|
||||
if(res) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||
} else {
|
||||
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)!=1) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement);
|
||||
} else {
|
||||
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||
if(row && row[0]) {
|
||||
unsigned long *lengths = mysql_fetch_lengths(mres);
|
||||
if(lengths) {
|
||||
if(lengths[0]<1) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong password data for user %s, size in MySQL DB is zero(0)\n",usname);
|
||||
} else {
|
||||
ns_bcopy(row[0],pwd,lengths[0]);
|
||||
pwd[lengths[0]]=0;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(mres)
|
||||
mysql_free_result(mres);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
|
||||
@@ -402,7 +361,7 @@ static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
if(row && row[0]) {
|
||||
unsigned long *lengths = mysql_fetch_lengths(mres);
|
||||
if(lengths) {
|
||||
STRCPY((char*)key->kid,kid);
|
||||
STRCPY(key->kid,kid);
|
||||
ns_bcopy(row[0],key->ikm_key,lengths[0]);
|
||||
key->ikm_key[lengths[0]]=0;
|
||||
|
||||
@@ -443,7 +402,7 @@ static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_list_oauth_keys(void) {
|
||||
static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas,secrets_list_t *tss,secrets_list_t *lts) {
|
||||
|
||||
oauth_key_data_raw key_;
|
||||
oauth_key_data_raw *key=&key_;
|
||||
@@ -498,9 +457,26 @@ static int mysql_list_oauth_keys(void) {
|
||||
ns_bcopy(row[8],key->kid,lengths[8]);
|
||||
key->kid[lengths[8]]=0;
|
||||
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, hkdf_hash_func=%s, as_rs_alg=%s, as_rs_key=%s, auth_alg=%s, auth_key=%s\n",
|
||||
if(kids) {
|
||||
add_to_secrets_list(kids,key->kid);
|
||||
add_to_secrets_list(hkdfs,key->hkdf_hash_func);
|
||||
add_to_secrets_list(teas,key->as_rs_alg);
|
||||
add_to_secrets_list(aas,key->auth_alg);
|
||||
{
|
||||
char ts[256];
|
||||
snprintf(ts,sizeof(ts)-1,"%llu",(unsigned long long)key->timestamp);
|
||||
add_to_secrets_list(tss,ts);
|
||||
}
|
||||
{
|
||||
char lt[256];
|
||||
snprintf(lt,sizeof(lt)-1,"%lu",(unsigned long)key->lifetime);
|
||||
add_to_secrets_list(lts,lt);
|
||||
}
|
||||
} else {
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, hkdf_hash_func=%s, as_rs_alg=%s, as_rs_key=%s, auth_alg=%s, auth_key=%s\n",
|
||||
key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, key->hkdf_hash_func,
|
||||
key->as_rs_alg, key->as_rs_key, key->auth_alg, key->auth_key);
|
||||
}
|
||||
}
|
||||
row = mysql_fetch_row(mres);
|
||||
}
|
||||
@@ -514,26 +490,32 @@ static int mysql_list_oauth_keys(void) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_set_user_key(u08bits *usname, u08bits *realm, const char *key) {
|
||||
static int mysql_set_user_key(u08bits *usname, u08bits *realm, const char *key)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if(myc) {
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if(myc) {
|
||||
snprintf(statement,sizeof(statement),"insert into turnusers_lt (realm,name,hmackey) values('%s','%s','%s')",realm,usname,key);
|
||||
int res = mysql_query(myc, statement);
|
||||
if(res) {
|
||||
int res = mysql_query(myc, statement);
|
||||
if(!res) {
|
||||
ret = 0;
|
||||
} else {
|
||||
snprintf(statement,sizeof(statement),"update turnusers_lt set hmackey='%s' where name='%s' and realm='%s'",key,usname,realm);
|
||||
res = mysql_query(myc, statement);
|
||||
if(res) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user key information: %s\n",mysql_error(myc));
|
||||
}
|
||||
}
|
||||
}
|
||||
res = mysql_query(myc, statement);
|
||||
if(!res) {
|
||||
ret = 0;
|
||||
} else {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user key information: %s\n",mysql_error(myc));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_set_oauth_key(oauth_key_data_raw *key) {
|
||||
int ret = -1;
|
||||
static int mysql_set_oauth_key(oauth_key_data_raw *key)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if(myc) {
|
||||
@@ -547,42 +529,22 @@ static int mysql_set_oauth_key(oauth_key_data_raw *key) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_set_user_pwd(u08bits *usname, st_password_t pwd) {
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if(myc) {
|
||||
snprintf(statement,sizeof(statement),"insert into turnusers_st values('%s','%s')",usname,pwd);
|
||||
int res = mysql_query(myc, statement);
|
||||
if(res) {
|
||||
snprintf(statement,sizeof(statement),"update turnusers_st set password='%s' where name='%s'",pwd,usname);
|
||||
res = mysql_query(myc, statement);
|
||||
if(res) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user key information: %s\n",mysql_error(myc));
|
||||
} else {
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
}
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_del_user(u08bits *usname, int is_st, u08bits *realm) {
|
||||
static int mysql_del_user(u08bits *usname, u08bits *realm) {
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if(myc) {
|
||||
if(is_st) {
|
||||
snprintf(statement,sizeof(statement),"delete from turnusers_st where name='%s'",usname);
|
||||
} else {
|
||||
snprintf(statement,sizeof(statement),"delete from turnusers_lt where name='%s' and realm='%s'",usname,realm);
|
||||
}
|
||||
snprintf(statement,sizeof(statement),"delete from turnusers_lt where name='%s' and realm='%s'",usname,realm);
|
||||
int res = mysql_query(myc, statement);
|
||||
if(res) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting user key information: %s\n",mysql_error(myc));
|
||||
@@ -609,17 +571,20 @@ static int mysql_del_oauth_key(const u08bits *kid) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_list_users(int is_st, u08bits *realm) {
|
||||
int ret = -1;
|
||||
static int mysql_list_users(u08bits *realm, secrets_list_t *users, secrets_list_t *realms)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if(myc) {
|
||||
if(is_st) {
|
||||
snprintf(statement,sizeof(statement),"select name,'' from turnusers_st order by name");
|
||||
} else if(realm && realm[0]) {
|
||||
if(realm[0]) {
|
||||
snprintf(statement,sizeof(statement),"select name, realm from turnusers_lt where realm='%s' order by name",realm);
|
||||
} else {
|
||||
snprintf(statement,sizeof(statement),"select name, realm from turnusers_lt order by name");
|
||||
snprintf(statement,sizeof(statement),"select name, realm from turnusers_lt order by realm,name");
|
||||
}
|
||||
int res = mysql_query(myc, statement);
|
||||
if(res) {
|
||||
@@ -637,10 +602,17 @@ static int mysql_list_users(int is_st, u08bits *realm) {
|
||||
break;
|
||||
} else {
|
||||
if(row[0]) {
|
||||
if(row[1] && row[1][0]) {
|
||||
printf("%s[%s]\n",row[0],row[1]);
|
||||
if(users) {
|
||||
add_to_secrets_list(users,row[0]);
|
||||
if(realms) {
|
||||
if(row[1]) {
|
||||
add_to_secrets_list(realms,row[1]);
|
||||
} else {
|
||||
add_to_secrets_list(realms,(char*)realm);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("%s\n",row[0]);
|
||||
printf("%s[%s]\n", row[0], row[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -655,10 +627,19 @@ static int mysql_list_users(int is_st, u08bits *realm) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_show_secret(u08bits *realm) {
|
||||
int ret = -1;
|
||||
static int mysql_list_secrets(u08bits *realm, secrets_list_t *secrets, secrets_list_t *realms)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm);
|
||||
if (realm[0]) {
|
||||
snprintf(statement, sizeof(statement), "select value,realm from turn_secret where realm='%s' order by value", realm);
|
||||
} else {
|
||||
snprintf(statement, sizeof(statement), "select value,realm from turn_secret order by realm,value");
|
||||
}
|
||||
|
||||
donot_print_connection_success=1;
|
||||
|
||||
@@ -671,7 +652,7 @@ static int mysql_show_secret(u08bits *realm) {
|
||||
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)!=1) {
|
||||
} else if(mysql_field_count(myc)!=2) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement);
|
||||
} else {
|
||||
for(;;) {
|
||||
@@ -679,19 +660,32 @@ static int mysql_show_secret(u08bits *realm) {
|
||||
if(!row) {
|
||||
break;
|
||||
} else {
|
||||
if(row[0]) {
|
||||
printf("%s\n",row[0]);
|
||||
const char* kval = row[0];
|
||||
if(kval) {
|
||||
const char* rval = row[1];
|
||||
if(secrets) {
|
||||
add_to_secrets_list(secrets,kval);
|
||||
if(realms) {
|
||||
if(rval && *rval) {
|
||||
add_to_secrets_list(realms,rval);
|
||||
} else {
|
||||
add_to_secrets_list(realms,(char*)realm);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("%s[%s]\n",kval,rval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if(mres)
|
||||
mysql_free_result(mres);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_del_secret(u08bits *secret, u08bits *realm) {
|
||||
@@ -729,6 +723,37 @@ static int mysql_set_secret(u08bits *secret, u08bits *realm) {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int del)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
donot_print_connection_success = 1;
|
||||
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if (myc) {
|
||||
if(del) {
|
||||
snprintf(statement, sizeof(statement), "delete from %s_peer_ip where realm = '%s' and ip_range = '%s'", kind, (char*)realm, ip);
|
||||
} else {
|
||||
snprintf(statement, sizeof(statement), "insert into %s_peer_ip (realm,ip_range) values('%s','%s')", kind, (char*)realm, ip);
|
||||
}
|
||||
int res = mysql_query(myc, statement);
|
||||
if (res) {
|
||||
TURN_LOG_FUNC(
|
||||
TURN_LOG_LEVEL_ERROR,
|
||||
"Error inserting permission ip information: %s\n",
|
||||
mysql_error(myc));
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_add_origin(u08bits *origin, u08bits *realm) {
|
||||
int ret = -1;
|
||||
@@ -768,16 +793,22 @@ static int mysql_del_origin(u08bits *origin) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_list_origins(u08bits *realm) {
|
||||
int ret = -1;
|
||||
static int mysql_list_origins(u08bits *realm, secrets_list_t *origins, secrets_list_t *realms)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
donot_print_connection_success = 1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if(myc) {
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
if(realm && realm[0]) {
|
||||
snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm where realm='%s' order by origin",realm);
|
||||
} else {
|
||||
snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm order by origin,realm");
|
||||
snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm order by realm,origin");
|
||||
}
|
||||
int res = mysql_query(myc, statement);
|
||||
if(res) {
|
||||
@@ -795,7 +826,20 @@ static int mysql_list_origins(u08bits *realm) {
|
||||
break;
|
||||
} else {
|
||||
if(row[0] && row[1]) {
|
||||
printf("%s ==>> %s\n",row[0],row[1]);
|
||||
const char* kval = row[0];
|
||||
const char* rval = row[1];
|
||||
if(origins) {
|
||||
add_to_secrets_list(origins,kval);
|
||||
if(realms) {
|
||||
if(rval && *rval) {
|
||||
add_to_secrets_list(realms,rval);
|
||||
} else {
|
||||
add_to_secrets_list(realms,(char*)realm);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("%s ==>> %s\n",kval,rval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1065,17 +1109,138 @@ static void mysql_reread_realms(secrets_list_t * realms_list) {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
static int mysql_get_admin_user(const u08bits *usname, u08bits *realm, password_t pwd)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
realm[0]=0;
|
||||
pwd[0]=0;
|
||||
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if(myc) {
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
snprintf(statement,sizeof(statement),"select realm,password from admin_user where name='%s'",usname);
|
||||
int res = mysql_query(myc, statement);
|
||||
if(res) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||
} else {
|
||||
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)!=2) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement);
|
||||
} else {
|
||||
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||
if(row && row[0]) {
|
||||
strncpy((char*)realm,row[0],STUN_MAX_REALM_SIZE);
|
||||
strncpy((char*)pwd,row[1],STUN_MAX_PWD_SIZE);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(mres)
|
||||
mysql_free_result(mres);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_set_admin_user(const u08bits *usname, const u08bits *realm, const password_t pwd)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
donot_print_connection_success=1;
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if(myc) {
|
||||
snprintf(statement,sizeof(statement),"insert into admin_user (realm,name,password) values('%s','%s','%s')",realm,usname,pwd);
|
||||
int res = mysql_query(myc, statement);
|
||||
if(!res) {
|
||||
ret = 0;
|
||||
} else {
|
||||
snprintf(statement,sizeof(statement),"update admin_user set realm='%s',password='%s' where name='%s'",realm,pwd,usname);
|
||||
res = mysql_query(myc, statement);
|
||||
if(!res) {
|
||||
ret = 0;
|
||||
} else {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user key information: %s\n",mysql_error(myc));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_del_admin_user(const u08bits *usname)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
donot_print_connection_success=1;
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if(myc) {
|
||||
snprintf(statement,sizeof(statement),"delete from admin_user where name='%s'",usname);
|
||||
int res = mysql_query(myc, statement);
|
||||
if(res) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting admin user information: %s\n",mysql_error(myc));
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mysql_list_admin_users(int no_print)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
donot_print_connection_success=1;
|
||||
MYSQL * myc = get_mydb_connection();
|
||||
if(myc) {
|
||||
snprintf(statement,sizeof(statement),"select name, realm from admin_user order by realm,name");
|
||||
int res = mysql_query(myc, statement);
|
||||
if(res) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||
} else {
|
||||
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)!=2) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement);
|
||||
} else {
|
||||
ret = 0;
|
||||
for(;;) {
|
||||
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||
if(!row) {
|
||||
break;
|
||||
} else {
|
||||
++ret;
|
||||
if(row[0] && !no_print) {
|
||||
if(row[1] && row[1][0]) {
|
||||
printf("%s[%s]\n",row[0],row[1]);
|
||||
} else {
|
||||
printf("%s\n",row[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(mres)
|
||||
mysql_free_result(mres);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
static const turn_dbdriver_t driver = {
|
||||
&mysql_get_auth_secrets,
|
||||
&mysql_get_user_key,
|
||||
&mysql_get_user_pwd,
|
||||
&mysql_set_user_key,
|
||||
&mysql_set_user_pwd,
|
||||
&mysql_del_user,
|
||||
&mysql_list_users,
|
||||
&mysql_show_secret,
|
||||
&mysql_list_secrets,
|
||||
&mysql_del_secret,
|
||||
&mysql_set_secret,
|
||||
&mysql_add_origin,
|
||||
@@ -1085,11 +1250,16 @@ static const turn_dbdriver_t driver = {
|
||||
&mysql_list_realm_options,
|
||||
&mysql_auth_ping,
|
||||
&mysql_get_ip_list,
|
||||
&mysql_set_permission_ip,
|
||||
&mysql_reread_realms,
|
||||
&mysql_set_oauth_key,
|
||||
&mysql_get_oauth_key,
|
||||
&mysql_del_oauth_key,
|
||||
&mysql_list_oauth_keys
|
||||
&mysql_list_oauth_keys,
|
||||
&mysql_get_admin_user,
|
||||
&mysql_set_admin_user,
|
||||
&mysql_del_admin_user,
|
||||
&mysql_list_admin_users
|
||||
};
|
||||
|
||||
const turn_dbdriver_t * get_mysql_dbdriver(void) {
|
||||
|
||||
@@ -152,34 +152,6 @@ static int pgsql_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_get_user_pwd(u08bits *usname, st_password_t pwd) {
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
snprintf(statement,sizeof(statement),"select password from turnusers_st where name='%s'",usname);
|
||||
|
||||
PGconn * pqc = get_pqdb_connection();
|
||||
if(pqc) {
|
||||
PGresult *res = PQexec(pqc, statement);
|
||||
|
||||
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res)!=1)) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
|
||||
} else {
|
||||
char *kval = PQgetvalue(res,0,0);
|
||||
if(kval) {
|
||||
strncpy((char*)pwd,kval,sizeof(st_password_t));
|
||||
ret = 0;
|
||||
} else {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong password data for user %s: NULL\n",usname);
|
||||
}
|
||||
}
|
||||
|
||||
if(res) {
|
||||
PQclear(res);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
|
||||
@@ -195,15 +167,15 @@ static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res)!=1)) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
|
||||
} else {
|
||||
STRCPY((char*)key->ikm_key,PQgetvalue(res,0,0));
|
||||
STRCPY(key->ikm_key,PQgetvalue(res,0,0));
|
||||
key->timestamp = (u64bits)strtoll(PQgetvalue(res,0,1),NULL,10);
|
||||
key->lifetime = (u32bits)strtol(PQgetvalue(res,0,2),NULL,10);
|
||||
STRCPY((char*)key->hkdf_hash_func,PQgetvalue(res,0,3));
|
||||
STRCPY((char*)key->as_rs_alg,PQgetvalue(res,0,4));
|
||||
STRCPY((char*)key->as_rs_key,PQgetvalue(res,0,5));
|
||||
STRCPY((char*)key->auth_alg,PQgetvalue(res,0,6));
|
||||
STRCPY((char*)key->auth_key,PQgetvalue(res,0,7));
|
||||
STRCPY((char*)key->kid,kid);
|
||||
STRCPY(key->hkdf_hash_func,PQgetvalue(res,0,3));
|
||||
STRCPY(key->as_rs_alg,PQgetvalue(res,0,4));
|
||||
STRCPY(key->as_rs_key,PQgetvalue(res,0,5));
|
||||
STRCPY(key->auth_alg,PQgetvalue(res,0,6));
|
||||
STRCPY(key->auth_key,PQgetvalue(res,0,7));
|
||||
STRCPY(key->kid,kid);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
@@ -215,7 +187,7 @@ static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_list_oauth_keys(void) {
|
||||
static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas,secrets_list_t *tss,secrets_list_t *lts) {
|
||||
|
||||
oauth_key_data_raw key_;
|
||||
oauth_key_data_raw *key=&key_;
|
||||
@@ -235,19 +207,36 @@ static int pgsql_list_oauth_keys(void) {
|
||||
int i = 0;
|
||||
for(i=0;i<PQntuples(res);i++) {
|
||||
|
||||
STRCPY((char*)key->ikm_key,PQgetvalue(res,i,0));
|
||||
STRCPY(key->ikm_key,PQgetvalue(res,i,0));
|
||||
key->timestamp = (u64bits)strtoll(PQgetvalue(res,i,1),NULL,10);
|
||||
key->lifetime = (u32bits)strtol(PQgetvalue(res,i,2),NULL,10);
|
||||
STRCPY((char*)key->hkdf_hash_func,PQgetvalue(res,i,3));
|
||||
STRCPY((char*)key->as_rs_alg,PQgetvalue(res,i,4));
|
||||
STRCPY((char*)key->as_rs_key,PQgetvalue(res,i,5));
|
||||
STRCPY((char*)key->auth_alg,PQgetvalue(res,i,6));
|
||||
STRCPY((char*)key->auth_key,PQgetvalue(res,i,7));
|
||||
STRCPY((char*)key->kid,PQgetvalue(res,i,8));
|
||||
STRCPY(key->hkdf_hash_func,PQgetvalue(res,i,3));
|
||||
STRCPY(key->as_rs_alg,PQgetvalue(res,i,4));
|
||||
STRCPY(key->as_rs_key,PQgetvalue(res,i,5));
|
||||
STRCPY(key->auth_alg,PQgetvalue(res,i,6));
|
||||
STRCPY(key->auth_key,PQgetvalue(res,i,7));
|
||||
STRCPY(key->kid,PQgetvalue(res,i,8));
|
||||
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, hkdf_hash_func=%s, as_rs_alg=%s, as_rs_key=%s, auth_alg=%s, auth_key=%s\n",
|
||||
if(kids) {
|
||||
add_to_secrets_list(kids,key->kid);
|
||||
add_to_secrets_list(hkdfs,key->hkdf_hash_func);
|
||||
add_to_secrets_list(teas,key->as_rs_alg);
|
||||
add_to_secrets_list(aas,key->auth_alg);
|
||||
{
|
||||
char ts[256];
|
||||
snprintf(ts,sizeof(ts)-1,"%llu",(unsigned long long)key->timestamp);
|
||||
add_to_secrets_list(tss,ts);
|
||||
}
|
||||
{
|
||||
char lt[256];
|
||||
snprintf(lt,sizeof(lt)-1,"%lu",(unsigned long)key->lifetime);
|
||||
add_to_secrets_list(lts,lt);
|
||||
}
|
||||
} else {
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, hkdf_hash_func=%s, as_rs_alg=%s, as_rs_key=%s, auth_alg=%s, auth_key=%s\n",
|
||||
key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, key->hkdf_hash_func,
|
||||
key->as_rs_alg, key->as_rs_key, key->auth_alg, key->auth_key);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
@@ -273,7 +262,7 @@ static int pgsql_set_user_key(u08bits *usname, u08bits *realm, const char *key)
|
||||
if(res) {
|
||||
PQclear(res);
|
||||
}
|
||||
snprintf(statement,sizeof(statement),"update turnusers_lt set hmackey='%s' where name='%s' and realm='%s'",key,usname,realm);
|
||||
snprintf(statement,sizeof(statement),"update turnusers_lt set hmackey='%s' where name='%s' and realm='%s'",key,usname,realm);
|
||||
res = PQexec(pqc, statement);
|
||||
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user information: %s\n",PQerrorMessage(pqc));
|
||||
@@ -311,50 +300,23 @@ static int pgsql_set_oauth_key(oauth_key_data_raw *key) {
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if(res) {
|
||||
PQclear(res);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_set_user_pwd(u08bits *usname, st_password_t pwd) {
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
PGconn *pqc = get_pqdb_connection();
|
||||
if(pqc) {
|
||||
snprintf(statement,sizeof(statement),"insert into turnusers_st values('%s','%s')",usname,pwd);
|
||||
PGresult *res = PQexec(pqc, statement);
|
||||
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||
if(res) {
|
||||
PQclear(res);
|
||||
}
|
||||
snprintf(statement,sizeof(statement),"update turnusers_st set password='%s' where name='%s'",pwd,usname);
|
||||
res = PQexec(pqc, statement);
|
||||
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user information: %s\n",PQerrorMessage(pqc));
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
if(res) {
|
||||
PQclear(res);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_del_user(u08bits *usname, int is_st, u08bits *realm) {
|
||||
static int pgsql_del_user(u08bits *usname, u08bits *realm) {
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
PGconn *pqc = get_pqdb_connection();
|
||||
if(pqc) {
|
||||
if(is_st) {
|
||||
snprintf(statement,sizeof(statement),"delete from turnusers_st where name='%s'",usname);
|
||||
} else {
|
||||
snprintf(statement,sizeof(statement),"delete from turnusers_lt where name='%s' and realm='%s'",usname,realm);
|
||||
}
|
||||
snprintf(statement,sizeof(statement),"delete from turnusers_lt where name='%s' and realm='%s'",usname,realm);
|
||||
PGresult *res = PQexec(pqc, statement);
|
||||
if(res) {
|
||||
PQclear(res);
|
||||
@@ -385,17 +347,20 @@ static int pgsql_del_oauth_key(const u08bits *kid) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_list_users(int is_st, u08bits *realm) {
|
||||
int ret = -1;
|
||||
static int pgsql_list_users(u08bits *realm, secrets_list_t *users, secrets_list_t *realms)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
PGconn *pqc = get_pqdb_connection();
|
||||
if(pqc) {
|
||||
if(is_st) {
|
||||
snprintf(statement,sizeof(statement),"select name,'' from turnusers_st order by name");
|
||||
} else if(realm && realm[0]) {
|
||||
if(realm[0]) {
|
||||
snprintf(statement,sizeof(statement),"select name,realm from turnusers_lt where realm='%s' order by name",realm);
|
||||
} else {
|
||||
snprintf(statement,sizeof(statement),"select name,realm from turnusers_lt order by name");
|
||||
snprintf(statement,sizeof(statement),"select name,realm from turnusers_lt order by realm,name");
|
||||
}
|
||||
PGresult *res = PQexec(pqc, statement);
|
||||
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
|
||||
@@ -406,10 +371,19 @@ static int pgsql_list_users(int is_st, u08bits *realm) {
|
||||
char *kval = PQgetvalue(res,i,0);
|
||||
if(kval) {
|
||||
char *rval = PQgetvalue(res,i,1);
|
||||
if(rval && *rval) {
|
||||
printf("%s[%s]\n",kval,rval);
|
||||
} else {
|
||||
printf("%s\n",kval);
|
||||
if(rval) {
|
||||
if(users) {
|
||||
add_to_secrets_list(users,kval);
|
||||
if(realms) {
|
||||
if(rval && *rval) {
|
||||
add_to_secrets_list(realms,rval);
|
||||
} else {
|
||||
add_to_secrets_list(realms,(char*)realm);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("%s[%s]\n", kval, rval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -422,10 +396,19 @@ static int pgsql_list_users(int is_st, u08bits *realm) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_show_secret(u08bits *realm) {
|
||||
int ret = -1;
|
||||
static int pgsql_list_secrets(u08bits *realm, secrets_list_t *secrets, secrets_list_t *realms)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm);
|
||||
if (realm[0]) {
|
||||
snprintf(statement, sizeof(statement), "select value,realm from turn_secret where realm='%s' order by value", realm);
|
||||
} else {
|
||||
snprintf(statement, sizeof(statement), "select value,realm from turn_secret order by realm,value");
|
||||
}
|
||||
|
||||
donot_print_connection_success=1;
|
||||
|
||||
@@ -439,16 +422,28 @@ static int pgsql_show_secret(u08bits *realm) {
|
||||
for(i=0;i<PQntuples(res);i++) {
|
||||
char *kval = PQgetvalue(res,i,0);
|
||||
if(kval) {
|
||||
printf("%s\n",kval);
|
||||
char* rval = PQgetvalue(res,i,1);
|
||||
if(secrets) {
|
||||
add_to_secrets_list(secrets,kval);
|
||||
if(realms) {
|
||||
if(rval && *rval) {
|
||||
add_to_secrets_list(realms,rval);
|
||||
} else {
|
||||
add_to_secrets_list(realms,(char*)realm);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("%s[%s]\n",kval,rval);
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
}
|
||||
if(res) {
|
||||
PQclear(res);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_del_secret(u08bits *secret, u08bits *realm) {
|
||||
@@ -474,13 +469,13 @@ static int pgsql_del_secret(u08bits *secret, u08bits *realm) {
|
||||
static int pgsql_set_secret(u08bits *secret, u08bits *realm) {
|
||||
int ret = -1;
|
||||
donot_print_connection_success = 1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
PGconn *pqc = get_pqdb_connection();
|
||||
if (pqc) {
|
||||
snprintf(statement,sizeof(statement),"insert into turn_secret (realm,value) values('%s','%s')",realm,secret);
|
||||
PGresult *res = PQexec(pqc, statement);
|
||||
if (!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||
TURN_LOG_FUNC(
|
||||
TURN_LOG_FUNC(
|
||||
TURN_LOG_LEVEL_ERROR,
|
||||
"Error inserting/updating secret key information: %s\n",
|
||||
PQerrorMessage(pqc));
|
||||
@@ -492,7 +487,45 @@ static int pgsql_set_secret(u08bits *secret, u08bits *realm) {
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int del)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
donot_print_connection_success = 1;
|
||||
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
|
||||
PGconn *pqc = get_pqdb_connection();
|
||||
|
||||
if (pqc) {
|
||||
|
||||
if(del) {
|
||||
snprintf(statement, sizeof(statement), "delete from %s_peer_ip where realm = '%s' and ip_range = '%s'", kind, (char*)realm, ip);
|
||||
} else {
|
||||
snprintf(statement, sizeof(statement), "insert into %s_peer_ip (realm,ip_range) values('%s','%s')", kind, (char*)realm, ip);
|
||||
}
|
||||
|
||||
PGresult *res = PQexec(pqc, statement);
|
||||
if (!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||
TURN_LOG_FUNC(
|
||||
TURN_LOG_LEVEL_ERROR,
|
||||
"Error inserting ip permission information: %s\n",
|
||||
PQerrorMessage(pqc));
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
if (res) {
|
||||
PQclear(res);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_add_origin(u08bits *origin, u08bits *realm) {
|
||||
@@ -533,16 +566,25 @@ static int pgsql_del_origin(u08bits *origin) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_list_origins(u08bits *realm) {
|
||||
int ret = -1;
|
||||
static int pgsql_list_origins(u08bits *realm, secrets_list_t *origins, secrets_list_t *realms)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
donot_print_connection_success = 1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
|
||||
PGconn *pqc = get_pqdb_connection();
|
||||
|
||||
if(pqc) {
|
||||
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
|
||||
if(realm && realm[0]) {
|
||||
snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm where realm='%s' order by origin",realm);
|
||||
} else {
|
||||
snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm order by origin,realm");
|
||||
snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm order by realm,origin");
|
||||
}
|
||||
PGresult *res = PQexec(pqc, statement);
|
||||
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
|
||||
@@ -550,21 +592,32 @@ static int pgsql_list_origins(u08bits *realm) {
|
||||
} else {
|
||||
int i = 0;
|
||||
for(i=0;i<PQntuples(res);i++) {
|
||||
char *oval = PQgetvalue(res,i,0);
|
||||
if(oval) {
|
||||
char *kval = PQgetvalue(res,i,0);
|
||||
if(kval) {
|
||||
char *rval = PQgetvalue(res,i,1);
|
||||
if(rval) {
|
||||
printf("%s ==>> %s\n",oval,rval);
|
||||
if(origins) {
|
||||
add_to_secrets_list(origins,kval);
|
||||
if(realms) {
|
||||
if(rval && *rval) {
|
||||
add_to_secrets_list(realms,rval);
|
||||
} else {
|
||||
add_to_secrets_list(realms,(char*)realm);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("%s ==>> %s\n",kval,rval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
}
|
||||
if(res) {
|
||||
PQclear(res);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) {
|
||||
@@ -785,17 +838,131 @@ static void pgsql_reread_realms(secrets_list_t * realms_list) {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////
|
||||
|
||||
static int pgsql_get_admin_user(const u08bits *usname, u08bits *realm, password_t pwd)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
realm[0]=0;
|
||||
pwd[0]=0;
|
||||
|
||||
PGconn * pqc = get_pqdb_connection();
|
||||
if(pqc) {
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
snprintf(statement,sizeof(statement),"select realm,password from admin_user where name='%s'",usname);
|
||||
PGresult *res = PQexec(pqc, statement);
|
||||
|
||||
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res)!=1)) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
|
||||
} else {
|
||||
const char *kval = PQgetvalue(res,0,0);
|
||||
if(kval) {
|
||||
strncpy((char*)realm,kval,STUN_MAX_REALM_SIZE);
|
||||
}
|
||||
kval = (const char*) PQgetvalue(res,0,1);
|
||||
if(kval) {
|
||||
strncpy((char*)pwd,kval,STUN_MAX_PWD_SIZE);
|
||||
}
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if(res)
|
||||
PQclear(res);
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_set_admin_user(const u08bits *usname, const u08bits *realm, const password_t pwd)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
donot_print_connection_success=1;
|
||||
PGconn *pqc = get_pqdb_connection();
|
||||
if(pqc) {
|
||||
snprintf(statement,sizeof(statement),"insert into admin_user (realm,name,password) values('%s','%s','%s')",realm,usname,pwd);
|
||||
|
||||
PGresult *res = PQexec(pqc, statement);
|
||||
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||
if(res) {
|
||||
PQclear(res);
|
||||
}
|
||||
snprintf(statement,sizeof(statement),"update admin_user set password='%s',realm='%s' where name='%s'",pwd,realm,usname);
|
||||
res = PQexec(pqc, statement);
|
||||
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user information: %s\n",PQerrorMessage(pqc));
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
if(res) {
|
||||
PQclear(res);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_del_admin_user(const u08bits *usname)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
donot_print_connection_success=1;
|
||||
PGconn *pqc = get_pqdb_connection();
|
||||
if(pqc) {
|
||||
snprintf(statement,sizeof(statement),"delete from admin_user where name='%s'",usname);
|
||||
PGresult *res = PQexec(pqc, statement);
|
||||
if(res) {
|
||||
PQclear(res);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pgsql_list_admin_users(int no_print)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
donot_print_connection_success=1;
|
||||
PGconn *pqc = get_pqdb_connection();
|
||||
if(pqc) {
|
||||
snprintf(statement,sizeof(statement),"select name,realm,password from admin_user order by realm,name");
|
||||
}
|
||||
PGresult *res = PQexec(pqc, statement);
|
||||
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
|
||||
} else {
|
||||
int i = 0;
|
||||
ret = 0;
|
||||
for(i=0;i<PQntuples(res);i++) {
|
||||
char *kval = PQgetvalue(res,i,0);
|
||||
++ret;
|
||||
if(kval && !no_print) {
|
||||
char *rval = PQgetvalue(res,i,1);
|
||||
if(rval && *rval) {
|
||||
printf("%s[%s]\n",kval,rval);
|
||||
} else {
|
||||
printf("%s\n",kval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(res) {
|
||||
PQclear(res);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
static const turn_dbdriver_t driver = {
|
||||
&pgsql_get_auth_secrets,
|
||||
&pgsql_get_user_key,
|
||||
&pgsql_get_user_pwd,
|
||||
&pgsql_set_user_key,
|
||||
&pgsql_set_user_pwd,
|
||||
&pgsql_del_user,
|
||||
&pgsql_list_users,
|
||||
&pgsql_show_secret,
|
||||
&pgsql_list_secrets,
|
||||
&pgsql_del_secret,
|
||||
&pgsql_set_secret,
|
||||
&pgsql_add_origin,
|
||||
@@ -805,11 +972,16 @@ static const turn_dbdriver_t driver = {
|
||||
&pgsql_list_realm_options,
|
||||
&pgsql_auth_ping,
|
||||
&pgsql_get_ip_list,
|
||||
&pgsql_set_permission_ip,
|
||||
&pgsql_reread_realms,
|
||||
&pgsql_set_oauth_key,
|
||||
&pgsql_get_oauth_key,
|
||||
&pgsql_del_oauth_key,
|
||||
&pgsql_list_oauth_keys
|
||||
&pgsql_list_oauth_keys,
|
||||
&pgsql_get_admin_user,
|
||||
&pgsql_set_admin_user,
|
||||
&pgsql_del_admin_user,
|
||||
&pgsql_list_admin_users
|
||||
};
|
||||
|
||||
const turn_dbdriver_t * get_pgsql_dbdriver(void) {
|
||||
|
||||
@@ -450,23 +450,6 @@ static int redis_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) {
|
||||
}
|
||||
turnFreeRedisReply(rget);
|
||||
}
|
||||
if(ret == 0) {
|
||||
snprintf(s,sizeof(s),"get turn/realm/%s/user/%s/password", (char*)realm, usname);
|
||||
rget = (redisReply *)redisCommand(rc, s);
|
||||
if(rget) {
|
||||
if (rget->type == REDIS_REPLY_ERROR)
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", rget->str);
|
||||
else if (rget->type != REDIS_REPLY_STRING) {
|
||||
if (rget->type != REDIS_REPLY_NIL)
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
|
||||
} else {
|
||||
if(stun_produce_integrity_key_str((u08bits*)usname, realm, (u08bits*)rget->str, key, turn_params.shatype)>=0) {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
turnFreeRedisReply(rget);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -519,41 +502,15 @@ static int redis_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int redis_get_user_pwd(u08bits *usname, st_password_t pwd) {
|
||||
int ret = -1;
|
||||
redisContext * rc = get_redis_connection();
|
||||
if(rc) {
|
||||
char s[TURN_LONG_STRING_SIZE];
|
||||
snprintf(s,sizeof(s),"get turn/user/%s/password", usname);
|
||||
redisReply *rget = (redisReply *)redisCommand(rc, s);
|
||||
if(rget) {
|
||||
if (rget->type == REDIS_REPLY_ERROR)
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", rget->str);
|
||||
else if (rget->type != REDIS_REPLY_STRING) {
|
||||
if (rget->type != REDIS_REPLY_NIL)
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
|
||||
} else {
|
||||
strncpy((char*)pwd,rget->str,SHORT_TERM_PASSWORD_SIZE);
|
||||
pwd[SHORT_TERM_PASSWORD_SIZE]=0;
|
||||
ret = 0;
|
||||
}
|
||||
turnFreeRedisReply(rget);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int redis_set_user_key(u08bits *usname, u08bits *realm, const char *key) {
|
||||
int ret = -1;
|
||||
redisContext *rc = get_redis_connection();
|
||||
if(rc) {
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
snprintf(statement,sizeof(statement),"set turn/realm/%s/user/%s/key %s",(char*)realm,usname,key);
|
||||
turnFreeRedisReply(redisCommand(rc, statement));
|
||||
snprintf(statement,sizeof(statement),"del turn/realm/%s/user/%s/password",(char*)realm,usname);
|
||||
turnFreeRedisReply(redisCommand(rc, statement));
|
||||
snprintf(statement,sizeof(statement),"set turn/realm/%s/user/%s/key %s",(char*)realm,usname,key);
|
||||
turnFreeRedisReply(redisCommand(rc, statement));
|
||||
turnFreeRedisReply(redisCommand(rc, "save"));
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -563,7 +520,7 @@ 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' hkdf_hash_func '%s' as_rs_alg '%s' as_rs_key '%s' auth_alg '%s' auth_key '%s' timestamp %llu lifetime %lu",
|
||||
snprintf(statement,sizeof(statement),"hmset turn/oauth/kid/%s ikm_key %s hkdf_hash_func %s as_rs_alg %s as_rs_key %s auth_alg %s auth_key %s timestamp %llu lifetime %lu",
|
||||
key->kid,key->ikm_key,key->hkdf_hash_func,key->as_rs_alg,key->as_rs_key,key->auth_alg,key->auth_key,(unsigned long long)key->timestamp,(unsigned long)key->lifetime);
|
||||
turnFreeRedisReply(redisCommand(rc, statement));
|
||||
turnFreeRedisReply(redisCommand(rc, "save"));
|
||||
@@ -572,32 +529,14 @@ static int redis_set_oauth_key(oauth_key_data_raw *key) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int redis_set_user_pwd(u08bits *usname, st_password_t pwd) {
|
||||
static int redis_del_user(u08bits *usname, u08bits *realm) {
|
||||
int ret = -1;
|
||||
redisContext *rc = get_redis_connection();
|
||||
if(rc) {
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
snprintf(statement,sizeof(statement),"set turn/user/%s/password %s",usname,pwd);
|
||||
turnFreeRedisReply(redisCommand(rc, statement));
|
||||
turnFreeRedisReply(redisCommand(rc, "save"));
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int redis_del_user(u08bits *usname, int is_st, u08bits *realm) {
|
||||
int ret = -1;
|
||||
redisContext *rc = get_redis_connection();
|
||||
if(rc) {
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
if(is_st) {
|
||||
snprintf(statement,sizeof(statement),"del turn/user/%s/password",usname);
|
||||
turnFreeRedisReply(redisCommand(rc, statement));
|
||||
} else {
|
||||
{
|
||||
snprintf(statement,sizeof(statement),"del turn/realm/%s/user/%s/key",(char*)realm,usname);
|
||||
turnFreeRedisReply(redisCommand(rc, statement));
|
||||
snprintf(statement,sizeof(statement),"del turn/realm/%s/user/%s/password",(char*)realm,usname);
|
||||
turnFreeRedisReply(redisCommand(rc, statement));
|
||||
}
|
||||
|
||||
turnFreeRedisReply(redisCommand(rc, "save"));
|
||||
@@ -619,9 +558,14 @@ static int redis_del_oauth_key(const u08bits *kid) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int redis_list_users(int is_st, u08bits *realm) {
|
||||
int ret = -1;
|
||||
static int redis_list_users(u08bits *realm, secrets_list_t *users, secrets_list_t *realms)
|
||||
{
|
||||
int ret = -1;
|
||||
redisContext *rc = get_redis_connection();
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
if(rc) {
|
||||
secrets_list_t keys;
|
||||
size_t isz = 0;
|
||||
@@ -630,13 +574,13 @@ static int redis_list_users(int is_st, u08bits *realm) {
|
||||
|
||||
redisReply *reply = NULL;
|
||||
|
||||
if(!is_st) {
|
||||
|
||||
{
|
||||
if(realm && realm[0]) {
|
||||
reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/user/*/key", (char*)realm);
|
||||
} else {
|
||||
reply = (redisReply*)redisCommand(rc, "keys turn/realm/*/user/*/key");
|
||||
}
|
||||
|
||||
if(reply) {
|
||||
|
||||
if (reply->type == REDIS_REPLY_ERROR)
|
||||
@@ -652,65 +596,48 @@ static int redis_list_users(int is_st, u08bits *realm) {
|
||||
}
|
||||
turnFreeRedisReply(reply);
|
||||
}
|
||||
|
||||
if(realm && realm[0]) {
|
||||
reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/user/*/password", (char*)realm);
|
||||
} else {
|
||||
reply = (redisReply*)redisCommand(rc, "keys turn/realm/*/user/*/password");
|
||||
}
|
||||
if(reply) {
|
||||
|
||||
if (reply->type == REDIS_REPLY_ERROR)
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
|
||||
else if (reply->type != REDIS_REPLY_ARRAY) {
|
||||
if (reply->type != REDIS_REPLY_NIL)
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
|
||||
} else {
|
||||
size_t i;
|
||||
for (i = 0; i < reply->elements; ++i) {
|
||||
add_to_secrets_list(&keys,reply->element[i]->str);
|
||||
}
|
||||
}
|
||||
turnFreeRedisReply(reply);
|
||||
}
|
||||
} else {
|
||||
|
||||
reply = (redisReply*)redisCommand(rc, "keys turn/user/*/password");
|
||||
if(reply) {
|
||||
if (reply->type == REDIS_REPLY_ERROR)
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
|
||||
else if (reply->type != REDIS_REPLY_ARRAY) {
|
||||
if (reply->type != REDIS_REPLY_NIL)
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
|
||||
} else {
|
||||
size_t i;
|
||||
for (i = 0; i < reply->elements; ++i) {
|
||||
add_to_secrets_list(&keys,reply->element[i]->str);
|
||||
}
|
||||
}
|
||||
turnFreeRedisReply(reply);
|
||||
}
|
||||
}
|
||||
|
||||
size_t rhsz=strlen("turn/realm/");
|
||||
size_t uhsz = strlen("user/");
|
||||
|
||||
for(isz=0;isz<keys.sz;++isz) {
|
||||
char *s = keys.secrets[isz];
|
||||
char *sh = strstr(s,"/user/");
|
||||
if(sh) {
|
||||
sh += 6;
|
||||
char* st = strchr(sh,'/');
|
||||
if(st)
|
||||
*st=0;
|
||||
printf("%s\n",sh);
|
||||
|
||||
char *sh = strstr(s,"turn/realm/");
|
||||
if(sh != s) continue;
|
||||
sh += rhsz;
|
||||
char* st = strchr(sh,'/');
|
||||
if(!st) continue;
|
||||
*st=0;
|
||||
char *sr = sh;
|
||||
++st;
|
||||
|
||||
sh = strstr(st,"user/");
|
||||
if(sh != st) continue;
|
||||
sh += uhsz;
|
||||
st = strchr(sh,'/');
|
||||
if(!st) continue;
|
||||
*st=0;
|
||||
char *su = sh;
|
||||
|
||||
if(users) {
|
||||
add_to_secrets_list(users,su);
|
||||
if(realms) {
|
||||
add_to_secrets_list(realms,sr);
|
||||
}
|
||||
} else {
|
||||
printf("%s[%s]\n", su, sr);
|
||||
}
|
||||
}
|
||||
|
||||
clean_secrets_list(&keys);
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int redis_list_oauth_keys(void) {
|
||||
static int redis_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas,secrets_list_t *tss,secrets_list_t *lts) {
|
||||
int ret = -1;
|
||||
redisContext *rc = get_redis_connection();
|
||||
secrets_list_t keys;
|
||||
@@ -746,9 +673,26 @@ static int redis_list_oauth_keys(void) {
|
||||
oauth_key_data_raw key_;
|
||||
oauth_key_data_raw *key=&key_;
|
||||
if(redis_get_oauth_key((const u08bits*)s,key) == 0) {
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, hkdf_hash_func=%s, as_rs_alg=%s, as_rs_key=%s, auth_alg=%s, auth_key=%s\n",
|
||||
key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, key->hkdf_hash_func,
|
||||
key->as_rs_alg, key->as_rs_key, key->auth_alg, key->auth_key);
|
||||
if(kids) {
|
||||
add_to_secrets_list(kids,key->kid);
|
||||
add_to_secrets_list(hkdfs,key->hkdf_hash_func);
|
||||
add_to_secrets_list(teas,key->as_rs_alg);
|
||||
add_to_secrets_list(aas,key->auth_alg);
|
||||
{
|
||||
char ts[256];
|
||||
snprintf(ts,sizeof(ts)-1,"%llu",(unsigned long long)key->timestamp);
|
||||
add_to_secrets_list(tss,ts);
|
||||
}
|
||||
{
|
||||
char lt[256];
|
||||
snprintf(lt,sizeof(lt)-1,"%lu",(unsigned long)key->lifetime);
|
||||
add_to_secrets_list(lts,lt);
|
||||
}
|
||||
} else {
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, hkdf_hash_func=%s, as_rs_alg=%s, as_rs_key=%s, auth_alg=%s, auth_key=%s\n",
|
||||
key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, key->hkdf_hash_func,
|
||||
key->as_rs_alg, key->as_rs_key, key->auth_alg, key->auth_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -759,9 +703,13 @@ static int redis_list_oauth_keys(void) {
|
||||
}
|
||||
|
||||
|
||||
static int redis_show_secret(u08bits *realm)
|
||||
static int redis_list_secrets(u08bits *realm, secrets_list_t *secrets, secrets_list_t *realms)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
donot_print_connection_success = 1;
|
||||
redisContext *rc = get_redis_connection();
|
||||
if (rc) {
|
||||
@@ -790,6 +738,8 @@ static int redis_show_secret(u08bits *realm)
|
||||
}
|
||||
}
|
||||
|
||||
size_t rhsz=strlen("turn/realm/");
|
||||
|
||||
for (isz = 0; isz < keys.sz; ++isz) {
|
||||
snprintf(s, sizeof(s), "smembers %s", keys.secrets[isz]);
|
||||
redisReply *rget = (redisReply *) redisCommand(rc, s);
|
||||
@@ -802,9 +752,32 @@ static int redis_show_secret(u08bits *realm)
|
||||
if (rget->type != REDIS_REPLY_NIL)
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
|
||||
} else {
|
||||
|
||||
char *s = keys.secrets[isz];
|
||||
|
||||
char *sh = strstr(s,"turn/realm/");
|
||||
if(sh != s) continue;
|
||||
sh += rhsz;
|
||||
char* st = strchr(sh,'/');
|
||||
if(!st) continue;
|
||||
*st=0;
|
||||
const char *rval = sh;
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < rget->elements; ++i) {
|
||||
printf("%s\n", rget->element[i]->str);
|
||||
const char *kval = rget->element[i]->str;
|
||||
if(secrets) {
|
||||
add_to_secrets_list(secrets,kval);
|
||||
if(realms) {
|
||||
if(rval && *rval) {
|
||||
add_to_secrets_list(realms,rval);
|
||||
} else {
|
||||
add_to_secrets_list(realms,(char*)realm);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("%s[%s]\n", kval, rval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -853,6 +826,32 @@ static int redis_set_secret(u08bits *secret, u08bits *realm)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int redis_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int del)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
donot_print_connection_success = 1;
|
||||
|
||||
redisContext *rc = get_redis_connection();
|
||||
if (rc) {
|
||||
char s[TURN_LONG_STRING_SIZE];
|
||||
|
||||
if(del) {
|
||||
snprintf(s, sizeof(s), "srem turn/realm/%s/%s-peer-ip %s", (char*) realm, kind, ip);
|
||||
} else {
|
||||
snprintf(s, sizeof(s), "sadd turn/realm/%s/%s-peer-ip %s", (char*) realm, kind, ip);
|
||||
}
|
||||
|
||||
turnFreeRedisReply(redisCommand(rc, s));
|
||||
turnFreeRedisReply(redisCommand(rc, "save"));
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int redis_add_origin(u08bits *origin, u08bits *realm) {
|
||||
int ret = -1;
|
||||
@@ -884,9 +883,15 @@ static int redis_del_origin(u08bits *origin) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int redis_list_origins(u08bits *realm) {
|
||||
int ret = -1;
|
||||
static int redis_list_origins(u08bits *realm, secrets_list_t *origins, secrets_list_t *realms)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
donot_print_connection_success = 1;
|
||||
|
||||
redisContext *rc = get_redis_connection();
|
||||
if(rc) {
|
||||
secrets_list_t keys;
|
||||
@@ -917,6 +922,7 @@ static int redis_list_origins(u08bits *realm) {
|
||||
}
|
||||
|
||||
for(isz=0;isz<keys.sz;++isz) {
|
||||
|
||||
char *o = keys.secrets[isz];
|
||||
|
||||
reply = (redisReply*)redisCommand(rc, "get turn/origin/%s",o);
|
||||
@@ -929,7 +935,14 @@ static int redis_list_origins(u08bits *realm) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
|
||||
} else {
|
||||
if(!(realm && realm[0] && strcmp((char*)realm,reply->str))) {
|
||||
printf("%s ==>> %s\n",o,reply->str);
|
||||
if(origins) {
|
||||
add_to_secrets_list(origins,o);
|
||||
if(realms) {
|
||||
add_to_secrets_list(realms,reply->str);
|
||||
}
|
||||
} else {
|
||||
printf("%s ==>> %s\n",o,reply->str);
|
||||
}
|
||||
}
|
||||
}
|
||||
turnFreeRedisReply(reply);
|
||||
@@ -937,9 +950,9 @@ static int redis_list_origins(u08bits *realm) {
|
||||
}
|
||||
|
||||
clean_secrets_list(&keys);
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int redis_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) {
|
||||
@@ -1203,17 +1216,142 @@ static void redis_reread_realms(secrets_list_t * realms_list) {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
static int redis_get_admin_user(const u08bits *usname, u08bits *realm, password_t pwd)
|
||||
{
|
||||
int ret = -1;
|
||||
redisContext * rc = get_redis_connection();
|
||||
if(rc) {
|
||||
char s[TURN_LONG_STRING_SIZE];
|
||||
realm[0]=0;
|
||||
pwd[0]=0;
|
||||
snprintf(s,sizeof(s),"hgetall turn/admin_user/%s", (const char*)usname);
|
||||
redisReply *reply = (redisReply *)redisCommand(rc, s);
|
||||
if(reply) {
|
||||
if (reply->type == REDIS_REPLY_ERROR)
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
|
||||
else if (reply->type != REDIS_REPLY_ARRAY) {
|
||||
if (reply->type != REDIS_REPLY_NIL)
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
|
||||
} else if(reply->elements > 1) {
|
||||
size_t i;
|
||||
for (i = 0; i < (reply->elements)/2; ++i) {
|
||||
char *kw = reply->element[2*i]->str;
|
||||
char *val = reply->element[2*i+1]->str;
|
||||
if(kw) {
|
||||
if(!strcmp(kw,"realm")) {
|
||||
strncpy((char*)realm,val,STUN_MAX_REALM_SIZE);
|
||||
} else if(!strcmp(kw,"password")) {
|
||||
strncpy((char*)pwd,val,STUN_MAX_PWD_SIZE);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
turnFreeRedisReply(reply);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int redis_set_admin_user(const u08bits *usname, const u08bits *realm, const password_t pwd)
|
||||
{
|
||||
int ret = -1;
|
||||
donot_print_connection_success = 1;
|
||||
redisContext *rc = get_redis_connection();
|
||||
if(rc) {
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
if(realm[0]) {
|
||||
snprintf(statement,sizeof(statement),"hmset turn/admin_user/%s realm %s password %s",usname,realm,pwd);
|
||||
} else {
|
||||
snprintf(statement,sizeof(statement),"hmset turn/admin_user/%s password %s",usname,pwd);
|
||||
}
|
||||
turnFreeRedisReply(redisCommand(rc, statement));
|
||||
turnFreeRedisReply(redisCommand(rc, "save"));
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int redis_del_admin_user(const u08bits *usname) {
|
||||
int ret = -1;
|
||||
donot_print_connection_success = 1;
|
||||
redisContext *rc = get_redis_connection();
|
||||
if(rc) {
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
snprintf(statement,sizeof(statement),"del turn/admin_user/%s",(const char*)usname);
|
||||
turnFreeRedisReply(redisCommand(rc, statement));
|
||||
turnFreeRedisReply(redisCommand(rc, "save"));
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int redis_list_admin_users(int no_print)
|
||||
{
|
||||
int ret = -1;
|
||||
donot_print_connection_success = 1;
|
||||
redisContext *rc = get_redis_connection();
|
||||
secrets_list_t keys;
|
||||
size_t isz = 0;
|
||||
init_secrets_list(&keys);
|
||||
|
||||
if(rc) {
|
||||
|
||||
redisReply *reply = NULL;
|
||||
|
||||
reply = (redisReply*)redisCommand(rc, "keys turn/admin_user/*");
|
||||
if(reply) {
|
||||
|
||||
if (reply->type == REDIS_REPLY_ERROR) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
|
||||
} else if (reply->type != REDIS_REPLY_ARRAY) {
|
||||
if (reply->type != REDIS_REPLY_NIL) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
|
||||
}
|
||||
} else {
|
||||
size_t i;
|
||||
for (i = 0; i < reply->elements; ++i) {
|
||||
add_to_secrets_list(&keys,reply->element[i]->str);
|
||||
}
|
||||
}
|
||||
turnFreeRedisReply(reply);
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
for(isz=0;isz<keys.sz;++isz) {
|
||||
char *s = keys.secrets[isz];
|
||||
s += strlen("turn/admin_user/");
|
||||
u08bits realm[STUN_MAX_REALM_SIZE];
|
||||
password_t pwd;
|
||||
if(redis_get_admin_user((const u08bits*)s,realm,pwd) == 0) {
|
||||
++ret;
|
||||
if(!no_print) {
|
||||
if(realm[0]) {
|
||||
printf("%s[%s]\n",s,realm);
|
||||
} else {
|
||||
printf("%s\n",s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clean_secrets_list(&keys);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
static const turn_dbdriver_t driver = {
|
||||
&redis_get_auth_secrets,
|
||||
&redis_get_user_key,
|
||||
&redis_get_user_pwd,
|
||||
&redis_set_user_key,
|
||||
&redis_set_user_pwd,
|
||||
&redis_del_user,
|
||||
&redis_list_users,
|
||||
&redis_show_secret,
|
||||
&redis_list_secrets,
|
||||
&redis_del_secret,
|
||||
&redis_set_secret,
|
||||
&redis_add_origin,
|
||||
@@ -1223,11 +1361,16 @@ static const turn_dbdriver_t driver = {
|
||||
&redis_list_realm_options,
|
||||
&redis_auth_ping,
|
||||
&redis_get_ip_list,
|
||||
&redis_set_permission_ip,
|
||||
&redis_reread_realms,
|
||||
&redis_set_oauth_key,
|
||||
&redis_get_oauth_key,
|
||||
&redis_del_oauth_key,
|
||||
&redis_list_oauth_keys
|
||||
&redis_list_oauth_keys,
|
||||
&redis_get_admin_user,
|
||||
&redis_set_admin_user,
|
||||
&redis_del_admin_user,
|
||||
&redis_list_admin_users
|
||||
};
|
||||
|
||||
const turn_dbdriver_t * get_redis_dbdriver(void) {
|
||||
|
||||
@@ -148,14 +148,14 @@ static void fix_user_directory(char *dir0) {
|
||||
static void init_sqlite_database(sqlite3 *sqliteconnection) {
|
||||
|
||||
const char * statements[] = {
|
||||
"CREATE TABLE turnusers_lt ( realm varchar(512) default '', name varchar(512), hmackey char(128), PRIMARY KEY (realm,name))",
|
||||
"CREATE TABLE turnusers_st (name varchar(512) PRIMARY KEY, password varchar(512))",
|
||||
"CREATE TABLE turn_secret (realm varchar(512) default '', value varchar(512), primary key (realm,value))",
|
||||
"CREATE TABLE allowed_peer_ip (realm varchar(512) default '', ip_range varchar(256), primary key (realm,ip_range))",
|
||||
"CREATE TABLE denied_peer_ip (realm varchar(512) default '', ip_range varchar(256), primary key (realm,ip_range))",
|
||||
"CREATE TABLE turn_origin_to_realm (origin varchar(512),realm varchar(512),primary key (origin))",
|
||||
"CREATE TABLE turn_realm_option (realm varchar(512) default '', opt varchar(32), value varchar(128), primary key (realm,opt))",
|
||||
"CREATE TABLE turnusers_lt ( realm varchar(127) default '', name varchar(512), hmackey char(128), PRIMARY KEY (realm,name))",
|
||||
"CREATE TABLE turn_secret (realm varchar(127) default '', value varchar(127), primary key (realm,value))",
|
||||
"CREATE TABLE allowed_peer_ip (realm varchar(127) default '', ip_range varchar(256), primary key (realm,ip_range))",
|
||||
"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) default '',timestamp bigint default 0,lifetime integer default 0,hkdf_hash_func varchar(64) default '',as_rs_alg varchar(64) default '',as_rs_key varchar(256) default '',auth_alg varchar(64) default '',auth_key varchar(256) default '',primary key (kid))",
|
||||
"CREATE TABLE admin_user (uname varchar(32), realm varchar(127), password varchar(127), primary key (uname))",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -188,10 +188,12 @@ static sqlite3 * get_sqlite_connection(void) {
|
||||
sqliteconnection=NULL;
|
||||
}
|
||||
turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_UNKNOWN;
|
||||
} else if(!donot_print_connection_success){
|
||||
} else {
|
||||
init_sqlite_database(sqliteconnection);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SQLite DB connection success: %s\n",pud->userdb);
|
||||
donot_print_connection_success = 1;
|
||||
if(!donot_print_connection_success){
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SQLite DB connection success: %s\n",pud->userdb);
|
||||
donot_print_connection_success = 1;
|
||||
}
|
||||
}
|
||||
if(sqliteconnection) {
|
||||
(void) pthread_setspecific(connection_key, sqliteconnection);
|
||||
@@ -284,42 +286,6 @@ static int sqlite_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sqlite_get_user_pwd(u08bits *usname, st_password_t pwd)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
sqlite3_stmt *st = NULL;
|
||||
int rc = 0;
|
||||
snprintf(statement, sizeof(statement), "select password from turnusers_st where name='%s'", usname);
|
||||
|
||||
sqlite3 *sqliteconnection = get_sqlite_connection();
|
||||
if (sqliteconnection) {
|
||||
|
||||
sqlite_lock(0);
|
||||
|
||||
if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) {
|
||||
int res = sqlite3_step(st);
|
||||
if (res == SQLITE_ROW) {
|
||||
const char *kval = (const char*) sqlite3_column_text(st, 0);
|
||||
if (kval) {
|
||||
strncpy((char*) pwd, kval, sizeof(st_password_t));
|
||||
ret = 0;
|
||||
} else {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong password data for user %s: NULL\n", usname);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const char* errmsg = sqlite3_errmsg(sqliteconnection);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg);
|
||||
}
|
||||
|
||||
sqlite3_finalize(st);
|
||||
|
||||
sqlite_unlock(0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sqlite_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
|
||||
int ret = -1;
|
||||
@@ -339,15 +305,15 @@ static int sqlite_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
int res = sqlite3_step(st);
|
||||
if (res == SQLITE_ROW) {
|
||||
|
||||
STRCPY((char*)key->ikm_key,sqlite3_column_text(st, 0));
|
||||
STRCPY(key->ikm_key,sqlite3_column_text(st, 0));
|
||||
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((char*)key->hkdf_hash_func,sqlite3_column_text(st, 3));
|
||||
STRCPY((char*)key->as_rs_alg,sqlite3_column_text(st, 4));
|
||||
STRCPY((char*)key->as_rs_key,sqlite3_column_text(st, 5));
|
||||
STRCPY((char*)key->auth_alg,sqlite3_column_text(st, 6));
|
||||
STRCPY((char*)key->auth_key,sqlite3_column_text(st, 7));
|
||||
STRCPY((char*)key->kid,kid);
|
||||
STRCPY(key->hkdf_hash_func,sqlite3_column_text(st, 3));
|
||||
STRCPY(key->as_rs_alg,sqlite3_column_text(st, 4));
|
||||
STRCPY(key->as_rs_key,sqlite3_column_text(st, 5));
|
||||
STRCPY(key->auth_alg,sqlite3_column_text(st, 6));
|
||||
STRCPY(key->auth_key,sqlite3_column_text(st, 7));
|
||||
STRCPY(key->kid,kid);
|
||||
ret = 0;
|
||||
}
|
||||
} else {
|
||||
@@ -363,7 +329,7 @@ static int sqlite_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sqlite_list_oauth_keys(void) {
|
||||
static int sqlite_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas,secrets_list_t *tss,secrets_list_t *lts) {
|
||||
|
||||
oauth_key_data_raw key_;
|
||||
oauth_key_data_raw *key=&key_;
|
||||
@@ -389,19 +355,36 @@ static int sqlite_list_oauth_keys(void) {
|
||||
int res = sqlite3_step(st);
|
||||
if (res == SQLITE_ROW) {
|
||||
|
||||
STRCPY((char*)key->ikm_key,sqlite3_column_text(st, 0));
|
||||
STRCPY(key->ikm_key,sqlite3_column_text(st, 0));
|
||||
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((char*)key->hkdf_hash_func,sqlite3_column_text(st, 3));
|
||||
STRCPY((char*)key->as_rs_alg,sqlite3_column_text(st, 4));
|
||||
STRCPY((char*)key->as_rs_key,sqlite3_column_text(st, 5));
|
||||
STRCPY((char*)key->auth_alg,sqlite3_column_text(st, 6));
|
||||
STRCPY((char*)key->auth_key,sqlite3_column_text(st, 7));
|
||||
STRCPY((char*)key->kid,sqlite3_column_text(st, 7));
|
||||
STRCPY(key->hkdf_hash_func,sqlite3_column_text(st, 3));
|
||||
STRCPY(key->as_rs_alg,sqlite3_column_text(st, 4));
|
||||
STRCPY(key->as_rs_key,sqlite3_column_text(st, 5));
|
||||
STRCPY(key->auth_alg,sqlite3_column_text(st, 6));
|
||||
STRCPY(key->auth_key,sqlite3_column_text(st, 7));
|
||||
STRCPY(key->kid,sqlite3_column_text(st, 8));
|
||||
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, hkdf_hash_func=%s, as_rs_alg=%s, as_rs_key=%s, auth_alg=%s, auth_key=%s\n",
|
||||
key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, key->hkdf_hash_func,
|
||||
key->as_rs_alg, key->as_rs_key, key->auth_alg, key->auth_key);
|
||||
if(kids) {
|
||||
add_to_secrets_list(kids,key->kid);
|
||||
add_to_secrets_list(hkdfs,key->hkdf_hash_func);
|
||||
add_to_secrets_list(teas,key->as_rs_alg);
|
||||
add_to_secrets_list(aas,key->auth_alg);
|
||||
{
|
||||
char ts[256];
|
||||
snprintf(ts,sizeof(ts)-1,"%llu",(unsigned long long)key->timestamp);
|
||||
add_to_secrets_list(tss,ts);
|
||||
}
|
||||
{
|
||||
char lt[256];
|
||||
snprintf(lt,sizeof(lt)-1,"%lu",(unsigned long)key->lifetime);
|
||||
add_to_secrets_list(lts,lt);
|
||||
}
|
||||
} else {
|
||||
printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, hkdf_hash_func=%s, as_rs_alg=%s, as_rs_key=%s, auth_alg=%s, auth_key=%s\n",
|
||||
key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, key->hkdf_hash_func,
|
||||
key->as_rs_alg, key->as_rs_key, key->auth_alg, key->auth_key);
|
||||
}
|
||||
|
||||
} else if (res == SQLITE_DONE) {
|
||||
break;
|
||||
@@ -481,7 +464,7 @@ static int sqlite_set_oauth_key(oauth_key_data_raw *key)
|
||||
ret = 0;
|
||||
} else {
|
||||
const char* errmsg = sqlite3_errmsg(sqliteconnection);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error updating SQLite DB information: %s\n", errmsg);
|
||||
}
|
||||
sqlite3_finalize(st);
|
||||
|
||||
@@ -490,7 +473,7 @@ static int sqlite_set_oauth_key(oauth_key_data_raw *key)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sqlite_set_user_pwd(u08bits *usname, st_password_t pwd)
|
||||
static int sqlite_del_user(u08bits *usname, u08bits *realm)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
@@ -501,40 +484,7 @@ static int sqlite_set_user_pwd(u08bits *usname, st_password_t pwd)
|
||||
|
||||
sqlite3 *sqliteconnection = get_sqlite_connection();
|
||||
if (sqliteconnection) {
|
||||
snprintf(statement, sizeof(statement), "insert or replace into turnusers_st values('%s','%s')", usname, pwd);
|
||||
|
||||
sqlite_lock(1);
|
||||
|
||||
if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) {
|
||||
sqlite3_step(st);
|
||||
ret = 0;
|
||||
} else {
|
||||
const char* errmsg = sqlite3_errmsg(sqliteconnection);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg);
|
||||
}
|
||||
sqlite3_finalize(st);
|
||||
|
||||
sqlite_unlock(1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sqlite_del_user(u08bits *usname, int is_st, u08bits *realm)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
sqlite3_stmt *st = NULL;
|
||||
int rc = 0;
|
||||
|
||||
donot_print_connection_success=1;
|
||||
|
||||
sqlite3 *sqliteconnection = get_sqlite_connection();
|
||||
if (sqliteconnection) {
|
||||
if (is_st) {
|
||||
snprintf(statement, sizeof(statement), "delete from turnusers_st where name='%s'", usname);
|
||||
} else {
|
||||
snprintf(statement, sizeof(statement), "delete from turnusers_lt where name='%s' and realm='%s'", usname, realm);
|
||||
}
|
||||
snprintf(statement, sizeof(statement), "delete from turnusers_lt where name='%s' and realm='%s'", usname, realm);
|
||||
|
||||
sqlite_lock(1);
|
||||
|
||||
@@ -583,23 +533,24 @@ static int sqlite_del_oauth_key(const u08bits *kid)
|
||||
}
|
||||
|
||||
|
||||
static int sqlite_list_users(int is_st, u08bits *realm)
|
||||
static int sqlite_list_users(u08bits *realm, secrets_list_t *users, secrets_list_t *realms)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
sqlite3_stmt *st = NULL;
|
||||
int rc = 0;
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
donot_print_connection_success=1;
|
||||
|
||||
sqlite3 *sqliteconnection = get_sqlite_connection();
|
||||
if (sqliteconnection) {
|
||||
if (is_st) {
|
||||
snprintf(statement, sizeof(statement), "select name,'' from turnusers_st order by name");
|
||||
} else if (realm && realm[0]) {
|
||||
if (realm[0]) {
|
||||
snprintf(statement, sizeof(statement), "select name,realm from turnusers_lt where realm='%s' order by name", realm);
|
||||
} else {
|
||||
snprintf(statement, sizeof(statement), "select name,realm from turnusers_lt order by name");
|
||||
snprintf(statement, sizeof(statement), "select name,realm from turnusers_lt order by realm,name");
|
||||
}
|
||||
|
||||
sqlite_lock(0);
|
||||
@@ -614,10 +565,17 @@ static int sqlite_list_users(int is_st, u08bits *realm)
|
||||
const char* kval = (const char*) sqlite3_column_text(st, 0);
|
||||
const char* rval = (const char*) sqlite3_column_text(st, 1);
|
||||
|
||||
if (rval && *rval) {
|
||||
printf("%s[%s]\n", kval, rval);
|
||||
if(users) {
|
||||
add_to_secrets_list(users,kval);
|
||||
if(realms) {
|
||||
if(rval && *rval) {
|
||||
add_to_secrets_list(realms,rval);
|
||||
} else {
|
||||
add_to_secrets_list(realms,(char*)realm);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("%s\n", kval);
|
||||
printf("%s[%s]\n", kval, rval);
|
||||
}
|
||||
|
||||
} else if (res == SQLITE_DONE) {
|
||||
@@ -640,13 +598,22 @@ static int sqlite_list_users(int is_st, u08bits *realm)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sqlite_show_secret(u08bits *realm)
|
||||
static int sqlite_list_secrets(u08bits *realm, secrets_list_t *secrets, secrets_list_t *realms)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
sqlite3_stmt *st = NULL;
|
||||
int rc = 0;
|
||||
snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm);
|
||||
|
||||
if (realm[0]) {
|
||||
snprintf(statement, sizeof(statement), "select value,realm from turn_secret where realm='%s' order by value", realm);
|
||||
} else {
|
||||
snprintf(statement, sizeof(statement), "select value,realm from turn_secret order by realm,value");
|
||||
}
|
||||
|
||||
donot_print_connection_success=1;
|
||||
|
||||
@@ -656,17 +623,37 @@ static int sqlite_show_secret(u08bits *realm)
|
||||
sqlite_lock(0);
|
||||
|
||||
if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) {
|
||||
int res = sqlite3_step(st);
|
||||
if (res == SQLITE_ROW) {
|
||||
ret = 0;
|
||||
const char* kval = (const char*) sqlite3_column_text(st, 0);
|
||||
if(kval) {
|
||||
printf("%s\n",kval);
|
||||
|
||||
int res = 0;
|
||||
while(1) {
|
||||
res = sqlite3_step(st);
|
||||
if (res == SQLITE_ROW) {
|
||||
ret = 0;
|
||||
const char* kval = (const char*) sqlite3_column_text(st, 0);
|
||||
if(kval) {
|
||||
const char* rval = (const char*) sqlite3_column_text(st, 1);
|
||||
if(secrets) {
|
||||
add_to_secrets_list(secrets,kval);
|
||||
if(realms) {
|
||||
if(rval && *rval) {
|
||||
add_to_secrets_list(realms,rval);
|
||||
} else {
|
||||
add_to_secrets_list(realms,(char*)realm);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("%s[%s]\n",kval,rval);
|
||||
}
|
||||
}
|
||||
} else if (res == SQLITE_DONE) {
|
||||
break;
|
||||
} else {
|
||||
const char* errmsg = sqlite3_errmsg(sqliteconnection);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const char* errmsg = sqlite3_errmsg(sqliteconnection);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg);
|
||||
}
|
||||
sqlite3_finalize(st);
|
||||
|
||||
@@ -791,20 +778,25 @@ static int sqlite_del_origin(u08bits *origin)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sqlite_list_origins(u08bits *realm)
|
||||
static int sqlite_list_origins(u08bits *realm, secrets_list_t *origins, secrets_list_t *realms)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
donot_print_connection_success = 1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
|
||||
sqlite3_stmt *st = NULL;
|
||||
int rc = 0;
|
||||
|
||||
sqlite3 *sqliteconnection = get_sqlite_connection();
|
||||
if (sqliteconnection) {
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
if (realm && realm[0]) {
|
||||
snprintf(statement, sizeof(statement), "select origin,realm from turn_origin_to_realm where realm='%s' order by origin", realm);
|
||||
} else {
|
||||
snprintf(statement, sizeof(statement), "select origin,realm from turn_origin_to_realm order by origin,realm");
|
||||
snprintf(statement, sizeof(statement), "select origin,realm from turn_origin_to_realm order by realm,origin");
|
||||
}
|
||||
|
||||
sqlite_lock(0);
|
||||
@@ -819,8 +811,18 @@ static int sqlite_list_origins(u08bits *realm)
|
||||
const char* kval = (const char*) sqlite3_column_text(st, 0);
|
||||
const char* rval = (const char*) sqlite3_column_text(st, 1);
|
||||
|
||||
printf("%s ==>> %s\n",kval,rval);
|
||||
|
||||
if(origins) {
|
||||
add_to_secrets_list(origins,kval);
|
||||
if(realms) {
|
||||
if(rval && *rval) {
|
||||
add_to_secrets_list(realms,rval);
|
||||
} else {
|
||||
add_to_secrets_list(realms,(char*)realm);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("%s ==>> %s\n",kval,rval);
|
||||
}
|
||||
} else if (res == SQLITE_DONE) {
|
||||
break;
|
||||
} else {
|
||||
@@ -974,6 +976,45 @@ static int sqlite_get_ip_list(const char *kind, ip_range_list_t * list)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sqlite_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int del)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
|
||||
if(!realm) realm=realm0;
|
||||
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
|
||||
sqlite3_stmt *st = NULL;
|
||||
int rc = 0;
|
||||
|
||||
donot_print_connection_success=1;
|
||||
|
||||
sqlite3 *sqliteconnection = get_sqlite_connection();
|
||||
if (sqliteconnection) {
|
||||
|
||||
sqlite_lock(1);
|
||||
|
||||
if(del) {
|
||||
snprintf(statement, sizeof(statement), "delete from %s_peer_ip where realm = '%s' and ip_range = '%s'", kind, (char*)realm, ip);
|
||||
} else {
|
||||
snprintf(statement, sizeof(statement), "insert or replace into %s_peer_ip (realm,ip_range) values('%s','%s')", kind, (char*)realm, ip);
|
||||
}
|
||||
|
||||
if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) {
|
||||
sqlite3_step(st);
|
||||
ret = 0;
|
||||
} else {
|
||||
const char* errmsg = sqlite3_errmsg(sqliteconnection);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error updating SQLite DB information: %s\n", errmsg);
|
||||
}
|
||||
sqlite3_finalize(st);
|
||||
|
||||
sqlite_unlock(1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sqlite_reread_realms(secrets_list_t * realms_list)
|
||||
{
|
||||
sqlite3 *sqliteconnection = get_sqlite_connection();
|
||||
@@ -1098,17 +1139,172 @@ static void sqlite_reread_realms(secrets_list_t * realms_list)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
static int sqlite_get_admin_user(const u08bits *usname, u08bits *realm, password_t pwd)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
realm[0]=0;
|
||||
pwd[0]=0;
|
||||
|
||||
sqlite3 *sqliteconnection = get_sqlite_connection();
|
||||
if (sqliteconnection) {
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
sqlite3_stmt *st = NULL;
|
||||
int rc = 0;
|
||||
snprintf(statement, sizeof(statement), "select realm,password from admin_user where name='%s'", usname);
|
||||
|
||||
sqlite_lock(0);
|
||||
|
||||
if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) {
|
||||
int res = sqlite3_step(st);
|
||||
if (res == SQLITE_ROW) {
|
||||
const char *kval = (const char*) sqlite3_column_text(st, 0);
|
||||
if(kval) {
|
||||
strncpy((char*)realm,kval,STUN_MAX_REALM_SIZE);
|
||||
}
|
||||
kval = (const char*) sqlite3_column_text(st, 1);
|
||||
if(kval) {
|
||||
strncpy((char*)pwd,kval,STUN_MAX_PWD_SIZE);
|
||||
}
|
||||
ret = 0;
|
||||
}
|
||||
} else {
|
||||
const char* errmsg = sqlite3_errmsg(sqliteconnection);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg);
|
||||
}
|
||||
|
||||
sqlite3_finalize(st);
|
||||
|
||||
sqlite_unlock(0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sqlite_set_admin_user(const u08bits *usname, const u08bits *realm, const password_t pwd)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
sqlite3_stmt *st = NULL;
|
||||
int rc = 0;
|
||||
|
||||
donot_print_connection_success=1;
|
||||
|
||||
sqlite3 *sqliteconnection = get_sqlite_connection();
|
||||
if (sqliteconnection) {
|
||||
|
||||
sqlite_lock(1);
|
||||
|
||||
snprintf(statement, sizeof(statement), "insert or replace into admin_user (realm,name,password) values('%s','%s','%s')", realm, usname, pwd);
|
||||
|
||||
if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) {
|
||||
sqlite3_step(st);
|
||||
ret = 0;
|
||||
} else {
|
||||
const char* errmsg = sqlite3_errmsg(sqliteconnection);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg);
|
||||
}
|
||||
sqlite3_finalize(st);
|
||||
|
||||
sqlite_unlock(1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sqlite_del_admin_user(const u08bits *usname)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
sqlite3_stmt *st = NULL;
|
||||
int rc = 0;
|
||||
|
||||
donot_print_connection_success=1;
|
||||
|
||||
sqlite3 *sqliteconnection = get_sqlite_connection();
|
||||
if (sqliteconnection) {
|
||||
snprintf(statement, sizeof(statement), "delete from admin_user where name='%s'", usname);
|
||||
|
||||
sqlite_lock(1);
|
||||
|
||||
if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) {
|
||||
sqlite3_step(st);
|
||||
ret = 0;
|
||||
} else {
|
||||
const char* errmsg = sqlite3_errmsg(sqliteconnection);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg);
|
||||
}
|
||||
sqlite3_finalize(st);
|
||||
|
||||
sqlite_unlock(1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sqlite_list_admin_users(int no_print)
|
||||
{
|
||||
int ret = -1;
|
||||
char statement[TURN_LONG_STRING_SIZE];
|
||||
sqlite3_stmt *st = NULL;
|
||||
int rc = 0;
|
||||
|
||||
donot_print_connection_success=1;
|
||||
|
||||
sqlite3 *sqliteconnection = get_sqlite_connection();
|
||||
if (sqliteconnection) {
|
||||
snprintf(statement, sizeof(statement), "select name,realm from admin_user order by realm,name");
|
||||
|
||||
sqlite_lock(0);
|
||||
|
||||
if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) {
|
||||
|
||||
ret = 0;
|
||||
while (1) {
|
||||
int res = sqlite3_step(st);
|
||||
if (res == SQLITE_ROW) {
|
||||
|
||||
const char* kval = (const char*) sqlite3_column_text(st, 0);
|
||||
const char* rval = (const char*) sqlite3_column_text(st, 1);
|
||||
|
||||
if(!no_print) {
|
||||
if (rval && *rval) {
|
||||
printf("%s[%s]\n", kval, rval);
|
||||
} else {
|
||||
printf("%s\n", kval);
|
||||
}
|
||||
}
|
||||
|
||||
++ret;
|
||||
|
||||
} else if (res == SQLITE_DONE) {
|
||||
break;
|
||||
} else {
|
||||
const char* errmsg = sqlite3_errmsg(sqliteconnection);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const char* errmsg = sqlite3_errmsg(sqliteconnection);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg);
|
||||
}
|
||||
sqlite3_finalize(st);
|
||||
|
||||
sqlite_unlock(0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
static const turn_dbdriver_t driver = {
|
||||
&sqlite_get_auth_secrets,
|
||||
&sqlite_get_user_key,
|
||||
&sqlite_get_user_pwd,
|
||||
&sqlite_set_user_key,
|
||||
&sqlite_set_user_pwd,
|
||||
&sqlite_del_user,
|
||||
&sqlite_list_users,
|
||||
&sqlite_show_secret,
|
||||
&sqlite_list_secrets,
|
||||
&sqlite_del_secret,
|
||||
&sqlite_set_secret,
|
||||
&sqlite_add_origin,
|
||||
@@ -1118,11 +1314,16 @@ static const turn_dbdriver_t driver = {
|
||||
&sqlite_list_realm_options,
|
||||
&sqlite_auth_ping,
|
||||
&sqlite_get_ip_list,
|
||||
&sqlite_set_permission_ip,
|
||||
&sqlite_reread_realms,
|
||||
&sqlite_set_oauth_key,
|
||||
&sqlite_get_oauth_key,
|
||||
&sqlite_del_oauth_key,
|
||||
&sqlite_list_oauth_keys
|
||||
&sqlite_list_oauth_keys,
|
||||
&sqlite_get_admin_user,
|
||||
&sqlite_set_admin_user,
|
||||
&sqlite_del_admin_user,
|
||||
&sqlite_list_admin_users
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
@@ -50,26 +50,29 @@ extern pthread_once_t connection_key_once;
|
||||
typedef struct _turn_dbdriver_t {
|
||||
int (*get_auth_secrets)(secrets_list_t *sl, u08bits *realm);
|
||||
int (*get_user_key)(u08bits *usname, u08bits *realm, hmackey_t key);
|
||||
int (*get_user_pwd)(u08bits *usname, st_password_t pwd);
|
||||
int (*set_user_key)(u08bits *usname, u08bits *realm, const char *key);
|
||||
int (*set_user_pwd)(u08bits *usname, st_password_t pwd);
|
||||
int (*del_user)(u08bits *usname, int is_st, u08bits *realm);
|
||||
int (*list_users)(int is_st, u08bits *realm);
|
||||
int (*show_secret)(u08bits *realm);
|
||||
int (*del_user)(u08bits *usname, u08bits *realm);
|
||||
int (*list_users)(u08bits *realm, secrets_list_t *users, secrets_list_t *realms);
|
||||
int (*list_secrets)(u08bits *realm, secrets_list_t *secrets, secrets_list_t *realms);
|
||||
int (*del_secret)(u08bits *secret, u08bits *realm);
|
||||
int (*set_secret)(u08bits *secret, u08bits *realm);
|
||||
int (*add_origin)(u08bits *origin, u08bits *realm);
|
||||
int (*del_origin)(u08bits *origin);
|
||||
int (*list_origins)(u08bits *realm);
|
||||
int (*list_origins)(u08bits *realm, secrets_list_t *origins, secrets_list_t *realms);
|
||||
int (*set_realm_option_one)(u08bits *realm, unsigned long value, const char* opt);
|
||||
int (*list_realm_options)(u08bits *realm);
|
||||
void (*auth_ping)(void * rch);
|
||||
int (*get_ip_list)(const char *kind, ip_range_list_t * list);
|
||||
int (*set_permission_ip)(const char *kind, u08bits *realm, const char* ip, int del);
|
||||
void (*reread_realms)(secrets_list_t * realms_list);
|
||||
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)(void);
|
||||
int (*list_oauth_keys)(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas,secrets_list_t *tss,secrets_list_t *lts);
|
||||
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);
|
||||
int (*list_admin_users)(int no_print);
|
||||
} turn_dbdriver_t;
|
||||
|
||||
/////////// USER DB CHECK //////////////////
|
||||
|
||||
@@ -459,7 +459,9 @@ static int handle_udp_packet(dtls_listener_relay_server_type *server,
|
||||
}
|
||||
s->e = ioa_eng;
|
||||
add_socket_to_map(s, amap);
|
||||
open_client_connection_session(ts, &(sm->m.sm));
|
||||
if(open_client_connection_session(ts, &(sm->m.sm))<0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2011, 2012, 2013 Citrix Systems
|
||||
* Copyright (C) 2011, 2012, 2013, 2014 Citrix Systems
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -30,7 +30,29 @@
|
||||
|
||||
#include "ns_ioalib_impl.h"
|
||||
|
||||
void write_http_echo(ioa_socket_handle s)
|
||||
#include "http_server.h"
|
||||
|
||||
#include <event2/http.h>
|
||||
#include <event2/keyvalq_struct.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
struct headers_list {
|
||||
size_t n;
|
||||
char **keys;
|
||||
char **values;
|
||||
};
|
||||
|
||||
struct http_headers {
|
||||
struct evkeyvalq *uri_headers;
|
||||
struct headers_list *post_headers;
|
||||
};
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
static void write_http_echo(ioa_socket_handle s)
|
||||
{
|
||||
if(s && !ioa_socket_tobeclosed(s)) {
|
||||
SOCKET_APP_TYPE sat = get_ioa_socket_app_type(s);
|
||||
@@ -41,8 +63,8 @@ void write_http_echo(ioa_socket_handle s)
|
||||
char data_http[1025];
|
||||
char content_http[1025];
|
||||
const char* title = "TURN Server";
|
||||
snprintf(content_http,sizeof(content_http)-1,"<!DOCTYPE html>\r\n<html>\r\n <head>\r\n <title>%s</title>\r\n </head>\r\n <body>\r\n %s\r\n </body>\r\n</html>\r\n",title,title);
|
||||
snprintf(data_http,sizeof(data_http)-1,"HTTP/1.1 200 OK\r\nServer: %s\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: %d\r\n\r\n%s",TURN_SOFTWARE,(int)strlen(content_http),content_http);
|
||||
snprintf(content_http,sizeof(content_http)-1,"<!DOCTYPE html>\r\n<html>\r\n <head>\r\n <title>%s</title>\r\n </head>\r\n <body>\r\n <b>%s</b> <br> <b><i>use https connection for the admin session</i></b>\r\n </body>\r\n</html>\r\n",title,title);
|
||||
snprintf(data_http,sizeof(data_http)-1,"HTTP/1.0 200 OK\r\nServer: %s\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: %d\r\n\r\n%s",TURN_SOFTWARE,(int)strlen(content_http),content_http);
|
||||
len_http = strlen(data_http);
|
||||
ns_bcopy(data_http,data,len_http);
|
||||
ioa_network_buffer_set_size(nbh_http,len_http);
|
||||
@@ -51,8 +73,307 @@ void write_http_echo(ioa_socket_handle s)
|
||||
}
|
||||
}
|
||||
|
||||
void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) {
|
||||
//TODO
|
||||
UNUSED_ARG(nbh);
|
||||
void handle_http_echo(ioa_socket_handle s) {
|
||||
write_http_echo(s);
|
||||
}
|
||||
|
||||
const char* get_http_date_header()
|
||||
{
|
||||
static char buffer_date[256];
|
||||
static char buffer_header[1025];
|
||||
static const char* wds[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
|
||||
static const char* mons[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
|
||||
|
||||
time_t now = time(NULL);
|
||||
struct tm *gmtm = gmtime(&now);
|
||||
|
||||
buffer_header[0]=0;
|
||||
buffer_date[0]=0;
|
||||
if(gmtm) {
|
||||
snprintf(buffer_date,sizeof(buffer_date)-1,"%s, %d %s %d %d:%d:%d GMT",wds[gmtm->tm_wday], gmtm->tm_mday, mons[gmtm->tm_mon], gmtm->tm_year+1900, gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec);
|
||||
buffer_date[sizeof(buffer_date)-1]=0;
|
||||
snprintf(buffer_header,sizeof(buffer_header)-1,"Date: %s\r\n",buffer_date);
|
||||
buffer_header[sizeof(buffer_header)-1]=0;
|
||||
}
|
||||
|
||||
return buffer_header;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
||||
static struct headers_list * post_parse(char *data, size_t data_len)
|
||||
{
|
||||
while((*data=='\r')||(*data=='\n')) ++data;
|
||||
char *post_data = (char*)calloc(data_len + 1, sizeof(char));
|
||||
memcpy(post_data, data, data_len);
|
||||
char *fmarker = NULL;
|
||||
char *fsplit = strtok_r(post_data, "&", &fmarker);
|
||||
struct headers_list *list = (struct headers_list*)malloc(sizeof(struct headers_list));
|
||||
ns_bzero(list,sizeof(struct headers_list));
|
||||
while (fsplit != NULL) {
|
||||
char *vmarker = NULL;
|
||||
char *key = strtok_r(fsplit, "=", &vmarker);
|
||||
char *value = strtok_r(NULL, "=", &vmarker);
|
||||
char empty[1];
|
||||
empty[0]=0;
|
||||
value = value ? value : empty;
|
||||
value = evhttp_decode_uri(value);
|
||||
char *p = value;
|
||||
while (*p) {
|
||||
if (*p == '+')
|
||||
*p = ' ';
|
||||
p++;
|
||||
}
|
||||
list->keys = (char**)realloc(list->keys,sizeof(char*)*(list->n+1));
|
||||
list->keys[list->n] = strdup(key);
|
||||
list->values = (char**)realloc(list->values,sizeof(char*)*(list->n+1));
|
||||
list->values[list->n] = value;
|
||||
++(list->n);
|
||||
fsplit = strtok_r(NULL, "&", &fmarker);
|
||||
}
|
||||
free(post_data);
|
||||
return list;
|
||||
}
|
||||
|
||||
static struct http_request* parse_http_request_1(struct http_request* ret, char* request, int parse_post)
|
||||
{
|
||||
|
||||
if(ret && request) {
|
||||
|
||||
char* s = strstr(request," HTTP/");
|
||||
if(!s) {
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
} else {
|
||||
*s = 0;
|
||||
|
||||
struct evhttp_uri *uri = evhttp_uri_parse(request);
|
||||
if(!uri) {
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
} else {
|
||||
|
||||
const char *query = evhttp_uri_get_query(uri);
|
||||
if(query) {
|
||||
struct evkeyvalq* kv = (struct evkeyvalq*)malloc(sizeof(struct evkeyvalq));
|
||||
ns_bzero(kv,sizeof(struct evkeyvalq));
|
||||
if(evhttp_parse_query_str(query, kv)<0) {
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
} else {
|
||||
ret->headers = (struct http_headers*)malloc(sizeof(struct http_headers));
|
||||
ns_bzero(ret->headers,sizeof(struct http_headers));
|
||||
ret->headers->uri_headers = kv;
|
||||
}
|
||||
}
|
||||
|
||||
const char *path = evhttp_uri_get_path(uri);
|
||||
if(path)
|
||||
ret->path = strdup(path);
|
||||
|
||||
evhttp_uri_free(uri);
|
||||
|
||||
if(parse_post) {
|
||||
char *body = strstr(s+1,"\r\n\r\n");
|
||||
if(body && body[0]) {
|
||||
if(!ret->headers) {
|
||||
ret->headers = (struct http_headers*)malloc(sizeof(struct http_headers));
|
||||
ns_bzero(ret->headers,sizeof(struct http_headers));
|
||||
}
|
||||
ret->headers->post_headers = post_parse(body,strlen(body));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*s = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct http_request* parse_http_request(char* request) {
|
||||
|
||||
struct http_request* ret = NULL;
|
||||
|
||||
if(request) {
|
||||
|
||||
ret = (struct http_request*)malloc(sizeof(struct http_request));
|
||||
ns_bzero(ret,sizeof(struct http_request));
|
||||
|
||||
if(strstr(request,"GET ") == request) {
|
||||
ret->rtype = HRT_GET;
|
||||
ret = parse_http_request_1(ret,request+4,0);
|
||||
} else if(strstr(request,"HEAD ") == request) {
|
||||
ret->rtype = HRT_HEAD;
|
||||
ret = parse_http_request_1(ret,request+5,0);
|
||||
} else if(strstr(request,"POST ") == request) {
|
||||
ret->rtype = HRT_POST;
|
||||
ret = parse_http_request_1(ret,request+5,1);
|
||||
} else if(strstr(request,"PUT ") == request) {
|
||||
ret->rtype = HRT_PUT;
|
||||
ret = parse_http_request_1(ret,request+4,1);
|
||||
} else if(strstr(request,"DELETE ") == request) {
|
||||
ret->rtype = HRT_DELETE;
|
||||
ret = parse_http_request_1(ret,request+7,1);
|
||||
} else {
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char * get_headers_list_value(struct headers_list *h, const char* key) {
|
||||
const char* ret = NULL;
|
||||
if(h && h->keys && h->values && key && key[0]) {
|
||||
size_t i = 0;
|
||||
for(i=0;i<h->n;++i) {
|
||||
if(h->keys[i] && !strcmp(key,h->keys[i]) && h->values[i]) {
|
||||
ret = h->values[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void free_headers_list(struct headers_list *h) {
|
||||
if(h) {
|
||||
if(h->keys) {
|
||||
size_t i = 0;
|
||||
for(i=0;i<h->n;++i) {
|
||||
if(h->keys[i]) {
|
||||
free(h->keys[i]);
|
||||
h->keys[i]=NULL;
|
||||
}
|
||||
}
|
||||
free(h->keys);
|
||||
h->keys = NULL;
|
||||
}
|
||||
if(h->values) {
|
||||
size_t i = 0;
|
||||
for(i=0;i<h->n;++i) {
|
||||
if(h->values[i]) {
|
||||
free(h->values[i]);
|
||||
h->values[i]=NULL;
|
||||
}
|
||||
}
|
||||
free(h->values);
|
||||
h->values = NULL;
|
||||
}
|
||||
h->n = 0;
|
||||
free(h);
|
||||
}
|
||||
}
|
||||
|
||||
const char *get_http_header_value(const struct http_request *request, const char* key, const char* default_value) {
|
||||
const char *ret = NULL;
|
||||
if(key && key[0] && request && request->headers) {
|
||||
if(request->headers->uri_headers) {
|
||||
ret = evhttp_find_header(request->headers->uri_headers,key);
|
||||
}
|
||||
if(!ret && request->headers->post_headers) {
|
||||
ret = get_headers_list_value(request->headers->post_headers,key);
|
||||
}
|
||||
}
|
||||
if(!ret) {
|
||||
ret = default_value;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void free_http_request(struct http_request *request) {
|
||||
if(request) {
|
||||
if(request->path) {
|
||||
free(request->path);
|
||||
request->path = NULL;
|
||||
}
|
||||
if(request->headers) {
|
||||
if(request->headers->uri_headers) {
|
||||
evhttp_clear_headers(request->headers->uri_headers);
|
||||
free(request->headers->uri_headers);
|
||||
request->headers->uri_headers = NULL;
|
||||
}
|
||||
if(request->headers->post_headers) {
|
||||
free_headers_list(request->headers->post_headers);
|
||||
request->headers->post_headers = NULL;
|
||||
}
|
||||
free(request->headers);
|
||||
request->headers = NULL;
|
||||
}
|
||||
free(request);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
||||
struct str_buffer {
|
||||
size_t capacity;
|
||||
size_t sz;
|
||||
char* buffer;
|
||||
};
|
||||
|
||||
struct str_buffer* str_buffer_new(void)
|
||||
{
|
||||
struct str_buffer* ret = (struct str_buffer*)malloc(sizeof(struct str_buffer));
|
||||
ns_bzero(ret,sizeof(struct str_buffer));
|
||||
ret->buffer = (char*)malloc(1);
|
||||
ret->buffer[0] = 0;
|
||||
ret->capacity = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void str_buffer_append(struct str_buffer* sb, const char* str)
|
||||
{
|
||||
if(sb && str && str[0]) {
|
||||
size_t len = strlen(str);
|
||||
while(sb->sz + len + 1 > sb->capacity) {
|
||||
sb->capacity += len + 1024;
|
||||
sb->buffer = (char*)realloc(sb->buffer,sb->capacity);
|
||||
}
|
||||
ns_bcopy(str,sb->buffer+sb->sz,len+1);
|
||||
sb->sz += len;
|
||||
}
|
||||
}
|
||||
|
||||
void str_buffer_append_sz(struct str_buffer* sb, size_t sz)
|
||||
{
|
||||
char ssz[129];
|
||||
snprintf(ssz,sizeof(ssz)-1,"%lu",(unsigned long)sz);
|
||||
str_buffer_append(sb,ssz);
|
||||
}
|
||||
|
||||
void str_buffer_append_sid(struct str_buffer* sb, turnsession_id sid)
|
||||
{
|
||||
char ssz[129];
|
||||
snprintf(ssz,sizeof(ssz)-1,"%018llu",(unsigned long long)sid);
|
||||
str_buffer_append(sb,ssz);
|
||||
}
|
||||
|
||||
const char* str_buffer_get_str(const struct str_buffer *sb)
|
||||
{
|
||||
if(sb) {
|
||||
return sb->buffer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t str_buffer_get_str_len(const struct str_buffer *sb)
|
||||
{
|
||||
if(sb) {
|
||||
return sb->sz;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void str_buffer_free(struct str_buffer *sb)
|
||||
{
|
||||
if(sb) {
|
||||
free(sb->buffer);
|
||||
free(sb);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2011, 2012, 2013, 2014 Citrix Systems
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __TURN_HTTP_SERVER__
|
||||
#define __TURN_HTTP_SERVER__
|
||||
|
||||
#include "ns_turn_utils.h"
|
||||
#include "ns_turn_server.h"
|
||||
#include "apputils.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
///////// HTTP REQUEST //////////
|
||||
|
||||
enum _HTTP_REQUEST_TYPE {
|
||||
HRT_UNKNOWN=0,
|
||||
HRT_GET,
|
||||
HRT_HEAD,
|
||||
HRT_POST,
|
||||
HRT_PUT,
|
||||
HRT_DELETE
|
||||
};
|
||||
|
||||
typedef enum _HTTP_REQUEST_TYPE HTTP_REQUEST_TYPE;
|
||||
|
||||
struct http_headers;
|
||||
|
||||
struct http_request {
|
||||
HTTP_REQUEST_TYPE rtype;
|
||||
char *path;
|
||||
struct http_headers *headers;
|
||||
};
|
||||
|
||||
struct http_request* parse_http_request(char* request);
|
||||
const char *get_http_header_value(const struct http_request *request, const char* key, const char* def);
|
||||
void free_http_request(struct http_request *request);
|
||||
|
||||
const char* get_http_date_header(void);
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
||||
struct str_buffer;
|
||||
|
||||
struct str_buffer* str_buffer_new(void);
|
||||
void str_buffer_append(struct str_buffer* sb, const char* str);
|
||||
void str_buffer_append_sz(struct str_buffer* sb, size_t sz);
|
||||
void str_buffer_append_sid(struct str_buffer* sb, turnsession_id sid);
|
||||
const char* str_buffer_get_str(const struct str_buffer *sb);
|
||||
size_t str_buffer_get_str_len(const struct str_buffer *sb);
|
||||
void str_buffer_free(struct str_buffer *sb);
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
||||
void handle_http_echo(ioa_socket_handle s);
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/// __TURN_HTTP_SERVER__///
|
||||
|
||||
+32
-59
@@ -33,7 +33,6 @@
|
||||
////// TEMPORARY data //////////
|
||||
|
||||
static int use_lt_credentials = 0;
|
||||
static int use_st_credentials = 0;
|
||||
static int anon_credentials = 0;
|
||||
|
||||
////// TURNDB //////////////
|
||||
@@ -81,7 +80,7 @@ NULL,
|
||||
|
||||
DH_1066, "", "", "",
|
||||
"turn_server_cert.pem","turn_server_pkey.pem", "", "",
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,
|
||||
#if !TLS_SUPPORTED
|
||||
1,
|
||||
#else
|
||||
@@ -120,7 +119,7 @@ LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,0,"",
|
||||
/////////////// MISC PARAMS ////////////////
|
||||
0,0,0,0,0,SHATYPE_SHA1,':',0,0,TURN_CREDENTIALS_NONE,0,0,0,0,0,0,
|
||||
///////////// Users DB //////////////
|
||||
{ (TURN_USERDB_TYPE)0, {"\0"}, {0,NULL,NULL, {NULL,0}} },
|
||||
{ (TURN_USERDB_TYPE)0, {"\0"}, {0,NULL, {NULL,0}} },
|
||||
///////////// CPUs //////////////////
|
||||
DEFAULT_CPUS_NUMBER
|
||||
};
|
||||
@@ -414,10 +413,9 @@ static char Usage[] = "Usage: turnserver [options]\n"
|
||||
" -o, --daemon Start process as daemon (detach from current shell).\n"
|
||||
" -f, --fingerprint Use fingerprints in the TURN messages.\n"
|
||||
" -a, --lt-cred-mech Use the long-term credential mechanism.\n"
|
||||
" -A, --st-cred-mech Use the short-term credential mechanism.\n"
|
||||
" -z, --no-auth Do not use any credential mechanism, allow anonymous access.\n"
|
||||
" -u, --user <user:pwd> User account, in form 'username:password', for long-term credentials.\n"
|
||||
" Cannot be used with TURN REST API or with short-term credentials.\n"
|
||||
" Cannot be used with TURN REST API.\n"
|
||||
" -r, --realm <realm> The default realm to be used for the users when no explicit\n"
|
||||
" origin/realm relationship was found in the database.\n"
|
||||
" Must be used with long-term credentials \n"
|
||||
@@ -445,7 +443,7 @@ static char Usage[] = "Usage: turnserver [options]\n"
|
||||
#endif
|
||||
#if !defined(TURN_NO_PQ)
|
||||
" -e, --psql-userdb, --sql-userdb <conn-string> PostgreSQL database connection string, if used (default - empty, no PostreSQL DB used).\n"
|
||||
" This database can be used for long-term and short-term credentials mechanisms,\n"
|
||||
" This database can be used for long-term credentials mechanism users,\n"
|
||||
" and it can store the secret value(s) for secret-based timed authentication in TURN RESP API.\n"
|
||||
" See http://www.postgresql.org/docs/8.4/static/libpq-connect.html for 8.x PostgreSQL\n"
|
||||
" versions format, see \n"
|
||||
@@ -454,7 +452,7 @@ static char Usage[] = "Usage: turnserver [options]\n"
|
||||
#endif
|
||||
#if !defined(TURN_NO_MYSQL)
|
||||
" -M, --mysql-userdb <connection-string> MySQL database connection string, if used (default - empty, no MySQL DB used).\n"
|
||||
" This database can be used for long-term and short-term credentials mechanisms,\n"
|
||||
" This database can be used for long-term credentials mechanism users,\n"
|
||||
" and it can store the secret value(s) for secret-based timed authentication in TURN RESP API.\n"
|
||||
" The connection string my be space-separated list of parameters:\n"
|
||||
" \"host=<ip-addr> dbname=<database-name> user=<database-user> \\\n password=<database-user-password> port=<db-port> connect_timeout=<seconds>\".\n\n"
|
||||
@@ -466,12 +464,12 @@ static char Usage[] = "Usage: turnserver [options]\n"
|
||||
#endif
|
||||
#if !defined(TURN_NO_MONGO)
|
||||
" -J, --mongo-userdb <connection-string> MongoDB connection string, if used (default - empty, no MongoDB used).\n"
|
||||
" This database can be used for long-term and short-term credentials mechanisms,\n"
|
||||
" This database can be used for long-term credentials mechanism users,\n"
|
||||
" and it can store the secret value(s) for secret-based timed authentication in TURN RESP API.\n"
|
||||
#endif
|
||||
#if !defined(TURN_NO_HIREDIS)
|
||||
" -N, --redis-userdb <connection-string> Redis user database connection string, if used (default - empty, no Redis DB used).\n"
|
||||
" This database can be used for long-term and short-term credentials mechanisms,\n"
|
||||
" This database can be used for long-term credentials mechanism users,\n"
|
||||
" and it can store the secret value(s) for secret-based timed authentication in TURN RESP API.\n"
|
||||
" The connection string my be space-separated list of parameters:\n"
|
||||
" \"host=<ip-addr> dbname=<db-number> \\\n password=<database-user-password> port=<db-port> connect_timeout=<seconds>\".\n\n"
|
||||
@@ -518,7 +516,6 @@ static char Usage[] = "Usage: turnserver [options]\n"
|
||||
" --dh2066 Use 2066 bits predefined DH TLS key. Default size of the predefined key is 1066.\n"
|
||||
" --dh-file <dh-file-name> Use custom DH TLS key, stored in PEM format in the file.\n"
|
||||
" Flags --dh566 and --dh2066 are ignored when the DH key is taken from a file.\n"
|
||||
" --no-sslv2 Do not allow SSLv2 protocol.\n"
|
||||
" --no-sslv3 Do not allow SSLv3 protocol.\n"
|
||||
" --no-tlsv1 Do not allow TLSv1/DTLSv1 protocol.\n"
|
||||
" --no-tlsv1_1 Do not allow TLSv1.1 protocol.\n"
|
||||
@@ -602,11 +599,11 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n"
|
||||
"\nCommands:\n\n"
|
||||
" -k, --key generate long-term credential mechanism key for a user\n"
|
||||
" -a, --add add/update a long-term mechanism user\n"
|
||||
" -A, --add-st add/update a short-term mechanism user\n"
|
||||
" -A, --add-admin add/update a web admin user\n"
|
||||
" -d, --delete delete a long-term mechanism user\n"
|
||||
" -D, --delete-st delete a short-term mechanism user\n"
|
||||
" -D, --delete-admin delete an admin user\n"
|
||||
" -l, --list list all long-term mechanism users\n"
|
||||
" -L, --list-st list all short-term mechanism users\n"
|
||||
" -L, --list-admin list all admin users\n"
|
||||
" -s, --set-secret=<value> Add shared secret for TURN RESP API\n"
|
||||
" -S, --show-secret Show stored shared secrets for TURN REST API\n"
|
||||
" -X, --delete-secret=<value> Delete a shared secret\n"
|
||||
@@ -634,7 +631,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n"
|
||||
" -N, --redis-userdb Redis user database connection string, if Redis DB is used.\n"
|
||||
#endif
|
||||
" -u, --user Username\n"
|
||||
" -r, --realm Realm for long-term mechanism only\n"
|
||||
" -r, --realm Realm\n"
|
||||
" -p, --password Password\n"
|
||||
#if !defined(TURN_NO_SQLITE) || !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS)
|
||||
" -o, --origin Origin\n"
|
||||
@@ -705,7 +702,7 @@ enum EXTRA_OPTS {
|
||||
DH566_OPT,
|
||||
DH2066_OPT,
|
||||
NE_TYPE_OPT,
|
||||
NO_SSLV2_OPT,
|
||||
NO_SSLV2_OPT, /*deprecated*/
|
||||
NO_SSLV3_OPT,
|
||||
NO_TLSV1_OPT,
|
||||
NO_TLSV1_1_OPT,
|
||||
@@ -747,7 +744,6 @@ static const struct myoption long_options[] = {
|
||||
{ "min-port", required_argument, NULL, MIN_PORT_OPT },
|
||||
{ "max-port", required_argument, NULL, MAX_PORT_OPT },
|
||||
{ "lt-cred-mech", optional_argument, NULL, 'a' },
|
||||
{ "st-cred-mech", optional_argument, NULL, 'A' },
|
||||
{ "no-auth", optional_argument, NULL, 'z' },
|
||||
{ "user", required_argument, NULL, 'u' },
|
||||
#if !defined(TURN_NO_SQLITE)
|
||||
@@ -828,7 +824,7 @@ static const struct myoption long_options[] = {
|
||||
{ "dh566", optional_argument, NULL, DH566_OPT },
|
||||
{ "dh2066", optional_argument, NULL, DH2066_OPT },
|
||||
{ "ne", required_argument, NULL, NE_TYPE_OPT },
|
||||
{ "no-sslv2", optional_argument, NULL, NO_SSLV2_OPT },
|
||||
{ "no-sslv2", optional_argument, NULL, NO_SSLV2_OPT }, /* deprecated */
|
||||
{ "no-sslv3", optional_argument, NULL, NO_SSLV3_OPT },
|
||||
{ "no-tlsv1", optional_argument, NULL, NO_TLSV1_OPT },
|
||||
{ "no-tlsv1_1", optional_argument, NULL, NO_TLSV1_1_OPT },
|
||||
@@ -841,13 +837,13 @@ static const struct myoption admin_long_options[] = {
|
||||
{ "add", no_argument, NULL, 'a' },
|
||||
{ "delete", no_argument, NULL, 'd' },
|
||||
{ "list", no_argument, NULL, 'l' },
|
||||
{ "list-st", no_argument, NULL, 'L' },
|
||||
{ "list-admin", no_argument, NULL, 'L' },
|
||||
{ "set-secret", required_argument, NULL, 's' },
|
||||
{ "show-secret", no_argument, NULL, 'S' },
|
||||
{ "delete-secret", required_argument, NULL, 'X' },
|
||||
{ "delete-all-secrets", no_argument, NULL, DEL_ALL_AUTH_SECRETS_OPT },
|
||||
{ "add-st", no_argument, NULL, 'A' },
|
||||
{ "delete-st", no_argument, NULL, 'D' },
|
||||
{ "add-admin", no_argument, NULL, 'A' },
|
||||
{ "delete-admin", no_argument, NULL, 'D' },
|
||||
#if !defined(TURN_NO_SQLITE)
|
||||
{ "userdb", required_argument, NULL, 'b' },
|
||||
{ "db", required_argument, NULL, 'b' },
|
||||
@@ -908,7 +904,7 @@ static void set_option(int c, char *value)
|
||||
turn_params.oauth = get_bool_value(value);
|
||||
break;
|
||||
case NO_SSLV2_OPT:
|
||||
turn_params.no_sslv2 = get_bool_value(value);
|
||||
//deprecated
|
||||
break;
|
||||
case NO_SSLV3_OPT:
|
||||
turn_params.no_sslv3 = get_bool_value(value);
|
||||
@@ -1120,15 +1116,6 @@ static void set_option(int c, char *value)
|
||||
use_lt_credentials=0;
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
if (get_bool_value(value)) {
|
||||
turn_params.ct = TURN_CREDENTIALS_SHORT_TERM;
|
||||
use_st_credentials=1;
|
||||
} else {
|
||||
turn_params.ct = TURN_CREDENTIALS_UNDEFINED;
|
||||
use_st_credentials=0;
|
||||
}
|
||||
break;
|
||||
case 'z':
|
||||
if (!get_bool_value(value)) {
|
||||
turn_params.ct = TURN_CREDENTIALS_UNDEFINED;
|
||||
@@ -1142,7 +1129,7 @@ static void set_option(int c, char *value)
|
||||
turn_params.fingerprint = get_bool_value(value);
|
||||
break;
|
||||
case 'u':
|
||||
add_user_account(value,0);
|
||||
add_static_user_account(value);
|
||||
break;
|
||||
#if !defined(TURN_NO_SQLITE)
|
||||
case 'b':
|
||||
@@ -1431,7 +1418,8 @@ static int adminmain(int argc, char **argv)
|
||||
int c = 0;
|
||||
|
||||
TURNADMIN_COMMAND_TYPE ct = TA_COMMAND_UNKNOWN;
|
||||
int is_st = 0;
|
||||
|
||||
int is_admin = 0;
|
||||
|
||||
u08bits user[STUN_MAX_USERNAME_SIZE+1]="";
|
||||
u08bits realm[STUN_MAX_REALM_SIZE+1]="";
|
||||
@@ -1483,18 +1471,18 @@ static int adminmain(int argc, char **argv)
|
||||
break;
|
||||
case 'A':
|
||||
ct = TA_UPDATE_USER;
|
||||
is_st = 1;
|
||||
is_admin = 1;
|
||||
break;
|
||||
case 'D':
|
||||
ct = TA_DELETE_USER;
|
||||
is_st = 1;
|
||||
is_admin = 1;
|
||||
break;
|
||||
case 'l':
|
||||
ct = TA_LIST_USERS;
|
||||
break;
|
||||
case 'L':
|
||||
ct = TA_LIST_USERS;
|
||||
is_st = 1;
|
||||
is_admin = 1;
|
||||
break;
|
||||
case 's':
|
||||
ct = TA_SET_SECRET;
|
||||
@@ -1597,7 +1585,7 @@ static int adminmain(int argc, char **argv)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
return adminuser(user, realm, pwd, secret, origin, ct, is_st, &po);
|
||||
return adminuser(user, realm, pwd, secret, origin, ct, &po, is_admin);
|
||||
}
|
||||
|
||||
static void print_features(unsigned long mfn)
|
||||
@@ -1816,7 +1804,6 @@ int main(int argc, char **argv)
|
||||
|
||||
ns_bzero(&turn_params.default_users_db,sizeof(default_users_db_t));
|
||||
turn_params.default_users_db.ram_db.static_accounts = ur_string_map_create(turn_free_simple);
|
||||
turn_params.default_users_db.ram_db.dynamic_accounts = ur_string_map_create(turn_free_simple);
|
||||
|
||||
if(strstr(argv[0],"turnadmin"))
|
||||
return adminmain(argc,argv);
|
||||
@@ -1896,17 +1883,7 @@ int main(int argc, char **argv)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if(use_st_credentials && anon_credentials) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nCONFIG ERROR: -A and -z options cannot be used together.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if(use_lt_credentials && use_st_credentials) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nCONFIG ERROR: -a and -A options cannot be used together.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if(!use_lt_credentials && !anon_credentials && !use_st_credentials) {
|
||||
if(!use_lt_credentials && !anon_credentials) {
|
||||
if(turn_params.default_users_db.ram_db.users_number) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "\nCONFIGURATION ALERT: you specified long-term user accounts, (-u option) \n but you did not specify the long-term credentials option\n (-a or --lt-cred-mech option).\n I am turning --lt-cred-mech ON for you, but double-check your configuration.\n");
|
||||
turn_params.ct = TURN_CREDENTIALS_LONG_TERM;
|
||||
@@ -1928,15 +1905,9 @@ int main(int argc, char **argv)
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "\nCONFIGURATION ALERT: you specified user accounts, (-u option) \n but you also specified the anonymous user access option (-z or --no-auth option).\n User accounts will be ignored.\n");
|
||||
turn_params.ct = TURN_CREDENTIALS_NONE;
|
||||
use_lt_credentials=0;
|
||||
use_st_credentials=0;
|
||||
}
|
||||
}
|
||||
|
||||
if(turn_params.use_auth_secret_with_timestamp && use_st_credentials) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nCONFIGURATION ERROR: Authentication secret (REST API) cannot be used with short-term credentials mechanism.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
openssl_setup();
|
||||
|
||||
int local_listeners = 0;
|
||||
@@ -2532,9 +2503,9 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol)
|
||||
int op = 0;
|
||||
|
||||
#if defined(SSL_OP_NO_SSLv2)
|
||||
if(turn_params.no_sslv2)
|
||||
op |= SSL_OP_NO_SSLv2;
|
||||
op |= SSL_OP_NO_SSLv2;
|
||||
#endif
|
||||
|
||||
if(turn_params.no_sslv3)
|
||||
op |= SSL_OP_NO_SSLv3;
|
||||
|
||||
@@ -2635,15 +2606,17 @@ static void openssl_setup(void)
|
||||
if(OPENSSL_VERSION_NUMBER < 0x10000000L) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: TURN Server was compiled with rather old OpenSSL version, DTLS may not be working correctly.\n");
|
||||
}
|
||||
turn_params.dtls_ctx = SSL_CTX_new(DTLSv1_server_method());
|
||||
set_ctx(turn_params.dtls_ctx,"DTLS");
|
||||
SSL_CTX_set_read_ahead(turn_params.dtls_ctx, 1);
|
||||
|
||||
#if DTLSv1_2_SUPPORTED
|
||||
turn_params.dtls_ctx = SSL_CTX_new(DTLS_server_method());
|
||||
turn_params.dtls_ctx_v1_2 = SSL_CTX_new(DTLSv1_2_server_method());
|
||||
set_ctx(turn_params.dtls_ctx_v1_2,"DTLS1,2");
|
||||
SSL_CTX_set_read_ahead(turn_params.dtls_ctx_v1_2, 1);
|
||||
#else
|
||||
turn_params.dtls_ctx = SSL_CTX_new(DTLSv1_server_method());
|
||||
#endif
|
||||
set_ctx(turn_params.dtls_ctx,"DTLS");
|
||||
SSL_CTX_set_read_ahead(turn_params.dtls_ctx, 1);
|
||||
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS cipher suite: %s\n",turn_params.cipher_list);
|
||||
|
||||
|
||||
@@ -65,12 +65,14 @@
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include "ns_turn_utils.h"
|
||||
#include "ns_turn_khash.h"
|
||||
|
||||
#include "userdb.h"
|
||||
#include "turncli.h"
|
||||
#include "turn_admin_server.h"
|
||||
|
||||
#include "tls_listener.h"
|
||||
#include "dtls_listener.h"
|
||||
@@ -197,7 +199,6 @@ typedef struct _turn_params_ {
|
||||
char tls_password[513];
|
||||
char dh_file[1025];
|
||||
|
||||
int no_sslv2;
|
||||
int no_sslv3;
|
||||
int no_tlsv1;
|
||||
int no_tlsv1_1;
|
||||
|
||||
+23
-30
@@ -402,17 +402,7 @@ static void auth_server_receive_message(struct bufferevent *bev, void *ptr)
|
||||
continue;
|
||||
}
|
||||
|
||||
if(am.ct == TURN_CREDENTIALS_SHORT_TERM) {
|
||||
st_password_t pwd;
|
||||
am.in_oauth = 0;
|
||||
am.out_oauth = 0;
|
||||
if(get_user_pwd(am.username,pwd)<0) {
|
||||
am.success = 0;
|
||||
} else {
|
||||
ns_bcopy(pwd,am.pwd,sizeof(st_password_t));
|
||||
am.success = 1;
|
||||
}
|
||||
} else {
|
||||
{
|
||||
hmackey_t key;
|
||||
if(get_user_key(am.in_oauth,&(am.out_oauth),&(am.max_session_time),am.username,am.realm,key,am.in_buffer.nbh)<0) {
|
||||
am.success = 0;
|
||||
@@ -752,7 +742,10 @@ static int handle_relay_message(relay_server_handle rs, struct message_to_relay
|
||||
sm->m.sm.s = NULL;
|
||||
} else {
|
||||
s->e = rs->ioa_eng;
|
||||
open_client_connection_session(&(rs->server), &(sm->m.sm));
|
||||
if(open_client_connection_session(&(rs->server), &(sm->m.sm))<0) {
|
||||
IOA_CLOSE_SOCKET(s);
|
||||
sm->m.sm.s = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ioa_network_buffer_delete(rs->ioa_eng, sm->m.sm.nd.nbh);
|
||||
@@ -790,7 +783,10 @@ static int handle_relay_message(relay_server_handle rs, struct message_to_relay
|
||||
sm->m.sm.s = NULL;
|
||||
} else {
|
||||
s->e = rs->ioa_eng;
|
||||
open_client_connection_session(&(rs->server), &(sm->m.sm));
|
||||
if(open_client_connection_session(&(rs->server), &(sm->m.sm))<0) {
|
||||
IOA_CLOSE_SOCKET(s);
|
||||
sm->m.sm.s = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ioa_network_buffer_delete(rs->ioa_eng, sm->m.sm.nd.nbh);
|
||||
@@ -1649,6 +1645,7 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int
|
||||
&turn_params.secure_stun, turn_params.shatype, &turn_params.mobility,
|
||||
turn_params.server_relay,
|
||||
send_turn_session_info,
|
||||
send_https_socket,
|
||||
allocate_bps,
|
||||
turn_params.oauth, turn_params.oauth_server_name);
|
||||
|
||||
@@ -1776,33 +1773,33 @@ static void setup_auth_server(struct auth_server *as)
|
||||
pthread_detach(as->thr);
|
||||
}
|
||||
|
||||
static void* run_cli_server_thread(void *arg)
|
||||
static void* run_admin_server_thread(void *arg)
|
||||
{
|
||||
ignore_sigpipe();
|
||||
|
||||
setup_cli_thread();
|
||||
setup_admin_thread();
|
||||
|
||||
barrier_wait();
|
||||
|
||||
while(cliserver.event_base) {
|
||||
run_events(cliserver.event_base,NULL);
|
||||
while(adminserver.event_base) {
|
||||
run_events(adminserver.event_base,NULL);
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
static void setup_cli_server(void)
|
||||
static void setup_admin_server(void)
|
||||
{
|
||||
ns_bzero(&cliserver,sizeof(struct cli_server));
|
||||
cliserver.listen_fd = -1;
|
||||
cliserver.verbose = turn_params.verbose;
|
||||
ns_bzero(&adminserver,sizeof(struct admin_server));
|
||||
adminserver.listen_fd = -1;
|
||||
adminserver.verbose = turn_params.verbose;
|
||||
|
||||
if(pthread_create(&(cliserver.thr), NULL, run_cli_server_thread, &cliserver)<0) {
|
||||
if(pthread_create(&(adminserver.thr), NULL, run_admin_server_thread, &adminserver)<0) {
|
||||
perror("Cannot create cli thread\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
pthread_detach(cliserver.thr);
|
||||
pthread_detach(adminserver.thr);
|
||||
}
|
||||
|
||||
void setup_server(void)
|
||||
@@ -1818,12 +1815,9 @@ void setup_server(void)
|
||||
#if !defined(TURN_NO_THREAD_BARRIERS)
|
||||
|
||||
/* relay threads plus auth threads plus main listener thread */
|
||||
/* plus admin thread */
|
||||
/* udp address listener thread(s) will start later */
|
||||
barrier_count = turn_params.general_relay_servers_number+authserver_number+1;
|
||||
|
||||
if(use_cli) {
|
||||
barrier_count += 1;
|
||||
}
|
||||
barrier_count = turn_params.general_relay_servers_number+authserver_number+1+1;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1870,8 +1864,7 @@ void setup_server(void)
|
||||
}
|
||||
}
|
||||
|
||||
if(use_cli)
|
||||
setup_cli_server();
|
||||
setup_admin_server();
|
||||
|
||||
barrier_wait();
|
||||
}
|
||||
|
||||
@@ -1633,6 +1633,7 @@ void detach_socket_net_data(ioa_socket_handle s)
|
||||
void close_ioa_socket(ioa_socket_handle s)
|
||||
{
|
||||
if (s) {
|
||||
|
||||
if(s->magic != SOCKET_MAGIC) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s wrong magic on socket: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)s, s->st, s->sat);
|
||||
return;
|
||||
@@ -1658,6 +1659,12 @@ void close_ioa_socket(ioa_socket_handle s)
|
||||
&(s->local_addr));
|
||||
}
|
||||
|
||||
if(s->special_session) {
|
||||
turn_free(s->special_session,s->special_session_size);
|
||||
s->special_session = NULL;
|
||||
}
|
||||
s->special_session_size = 0;
|
||||
|
||||
delete_socket_from_map(s);
|
||||
delete_socket_from_parent(s);
|
||||
|
||||
@@ -2263,13 +2270,11 @@ static TURN_TLS_TYPE check_tentative_tls(ioa_socket_raw fd)
|
||||
if((s[0]==22)&&(s[1]==3)&&(s[5]==1)&&(s[9]==3)) {
|
||||
char max_supported = (char)(TURN_TLS_TOTAL-2);
|
||||
if(s[10] >= max_supported)
|
||||
ret = (TURN_TLS_TYPE)((((int)TURN_TLS_TOTAL)-1));
|
||||
ret = TURN_TLS_SSL23; /* compatibility mode */
|
||||
else
|
||||
ret = (TURN_TLS_TYPE)(s[10]+1);
|
||||
} else if((s[2]==1)&&(s[3]==3)) {
|
||||
ret = TURN_TLS_SSL23; /* compatibility mode */
|
||||
} else if((s[2]==1)&&(s[3]==0)&&(s[4]==2)) {
|
||||
ret = TURN_TLS_SSL23; /* old mode */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2403,11 +2408,11 @@ static int socket_input_worker(ioa_socket_handle s)
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!!%s on socket: 0x%lx, st=%d, sat=%d: bev already exist\n", __FUNCTION__,(long)s, s->st, s->sat);
|
||||
}
|
||||
s->bev = bufferevent_socket_new(s->e->event_base,
|
||||
s->fd,
|
||||
TURN_BUFFEREVENTS_OPTIONS);
|
||||
s->fd,
|
||||
TURN_BUFFEREVENTS_OPTIONS);
|
||||
debug_ptr_add(s->bev);
|
||||
bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev,
|
||||
eventcb_bev, s);
|
||||
eventcb_bev, s);
|
||||
bufferevent_setwatermark(s->bev, EV_READ|EV_WRITE, 0, BUFFEREVENT_HIGH_WATERMARK);
|
||||
bufferevent_enable(s->bev, EV_READ|EV_WRITE); /* Start reading. */
|
||||
}
|
||||
@@ -2599,6 +2604,19 @@ static void socket_input_handler(evutil_socket_t fd, short what, void* arg)
|
||||
void close_ioa_socket_after_processing_if_necessary(ioa_socket_handle s)
|
||||
{
|
||||
if (s && ioa_socket_tobeclosed(s)) {
|
||||
|
||||
if(s->special_session) {
|
||||
turn_free(s->special_session,s->special_session_size);
|
||||
s->special_session = NULL;
|
||||
}
|
||||
s->special_session_size = 0;
|
||||
|
||||
if(!(s->session) && !(s->sub_session)) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s https server socket closed: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)s, get_ioa_socket_type(s), get_ioa_socket_app_type(s));
|
||||
IOA_CLOSE_SOCKET(s);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (s->sat){
|
||||
case TCP_CLIENT_DATA_SOCKET:
|
||||
case TCP_RELAY_DATA_SOCKET:
|
||||
@@ -2606,6 +2624,7 @@ void close_ioa_socket_after_processing_if_necessary(ioa_socket_handle s)
|
||||
tcp_connection *tc = s->sub_session;
|
||||
if (tc) {
|
||||
delete_tcp_connection(tc);
|
||||
s->sub_session = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2772,6 +2791,20 @@ static void eventcb_bev(struct bufferevent *bev, short events, void *arg)
|
||||
|
||||
s->tobeclosed = 1;
|
||||
|
||||
if(s->special_session) {
|
||||
turn_free(s->special_session,s->special_session_size);
|
||||
s->special_session = NULL;
|
||||
}
|
||||
s->special_session_size = 0;
|
||||
|
||||
if(!(s->session) && !(s->sub_session)) {
|
||||
char sraddr[129]="\0";
|
||||
addr_to_string(&(s->remote_addr),(u08bits*)sraddr);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s https server socket closed: 0x%lx, st=%d, sat=%d, remote addr=%s\n", __FUNCTION__,(long)s, get_ioa_socket_type(s), get_ioa_socket_app_type(s),sraddr);
|
||||
IOA_CLOSE_SOCKET(s);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (s->sat){
|
||||
case TCP_CLIENT_DATA_SOCKET:
|
||||
case TCP_RELAY_DATA_SOCKET:
|
||||
@@ -2779,6 +2812,7 @@ static void eventcb_bev(struct bufferevent *bev, short events, void *arg)
|
||||
tcp_connection *tc = s->sub_session;
|
||||
if (tc) {
|
||||
delete_tcp_connection(tc);
|
||||
s->sub_session = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -3176,6 +3210,68 @@ int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int send_data_from_ioa_socket_tcp(ioa_socket_handle s, const void *data, size_t sz)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if(s && data) {
|
||||
|
||||
if (s->done || (s->fd == -1) || ioa_socket_tobeclosed(s) || !(s->e)) {
|
||||
TURN_LOG_FUNC(
|
||||
TURN_LOG_LEVEL_INFO,
|
||||
"!!! %s: (1) Trying to send data from bad socket: 0x%lx (1): done=%d, fd=%d, st=%d, sat=%d\n",
|
||||
__FUNCTION__, (long) s, (int) s->done,
|
||||
(int) s->fd, s->st, s->sat);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s);
|
||||
|
||||
} else if (s->connected && s->bev) {
|
||||
if (s->st == TLS_SOCKET) {
|
||||
#if TLS_SUPPORTED
|
||||
SSL *ctx = bufferevent_openssl_get_ssl(s->bev);
|
||||
if (!ctx || SSL_get_shutdown(ctx)) {
|
||||
s->tobeclosed = 1;
|
||||
ret = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!(s->tobeclosed)) {
|
||||
|
||||
ret = (int)sz;
|
||||
|
||||
s->in_write = 1;
|
||||
if (bufferevent_write(s->bev, data, sz) < 0) {
|
||||
ret = -1;
|
||||
perror("bufev send");
|
||||
log_socket_event(s, "socket write failed, to be closed", 1);
|
||||
s->tobeclosed = 1;
|
||||
s->broken = 1;
|
||||
}
|
||||
s->in_write = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int send_str_from_ioa_socket_tcp(ioa_socket_handle s, const void *data)
|
||||
{
|
||||
if(data) {
|
||||
return send_data_from_ioa_socket_tcp(s, data, strlen((const char*)data));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int send_ulong_from_ioa_socket_tcp(ioa_socket_handle s, size_t data)
|
||||
{
|
||||
char str[129];
|
||||
snprintf(str,sizeof(str)-1,"%lu",(unsigned long)data);
|
||||
|
||||
return send_str_from_ioa_socket_tcp(s,str);
|
||||
}
|
||||
|
||||
int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, int event_type, ioa_net_event_handler cb, void* ctx, int clean_preexisting)
|
||||
{
|
||||
if(s) {
|
||||
@@ -3227,14 +3323,19 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
s->bev = bufferevent_socket_new(s->e->event_base,
|
||||
if(check_tentative_tls(s->fd)) {
|
||||
s->tobeclosed = 1;
|
||||
return -1;
|
||||
} else {
|
||||
s->bev = bufferevent_socket_new(s->e->event_base,
|
||||
s->fd,
|
||||
TURN_BUFFEREVENTS_OPTIONS);
|
||||
debug_ptr_add(s->bev);
|
||||
bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev,
|
||||
eventcb_bev, s);
|
||||
bufferevent_setwatermark(s->bev, EV_READ|EV_WRITE, 0, BUFFEREVENT_HIGH_WATERMARK);
|
||||
bufferevent_enable(s->bev, EV_READ|EV_WRITE); /* Start reading. */
|
||||
debug_ptr_add(s->bev);
|
||||
bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev,
|
||||
eventcb_bev, s);
|
||||
bufferevent_setwatermark(s->bev, EV_READ|EV_WRITE, 0, BUFFEREVENT_HIGH_WATERMARK);
|
||||
bufferevent_enable(s->bev, EV_READ|EV_WRITE); /* Start reading. */
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TLS_SOCKET:
|
||||
|
||||
@@ -223,6 +223,8 @@ struct _ioa_socket
|
||||
accept_cb acb;
|
||||
void *acbarg;
|
||||
/* <<== RFC 6062 */
|
||||
void *special_session;
|
||||
size_t special_session_size;
|
||||
};
|
||||
|
||||
typedef struct _timer_event
|
||||
@@ -297,6 +299,10 @@ int set_socket_options(ioa_socket_handle s);
|
||||
|
||||
int send_session_cancellation_to_relay(turnsession_id sid);
|
||||
|
||||
int send_data_from_ioa_socket_tcp(ioa_socket_handle s, const void *data, size_t sz);
|
||||
int send_str_from_ioa_socket_tcp(ioa_socket_handle s, const void *data);
|
||||
int send_ulong_from_ioa_socket_tcp(ioa_socket_handle s, size_t data);
|
||||
|
||||
///////////////////////// SUPER MEMORY ////////
|
||||
|
||||
#define allocate_super_memory_engine(e,size) allocate_super_memory_engine_func(e, size, __FILE__, __FUNCTION__, __LINE__)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -28,8 +28,8 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __TURNCLI__
|
||||
#define __TURNCLI__
|
||||
#ifndef __TURN_ADMIN_SERVER__
|
||||
#define __TURN_ADMIN_SERVER__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -51,20 +51,33 @@ extern "C" {
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
||||
struct cli_server {
|
||||
#define ADMIN_USER_MAX_LENGTH (32)
|
||||
|
||||
struct admin_session {
|
||||
int as_ok;
|
||||
char as_login[ADMIN_USER_MAX_LENGTH + 1];
|
||||
char as_realm[STUN_MAX_REALM_SIZE + 1];
|
||||
char as_eff_realm[STUN_MAX_REALM_SIZE + 1];
|
||||
size_t number_of_user_sessions;
|
||||
};
|
||||
|
||||
struct admin_server {
|
||||
evutil_socket_t listen_fd;
|
||||
struct event_base* event_base;
|
||||
ioa_engine_handle e;
|
||||
int verbose;
|
||||
struct evconnlistener *l;
|
||||
struct bufferevent *in_buf;
|
||||
struct bufferevent *out_buf;
|
||||
struct bufferevent *https_in_buf;
|
||||
struct bufferevent *https_out_buf;
|
||||
ur_map *sessions;
|
||||
pthread_t thr;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////
|
||||
|
||||
extern struct cli_server cliserver;
|
||||
extern struct admin_server adminserver;
|
||||
|
||||
extern int use_cli;
|
||||
|
||||
@@ -83,11 +96,13 @@ extern int cli_max_output_sessions;
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
||||
void setup_cli_thread(void);
|
||||
void setup_admin_thread(void);
|
||||
|
||||
void cli_server_receive_message(struct bufferevent *bev, void *ptr);
|
||||
void admin_server_receive_message(struct bufferevent *bev, void *ptr);
|
||||
void https_admin_server_receive_message(struct bufferevent *bev, void *ptr);
|
||||
|
||||
int send_turn_session_info(struct turn_session_info* tsi);
|
||||
void send_https_socket(ioa_socket_handle s);
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
||||
@@ -96,5 +111,5 @@ int send_turn_session_info(struct turn_session_info* tsi);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/// __TURNCLI__///
|
||||
/// __TURN_ADMIN_SERVER__///
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+100
-76
@@ -405,7 +405,7 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u
|
||||
if(max_session_time)
|
||||
*max_session_time = 0;
|
||||
|
||||
if(in_oauth && out_oauth && usname && usname[0] && realm && realm[0]) {
|
||||
if(in_oauth && out_oauth && usname && usname[0]) {
|
||||
|
||||
stun_attr_ref sar = stun_attr_get_first_by_type_str(ioa_network_buffer_data(nbh),
|
||||
ioa_network_buffer_get_size(nbh),
|
||||
@@ -471,6 +471,10 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u
|
||||
const char* server_name = (char*)turn_params.oauth_server_name;
|
||||
if(!(server_name && server_name[0])) {
|
||||
server_name = (char*)realm;
|
||||
if(!(server_name && server_name[0])) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot determine oAuth server name");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (decode_oauth_token((const u08bits *) server_name, &etoken,&okey, &dot) < 0) {
|
||||
@@ -496,7 +500,7 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u
|
||||
return -1;
|
||||
};
|
||||
|
||||
st_password_t pwdtmp;
|
||||
password_t pwdtmp;
|
||||
if(stun_check_message_integrity_by_key_str(TURN_CREDENTIALS_LONG_TERM,
|
||||
ioa_network_buffer_data(nbh),
|
||||
ioa_network_buffer_get_size(nbh),
|
||||
@@ -549,7 +553,7 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u
|
||||
|
||||
u08bits hmac[MAXSHASIZE];
|
||||
unsigned int hmac_len;
|
||||
st_password_t pwdtmp;
|
||||
password_t pwdtmp;
|
||||
|
||||
hmac[0] = 0;
|
||||
|
||||
@@ -620,12 +624,6 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u
|
||||
ur_string_map_lock(turn_params.default_users_db.ram_db.static_accounts);
|
||||
if(ur_string_map_get(turn_params.default_users_db.ram_db.static_accounts, (ur_string_map_key_type)usname, &ukey)) {
|
||||
ret = 0;
|
||||
} else {
|
||||
ur_string_map_lock(turn_params.default_users_db.ram_db.dynamic_accounts);
|
||||
if(ur_string_map_get(turn_params.default_users_db.ram_db.dynamic_accounts, (ur_string_map_key_type)usname, &ukey)) {
|
||||
ret = 0;
|
||||
}
|
||||
ur_string_map_unlock(turn_params.default_users_db.ram_db.dynamic_accounts);
|
||||
}
|
||||
ur_string_map_unlock(turn_params.default_users_db.ram_db.static_accounts);
|
||||
|
||||
@@ -643,21 +641,6 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Short-term mechanism password retrieval
|
||||
*/
|
||||
int get_user_pwd(u08bits *usname, st_password_t pwd)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
const turn_dbdriver_t * dbd = get_dbdriver();
|
||||
if (dbd && dbd->get_user_pwd) {
|
||||
ret = (*dbd->get_user_pwd)(usname, pwd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u08bits *start_user_check(turnserver_id id, turn_credential_type ct, int in_oauth, int *out_oauth, u08bits *usname, u08bits *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, u64bits ctxkey, int *postpone_reply)
|
||||
{
|
||||
*postpone_reply = 1;
|
||||
@@ -736,7 +719,7 @@ void release_allocation_quota(u08bits *user, int oauth, u08bits *realm)
|
||||
|
||||
//////////////////////////////////
|
||||
|
||||
int add_user_account(char *user, int dynamic)
|
||||
int add_static_user_account(char *user)
|
||||
{
|
||||
/* Realm is either default or empty for users taken from file or command-line */
|
||||
if(user && !turn_params.use_auth_secret_with_timestamp) {
|
||||
@@ -770,11 +753,7 @@ int add_user_account(char *user, int dynamic)
|
||||
//this is only for default realm
|
||||
stun_produce_integrity_key_str((u08bits*)usname, (u08bits*)get_realm(NULL)->options.name, (u08bits*)s, *key, turn_params.shatype);
|
||||
}
|
||||
if(dynamic) {
|
||||
ur_string_map_lock(turn_params.default_users_db.ram_db.dynamic_accounts);
|
||||
ur_string_map_put(turn_params.default_users_db.ram_db.dynamic_accounts, (ur_string_map_key_type)usname, (ur_string_map_value_type)*key);
|
||||
ur_string_map_unlock(turn_params.default_users_db.ram_db.dynamic_accounts);
|
||||
} else {
|
||||
{
|
||||
ur_string_map_lock(turn_params.default_users_db.ram_db.static_accounts);
|
||||
ur_string_map_put(turn_params.default_users_db.ram_db.static_accounts, (ur_string_map_key_type)usname, (ur_string_map_value_type)*key);
|
||||
ur_string_map_unlock(turn_params.default_users_db.ram_db.static_accounts);
|
||||
@@ -790,11 +769,19 @@ int add_user_account(char *user, int dynamic)
|
||||
|
||||
////////////////// Admin /////////////////////////
|
||||
|
||||
static int list_users(int is_st, u08bits *realm)
|
||||
static int list_users(u08bits *realm, int is_admin)
|
||||
{
|
||||
const turn_dbdriver_t * dbd = get_dbdriver();
|
||||
if (dbd && dbd->list_users) {
|
||||
(*dbd->list_users)(is_st, realm);
|
||||
if (dbd) {
|
||||
if(is_admin) {
|
||||
if(dbd->list_admin_users) {
|
||||
(*dbd->list_admin_users)(0);
|
||||
}
|
||||
} else {
|
||||
if(dbd->list_users) {
|
||||
(*dbd->list_users)(realm,NULL,NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -802,26 +789,24 @@ static int list_users(int is_st, u08bits *realm)
|
||||
|
||||
static int show_secret(u08bits *realm)
|
||||
{
|
||||
must_set_admin_realm(realm);
|
||||
|
||||
const turn_dbdriver_t * dbd = get_dbdriver();
|
||||
if (dbd && dbd->show_secret) {
|
||||
(*dbd->show_secret)(realm);
|
||||
}
|
||||
if (dbd && dbd->list_secrets) {
|
||||
(*dbd->list_secrets)(realm,NULL,NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int del_secret(u08bits *secret, u08bits *realm) {
|
||||
|
||||
must_set_admin_realm(realm);
|
||||
|
||||
const turn_dbdriver_t * dbd = get_dbdriver();
|
||||
if (dbd && dbd->del_secret) {
|
||||
(*dbd->del_secret)(secret, realm);
|
||||
const turn_dbdriver_t * dbd = get_dbdriver();
|
||||
if (dbd && dbd->del_secret) {
|
||||
(*dbd->del_secret)(secret, realm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_secret(u08bits *secret, u08bits *realm) {
|
||||
@@ -833,9 +818,9 @@ static int set_secret(u08bits *secret, u08bits *realm) {
|
||||
|
||||
del_secret(secret, realm);
|
||||
|
||||
const turn_dbdriver_t * dbd = get_dbdriver();
|
||||
if (dbd && dbd->set_secret) {
|
||||
(*dbd->set_secret)(secret, realm);
|
||||
const turn_dbdriver_t * dbd = get_dbdriver();
|
||||
if (dbd && dbd->set_secret) {
|
||||
(*dbd->set_secret)(secret, realm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -847,9 +832,9 @@ static int add_origin(u08bits *origin0, u08bits *realm)
|
||||
|
||||
get_canonic_origin((const char *)origin0, (char *)origin, sizeof(origin)-1);
|
||||
|
||||
const turn_dbdriver_t * dbd = get_dbdriver();
|
||||
if (dbd && dbd->add_origin) {
|
||||
(*dbd->add_origin)(origin, realm);
|
||||
const turn_dbdriver_t * dbd = get_dbdriver();
|
||||
if (dbd && dbd->add_origin) {
|
||||
(*dbd->add_origin)(origin, realm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -861,9 +846,9 @@ static int del_origin(u08bits *origin0)
|
||||
|
||||
get_canonic_origin((const char *)origin0, (char *)origin, sizeof(origin)-1);
|
||||
|
||||
const turn_dbdriver_t * dbd = get_dbdriver();
|
||||
if (dbd && dbd->del_origin) {
|
||||
(*dbd->del_origin)(origin);
|
||||
const turn_dbdriver_t * dbd = get_dbdriver();
|
||||
if (dbd && dbd->del_origin) {
|
||||
(*dbd->del_origin)(origin);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -873,10 +858,10 @@ static int list_origins(u08bits *realm)
|
||||
{
|
||||
const turn_dbdriver_t * dbd = get_dbdriver();
|
||||
if (dbd && dbd->list_origins) {
|
||||
(*dbd->list_origins)(realm);
|
||||
}
|
||||
(*dbd->list_origins)(realm,NULL,NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_realm_option_one(u08bits *realm, unsigned long value, const char* opt)
|
||||
@@ -884,9 +869,9 @@ static int set_realm_option_one(u08bits *realm, unsigned long value, const char*
|
||||
if(value == (unsigned long)-1)
|
||||
return 0;
|
||||
|
||||
const turn_dbdriver_t * dbd = get_dbdriver();
|
||||
if (dbd && dbd->set_realm_option_one) {
|
||||
(*dbd->set_realm_option_one)(realm, value, opt);
|
||||
const turn_dbdriver_t * dbd = get_dbdriver();
|
||||
if (dbd && dbd->set_realm_option_one) {
|
||||
(*dbd->set_realm_option_one)(realm, value, opt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -910,15 +895,13 @@ static int list_realm_options(u08bits *realm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08bits *origin, TURNADMIN_COMMAND_TYPE ct, int is_st, perf_options_t *po)
|
||||
int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08bits *origin, TURNADMIN_COMMAND_TYPE ct, perf_options_t *po, int is_admin)
|
||||
{
|
||||
hmackey_t key;
|
||||
char skey[sizeof(hmackey_t) * 2 + 1];
|
||||
|
||||
st_password_t passwd;
|
||||
|
||||
if (ct == TA_LIST_USERS) {
|
||||
return list_users(is_st, realm);
|
||||
return list_users(realm, is_admin);
|
||||
}
|
||||
|
||||
if (ct == TA_LIST_ORIGINS) {
|
||||
@@ -963,13 +946,11 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b
|
||||
|
||||
must_set_admin_user(user);
|
||||
|
||||
if (ct != TA_DELETE_USER) {
|
||||
if (ct != TA_DELETE_USER && !is_admin) {
|
||||
|
||||
must_set_admin_pwd(pwd);
|
||||
|
||||
if (is_st) {
|
||||
strncpy((char*) passwd, (char*) pwd, sizeof(st_password_t));
|
||||
} else {
|
||||
{
|
||||
stun_produce_integrity_key_str(user, realm, pwd, key, turn_params.shatype);
|
||||
size_t i = 0;
|
||||
size_t sz = get_hmackey_size(turn_params.shatype);
|
||||
@@ -988,23 +969,29 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b
|
||||
|
||||
if (ct == TA_PRINT_KEY) {
|
||||
|
||||
if (!is_st) {
|
||||
printf("0x%s\n", skey);
|
||||
}
|
||||
printf("0x%s\n", skey);
|
||||
|
||||
} else if (dbd) {
|
||||
|
||||
if (!is_st) {
|
||||
if(!is_admin)
|
||||
must_set_admin_realm(realm);
|
||||
}
|
||||
|
||||
if (ct == TA_DELETE_USER) {
|
||||
if (dbd->del_user)
|
||||
(*dbd->del_user)(user, is_st, realm);
|
||||
if(is_admin) {
|
||||
if (dbd->del_admin_user)
|
||||
(*dbd->del_admin_user)(user);
|
||||
} else {
|
||||
if (dbd->del_user)
|
||||
(*dbd->del_user)(user, realm);
|
||||
}
|
||||
} else if (ct == TA_UPDATE_USER) {
|
||||
if (is_st) {
|
||||
if (dbd->set_user_pwd)
|
||||
(*dbd->set_user_pwd)(user, passwd);
|
||||
if(is_admin) {
|
||||
must_set_admin_pwd(pwd);
|
||||
if (dbd->set_admin_user) {
|
||||
password_t password;
|
||||
STRCPY(password,pwd);
|
||||
(*dbd->set_admin_user)(user, realm, password);
|
||||
}
|
||||
} else {
|
||||
if (dbd->set_user_key)
|
||||
(*dbd->set_user_key)(user, realm, skey);
|
||||
@@ -1279,6 +1266,43 @@ int add_ip_list_range(const char * range0, const char * realm, ip_range_list_t *
|
||||
return 0;
|
||||
}
|
||||
|
||||
int check_ip_list_range(const char * range0)
|
||||
{
|
||||
char *range = turn_strdup(range0);
|
||||
|
||||
char* separator = strchr(range, '-');
|
||||
|
||||
if (separator) {
|
||||
*separator = '\0';
|
||||
}
|
||||
|
||||
ioa_addr min, max;
|
||||
|
||||
if (make_ioa_addr((const u08bits*) range, 0, &min) < 0) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong address range format: %s\n", range);
|
||||
turn_free(range,0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (separator) {
|
||||
if (make_ioa_addr((const u08bits*) separator + 1, 0, &max) < 0) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong address range format: %s\n", separator + 1);
|
||||
turn_free(range,0);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
// Doesn't have a '-' character in it, so assume that this is a single address
|
||||
addr_cpy(&max, &min);
|
||||
}
|
||||
|
||||
if (separator)
|
||||
*separator = '-';
|
||||
|
||||
turn_free(range,0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////// REALM //////////////
|
||||
|
||||
void reread_realms(void)
|
||||
|
||||
@@ -46,10 +46,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//////////// Defines //////////////////////////////
|
||||
|
||||
#define AUTH_SECRET_SIZE (512)
|
||||
|
||||
//////////// REALM //////////////
|
||||
|
||||
struct _realm_status_t;
|
||||
@@ -90,7 +86,7 @@ struct auth_message {
|
||||
u08bits username[STUN_MAX_USERNAME_SIZE + 1];
|
||||
u08bits realm[STUN_MAX_REALM_SIZE + 1];
|
||||
hmackey_t key;
|
||||
st_password_t pwd;
|
||||
password_t pwd;
|
||||
get_username_resume_cb resume_func;
|
||||
ioa_net_data in_buffer;
|
||||
u64bits ctxkey;
|
||||
@@ -153,7 +149,6 @@ typedef struct _secrets_list secrets_list_t;
|
||||
typedef struct _ram_users_db_t {
|
||||
size_t users_number;
|
||||
ur_string_map *static_accounts;
|
||||
ur_string_map *dynamic_accounts;
|
||||
secrets_list_t static_auth_secrets;
|
||||
} ram_users_db_t;
|
||||
|
||||
@@ -191,7 +186,6 @@ void add_to_secrets_list(secrets_list_t *sl, const char* elem);
|
||||
/////////// USER DB CHECK //////////////////
|
||||
|
||||
int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *uname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh);
|
||||
int get_user_pwd(u08bits *uname, st_password_t pwd);
|
||||
u08bits *start_user_check(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);
|
||||
int check_new_allocation_quota(u08bits *username, int oauth, u08bits *realm);
|
||||
void release_allocation_quota(u08bits *username, int oauth, u08bits *realm);
|
||||
@@ -204,10 +198,11 @@ void release_allocation_quota(u08bits *username, int oauth, u08bits *realm);
|
||||
|
||||
void auth_ping(redis_context_handle rch);
|
||||
void reread_realms(void);
|
||||
int add_user_account(char *user, int dynamic);
|
||||
int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08bits *origin, TURNADMIN_COMMAND_TYPE ct, int is_st, perf_options_t* po);
|
||||
int add_static_user_account(char *user);
|
||||
int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08bits *origin, TURNADMIN_COMMAND_TYPE ct, perf_options_t* po, int is_admin);
|
||||
|
||||
int add_ip_list_range(const char* range, const char* realm, ip_range_list_t * list);
|
||||
int check_ip_list_range(const char* range);
|
||||
ip_range_list_t* get_ip_list(const char *kind);
|
||||
void ip_list_free(ip_range_list_t *l);
|
||||
|
||||
|
||||
@@ -56,14 +56,13 @@ int c2c=0;
|
||||
int clnet_verbose=TURN_VERBOSE_NONE;
|
||||
int use_tcp=0;
|
||||
int use_secure=0;
|
||||
int use_short_term=0;
|
||||
int hang_on=0;
|
||||
ioa_addr peer_addr;
|
||||
int no_rtcp = 0;
|
||||
int default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT;
|
||||
int dont_fragment = 0;
|
||||
u08bits g_uname[STUN_MAX_USERNAME_SIZE+1];
|
||||
st_password_t g_upwd;
|
||||
password_t g_upwd;
|
||||
char g_auth_secret[1025]="\0";
|
||||
int g_use_auth_secret_with_timestamp = 0;
|
||||
int use_fingerprints = 1;
|
||||
@@ -125,8 +124,6 @@ static char Usage[] =
|
||||
" -x IPv6 relay address requested.\n"
|
||||
" -X IPv4 relay address explicitly requested.\n"
|
||||
" -g Include DONT_FRAGMENT option.\n"
|
||||
" -A Use short-term credentials mechanism. By default, the program uses\n"
|
||||
" the long-term credentials mechanism if authentication is required.\n"
|
||||
" -D Mandatory channel padding (like in pjnath).\n"
|
||||
" -N Negative tests (some limited cases only).\n"
|
||||
" -R Negative protocol tests.\n"
|
||||
@@ -139,7 +136,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.\n"
|
||||
" -J Use oAuth with default test key kid='north'.\n"
|
||||
" -J Use oAuth with default test key kid='north' or 'oldempire'.\n"
|
||||
"Options:\n"
|
||||
" -l Message length (Default: 100 Bytes).\n"
|
||||
" -i Certificate file (for secure connections only, optional).\n"
|
||||
@@ -219,11 +216,6 @@ int main(int argc, char **argv)
|
||||
|
||||
oauth = 1;
|
||||
|
||||
if(use_short_term) {
|
||||
fprintf(stderr,"Short-term mechanism cannot be used together with oAuth.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
oauth_key_data okd_array[2];
|
||||
convert_oauth_key_data_raw(&okdr_array[0], &okd_array[0]);
|
||||
convert_oauth_key_data_raw(&okdr_array[1], &okd_array[1]);
|
||||
@@ -297,13 +289,6 @@ int main(int argc, char **argv)
|
||||
case 'Z':
|
||||
dual_allocation = 1;
|
||||
break;
|
||||
case 'A':
|
||||
if(oauth) {
|
||||
fprintf(stderr,"Short-term mechanism cannot be used together with oAuth.\n");
|
||||
exit(-1);
|
||||
}
|
||||
use_short_term = 1;
|
||||
break;
|
||||
case 'u':
|
||||
STRCPY(g_uname, optarg);
|
||||
break;
|
||||
@@ -409,10 +394,6 @@ int main(int argc, char **argv)
|
||||
|
||||
if(g_use_auth_secret_with_timestamp) {
|
||||
|
||||
if(use_short_term) {
|
||||
fprintf(stderr,"ERROR: You cannot use authentication secret (REST API) with short-term credentials mechanism.\n");
|
||||
exit(-1);
|
||||
}
|
||||
{
|
||||
char new_uname[1025];
|
||||
const unsigned long exp_time = 3600 * 24; /* one day */
|
||||
@@ -496,18 +477,13 @@ int main(int argc, char **argv)
|
||||
SSL_load_error_strings();
|
||||
OpenSSL_add_ssl_algorithms();
|
||||
|
||||
const char *csuite = "ALL:SSLv2"; //"AES256-SHA" "DH"
|
||||
const char *csuite = "ALL"; //"AES256-SHA" "DH"
|
||||
if(use_null_cipher)
|
||||
csuite = "eNULL";
|
||||
else if(cipher_suite[0])
|
||||
csuite=cipher_suite;
|
||||
|
||||
if(use_tcp) {
|
||||
#ifndef OPENSSL_NO_SSL2
|
||||
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(SSLv2_client_method());
|
||||
SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
|
||||
root_tls_ctx_num++;
|
||||
#endif
|
||||
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(SSLv23_client_method());
|
||||
SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
|
||||
root_tls_ctx_num++;
|
||||
|
||||
@@ -448,7 +448,7 @@ static int clnet_allocate(int verbose,
|
||||
allocate_received = 1;
|
||||
allocate_finished = 1;
|
||||
|
||||
if(clnet_info->nonce[0] || use_short_term) {
|
||||
if(clnet_info->nonce[0]) {
|
||||
if(check_integrity(clnet_info, &response_message)<0)
|
||||
return -1;
|
||||
}
|
||||
@@ -528,16 +528,11 @@ static int clnet_allocate(int verbose,
|
||||
goto beg_allocate;
|
||||
} else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) {
|
||||
|
||||
if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1) && use_short_term) {
|
||||
clnet_info->shatype = SHATYPE_SHA256;
|
||||
goto beg_allocate;
|
||||
}
|
||||
|
||||
allocate_received = 1;
|
||||
|
||||
if(err_code == 300) {
|
||||
|
||||
if(clnet_info->nonce[0] || use_short_term) {
|
||||
if(clnet_info->nonce[0]) {
|
||||
if(check_integrity(clnet_info, &response_message)<0)
|
||||
return -1;
|
||||
}
|
||||
@@ -797,7 +792,7 @@ static int turn_channel_bind(int verbose, uint16_t *chn,
|
||||
|
||||
cb_received = 1;
|
||||
|
||||
if(clnet_info->nonce[0] || use_short_term) {
|
||||
if(clnet_info->nonce[0]) {
|
||||
if(check_integrity(clnet_info, &response_message)<0)
|
||||
return -1;
|
||||
}
|
||||
@@ -906,7 +901,7 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info,
|
||||
|
||||
cp_received = 1;
|
||||
|
||||
if(clnet_info->nonce[0] || use_short_term) {
|
||||
if(clnet_info->nonce[0]) {
|
||||
if(check_integrity(clnet_info, &response_message)<0)
|
||||
return -1;
|
||||
}
|
||||
@@ -1481,7 +1476,7 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a
|
||||
u08bits err_msg[129];
|
||||
if (stun_is_success_response(&response_message)) {
|
||||
|
||||
if(clnet_info->nonce[0] || use_short_term) {
|
||||
if(clnet_info->nonce[0]) {
|
||||
if(check_integrity(clnet_info, &response_message)<0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -678,12 +678,6 @@ static int client_read(app_ur_session *elem, int is_tcp_data, app_tcp_conn_info
|
||||
}
|
||||
} else if (stun_is_indication(&(elem->in_buffer))) {
|
||||
|
||||
if(use_short_term) {
|
||||
|
||||
if(check_integrity(&(elem->pinfo), &(elem->in_buffer))<0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t method = stun_get_method(&elem->in_buffer);
|
||||
|
||||
if((method == STUN_METHOD_CONNECTION_ATTEMPT)&& is_TCP_relay()) {
|
||||
@@ -733,7 +727,7 @@ static int client_read(app_ur_session *elem, int is_tcp_data, app_tcp_conn_info
|
||||
|
||||
} else if (stun_is_success_response(&(elem->in_buffer))) {
|
||||
|
||||
if(elem->pinfo.nonce[0] || use_short_term) {
|
||||
if(elem->pinfo.nonce[0]) {
|
||||
if(check_integrity(&(elem->pinfo), &(elem->in_buffer))<0)
|
||||
return -1;
|
||||
}
|
||||
@@ -908,10 +902,6 @@ static int client_write(app_ur_session *elem) {
|
||||
if(dont_fragment)
|
||||
stun_attr_add(&(elem->out_buffer), STUN_ATTRIBUTE_DONT_FRAGMENT, NULL, 0);
|
||||
|
||||
if (use_short_term) {
|
||||
if(add_integrity(&(elem->pinfo), &(elem->out_buffer))<0) return -1;
|
||||
}
|
||||
|
||||
if(use_fingerprints)
|
||||
stun_attr_add_fingerprint_str(elem->out_buffer.buf,(size_t*)&(elem->out_buffer.len));
|
||||
}
|
||||
@@ -1590,19 +1580,12 @@ void start_mclient(const char *remote_address, int port,
|
||||
|
||||
turn_credential_type get_turn_credentials_type(void)
|
||||
{
|
||||
if(use_short_term)
|
||||
return TURN_CREDENTIALS_SHORT_TERM;
|
||||
return TURN_CREDENTIALS_LONG_TERM;
|
||||
}
|
||||
|
||||
int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message)
|
||||
{
|
||||
if(use_short_term) {
|
||||
if(stun_attr_add_integrity_by_user_short_term_str(message->buf, (size_t*)&(message->len), g_uname, g_upwd, clnet_info->shatype)<0) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot add integrity to the message\n");
|
||||
return -1;
|
||||
}
|
||||
} else if(clnet_info->nonce[0]) {
|
||||
if(clnet_info->nonce[0]) {
|
||||
|
||||
if(oauth && clnet_info->oauth) {
|
||||
|
||||
@@ -1654,7 +1637,7 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message)
|
||||
|
||||
//self-test:
|
||||
{
|
||||
st_password_t pwd;
|
||||
password_t pwd;
|
||||
if(stun_check_message_integrity_by_key_str(get_turn_credentials_type(),
|
||||
message->buf, (size_t)(message->len), clnet_info->key, pwd, clnet_info->shatype, NULL)<1) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR," Self-test of integrity does not comple correctly !\n");
|
||||
@@ -1679,7 +1662,7 @@ int check_integrity(app_ur_conn_info *clnet_info, stun_buffer *message)
|
||||
|
||||
if(oauth && clnet_info->oauth) {
|
||||
|
||||
st_password_t pwd;
|
||||
password_t pwd;
|
||||
|
||||
return stun_check_message_integrity_by_key_str(get_turn_credentials_type(),
|
||||
message->buf, (size_t)(message->len), clnet_info->key, pwd, sht, NULL);
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
#include "session.h"
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -51,7 +53,6 @@ extern int do_not_use_channel;
|
||||
extern int clnet_verbose;
|
||||
extern int use_tcp;
|
||||
extern int use_secure;
|
||||
extern int use_short_term;
|
||||
extern char cert_file[1025];
|
||||
extern char pkey_file[1025];
|
||||
extern int hang_on;
|
||||
@@ -61,7 +62,7 @@ extern int no_rtcp;
|
||||
extern int default_address_family;
|
||||
extern int dont_fragment;
|
||||
extern u08bits g_uname[STUN_MAX_USERNAME_SIZE+1];
|
||||
extern st_password_t g_upwd;
|
||||
extern password_t g_upwd;
|
||||
extern char g_auth_secret[1025];
|
||||
extern int g_use_auth_secret_with_timestamp;
|
||||
extern int use_fingerprints;
|
||||
|
||||
@@ -185,19 +185,35 @@ int addr_eq_no_port(const ioa_addr* a1, const ioa_addr *a2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int make_ioa_addr(const u08bits* saddr, int port, ioa_addr *addr) {
|
||||
int make_ioa_addr(const u08bits* saddr0, int port, ioa_addr *addr) {
|
||||
|
||||
if(!saddr || !addr) return -1;
|
||||
if(!saddr0 || !addr) return -1;
|
||||
|
||||
char ssaddr[257];
|
||||
STRCPY(ssaddr,saddr0);
|
||||
|
||||
char* saddr=ssaddr;
|
||||
while(*saddr == ' ') ++saddr;
|
||||
|
||||
size_t len=strlen(saddr);
|
||||
while(len>0) {
|
||||
if(saddr[len-1]==' ') {
|
||||
saddr[len-1]=0;
|
||||
--len;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ns_bzero(addr, sizeof(ioa_addr));
|
||||
if((strlen((const s08bits*)saddr) == 0)||
|
||||
(inet_pton(AF_INET, (const s08bits*)saddr, &addr->s4.sin_addr) == 1)) {
|
||||
if((len == 0)||
|
||||
(inet_pton(AF_INET, saddr, &addr->s4.sin_addr) == 1)) {
|
||||
addr->s4.sin_family = AF_INET;
|
||||
#if defined(TURN_HAS_SIN_LEN) /* tested when configured */
|
||||
addr->s4.sin_len = sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
addr->s4.sin_port = nswap16(port);
|
||||
} else if (inet_pton(AF_INET6, (const s08bits*)saddr, &addr->s6.sin6_addr) == 1) {
|
||||
} else if (inet_pton(AF_INET6, saddr, &addr->s6.sin6_addr) == 1) {
|
||||
addr->s6.sin6_family = AF_INET6;
|
||||
#if defined(SIN6_LEN) /* this define is required by IPv6 if used */
|
||||
addr->s6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
@@ -217,7 +233,7 @@ int make_ioa_addr(const u08bits* saddr, int port, ioa_addr *addr) {
|
||||
addr_hints.ai_addr = NULL;
|
||||
addr_hints.ai_next = NULL;
|
||||
|
||||
err = getaddrinfo((const char*)saddr, NULL, &addr_hints, &addr_result);
|
||||
err = getaddrinfo(saddr, NULL, &addr_hints, &addr_result);
|
||||
if ((err != 0)||(!addr_result)) {
|
||||
fprintf(stderr,"error resolving '%s' hostname: %s\n",saddr,gai_strerror(err));
|
||||
return -1;
|
||||
|
||||
+38
-21
@@ -611,17 +611,22 @@ int stun_is_channel_message_str(const u08bits *buf, size_t *blen, u16bits* chnum
|
||||
|
||||
////////// STUN message ///////////////////////////////
|
||||
|
||||
static inline int sheadof(const char *head, const char* full)
|
||||
static inline int sheadof(const char *head, const char* full, int ignore_case)
|
||||
{
|
||||
while(*head) {
|
||||
if(*head != *full)
|
||||
return 0;
|
||||
if(*head != *full) {
|
||||
if(ignore_case && (tolower((int)*head)==tolower((int)*full))) {
|
||||
//OK
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
++head;++full;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline const char* findstr(const char *hay, size_t slen, const char *needle)
|
||||
static inline const char* findstr(const char *hay, size_t slen, const char *needle, int ignore_case)
|
||||
{
|
||||
const char *ret = NULL;
|
||||
|
||||
@@ -632,7 +637,7 @@ static inline const char* findstr(const char *hay, size_t slen, const char *need
|
||||
size_t i;
|
||||
const char *sp = hay;
|
||||
for(i=0;i<smax;++i) {
|
||||
if(sheadof(needle,sp+i)) {
|
||||
if(sheadof(needle,sp+i,ignore_case)) {
|
||||
ret = sp+i;
|
||||
break;
|
||||
}
|
||||
@@ -643,28 +648,36 @@ static inline const char* findstr(const char *hay, size_t slen, const char *need
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int is_http_get_inline(const char *s, size_t blen) {
|
||||
static inline int is_http_inline(const char *s, size_t blen) {
|
||||
if(s && blen>=12) {
|
||||
if((s[0]=='G')&&(s[1]=='E')&&(s[2]=='T')&&(s[3]==' ')) {
|
||||
const char *sp=findstr(s+4,blen-4,"HTTP");
|
||||
if((strstr(s,"GET ")==s) ||(strstr(s,"POST ")==s) || (strstr(s,"DELETE ")==s) || (strstr(s,"PUT ")==s)) {
|
||||
const char *sp=findstr(s+4,blen-4," HTTP/",0);
|
||||
if(sp) {
|
||||
sp += 4;
|
||||
sp += 6;
|
||||
size_t diff_blen = sp-s;
|
||||
if(diff_blen+4 <= blen) {
|
||||
sp=findstr(sp,blen-diff_blen,"\r\n\r\n");
|
||||
sp=findstr(sp,blen-diff_blen,"\r\n\r\n",0);
|
||||
if(sp) {
|
||||
return (int)(sp-s+4);
|
||||
int ret_len = (int)(sp-s+4);
|
||||
const char* clheader = "content-length: ";
|
||||
const char* cl = findstr(s,sp-s,clheader,1);
|
||||
if(cl) {
|
||||
unsigned long clen = strtoul(cl+strlen(clheader),NULL,10);
|
||||
if(clen>0 && clen<(0x0FFFFFFF)) {
|
||||
ret_len += (int)clen;
|
||||
}
|
||||
}
|
||||
return ret_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_http_get(const char *s, size_t blen) {
|
||||
return is_http_get_inline(s, blen);
|
||||
int is_http(const char *s, size_t blen) {
|
||||
return is_http_inline(s, blen);
|
||||
}
|
||||
|
||||
int stun_get_message_len_str(u08bits *buf, size_t blen, int padding, size_t *app_len) {
|
||||
@@ -690,7 +703,7 @@ int stun_get_message_len_str(u08bits *buf, size_t blen, int padding, size_t *app
|
||||
|
||||
//HTTP request ?
|
||||
{
|
||||
int http_len = is_http_get_inline(((char*)buf), blen);
|
||||
int http_len = is_http_inline(((char*)buf), blen);
|
||||
if((http_len>0) && ((size_t)http_len<=blen)) {
|
||||
*app_len = (size_t)http_len;
|
||||
return http_len;
|
||||
@@ -1452,7 +1465,7 @@ void print_bin_func(const char *name, size_t len, const void *s, const char *fun
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
int stun_attr_add_integrity_str(turn_credential_type ct, u08bits *buf, size_t *len, hmackey_t key, st_password_t pwd, SHATYPE shatype)
|
||||
int stun_attr_add_integrity_str(turn_credential_type ct, u08bits *buf, size_t *len, hmackey_t key, password_t pwd, SHATYPE shatype)
|
||||
{
|
||||
u08bits hmac[MAXSHASIZE];
|
||||
|
||||
@@ -1491,7 +1504,7 @@ int stun_attr_add_integrity_by_key_str(u08bits *buf, size_t *len, u08bits *uname
|
||||
if(stun_attr_add_str(buf, len, STUN_ATTRIBUTE_REALM, realm, strlen((s08bits*)realm))<0)
|
||||
return -1;
|
||||
|
||||
st_password_t p;
|
||||
password_t p;
|
||||
return stun_attr_add_integrity_str(TURN_CREDENTIALS_LONG_TERM, buf, len, key, p, shatype);
|
||||
}
|
||||
|
||||
@@ -1505,7 +1518,7 @@ int stun_attr_add_integrity_by_user_str(u08bits *buf, size_t *len, u08bits *unam
|
||||
return stun_attr_add_integrity_by_key_str(buf, len, uname, realm, key, nonce, shatype);
|
||||
}
|
||||
|
||||
int stun_attr_add_integrity_by_user_short_term_str(u08bits *buf, size_t *len, u08bits *uname, st_password_t pwd, SHATYPE shatype)
|
||||
int stun_attr_add_integrity_by_user_short_term_str(u08bits *buf, size_t *len, u08bits *uname, password_t pwd, SHATYPE shatype)
|
||||
{
|
||||
if(stun_attr_add_str(buf, len, STUN_ATTRIBUTE_USERNAME, uname, strlen((s08bits*)uname))<0)
|
||||
return -1;
|
||||
@@ -1527,7 +1540,7 @@ void print_hmac(const char *name, const void *s, size_t len)
|
||||
/*
|
||||
* Return -1 if failure, 0 if the integrity is not correct, 1 if OK
|
||||
*/
|
||||
int stun_check_message_integrity_by_key_str(turn_credential_type ct, u08bits *buf, size_t len, hmackey_t key, st_password_t pwd, SHATYPE shatype, int *too_weak)
|
||||
int stun_check_message_integrity_by_key_str(turn_credential_type ct, u08bits *buf, size_t len, hmackey_t key, password_t pwd, SHATYPE shatype, int *too_weak)
|
||||
{
|
||||
int res = 0;
|
||||
u08bits new_hmac[MAXSHASIZE];
|
||||
@@ -1595,10 +1608,10 @@ int stun_check_message_integrity_by_key_str(turn_credential_type ct, u08bits *bu
|
||||
int stun_check_message_integrity_str(turn_credential_type ct, u08bits *buf, size_t len, u08bits *uname, u08bits *realm, u08bits *upwd, SHATYPE shatype)
|
||||
{
|
||||
hmackey_t key;
|
||||
st_password_t pwd;
|
||||
password_t pwd;
|
||||
|
||||
if(ct == TURN_CREDENTIALS_SHORT_TERM)
|
||||
strncpy((char*)pwd,(char*)upwd,sizeof(st_password_t));
|
||||
strncpy((char*)pwd,(char*)upwd,sizeof(password_t));
|
||||
else if (stun_produce_integrity_key_str(uname, realm, upwd, key, shatype) < 0)
|
||||
return -1;
|
||||
|
||||
@@ -1882,6 +1895,8 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er
|
||||
key->auth_alg = AUTH_ALG_ERROR;
|
||||
OAUTH_ERROR("Wrong oAuth token hash algorithm: %s (2)\n",oakd->auth_alg);
|
||||
return -1;
|
||||
} else {
|
||||
key->auth_alg = AUTH_ALG_UNDEFINED;
|
||||
}
|
||||
|
||||
key->as_rs_alg = ENC_ALG_DEFAULT;
|
||||
@@ -1891,8 +1906,10 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er
|
||||
key->as_rs_alg = AES_256_CBC;
|
||||
} else if(!strcmp(oakd->as_rs_alg,"AEAD-AES-128-GCM")) {
|
||||
key->as_rs_alg = AEAD_AES_128_GCM;
|
||||
key->auth_alg = AUTH_ALG_UNDEFINED;
|
||||
} else if(!strcmp(oakd->as_rs_alg,"AEAD-AES-256-GCM")) {
|
||||
key->as_rs_alg = AEAD_AES_256_GCM;
|
||||
key->auth_alg = AUTH_ALG_UNDEFINED;
|
||||
} else if(oakd->as_rs_alg[0]) {
|
||||
if(err_msg) {
|
||||
snprintf(err_msg,err_msg_size,"Wrong oAuth token encryption algorithm: %s (2)\n",oakd->as_rs_alg);
|
||||
|
||||
@@ -63,11 +63,7 @@ typedef enum {
|
||||
*/
|
||||
typedef u08bits hmackey_t[64];
|
||||
|
||||
/**
|
||||
* Short-term credentials password
|
||||
*/
|
||||
#define SHORT_TERM_PASSWORD_SIZE (512)
|
||||
typedef u08bits st_password_t[SHORT_TERM_PASSWORD_SIZE+1];
|
||||
typedef u08bits password_t[STUN_MAX_PWD_SIZE+1];
|
||||
typedef unsigned int band_limit_t;
|
||||
|
||||
///////////////////////////////////
|
||||
@@ -180,12 +176,12 @@ void print_bin_func(const char *name, size_t len, const void *s, const char *fun
|
||||
/*
|
||||
* Return -1 if failure, 0 if the integrity is not correct, 1 if OK
|
||||
*/
|
||||
int stun_check_message_integrity_by_key_str(turn_credential_type ct, u08bits *buf, size_t len, hmackey_t key, st_password_t pwd, SHATYPE shatype, int *too_weak);
|
||||
int stun_check_message_integrity_by_key_str(turn_credential_type ct, u08bits *buf, size_t len, hmackey_t key, password_t pwd, SHATYPE shatype, int *too_weak);
|
||||
int stun_check_message_integrity_str(turn_credential_type ct, u08bits *buf, size_t len, u08bits *uname, u08bits *realm, u08bits *upwd, SHATYPE shatype);
|
||||
int stun_attr_add_integrity_str(turn_credential_type ct, u08bits *buf, size_t *len, hmackey_t key, st_password_t pwd, SHATYPE shatype);
|
||||
int stun_attr_add_integrity_str(turn_credential_type ct, u08bits *buf, size_t *len, hmackey_t key, password_t pwd, SHATYPE shatype);
|
||||
int stun_attr_add_integrity_by_key_str(u08bits *buf, size_t *len, u08bits *uname, u08bits *realm, hmackey_t key, u08bits *nonce, SHATYPE shatype);
|
||||
int stun_attr_add_integrity_by_user_str(u08bits *buf, size_t *len, u08bits *uname, u08bits *realm, u08bits *upwd, u08bits *nonce, SHATYPE shatype);
|
||||
int stun_attr_add_integrity_by_user_short_term_str(u08bits *buf, size_t *len, u08bits *uname, st_password_t pwd, SHATYPE shatype);
|
||||
int stun_attr_add_integrity_by_user_short_term_str(u08bits *buf, size_t *len, u08bits *uname, password_t pwd, SHATYPE shatype);
|
||||
size_t get_hmackey_size(SHATYPE shatype);
|
||||
|
||||
/*
|
||||
@@ -207,7 +203,7 @@ int stun_attr_get_padding_len_str(stun_attr_ref attr);
|
||||
int stun_attr_add_padding_str(u08bits *buf, size_t *len, u16bits padding_len);
|
||||
|
||||
/* HTTP */
|
||||
int is_http_get(const char *s, size_t blen);
|
||||
int is_http(const char *s, size_t blen);
|
||||
|
||||
/* OAUTH */
|
||||
int convert_oauth_key_data(const oauth_key_data *oakd, oauth_key *key, char *err_msg, size_t err_msg_size);
|
||||
|
||||
@@ -40,11 +40,12 @@
|
||||
#define STUN_HEADER_LENGTH (20)
|
||||
#define STUN_CHANNEL_HEADER_LENGTH (4)
|
||||
|
||||
#define STUN_MAX_USERNAME_SIZE (513)
|
||||
#define STUN_MAX_USERNAME_SIZE (512)
|
||||
#define STUN_MAX_REALM_SIZE (127)
|
||||
#define STUN_MAX_NONCE_SIZE (127)
|
||||
#define STUN_MAX_SERVER_NAME_SIZE (1025)
|
||||
#define STUN_MAX_PWD_SIZE (127)
|
||||
#define AUTH_SECRET_SIZE STUN_MAX_PWD_SIZE
|
||||
|
||||
#define STUN_MAGIC_COOKIE (0x2112A442)
|
||||
|
||||
|
||||
+2
-2
@@ -31,8 +31,8 @@
|
||||
#ifndef __IOADEFS__
|
||||
#define __IOADEFS__
|
||||
|
||||
#define TURN_SERVER_VERSION "4.3.3.1"
|
||||
#define TURN_SERVER_VERSION_NAME "Tolomei"
|
||||
#define TURN_SERVER_VERSION "4.4.1.1"
|
||||
#define TURN_SERVER_VERSION_NAME "Ardee West"
|
||||
#define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'"
|
||||
|
||||
#if (defined(__unix__) || defined(unix)) && !defined(USG)
|
||||
|
||||
@@ -278,8 +278,7 @@ int get_default_protocol_port(const char* scheme, size_t slen);
|
||||
|
||||
///////////// HTTP ////////////////////
|
||||
|
||||
void write_http_echo(ioa_socket_handle s);
|
||||
void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh);
|
||||
void handle_http_echo(ioa_socket_handle s);
|
||||
|
||||
///////////////////////////////////////
|
||||
|
||||
|
||||
+43
-59
@@ -2148,13 +2148,6 @@ static void tcp_peer_accept_connection(ioa_socket_handle s, void *arg)
|
||||
ioa_network_buffer_set_size(nbh, len);
|
||||
}
|
||||
|
||||
/* We add integrity for short-term indication messages, only */
|
||||
if(server->ct == TURN_CREDENTIALS_SHORT_TERM)
|
||||
{
|
||||
stun_attr_add_integrity_str(server->ct,ioa_network_buffer_data(nbh),&len,ss->hmackey,ss->pwd,server->shatype);
|
||||
ioa_network_buffer_set_size(nbh,len);
|
||||
}
|
||||
|
||||
if ((server->fingerprint) || ss->enforce_fingerprints) {
|
||||
size_t len = ioa_network_buffer_get_size(nbh);
|
||||
stun_attr_add_fingerprint_str(ioa_network_buffer_data(nbh), &len);
|
||||
@@ -3118,8 +3111,6 @@ static int need_stun_authentication(turn_turnserver *server, ts_ur_super_session
|
||||
switch(server->ct) {
|
||||
case TURN_CREDENTIALS_LONG_TERM:
|
||||
return 1;
|
||||
case TURN_CREDENTIALS_SHORT_TERM:
|
||||
return 1;
|
||||
default:
|
||||
;
|
||||
};
|
||||
@@ -3164,7 +3155,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, st_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)
|
||||
{
|
||||
|
||||
if(server && in_buffer && in_buffer->nbh) {
|
||||
@@ -3178,7 +3169,7 @@ static void resume_processing_after_username_check(int success, int oauth, int
|
||||
ss->hmackey_set = 1;
|
||||
ss->oauth = oauth;
|
||||
ss->max_session_time_auth = (turn_time_t)max_session_time;
|
||||
ns_bcopy(pwd,ss->pwd,sizeof(st_password_t));
|
||||
ns_bcopy(pwd,ss->pwd,sizeof(password_t));
|
||||
}
|
||||
|
||||
read_client_connection(server,ss,in_buffer,0,0);
|
||||
@@ -3252,11 +3243,7 @@ static int check_stun_auth(turn_turnserver *server,
|
||||
if(!sar) {
|
||||
*err_code = 401;
|
||||
*reason = (const u08bits*)"Unauthorised";
|
||||
if(server->ct != TURN_CREDENTIALS_SHORT_TERM) {
|
||||
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -3280,7 +3267,7 @@ static int check_stun_auth(turn_turnserver *server,
|
||||
};
|
||||
}
|
||||
|
||||
if(server->ct != TURN_CREDENTIALS_SHORT_TERM) {
|
||||
{
|
||||
|
||||
/* REALM ATTR: */
|
||||
|
||||
@@ -3351,7 +3338,7 @@ static int check_stun_auth(turn_turnserver *server,
|
||||
set_realm_hash(ss->client_socket,(u08bits*)ss->realm_options.name);
|
||||
}
|
||||
|
||||
if(server->ct != TURN_CREDENTIALS_SHORT_TERM) {
|
||||
{
|
||||
/* NONCE ATTR: */
|
||||
|
||||
sar = stun_attr_get_first_by_type_str(ioa_network_buffer_data(in_buffer->nbh),
|
||||
@@ -3391,18 +3378,14 @@ static int check_stun_auth(turn_turnserver *server,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* we always return NULL for short-term credentials here */
|
||||
|
||||
/* direct user pattern is supported only for long-term credentials */
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
|
||||
"%s: Cannot find credentials of user <%s>\n",
|
||||
__FUNCTION__, (char*)usname);
|
||||
*err_code = 401;
|
||||
*reason = (const u08bits*)"Unauthorised";
|
||||
if(server->ct != TURN_CREDENTIALS_SHORT_TERM) {
|
||||
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
|
||||
}
|
||||
|
||||
/* Check integrity */
|
||||
@@ -3420,11 +3403,7 @@ static int check_stun_auth(turn_turnserver *server,
|
||||
__FUNCTION__, (char*)usname);
|
||||
*err_code = SHA_TOO_WEAK_ERROR_CODE;
|
||||
*reason = (const u08bits*)"Unauthorised: weak SHA function is used";
|
||||
if(server->ct != TURN_CREDENTIALS_SHORT_TERM) {
|
||||
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
|
||||
}
|
||||
|
||||
if(can_resume) {
|
||||
@@ -3439,11 +3418,7 @@ static int check_stun_auth(turn_turnserver *server,
|
||||
__FUNCTION__, (char*)usname);
|
||||
*err_code = 401;
|
||||
*reason = (const u08bits*)"Unauthorised";
|
||||
if(server->ct != TURN_CREDENTIALS_SHORT_TERM) {
|
||||
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
|
||||
}
|
||||
|
||||
*message_integrity = 1;
|
||||
@@ -3792,10 +3767,6 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss,
|
||||
no_response = 1;
|
||||
int postpone = 0;
|
||||
|
||||
if(server->ct == TURN_CREDENTIALS_SHORT_TERM) {
|
||||
check_stun_auth(server, ss, &tid, resp_constructed, &err_code, &reason, in_buffer, nbh, method, &message_integrity, &postpone, can_resume);
|
||||
}
|
||||
|
||||
if (!postpone && !err_code) {
|
||||
|
||||
switch (method){
|
||||
@@ -4349,8 +4320,9 @@ static int create_relay_connection(turn_turnserver* server,
|
||||
set_do_not_use_df(newelem->s);
|
||||
|
||||
if(get_ioa_socket_type(newelem->s) != TCP_SOCKET) {
|
||||
register_callback_on_ioa_socket(server->e, newelem->s, IOA_EV_READ,
|
||||
peer_input_handler, ss, 0);
|
||||
if(register_callback_on_ioa_socket(server->e, newelem->s, IOA_EV_READ,peer_input_handler, ss, 0)<0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (lifetime<1)
|
||||
@@ -4441,13 +4413,15 @@ static int read_client_connection(turn_turnserver *server,
|
||||
|
||||
if(sat == HTTP_CLIENT_SOCKET) {
|
||||
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTP connection input: %s\n", __FUNCTION__, (char*)ioa_network_buffer_data(in_buffer->nbh));
|
||||
write_http_echo(ss->client_socket);
|
||||
if(server->verbose) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTP connection input: %s\n", __FUNCTION__, (char*)ioa_network_buffer_data(in_buffer->nbh));
|
||||
}
|
||||
|
||||
handle_http_echo(ss->client_socket);
|
||||
|
||||
} else if(sat == HTTPS_CLIENT_SOCKET) {
|
||||
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection input: %s\n", __FUNCTION__, (char*)ioa_network_buffer_data(in_buffer->nbh));
|
||||
handle_https(ss->client_socket,in_buffer->nbh);
|
||||
//???
|
||||
|
||||
} else if (stun_is_channel_message_str(ioa_network_buffer_data(in_buffer->nbh),
|
||||
&blen,
|
||||
@@ -4536,17 +4510,28 @@ static int read_client_connection(turn_turnserver *server,
|
||||
} else {
|
||||
SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket);
|
||||
if((st == TCP_SOCKET)||(st==TLS_SOCKET)||(st==TENTATIVE_TCP_SOCKET)) {
|
||||
if(is_http_get((char*)ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh))) {
|
||||
if(is_http((char*)ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh))) {
|
||||
const char *proto = "HTTP";
|
||||
ioa_network_buffer_data(in_buffer->nbh)[ioa_network_buffer_get_size(in_buffer->nbh)] = 0;
|
||||
if(st==TLS_SOCKET) {
|
||||
proto = "HTTPS";
|
||||
set_ioa_socket_app_type(ss->client_socket,HTTPS_CLIENT_SOCKET);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s (%s %s) request: %s\n", __FUNCTION__, proto, get_ioa_socket_cipher(ss->client_socket), get_ioa_socket_ssl_method(ss->client_socket), (char*)ioa_network_buffer_data(in_buffer->nbh));
|
||||
handle_https(ss->client_socket,in_buffer->nbh);
|
||||
if(server->send_https_socket) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s socket to be detached: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)ss->client_socket, get_ioa_socket_type(ss->client_socket), get_ioa_socket_app_type(ss->client_socket));
|
||||
ioa_socket_handle new_s = detach_ioa_socket(ss->client_socket);
|
||||
if(new_s) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s new detached socket: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)new_s, get_ioa_socket_type(new_s), get_ioa_socket_app_type(new_s));
|
||||
server->send_https_socket(new_s);
|
||||
}
|
||||
ss->to_be_closed = 1;
|
||||
}
|
||||
} else {
|
||||
set_ioa_socket_app_type(ss->client_socket,HTTP_CLIENT_SOCKET);
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s request: %s\n", __FUNCTION__, proto, (char*)ioa_network_buffer_data(in_buffer->nbh));
|
||||
write_http_echo(ss->client_socket);
|
||||
if(server->verbose) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s request: %s\n", __FUNCTION__, proto, (char*)ioa_network_buffer_data(in_buffer->nbh));
|
||||
}
|
||||
handle_http_echo(ss->client_socket);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -4572,8 +4557,10 @@ static int attach_socket_to_session(turn_turnserver* server, ioa_socket_handle s
|
||||
|
||||
ss->client_socket = s;
|
||||
|
||||
register_callback_on_ioa_socket(server->e, s, IOA_EV_READ,
|
||||
client_input_handler, ss, 0);
|
||||
if(register_callback_on_ioa_socket(server->e, s, IOA_EV_READ,
|
||||
client_input_handler, ss, 0)<0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_ioa_socket_session(s, ss);
|
||||
}
|
||||
@@ -4599,8 +4586,10 @@ int open_client_connection_session(turn_turnserver* server,
|
||||
|
||||
ss->client_socket = sm->s;
|
||||
|
||||
register_callback_on_ioa_socket(server->e, ss->client_socket, IOA_EV_READ,
|
||||
client_input_handler, ss, 0);
|
||||
if(register_callback_on_ioa_socket(server->e, ss->client_socket, IOA_EV_READ,
|
||||
client_input_handler, ss, 0)<0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_ioa_socket_session(ss->client_socket, ss);
|
||||
|
||||
@@ -4722,13 +4711,6 @@ static void peer_input_handler(ioa_socket_handle s, int event_type,
|
||||
ioa_network_buffer_set_size(nbh, len);
|
||||
}
|
||||
|
||||
/* We add integrity for short-term indication messages, only */
|
||||
if(server->ct == TURN_CREDENTIALS_SHORT_TERM)
|
||||
{
|
||||
stun_attr_add_integrity_str(server->ct,ioa_network_buffer_data(nbh),&len,ss->hmackey,ss->pwd,server->shatype);
|
||||
ioa_network_buffer_set_size(nbh,len);
|
||||
}
|
||||
|
||||
if ((server->fingerprint) || ss->enforce_fingerprints) {
|
||||
size_t len = ioa_network_buffer_get_size(nbh);
|
||||
stun_attr_add_fingerprint_str(ioa_network_buffer_data(nbh), &len);
|
||||
@@ -4802,6 +4784,7 @@ void init_turn_server(turn_turnserver* server,
|
||||
send_socket_to_relay_cb send_socket_to_relay,
|
||||
vintp secure_stun, SHATYPE shatype, vintp mobility, int server_relay,
|
||||
send_turn_session_info_cb send_turn_session_info,
|
||||
send_https_socket_cb send_https_socket,
|
||||
allocate_bps_cb allocate_bps_func,
|
||||
int oauth, const char* oauth_server_name) {
|
||||
|
||||
@@ -4827,6 +4810,7 @@ void init_turn_server(turn_turnserver* server,
|
||||
server->mobility = mobility;
|
||||
server->server_relay = server_relay;
|
||||
server->send_turn_session_info = send_turn_session_info;
|
||||
server->send_https_socket = send_https_socket;
|
||||
server->oauth = oauth;
|
||||
if(oauth)
|
||||
server->oauth_server_name = oauth_server_name;
|
||||
|
||||
@@ -90,12 +90,13 @@ 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, st_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);
|
||||
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);
|
||||
typedef int (*send_socket_to_relay_cb)(turnserver_id id, u64bits cid, stun_tid *tid, ioa_socket_handle s, int message_integrity, MESSAGE_TO_RELAY_TYPE rmt, ioa_net_data *nd, int can_resume);
|
||||
typedef int (*send_turn_session_info_cb)(struct turn_session_info *tsi);
|
||||
typedef void (*send_https_socket_cb)(ioa_socket_handle s);
|
||||
|
||||
typedef band_limit_t (*allocate_bps_cb)(band_limit_t bps, int positive);
|
||||
|
||||
@@ -131,6 +132,7 @@ struct _turn_turnserver {
|
||||
vintp no_loopback_peers;
|
||||
vintp no_multicast_peers;
|
||||
send_turn_session_info_cb send_turn_session_info;
|
||||
send_https_socket_cb send_https_socket;
|
||||
|
||||
/* RFC 6062 ==>> */
|
||||
vintp no_udp_relay;
|
||||
@@ -199,6 +201,7 @@ void init_turn_server(turn_turnserver* server,
|
||||
vintp mobility,
|
||||
int server_relay,
|
||||
send_turn_session_info_cb send_turn_session_info,
|
||||
send_https_socket_cb send_https_socket,
|
||||
allocate_bps_cb allocate_bps_func,
|
||||
int oauth,
|
||||
const char* oauth_server_name);
|
||||
|
||||
@@ -44,7 +44,7 @@ extern "C" {
|
||||
|
||||
typedef struct _perf_options_t {
|
||||
|
||||
band_limit_t max_bps;
|
||||
volatile band_limit_t max_bps;
|
||||
vint total_quota;
|
||||
vint user_quota;
|
||||
|
||||
@@ -81,7 +81,7 @@ struct _ts_ur_super_session {
|
||||
u08bits username[STUN_MAX_USERNAME_SIZE+1];
|
||||
hmackey_t hmackey;
|
||||
int hmackey_set;
|
||||
st_password_t pwd;
|
||||
password_t pwd;
|
||||
int quota_used;
|
||||
int oauth;
|
||||
turn_time_t max_session_time_auth;
|
||||
|
||||
@@ -5,10 +5,10 @@ mongo $* <<EOF
|
||||
use coturn;
|
||||
|
||||
db.turnusers_lt.ensureIndex({ realm: 1, name: 1 }, { unique: 1 });
|
||||
db.turnusers_st.ensureIndex({ name: 1 }, { unique: 1 });
|
||||
db.turn_secret.ensureIndex({ realm: 1 }, { unique: 1 });
|
||||
db.turn_secret.ensureIndex({ realm: 1, value:1 }, { unique: 1 });
|
||||
db.realm.ensureIndex({ realm: 1 }, { unique: 1 });
|
||||
db.oauth_key.ensureIndex({ kid: 1 }, {unique: 1 });
|
||||
db.admin_user.ensureIndex({ name: 1 }, {unique: 1 });
|
||||
|
||||
exit
|
||||
|
||||
|
||||
+15
-13
@@ -1,42 +1,37 @@
|
||||
|
||||
CREATE TABLE turnusers_lt (
|
||||
realm varchar(512) default '',
|
||||
realm varchar(127) default '',
|
||||
name varchar(512),
|
||||
hmackey char(128),
|
||||
PRIMARY KEY (realm,name)
|
||||
);
|
||||
|
||||
CREATE TABLE turnusers_st (
|
||||
name varchar(512) PRIMARY KEY,
|
||||
password varchar(512)
|
||||
);
|
||||
|
||||
CREATE TABLE turn_secret (
|
||||
realm varchar(512) default '',
|
||||
value varchar(512),
|
||||
realm varchar(127) default '',
|
||||
value varchar(127),
|
||||
primary key (realm,value)
|
||||
);
|
||||
|
||||
CREATE TABLE allowed_peer_ip (
|
||||
realm varchar(512) default '',
|
||||
realm varchar(127) default '',
|
||||
ip_range varchar(256),
|
||||
primary key (realm,ip_range)
|
||||
);
|
||||
|
||||
CREATE TABLE denied_peer_ip (
|
||||
realm varchar(512) default '',
|
||||
realm varchar(127) default '',
|
||||
ip_range varchar(256),
|
||||
primary key (realm,ip_range)
|
||||
);
|
||||
|
||||
CREATE TABLE turn_origin_to_realm (
|
||||
origin varchar(512),
|
||||
realm varchar(512),
|
||||
origin varchar(127),
|
||||
realm varchar(127),
|
||||
primary key (origin)
|
||||
);
|
||||
|
||||
CREATE TABLE turn_realm_option (
|
||||
realm varchar(512) default '',
|
||||
realm varchar(127) default '',
|
||||
opt varchar(32),
|
||||
value varchar(128),
|
||||
primary key (realm,opt)
|
||||
@@ -54,3 +49,10 @@ CREATE TABLE oauth_key (
|
||||
auth_key varchar(256) default '',
|
||||
primary key (kid)
|
||||
);
|
||||
|
||||
CREATE TABLE admin_user (
|
||||
name varchar(32),
|
||||
realm varchar(127),
|
||||
password varchar(127),
|
||||
primary key (name)
|
||||
);
|
||||
|
||||
+16
-24
@@ -8,16 +8,9 @@ has the following schema:
|
||||
"turn/realm/<realm-name>/user/<username>/key" and the values must be
|
||||
the the hmackeys. For example, for the user "gorst", realm "north.gov"
|
||||
and password "hero", there must be key "turn/realm/north.gov/user/gorst/key"
|
||||
with value "7da2270ccfa49786e0115366d3a3d14d". Alternatively, the password
|
||||
may be stored in clear text format. Then the key will be
|
||||
"turn/realm/north.gov/user/gorst/password" and the key will be simply "hero".
|
||||
with value "7da2270ccfa49786e0115366d3a3d14d".
|
||||
|
||||
2) For the short-term credentials, the passwords are stored always in
|
||||
clear text format, with no realm name (because the short-term credentials
|
||||
are not bound to a realm). So, there will be key "turn/user/gorst/password"
|
||||
and the value will be "hero".
|
||||
|
||||
3) For the shared secrets (REST API), several key/value pairs
|
||||
2) For the shared secrets (REST API), several key/value pairs
|
||||
may be used (same as in SQL schema). The secrets are stored as members
|
||||
of an unordered set. The name of the set will be
|
||||
"turn/realm/<realm-name>/secret" and the value(s) will be the secret(s).
|
||||
@@ -26,7 +19,7 @@ then we will have set "turn/realm/north.gov/secret" with values
|
||||
"hero1", "hero2" and "hero3". The turnserver will try to use the
|
||||
secrets in arbitrary order.
|
||||
|
||||
4) The "white" and "black" peer IP ranges are stored as unordered sets
|
||||
3) The "white" and "black" peer IP ranges are stored as unordered sets
|
||||
of the following names:
|
||||
"turn/realm/<realm>/allowed-peer-ip" and
|
||||
"turn/realm/<realm>/denied-peer-ip".
|
||||
@@ -38,7 +31,7 @@ The only difference is that the turnserver option values are "static"
|
||||
the database records can be dynamically changed
|
||||
and they will be almost immediately "seen" by the turnserver process.
|
||||
|
||||
5) For the oAuth authentication, there is a hash structure with the key
|
||||
4) For the oAuth authentication, there is a hash structure with the key
|
||||
"turn/oauth/kid/<kid-value>". The kid structure fields are:
|
||||
|
||||
ikm_key - (optional) base64-encoded key ("input keying material");
|
||||
@@ -72,6 +65,10 @@ and they will be almost immediately "seen" by the turnserver process.
|
||||
auth_key - (optional) base64-encoded AUTH key. If not defined, then
|
||||
calculated with ikm_key and hkdf_hash_func. The auth_key length
|
||||
is defined by auth_alg.
|
||||
|
||||
5) admin users (over https interface) are maintained as keys of form:
|
||||
"turn/admin_user/<username> with hash members "password" and,
|
||||
optionally, "realm".
|
||||
|
||||
II. Extra realms data in the database
|
||||
|
||||
@@ -95,7 +92,6 @@ This example sets user database for:
|
||||
* long-term credentials with open passwords and
|
||||
with default realm "north.gov";
|
||||
* TURN REST API with shared secrets "logen", etc;
|
||||
* short-term credentials mechanism, with open passwords;
|
||||
* Black and white IP peer lists used.
|
||||
* Information how to match ORIGIN field with extra
|
||||
realms (if used). If no origin match found
|
||||
@@ -104,7 +100,9 @@ This example sets user database for:
|
||||
* The realm performance parameters: "max_bps",
|
||||
"total_quota" and "user_quota" (same names as the turnserver
|
||||
configuration options, with the same meanings).
|
||||
* The oAuth data for the key with kid "north" and key value "carleon".
|
||||
* The oAuth data for the key with kid "north" and key value "carleon".
|
||||
* The admin user 'skarling', realm 'north.gov', with password 'hoodless';
|
||||
* The global admin user 'bayaz' with password 'magi';
|
||||
|
||||
The shell command would be:
|
||||
|
||||
@@ -118,19 +116,9 @@ set turn/realm/north.gov/user/gorst/key "7da2270ccfa49786e0115366d3a3d14d"
|
||||
set turn/realm/crinna.org/user/whirrun/key "6972e85e51f36e53b0b61759c5a5219a"
|
||||
set turn/realm/crinna.org/user/stranger-come-knocking/key "d43cb678560259a1839bff61c19de15e"
|
||||
|
||||
set turn/realm/north.gov/user/ninefingers/password "youhavetoberealistic"
|
||||
set turn/realm/north.gov/user/gorst/password "hero"
|
||||
set turn/realm/crinna.org/user/whirrun/password "sword"
|
||||
set turn/realm/crinna.org/user/stranger-come-knocking/password "civilization"
|
||||
|
||||
sadd turn/realm/north.gov/secret "logen" "bloody9"
|
||||
sadd turn/realm/crinna.org/secret "north" "library"
|
||||
|
||||
set turn/user/ninefingers/password "youhavetoberealistic"
|
||||
set turn/user/gorst/password "hero"
|
||||
set turn/user/whirrun/password "sword"
|
||||
set turn/user/stranger-come-knocking/password "civilization"
|
||||
|
||||
set turn/realm/north.gov/max-bps 500000
|
||||
set turn/realm/north.gov/total-quota 12000
|
||||
set turn/realm/north.gov/user-quota 10000
|
||||
@@ -147,7 +135,11 @@ 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 Y2FybGVvbg== hkdf_hash_func 'SHA-256' as_rs_alg 'AES-128-CBC' auth_alg 'HMAC-SHA-256-128'
|
||||
hmset turn/oauth/kid/north ikm_key 'Y2FybGVvbg==' hkdf_hash_func 'SHA-256' as_rs_alg 'AES-128-CBC' auth_alg 'HMAC-SHA-256-128'
|
||||
hmset turn/oauth/kid/oldempire ikm_key 'YXVsY3Vz' hkdf_hash_func 'SHA-256' as_rs_alg 'AEAD-AES-256-GCM'
|
||||
|
||||
hmset turn/admin_user/skarling realm 'north.gov' password 'hoodless'
|
||||
hmset turn/admin_user/bayaz password 'magi'
|
||||
|
||||
save
|
||||
|
||||
|
||||
@@ -5,23 +5,23 @@ mongo $* <<EOF
|
||||
use coturn;
|
||||
|
||||
db.turnusers_lt.ensureIndex({ realm: 1, name: 1 }, { unique: 1 });
|
||||
db.turnusers_st.ensureIndex({ name: 1 }, { unique: 1 });
|
||||
db.turn_secret.ensureIndex({ realm: 1 }, { unique: 1 });
|
||||
db.turn_secret.ensureIndex({ realm: 1, value:1 }, { unique: 1 });
|
||||
db.realm.ensureIndex({ realm: 1 }, { unique: 1 });
|
||||
db.oauth_key.ensureIndex({ kid: 1 }, {unique: 1 });
|
||||
db.admin_user.ensureIndex({ name: 1 }, {unique: 1 });
|
||||
|
||||
db.turnusers_lt.insert({ realm: 'north.gov', name: 'ninefingers', hmackey: 'bc807ee29df3c9ffa736523fb2c4e8ee' });
|
||||
db.turnusers_lt.insert({ realm: 'north.gov', name: 'gorst', hmackey: '7da2270ccfa49786e0115366d3a3d14d' });
|
||||
db.turnusers_lt.insert({ realm: 'crinna.org', name: 'whirrun', hmackey: '6972e85e51f36e53b0b61759c5a5219a' });
|
||||
db.turnusers_lt.insert({ realm: 'crinna.org', name: 'stranger-come-knocking', hmackey: 'd43cb678560259a1839bff61c19de15e' });
|
||||
|
||||
db.turnusers_st.insert({ name: 'ninefingers', password: 'youhavetoberealistic'});
|
||||
db.turnusers_st.insert({ name: 'gorst', password: 'hero'});
|
||||
db.turnusers_st.insert({ name: 'whirrun', password: 'sword'});
|
||||
db.turnusers_st.insert({ name: 'stranger-come-knocking', password: 'civilization'});
|
||||
|
||||
db.turn_secret.insert({ realm: 'north.gov', value: 'logen' });
|
||||
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: 'hoodless' });
|
||||
db.admin_user.insert({ name: 'bayaz', realm: '', password: 'magi' });
|
||||
|
||||
db.realm.insert({
|
||||
realm: 'north.gov',
|
||||
|
||||
+10
-20
@@ -1,5 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
# ninefingers:password: youhavetoberealistic
|
||||
# gorst:password: hero
|
||||
# whirrun:password: sword
|
||||
# stranger-come-knocking:password: civilization
|
||||
|
||||
redis-cli <<!
|
||||
|
||||
SELECT 2
|
||||
@@ -8,30 +13,12 @@ AUTH turn
|
||||
set turn/realm/north.gov/user/ninefingers/key "bc807ee29df3c9ffa736523fb2c4e8ee"
|
||||
set turn/realm/north.gov/user/gorst/key "7da2270ccfa49786e0115366d3a3d14d"
|
||||
|
||||
set turn/realm/north.gov/user/bethod/key "3b4125e139811b8577a214c24273fee27b15ff397631c7775b980785a229e6bd"
|
||||
|
||||
set turn/realm/crinna.org/user/whirrun/key "6972e85e51f36e53b0b61759c5a5219a"
|
||||
set turn/realm/crinna.org/user/stranger-come-knocking/key "d43cb678560259a1839bff61c19de15e"
|
||||
|
||||
set turn/realm/north.gov/user/ninefingers/password "youhavetoberealistic"
|
||||
set turn/realm/north.gov/user/gorst/password "hero"
|
||||
|
||||
set turn/realm/north.gov/user/bethod/password "king-of-north"
|
||||
|
||||
set turn/realm/crinna.org/user/whirrun/password "sword"
|
||||
set turn/realm/crinna.org/user/stranger-come-knocking/password "civilization"
|
||||
|
||||
sadd turn/realm/north.gov/secret "logen" "bloody9"
|
||||
sadd turn/realm/crinna.org/secret "north" "library"
|
||||
|
||||
set turn/user/ninefingers/password "youhavetoberealistic"
|
||||
set turn/user/gorst/password "hero"
|
||||
|
||||
set turn/user/bethod/password "king-of-north"
|
||||
|
||||
set turn/user/whirrun/password "sword"
|
||||
set turn/user/stranger-come-knocking/password "civilization"
|
||||
|
||||
set turn/realm/north.gov/max-bps 500000
|
||||
set turn/realm/north.gov/total-quota 12000
|
||||
set turn/realm/north.gov/user-quota 10000
|
||||
@@ -48,8 +35,11 @@ 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 Y2FybGVvbg== hkdf_hash_func 'SHA-256' as_rs_alg 'AES-256-CBC' auth_alg 'HMAC-SHA-256-128'
|
||||
hmset turn/oauth/kid/oldempire ikm_key YXVsY3Vz hkdf_hash_func 'SHA-256' as_rs_alg 'AEAD-AES-256-GCM'
|
||||
hmset turn/oauth/kid/north ikm_key 'Y2FybGVvbg==' hkdf_hash_func 'SHA-256' as_rs_alg 'AES-256-CBC' auth_alg 'HMAC-SHA-256-128'
|
||||
hmset turn/oauth/kid/oldempire ikm_key 'YXVsY3Vz' hkdf_hash_func 'SHA-256' as_rs_alg 'AEAD-AES-256-GCM'
|
||||
|
||||
hmset turn/admin_user/skarling realm 'north.gov' password 'hoodless'
|
||||
hmset turn/admin_user/bayaz password 'magi'
|
||||
|
||||
save
|
||||
|
||||
|
||||
@@ -4,13 +4,13 @@ insert into turnusers_lt (realm, name, hmackey) values('north.gov','gorst','7da2
|
||||
insert into turnusers_lt (realm, name, hmackey) values('crinna.org','whirrun','6972e85e51f36e53b0b61759c5a5219a');
|
||||
insert into turnusers_lt (realm, name, hmackey) values('crinna.org','stranger-come-knocking','d43cb678560259a1839bff61c19de15e');
|
||||
|
||||
insert into turnusers_st (name, password) values('ninefingers','youhavetoberealistic');
|
||||
insert into turnusers_st (name, password) values('gorst','hero');
|
||||
insert into turnusers_st (name, password) values('whirrun','sword');
|
||||
insert into turnusers_st (name, password) values('stranger-come-knocking','civilization');
|
||||
|
||||
insert into turn_secret (realm,value) values('north.gov','logen');
|
||||
insert into turn_secret (realm,value) values('north.gov','bloody9');
|
||||
insert into turn_secret (realm,value) values('crinna.org','north');
|
||||
insert into turn_secret (realm,value) values('crinna.org','library');
|
||||
|
||||
insert into admin_user (name, realm, password) values('skarling','north.gov','hoodless');
|
||||
insert into admin_user (name, realm, password) values('bayaz','','magi');
|
||||
|
||||
insert into turn_origin_to_realm (origin,realm) values('http://crinna.org:80','crinna.org');
|
||||
insert into turn_origin_to_realm (origin,realm) values('https://bligh.edu:443','crinna.org');
|
||||
|
||||
Reference in New Issue
Block a user