From 702b29bc22da6b6e441ed86ea059cbced5b123ac Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 20 Apr 2014 21:10:18 +0000 Subject: [PATCH 001/805] initial code import --- AUTHORS | 46 + ChangeLog | 970 ++++ INSTALL | 963 ++++ LICENSE | 31 + LICENSE.OpenSSL | 127 + Makefile.in | 173 + NOTE | 2 + README.turnadmin | 239 + README.turnserver | 880 ++++ README.turnutils | 329 ++ STATUS | 101 + TODO | 128 + configure | 1063 ++++ examples/etc/turn_client_cert.pem | 23 + examples/etc/turn_client_pkey.pem | 27 + examples/etc/turn_server_cert.pem | 22 + examples/etc/turn_server_pkey.pem | 27 + examples/etc/turnserver.conf | 589 +++ examples/etc/turnuserdb.conf | 23 + examples/scripts/basic/dos_attack.sh | 35 + examples/scripts/basic/relay.sh | 30 + examples/scripts/basic/tcp_client.sh | 27 + .../scripts/basic/tcp_client_c2c_tcp_relay.sh | 25 + examples/scripts/basic/udp_c2c_client.sh | 29 + examples/scripts/basic/udp_client.sh | 28 + examples/scripts/loadbalance/master_relay.sh | 38 + examples/scripts/loadbalance/slave_relay_1.sh | 37 + examples/scripts/loadbalance/slave_relay_2.sh | 37 + .../scripts/loadbalance/tcp_c2c_tcp_relay.sh | 29 + examples/scripts/loadbalance/udp_c2c.sh | 31 + .../longtermsecure/secure_dos_attack.sh | 49 + .../longtermsecure/secure_dtls_client.sh | 36 + .../longtermsecure/secure_dtls_client_cert.sh | 36 + .../scripts/longtermsecure/secure_relay.sh | 35 + .../longtermsecure/secure_relay_cert.sh | 38 + .../longtermsecure/secure_tcp_client.sh | 31 + .../secure_tcp_client_c2c_tcp_relay.sh | 31 + .../longtermsecure/secure_tls_client.sh | 34 + .../secure_tls_client_c2c_tcp_relay.sh | 35 + .../longtermsecure/secure_tls_client_cert.sh | 36 + .../scripts/longtermsecure/secure_udp_c2c.sh | 32 + .../longtermsecure/secure_udp_client.sh | 32 + .../secure_relay_with_db_mysql.sh | 34 + .../secure_relay_with_db_psql.sh | 37 + .../secure_relay_with_db_redis.sh | 37 + examples/scripts/mobile/mobile_dtls_client.sh | 36 + examples/scripts/mobile/mobile_relay.sh | 36 + examples/scripts/mobile/mobile_tcp_client.sh | 32 + .../mobile/mobile_tls_client_c2c_tcp_relay.sh | 36 + examples/scripts/mobile/mobile_udp_client.sh | 33 + examples/scripts/peer.sh | 16 + examples/scripts/readme.txt | 26 + .../scripts/restapi/secure_relay_secret.sh | 36 + .../secure_relay_secret_with_db_mysql.sh | 38 + .../secure_relay_secret_with_db_psql.sh | 38 + .../secure_relay_secret_with_db_redis.sh | 38 + .../restapi/secure_udp_client_with_secret.sh | 31 + .../restapi/shared_secret_maintainer.pl | 105 + examples/scripts/rfc5769.sh | 14 + .../selfloadbalance/secure_dos_attack.sh | 130 + .../scripts/selfloadbalance/secure_relay.sh | 42 + .../secure_relay_short_term_mech.sh | 37 + ...ure_tcp_client_c2c_tcp_relay_short_term.sh | 31 + .../secure_udp_client_short_term.sh | 30 + make-man.sh | 15 + man/man1/coturn.1 | 1 + man/man1/turnadmin.1 | 325 ++ man/man1/turnserver.1 | 1121 +++++ man/man1/turnutils.1 | 439 ++ man/man1/turnutils_peer.1 | 1 + man/man1/turnutils_stunclient.1 | 1 + man/man1/turnutils_uclient.1 | 1 + postinstall.txt | 35 + rpm/CentOS6.pre.build.sh | 98 + rpm/Fedora.pre.build.sh | 20 + rpm/build.instructions.txt | 43 + rpm/build.settings.sh | 14 + rpm/build.sh | 98 + rpm/common.pre.build.sh | 26 + rpm/epel.install.sh | 39 + rpm/turnserver.init.el | 82 + rpm/turnserver.service.fc | 15 + rpm/turnserver.spec | 358 ++ rpm/turnserver.sysconfig | 5 + rpm/uninstall.turnserver.sh | 19 + src/apps/common/apputils.c | 902 ++++ src/apps/common/apputils.h | 163 + src/apps/common/hiredis_libevent2.c | 383 ++ src/apps/common/hiredis_libevent2.h | 67 + src/apps/common/ns_turn_utils.c | 643 +++ src/apps/common/ns_turn_utils.h | 86 + src/apps/common/stun_buffer.c | 252 + src/apps/common/stun_buffer.h | 131 + src/apps/peer/mainudpserver.c | 102 + src/apps/peer/udpserver.c | 172 + src/apps/peer/udpserver.h | 76 + src/apps/relay/dtls_listener.c | 954 ++++ src/apps/relay/dtls_listener.h | 72 + src/apps/relay/libtelnet.c | 1545 ++++++ src/apps/relay/libtelnet.h | 677 +++ src/apps/relay/mainrelay.c | 2376 +++++++++ src/apps/relay/mainrelay.h | 361 ++ src/apps/relay/netengine.c | 1573 ++++++ src/apps/relay/ns_ioalib_engine_impl.c | 3654 ++++++++++++++ src/apps/relay/ns_ioalib_impl.h | 297 ++ src/apps/relay/ns_sm.h | 66 + src/apps/relay/tls_listener.c | 240 + src/apps/relay/tls_listener.h | 63 + src/apps/relay/turn_ports.c | 417 ++ src/apps/relay/turn_ports.h | 73 + src/apps/relay/turncli.c | 1261 +++++ src/apps/relay/turncli.h | 100 + src/apps/relay/userdb.c | 3595 ++++++++++++++ src/apps/relay/userdb.h | 222 + src/apps/rfc5769/rfc5769check.c | 405 ++ src/apps/stunclient/stunclient.c | 466 ++ src/apps/uclient/mainuclient.c | 532 ++ src/apps/uclient/session.h | 132 + src/apps/uclient/startuclient.c | 1548 ++++++ src/apps/uclient/startuclient.h | 85 + src/apps/uclient/uclient.c | 1433 ++++++ src/apps/uclient/uclient.h | 110 + src/client++/TurnMsgLib.h | 1195 +++++ src/client/ns_turn_ioaddr.c | 477 ++ src/client/ns_turn_ioaddr.h | 108 + src/client/ns_turn_msg.c | 1561 ++++++ src/client/ns_turn_msg.h | 213 + src/client/ns_turn_msg_addr.c | 183 + src/client/ns_turn_msg_addr.h | 51 + src/client/ns_turn_msg_defs.h | 160 + src/ns_turn_defs.h | 184 + src/server/ns_turn_allocation.c | 694 +++ src/server/ns_turn_allocation.h | 235 + src/server/ns_turn_ioalib.h | 274 + src/server/ns_turn_khash.h | 391 ++ src/server/ns_turn_maps.c | 1122 +++++ src/server/ns_turn_maps.h | 268 + src/server/ns_turn_maps_rtcp.c | 259 + src/server/ns_turn_maps_rtcp.h | 89 + src/server/ns_turn_server.c | 4407 +++++++++++++++++ src/server/ns_turn_server.h | 211 + src/server/ns_turn_session.h | 168 + turndb/schema.sql | 41 + turndb/schema.stats.redis | 38 + turndb/schema.userdb.redis | 132 + turndb/testredisdbsetup.sh | 43 + turndb/testsqldbsetup.sql | 29 + 147 files changed, 47950 insertions(+) create mode 100644 AUTHORS create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 LICENSE create mode 100644 LICENSE.OpenSSL create mode 100755 Makefile.in create mode 100644 NOTE create mode 100644 README.turnadmin create mode 100644 README.turnserver create mode 100644 README.turnutils create mode 100644 STATUS create mode 100644 TODO create mode 100755 configure create mode 100644 examples/etc/turn_client_cert.pem create mode 100644 examples/etc/turn_client_pkey.pem create mode 100644 examples/etc/turn_server_cert.pem create mode 100644 examples/etc/turn_server_pkey.pem create mode 100644 examples/etc/turnserver.conf create mode 100644 examples/etc/turnuserdb.conf create mode 100755 examples/scripts/basic/dos_attack.sh create mode 100755 examples/scripts/basic/relay.sh create mode 100755 examples/scripts/basic/tcp_client.sh create mode 100755 examples/scripts/basic/tcp_client_c2c_tcp_relay.sh create mode 100755 examples/scripts/basic/udp_c2c_client.sh create mode 100755 examples/scripts/basic/udp_client.sh create mode 100755 examples/scripts/loadbalance/master_relay.sh create mode 100755 examples/scripts/loadbalance/slave_relay_1.sh create mode 100755 examples/scripts/loadbalance/slave_relay_2.sh create mode 100755 examples/scripts/loadbalance/tcp_c2c_tcp_relay.sh create mode 100755 examples/scripts/loadbalance/udp_c2c.sh create mode 100755 examples/scripts/longtermsecure/secure_dos_attack.sh create mode 100755 examples/scripts/longtermsecure/secure_dtls_client.sh create mode 100755 examples/scripts/longtermsecure/secure_dtls_client_cert.sh create mode 100755 examples/scripts/longtermsecure/secure_relay.sh create mode 100755 examples/scripts/longtermsecure/secure_relay_cert.sh create mode 100755 examples/scripts/longtermsecure/secure_tcp_client.sh create mode 100755 examples/scripts/longtermsecure/secure_tcp_client_c2c_tcp_relay.sh create mode 100755 examples/scripts/longtermsecure/secure_tls_client.sh create mode 100755 examples/scripts/longtermsecure/secure_tls_client_c2c_tcp_relay.sh create mode 100755 examples/scripts/longtermsecure/secure_tls_client_cert.sh create mode 100755 examples/scripts/longtermsecure/secure_udp_c2c.sh create mode 100755 examples/scripts/longtermsecure/secure_udp_client.sh create mode 100755 examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh create mode 100755 examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh create mode 100755 examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh create mode 100755 examples/scripts/mobile/mobile_dtls_client.sh create mode 100755 examples/scripts/mobile/mobile_relay.sh create mode 100755 examples/scripts/mobile/mobile_tcp_client.sh create mode 100755 examples/scripts/mobile/mobile_tls_client_c2c_tcp_relay.sh create mode 100755 examples/scripts/mobile/mobile_udp_client.sh create mode 100755 examples/scripts/peer.sh create mode 100644 examples/scripts/readme.txt create mode 100755 examples/scripts/restapi/secure_relay_secret.sh create mode 100755 examples/scripts/restapi/secure_relay_secret_with_db_mysql.sh create mode 100755 examples/scripts/restapi/secure_relay_secret_with_db_psql.sh create mode 100755 examples/scripts/restapi/secure_relay_secret_with_db_redis.sh create mode 100755 examples/scripts/restapi/secure_udp_client_with_secret.sh create mode 100755 examples/scripts/restapi/shared_secret_maintainer.pl create mode 100755 examples/scripts/rfc5769.sh create mode 100755 examples/scripts/selfloadbalance/secure_dos_attack.sh create mode 100755 examples/scripts/selfloadbalance/secure_relay.sh create mode 100755 examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh create mode 100755 examples/scripts/shorttermsecure/secure_tcp_client_c2c_tcp_relay_short_term.sh create mode 100755 examples/scripts/shorttermsecure/secure_udp_client_short_term.sh create mode 100755 make-man.sh create mode 120000 man/man1/coturn.1 create mode 100644 man/man1/turnadmin.1 create mode 100644 man/man1/turnserver.1 create mode 100644 man/man1/turnutils.1 create mode 120000 man/man1/turnutils_peer.1 create mode 120000 man/man1/turnutils_stunclient.1 create mode 120000 man/man1/turnutils_uclient.1 create mode 100644 postinstall.txt create mode 100755 rpm/CentOS6.pre.build.sh create mode 100755 rpm/Fedora.pre.build.sh create mode 100644 rpm/build.instructions.txt create mode 100755 rpm/build.settings.sh create mode 100755 rpm/build.sh create mode 100755 rpm/common.pre.build.sh create mode 100755 rpm/epel.install.sh create mode 100644 rpm/turnserver.init.el create mode 100644 rpm/turnserver.service.fc create mode 100644 rpm/turnserver.spec create mode 100644 rpm/turnserver.sysconfig create mode 100755 rpm/uninstall.turnserver.sh create mode 100644 src/apps/common/apputils.c create mode 100644 src/apps/common/apputils.h create mode 100644 src/apps/common/hiredis_libevent2.c create mode 100644 src/apps/common/hiredis_libevent2.h create mode 100644 src/apps/common/ns_turn_utils.c create mode 100644 src/apps/common/ns_turn_utils.h create mode 100644 src/apps/common/stun_buffer.c create mode 100644 src/apps/common/stun_buffer.h create mode 100644 src/apps/peer/mainudpserver.c create mode 100644 src/apps/peer/udpserver.c create mode 100644 src/apps/peer/udpserver.h create mode 100644 src/apps/relay/dtls_listener.c create mode 100644 src/apps/relay/dtls_listener.h create mode 100644 src/apps/relay/libtelnet.c create mode 100644 src/apps/relay/libtelnet.h create mode 100644 src/apps/relay/mainrelay.c create mode 100644 src/apps/relay/mainrelay.h create mode 100644 src/apps/relay/netengine.c create mode 100644 src/apps/relay/ns_ioalib_engine_impl.c create mode 100644 src/apps/relay/ns_ioalib_impl.h create mode 100644 src/apps/relay/ns_sm.h create mode 100644 src/apps/relay/tls_listener.c create mode 100644 src/apps/relay/tls_listener.h create mode 100644 src/apps/relay/turn_ports.c create mode 100644 src/apps/relay/turn_ports.h create mode 100644 src/apps/relay/turncli.c create mode 100644 src/apps/relay/turncli.h create mode 100644 src/apps/relay/userdb.c create mode 100644 src/apps/relay/userdb.h create mode 100644 src/apps/rfc5769/rfc5769check.c create mode 100644 src/apps/stunclient/stunclient.c create mode 100644 src/apps/uclient/mainuclient.c create mode 100644 src/apps/uclient/session.h create mode 100644 src/apps/uclient/startuclient.c create mode 100644 src/apps/uclient/startuclient.h create mode 100644 src/apps/uclient/uclient.c create mode 100644 src/apps/uclient/uclient.h create mode 100644 src/client++/TurnMsgLib.h create mode 100644 src/client/ns_turn_ioaddr.c create mode 100644 src/client/ns_turn_ioaddr.h create mode 100644 src/client/ns_turn_msg.c create mode 100644 src/client/ns_turn_msg.h create mode 100644 src/client/ns_turn_msg_addr.c create mode 100644 src/client/ns_turn_msg_addr.h create mode 100644 src/client/ns_turn_msg_defs.h create mode 100644 src/ns_turn_defs.h create mode 100644 src/server/ns_turn_allocation.c create mode 100644 src/server/ns_turn_allocation.h create mode 100644 src/server/ns_turn_ioalib.h create mode 100644 src/server/ns_turn_khash.h create mode 100644 src/server/ns_turn_maps.c create mode 100644 src/server/ns_turn_maps.h create mode 100644 src/server/ns_turn_maps_rtcp.c create mode 100644 src/server/ns_turn_maps_rtcp.h create mode 100644 src/server/ns_turn_server.c create mode 100644 src/server/ns_turn_server.h create mode 100644 src/server/ns_turn_session.h create mode 100644 turndb/schema.sql create mode 100644 turndb/schema.stats.redis create mode 100644 turndb/schema.userdb.redis create mode 100755 turndb/testredisdbsetup.sh create mode 100755 turndb/testsqldbsetup.sql diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..6b8ea91c --- /dev/null +++ b/AUTHORS @@ -0,0 +1,46 @@ +Oleg Moskalenko : + General design and implementation + (2011-2013); + +Gabor Kovesdan, http://kovesdan.org : + FreeBSD packaging + (since v1.5.2.6); + +Daniel Pocock, http://danielpocock.com : + Debian packaging + (since v1.8.3.6); + +John Selbie (jselbie@gmail.com) : + Stuntman interoperability, RFC5780 fixes + MS Windows port work + (since v1.8.3.6); + +Lee Sylvester : + Status and statistics - ideas and pilot implementation + (since v1.8.4.0); + +Erik Johnston : + Access Control Lists, 2013 + (since v1.8.5.0); + +Roman Lisagor : + Testing, code optimization + (since v1.8.6.0); + +Vladimir Tsanev : + configure script and Makefile fixes, + Arch Linux port + (since v1.8.6.1); + +Po-sheng Lin : + Libevent dependencies cleaning + (since v2.0.1.1); + +Peter Dunkley : + CentOS/Fedora port + (since v2.6.6.1) + +Mutsutoshi Yoshimoto + TCP routing: testing and bug fixes + (since v3.2.2.7) + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 00000000..fc896c1e --- /dev/null +++ b/ChangeLog @@ -0,0 +1,970 @@ +04/20/2014 Oleg Moskalenko +Version 3.3.0.0 'Threetrees': + - multi-tenant server. + +04/13/2014 Oleg Moskalenko +Version 3.2.3.6 'Marshal West': + - Addresses logging fixed. + - Redis admin options fixed. + - Redis compilation cleaned. + +04/07/2014 Oleg Moskalenko +Version 3.2.3.5 'Marshal West': + - Mobile allocation quota fixed (issue 121); + - --simple-log option added (Issue 122); + - documentation fixes (REST API, Redis). + +04/06/2014 Oleg Moskalenko +Version 3.2.3.4 'Marshal West': + - Mobile TCP sessions fixed (issue 120); + - log information improvements. + +04/04/2014 Oleg Moskalenko +Version 3.2.3.3 'Marshal West': + - Pkey and cert file descriptors to be closed + on initialization (issue 118); + - Address bind indefinite cycle on start-up fixed + (Issue 119); + - Allocation counters time lag improved. + +03/30/2014 Oleg Moskalenko +Version 3.2.3.2 'Marshal West': + - Allocation counters fixed (issue 117); + - a possible core dump in the server code fixed; + - a possible memory leak in server fixed. + +03/29/2014 Oleg Moskalenko +Version 3.2.3.1 'Marshal West': + - TCP congestion avoidance completed. + - Read and write streams are treated separately in + bandwidth control. + - Test client fixed. + - Experimental SHA256 key storage supported. + +03/17/2014 Oleg Moskalenko +Version 3.2.2.912 'Marshal West': + - TCP-in-TCP congestion avoidance implemented. + - UDP-in-TCP congestion avoidance improved. + - Alternate-server code cleaned. + +03/10/2014 Oleg Moskalenko +Version 3.2.2.911 'Marshal West': + - "Congestion control" for UDP-inside-TCP tunneling; + - memory management improvements; + - socket logging improvements; + - debug info added to CentOS and Fedora RPMs; + - TCP traffic buffering improved; + - Thread barriers cleaned; + - TCP memory leak fixed; + - minor TCP test client improvement. + +03/09/2014 Oleg Moskalenko +Version 3.2.2.910 'Marshal West': + - Log messages extended and cleaned. + - Some memory cleaning. + +03/02/2014 Oleg Moskalenko +Version 3.2.2.9 'Marshal West': + - Issue 113 fixed (TCP rate limit fixed); + - Issue 114 fixed (TCP stability). + +02/18/2014 Oleg Moskalenko +Version 3.2.2.8 'Marshal West': + - Issue 102: SO_BSDCOMPAT socket option removed; + - Issue 104: check for the REALM attribute value; + - Issue 105: no-cli segfault fixed; + - Issue 106: MESSAGE-INTEGRITY removed from DATA indication; + - Issue 108: Server should return 438 on unknown nonce; + - Issue 109: make the random functions stronger (mostly for + transaction ID and for nonce); + - Issue 111: fix valgrind warning on memory initialization. + - Issue 112: RTCP sockets logging. + +02/12/2014 Oleg Moskalenko +Version 3.2.2.7 'Marshal West': + - Possible indefinite cycle fixed in TCP/TCP routing (Issue 99); + - Address 0.0.0.0 can be used as a listener address (Issue 100); + - DHCP-configured servers supported (Issue 101); + +02/04/2014 Oleg Moskalenko +Version 3.2.2.6 'Marshal West': + - Channel traffic memory copy elimination. + - Send indication memory copy elimination. + - DTLS traffic processing memory copy eliminated. + - Mobility forbidden error code number fixed - according to the new draft document. + - getsockname() usage minimized. + - port allocation improved. + - default relay behavior fixed (when no relay addresses defined). + - atomic create permission request handling (Issue 97). + +01/25/2014 Oleg Moskalenko +Version 3.2.2.5 'Marshal West': + - code optimization. + +01/24/2014 Oleg Moskalenko +Version 3.2.2.4 'Marshal West': + - HMAC key handling fixed (Issue 96). + +01/23/2014 Oleg Moskalenko +Version 3.2.2.3 'Marshal West': + - Security fix (issue 95). + - Default "implicit" relay IP allocation policy is more usable + (issue 94 fixed). + - SSLv2 fixed (for those who are still using it) + (issue 93 fixed). + - Cosmetic changes. + +01/19/2014 Oleg Moskalenko +Version 3.2.2.1 'Marshal West': + - CPU/memory cache optimization (memory locality). + - torture tests enhanced. + - stability fixes. + - minor possible memory leak fix. + - new TLS options: --no-sslv2, --no-sslv3, --no-tlsv1, + --no-tlsv1_1, --no-tlsv1_2 + +01/06/2014 Oleg Moskalenko +Version 3.2.1.4 'Marshal West': + - Linux epoll performance improvements. + - DTLS minor fix. + +01/06/2014 Oleg Moskalenko +Version 3.2.1.3 'Marshal West': + - Telnet client added to installation when necessary. + +01/05/2014 Oleg Moskalenko +Version 3.2.1.2 'Marshal West': + - Config file adjusted for DragonFly. + +01/03/2014 Oleg Moskalenko +Version 3.2.1.1 'Marshal West': + - Minor TLS fix. + - Default cipher list is DEFAULT now. + +12/26/2013 Oleg Moskalenko +Version 3.2.1.0 'Marshal West': + - Optimized TCP network engine for Linux 3.9+. + - Security fix: DH and ECDH temporary keys are now + regenerated for each TLS or DTLS session. + - Fix for systems with multiple CPU cores (more than 128). + - DH TLS key now can be configured as 566, 1066 (default) or 2066 bits. + - DH TLS key can be taken from a PEM file. + - Issue 91 (test client crash) fixed. + - Configurable net engine type. + +12/25/2013 Oleg Moskalenko +Version 3.1.6.0 'Arch Lector': + - Timers optimization: linked list timers structure + for often-used intervals. + +12/23/2013 Oleg Moskalenko +Version 3.1.5.3 'Arch Lector': + - HTTP "keep-alive" support improved. + - TCP channel "fortification". + +12/19/2013 Oleg Moskalenko +Version 3.1.5.1 'Arch Lector': + - Private key password allowed for encrypted keys. + - HTTP "keep-alive" supported. + - "psd" CLI command added (ps dump to file). + +12/18/2013 Oleg Moskalenko +Version 3.1.4.2 'Arch Lector': + - Time functions optimization. + - Online changes to the alternate servers list thru telnet CLI. + - Certificate chain files allowed. + +12/13/2013 Oleg Moskalenko +Version 3.1.3.1 'Arch Lector': + - "Start time" ps command info added. + - Protocol option added to "pu" command. + - "Delete allocation" debug message fixed. + - "Allocation id" debug info message fixed. + - RFC6062 usage statistics fixed. + - Info/Debug messages cleaned. + +12/11/2013 Oleg Moskalenko +Version 3.1.2.3 'Arch Lector': + - CentOS 6 package fixed. + +12/10/2013 Oleg Moskalenko +Version 3.1.2.2 'Arch Lector': + - ps output typo fixed (TLS params). + - configurable EC curve name. + - CLI TLS-related information extended. + - "print users" (pu) CLI command added. + +12/09/2013 Oleg Moskalenko +Version 3.1.2.1 'Arch Lector': + - DH cipher suites basic implementation. + - Elliptic Curve cipher suites basic implementation. + - RFC 6062 crash fixed. + - More CLI parameters added. + - Redis allocation statistics fixed. + - Number of cli max session lines configurable. + - uclient cipher suite configurable. + +12/08/2013 Oleg Moskalenko +Version 3.1.1.0 'Arch Lector': + - Telnet CLI. + - RFC 6062 internal messaging fixed. + - Server relay endpoints (a non-standard feature). + - "atomic line" stdout log print. + - printed help minor fix. + - client program does not necessary + require certificate for TLS. + - docs fixes. + - allocation quota bug fixed. + +11/29/2013 Oleg Moskalenko +Version 3.0.2.1 'Practical Frost': + - TCP stability fixes. + - RFC 6062 "first packet(s)" bug fixed. + - RFC 6062 stability fixes. + - Multithreaded Mobile ICE. + +11/28/2013 Oleg Moskalenko +Version 3.0.1.4 'Practical Frost': + - CentOS/Fedora packaging fixed. + - PID file fixed. + +11/26/2013 Oleg Moskalenko +Version 3.0.1.3 'Practical Frost': + - Misc cosmetic changes. + - CentOS/Fedora packaging fixed. + +11/25/2013 Oleg Moskalenko +Version 3.0.1.2 'Practical Frost': + - Mobility draft implemented. + - DTLS communications fixes. + - UDP Linux optimization. + - Log output time starts with 0. + - A new "drop root privileges" options: + --proc-user and --proc-group added. + - SHA256 agility updated: 426 error code on too weak SHA function. + - "-m 0" and "-m 1" options improved. + - non-threading environment support dropped. + - stability fixes. + - OpenSUSE support added. + +11/10/2013 Oleg Moskalenko +Version 3.0.0.0 'Practical Frost': + - New network engine for Linux kernel 3.9+. + +11/08/2013 Oleg Moskalenko +Version 2.6.7.2 'Harding Grim': + - SHA256 agility updated: 441 error code on too weak SHA function. + +11/07/2013 Oleg Moskalenko +Version 2.6.7.1 'Harding Grim': + - CentOS / Fedora uninstall script. + - Debian compilation error fixed. + - OpenSSL 0.9.7 and earlier build fixed. + - NetBSD build fixed. + +11/03/2013 Oleg Moskalenko , + Peter Dunkley +Version 2.6.7.0 'Harding Grim': + - CentOS 6 pre-compiled distribution. + - Fedora pre-compiled distribution. + - TURN_NO_TLS case compilation cleaning. + - Text files cleaning. + - Issue 68 fixed (no-stun option added). + +10/27/2013 Oleg Moskalenko +Version 2.6.6.1 'Harding Grim': + - SHA256 added as a non-standard message integrity option. + - CentOS rpm specs added. + - Peter Dunkley added to the authors list. + +10/20/2013 Oleg Moskalenko +Version 2.6.6.0 'Harding Grim': + - Cygwin loopback relay interfaces fixed (Issue 62). + - rpath added to the Makefile (Issue 63). + - CONFLICTS added to FreeBSD port Makefile (Issue 64). + - Certificate check options, for server and for the test client (Issue 65). + - Some compilation cleaning. + +10/09/2013 Oleg Moskalenko +Version 2.6.5.2 'Harding Grim': + - Documentation changes. + - Redis-related memory leak fixed (Issue 61). + +09/25/2013 Oleg Moskalenko +Version 2.6.4.1 'Harding Grim': + - Crash on uninitialized redis db name is fixed (Issue 59). + - Optional authentication of STUN Binding request is implemented (Issue 60). + +09/16/2013 Oleg Moskalenko +Version 2.6.3.1 'Harding Grim': + - Issue 58: support changing white/black IP lists while server is running. + database tables (keys for redis) added for that new functionality. + +09/03/2013 Oleg Moskalenko +Version 2.6.2.2 'Harding Grim': + - Issue 52: RFC 6062 relay endpoints connection process + fixed for Linux pre-3.9 kernel. + +09/03/2013 Oleg Moskalenko +Version 2.6.2.1 'Harding Grim': + - UDP performance improvements. + - Issue 56: DTLS scaleability improvements. + - Issue 55: DTLS support in Cygwin. + - Issue 57: --pidfile option + - Issue 52: RFC 6062 relay endpoints connection process fixed. + - Issue 53: Fingerprints added to the indications. + - Issue 54: Long-term credentials mechanism integrity and software attributes + added to the indications. + +08/11/2013 Oleg Moskalenko +Version 2.6.1.4 'Harding Grim': + - UDP memory leak fixed. + +08/11/2013 Oleg Moskalenko +Version 2.6.1.3 'Harding Grim': + - DTLS crash fix. + +08/10/2013 Oleg Moskalenko +Version 2.6.1.2 'Harding Grim': + - TLS buffer decreased to avoid memory problems. + - TLS BIO object fix. + - UDP socket open/reopen process fixed. + +08/08/2013 Oleg Moskalenko +Version 2.6.1.1 'Harding Grim': + - Network optimization: + * "pure" UDP setup optimized (when no DTLS configured); + * Auxiliary listening endpoints (configured by + --aux-server=). + * --udp-self-balance option to balance the UDP traffic + among the aux endpoints (for clients supporting + 300 ALTERNATE-SERVER response). + - Security improvements: + * no authentication required on the load balancer server (Issue 50). + * REST API improvement: + = --secret-ts-exp-time option deprecated; + = In REST API timestamp, we are now using + the expiration time (Issue 31). + * Configurable cipher suite in the TURN server. + * SSL3 support. + * TLS 1.1 and 1.2 support. + * SSL2 "encapsulation" mode support. + * NULL OpenSSL cipher is allowed to be negotiated between + server and client. + * -U option (NULL cipher) added to the test client. + * DTLS crash fixed on overload. + - STUN enhancements and fixes: + * Classic STUN transaction ID fixed (Issue 48). + * Classic STUN attribute ERROR fixed (Issue 49). + * Unused RFC 5780 functionality removed from TCP, TLS and DTLS relays. + * resources optimization for stun-only: short connection expiration time. + +07/26/2013 Oleg Moskalenko , + Vladimir Tsanev +Version 2.5.2.1 'Shivers': + - log file placement changes. + - Base64 encode/decode memory initialization fix. + +07/23/2013 Oleg Moskalenko , + Po-sheng Lin +Version 2.5.1.2 'Shivers': + - getopt fix in client test programs. + - cosmetic changes. + - allow anonymous alternate-server functionality. + +07/21/2013 Oleg Moskalenko +Version 2.5.1.1 'Shivers': + - Improved "split" network engine: + two different threading models for TCP and UDP. + - DTLS crash fixed. + - Multithreading with Cygwin. + +07/20/2013 Oleg Moskalenko +Version 2.1.3.1 'Shivers': + - DTLS improvements for DOS attacks + - deeper optimization for DOS attack (mostly for Linux) + +07/19/2013 Oleg Moskalenko +Version 2.1.2.0 'Shivers': + - deeper optimization for DOS attack (mostly for Linux) + +07/18/2013 Oleg Moskalenko , + Po-sheng Lin +Version 2.1.1.1 'Shivers': + - udp fixes. + - Makefile cleaning. + - Dependencies cleaning. + - DOS attack client emulation. + - DOS attack defense logic added to the server. + +07/14/2013 Oleg Moskalenko +Version 2.0.0.0 'Shivers': + - new networking engine: + - scalable UDP socket model. + - multithreaded TCP relay implemented. + - race condition fixed in authentication of TCP sessions. + - Cygwin "port" fixed. + +06/23/2013 Oleg Moskalenko , + Vladimir Tsanev +Version 1.8.7.0 'Black Dow': + + - Added support for obsolete "classic" STUN RFC 3489; + - Full TURN support for Cygwin implemented: MS-Win UDP sockets fixed; + - Relay threads number changed; + - Fedora warnings fixed; + - turndb/testdbsetup.sh example file added; + - Multiple Makefile and ./configure script fixes implemented: + * Changes taken from Arch Linux port; + * Manpages installation and deinstallation; + * rfc5769check utility removed from installation, it is used for the + compilation result test only and makes no sense for the end user; + * "--parameter" format support in ./configure script; it allows + simpler native OS package definitions (like in Debian package); + * Mac OS X linking warnings removed. + * pthread test fixed. + +06/08/2013 Oleg Moskalenko +Version 1.8.6.3 'Black Dow': + + - DONT-FRAGMENT flag removed on UDP listening (clients-facing) sockets. + - UDP fix for Cygwin only: UDP channels work fine now. + - docs fixes. + +06/06/2013 Oleg Moskalenko +Version 1.8.6.2 'Black Dow': + + - Just cosmetic re-packaging for Debian, tarball warnings removed. + +06/05/2013 Oleg Moskalenko +Version 1.8.6.1 'Black Dow': + + - Peer permissions bug fixed. + +06/03/2013 Oleg Moskalenko +Version 1.8.6.0 'Black Dow': + + - Optimization. + - Mac OS X compilation fixes. + +06/01/2013 Oleg Moskalenko +Version 1.8.5.4 'Black Dow': + + - Issues 29 and 30 fixed (channels padding). + - minor fixes. + - Mac OS X compilation fixes. + - Cygwin-related compilation fixes and INSTALL additions. + +05/31/2013 Oleg Moskalenko +Version 1.8.5.3 'Black Dow': + + - REST API extra script example and docs extention. + +05/26/2013 Oleg Moskalenko +Version 1.8.5.1 'Black Dow': + + - Config file parsing fixed (Issue 28) + +05/20/2013 Oleg Moskalenko , + Erik Johnston +Version 1.8.5.0 'Black Dow': + + - IP access control lists. + - log file name fix. + - alt-* ports default behavior changed. + - "passive TCP" option in uclient. + +05/18/2013 Oleg Moskalenko +Version 1.8.4.5 'Black Dow': + + - socket conditions cleaned (SIGPIPE, etc) + +05/17/2013 Oleg Moskalenko +Version 1.8.4.4 'Black Dow': + + - configuration and installation adjusted for: + - NetBSD; + - Solaris; + - OpenBSD; + - Screen messages fixed; + - code security fixes. + +05/15/2013 Oleg Moskalenko +Version 1.8.4.3 'Black Dow': + + - Compilation warning removed. + - Log file fixed (Issue 26) + +05/15/2013 Oleg Moskalenko +Version 1.8.4.2 'Black Dow': + + - repackaging for Debian compliance. Docs separated. + +05/14/2013 Oleg Moskalenko +Version 1.8.4.1 'Black Dow': + + - Cosmetics (docs, warnings, etc). + - More complex case of TURN-server-behind-NAT is implemented, + when multiple public-ip/private-ip mappings are involved. + +05/13/2013 Oleg Moskalenko +Version 1.8.4.0 'Black Dow': + + - Redis DB support added. + - Crash on help text fixed. + - Max allocation time can be changed in the command-line or + in the config file. + +05/09/2013 Oleg Moskalenko +Version 1.8.3.9 'Black Dow': + + - No changes - just the tarball is repackaged for Debian compatibility. + +05/07/2013 Oleg Moskalenko +Version 1.8.3.8 'Black Dow': + + - multicast and loopback addresses disallow options added. + - option to direct all log messages to the system log (syslog). + +05/02/2013 Oleg Moskalenko +Version 1.8.3.7 'Black Dow': + + - Allocation status log. + +05/01/2013 Oleg Moskalenko +Version 1.8.3.6 'Black Dow': + + - Stuntman client interoperability fixed. + - Manpages installation fixed. + +04/30/2013 Oleg Moskalenko +Version 1.8.3.5 'Black Dow': + + - Lintian fixes. + +04/27/2013 Oleg Moskalenko +Version 1.8.3.4 'Black Dow': + + - Installation fixes. + +04/26/2013 Oleg Moskalenko +Version 1.8.3.3 'Black Dow': + + - Log file midnight rollover implemented (Issue 15). + +04/25/2013 Oleg Moskalenko +Version 1.8.3.1 'Black Dow': + + - Configurable REST API separator symbol (Issue 16). + - Stale Nonce bug fixed (Issue 17). + - Minor client fix. + +04/21/2013 Oleg Moskalenko +Version 1.8.3.0 'Black Dow': + + - STUN stand-alone functionality improved according to RFC 5389. + - ALTERNATE-SERVER implemented as "light" load balancing feature. + - stun-only option implemented. + - scripts directory reorganized. + +04/19/2013 Oleg Moskalenko +Version 1.8.2.1 'Black Dow': + + - Misc docs fixes. + +04/13/2013 Oleg Moskalenko +Version 1.8.2.0 'Black Dow': + + - Multiple database shared secrets supported for REST API. + - Added support for some OpenSSL FIPS versions (like openssl 0.9.8e-fips-rhel5). + +04/13/2013 Oleg Moskalenko +Version 1.8.1.3 'Black Dow': + + - Maintenance (docs, etc). + - Added partial support for Cygwin. Only TCP & TLS protocols + are support for client-to-server communications (as in RFC 5766 and + RFC 6062). UDP supported only for relay communications. DTLS is not + supported at all. The problem is in Winsock UDP sockets implementation. + +04/11/2013 Oleg Moskalenko +Version 1.8.1.2 'Black Dow': + + - Work on configuration and build. + +04/9/2013 Oleg Moskalenko +Version 1.8.1.1 'Black Dow': + + - Docs improvements. + - Load balancing use case added to TurnNetworks.pdf. + - Verbose mode split into 'normal' and 'extra' modes. + - Logging extended and fixed. + +04/7/2013 Oleg Moskalenko +Version 1.8.1.0 'Black Dow': + + - Compilation flags improved. + - utility programs renamed and moved to bin/ directory. + - README and turnserver man page separated into three sections - + turnserver, turnadmin, turnutils. + +04/6/2013 Oleg Moskalenko +Version 1.8.0.6 'Black Dow': + + - Added option "--psql-userdb" for better visual separation + between PostgreSQL and MySQL stuff. + - turnadmin flat files handling fixed. + - added set/show commands to turnadmin for secret key. + +04/6/2013 Oleg Moskalenko +Version 1.8.0.5 'Black Dow': + + - turnadmin MySQL connection fixed. + - minor cosmetic changes. + - Added "list" commands for long-term and short-term users, + to turnadmin. + +04/5/2013 Oleg Moskalenko +Version 1.8.0.4 'Black Dow': + + - Minor compilation fixes. + - Minor docs fixes. + - "connect_timeout" option support for MySQL. + +04/5/2013 Oleg Moskalenko +Version 1.8.0.3 'Black Dow': + + - Issue 11 (secret timestamp check) fixed. + +04/4/2013 Oleg Moskalenko +Version 1.8.0.2 'Black Dow': + + - TCP sockets flush removed. + - rfc5769check utility removed from the Makefile. + +04/4/2013 Oleg Moskalenko +Version 1.8.0.1 'Black Dow': + + - Some short-term auth problems fixed. + - rfc5769check utility added to the Makefile and upgraded. + +04/3/2013 Oleg Moskalenko +Version 1.8.0.0 'Black Dow': + + - Short-term credentials mechanism implemented. + +04/2/2013 Oleg Moskalenko +Version 1.7.3.1 'Superior Glokta': + + - Listeners code cleaned. + - The default number of extra relay threads changes from 0 to 1. + +04/1/2013 Oleg Moskalenko +Version 1.7.3.0 'Superior Glokta': + + - Issue 10 fixed: log file control options. + Two options added: --no-stdout-log and --log-file. + +03/29/2013 Oleg Moskalenko +Version 1.7.2.0 'Superior Glokta': + + - Issue 9 fixed (uclient). + - Secret-based authentication implemented (see TURNServerRESTAPI.pdf). + - Uclient docs fixed. + - database schema extended (table for the secret added). + +03/27/2013 Oleg Moskalenko +Version 1.7.1.2 'Superior Glokta': + + - CHANNEL BIND request handling fixed: now it produces an error + when client is trying to tie the same peer address to + different channels. + - uclient and peer test apps upgraded so that RTP channels + are talking to and RTCP channels are talking + to in client-to-peer communication patterns. + - compilation warning is fixed when MySQL is not used. + +03/27/2013 Oleg Moskalenko +Version 1.7.1.1 'Superior Glokta': + + - CONNECT response fixed in RFC 6062. + - uclient checks server responses integrity. + +03/26/2013 Oleg Moskalenko +Version 1.7.1.0 'Superior Glokta': + + - MySQL support added for the user keys repository. + - PostgreSQL support improved. + - Docs fixed. + - 64 bits platform fixes. + +03/23/2013 Oleg Moskalenko +Version 1.7.0.0 'Glokta': + + - Authentication fix. + - PostgreSQL database can be used as the user keys repository. + +03/21/2013 Oleg Moskalenko +Version 1.6.1.3 'Whirrun': + + - UDP segmentation fault fixed + +03/21/2013 Oleg Moskalenko +Version 1.6.1.2 'Whirrun': + + - RFC 6062 fix + +03/21/2013 Oleg Moskalenko +Version 1.6.1.1 'Whirrun': + + - Authentication error fixed + +03/19/2013 Oleg Moskalenko +Version 1.6.1.0 'Whirrun': + + - --stale-nonce option + - working on userdb + - "hang on" option fixed in uclient + +03/18/2013 Oleg Moskalenko +Version 1.6.0.2 'Whirrun': + + - working on userdb + - c++ compilation fix + +03/17/2013 Oleg Moskalenko +Version 1.6.0.1 'Whirrun': + + - uclient performance improved + - TurnNetworks.pdf document added + +03/15/2013 Oleg Moskalenko +Version 1.6.0.0 'Whirrun': + + - "Pure" TCP relaying (RFC 6062) implemented. + - Network interactions fixes. + - RFC 6062 test scripts added. + +03/03/2013 Oleg Moskalenko +Version 1.5.2.8 'Iosiv Lestek': + + - authorization processing improvements. + - peer application fixed. + - some ICE attributes added. + +02/27/2013 Oleg Moskalenko +Version 1.5.2.7 'Iosiv Lestek': + + - authorization processing improvements + - Issue 4 fixed. + - secure client-to-client script added + +02/22/2013 Oleg Moskalenko +Version 1.5.2.6 'Iosiv Lestek': + + - strcpy/strncpy fixed + - some screen messages fixed + - uclient statistics fixed + - software attribute fixed + - example scripts fixed + +02/16/2013 Oleg Moskalenko +Version 1.5.2.5 'Lestek': + + - uclient application fixed + - Docs fixes + +02/14/2013 Oleg Moskalenko +Version 1.5.2.4 'Lestek': + + - Crash fixed on unconfigured interfaces + - Docs fixes + +02/12/2013 Oleg Moskalenko +Version 1.5.2.3 'Lestek': + + - Added feature: TURN Server always uses fingerprints in a session if + the session client is using fingerprints. + - Default unsecure alternative port changed to 3479, + default secure alternative port changed to 5350. + - TURN Server always trying to search for default certificate file + turn_server_cert.pem and for default private key file + turn_server_pkey.pem, if not certificate or private key is + explicitly configured. + - configurable packet rate in the uclient test program. + - default peer port changed to 3480. + - -z, --no-auth option added to turnserver. + +02/11/2013 Oleg Moskalenko +Version 1.5.2.2 'Lestek': + + - Some cleanup added to the network input handlers. + +02/9/2013 Oleg Moskalenko +Version 1.5.2.1 'Lestek': + + - Binding requests do not require authentication. + - SOFTWARE in the end of the message. + +02/8/2013 Oleg Moskalenko +Version 1.5.2.0 'Lestek': + + - NAT discovery fixed (RFC5780). + +02/8/2013 Oleg Moskalenko +Version 1.5.1.6 'Calder': + + - Installation instructions fixed. + +02/8/2013 Oleg Moskalenko +Version 1.5.1.5 'Calder': + + - Mac compilation fixes. + - Fixes for old Linuxes. + +02/7/2013 Oleg Moskalenko +Version 1.5.1.4 'Calder': + + - Configuration alert (warning) messages. + - Relay addresses by default use listener addresses. + - Realm/user sequence fixed in the config file reading. + +01/27/2013 Oleg Moskalenko +Version 1.5.1.3 'Calder': + + - 'External' IP implemented for TURN-server-behind-NAT situation. + +01/26/2013 Oleg Moskalenko +Version 1.5.1.2 'Calder': + + - Alternative ports moved to 20000-ish territory. + - Docs fixes. + +01/22/2013 Oleg Moskalenko +Version 1.5.1.1 'Calder': + + - Docs fixes. + +01/22/2013 Oleg Moskalenko +Version 1.5.1.0 'Calder': + + - C++ compatible headers and build. + - C++ library header. + - HTML-formatted development reference. + +01/14/2013 Oleg Moskalenko +Version 1.5.0.0 'Calder': + + - RFC 5769 check utility implemented. + - RFC 5780 STUN extension implemented. + +01/13/2013 Oleg Moskalenko +Version 1.4.2.5 'Scale': + + - Issue 2 fixed. + +01/08/2013 Oleg Moskalenko +Version 1.4.2.4 'Scale': + + - Bogus "Bind to device" error message removed (Linux). + - Docs improvements. + +01/08/2013 Oleg Moskalenko +Version 1.4.2.3 'Scale': + + - Bandwidth limitation implemented (--max-bps option). + - DTLS communications improved. + +01/07/2013 Oleg Moskalenko +Version 1.4.2.2 'Scale': + + - Output messages fixed. + - Peer test application accepts multiple listening addresses. + - config search directories improved. + +01/06/2013 Oleg Moskalenko +Version 1.4.2.1 'Scale': + + - Examples directory structure fixed + - Installation fixes + - Output messages fixed + +01/05/2013 Oleg Moskalenko +Version 1.4.2 'Scale': + + - Daemon execution improved + - Installation fixes + - Added comments to the scripts + +01/04/2013 Oleg Moskalenko +Version 1.4.1.2 'Scale': + + - Configure script introduced + - Installation fixes + - Run as daemon + +01/01/2013 Oleg Moskalenko +Version 1.4.1 'Scale': + + - Options fixes + - Build fixes + - Script fixes + - Installation fixes + +12/31/2012 Oleg Moskalenko +Version 1.4 'Scale': + + - Separate file for the dynamic user database + - Build fixes + - Script fixes + - Logging fixes + +12/29/2012 Oleg Moskalenko +Version 1.3.0.2 'Ferro': + + - Debian 'squeeze' compilation fix + +12/26/2012 Oleg Moskalenko +Version 1.3.0.1 'Ferro': + + - install procedure minor improvements + +12/24/2012 Oleg Moskalenko +Version 1.3 'Ferro': + + - default conf file renamed to turnserver.conf + - build script improved + - client library linking fixed + - install procedure + +12/23/2012 Oleg Moskalenko +Version 1.2.3 'Luthar': + + - turnserver options fixed + - man page renamed to turnserver + +12/22/2012 Oleg Moskalenko +Version 1.2.2: + + - Man page fix + +12/21/2012 Oleg Moskalenko +Version 1.2.1 'Juvens': + + - Man page + +12/21/2012 Oleg Moskalenko +Version 1.2 'Euz': + + - Project cleaning + +12/20/2012 Oleg Moskalenko +Version 1.1 'no name': + + - DTLS extension + +12/17/2012 Oleg Moskalenko +Version 1.0 'no name': + + - RFC 5766 + - RFC 6156 diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..18581344 --- /dev/null +++ b/INSTALL @@ -0,0 +1,963 @@ +I. TURN Server as a standard OS package + +At the present time, several operation systems have this project pre-packaged: + +1) FreeBSD (and PC-BSD) have this project as a "port", named "turnserver", +in /usr/ports/net/turnserver directory. Installation is very simple: + +# optional commands, to update the ports tree: + $ sudo portsnap fetch + $ sudo portsnap update + +# Build and install the TURN Server: + $ cd /usr/ports/net/turnserver + $ sudo make install clean + +2) Debian "jessie" (and the recent version of Ubuntu and Mint) +have the predecessor of this project packaged as "rfc5766-turn-server", see the link: + +http://packages.qa.debian.org/r/rfc5766-turn-server.html + +In the new Debian "jessie", and in the related Ubuntu and Mint, you will +be able to just select rfc5766-turn-server from the packages list and +install it through Synaptic or through the package manager. + +3) ArchLinux has alse the predecessor of the TURN server package: + +https://aur.archlinux.org/packages/rfc5766-turn-server/ + +4) OpenSUSE has a package, too: + +https://build.opensuse.org/package/show/home:ehauenstein/rfc5766-turn-server + +If you are using a pre-packaged TURN server then you can skip +to the section IX. + +II. DOWNLOAD + +You have to download the archive file turnserver-*.tar.gz and unpack it: + +$ tar xfz turnserver-*.tgz + +it will create the directory 'turnserver-*' with all sources, build files, +examples and documentation. + +III. BUILD + +If you are sure that you system is ready for the build (see the section +"Extra libraries and Utilities" below) then you can build the system. +First, you have to run the configure script: + + $ cd turnserver-* + $ ./configure + +It will create a Makefile customized for your system. + +By default, the generated Makefile will be set to install everything +in: + - /usr on Solaris. + - /usr/pkg on NetBSD. + - /usr/local everywhere else. + +The binaries will be copied in bin subdirectory of the installation +destination, config files copied to etc subdirectory. There will be +also documents, examples and some other files, in separate directories. + + You can change the root configured destination directory by +setting PREFIX variable in the +configure command line. For example: + + $ PREFIX=/opt ./configure + +Or: + + $ ./configure --prefix=/opt + + You can change the auxiliary configured destination sub-directories by +setting BINDIR, CONFDIR, MANPREFIX, EXAMPLESDIR, DOCSDIR, LIBDIR, SCHEMADIR +and TURNINCLUDEDIR variables in the +configure command line. For example: + + $ PREFIX=/opt BINDIR=/opt/bin64 CONFDIR=/opt/conf ./configure + +Or: + + $ ./configure --prefix=/opt --bindir=/opt/bin64 --confdir=/opt/conf + + You also can change the compilation and link options by +setting common build variables in the +configure command line. For example: + + $ CC=clang CFLAGS=-D_CAURIB LDFLAGS=-lshanka ./configure --prefix=/opt/shy + +See below a separate INSTALL section for more details. + +The script configure is a proprietary script. It will create a Makefile +that you can use to build the project: + + $ make + +The make command without options will do the following: + - compile the code. + - create bin/ sub-directory and put the TURN server, TURN admin and + "utility" programs there. + - create lib/ sub-directory and put the client library there. + - create include/turn/ sub-directory and put include files there. + +The programs can be either called directly, or a shell scripts can be used. +The script examples are located in examples/scripts directory. These scripts +are just examples: you can run them successfully for the tests, but +you will have to change the script parameters for your real environment. + +The command: + + $ sudo make install + +will install everything into the system file structure (see below). + +(NOTE: On NetBSD, use "su root -c"). + +The command: + + $ sudo make deinstall + +will remove all installed TURN Server files from your system. + +The command: + + $ make clean + +will clean all results of the build and configuration actions. + +Do not run "make clean" before "make deinstall". The "clean" command will +remove the Makefile and you will not be able to "deinstall" then. If that +has happened, then run ./configure and make again, then deinstall and then +clean. + +NOTE: On most modern systems, the build will produce dynamically linked +executables. If you want statically linked executables, you have to modify, +accordingly, the Makefile.in template file. + +IV. INSTALL + +This step is optional. You can run the turnserver from the original build +directory, successfully, without installing the TURN server into the system. +You have to install the turnserver only if you want to integrate the +turnserver in your system. + +Run the command: + +$ make install + +It will install turnserver in /usr/local/ directory (or to whatever directory +was set in the PREFIX variable). You will have to copy +/usr/local/etc/turnserver.conf.default to /usr/local/etc/turnserver.conf file +and adjust your runtime configuration. + +This command will also: + + - copy the content of examples subdirectory into + PREFIX/share/examples/turnserver/ directory; + - copy the content of include/turn subdirectory into + PREFIX/include/turn/ directory; + - copy the database schema file turndb/schema.sql into + PREFIX/share/turnserver/ + directory; + - copy all docs into PREFIX/share/doc/turnserver/ directory. + +The installation destination of "make install" can be changed by +using DESTDIR variable, for example: + + $ ./configure --prefix=/usr + $ make + $ make DESTDIR=/opt install + +In this example, the root installation directory will be /opt/usr. + +The "configure" script by default generates a Makefile with "rpath" option +set for the binaries linking (if your compiler allows that option). If that +is not desirable (like in some OS packaging procedures), then run the +"configure" script with --disable-rpath option. + +If you do not want to use the rpath linking option, or you OS or compiler +do not allows that, then after the installation, you may have to adjust the +system-wide shared library search path by using "ldconfig -n " +(Linux), "ldconfig -m " (BSD) or "crle -u -l " +(Solaris). Your system must be able to find the libevent2, openssl and +(optionally) PostgreSQL and/or MySQL (MariaDB) and/or Redis shared libraries, +either with the help of the system-wide library search configuration or by +using LD_LIBRARY_PATH. "make install" will make a non-garantied effort to add +automatically PREFIX/lib and /usr/local/lib to the libraries search path, +but if you have some libraries in different non-default directories +you will have to add them manually to the search path, or you +will have to adjust LD_LIBRARY_PATH. + +V. PLATFORMS + +The TURN Server is using generic *NIX system APIs and is supposed to be +usable on wide range of *NIX systems. + +The following platforms have been used in the development: + + - Linux Ubuntu 11.x and 12.x, i386 and x86_64 + - FreeBSD 6.x, i386 + - FreeBSD 8.x, i386 + - PC-BSD 9.x, x86_64 + - Solaris 11, x86_64 + - Linux CentOS / Red Hat Enterprise Edition 6.3, x86_64 (amd64) + - Linux CentOS / Red Hat Enterprise Edition 6.4, x86_32 (i386) + - Linux Debian 'Squeeze', i386 + - Linux Mint 14.1 'Nadia', i386 + - Linux Debian 'Wheezy', x86_64 + - Cygwin 1.7.20 + - NetBSD 6.0.1 + - OpenBSD 5.3 + - Amazon Linux + - Mac OS X Mountain Lion + - ArchLinux + - Fedora 19 + - OpenSUSE 12.3 x86_64 + +It must work on many other *NIXes, as well. The configure script and/or +Makefile may need adjustments for other *NIXes not mentioned above. + +The code of the client messaging library can be compiled and used on +Windows, too, but it is not supported for now. + +VI. COMPILERS + +The TURN Server is written in C programming language, for portability +and for the performance reasons. + +The tested C compilers are: + + - gcc 3.4.4 thru 4.8.1 + - clang 3.0 or better + - Solaris Studio 12.3 C compiler, version 5.12 + +It may be compiled with others compilers, too. + +The code is compatible with C++ compiler, and a C++ compiler +(like g++) can be used for the compilation, too: + + $ CC=g++ ./configure + $ make + +VII. WHICH EXTRA LIBRARIES AND UTILITIES YOU NEED + +In addition to common *NIX OS services and libraries, to compile this code, +OpenSSL (version 1.0.0a or better recommended) and libevent2 (version 2.0.5 +or better) are required, the PostgreSQL C client development setup is +optional, the MySQL (MariaDB) C client development setup is optional, and the +Hiredis development files for Redis database access are optional. +For fully functional build, the extra set of libraries must be installed +in full version (the development headers and the libraries to link with). +For runtime, only runtime setup is required. If the build is modified for +static linking, then even runtime installation is not needed. + +OpenSSL, libevent2, PostgreSQL, MySQL (or MariaDB) and Hiredis +libraries can be downloaded from their web sites: + - http://www.openssl.org (required); + - http://www.libevent.org (required); + - http://www.postgresql.org (optional); + - http://www.mysql.org (or http://mariadb.org) (optional); + - http://redis.io (optional). + +The installations are pretty straightforward - the usual +"./configure" and "make install" commands. Install them into their default +locations - the configure script and the Makefile are assuming that they are +installed in their default locations. If not, then you will have to modify +those. + +Most modern popular systems (FreeBSD / PC-BSD, Linux Ubuntu 11.10+, Debian Wheezy, +Linux Mint 14+, Amazon Linux, Fedora) have a simpler way of the third party tools +installation: + + *) PC-BSD or FreeBSD (the FRESH ports database is assumed to be installed, with + the turnserver port included): + + $ cd /usr/ports/net/turnserver + $ sudo make install clear + + That's it - that command will install the TURN server with all necesary + thrid-party tools. + + If you system have no fresh ports repository: + + $ cd /usr/ports/security/openssl/ + $ sudo make install clean + $ cd /usr/ports/devel/libevent2/ + $ sudo make install clean + $ cd /usr/ports/databases/postgresql84-client/ (or any other version) + $ sudo make install clean + $ cd /usr/ports/databases/mysql51-client/ (or any other version) + $ sudo make install clean + $ cd /usr/ports/databases/hiredis/ + $ sudo make install clean + + **) Linux Ubuntu 11.10+, Debian Wheezy, Mint 14+: + + $ sudo apt-get install libssl-dev + $ sudo apt-get install libevent-dev + $ sudo apt-get install libpq-dev + $ sudo apt-get install mysql-client + $ sudo apt-get install libmysqlclient-dev + $ sudo apt-get install libhiredis-dev + + or you can use Synaptic or other software center. + + ***) Fedora: + + $ sudo yum install openssl-devel + $ sudo yum install libevent + $ sudo yum install libevent-devel + $ sudo yum install postgresql-devel + $ sudo yum install postgresql-server + $ sudo yum install mysql-devel + $ sudo yum install mysql-server + $ sudo yum install hiredis + $ sudo yum install hiredis-devel + + ****) Amazon Linux is similar to Fedora, but: + + - you have to install gcc first: + $ sudo yum install gcc + + - hiredis packages are not available, so do not issue the + hiredis installation commands. Redis support will not be + compiled, unless you install it "manually" before the TURN + server compilation. For Amazon EC2 AMIs, we install the + redis manually in the system. But the TURN server can be + perfectly installed without redis support - if you do not + need it. + + *****) Some OSes in Debian family (Debian Squeeze and + pre-11.10 Ubuntus) setups are similar to Debian Wheezy, + although some packages have different names. + + ******) On some CentOS / RedHat 6.x systems you have to install + libevent2 "manually", and optionally you have to download and + install Hiredis, but everything else can be found in the software + repository. Also, if you would like to make an RPM for CentOS, + check the directory rpm/ with the instructions. + +NOTE: If your tools are installed in non-standard locations, you will +have to adjust CFLAGS and LDFLAGS environment variables for TURN +server ./configure script. For example, to configure the TURN server +with Solaris 11 PostgreSQL 32-bits setup, you may use a command +like this: + + $ CFLAGS="${CFLAGS} -I/usr/postgres/9.2-pgdg/include/" LDFLAGS="${LDFLAGS} -L/usr/postgres/9.2-pgdg/lib/" ./configure + +Dynamic library paths: + +You may also have to adjust the turn server start script, add PostgreSQL +and/or MySQL and/or Redis runtime library path to LD_LIBRARY_PATH. +Or you may find that it would be more convenient to adjust the +system-wide shared library search path by using commands: + +on Linux: + + $ ldconfig -n + +or on BSD: + + $ ldconfig -m + +or on Solaris: + + $ crle -u -l + +On Mac OS X, you have three different choices for dynamic libraries handling: + +1) Use DYLD_LIBRARY_PATH environment variable in runtime; OR + +2) Before the compilation, check the dynamic libraries and adjust their identification names, +if necessary, to the absolute library path or to @rpath/. +For exmple, the MySQL dynamic library may need that adjustment. You will have to use +"adjust_name_tool" with -id option for that; OR + +3) After the compilation, you can use the same tool, "adjust_name_tool", with option -change, +to adjust the library paths values in the binary, where necessary. All library paths must be +absolute paths or @rpath/... . + +See also the next section. + +NOTE: See "PostgreSQL setup" and "MySQL setup" and "Redis setup" sections +below for more database setup information. + +NOTE: If you do not install PostgreSQL or MySQL or Redis then you will +be limited to flat files for user database. It will work great for +smaller user databases (like 100 users) but for larger systems you +will need PostgreSQL or MySQL or Redis. + +NOTE: To run PostgreSQL or MySQL or Redis server on the same system, +you will also have to install a corresponding PostgreSQL or MySQL or +Redis server package. The DB C development packages only provide +development libraries, and client libraries only provide client +access utilities and runtime libraries. The server packages may +include everything - client, C development and server runtime. + +NOTE: OpenSSL to be installed before libevent2. When libevent2 is building, +it is checking whether OpenSSL has been already installed, and which version +of OpenSSL. If the OpenSSL is missed, or too old, then libevent_openssl +library is not being created during the build, and you will not be able to +compile the TURN Server with TLS support. + +NOTE: An older libevent version, version 1.x.x, is often included in some *NIX +distributions. That version has its deficiencies and is inferior to the newer +libevent2, especially in the performance department. This is why we are +not providing backward compatibility with the older libevent 1.x version. +If you have a system with older libevent, then you have to install the new +libevent2 from their web site. It was tested with older *NIXes +(like FreeBSD 6.x) and it works just fine. + +NOTE: For extra security features (DTLS and SHA256) support, OpenSSL version +1.0.0a or newer is recommended. Older versions do not support DTLS, reliably, +in some cases. For example, the Debian 'Squeeze' Linux supplies 0.9.8 version +of OpenSSL, that does not work correctly with DTLS over IPv6. If your system +already has an older version of OpenSSL installed (usually in directory /usr) +then you may want to install your newer OpenSSL "over" the old one (because it +will most probably will not allow removal of the old one). When installing +the newer OpenSSL, run the OpenSSL's configure command like this: + + $ ./config --prefix=/usr + +that will set the installation prefix to /usr (without "--prefix=/usr" +by default it would be installed to /usr/local). This is necessary if you +want to overwrite your existing older OpenSSL installation. + +VIII. BUILDING WITH NON-DEFAULT PREFIX DIRECTORY + +Say, you have an older system with old openssl and old libevent +library and you do not want to change that, but you still want +to build the turnserver. + +Do the following steps: + +1) Download new openssl from openssl.org. +2) Configure and build new openssl and install it into /opt: + + $ ./config --prefix=/opt + $ make + $ make install + +3) Download the latest libevent2 from libevent.org, configure and install +it into /opt: + + $ ./configure --prefix=/opt + $ make + $ make install + +4) Change directory to coturn and build it: + + $ ./configure --prefix=/opt + $ make + +After that, you can either use it locally, or install it into /opt. +But remember that to run it, you have to adjust your LD_LIBRARY_PATH, +like that: + + $ LD_LIBRARY_PATH=/opt/lib ./bin/turnserver + +An alternative would be adjusting the system-wide shared library search path +by using + $ ldconfig -n (Linux) + $ ldconfig -m (BSD) + $ crle -u -l (Solaris) + +IX. TEST SCRIPT SETS + +First of all, we can use test vectors from RFC 5769 to double-check that our +STUN/TURN message encoding algorithms work properly. Run the utility: + + $ cd examples + $ ./scripts/rfc5769.sh + +It will perform several protocol checks and print the results on the output. +If anything has compiled wrongly (TURN Server, or OpenSSL libraries) +then you will see some errors. + +Now, you can perform the TURN functionality test (bare minimum TURN example). + +If everything compiled properly, then the following programs must run +together successfully, simulating TURN network routing in local loopback +networking environment: + +Open two shell screens or consoles: + +In shell number 1, run TURN server application: + $ cd examples + $ ./scripts/basic/relay.sh + +In shell number 2, run test client application: + + $ cd examples + $ ./scripts/basic/udp_c2c_client.sh + +If the client application produces output and in approximately 22 seconds +prints the jitter, loss and round-trip-delay statistics, then everything is +fine. + +There is another more complex test: + +In shell number 1, run TURN server application: + $ cd examples + $ ./scripts/basic/relay.sh + +In shell number 2, run "peer" application: + $ cd examples + $ ./scripts/peer.sh + +In shell number 3, run test client application: + + $ cd examples + $ ./scripts/basic/udp_client.sh (or ./scripts/basic/tcp_client.sh) + +There is a similar set of examples/scripts/longtermsecure/* scripts for +TURN environment with long-term authentication mechanism. This set of +scripts is more complex, and checking the scripts options is useful for +understanding how the TURN Server works: + +In shell number 1, run secure TURN server application: + $ cd examples + $ ./scripts/longtermsecure/secure_relay.sh + +In shell number 2, run "peer" application: + $ cd examples + $ ./scripts/peer.sh + +In shell number 3, run secure test client application: + + $ cd examples + $ ./scripts/longtermsecure/secure_udp_client.sh + + (or ./scripts/longtermsecure/secure_tcp_client.sh) + (or ./scripts/longtermsecure/secure_tls_client.sh) + (or ./scripts/longtermsecure/secure_dtls_client.sh) + (or ./scripts/longtermsecure/secure_udp_c2c.sh for "peerless" +client-to-client communications) + +The provided scripts are set for the local loopback communications, +as an example and as a test environment. Real networking IPs must be +used in real work environments. + +Try wireshark to check the communications between client, turnserver +and the peer. + +Check the README.* files and the comments in the scripts relay.sh and +secure_relay.sh as a guidance how to run the TURN server. + +X. OS X compilation notes + +OS X usually has an older version of openssl supplied, with some Apple +additions. The best option is to install a good fresh openssl development +library, free of Apple tweaks, from http://www.openssl.org. But the "native" +openssl will work, too. + +XI. MS Windows and Cygwin support + +Currently, this project cannot be compiled under MS Windows. + +As the project is using fairly straightforward *NIX API, it is supported +under Cygwin environment in MS Windows. + +One note for Cygwin users: we recommended libevent2 installation from the cygwin +"ports" site: http://sourceware.org/cygwinports/ . You will have to install +libevent2 runtime and libevent-devel packages. "Manual" libevent2 compilation +and installation in Cygwin is not recommended and does not garantee a good +outcome. + +XII. CLIENT API LIBRARY. + +The compilation process will create lib/ sub-directory with libturnclient.a +library. The header files for this library are located in include/turn/client/ +sub-directory. The C++ wrapper for the messaging functionality is located in +TurnMsgLib.h header. An example of C++ code can be found in stunclient.c file. +This file is compiled as a C++ program if C++ compiler is used, and as a C +program if C compiler is used. + +XIII. DOCS + +After installation, the man page turnserver(1) must be available. The man page +is located in man/man1 subdirectory. If you want to see the man page without +installation, run the command: + + $ man -M man turnserver + +HTML-formatted client library functions reference is located in docs/html +subdirectory of the original archive tree. After the installation, it will +be placed in PREFIX/share/doc/turnserver/html. + +XIV. PostgreSQL setup + +The site http://www.postgresql.org site has excellent extensive documentation. +For a quick-start guide, you can take a look into this page: +http://www.freebsddiary.org/postgresql.php. That page is written for +FreeBSD users, but it has lots of generic information applicable to other +*NIXes, too. + +For the psql-userdb TURN server parameter, you can either set a PostgreSQL +connection string, or a PostgreSQL URI, see the link: + +For 8.4 PostgreSQL version: +http://www.postgresql.org/docs/8.4/static/libpq-connect.html + +For newer 9.x versions: +http://www.postgresql.org/docs/9.2/static/libpq-connect.html#LIBPQ-CONNSTRING. + +In the PostgreSQL connection string or URI, you can set the host, the +access port, the database name, the user, and the user password +(if the access is secured). Numerous other parameters can be set, +see the links above. The TURN server will blindly use that connection +string without any modifications. You are responsible for the right +connection string format. + +Below are the steps to setup the PostgreSQL database server from scratch: + +1) Install PostgreSQL server. + +2) Find and edit Postgres' pg_hba.conf file to set the access options +(see docs). On different systems, it may be located in different places. +Set the lines for local access as "trust" for now (you can change it later), +for TCP/IP access set the value as "md5". +To set TCP/IP access from any host, use "0.0.0.0/0" for IPv4, and "::/0" +for IPv6. + +3) Edit postgresql.conf file to allow TCP/IP access - uncomment and edit +the "listen_addresses" option (see docs). On different systems, this file +may be located in different places. + +4) Restart your system or restart the postgresql server, for example: + + $ sudo /etc/init.d/postgresql stop + $ sudo /etc/init.d/postgresql start + +5) Check /etc/passwd file to find out which user account is used for the +PostgreSQL admin access on your system (it may be "pgsql", or "postgres", +or "postgresql"). Let's assume that this is "postgres" account. + +6) Create a database for the TURN purposes, with name, say, "turn": + + $ createdb -U postgres turn + +7) Create a user for the TURN with name, say, "turn": + $ psql -U postgres turn + turn=# create user turn with password 'turn'; + turn=# + Ctrl-D + +8) Create the TURN users database schema. + +The database schema for the TURN server is very minimalistic and is located +in project's turndb/schema.sql file, or in the system's +PREFIX/share/turnserver/schema.sql file after the turnserver installation: + +$ cat turndb/schema.sql | psql -U turn 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 +$ + +The schema description: + +# Table for long-term credentials mechanism authorization: +# +CREATE TABLE turnusers_lt ( + realm varchar(512), + name varchar(512), + hmackey char(128), + PRIMARY KEY (realm,name) +); + +# 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), + value varchar(512), + primary key (realm,value) +); + +# Table holding "white" allowed peer IP ranges. +# +CREATE TABLE allowed_peer_ip ( + ip_range varchar(256), + primary key (ip_range) +); + +# Table holding "black" denied peer IP ranges. +# +CREATE TABLE denied_peer_ip ( + ip_range varchar(256), + primary key (ip_range) +); + +# Table to match origin to realm. +# Multiple origins may have the same realm. +# If no realm is found or the origin is absent +# then the default realm is used. +# +CREATE TABLE turn_origin_to_realm ( + origin varchar(512), + realm varchar(512), + primary key (origin,realm) +); + +# Realm options. +# Valid options are 'max-bps', +# 'total-quota' and 'user-quota'. +# Values for them are integers (in text form). +# +CREATE TABLE turn_realm_option ( + realm varchar(512), + opt varchar(32), + value varchar(128), + primary key (realm,opt) +); + +The field hmackey contains HEX string representation of the key. +We do not store the user open passwords for long-term credentials, for security reasons. +Storing only the HMAC key has its own implications - if you change the realm, +you will have to update the HMAC keys of all users, because the realm is +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. + +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. + +More examples of database schema creation: + +psql -h -U -d < turndb/schema.sql +(old style for 8.4) + +psql postgresql://username:password@/databasename < turndb/schema.sql +(newer style for 9.x, UNIX domain local sockets) + +Or: + +psql postgresql://username:password@hostname:port/databasename < turndb/schema.sql +(newer style for 9.x, TCP/IP access) + +Below, the string "postgresql://turn:turn@/turn" is the connection URI. +Of course, the administrators can play with the connection string as they want. + +When starting the turnserver, the psql-userdb parameter will be, for example: + +turnserver ... --psql-userdb="host=localhost dbname=turn user=turn password=turn connect_timeout=30" + +Or, for 9.x PostgreSQL versions: +turnserver ... --psql-userdb=postgresql://username:password@/databasename ... + +9) You are ready to use the TURN database. The database name is "turn", +the user name is "turn", the user password is "turn". Of course, you can +choose your own names. Now, you will have to use the program turnadmin to fill the +database, or you can do that manually with psql. + +Fill in users, for example: + + Shared secret for the TURN REST API: + + $ bin/turnadmin -s logen -e "host=localhost dbname=turn user=turn password=turn" + + Long-term credentials mechanism: + + $ bin/turnadmin -a -e "host=localhost dbname=turn user=turn password=turn" -u gorst -r north.gov -p hero + $ bin/turnadmin -a -e "host=localhost dbname=turn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + + Long-term credentials mechanism with SHA256 extention: + $ bin/turnadmin -a -e "host=localhost dbname=turn user=turn password=turn" -u bethod -r north.gov -p king-of-north --sha256 + + Short-term credentials mechanism: + + $ bin/turnadmin -A -e "host=localhost dbname=turn user=turn password=turn" -u gorst -r north.gov -p hero + $ bin/turnadmin -A -e "host=localhost dbname=turn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + +XV. MySQL (MariaDB) setup + +The MySQL setup is similar to PostgreSQL (same idea), and is well documented +on their site http://www.mysql.org. The TURN Server database schema is the +same as for PostgreSQL and you can find it in turndb/schema.sql file, or +in the system's PREFIX/share/turnserver/schema.sql file after the turnserver +installation. + +The general setup idea is the same as for PostgreSQL case: + +1) Check that the mysql server access is OK. Immediately after the MySQL server +installation, it must be accessible, at the very minimum, at the localhost with +the root account. + +2) Login into mysql console from root account: + + $ sudo bash + # mysql -p mysql + +3) Add 'turn' user with 'turn' password (for example): + + > create user 'turn'@'localhost' identified by 'turn'; + +4) Create database 'turn' (for example) and grant privileges to user 'turn': + + > create database turn; + > grant all on turn.* to 'turn'@'localhost'; + > flush privileges; + Ctrl-D + +5) Create database schema: + + $ mysql -p -u turn turn < turndb/schema.sql + Enter password: turn + $ + +6) Fill in users, for example: + + Shared secret for the TURN REST API: + + $ bin/turnadmin -s logen -M "host=localhost dbname=turn user=turn password=turn" + + Long-term credentials mechanism: + + $ bin/turnadmin -a -M "host=localhost dbname=turn user=turn password=turn" -u gorst -r north.gov -p hero + $ bin/turnadmin -a -M "host=localhost dbname=turn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + + Long-term credentials mechanism with SHA256 extention: + $ bin/turnadmin -a -M "host=localhost dbname=turn user=turn password=turn" -u bethod -r north.gov -p king-of-north --sha256 + + Short-term credentials mechanism: + + $ bin/turnadmin -A -M "host=localhost dbname=turn user=turn password=turn" -u gorst -r north.gov -p hero + $ bin/turnadmin -A -M "host=localhost dbname=turn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + +7) Now we can use mysql in the turnserver. + +If the TURN server was compiled with MySQL support, then we can use the +TURN server database parameter --mysql-userdb. The value of this parameter +is a connection string for the MySQL database. As "native" MySQL does not +have such a feature as "connection string", the TURN server parses the +connection string and converts it into MySQL database connection parameter. +The format of the MySQL connection string is: + +"host= dbname= user= password= port= connect_timeout=" + +(all parameters are optional) + +So, an example of the MySQL database parameter in the TURN server command +line would be: + +--mysql-userdb="host=localhost dbname=turn user=turn password=turn connect_timeout=30" + +Or in the turnserver.conf file: + +mysql-userdb="host=localhost dbname=turn user=turn password=turn connect_timeout=30" + +XVI. Redis setup + +The Redis setup is well documented on their site http://redis.io. +The TURN Server Redis database schema description can be found +in schema.userdb.redis and schema.stats.redis files. Those files are located +either in the turndb subdirectory of the main source code directory, +or in /usr/local/share/turnserver/ after the installation, or somewhere in /usr/share/ +directory, depending on the OS and on the instalation package. + +If the TURN server was compiled with Hiredis support (Hiredis is the C client +library for Redis), then we can use the TURN server database parameter +--redis-userdb. The value of this parameter is a connection string +for the Redis database. As "native" Redis does not have such a feature as +"connection string", the TURN server parses the connection string and +converts it into Redis database access parameter. The format of the Redis +connection string is: + +"ip= dbname= password= port= connect_timeout=" + +(all parameters are optional) + +So, an example of the Redis database parameter in the TURN server command +line would be: + +--redis-userdb="ip=127.0.0.1 dbname=0 password=turn connect_timeout=30" + +Or in the turnserver.conf file: + +redis-userdb="ip=127.0.0.1 dbname=0 password=turn connect_timeout=30" + +Redis can be also used for the TURN allocation status check and for status and +traffic notifications. + +See the explanation in the turndb/schema.stats.redis file, and an example in +turndb/testredisdbsetup.sh file. One special thing about TURN Redis security setup +is that you can store open passwords for long-term credentials in Redis. +You cannot set open passwords for long-term credentials in MySQL and PostgreSQL - +with those DBs, you have to use the keys only. With Redis, you have a choice - +keys or open passwords. + +You also have to take care about Redis connection parameters, the timeout and the +keepalive. The following settings must be in your Redis config file +(/etc/redis.conf or /usr/local/etc/redis.conf): + +.......... +timeout 0 +.......... +tcp-keepalive 60 +.......... + +Redis TURN admin commands: + + Shared secret for the TURN REST API: + + $ bin/turnadmin -s logen -N "host=localhost dbname=0 user=turn password=turn" + + Long-term credentials mechanism: + + $ bin/turnadmin -a -N "host=localhost dbname=0 user=turn password=turn" -u gorst -r north.gov -p hero + $ bin/turnadmin -a -N "host=localhost dbname=0 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + + Long-term credentials mechanism with SHA256 extention: + $ bin/turnadmin -a -N "host=localhost dbname=0 user=turn password=turn" -u bethod -r north.gov -p king-of-north --sha256 + + Short-term credentials mechanism: + + $ bin/turnadmin -A -N "host=localhost dbname=0 user=turn password=turn" -u gorst -r north.gov -p hero + $ bin/turnadmin -A -N "host=localhost dbname=0 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + +XV. Performance tuning + +This topic is covered in the wiki page: + +http://code.google.com/p/coturn/wiki/turn_performance_and_load_balance + +XVI. TURN Server setup + +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. + +XVI. 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 +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. + +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 +or ::1). The CLI may have a password configured, but that password is +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. diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..f3529855 --- /dev/null +++ b/LICENSE @@ -0,0 +1,31 @@ +/* + * TURN Server - RFC5766 TURN Server implementation + * Copyright (C) 2011, 2012, 2013 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. + */ + diff --git a/LICENSE.OpenSSL b/LICENSE.OpenSSL new file mode 100644 index 00000000..a2c4adcb --- /dev/null +++ b/LICENSE.OpenSSL @@ -0,0 +1,127 @@ + + LICENSE ISSUES + ============== + + The OpenSSL toolkit stays under a dual license, i.e. both the conditions of + the OpenSSL License and the original SSLeay license apply to the toolkit. + See below for the actual license texts. Actually both licenses are BSD-style + Open Source licenses. In case of any license issues related to OpenSSL + please contact openssl-core@openssl.org. + + OpenSSL License + --------------- + +/* ==================================================================== + * Copyright (c) 1998-2008 The OpenSSL Project. 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + Original SSLeay License + ----------------------- + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + diff --git a/Makefile.in b/Makefile.in new file mode 100755 index 00000000..785d738e --- /dev/null +++ b/Makefile.in @@ -0,0 +1,173 @@ + +LIBEVENT_INCLUDE = -I${PREFIX}/include/ -I/usr/local/include/ + +INCFLAGS = -Isrc -Isrc/apps/common -Isrc/server -Isrc/client -Isrc/client++ ${LIBEVENT_INCLUDE} + +CFLAGS += ${INCFLAGS} + +MAKE_DEPS = Makefile + +LIBCLIENTTURN_HEADERS = src/ns_turn_defs.h src/client++/TurnMsgLib.h src/client/ns_turn_ioaddr.h src/client/ns_turn_msg.h src/client/ns_turn_msg_defs.h src/client/ns_turn_msg_addr.h +LIBCLIENTTURN_MODS = src/client/ns_turn_ioaddr.c src/client/ns_turn_msg_addr.c src/client/ns_turn_msg.c +LIBCLIENTTURN_DEPS = ${LIBCLIENTTURN_HEADERS} ${MAKE_DEPS} +LIBCLIENTTURN_OBJS = build/obj/ns_turn_ioaddr.o build/obj/ns_turn_msg_addr.o build/obj/ns_turn_msg.o + +SERVERTURN_HEADERS = src/server/ns_turn_allocation.h src/server/ns_turn_ioalib.h src/server/ns_turn_khash.h src/server/ns_turn_maps_rtcp.h src/server/ns_turn_maps.h src/server/ns_turn_server.h src/server/ns_turn_session.h +SERVERTURN_DEPS = ${LIBCLIENTTURN_HEADERS} ${SERVERTURN_HEADERS} ${MAKE_DEPS} +SERVERTURN_MODS = ${LIBCLIENTTURN_MODS} src/server/ns_turn_allocation.c src/server/ns_turn_maps_rtcp.c src/server/ns_turn_maps.c src/server/ns_turn_server.c + +COMMON_HEADERS = src/apps/common/apputils.h src/apps/common/ns_turn_utils.h src/apps/common/stun_buffer.h +COMMON_MODS = src/apps/common/apputils.c src/apps/common/ns_turn_utils.c src/apps/common/stun_buffer.c +COMMON_DEPS = ${LIBCLIENTTURN_DEPS} ${COMMON_MODS} ${COMMON_HEADERS} + +IMPL_HEADERS = src/apps/relay/ns_ioalib_impl.h src/apps/relay/ns_sm.h src/apps/relay/turn_ports.h +IMPL_MODS = src/apps/relay/ns_ioalib_engine_impl.c src/apps/relay/turn_ports.c +IMPL_DEPS = ${COMMON_DEPS} ${IMPL_HEADERS} ${IMPL_MODS} + +HIREDIS_HEADERS = src/apps/common/hiredis_libevent2.h +HIREDIS_MODS = src/apps/common/hiredis_libevent2.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} +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} +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 + +all: ${TURN_BUILD_RESULTS} + +test: check + +check: bin/turnutils_rfc5769check + bin/turnutils_rfc5769check + +include/turn/ns_turn_defs.h: src/ns_turn_defs.h + ${RMCMD} include + ${MKBUILDDIR} include/turn/client + cp -pf src/client/*.h include/turn/client/ + cp -pf src/client++/*.h include/turn/client/ + cp -pf src/ns_turn_defs.h include/turn/ + +bin/turnutils_uclient: ${COMMON_DEPS} src/apps/uclient/session.h lib/libturnclient.a src/apps/uclient/mainuclient.c src/apps/uclient/uclient.c src/apps/uclient/uclient.h src/apps/uclient/startuclient.c src/apps/uclient/startuclient.h + ${MKBUILDDIR} bin + ${CC} ${CPPFLAGS} ${CFLAGS} src/apps/uclient/uclient.c src/apps/uclient/startuclient.c src/apps/uclient/mainuclient.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS} + +bin/turnutils_stunclient: ${COMMON_DEPS} lib/libturnclient.a src/apps/stunclient/stunclient.c + pwd + ${MKBUILDDIR} bin + ${CC} ${CPPFLAGS} ${CFLAGS} src/apps/stunclient/stunclient.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS} + +bin/turnutils_rfc5769check: ${COMMON_DEPS} lib/libturnclient.a src/apps/rfc5769/rfc5769check.c + pwd + ${MKBUILDDIR} bin + ${CC} ${CPPFLAGS} ${CFLAGS} src/apps/rfc5769/rfc5769check.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS} + +bin/turnserver: ${SERVERAPP_DEPS} + ${MKBUILDDIR} bin + ${RMCMD} bin/turnadmin + ${CC} ${CPPFLAGS} ${CFLAGS} ${DBCFLAGS} ${IMPL_MODS} -Ilib ${SERVERAPP_MODS} ${COMMON_MODS} ${SERVERTURN_MODS} -o $@ ${DBLIBS} ${LDFLAGS} + cd bin; ln -s turnserver turnadmin + +bin/turnutils_peer: ${COMMON_DEPS} ${LIBCLIENTTURN_MODS} ${LIBCLIENTTURN_DEPS} lib/libturnclient.a src/apps/peer/mainudpserver.c src/apps/peer/udpserver.h src/apps/peer/udpserver.c + ${MKBUILDDIR} bin + ${CC} ${CPPFLAGS} ${CFLAGS} src/apps/peer/mainudpserver.c src/apps/peer/udpserver.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS} + +### Client Library: + +lib/libturnclient.a: ${LIBCLIENTTURN_OBJS} ${LIBCLIENTTURN_DEPS} + ${MKBUILDDIR} lib + ${ARCHIVERCMD} $@ ${LIBCLIENTTURN_OBJS} + +build/obj/ns_turn_ioaddr.o: src/client/ns_turn_ioaddr.c ${LUBCLIENTTURN_DEPS} + ${MKBUILDDIR} build/obj + ${CC} ${CPPFLAGS} ${CFLAGS} -c src/client/ns_turn_ioaddr.c -o $@ + +build/obj/ns_turn_msg_addr.o: src/client/ns_turn_msg_addr.c ${LUBCLIENTTURN_DEPS} + ${MKBUILDDIR} build/obj + ${CC} ${CPPFLAGS} ${CFLAGS} -c src/client/ns_turn_msg_addr.c -o $@ + +build/obj/ns_turn_msg.o: src/client/ns_turn_msg.c ${LUBCLIENTTURN_DEPS} + ${MKBUILDDIR} build/obj + ${CC} ${CPPFLAGS} ${CFLAGS} -c src/client/ns_turn_msg.c -o $@ + +### Clean all: + +clean: + ${RMCMD} bin build lib obj *bak *~ */*~ */*/*~ */*/*/*~ *core */*core */*/*core include Makefile tmp + +distclean: clean + +### Install all: + +install: all ${MAKE_DEPS} + ${MKDIR} ${DESTDIR}${PREFIX} + ${MKDIR} ${DESTDIR}${BINDIR} + ${MKDIR} ${DESTDIR}${MANPREFIX}/man/man1 + ${MKDIR} ${DESTDIR}${CONFDIR} + ${MKDIR} ${DESTDIR}${LIBDIR} + ${MKDIR} ${DESTDIR}${EXAMPLESDIR} + ${MKDIR} ${DESTDIR}${DOCSDIR} + ${MKDIR} ${DESTDIR}${SCHEMADIR} + ${MKDIR} ${DESTDIR}${TURNINCLUDEDIR} + ${INSTALL_PROGRAM} bin/turnserver ${DESTDIR}${BINDIR} + ${INSTALL_PROGRAM} bin/turnadmin ${DESTDIR}${BINDIR} + ${INSTALL_PROGRAM} bin/turnutils_uclient ${DESTDIR}${BINDIR} + ${INSTALL_PROGRAM} bin/turnutils_peer ${DESTDIR}${BINDIR} + ${INSTALL_PROGRAM} bin/turnutils_stunclient ${DESTDIR}${BINDIR} + ${INSTALL_MAN} man/man1/turnserver.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_MAN} man/man1/turnadmin.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_MAN} man/man1/turnutils.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_MAN} man/man1/turnutils_uclient.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_MAN} man/man1/turnutils_stunclient.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_MAN} man/man1/turnutils_peer.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_MAN} man/man1/coturn.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_STATIC_LIB} lib/libturnclient.a ${DESTDIR}${LIBDIR} + ${INSTALL_DATA} LICENSE ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} README.turnserver ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} README.turnadmin ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} README.turnutils ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} INSTALL ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} postinstall.txt ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} turndb/schema.sql ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} turndb/schema.sql ${DESTDIR}${SCHEMADIR} + ${INSTALL_DATA} turndb/testredisdbsetup.sh ${DESTDIR}${SCHEMADIR} + ${INSTALL_DATA} turndb/testsqldbsetup.sql ${DESTDIR}${SCHEMADIR} + ${INSTALL_DATA} turndb/schema.userdb.redis ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} turndb/schema.userdb.redis ${DESTDIR}${SCHEMADIR} + ${INSTALL_DATA} turndb/schema.stats.redis ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} turndb/schema.stats.redis ${DESTDIR}${SCHEMADIR} + ${INSTALL_DATA} examples/etc/turnserver.conf ${DESTDIR}${CONFDIR}/turnserver.conf.default + ${INSTALL_DATA} examples/etc/turnuserdb.conf ${DESTDIR}${CONFDIR}/turnuserdb.conf.default + ${INSTALL_DIR} examples/etc ${DESTDIR}${EXAMPLESDIR} + ${INSTALL_DIR} examples/scripts ${DESTDIR}${EXAMPLESDIR} + ${RMCMD} ${DESTDIR}${EXAMPLESDIR}/scripts/rfc5769.sh + ${INSTALL_DIR} include/turn/client ${DESTDIR}${TURNINCLUDEDIR} + ${INSTALL_DATA} include/turn/ns_turn_defs.h ${DESTDIR}${TURNINCLUDEDIR} + ${MORECMD} ${DESTDIR}${DOCSDIR}/postinstall.txt + +deinstall: ${MAKE_DEPS} + ${PKILL_PROGRAM} turnserver || ${ECHO_CMD} OK + ${RMCMD} ${DESTDIR}${DOCSDIR} + ${RMCMD} ${DESTDIR}${SCHEMADIR} + ${RMCMD} ${DESTDIR}${BINDIR}/turnserver + ${RMCMD} ${DESTDIR}${BINDIR}/turnadmin + ${RMCMD} ${DESTDIR}${BINDIR}/turnutils_peer + ${RMCMD} ${DESTDIR}${BINDIR}/turnutils_uclient + ${RMCMD} ${DESTDIR}${BINDIR}/turnutils_stunclient + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnserver.1 + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnadmin.1 + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils.1 + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_uclient.1 + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_stunclient.1 + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_peer.1 + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/coturn.1 + ${RMCMD} ${DESTDIR}${LIBDIR}/libturnclient.a + ${RMCMD} ${DESTDIR}${EXAMPLESDIR}/ + ${RMCMD} ${DESTDIR}${CONFDIR}/turnserver.conf.default + ${RMCMD} ${DESTDIR}${CONFDIR}/turnuserdb.conf.default + ${RMCMD} ${DESTDIR}${TURNINCLUDEDIR} + +uninstall: deinstall + +reinstall: deinstall install + + diff --git a/NOTE b/NOTE new file mode 100644 index 00000000..3cb9955c --- /dev/null +++ b/NOTE @@ -0,0 +1,2 @@ +This project is active in Google code: http://code.google.com/p/coturn/ + diff --git a/README.turnadmin b/README.turnadmin new file mode 100644 index 00000000..fb5f176d --- /dev/null +++ b/README.turnadmin @@ -0,0 +1,239 @@ +GENERAL INFORMATION + +turnadmin is a TURN administration tool. This tool can be used to manage +the user accounts (add/remove users, generate +TURN keys for the users). For security reasons, we do not recommend +storing passwords openly. The better option is to use pre-processed "keys" +which are then used for authentication. These keys are generated by turnadmin. +Turnadmin is a link to turnserver binary, but turnadmin performs different +functions. + +Options note: turnadmin has long and short option names, for most options. +Some options have only long form, some options have only short form. Their syntax +somewhat different, if an argument is required: + +The short form must be used as this (for example): + + $ turnadmin -u ... + +The long form equivalent must use the "=" character: + + $ turnadmin --user= ... + +If this is a flag option (no argument required) then their usage are the same, for example: + + $ turnadmin -k ... + +is equivalent to: + + $ turnadmin --key ... + +You have always the use the -r option with commands for long term credentials - +because data for multiple realms can be stored in the same database. + +===================================== + + NAME + +turnadmin - a TURN relay administration tool. + + SYNOPSIS + +$ turnadmin [command] [options] + +$ turnadmin [ -h | --help] + + DESCRIPTION + +Commands: + +-k, --key Generate key for a long-term credentials mechanism user. + +-a, --add Add or update a long-term user. + +-A, --add-st Add or update a short-term credentials mechanism user. + +-d, --delete Delete a long-term user. + +-D, --delete-st Delete a short-term user. + +-l, --list List long-term users in the database. + +-L, --list-st List short-term users in the database. + +-s, --set-secret= Add shared secret for TURN RESP API + +-S, --show-secret Show stored shared secrets for TURN REST API + +-X, --delete-secret= Delete a shared secret. + --delete-all_secrets Delete all shared secrets for REST API. + +-O, --add-origin Add origin-to-realm relation. + +-R, --del-origin Delete origin-to-realm relation. + +-I, --list-origins List origin-to-realm relations. + +-g, --set-realm-option Set realm params: max-bps, total-quota, user-quota. + +-G, --list-realm-options List realm params. + +NOTE: if you are using the flat file for the user database, then you will have +to use a text editor to set or show the shared secrets. + +NOTE: the origin functionality is not supported with flat user db file, +a "real" database must be used. + +Options with required values: + +-b, --userdb File-based user database file name (default - turnuserdb.conf). + See the --userdb option in the turnserver section. +-e, --psql-userdb PostgreSQL user database connection string. + See the --psql-userdb option in the turnserver section. +-M, --mysql-userdb MySQL user database connection string. + See the --mysql-userdb option in the turnserver section. +-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. +-p, --password Password. +-o, --origin Origin +-H, --sha256 Use SHA256 as the keys hash function (a non-standard feature). + By default, MD5 is used for the key storage encryption + (as required by the current STUN/TURNstandards). +--max-bps Set value of realm's max-bps parameter. +--total-quota Set value of realm's total-quota parameter. +--user-quota Set value of realm's user-quota parameter. +-h, --help Help. + +Generate a key: + +$ turnadmin -k -u -r -p + +Add/update a user in the userdb file or in the database: + +$ turnadmin -a [-b | -e | -M | -N ] -u -r -p + +Delete a user from the userdb file or from the database: + +$ turnadmin -d [-b | -e | -M | -N ] -u -r + +List all long-term users in MySQL database: + +$ turnadmin -l --mysql-userdb="" -r + +List all short-term users in Redis database: + +$ turnadmin -L --redis-userdb="" + +Set secret in MySQL database: + +$ turnadmin -s --mysql-userdb="" -r + +Show secret stored in PostgreSQL database: + +$ turnadmin -S --psql-userdb="" -r + +Set origin-to-realm relation in MySQL database: + +$ turnadmin --mysql-userdb="" -r -o + +Delete origin-to-realm relation from Redis DB: + +$ turnadmin --redis-userdb="" -o + +List all origin-to-realm relations in Redis DB: + +$ turnadmin --redis-userdb="" -I + +List the origin-to-realm relations in PostgreSQL DB for a single realm: + +$ turnadmin --psql-userdb="" -I -r + +Help: + +$ turnadmin -h + +======================================= + + DOCS + +After installation, run the command: + +$ man turnadmin + +or in the project root directory: + +$ man -M man turnadmin + +to see the man page. + +===================================== + + FILES + +/etc/turnserver.conf + +/etc/turnuserdb.conf + +/usr/local/etc/turnserver.conf + +/usr/local/etc/turnuserdb.conf + +===================================== + + DIRECTORIES + +/usr/local/share/turnserver + +/usr/local/share/doc/turnserver + +/usr/local/share/examples/turnserver + +====================================== + + SEE ALSO + + turnserver, turnutils + +====================================== + + WEB RESOURCES + + project page: + + http://code.google.com/p/coturn/ + + Wiki page: + + http://code.google.com/p/coturn/wiki/Readme + + forum: + + https://groups.google.com/forum/?fromgroups=#!forum/turn-server-project-rfc5766-turn-server/ + +====================================== + + AUTHORS + + Oleg Moskalenko + + Gabor Kovesdan http://kovesdan.org/ + + Daniel Pocock http://danielpocock.com/ + + John Selbie (jselbie@gmail.com) + + Lee Sylvester + + Erik Johnston + + Roman Lisagor + + Vladimir Tsanev + + Po-sheng Lin + + Peter Dunkley + + Mutsutoshi Yoshimoto diff --git a/README.turnserver b/README.turnserver new file mode 100644 index 00000000..d0ccff7d --- /dev/null +++ b/README.turnserver @@ -0,0 +1,880 @@ +GENERAL INFORMATION + +The TURN Server project contains the source code of a TURN server and TURN client +messaging library. Also, some extra programs provided, for testing-only +purposes. + +See the INSTALL file for the building instructions. + +After the build, you will have the following binary images: + +1. turnserver: TURN Server relay. +The compiled binary image of the TURN Server program is located in bin/ sub-directory. + +2. turnadmin: TURN administration tool. See README.turnadmin and turnadmin man page. + +3. turnutils_uclient. See README.turnutils and turnutils man page. + +4. turnutils_peer. See README.turnutils and turnutils man page. + +5. turnutils_stunclient. See README.turnutils and turnutils man page. + +6. turnutils_rfc5769check. See README.turnutils and turnutils man page. + +In the "examples/scripts" sub-directory, you will find the examples of command lines to be used +to run the programs. The scripts are meant to be run from examples/ sub-directory, for example: + +$ cd examples +$ ./scripts/secure_relay.sh + +RUNNING THE TURN SERVER + +Options note: turnserver has long and short option names, for most options. +Some options have only long form, some options have only short form. Their syntax +somewhat different, if an argument is required: + +The short form must be used as this (for example): + + $ turnserver -L 12.34.56.78 + +The long form equivalent must use the "=" character: + + $ turnserver --listening-ip=12.34.56.78 + +If this is a flag option (no argument required) then their usage are the same, for example: + + $ turnserver -a + +is equivalent to: + + $ turnserver --lt-cred-mech + +===================================== + + NAME + +turnserver - a TURN relay server implementation. + + SYNOPSIS + +$ turnserver [-n | -c ] [flags] [ --userdb= | --psql-userdb= | --mysql-userdb= | --redis-userdb= ] [-z | --no-auth | -a | --lt-cred-mech ] [options] +$ turnserver -h + + DESCRIPTION + +Config file settings: + +-n Do not use configuration file, use only command line parameters. + +-c Configuration file name (default - turnserver.conf). + The format of config file can be seen in + the supplied examples/etc/turnserver.conf example file. Long + names of the options are used as the configuration + items names in the file. If not an absolute path is supplied, + then the file is searched in the following directories: + * current directory + * current directory etc/ sub-directory + * upper directory level etc/ + * /etc/ + * /usr/local/etc/ + * installation directory /etc + +User database settings: + +-b, --userdb User database file name (default - turnuserdb.conf), + for long-term credentials mechanism only. + This user file database is being dynamically checked while the turnserver + is working, and the user accounts can be changed dynamically by + editing the database. + +-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 for secret-based timed authentication in TURN RESP API. + The connection string format is like that: + + "host= dbname= user= password= connect_timeout=" + (for 8.x or newer Postgres). + + Or: + + "postgresql://username:password@hostname:port/databasename" (for 9.x or newer Postgres). + See the INSTALL file for more explanations and examples. + + 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 secret-based timed authentication in TURN RESP API. + The connection string format is like that: + + "host= dbname= user= password= connect_timeout=" + See the INSTALL file for more explanations and examples. + + Also, see http://www.mysql.org or http://mariadb.org + for full MySQL 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 value for secret-based timed authentication in TURN RESP API. + The connection string format is like that: + + "ip= dbname= password= connect_timeout=" + See the INSTALL file for more explanations and examples. + + Also, see http://redis.io for full Redis documentation. + +Flags: + +-v, --verbose Moderate verbose mode. + +-V, --Verbose Extra verbose mode, very annoying and not recommended. + +-o, --daemon Run server as daemon. + +-f, --fingerprint Use fingerprints in the TURN messages. If an incoming request + contains a fingerprint, then TURN server will always add + fingerprints to the messages in this session, regardless of the + per-server setting. + +-a, --lt-cred-mech Use long-term credentials mechanism (this one you need for WebRTC usage). + This option can be used with either flat file user database or + PostgreSQL DB or MySQL DB or Redis for user keys storage. +-A, --st-cred-mech Use the short-term credentials mechanism. This option requires + a PostgreSQL or MySQL or Redis DB for short term passwords storage. + +-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. + By default, no credential mechanism is used - + any user is allowed. + +--use-auth-secret TURN REST API flag. + Flag that sets a special WebRTC authorization option + that is based upon authentication secret. The feature purpose + is to support "TURN Server REST API" as described in + the TURN REST API section below. + This option uses timestamp as part of combined username: + usercombo -> "timestamp:username", + turn user -> usercombo, + turn password -> base64(hmac(secret key, usercombo)). + This allows TURN credentials to be accounted for a specific user id. + 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. + +--dh566 Use 566 bits predefined DH TLS key. Default size of the key is 1066. + +--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 protocol. + +--no-tlsv1_1 Do not allow TLSv1.1 protocol. + +--no-tlsv1_2 Do not allow TLSv1.2 protocol. + +--no-udp Do not start UDP client listeners. + +--no-tcp Do not start TCP client listeners. + +--no-tls Do not start TLS client listeners. + +--no-dtls Do not start DTLS client listeners. + +--no-udp-relay Do not allow UDP relay endpoints defined in RFC 5766, + use only TCP relay endpoints as defined in RFC 6062. + +--no-tcp-relay Do not allow TCP relay endpoints defined in RFC 6062, + use only UDP relay endpoints as defined in RFC 5766. + +--stale-nonce Use extra security with nonce value having limited lifetime (600 secs). + +--no-stdout-log Flag to prevent stdout log messages. + By default, all log messages are going to both stdout and to + the configured log file. With this option everything will be going to + the log file only (unless the log file itself is stdout). + +--syslog With this flag, all log will be redirected to the system log (syslog). + +--simple-log This flag means that no log file rollover will be used, and the log file + name will be constructed as-is, without PID and date appendage. + +--secure-stun Require authentication of the STUN Binding request. + By default, the clients are allowed anonymous access to the STUN Binding functionality. + +-S, --stun-only Run as STUN server only, all TURN requests will be ignored. + Option to suppress TURN functionality, only STUN requests will be processed. + +--no-stun Run as TURN server only, all STUN requests will be ignored. + Option to suppress STUN functionality, only TURN requests will be processed. + +--no-loopback-peers Disallow peers on the loopback addresses (127.x.x.x and ::1). + +--no-multicast-peers Disallow peers on well-known broadcast addresses + (224.0.0.0 and above, and FFXX:*). + +--sha256 Require SHA256 digest function to be used for the message integrity. + By default, the server uses SHA1 hashes. With this option, the server + requires the stronger SHA256 hashes. The client application must support + SHA256 hash function if this option is used. If the server obtains a message + from the client with a weaker (SHA1) hash function then the server returns + error code 426. + +--mobility Mobility with ICE (MICE) specs support. + +--no-cli Turn OFF the CLI support. By default it is always ON. + See also options --cli-ip and --cli-port. + +--server-relay Server relay. NON-STANDARD AND DANGEROUS OPTION. + Only for those applications when we want to run + server applications on the relay endpoints. + This option eliminates the IP permissions check + on the packets incoming to the relay endpoints. + See http://tools.ietf.org/search/rfc5766#section-17.2.3 . + +--udp-self-balance (recommended for older Linuxes only) + Automatically balance UDP traffic over auxiliary servers + (if configured). The load balancing is using the + ALTERNATE-SERVER mechanism. The TURN client must support + 300 ALTERNATE-SERVER response for this functionality. + +-h Help. + +Options with required values: + +-d, --listening-device Listener interface device. + (NOT RECOMMENDED. Optional functionality, Linux only). + The turnserver process must have root privileges to bind the + listening endpoint to a device. If turnserver must run as a + process without root privileges, then just do not use this setting. + +-L, --listening-ip Listener IP address of relay server. + Multiple listeners can be specified, for example: + -L ip1 -L ip2 -L ip3 + If no IP(s) specified, then all IPv4 and + IPv6 system IPs will be used for listening. + The same ip(s) can be used as both listening and relay ip(s). + +-p, --listening-port TURN listener port for UDP and TCP listeners (Default: 3478). + Note: actually, TLS & DTLS sessions can connect to the "plain" TCP & UDP + port(s), too - if allowed by configuration. + +--tls-listening-port TURN listener port for TLS and DTLS listeners (Default: 5349). + Note: actually, "plain" TCP & UDP sessions can connect to the TLS & DTLS + port(s), too - if allowed by configuration. The TURN server + "automatically" recognizes the type of traffic. Actually, two listening + 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. + For secure UDP connections, we support DTLS version 1. + +--alt-listening-port Alternative listening port for UDP and TCP listeners; + default (or zero) value means "listening port plus one". + This is needed for STUN CHANGE_REQUEST - in RFC 5780 sense + or in old RFC 3489 sense - for NAT behavior discovery). The TURN Server + supports CHANGE_REQUEST only if it is started with more than one + listening IP address of the same family (IPv4 or IPv6). The CHANGE_REQUEST + is only supported by UDP protocol, other protocols are listening + on that endpoint only for "symmetry". + +--alt-tls-listening-port Alternative listening port for TLS and DTLS protocols. + Default (or zero) value means "TLS listening port plus one". + +--aux-server Auxiliary STUN/TURN server listening endpoint. + Aux servers have almost full TURN and STUN functionality. + The (minor) limitations are: + 1) Auxiliary servers do not have alternative ports and + they do not support STUN RFC 5780 functionality (CHANGE REQUEST). + 2) Auxiliary servers also are never returning ALTERNATIVE-SERVER reply. + + Valid formats are 1.2.3.4:5555 for IPv4 and [1:2::3:4]:5555 for IPv6. + There may be multiple aux-server options, each will be used for listening + to client requests. + +-i, --relay-device Relay interface device for relay sockets + (NOT RECOMMENDED. Optional, Linux only). + +-E, --relay-ip Relay address (the local IP address that + will be used to relay the packets to the + peer). Multiple relay addresses may be used: + -E ip1 -E ip2 -E ip3 + The same IP(s) can be used as both listening IP(s) and relay IP(s). + If no relay IP(s) specified, then the turnserver will apply the + default policy: it will decide itself which relay addresses to be + used, and it will always be using the client socket IP address as + the relay IP address of the TURN session (if the requested relay + address family is the same as the family of the client socket). + +-X, --external-ip TURN Server public/private address mapping, if the server is behind NAT. + In that situation, if a -X is used in form "-X " then that ip will be reported + as relay IP address of all allocations. This scenario works only in a simple case + when one single relay address is be used, and no CHANGE_REQUEST functionality is + required. That single relay address must be mapped by NAT to the 'external' IP. + The "external-ip" value, if not empty, is returned in XOR-RELAYED-ADDRESS field. + For that 'external' IP, NAT must forward ports directly (relayed port 12345 + must be always mapped to the same 'external' port 12345). + In more complex case when more than one IP address is involved, + that option must be used several times, each entry must + have form "-X ", to map all involved addresses. + CHANGE_REQUEST (RFC5780 or RFC3489) NAT discovery STUN functionality will work + correctly, if the addresses are mapped properly, even when the TURN server itself + is behind A NAT. + By default, this value is empty, and no address mapping is used. + +-m, --relay-threads Number of relay threads to handle the established connections + (in addition to authentication thread and the listener thread). + If set to 0 then application runs relay process in a single thread, + in the same thread with the listener process (the authentication thread will + still be a separate thread). In older systems (before Linux kernel 3.9), + the number of UDP threads is always one threads per network listening endpoint - + unless "-m 0" or "-m 1" is set. + +--min-port Lower bound of the UDP port range for relay + endpoints allocation. + Default value is 49152, according to RFC 5766. + +--max-port Upper bound of the UDP port range for relay + endpoints allocation. + Default value is 65535, according to RFC 5766. + +-u, --user Long-term security mechanism credentials user account, + in the column-separated form username:key. + Multiple user accounts may used in the command line. + The key is either the user password, or + the key is generated + by turnadmin 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. + +-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 + server is not using any database (just the commands-line settings + and the userdb file). Must be used with long-term credentials + mechanism or with TURN REST API. + +-C, --rest-api-separator This is the timestamp/username separator symbol (character) in TURN REST API. + The default value is :. + +-q, --user-quota Per-user allocations quota: how many concurrent + allocations a user can create. This option can also be set + through the database, for a particular realm. + +-Q, --total-quota Total allocations quota: global limit on concurrent allocations. + This option can also be set through the database, for a particular realm. + +-s, --max-bps Max bytes-per-second bandwidth a TURN session is allowed to handle + (input and output network streams are treated separately). Anything above + that limit will be dropped or temporary suppressed (within the + available buffer limits). This option can also be set through the + database, for a particular realm. + +--static-auth-secret Static authentication secret value (a string) for TURN REST API only. + If not set, then the turn server will try to use the dynamic value + in turn_secret table in user database (if present). The database-stored + value can be changed on-the-fly by a separate program, so this is why + that other mode is dynamic. Multiple shared secrets can be used + (both in the database and in the "static" fashion). + +--cert Certificate file, PEM format. Same file + search rules applied as for the configuration + file. If both --no-tls and --no-dtls options + are specified, then this parameter is not needed. + Default value is turn_server_cert.pem. + +--pkey Private key file, PEM format. Same file + search rules applied as for the configuration + file. If both --no-tls and --no-dtls options + are specified, then this parameter is not needed. + Default value is turn_server_pkey.pem. + +--pkey-pwd If the private key file is encrypted, then this password to be used. + +--cipher-list Allowed OpenSSL cipher list for TLS/DTLS connections. + Default value is "DEFAULT". + +--CA-file CA file in OpenSSL format. + Forces TURN server to verify the client SSL certificates. + By default, no CA is set and no client certificate check is performed. + +--ec-curve-name Curve name for EC ciphers, if supported by OpenSSL library (TLS and DTLS). + The default value is prime256v1. + +--dh-file Use custom DH TLS key, stored in PEM format in the file. + Flags --dh566 and --dh2066 are ignored when the DH key is taken from a file. + +-l, --log-file Option to set the full path name of the log file. + By default, the turnserver tries to open a log file in + /var/log/turnserver, /var/log, /var/tmp, /tmp and . (current) + directories (which file open operation succeeds + first that file will be used). With this option you can set the + definite log file name. + The special names are "stdout" and "-" - they will force everything + to the stdout. Also, "syslog" name will redirect everything into + the system log (syslog), as if the option "--syslog" was set. + +--alternate-server Option to set the "redirection" mode. The value of this option + will be the address of the alternate server for UDP & TCP service in form of + [:]. The server will send this value in the attribute + ALTERNATE-SERVER, with error 300, on ALLOCATE request, to the client. + Client will receive only values with the same address family + as the client network endpoint address family. + See RFC 5389 and RFC 5766 for ALTERNATE-SERVER functionality description. + The client must use the obtained value for subsequent TURN communications. + If more than one --alternate-server options are provided, then the functionality + can be more accurately described as "load-balancing" than a mere "redirection". + If the port number is omitted, then the default port + number 3478 for the UDP/TCP protocols will be used. + Colon (:) characters in IPv6 addresses may conflict with the syntax of + the option. To alleviate this conflict, literal IPv6 addresses are enclosed + in square brackets in such resource identifiers, for example: + [2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478 . + Multiple alternate servers can be set. They will be used in the + round-robin manner. All servers in the pool are considered of equal weight and + the load will be distributed equally. For example, if we have 4 alternate servers, + then each server will receive 25% of ALLOCATE requests. An alternate TURN server + address can be used more than one time with the alternate-server option, so this + can emulate "weighting" of the servers. + +--tls-alternate-server Option to set alternative server for TLS & DTLS services in form of + :. If the port number is omitted, then the default port + number 5349 for the TLS/DTLS protocols will be used. See the previous option for the + functionality description. + +-O, --redis-statsdb Redis status and statistics database connection string, if used (default - empty, + no Redis stats DB used). This database keeps allocations status information, and it can + be also used for publishing and delivering traffic and allocation event notifications. + This database option can be used independently of --redis-userdb option, + and actually Redis can be used for status/statistics and MySQL or PostgreSQL can + be used for the user database. + The connection string has the same parameters as redis-userdb connection string. + +--max-allocate-timeout Max time, in seconds, allowed for full allocation establishment. + Default is 60 seconds. + +--denied-peer-ip= + +--allowed-peer-ip= Options to ban or allow specific ip addresses or ranges + of ip addresses. If an ip address is specified as both allowed and denied, then + the ip address is considered to be allowed. This is useful when you wish to ban + a range of ip addresses, except for a few specific ips within that range. + This can be used when you do not want users of the turn server to be able to access + machines reachable by the turn server, but would otherwise be unreachable from the + internet (e.g. when the turn server is sitting behind a NAT). The 'white" and "black" peer + IP ranges can also be dynamically changed in the database. + The allowed/denied addresses (white/black lists) rules are very simple: + 1) If there is no rule for an address, then it is allowed; + 2) If there is an "allowed" rule that fits the address then it is allowed - no matter what; + 3) If there is no "allowed" rule that fits the address, and if there is a "denied" rule that + fits the address, then it is denied. + +--pidfile File name to store the pid of the process. + Default is /var/run/turnserver.pid (if superuser account is used) or + /var/tmp/turnserver.pid . + +--proc-user User name to run the process. After the initialization, the turnserver process + will make an attempt to change the current user ID to that user. + +--proc-group Group name to run the process. After the initialization, the turnserver process + will make an attempt to change the current group ID to that group. + +--cli-ip Local system IP address to be used for CLI management interface. + The turnserver process can be accessed for management with telnet, + at this IP address and on the CLI port (see the next parameter). + Default value is 127.0.0.1. You can use telnet or putty (in telnet mode) + to access the CLI management interface. + +--cli-port CLI management interface listening port. Default is 5766. + +--cli-password CLI access password. Default is empty (no password). + +--cli-max-output-sessions Maximum number of output sessions in ps CLI command. + This value can be changed on-the-fly in CLI. The default value is 256. + +--ne=[1|2|3] Set network engine type for the process (for internal purposes). + +================================== + +LOAD BALANCE AND PERFORMANCE TUNING + +This topic is covered in the wiki page: + +http://code.google.com/p/coturn/wiki/turn_performance_and_load_balance + +=================================== + +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 +default realm (-r option). You will also have to set up the user accounts, +for that you have a number of options: + + a) command-line options (-u). + + b) userdb config file. + + c) a database table (PostgreSQL or MySQL). You will have to set keys with + turnadmin utility (see docs and wiki for turnadmin). You cannot use open passwords + in the database. + + d) Redis key/value pair(s), if Redis is used. You key use either keys or + open passwords with Redis; see turndb/testredisdbsetup.sh file. + + e) You also can use the TURN REST API. You will need shared secret(s) set + either through the command line option, or through the config file, or through + the database table or Redis key/value pairs. + +2) Usually WebRTC uses fingerprinting (-f). + +3) -v option may be nice to see the connected clients. + +4) -X is needed if you are running your TURN server behind a NAT. + +5) --min-port and --max-port may be needed if you want to limit the relay endpoints ports +number range. + +=================================== + +TURN REST API + +In WebRTC, the browser obtains the TURN connection information from the web +server. This information is a secure information - because it contains the +necessary TURN credentials. As these credentials are transmitted over the +public networks, we have a potential security breach. + +If we have to transmit a valuable information over the public network, +then this information has to have a limited lifetime. Then the guy who +obtains this information without permission will be able to perform +only limited damage. + +This is how the idea of TURN REST API - time-limited TURN credentials - +appeared. This security mechanism is based upon the long-term credentials +mechanism. The main idea of the REST API is that the web server provides +the credentials to the client, but those credentials can be used only +limited time by an application that has to create a TURN server connection. + +The "classic" long-term credentials mechanism (LTCM) is described here: + +http://tools.ietf.org/html/rfc5389#section-10.2 +http://tools.ietf.org/html/rfc5389#section-15.4 + +For authentication, each user must know two things: the username and the +password. Optionally, the user must supply the ORIGIN value, so that the +server can figure out the realm to be used for the user. The nonce and +the realm values are supplied by the TURN server. But LTCM is not saying +anything about the nature and about the persistence +of the username and of the password; and this is used by the REST API. + +In the TURN REST API, there is no persistent passwords for users. A user has +just the username. The password is always temporary, and it is generated by +the web server on-demand, when the user accesses the WebRTC page. And, +actually, a temporary one-time session only, username is provided to the user, +too. + +The temporary user is generated as: + +temporary-username="timestamp" + ":" + "username" + +where username is the persistent user name, and the timestamp format is just +seconds sinse 1970 - the same value as time(NULL) function returns. + +The temporary password is obtained as HMAC-SHA1 function over the temporary +username, with shared secret as the HMAC key, and then the result is encoded: + +temporary-password = base64_encode(hmac-sha1(shared-secret, temporary-username)) + +Both the TURN server and the web server know the same shared secret. How the +shared secret is distributed among the involved entities is left to the WebRTC +deployment details - this is beyond the scope of the TURN REST API. + +So, a timestamp is used for the temporary password calculation, and this +timestamp can be retrieved from the temporary username. This information +is valuable, but only temporary, while the timestamp is not expired. Without +knowledge of the shared secret, a new temporary password cannot be generated. + +This is all formally described in Justin's Uberti TURN REST API document +that can be obtained following the link "TURN REST API" in the TURN Server +project's page http://code.google.com/p/coturn/. + +Once the temporary username and password are obtained by the client (browser) +application, then the rest is just 'classic" long-term credentials mechanism. +For developers, we are going to describe it step-by-step below: + + - a new TURN client sends a request command to the TURN server. + - TURN server sees that this is a new client and the message is not + authenticated. + - the TURN server generates a random nonce string, and return the + error 401 to the client, with nonce and realm included. + - the client sees the 401 error and it extracts two values from + the error response: the nonce and the realm. + - the client uses username, realm and password to produce a key: + + key = MD5(username ":" realm ":" SASLprep(password)) + (SASLprep is described here: http://tools.ietf.org/html/rfc4013) + + - the client forms a new request, adds username, realm and nonce to the + request. Then, the client calculates and adds the integrity field to + the request. This is the trickiest part of the process, and it is + described in the end of section 15.4: + http://tools.ietf.org/html/rfc5389#section-15.4 + - the client, optionally, adds the fingerprint field. This may be also + a tricky procedure, described in section 15.5 of the same document. + WebRTC usually uses fingerprinted TURN messages. + - the TURN server receives the request, reads the username. + - then the TURN server checks that the nonce and the realm in the request + are the valid ones. + - then the TURN server calculates the key. + - then the TURN server calculates the integrity field. + - then the TURN server compares the calculated integrity field with the + received one - they must be the same. If the integrity fields differ, + then the request is rejected. + +In subsequent communications, the client may go with exactly the same +sequence, but for optimization usually the client, having already +information about realm and nonce, pre-calculates the integrity string +for each request, so that the 401 error response becomes unnecessary. +The TURN server may use "--stale-nonce" option for extra security: in +some time, the nonce expires and the client will obtain 438 error response +with the new nonce, and the client will have to start using the new nonce. + +In subsequent communications, the sever and the client will always assume +the same password - the original password becomes the session parameter and +is never expiring. So the password is not changing while the session is valid +and unexpired. So, if the session is properly maintained, it may go forever, +even if the user password has been already changed (in the database). The +session simply is using the old password. Once the session got disconnected, +the client will have to use the new password to re-connect (if the password +has been changed). + +An example when a new shared secret is generated every hour by the TURN server +box and then supplied to the web server, remotely, is provided in the script +examples/scripts/restapi/shared_secret_maintainer.pl . + +A very important thing is that the nonce must be totally random and it must be +different for different clients and different sessions. + +=================================== + +DATABASES + +For the user database, the turnserver has the following options: + +1) Users can be set in the command line, with multiple -u or --user options. +Obviously, only a few users can be set that way, and their credentials are fixed +for the turnserver process lifetime. + +2) Users can be set in turnusers.conf flat file DB. The turnserver process periodically +re-reads this file, so the user accounts may be changed while the turnserver is running. +But still a relatively small (up to a hundred ?) number of users can be handled that way. + +3) Users can be stored in PostgreSQL database, if the turnserver was compiled with PostgreSQL +support. Each time turnserver checks user credentials, it reads the database (asynchronously, +of course, so that the current flow of packets is not delayed in any way), so any change in the +database content is immediately visible by the turnserver. This is the way if you need the +best scalability. The schema for the database can be found in schema.sql file. +For long-term credentials, you have to set the "keys" for the users; the "keys" are generated +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. + +4) The same is true for MySQL database. The same schema file is applicable. +The same considerations are applicable. + +5) The same is true for the Redis database, but the Redis database has aa different schema - +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. + +6) Of course, the turnserver can be used in non-secure mode, when users are allowed to establish +sessions anonymously. But in most cases (like WebRTC) that will not work. + +For the status and statistics database, there are two choices: + +1) The simplest choice is not to use it. Do not set --redis-statsdb option, and this functionality +will be simply ignored. + +2) If you choose to use it, then set the --redis-statsdb option. This may be the same database +as in --redis-userdb option, or it may be a different database. You may want to use different +database for security or convenience reasons. Also, you can use different database management +systems for the user database and for the ststus and statistics database. For example, you can use +MySQL as the user database, and you can use redis for the statistics. Or you can use Redis for both. + +So, we have 6 choices for the user management, and 2 choices for the statistics management. These +two are totally independent. So, you have overall 6*2=12 ways to handle persistent information, +choose any for your convenience. + +You do not have to handle the database information "manually" - the turnadmin program can handle +everything for you. For PostgreSQL and MySQL you will just have to create an empty database +with schema.sql SQL script. With Redis, you do not have to do even that - just run turnadmin and +it will set the users for you (see the turnadmin manuals). + +================================= + +LIBRARIES + +In the lib/ sub-directory the build process will create TURN client messaging library. +In the include/ sub-directory, the necessary include files will be placed. +The C++ wrapper for the messaging functionality is located in TurnMsgLib.h header. +An example of C++ code can be found in stunclient.c file. + +================================= + +DOCS + +After installation, run the command: + +$ man turnserver + +or in the project root directory: + +$ man -M man turnserver + +to see the man page. + +In the docs/html subdirectory of the original archive tree, you will find the client library +reference. After the installation, it will be placed in PREFIX/share/doc/turnserver/html. + +================================= + +LOGS + +When the TURN Server starts, it makes efforts to create a log file turn_.log +in the following directories: + + * /var/log + * /log/ + * /var/tmp + * /tmp + * 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. + +This behavior can be controlled by --log-file, --syslog and --no-stdout-log options. + +================================= + +TELNET CLI + +The turnserver process provides a telnet CLI access as statistics and basic management +interface. By default, the turnserver starts a telnet CLI listener on IP 127.0.0.1 and +port 5766. That can be changed by the command-cline options of the turnserver process +(see --cli-ip and --cli-port options). The full list of telnet CLI commands is provided +in "help" command output in the telnet CLI. + +================================= + +CLUSTERS + +TURN Server can be a part of the cluster installation. But, to support the "even port" functionality +(RTP/RTCP streams pairs) the client requests from a particular IP must be delivered to the same +TURN Server instance, so it requires some networking setup massaging for the cluster. The reason is that +the RTP and RTCP relaying endpoints must be allocated on the same relay IP. It would be possible +to design a scheme with the application-level requests forwarding (and we may do that later) but +it would affect the performance. + +================================= + +FILES + +/etc/turnserver.conf + +/etc/turnuserdb.conf + +/usr/local/etc/turnserver.conf + +/usr/local/etc/turnuserdb.conf + +================================= + +DIRECTORIES + +/usr/local/share/turnserver + +/usr/local/share/doc/turnserver + +/usr/local/share/examples/turnserver + +================================= + +STANDARDS + +obsolete STUN RFC 3489 + +new STUN RFC 5389 + +TURN RFC 5766 + +TURN-TCP extension RFC 6062 + +TURN IPv6 extension RFC 6156 + +STUN/TURN test vectors RFC 5769 + +STUN NAT behavior discovery RFC 5780 + +================================= + +SEE ALSO + + turnadmin, turnutils + +====================================== + + WEB RESOURCES + + project page: + + http://code.google.com/p/coturn/ + + Wiki page: + + http://code.google.com/p/coturn/wiki/Readme + + forum: + + https://groups.google.com/forum/?fromgroups=#!forum/turn-server-project-rfc5766-turn-server/ + +====================================== + + AUTHORS + + Oleg Moskalenko + + Gabor Kovesdan http://kovesdan.org/ + + Daniel Pocock http://danielpocock.com/ + + John Selbie (jselbie@gmail.com) + + Lee Sylvester + + Erik Johnston + + Roman Lisagor + + Vladimir Tsanev + + Po-sheng Lin + + Peter Dunkley + + Mutsutoshi Yoshimoto diff --git a/README.turnutils b/README.turnutils new file mode 100644 index 00000000..e0c7c8c8 --- /dev/null +++ b/README.turnutils @@ -0,0 +1,329 @@ +GENERAL INFORMATION + +A set of turnutils_* programs provides some utility functionality to be used +for testing and for setting up the TURN server. + +1. turnutils_uclient: emulates multiple UDP,TCP,TLS or DTLS clients. +(this program is provided for the testing purposes only !) +The compiled binary image of this program is located in bin/ +sub-directory. + +WARNING: the turnutils_uclient program is a primitive client application. +It does not implement the re-transmission pattern that is necessary for +a correct TURN client implementation. In TURN, the retransmission burden +is lying almost entirely on the client application. We provide the messaging +functionality in the client library, but the client must implement +the correct Networking IO processing in the client program code. + +2. turnutils_peer: a simple stateless UDP-only "echo" server, +to be used as the final server in relay pattern ("peer"). For every incoming +UDP packet, it simply echoes it back. +(this program is provided for the testing purposes only !) +When the test clients are communicating in the client-to-client manner +(when the "turnutils_uclient" program is used with "-y" option) then the +turnutils_peer is not needed. + +The compiled binary image of this program is located in bin/ subdirectory. + +3. turnutils_stunclient: a simple STUN client example. +The compiled binary image of this program is located in bin/ subdirectory. + +4. turnutils_rfc5769check: a utility that checks the correctness of the +STUN/TURN protocol implementation. This utility is used only for the compilation +check procedure, it is not copied to the installation destination. + + +In the "examples/scripts" subdirectory, you will find the examples of command lines to be used +to run the programs. The scripts are meant to be run from examples/ subdirectory, for example: + +$ cd examples + +$ ./scripts/secure_relay.sh + +===================================== + + NAME + +turnutils_uclient - this client emulation application is supplied for the test purposes only. + + SYNOPSIS + +$ turnutils_uclient [-tTSvsyhcxg] [options] + + DESCRIPTION + +It was designed to simulate multiple clients. It uses asynch IO API in +libevent to handle multiple clients. A client connects to the relay, +negotiates the session, and sends multiple (configured number) messages to the server (relay), +expecting the same number of replies. The length of the messages is configurable. +The message is an arbitrary octet stream, but it can be configured as a string. +The number of the messages to send is configurable. + +Flags: + +-t Use TCP for communications between client and TURN server (default is UDP). + +-T Use TCP for the relay transport (default - UDP). Implies options -t, -y, -c, + and ignores flags and options -s, -e, -r and -g. + +-P Passive TCP (RFC6062 with active peer). Implies -T. + +-S Secure SSL connection: SSL/TLS for TCP, DTLS for UDP. + +-U Secure unencrypted connection (suite eNULL): SSL/TLS for TCP, DTLS for UDP. + +-v Verbose. + +-s Use "Send" method in TURN; by default, it uses TURN Channels. + +-y Use client-to-client connections: + RTP/RTCP pair of channels to another RTP/RTCP pair of channels. + with this option the turnutils_peer application is not used, + as the allocated relay endpoints are talking to each other. + +-h Hang on indefinitely after the last sent packet. + +-c Do not create rtcp connections. + +-x Request IPv6 relay address (RFC6156). + +-X IPv4 relay address explicitly requested. + +-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). + +-R do negative protocol tests. + +-O DOS attack mode. + +-H SHA256 digest function for message integrity calculation. + Without this option, by default, SHA1 is used. + +-M Use TURN ICE Mobility. + +-I Do not set permissions on TURN relay endpoints + (for testing the non-standard server relay functionality). + +-G Generate extra requests (create permissions, channel bind). + +Options with required values: + +-l Message length (Default: 100 Bytes). + +-i Certificate file (for secure connections only, optional). + +-k Private key file (for secure connections only). + +-E CA file for server certificate verification, + if the server certificate to be verified. + +-p TURN Server port (Defaults: 3478 unsecure, 5349 secure). + +-n Number of messages to send (Default: 5). + +-d Local interface device (optional, Linux only). + +-L Local IP address (optional). + +-m Number of clients (Default: 1, 2 or 4, depending on options). + +-e Peer address. + +-r Peer port (Default: 3480). + +-z Per-session packet interval in milliseconds (Default: 20). + +-u STUN/TURN user name. + +-w STUN/TURN user password. + +-W TURN REST API authentication secret. Is not compatible with -A flag. + +-C This is the timestamp/username separator symbol (character) in + TURN REST API. The default value is :. + +-F Cipher suite for TLS/DTLS. Default value is DEFAULT. + +See the examples in the "examples/scripts" directory. + +====================================== + + NAME + +turnutils_peer - a simple UDP-only echo backend server. + + SYNOPSYS + +$ turnutils_peer [-v] [options] + + DESCRIPTION + +This application is used for the test purposes only, as a peer for the turnutils_uclient application. + +Options with required values: + +-p Listening UDP port (Default: 3480). + +-d Listening interface device (optional) + +-L Listening address of turnutils_peer server. Multiple listening addresses can be used, IPv4 and IPv6. +If no listener address(es) defined, then it listens on all IPv4 and IPv6 addresses. + +-v Verbose + +======================================== + + NAME + +turnutils_stunclient - a basic STUN client. + + SYNOPSIS + +$ turnutils_stunclient [options] + + DESCRIPTION + +It sends a "new" STUN RFC 5389 request (over UDP) and shows the reply information. + +Options with required values: + +-p STUN server port (Default: 3478). + +-L Local address to use (optional). + +-f Force RFC 5780 processing. + +The turnutils_stunclient program checks the results of the first request, +and if it finds that the STUN server supports RFC 5780 +(the binding response reveals that) then the turnutils_stunclient makes a couple more +requests with different parameters, to demonstrate the NAT discovery capabilities. + +This utility does not support the "old" "classic" STUN protocol (RFC 3489). + +===================================== + + NAME + +turnutils_rfc5769check - a utility that tests the correctness of STUN protocol implementation. + + SYNOPSIS + + $ turnutils_rfc5769check + + DESCRIPTION + +turnutils_rfc5769check tests the correctness of STUN protocol implementation +against the test vectors predefined in RFC 5769 and prints the results of the +tests on the screen. This utility is used only for the compilation +check procedure, it is not copied to the installation destination. + +Usage: + +$ turnutils_rfc5769check + +=================================== + +DOCS + +After installation, run the command: + +$ man turnutils + +or in the project root directory: + +$ man -M man turnutils + +to see the man page. + +===================================== + +FILES + +/etc/turnserver.conf + +/etc/turnuserdb.conf + +/usr/local/etc/turnserver.conf + +/usr/local/etc/turnuserdb.conf + +================================= + +DIRECTORIES + +/usr/local/share/turnserver + +/usr/local/share/doc/turnserver + +/usr/local/share/examples/turnserver + +=================================== + +STANDARDS + +new STUN RFC 5389 + +TURN RFC 5766 + +TURN-TCP extension RFC 6062 + +TURN IPv6 extension RFC 6156 + +STUN/TURN test vectors RFC 5769 + +STUN NAT behavior discovery RFC 5780 + +==================================== + +SEE ALSO + + turnserver, turnadmin + +====================================== + + WEB RESOURCES + + project page: + + http://code.google.com/p/coturn/ + + Wiki page: + + http://code.google.com/p/coturn/wiki/Readme + + forum: + + https://groups.google.com/forum/?fromgroups=#!forum/turn-server-project-rfc5766-turn-server/ + +====================================== + + AUTHORS + + Oleg Moskalenko + + Gabor Kovesdan http://kovesdan.org/ + + Daniel Pocock http://danielpocock.com/ + + John Selbie (jselbie@gmail.com) + + Lee Sylvester + + Erik Johnston + + Roman Lisagor + + Vladimir Tsanev + + Po-sheng Lin + + Peter Dunkley + + Mutsutoshi Yoshimoto diff --git a/STATUS b/STATUS new file mode 100644 index 00000000..8febb474 --- /dev/null +++ b/STATUS @@ -0,0 +1,101 @@ +Currently implemented functionality: + +1) RFC5389 (new STUN protocol) full server and client +implementations. We do not maintain strict compatibility +with the obsolete RFC 3489 "old STUN" protocol. + +2) RFC5766 TURN protocol full server and client +implementations. We support file-based long term +user credentials, for now. We added experimental DTLS +protocol, too. + +3) RFC6156 TURN IPv6 extension. + +4) We support the following client-to-server +network transports for TURN messages: + a) UDP + b) TCP + c) TLS + d) DTLS + +5) Performance tested. + +6) Torture and stability tests. + +7) Multiple *NIX platforms tested and supported. + +8) TTL field handling implemented for all platforms, preferred behavior in RFC5766. + +9) TOS (DiffServ and ECN) field handling (preferred behavior of RFC 5766) implemented, +for Linux. Other platforms support the alternative behavior of RFC 5766. + +10) DF field alternative behavior of RFC 5766 implemented. + +11) Bandwidth limitation per session implemented. + +12) RFC 5769 test vectors implemented (where applicable). + +13) RFC 5780 STUN extension: NAT behavior discovery. + +14) C++ mapping implemented. + +15) RFC 6062 TCP relaying implemented. + +16) Users can be stored in PostgreSQL database. + +17) Users can be stored in MySQL database. + +18) TURN Server REST API implemented. + +19) Short-term credentials mechanism implemented. + +20) Simple load-balancing with ALTERNATE-SERVER implemented. + +21) Redis database support added. + +22) RFC3489 backward compatibility. + +23) Multithreaded TCP relay processing (UDP relay has been +multithreaded from the beginning). + +24) Networking engine 2.0 implemented, with more scalable approach +to the UDP sockets handling. + +25) DOS attack prevention logic added to the server; DOS attack client +emulation implemented. + +26) Linux UDP sockets workaround added to counter RFC 1122 behavior. + +27) DTLS sockets re-implemented for better scalability and for Cygwin +compatibility. + +28) A number of TLS/DTLS improvements added: multiple protocols support, certificate check option. + +29) SHA256 support added (experimental). + +30) UDP network engine optimized for the new Linux kernels (3.9+). + +31) ICE Mobility draft implemented (experimental). + +32) CLI implemented. + +33) DH and EC TLS ciphers added. + +34) HTTP "keep alive" request supported. + +35) Optimized (for thousands and more sessions) timers implementation. + +36) TCP network engine optimized for the new Linux kernels (3.9+). + +37) telnet-based monitor implemented. + +38) Package memory copy eliminated in traffic routing. + +39) Congestion avoidance implemented, for all protocols. + +40) Multi-tenant server implemented. + +41) Coturn project forked from rfc5766-turn-server. + +Things to be implemented in future (the development roadmap) +are described in the TODO file. diff --git a/TODO b/TODO new file mode 100644 index 00000000..fa334dea --- /dev/null +++ b/TODO @@ -0,0 +1,128 @@ +================================================================== + +### I. PLATFORMS SUPPORT ### + +================================================================== + +1) Fedora official package (turnserver or coturn ? TBD). + +2) MS Windows support. + + Cygwin is supported. A "real" MS-Windows port would + involve a usable GUI. + +================================================================== + +### II. DOCS ### + +================================================================== + +1) User's manual. + +2) Developer's manual. + +================================================================== + +### III. NETWORK ENGINE ### + +================================================================== + +1) Exclusive IP addresses for relay + +================================================================== + +### IV. PERFORMANCE OPTIMIZATION ### + +================================================================== + +1) A smarter load balancer has to be implemented. + + The load balancer has to have a heartbeat channels with + the slave servers, currently it is only just a dumb + round-robin load distributor. + +2) For a large enterprise, a user-space stack to be integrated. + + An another socket abstraction to be implemented, + the one that uses the user-space TCP/IP stack with + zero memory copy. This is an ambitious goal that would + increase the system scaleability, significantly. + The stock TCP/IP stack in UNIX and in MS Windows do not + scale gracefully. We are trying to suppress those issues + in the TURN Server, by using an advanced synchronous + I/O technique, but still the underlying stock TCP/IP stack + is a limitation. + +3) Multiple authentication threads. + +================================================================== + +### V. SECURITY ### + +================================================================== + +1) RADIUS integration ? + +2) Watch new TURN security draft. oAuth integration. + +================================================================== + +### VI. STANDARDS SUPPORT ### + +================================================================== + +1) Follow the draft ICE endpoint mobility standard and add changes +when necessary: + + https://ietf.org/doc/draft-wing-mmusic-ice-mobility/ + +2) For extra difficult NAT/FWs, consider implementing Websockets. + +3) MS TURN, MS STUN extensions. + +4) Bandwidth draft. + +5) ALPN with TLS and DTLS. + +6) Redirect draft. + +================================================================== + +### VII. MISC FEATURES ### + +================================================================== + +1) Locale support (?). + + Currently we assume that all text data is 8-bits ASCII + encoded, like C locale. It would be nice to support localized + strings (both 8-bits and 2-bytes). But I am not sure + whether this is really important, given the essentially + backend nature of the TURN Server. The TURN server is so + 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). + + That would be a helpful feature for a large enterprise + (for testing and security purposes). + +4) Ganglia monitoring. + +================================================================== + +### VIII. CODING STUFF ### + +================================================================== + +Nope + +================================================================== + diff --git a/configure b/configure new file mode 100755 index 00000000..c09a3b64 --- /dev/null +++ b/configure @@ -0,0 +1,1063 @@ +#!/bin/sh + +# Proprietary configure script of Coturn project + +cleanup() { + rm -rf ${TMPCPROGC} + rm -rf ${TMPCPROGB} + rm -rf ${TH_TMPCPROGC} + rm -rf ${TH_TMPCPROGB} + rm -rf ${DTLS_TMPCPROGC} + rm -rf ${DTLS_TMPCPROGB} + rm -rf ${PQ_TMPCPROGC} + rm -rf ${PQ_TMPCPROGB} + rm -rf ${MYSQL_TMPCPROGC} + rm -rf ${MYSQL_TMPCPROGB} + rm -rf ${D_TMPCPROGC} + rm -rf ${D_TMPCPROGB} + rm -rf ${E_TMPCPROGC} + rm -rf ${E_TMPCPROGO} + rm -rf ${HR_TMPCPROGC} + rm -rf ${HR_TMPCPROGB} + rm -rf ${TMPCADDRPROGO} +} + +testlibraw() { + ${CC} ${TMPCPROGC} -o ${TMPCPROGB} ${OSCFLAGS} ${OSLIBS} -${1} 2>>/dev/null + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "Do not use -${1}" + return 0 + else + OSLIBS="${OSLIBS} -${1}" + return 1 + fi +} + +testlibevent2_comp() { + ${CC} -c ${E_TMPCPROGC} -o ${E_TMPCPROGO} ${OSCFLAGS} 2>>/dev/null + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "Libevent2 development is not installed properly" + return 0 + else + return 1 + fi +} + +testhiredis() { + HIREDISCFLAGS= + HIREDISLIBS=-lhiredis + ${CC} ${HR_TMPCPROGC} -o ${HR_TMPCPROGB} ${OSCFLAGS} ${DBLIBS} ${HIREDISCFLAGS} ${HIREDISLIBS} 2>>/dev/null + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} + ${ECHO_CMD} "HIREDIS DEVELOPMENT LIBRARY (libhiredis.*) AND/OR HEADERS (hiredis/*.h)" + ${ECHO_CMD} " ARE NOT INSTALLED PROPERLY ON THIS SYSTEM." + ${ECHO_CMD} " THAT'S OK BUT THE TURN SERVER IS BUILDING WITHOUT REDIS SUPPORT." + ${ECHO_CMD} + return 0 + else + DBCFLAGS="${DBCFLAGS} ${HIREDISCFLAGS}" + DBLIBS="${DBLIBS} ${HIREDISLIBS}" + return 1 + fi +} + +testlibpq() { + POSTCFLAGS="-I${PREFIX}/pgsql/include -I${PREFIX}/include/pgsql/ -I${PREFIX}/include/postgres/ -I${PREFIX}/postgres/include/ -I${PREFIX}/include/postgresql/ -I${PREFIX}/postgresql/include/" + POSTCFLAGS="${POSTCFLAGS} -I/usr/local/pgsql/include -I/usr/local/include/pgsql/ -I/usr/local/include/postgres/ -I/usr/local/postgres/include/ -I/usr/local/include/postgresql/ -I/usr/local/postgresql/include/" + POSTCFLAGS="${POSTCFLAGS} -I/usr/pgsql/include -I/usr/include/pgsql/ -I/usr/include/postgres/ -I/usr/postgres/include/ -I/usr/include/postgresql/ -I/usr/postgresql/include/" + for ilib in ${PREFIX}/pgsql/lib ${PREFIX}/lib/pgsql ${PREFIX}/lib64/pgsql /usr/local/pgsql/lib /usr/local/lib/pgsql /usr/local/lib64/pgsql /usr/pgsql/lib /usr/lib/pgsql /usr/lib64/pgsql ${PREFIX}/postgres/lib ${PREFIX}/lib/postgres ${PREFIX}/lib64/postgres /usr/local/postgres/lib /usr/local/lib/postgres /usr/local/lib64/postgres /usr/postgres/lib /usr/lib/postgres /usr/lib64/postgres ${PREFIX}/postgresql/lib ${PREFIX}/lib/postgresql ${PREFIX}/lib64/postgresql /usr/local/postgresql/lib /usr/local/lib/postgresql /usr/local/lib64/postgresql /usr/postgresql/lib /usr/lib/postgresql /usr/lib64/postgresql + do + if [ -d ${ilib} ] ; then + POSTLIBS="${POSTLIBS} -L${ilib}" + if ! [ -z "${TURN_ACCEPT_RPATH}" ] ; then + TURN_RPATH="${TURN_RPATH} -Wl,-rpath,${ilib}" + fi + fi + done + POSTLIBS="${OSLIBS} ${POSTLIBS} -lpq" + ${CC} ${PQ_TMPCPROGC} -o ${PQ_TMPCPROGB} ${OSCFLAGS} ${DBCFLAGS} ${POSTCFLAGS} ${DBLIBS} ${POSTLIBS} ${OSLIBS} 2>>/dev/null + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} + ${ECHO_CMD} "POSTGRESQL DEVELOPMENT LIBRARY (libpq.a) AND/OR HEADER (libpq-fe.h)" + ${ECHO_CMD} " ARE NOT INSTALLED PROPERLY ON THIS SYSTEM." + ${ECHO_CMD} " THAT'S OK BUT THE TURN SERVER IS BUILDING WITHOUT POSTGRESQL DATABASE SUPPORT." + ${ECHO_CMD} + return 0 + else + DBCFLAGS="${DBCFLAGS} ${POSTCFLAGS}" + DBLIBS="${DBLIBS} ${POSTLIBS}" + return 1 + fi +} + +testlibmysql() { + MYSQL_CFLAGS="-I${PREFIX}/mysql/include -I${PREFIX}/include/mysql/" + MYSQL_CFLAGS="${MYSQL_CFLAGS} -I/usr/local/mysql/include -I/usr/local/include/mysql/" + MYSQL_CFLAGS="${MYSQL_CFLAGS} -I/usr/mysql/include -I/usr/include/mysql/" + for ilib in ${PREFIX}/mysql/lib ${PREFIX}/lib/mysql ${PREFIX}/lib64/mysql /usr/local/mysql/lib /usr/local/lib/mysql /usr/local/lib64/mysql /usr/mysql/lib /usr/lib/mysql /usr/lib64/mysql + do + if [ -d ${ilib} ] ; then + MYSQL_LIBS="${MYSQL_LIBS} -L${ilib}" + if ! [ -z "${TURN_ACCEPT_RPATH}" ] ; then + TURN_RPATH="${TURN_RPATH} -Wl,-rpath,${ilib}" + fi + fi + done + MYSQL_LIBS="${OSLIBS} ${MYSQL_LIBS} -lmysqlclient" + ${CC} ${MYSQL_TMPCPROGC} -o ${MYSQL_TMPCPROGB} ${OSCFLAGS} ${DBCFLAGS} ${DBLIBS} ${MYSQL_CFLAGS} ${MYSQL_LIBS} ${OSLIBS} 2>>/dev/null + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} + ${ECHO_CMD} "MYSQL DEVELOPMENT LIBRARY (libmysqlclient) AND/OR HEADER (mysql.h)" + ${ECHO_CMD} " ARE NOT INSTALLED PROPERLY ON THIS SYSTEM." + ${ECHO_CMD} " THAT'S OK BUT THE TURN SERVER IS BUILDING WITHOUT MYSQL DATABASE SUPPORT." + ${ECHO_CMD} + return 0 + else + DBCFLAGS="${DBCFLAGS} ${MYSQL_CFLAGS}" + DBLIBS="${DBLIBS} ${MYSQL_LIBS}" + return 1 + fi +} + +testlib() { + testlibraw l${1} +} + +pthread_testlib() { + + SYSTEM=`uname` + + if [ "${SYSTEM}" = "DragonFly" ] ; then + OSLIBS="${OSLIBS} -pthread" + fi + + ISBSD=`uname | grep -i bsd` + if ! [ -z "${ISBSD}" ] ; then + OSLIBS="${OSLIBS} -pthread" + fi + + if [ -z "${PTHREAD_LIBS}" ] ; then + ${CC} ${TH_TMPCPROGC} -o ${TH_TMPCPROGB} ${OSCFLAGS} ${OSLIBS} 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + return 1 + else + ${CC} ${TH_TMPCPROGC} -o ${TH_TMPCPROGB} ${OSCFLAGS} ${OSLIBS} -pthread 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + OSLIBS="${OSLIBS} -pthread" + return 1 + else + ${CC} ${TH_TMPCPROGC} -o ${TH_TMPCPROGB} ${OSCFLAGS} ${OSLIBS} -lpthread 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + OSLIBS="${OSLIBS} -lpthread" + return 1 + fi + fi + fi + else + OSLIBS="${OSLIBS} ${PTHREAD_LIBS}" + fi + + + ${CC} ${TH_TMPCPROGC} -o ${TH_TMPCPROGB} ${OSCFLAGS} ${OSLIBS} 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + return 1 + else + ${CC} ${TH_TMPCPROGC} -o ${TH_TMPCPROGB} ${OSCFLAGS} ${OSLIBS} -D_GNU_SOURCE 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "Older GNU pthread library found" + OSCFLAGS="${OSCFLAGS} -D_GNU_SOURCE" + return 1 + else + ${ECHO_CMD} "Do not use pthreads" + fi + fi + + return 0 +} + +pthread_testbarriers() { + + ${ECHO_CMD} "pthread_barrier_t barrier;" >> ${TH_TMPCPROGC} + ${CC} ${TH_TMPCPROGC} -o ${TH_TMPCPROGB} ${OSCFLAGS} ${OSLIBS} 2>>/dev/null + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "pthread barriers not found" + OSCFLAGS="${OSCFLAGS} -DTURN_NO_THREAD_BARRIERS" + fi +} + +dtls_testlib() { + + if [ -z "${TURN_NO_DTLS}" ] ; then + ${CC} ${DTLS_TMPCPROGC} -o ${DTLS_TMPCPROGB} ${OSCFLAGS} ${OSLIBS} 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + return 1 + else + return 0 + fi + else + return 0 + fi +} + +testdaemon() { + + ${CC} ${D_TMPCPROGC} -o ${D_TMPCPROGB} ${OSCFLAGS} ${OSLIBS} 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + OSCFLAGS="${OSCFLAGS} -DTURN_HAS_DAEMON" + fi +} + +test_sin_len() { + TMPCADDRPROGC=src/client/ns_turn_ioaddr.c + ${CC} -c ${OSCFLAGS} -DTURN_HAS_SIN_LEN -Isrc ${TMPCADDRPROGC} -o ${TMPCADDRPROGO} 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + OSCFLAGS="${OSCFLAGS} -DTURN_HAS_SIN_LEN" + ${ECHO_CMD} "Sockets code is fine: sin_len field present" + else + ${CC} -c ${OSCFLAGS} -Isrc ${TMPCADDRPROGC} -o ${TMPCADDRPROGO} 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "Sockets code is fine: no sin_len field present" + else + ${ECHO_CMD} "WARNING: trial compilation failed: src/client/ns_turn_ioaddr.c" + fi + fi +} + +######################### +# Start +######################### + +cleanup + +######################### +# To be set: +######################### + +if [ -z "${ECHO_CMD}" ] ; then + ECHO_CMD=echo +fi + +if [ -z "${PORTNAME}" ] ; then + PORTNAME=turnserver +fi + +######################### + +# Installation directory options + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=BINDIR ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + BINDIR=$ac_optarg ;; + + -datadir | --datadir | --datadi | --datad | -schemadir | --schemadir) + ac_prev=SCHEMADIR ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | -schemadir=* | --schemadir=*) + SCHEMADIR=$ac_optarg ;; + + -docdir | --docdir | --docdi | --doc | --do | -docsdir | --docsdir | --docsdi | --docs) + ac_prev=DOCDIR ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=* | -docsdir=* | --docsdir=* | --docsdi=* | --docs=*) + DOCSDIR=$ac_optarg ;; + + -examplesdir | --examplesdir | -examples | --examples) + ac_prev=EXAMPLESDIR ;; + -examplesdir=* | --examplesdir=* | -examples=* | --examples=*) + EXAMPLESDIR=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=INCLUDEDIR ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + INCLUDEDIR=$ac_optarg ;; + + -turnincludedir | --turnincludedir) + ac_prev=TURNINCLUDEDIR ;; + -turnincludedir=* | --turnincludedir=*) + TURNINCLUDEDIR=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=LIBDIR ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + LIBDIR=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m | -manprefix | --manprefix) + ac_prev=MAXPREFIX ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=* | -manprefix=* | --manprefix=*) + MANPREFIX=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=PREFIX ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + PREFIX=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy | -confdir | --confdir) + ac_prev=CONFDIR ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=* | -confdir=* | --confdir=*) + CONFDIR=$ac_optarg ;; + + -disable-rpath | --disable-rpath) + TURN_DISABLE_RPATH=1 ;; + + esac + +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +############################################# + +if [ -z "${PREFIX}" ] ; then + + if [ -z "${prefix}" ] ; then + + SYSTEM=`uname` + + if [ "${SYSTEM}" = "NetBSD" ] ; then + # A little tough guy + PREFIX=/usr/pkg + elif [ "${SYSTEM}" = "SunOS" ] ; then + # A fat guy + PREFIX=/usr + else + # An ordinary person + PREFIX=/usr/local + fi + else + PREFIX=${prefix} + fi +fi + +if [ -z "${BINDIR}" ] ; then + if [ -z "${bindir}" ] ; then + BINDIR=${PREFIX}/bin + else + BINDIR=${bindir} + fi +fi + +if [ -z "${CONFDIR}" ] ; then + if [ -z "${confdir}" ] ; then + CONFDIR=${PREFIX}/etc + else + CONFDIR=${confdir} + fi +fi + +if [ -z "${MANPREFIX}" ] ; then + if [ -z "${manprefix}" ] ; then + MANPREFIX=${PREFIX} + else + MANPREFIX=${manprefix} + fi +fi + +if [ -z "${EXAMPLESDIR}" ] ; then + if [ -z "${examplesdir}" ] ; then + EXAMPLESDIR=${PREFIX}/share/examples/${PORTNAME} + else + EXAMPLESDIR=${examplesdir} + fi +fi + +if [ -z "${DOCSDIR}" ] ; then + if [ -z "${docsdir}" ] ; then + DOCSDIR=${PREFIX}/share/doc/${PORTNAME} + else + DOCSDIR=${docsdir} + fi +fi + +if [ -z "${LIBDIR}" ] ; then + if [ -z "${libdir}" ] ; then + LIBDIR=${PREFIX}/lib + else + LIBDIR=${libdir} + fi +fi + +if [ -z "${SCHEMADIR}" ] ; then + if [ -z "${schemadir}" ] ; then + SCHEMADIR=${PREFIX}/share/${PORTNAME} + else + SCHEMADIR=${schemadir} + fi +fi + +if [ -z "${INCLUDEDIR}" ] ; then + if [ -z "${includedir}" ] ; then + INCLUDEDIR=${PREFIX}/include + else + INCLUDEDIR=${includedir} + fi +fi + +if [ -z "${TURNINCLUDEDIR}" ] ; then + if [ -z "${turnincludedir}" ] ; then + TURNINCLUDEDIR=${INCLUDEDIR}/turn + else + TURNINCLUDEDIR=${turnincludedir} + fi +fi + +############################################### + +if [ -z "${ARCHIVERCMD}" ] ; then + ARCHIVERCMD="ar -r" +fi + +if [ -z "${MORECMD}" ]; then + type more 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + MORECMD="more" + else + type less 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + MORECMD="less" + else + MORECMD="cat" + fi + fi +fi + +OSCFLAGS="-I${INCLUDEDIR} -I${PREFIX}/include/ -I/usr/local/include ${CFLAGS}" +OSLIBS="${LDFLAGS}" +for ilib in ${PREFIX}/lib/event2/ ${PREFIX}/lib/ /usr/local/lib/event2/ /usr/local/lib/ ${PREFIX}/lib64/event2/ ${PREFIX}/lib64/ /usr/local/lib64/event2/ /usr/local/lib64/ +do + if [ -d ${ilib} ] ; then + OSLIBS="${OSLIBS} -L${ilib}" + TURN_RPATH="${TURN_RPATH} -Wl,-rpath,${ilib}" + fi +done + +SYSTEM=`uname` +if [ "${SYSTEM}" = "NetBSD" ] ; then + OSCFLAGS="${OSCFLAGS} -I/usr/pkg/include" + OSLIBS="-L/usr/pkg/lib ${OSLIBS}" + if ! [ -z "${TURN_ACCEPT_RPATH}" ] ; then + TURN_RPATH="${TURN_RPATH} -Wl,-rpath,/usr/pkg/lib" + fi +fi + +########################### +# Install shell commands +########################### + +type ginstall 2>>/dev/null +ER=$? +if [ ${ER} -eq 0 ] ; then + INSTALL_PROGRAM="ginstall" + INSTALL_MAN="ginstall" + INSTALL_SCRIPT="ginstall" + INSTALL_SHARED_LIB="ginstall" + INSTALL_STATIC_LIB="ginstall" + INSTALL_DATA="ginstall" + MKDIR="ginstall -d" +else + type install 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + INSTALL_PROGRAM="install" + INSTALL_MAN="install" + INSTALL_SCRIPT="install" + INSTALL_SHARED_LIB="install" + INSTALL_STATIC_LIB="install" + INSTALL_DATA="install" + MKDIR="install -d" + else + INSTALL_PROGRAM="cp -pf" + INSTALL_MAN="cp -pf" + INSTALL_SCRIPT="cp -pf" + INSTALL_SHARED_LIB="cp -pf" + INSTALL_STATIC_LIB="cp -pf" + INSTALL_DATA="cp -pf" + MKDIR="mkdir -p" + fi +fi + +type pkill 2>>/dev/null +ER=$? +if [ ${ER} -eq 0 ] ; then + PKILL_PROGRAM="pkill" +else + PKILL_PROGRAM="${ECHO_CMD}" +fi + +INSTALL_DIR="cp -rpf" +MKBUILDDIR="mkdir -p" +RMCMD="rm -rf" + +############################# +# Adjustments for Solaris +############################# + +SYSTEM=`uname` + +if [ "${SYSTEM}" = "SunOS" ] ; then +# Solaris ? is this you ?! + OSCFLAGS="${OSCFLAGS} -D__EXTENSIONS__ -D_XOPEN_SOURCE=500" +fi + +######################### +# Temporary DIR location: +######################### + +TMPDIR="." + +if [ -d /var/tmp ] ; then + TMPDIR="/var/tmp" +elif [ -d /tmp ] ; then + TMPDIR=/tmp +fi + +${ECHO_CMD} Use TMP dir ${TMPDIR} + +######################### +# Basic C test programs +######################### + +TMPCADDRPROGO=${TMPDIR}/__test__ccomp_addr_$$.o + +TMPCPROG=__test__ccomp__$$ +TMPCPROGC=${TMPDIR}/${TMPCPROG}.c +TMPCPROGB=${TMPDIR}/${TMPCPROG} + +cat > ${TMPCPROGC} < +int main(int argc, char** argv) { + return (int)(argv[argc][0]); +} +! + +TH_TMPCPROG=__test__ccomp__pthread__$$ +TH_TMPCPROGC=${TMPDIR}/${TH_TMPCPROG}.c +TH_TMPCPROGB=${TMPDIR}/${TH_TMPCPROG} + +cat > ${TH_TMPCPROGC} < +#include +int main(int argc, char** argv) { + pthread_mutexattr_settype(0,PTHREAD_MUTEX_RECURSIVE); + return (int)pthread_create(0,0,0,0)+(int)(argv[argc][0]); +} + +! + +DTLS_TMPCPROG=__test__ccomp__dtls__$$ +DTLS_TMPCPROGC=${TMPDIR}/${DTLS_TMPCPROG}.c +DTLS_TMPCPROGB=${TMPDIR}/${DTLS_TMPCPROG} + +cat > ${DTLS_TMPCPROGC} < +#include +#include +int main(int argc, char** argv) { + return (((int)(BIO_CTRL_DGRAM_QUERY_MTU)) + argc + (int)(argv[argc][0]) + DTLSv1_listen(NULL,NULL)); +} +! + +D_TMPCPROG=__test__ccomp__daemon__$$ +D_TMPCPROGC=${TMPDIR}/${D_TMPCPROG}.c +D_TMPCPROGB=${TMPDIR}/${D_TMPCPROG} + +cat > ${D_TMPCPROGC} < +#include +int main(int argc, char** argv) { + return (int)daemon(0,0)+(int)(argv[argc][0]); +} +! + +E_TMPCPROG=__test__ccomp__libevent2__$$ +E_TMPCPROGC=${TMPDIR}/${E_TMPCPROG}.c +E_TMPCPROGO=${TMPDIR}/${E_TMPCPROG}.o + +cat > ${E_TMPCPROGC} < +#include +int main(int argc, char** argv) { + return (int)(argv[argc][0]); +} +! + +HR_TMPCPROG=__test__ccomp__hiredis__$$ +HR_TMPCPROGC=${TMPDIR}/${HR_TMPCPROG}.c +HR_TMPCPROGB=${TMPDIR}/${HR_TMPCPROG} + +cat > ${HR_TMPCPROGC} < +#include +#include +int main(int argc, char** argv) { + redisAsyncHandleRead(NULL); + return (int)(argv[argc][0]); +} +! + +PQ_TMPCPROG=__test__ccomp__libpq__$$ +PQ_TMPCPROGC=${TMPDIR}/${PQ_TMPCPROG}.c +PQ_TMPCPROGB=${TMPDIR}/${PQ_TMPCPROG} + +cat > ${PQ_TMPCPROGC} < +#include +int main(int argc, char** argv) { + return (argc+(PQprotocolVersion(NULL))+(int)(argv[0][0])); +} +! + +MYSQL_TMPCPROG=__test__ccomp__libmysql__$$ +MYSQL_TMPCPROGC=${TMPDIR}/${MYSQL_TMPCPROG}.c +MYSQL_TMPCPROGB=${TMPDIR}/${MYSQL_TMPCPROG} + +cat > ${MYSQL_TMPCPROGC} < +#include +int main(int argc, char** argv) { + return (argc+ + (int)(mysql_real_connect(NULL, NULL, NULL, NULL, NULL, 0, NULL, 0)!=0)+ + (int)(argv[0][0])); +} +! + +########################## +# What is our compiler ? +########################## + +if [ -z "${CC}" ] ; then + CC=cc + ${CC} ${TMPCPROGC} ${OSCFLAGS} -o ${TMPCPROGB} 2>>/dev/null + ER=$? + if ! [ ${ER} -eq 0 ] ; then + CC=gcc + ${CC} ${TMPCPROGC} ${OSCFLAGS} -o ${TMPCPROGB} 2>>/dev/null + ER=$? + if ! [ ${ER} -eq 0 ] ; then + CC=clang + ${CC} ${TMPCPROGC} ${OSCFLAGS} -o ${TMPCPROGB} 2>>/dev/null + ER=$? + if ! [ ${ER} -eq 0 ] ; then + CC=unknown + fi + fi + fi +fi + +${ECHO_CMD} "Compiler: ${CC}" + +if [ -z "${TURN_ACCEPT_RPATH}" ] ; then + ${CC} ${TMPCPROGC} ${OSCFLAGS} -o ${TMPCPROGB} -Wl,-rpath,/usr/lib 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + TURN_ACCEPT_RPATH=1 + fi +fi + +${CC} ${TMPCPROGC} ${OSCFLAGS} -o ${TMPCPROGB} 2>>/dev/null +ER=$? +if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "ERROR: cannot use compiler ${CC} properly" + cleanup + exit +fi + +########################### +# Check if we can use GNU +# or Clang compiler flags +########################### + +GNUOSCFLAGS="-g ${GNUOSCFLAGS}" +GNUOSCFLAGS="${GNUOSCFLAGS} -Wall -Wno-deprecated-declarations -Wextra -Wformat-security -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wcast-qual" +GNUOSCFLAGS="${GNUOSCFLAGS} -Wno-write-strings" + +${CC} -Werror ${GNUOSCFLAGS} ${TMPCPROGC} ${OSCFLAGS} -o ${TMPCPROGB} 2>>/dev/null +ER=$? +if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "Hm..." + ${CC} -Wall ${TMPCPROGC} ${OSCFLAGS} -o ${TMPCPROGB} 2>>/dev/null + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "Not an ordinary GNU or Clang compiler" + else + ${ECHO_CMD} "g++ or something..." + GNUOSCFLAGS="-g -Wall -Wno-deprecated-declarations -Wextra -Wformat-security -Wpointer-arith -Wcast-qual -Wno-write-strings" + ${CC} -Werror ${GNUOSCFLAGS} ${TMPCPROGC} ${OSCFLAGS} -o ${TMPCPROGB} 2>>/dev/null + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "Not an ordinary g++ compiler" + GNUOSCFLAGS="-x c++ -g -Wall -Wno-deprecated-declarations -Wextra -Wformat-security -Wpointer-arith -Wcast-qual -Wno-write-strings" + ${CC} -Werror ${GNUOSCFLAGS} ${TMPCPROGC} ${OSCFLAGS} -o ${TMPCPROGB} 2>>/dev/null + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "Not an ordinary c++ compiler" + else + ${ECHO_CMD} "Clang++ compiler ?" + OSCFLAGS="${GNUOSCFLAGS} ${OSCFLAGS}" + fi + else + OSCFLAGS="${GNUOSCFLAGS} ${OSCFLAGS}" + fi + fi +else + OSCFLAGS="${GNUOSCFLAGS} ${OSCFLAGS}" +fi + +########################### +# Test some general-purpose +# libraries +########################### + +testlib socket +testlib nsl +testlib dl +testlib rt +testlib wldap32 +ER=$? +if ! [ ${ER} -eq 0 ] ; then + echo "CYGWIN ?" +fi +testlib wldap64 +testlib intl + +########################### +# Test sockets compilation +########################### + +test_sin_len + +########################### +# Can we use multi-threading ? +########################### + +pthread_testlib +ER=$? +if [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "ERROR: Cannot find pthread library functions." + exit +fi + +if [ -z ${TURN_NO_THREAD_BARRIERS} ] ; then + pthread_testbarriers +else + TURN_NO_THREAD_BARRIERS="-DTURN_NO_THREAD_BARRIERS" +fi + +if [ -z ${TURN_IP_RECVERR} ] ; then + ${ECHO_CMD} "Ignore IP_RECVERR" +else + ${ECHO_CMD} "Use IP_RECVERR" + TURN_IP_RECVERR="-DTURN_IP_RECVERR" + OSCFLAGS="${OSCFLAGS} ${TURN_IP_RECVERR}" +fi + +########################### +# Can we use daemon ? +########################### + +testdaemon + +########################### +# Test OpenSSL installation +########################### + +testlib crypto +ER=$? +if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "Crypto SSL lib found." +else + ${ECHO_CMD} "ERROR: OpenSSL Crypto development libraries are not installed properly in required location." + ${ECHO_CMD} "Abort." + cleanup + exit +fi + +testlib ssl +ER=$? +if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "SSL lib found." +else + ${ECHO_CMD} "ERROR: OpenSSL development libraries are not installed properly in required location." + ${ECHO_CMD} "Abort." + cleanup + exit +fi + +########################### +# Can we use DTLS ? +########################### + +if [ -z ${TURN_NO_DTLS} ] ; then + +dtls_testlib +ER=$? +if [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "WARNING: Cannot find DTLS support." + ${ECHO_CMD} "Turning DTLS off." + TURN_NO_DTLS="-DTURN_NO_DTLS" +fi + +else + TURN_NO_DTLS="-DTURN_NO_DTLS" +fi + +########################### +# Test Libevent2 setup +########################### +testlibevent2_comp +ER=$? +if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "Libevent2 development found." +else + ${ECHO_CMD} "ERROR: Libevent2 development libraries are not installed properly in required location." + ${ECHO_CMD} "ERROR: may be you have just too old libevent tool - then you have to upgrade it." + ${ECHO_CMD} "See the INSTALL file." + ${ECHO_CMD} "Abort." + cleanup + exit +fi + +testlib event_core +ER=$? +if ! [ ${ER} -eq 0 ] ; then + testlib event_extra + ${ECHO_CMD} "Libevent2 runtime found." +else + testlib event + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "Libevent2 runtime found." + else + ${ECHO_CMD} "ERROR: Libevent2 runtime libraries are not installed properly in required location." + ${ECHO_CMD} "See the INSTALL file." + ${ECHO_CMD} "Abort." + cleanup + exit + fi +fi + +if [ -z "${TURN_NO_TLS}" ] ; then + + testlib event_openssl + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "Libevent2 openssl found." + else + ${ECHO_CMD} "ERROR: Libevent2 development libraries are not compiled with OpenSSL support." + ${ECHO_CMD} "TLS will be disabled." + TURN_NO_TLS="-DTURN_NO_TLS" + fi + +else + TURN_NO_TLS="-DTURN_NO_TLS" +fi + +testlib event_pthreads +ER=$? +if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "Libevent2 pthreads found." +else + ${ECHO_CMD} "ERROR: Libevent2 development libraries are not compiled with threads support." + exit +fi + +########################### +# Test PostgreSQL +########################### + +if [ -z "${TURN_NO_PQ}" ] ; then + + testlibpq + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "PostgreSQL found." + else + TURN_NO_PQ="-DTURN_NO_PQ" + fi +else + TURN_NO_PQ="-DTURN_NO_PQ" +fi + +########################### +# Test MySQL +########################### + +if [ -z "${TURN_NO_MYSQL}" ] ; then + + testlibmysql + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "MySQL found." + else + TURN_NO_MYSQL="-DTURN_NO_MYSQL" + fi +else + TURN_NO_MYSQL="-DTURN_NO_MYSQL" +fi + +########################### +# Test Redis +########################### + +if [ -z "${TURN_NO_HIREDIS}" ] ; then + + testhiredis + + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "Hiredis found." + else + TURN_NO_HIREDIS="-DTURN_NO_HIREDIS" + fi + +else + TURN_NO_HIREDIS="-DTURN_NO_HIREDIS" + +fi + +############################### +# LDCONFIG +############################### + +if [ -z "${LDCONFIG}" ] ; then + ISBSD=`uname | grep -i bsd` + if [ -z "${ISBSD}" ] ; then + ISLINUX=`uname | grep -i linux` + if [ -z "${ISLINUX}" ] ; then + SYSTEM=`uname` + if [ "${SYSTEM}" = "SunOS" ] ; then + LDCONFIG="crle -u -l" + else + LDCONFIG=${ECHO_CMD} + fi + else + LDCONFIG="ldconfig -n" + fi + else + LDCONFIG="ldconfig -m" + fi +fi + + +############################### +# So, what we have now: +############################### + +OSCFLAGS="${OSCFLAGS} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX}" + +if ! [ -z "${TURN_ACCEPT_RPATH}" ] ; then + if [ -z "${TURN_DISABLE_RPATH}" ] ; then + TURN_RPATH="${TURN_RPATH} -Wl,-rpath,/usr/local/lib" + OSLIBS="${OSLIBS} ${TURN_RPATH}" + fi +fi + +${ECHO_CMD} PREFIX="${PREFIX}" OSLIBS="${OSLIBS}" DBLIBS="${DBLIBS}" OSCFLAGS="${OSCFLAGS}" DBCFLAGS="${DBCFLAGS}" $@ + +############################### +# Make make: +############################### + +${ECHO_CMD} "#################################" > Makefile +${ECHO_CMD} "# Generated by configure script #" >> Makefile +${ECHO_CMD} "#################################" >> Makefile +${ECHO_CMD} "ECHO_CMD = ${ECHO_CMD}" >> Makefile +${ECHO_CMD} "CC = ${CC}" >> Makefile +${ECHO_CMD} "LDFLAGS += ${OSLIBS}" >> Makefile +${ECHO_CMD} "DBLIBS += ${DBLIBS}" >> Makefile +${ECHO_CMD} "CFLAGS += ${OSCFLAGS}" >> Makefile +${ECHO_CMD} "CPPFLAGS = ${CPPFLAGS}" >> Makefile +${ECHO_CMD} "DBCFLAGS += ${DBCFLAGS} ${TURN_NO_PQ} ${TURN_NO_MYSQL} ${TURN_NO_HIREDIS}" >> Makefile +${ECHO_CMD} "#" >> Makefile +${ECHO_CMD} "PORTNAME = ${PORTNAME}" >> Makefile +${ECHO_CMD} "PREFIX = ${PREFIX}" >> Makefile +${ECHO_CMD} "prefix = ${PREFIX}" >> Makefile +${ECHO_CMD} "BINDIR = ${BINDIR}" >> Makefile +${ECHO_CMD} "bindir = ${BINDIR}" >> Makefile +${ECHO_CMD} "CONFDIR = ${CONFDIR}" >> Makefile +${ECHO_CMD} "confdir = ${CONFDIR}" >> Makefile +${ECHO_CMD} "MANPREFIX = ${MANPREFIX}" >> Makefile +${ECHO_CMD} "manprefix = ${MANPREFIX}" >> Makefile +${ECHO_CMD} "EXAMPLESDIR = ${EXAMPLESDIR}" >> Makefile +${ECHO_CMD} "examplesdir = ${EXAMPLESDIR}" >> Makefile +${ECHO_CMD} "DOCSDIR = ${DOCSDIR}" >> Makefile +${ECHO_CMD} "docsdir = ${DOCSDIR}" >> Makefile +${ECHO_CMD} "LIBDIR = ${LIBDIR}" >> Makefile +${ECHO_CMD} "libdir = ${LIBDIR}" >> Makefile +${ECHO_CMD} "SCHEMADIR = ${SCHEMADIR}" >> Makefile +${ECHO_CMD} "schemadir = ${SCHEMADIR}" >> Makefile +${ECHO_CMD} "INCLUDEDIR = ${INCLUDEDIR}" >> Makefile +${ECHO_CMD} "includedir = ${INCLUDEDIR}" >> Makefile +${ECHO_CMD} "TURNINCLUDEDIR = ${TURNINCLUDEDIR}" >> Makefile +${ECHO_CMD} "turnincludedir = ${TURNINCLUDEDIR}" >> Makefile +${ECHO_CMD} "#" >> Makefile +${ECHO_CMD} "ARCHIVERCMD = ${ARCHIVERCMD}" >> Makefile +${ECHO_CMD} "MKDIR = ${MKDIR}" >> Makefile +${ECHO_CMD} "INSTALL_PROGRAM = ${INSTALL_PROGRAM}" >> Makefile +${ECHO_CMD} "PKILL_PROGRAM = ${PKILL_PROGRAM}" >> Makefile +${ECHO_CMD} "INSTALL_MAN = ${INSTALL_MAN}" >> Makefile +${ECHO_CMD} "INSTALL_SCRIPT = ${INSTALL_SCRIPT}" >> Makefile +${ECHO_CMD} "INSTALL_SHARED_LIB = ${INSTALL_SHARED_LIB}" >> Makefile +${ECHO_CMD} "INSTALL_STATIC_LIB = ${INSTALL_STATIC_LIB}" >> Makefile +${ECHO_CMD} "INSTALL_DATA = ${INSTALL_DATA}" >> Makefile +${ECHO_CMD} "INSTALL_DIR = ${INSTALL_DIR}" >> Makefile +${ECHO_CMD} "MKBUILDDIR = ${MKBUILDDIR}" >> Makefile +${ECHO_CMD} "RMCMD = ${RMCMD}" >> Makefile +${ECHO_CMD} "MORECMD = ${MORECMD}" >> Makefile +${ECHO_CMD} "LDCONFIG=${LDCONFIG}" >> Makefile +${ECHO_CMD} "################################" >> Makefile +${ECHO_CMD} "" >> Makefile +cat Makefile.in >> Makefile + +############################### +# End: +############################### + +cleanup + + diff --git a/examples/etc/turn_client_cert.pem b/examples/etc/turn_client_cert.pem new file mode 100644 index 00000000..2e00e7e8 --- /dev/null +++ b/examples/etc/turn_client_cert.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDzjCCArYCCQD3YHhln4EqhDANBgkqhkiG9w0BAQUFADCBpzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRUwEwYDVQQHEwxXYWxudXQgQ3JlZWsxKzApBgNVBAoT +IlJGQzU3NjYgVFVSTiBTZXJ2ZXIgcHVibGljIHByb2plY3QxFDASBgNVBAsTC2Rl +dmVsb3BtZW50MQ0wCwYDVQQDEwRPbGVnMSIwIAYJKoZIhvcNAQkBFhNtb20wNDAy +NjdAZ21haWwuY29tMCAXDTEyMTEyNzAwNDEwNVoYDzIxMTIxMTAzMDA0MTA1WjCB +pzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRUwEwYDVQQHEwxXYWxudXQgQ3Jl +ZWsxKzApBgNVBAoTIlJGQzU3NjYgVFVSTiBTZXJ2ZXIgcHVibGljIHByb2plY3Qx +FDASBgNVBAsTC2RldmVsb3BtZW50MQ0wCwYDVQQDEwRPbGVnMSIwIAYJKoZIhvcN +AQkBFhNtb20wNDAyNjdAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEA3huHvPYyvNZBK91bP3O1dBdOj93YQ3812BTcRMjEYnvSyyEosxFd +dEnILgDiFK//pFnDtwm7FxOCtVwRQ0+8qGTH4vH0EIpKTBsaafKH3L9CYe40pwcm +BJHvclOa4vl2Ghi09+M0UEHdokkM77K9rpXx7aZILoICkqnoAuBe0TY8D5PBXinM +gtk7HlrvANxSmPHAAaGQ5t/+jfTWVH1UYCpogTgCKYPbNi+joKu6oEz+qRKAqDYd +FY6/Qpiv7reYiNiVhM7HGNY27FkKDJDBhsmZRmtTIEdYFfcWPZvv69L7Rf1skOXF +Vm5/to3HArJJF+lz6YGj0C3pE6dZt6sUmQIDAQABMA0GCSqGSIb3DQEBBQUAA4IB +AQAhXgGdXXf0dMPdkfl4jv4dqFNSmax6wmeNc+oJC9qIFVDLsdAaAWXZ+pZHYIMR +UN8mQobsIZdfPQ0gs8CgUwrKziAjA92y2Q/I7vsg83qRLhysGC5etYMD/wlySDDS +AJKraevDPTEdmfNstCblubNG2PIeqV1isWtPMqB2dMsCeyzJXVyfD0QcABzFv4Fs +MMy7JI7MsctNh1tjV/0TsddDMeMLs22rix5fS8MZ6uunFzIuJ0MshFNehXFuvz0B +uNmn0k7djUm3h+2Avs3YGCo/8GtqHapc/lva/9gT+iEW0e7i0Ru5Jhar66VMzJqv ++wEhQafC77d3vWHtXQU8dYmM +-----END CERTIFICATE----- diff --git a/examples/etc/turn_client_pkey.pem b/examples/etc/turn_client_pkey.pem new file mode 100644 index 00000000..11f9d2aa --- /dev/null +++ b/examples/etc/turn_client_pkey.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA3huHvPYyvNZBK91bP3O1dBdOj93YQ3812BTcRMjEYnvSyyEo +sxFddEnILgDiFK//pFnDtwm7FxOCtVwRQ0+8qGTH4vH0EIpKTBsaafKH3L9CYe40 +pwcmBJHvclOa4vl2Ghi09+M0UEHdokkM77K9rpXx7aZILoICkqnoAuBe0TY8D5PB +XinMgtk7HlrvANxSmPHAAaGQ5t/+jfTWVH1UYCpogTgCKYPbNi+joKu6oEz+qRKA +qDYdFY6/Qpiv7reYiNiVhM7HGNY27FkKDJDBhsmZRmtTIEdYFfcWPZvv69L7Rf1s +kOXFVm5/to3HArJJF+lz6YGj0C3pE6dZt6sUmQIDAQABAoIBAH5ITN8FZEe10gws +qUrkcRD2h3aI/gMyetzGz45UUERmfq17xvY5M1eA884kNmbowoMhfoO9hqBSOYkA +Ndh9p5he5L+GLeyRlDi9WEFQ4iqCnC2uEEW/bMBAcVIhcvkGOT4ROiOPDRlsuaUh +v7cxe2OeYZVra7L1vJzC+eVYyNBN5CgK8w08MPEkupQS9+Jvr0QWCikRz187cG45 +EiDMrBKyJNE9lY6u4P8gJ+/NgaASWP/D3kbsjiQ2OwSGLrwDAvWC7Bx2GK3/0goA +btp7YGaWvp+mE5V91cOW+PfweC5Do4MjOr4ToNkczW0AxKE5o94yo56h+II5bX6N +z65VvtkCgYEA/Sq/3S2yup/Oodzj003KG4skWYFrj7KXeXgm7RZcpNwkd8JaFXJ/ +Cwl7/3bkRv6RHLmXX/2hcNWlxq3u6Efs1EjtycdArU68kO01vLdExJYIzHKmHikV +n+T4hukxGDzObxn3lH1KcOodh/x572Uufn79dewoZCPzH8t/jiMOWGcCgYEA4JfN +66Kq/oDookqenM9Ij5l6zeeNwzMjIlkU2eG0DAH0KdsBN/hTGGGRQVBk03YREQmK +crEhGAZxzfrX5fK11UVG3C2pqAtrVe6FuD32vFUpP1MO0ftSA889NoEwGdNZV4pV +Mk0+6xVCNOatj2inMXlQq5s68WfCzkiWD7uLCv8CgYBcwuYsF4tuYBGpMzNzAAS2 +1OPLu+T6cPiZdFHm+xOVAGiITPkO9LXiCGabsydvb+UhvkrdzCP0IQQt6RsplvkK +y3H9RfnHxprHC3NuI0SaN1Mf/j4pvOoEfTQm0pi/hcAp6zzQ9ptpBg8t/W98LPm9 +NbCPHamrD5UMqFajcOrXrwKBgD8D2M8IcRm/aYY/kYlFz4Ia+g3Trj7alj0I6YTI +gw/rbGph/FGL5ySsG2lL+T4rnlY9aw8LC9IF3OCCRRlLpCEWsu8MENIJgjA2IGa1 +XAkzi8MstrfL4BMZjn9AeBKG7kZVldnrOoATEuRs5L2cC20iMLQ1dbBOAKaITzJS +2IxZAoGBAKqwr/uennxJrnMtpjLBgcphoU3aXJZvzzDqlOaqzJp6Xmbese4sDEe0 +hvVHreigDzOnGnqL/vSjTDWaLqS/O1iE7p+UrGIkZj/Zl6Jk54OX6AHmWE2LhdlU +FYgIQKX7fuocpF1Dpe7xEeVwvdp+UqbDzHQg1CWGe1cBPYDYIkSH +-----END RSA PRIVATE KEY----- diff --git a/examples/etc/turn_server_cert.pem b/examples/etc/turn_server_cert.pem new file mode 100644 index 00000000..99b3f018 --- /dev/null +++ b/examples/etc/turn_server_cert.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDsDCCApgCCQCmgrJCiQlGOTANBgkqhkiG9w0BAQUFADCBmDELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRUwEwYDVQQHEwxXYWxudXQgQ3JlZWsxHDAaBgNVBAoT +E1RVUk4gU2VydmVyIHByb2plY3QxFDASBgNVBAsTC0RldmVsb3BtZW50MQ0wCwYD +VQQDEwRPbGVnMSIwIAYJKoZIhvcNAQkBFhNtb20wNDAyNjdAZ21haWwuY29tMCAX +DTEyMTEyNTA4MjAxNloYDzIxMTIxMTAxMDgyMDE2WjCBmDELMAkGA1UEBhMCVVMx +CzAJBgNVBAgTAkNBMRUwEwYDVQQHEwxXYWxudXQgQ3JlZWsxHDAaBgNVBAoTE1RV +Uk4gU2VydmVyIHByb2plY3QxFDASBgNVBAsTC0RldmVsb3BtZW50MQ0wCwYDVQQD +EwRPbGVnMSIwIAYJKoZIhvcNAQkBFhNtb20wNDAyNjdAZ21haWwuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv6bYkERhZ43RjW4EuqCaTq5g+D+l +JI/GwlVzdzQ3+F4clMQDR1kp1nX+9AvwjCXz3AYwY1H9CqjmjGM4R9uNJJseK/aJ +d2DUFADkF+7I674XwX8U2Fy5on9jqWq3jdbb8eg/awcTBdrNLWNPquwfS2KVdooj +9yPkqnO0c3ko1/OzIQCcs09O3l/MPt+aOsHk3B9l79ZRs3zWkylI+we0Fnc+7tZE +psCztA+KCCoiJf7NenOvVhdKg7D1AXuzJ/P/Euvc3+CIiS9HI4pWLopY1k+HydLe +IcopqSbg9CRIKe1HOL8YTvCm2ZoTqgijwWUlGtwEDf2xxUQX/TLYiW8JFQIDAQAB +MA0GCSqGSIb3DQEBBQUAA4IBAQATbrBOLV4e8Qmsby9+srxXsdbNc60PmDZ4WiZ1 +IElfWmzM7wGXm9sJg1PX/7T24R1tbwZGLIhZnkhecG372GChULZJ9Pdjh0Ab2nK5 +LRKHXTpjp/xOJvx0JMCIIyRnGZT1nABPOk8uEjNW8PaU6yhQ4f5nKaSOgYGRCln6 +dcy5vylCsyD9Q7GXs0KOC38XD+Ycv6VLX4zKJ2Yum50Wt643nLjG9RlGT3FXWJ1K +HUbPC5TO6bcYLdiTjaYr+X8xC/x6h/Ngdo/16w7fRmQQ4uS+TVXrg8ITmI71KX/I +m7C9jbsubwzrhW84oZXYf+o/0ATtEAhiVLnHifKCCYikqfVj +-----END CERTIFICATE----- diff --git a/examples/etc/turn_server_pkey.pem b/examples/etc/turn_server_pkey.pem new file mode 100644 index 00000000..ada07d6c --- /dev/null +++ b/examples/etc/turn_server_pkey.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAv6bYkERhZ43RjW4EuqCaTq5g+D+lJI/GwlVzdzQ3+F4clMQD +R1kp1nX+9AvwjCXz3AYwY1H9CqjmjGM4R9uNJJseK/aJd2DUFADkF+7I674XwX8U +2Fy5on9jqWq3jdbb8eg/awcTBdrNLWNPquwfS2KVdooj9yPkqnO0c3ko1/OzIQCc +s09O3l/MPt+aOsHk3B9l79ZRs3zWkylI+we0Fnc+7tZEpsCztA+KCCoiJf7NenOv +VhdKg7D1AXuzJ/P/Euvc3+CIiS9HI4pWLopY1k+HydLeIcopqSbg9CRIKe1HOL8Y +TvCm2ZoTqgijwWUlGtwEDf2xxUQX/TLYiW8JFQIDAQABAoIBADUPHCXUyKLCwKFH +NEf27sGZxX71H+NfaseioLT/3/8DDyagncfDB7I4OL2YEKC8YScpD3xv1n59BFcZ +oRtDzW+1AkVpm+VRCWYAWSXHFhkuJ6WKaVr9UOeMHStqQCcktP/kLKqU6s9UJDnM +pOHNPVzBjl+jHxHs/gGyxuKxSH2Anwkrzpiv5j0obKFnw3QtAqeZRs1NlvPtYt2S +eihZWr8r8LqylPk9ga9MYmO79Yr+EPVaqd6bmz4MpZJ4/7LEjx03Q6azdMCPhFNY +cYzPIDZFEj81Zj/tqA2MU/uTTUUrcXint4dHRJs34m5N68PV1Y1XhhH6FG0+X711 +ZymudoECgYEA/ChS5zmmOoLoaq2441+PzQbDP45qR6+G4slHwC8RDZhsYw0hQnp9 +n44Qagpt74J4FjxT20BdE714DZP32IqagUwatWRQ+z3UoGafkJSNc5JSEogwZ65C +nC8RI1pPHLEvE8IzBJiqUA1kbMOMfTYW694wdN9JVZang05/AXaJzm8CgYEAwpJ8 +nJRR9JFweHRrRgnrVk0Qi+ABbN9T/nhPXYab2vjBfeBOTA1Mob0M3zMJDCnL2i+D +K1GzE6WaYHElr45j2Wfphd/rRTk74WR4BaPpTCGaAhBQNn0ufqUkKsCPEAlTU+nG +iyXP4OvdMPjEBckjbKm/mlX7m0njSHAY6SWNorsCgYEAi8Yubk3efwChpMC3hBIs +vBHLmSdwclwyAPRh+X4djdO4AQ/+J8OObytond86IVHJD0pRkW+UKKUWLzCeakIq +cxGknHgHC72yZ1d7i8FMx4uMQwmLC23lLn5ImbgtslHlLqavcRTPE6DY0hFzhtS8 +z/JSGfbLx83C/V49uKnkqbECgYA6h1oYt70XdpCAi3ShcuZp5XCuwslq+JsJlyM4 +nP9RFTcPKGQlGHMOzBGNKor0L7Z0gYpRg5f8tvoDPMX7UzfR9CIY9UyOXDMZD+HS +wIWzMwBi0olueqV7zy1b9uSSDFwWh+IDhXJM1GaLDqnYm7KeQ0mxoV+4TLej2KSF +rZg3dQKBgQCVrVxFV8jHBsRsH5PzMx6pUSAollmuyte9mGU1MIE7EZf+LEQIAjGZ +9jvtAILYVJXwVZv1/zNxldUfBNuWc95ft+Gg7FEN0p0uLpdYNXQUcXuJaJ9tJ1td +ZfvRcrUXdFNKYt9/yaGeHVaIQfp4W1faZD7OnII7EOVkUKyv/qNGAA== +-----END RSA PRIVATE KEY----- diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf new file mode 100644 index 00000000..07fdfb32 --- /dev/null +++ b/examples/etc/turnserver.conf @@ -0,0 +1,589 @@ +# Coturn TURN SERVER configuration file +# +# Boolean values note: where boolean value is supposed to be used, +# you can use '0', 'off', 'no', 'false', 'f' as 'false, +# and you can use '1', 'on', 'yes', 'true', 't' as 'true' +# If the value is missed, then it means 'true'. +# + +# Listener interface device (optional, Linux only). +# NOT RECOMMENDED. +# +#listening-device=eth0 + +# TURN listener port for UDP and TCP (Default: 3478). +# Note: actually, TLS & DTLS sessions can connect to the +# "plain" TCP & UDP port(s), too - if allowed by configuration. +# +#listening-port=3478 + +# TURN listener port for TLS (Default: 5349). +# Note: actually, "plain" TCP & UDP sessions can connect to the TLS & DTLS +# port(s), too - if allowed by configuration. The TURN server +# "automatically" recognizes the type of traffic. Actually, two listening +# 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. +# For secure UDP connections, we support DTLS version 1. +# +#tls-listening-port=5349 + +# Alternative listening port for UDP and TCP listeners; +# default (or zero) value means "listening port plus one". +# This is needed for RFC 5780 support +# (STUN extension specs, NAT behavior discovery). The TURN Server +# supports RFC 5780 only if it is started with more than one +# listening IP address of the same family (IPv4 or IPv6). +# RFC 5780 is supported only by UDP protocol, other protocols +# are listening to that endpoint only for "symmetry". +# +#alt-listening-port=0 + +# Alternative listening port for TLS and DTLS protocols. +# Default (or zero) value means "TLS listening port plus one". +# +#alt-tls-listening-port=0 + +# Listener IP address of relay server. Multiple listeners can be specified. +# If no IP(s) specified in the config file or in the command line options, +# then all IPv4 and IPv6 system IPs will be used for listening. +# +#listening-ip=172.17.19.101 +#listening-ip=10.207.21.238 +#listening-ip=2607:f0d0:1002:51::4 + +# Auxiliary STUN/TURN server listening endpoint. +# Aux servers have almost full TURN and STUN functionality. +# The (minor) limitations are: +# +# 1) Auxiliary servers do not have alternative ports and +# they do not support STUN RFC 5780 functionality (CHANGE REQUEST). +# +# 2) Auxiliary servers also are never returning ALTERNATIVE-SERVER reply. +# +# Valid formats are 1.2.3.4:5555 for IPv4 and [1:2::3:4]:5555 for IPv6. +# +# There may be multiple aux-server options, each will be used for listening +# to client requests. +# +#aux-server=172.17.19.110:33478 +#aux-server=[2607:f0d0:1002:51::4]:33478 + +# (recommended for older Linuxes only) +# Automatically balance UDP traffic over auxiliary servers (if configured). +# The load balancing is using the ALTERNATE-SERVER mechanism. +# The TURN client must support 300 ALTERNATE-SERVER response for this +# functionality. +# +#udp-self-balance + +# Relay interface device for relay sockets (optional, Linux only). +# NOT RECOMMENDED. +# +#relay-device=eth1 + +# Relay address (the local IP address that will be used to relay the +# packets to the peer). +# Multiple relay addresses may be used. +# The same IP(s) can be used as both listening IP(s) and relay IP(s). +# +# If no relay IP(s) specified, then the turnserver will apply the default +# policy: it will decide itself which relay addresses to be used, and it +# will always be using the client socket IP address as the relay IP address +# of the TURN session (if the requested relay address family is the same +# as the family of the client socket). +# +#relay-ip=172.17.19.105 +#relay-ip=2607:f0d0:1002:51::5 + +# For Amazon EC2 users: +# +# TURN Server public/private address mapping, if the server is behind NAT. +# In that situation, if a -X is used in form "-X " then that ip will be reported +# as relay IP address of all allocations. This scenario works only in a simple case +# when one single relay address is be used, and no RFC5780 functionality is required. +# That single relay address must be mapped by NAT to the 'external' IP. +# The "external-ip" value, if not empty, is returned in XOR-RELAYED-ADDRESS field. +# For that 'external' IP, NAT must forward ports directly (relayed port 12345 +# must be always mapped to the same 'external' port 12345). +# +# In more complex case when more than one IP address is involved, +# that option must be used several times, each entry must +# have form "-X ", to map all involved addresses. +# RFC5780 NAT discovery STUN functionality will work correctly, +# if the addresses are mapped properly, even when the TURN server itself +# is behind A NAT. +# +# By default, this value is empty, and no address mapping is used. +# +#external-ip=60.70.80.91 +# +#OR: +# +#external-ip=60.70.80.91/172.17.19.101 +#external-ip=60.70.80.92/172.17.19.102 + + +# Number of relay threads to handle the established connections +# (in addition to authentication thread and the listener thread). +# If set to 0 then application runs relay process in a single thread, +# in the same thread with the listener process (the authentication thread will +# still be a separate thread). +# +# In the older systems (Linux kernel before 3.9), +# the number of UDP threads is always one thread per network listening endpoint - +# including the auxiliary endpoints - unless 0 (zero) or 1 (one) value is set. +# +#relay-threads=0 + +# Lower and upper bounds of the UDP relay endpoints: +# (default values are 49152 and 65535) +# +#min-port=49152 +#max-port=65535 + +# Uncomment to run TURN server in 'normal' 'moderate' verbose mode. +# By default the verbose mode is off. +#verbose + +# Uncomment to run TURN server in 'extra' verbose mode. +# This mode is very annoying and produces lots of output. +# Not recommended under any normal circumstances. +# +#Verbose + +# Uncomment to use fingerprints in the TURN messages. +# By default the fingerprints are off. +# +#fingerprint + +# Uncomment to use long-term credential mechanism. +# By default no credentials mechanism is used (any user allowed). +# This option can be used with either flat file user database or +# PostgreSQL DB or MySQL DB or Redis DB for user keys storage. +# +#lt-cred-mech + +# Uncomment to use short-term credential mechanism. +# By default no credentials mechanism is used (any user allowed). +# For short-term credential mechanism you have to use PostgreSQL or +# MySQL or Redis database for user password storage. +# +#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, +# then no-auth is default. If at least one user is defined, +# in this file or in command line or in usersdb file, then +# lt-cred-mech is default. +# +#no-auth + +# TURN REST API flag. +# Flag that sets a special authorization option that is based upon authentication secret. +# This feature can be used with the long-term authentication mechanism, only. +# This feature purpose is to support "TURN Server REST API", see +# "TURN REST API" link in the project's page +# http://code.google.com/p/coturn/. +# +# This option is used with timestamp: +# +# usercombo -> "timestamp:userid" +# turn user -> usercombo +# turn password -> base64(hmac(secret key, usercombo)) +# +# This allows TURN credentials to be accounted for a specific user id. +# If you don't have a suitable id, the timestamp alone can be used. +# This option is just turning 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 (see below). +# +#use-auth-secret + +# 'Static' authentication secret value (a string) for TURN REST API only. +# If not set, then the turn server +# will try to use the 'dynamic' value in turn_secret table +# in user database (if present). The database-stored value can be changed on-the-fly +# by a separate program, so this is why that other mode is 'dynamic'. +# +#static-auth-secret + +# 'Static' user accounts for long term credentials mechanism, only. +# This option cannot be used with TURN REST API or with short-term credentials +# mechanism. +# 'Static' user accounts are NOT dynamically checked by the turnserver process, +# so that they can NOT be changed while the turnserver is running. +# +#user=username1:key1 +#user=username2:key2 +# OR: +#user=username1:password1 +#user=username2:password2 +# +# Keys must be generated by turnadmin utility. The key value depends +# on user name, realm, and password: +# +# Example: +# $ turnadmin -k -u ninefingers -r north.gov -p youhavetoberealistic +# Output: 0xbc807ee29df3c9ffa736523fb2c4e8ee +# ('0x' in the beginning of the key is what differentiates the key from +# password. If it has 0x then it is a key, otherwise it is a password). +# +# The corresponding user account entry in the config file will be: +# +#user=ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee +# Or, equivalently, with open clear password (less secure): +#user=ninefingers:youhavetoberealistic +# + +# 'Dynamic' user accounts database file name. +# Only users for long-term mechanism can be stored in a flat file, +# short-term mechanism will not work with option, the short-term +# mechanism required PostgreSQL or MySQL or Redis database. +# 'Dynamic' long-term user accounts are dynamically checked by the turnserver process, +# so that they can be changed while the turnserver is running. +# +# Default file name is turnuserdb.conf. +# +#userdb=/usr/local/etc/turnuserdb.conf + +# 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 +# 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 +# http://www.postgresql.org/docs/9.2/static/libpq-connect.html#LIBPQ-CONNSTRING +# for 9.x and newer connection string formats. +# +#psql-userdb="host= dbname= user= password= connect_timeout=30" + +# 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 +# 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): +# +#mysql-userdb="host= dbname= user= password= port= connect_timeout=" + +# 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 +# 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): +# +#redis-userdb="ip= dbname= password= port= connect_timeout=" + +# Redis status and statistics database connection string, if used (default - empty, no Redis stats DB used). +# This database keeps allocations status information, and it can be also used for publishing +# and delivering traffic and allocation event notifications. +# The connection string has the same parameters as redis-userdb connection string. +# Use string format as below (space separated parameters, all optional): +# +#redis-statsdb="ip= dbname= password= port= connect_timeout=" + +# The default realm to be used for the users when no explicit +# origin/realm relationship was found in the database, or if the TURN +# server is not using any database (just the commands-line settings +# and the userdb file). Must be used with long-term credentials +# mechanism or with TURN REST API. +# +#realm=mycompany.org + +# Per-user allocation quota. +# default value is 0 (no quota, unlimited number of sessions per user). +# This option can also be set through the database, for a particular realm. +# +#user-quota=0 + +# Total allocation quota. +# default value is 0 (no quota). +# This option can also be set through the database, for a particular realm. +# +#total-quota=0 + +# Max bytes-per-second bandwidth a TURN session is allowed to handle +# (input and output network streams are treated separately). Anything above +# that limit will be dropped or temporary suppressed (within +# the available buffer limits). +# This option can also be set through the database, for a particular realm. +# +#max-bps=0 + +# Uncomment if no UDP client listener is desired. +# By default UDP client listener is always started. +# +#no-udp + +# Uncomment if no TCP client listener is desired. +# By default TCP client listener is always started. +# +#no-tcp + +# Uncomment if no TLS client listener is desired. +# By default TLS client listener is always started. +# +#no-tls + +# Uncomment if no DTLS client listener is desired. +# By default DTLS client listener is always started. +# +#no-dtls + +# Uncomment if no UDP relay endpoints are allowed. +# By default UDP relay endpoints are enabled (like in RFC 5766). +# +#no-udp-relay + +# Uncomment if no TCP relay endpoints are allowed. +# By default TCP relay endpoints are enabled (like in RFC 6062). +# +#no-tcp-relay + +# Uncomment if extra security is desired, +# with nonce value having limited lifetime (600 secs). +# By default, the nonce value is unique for a session, +# but it has unlimited lifetime. With this option, +# the nonce lifetime is limited to 600 seconds, after that +# the client will get 438 error and will have to re-authenticate itself. +# +#stale-nonce + +# Certificate file. +# Use an absolute path or path relative to the +# configuration file. +# +#cert=/usr/local/etc/turn_server_cert.pem + +# Private key file. +# Use an absolute path or path relative to the +# configuration file. +# Use PEM file format. +# +#pkey=/usr/local/etc/turn_server_pkey.pem + +# Private key file password, if it is in encoded format. +# This option has no default value. +# +#pkey-pwd=... + +# Allowed OpenSSL cipher list for TLS/DTLS connections. +# Default value is "DEFAULT". +# +#cipher-list="DEFAULT" + +# CA file in OpenSSL format. +# Forces TURN server to verify the client SSL certificates. +# By default it is not set: there is no default value and the client +# certificate is not checked. +# +# Example: +#CA-file=/etc/ssh/id_rsa.cert + +# Curve name for EC ciphers, if supported by OpenSSL library (TLS and DTLS). +# The default value is prime256v1. +# +#ec-curve-name=prime256v1 + +# Use 566 bits predefined DH TLS key. Default size of the key is 1066. +# +#dh566 + +# Use 2066 bits predefined DH TLS key. Default size of the key is 1066. +# +#dh2066 + +# Use custom DH TLS key, stored in PEM format in the file. +# Flags --dh566 and --dh2066 are ignored when the DH key is taken from a file. +# +#dh-file= + +# Flag to prevent stdout log messages. +# By default, all log messages are going to both stdout and to +# the configured log file. With this option everything will be +# going to the configured log only (unless the log file itself is stdout). +# +#no-stdout-log + +# Option to set the log file name. +# By default, the turnserver tries to open a log file in +# /var/log, /var/tmp, /tmp and current directories directories +# (which open operation succeeds first that file will be used). +# With this option you can set the definite log file name. +# The special names are "stdout" and "-" - they will force everything +# to the stdout. Also, the "syslog" name will force everything to +# the system log (syslog). +# +#log-file=/var/tmp/turn.log + +# Option to redirect all log output into system log (syslog). +# +#syslog + +# This flag means that no log file rollover will be used, and the log file +# name will be constructed as-is, without PID and date appendage. +#simple-log + +# Option to set the "redirection" mode. The value of this option +# will be the address of the alternate server for UDP & TCP service in form of +# [:]. The server will send this value in the attribute +# ALTERNATE-SERVER, with error 300, on ALLOCATE request, to the client. +# Client will receive only values with the same address family +# as the client network endpoint address family. +# See RFC 5389 and RFC 5766 for ALTERNATE-SERVER functionality description. +# The client must use the obtained value for subsequent TURN communications. +# If more than one --alternate-server options are provided, then the functionality +# can be more accurately described as "load-balancing" than a mere "redirection". +# If the port number is omitted, then the default port +# number 3478 for the UDP/TCP protocols will be used. +# Colon (:) characters in IPv6 addresses may conflict with the syntax of +# the option. To alleviate this conflict, literal IPv6 addresses are enclosed +# in square brackets in such resource identifiers, for example: +# [2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478 . +# Multiple alternate servers can be set. They will be used in the +# round-robin manner. All servers in the pool are considered of equal weight and +# the load will be distributed equally. For example, if we have 4 alternate servers, +# then each server will receive 25% of ALLOCATE requests. A alternate TURN server +# address can be used more than one time with the alternate-server option, so this +# can emulate "weighting" of the servers. +# +# Examples: +#alternate-server=1.2.3.4:5678 +#alternate-server=11.22.33.44:56789 +#alternate-server=5.6.7.8 +#alternate-server=[2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478 + +# Option to set alternative server for TLS & DTLS services in form of +# :. If the port number is omitted, then the default port +# number 5349 for the TLS/DTLS protocols will be used. See the previous +# option for the functionality description. +# +# Examples: +#tls-alternate-server=1.2.3.4:5678 +#tls-alternate-server=11.22.33.44:56789 +#tls-alternate-server=[2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478 + +# Option to suppress TURN functionality, only STUN requests will be processed. +# Run as STUN server only, all TURN requests will be ignored. +# By default, this option is NOT set. +# +#stun-only + +# Option to suppress STUN functionality, only TURN requests will be processed. +# Run as TURN server only, all STUN requests will be ignored. +# By default, this option is NOT set. +# +#no-stun + +# This is the timestamp/username separator symbol (character) in TURN REST API. +# The default value is ':'. +# rest-api-separator=: + +# Flag that can be used to disallow peers on the loopback addresses (127.x.x.x and ::1). +# This is an extra security measure. +# +#no-loopback-peers + +# Flag that can be used to disallow peers on well-known broadcast addresses (224.0.0.0 and above, and FFXX:*). +# This is an extra security measure. +# +#no-multicast-peers + +# Option to set the max time, in seconds, allowed for full allocation establishment. +# Default is 60 seconds. +# +#max-allocate-timeout=60 + +# Option to allow or ban specific ip addresses or ranges of ip addresses. +# If an ip address is specified as both allowed and denied, then the ip address is +# considered to be allowed. This is useful when you wish to ban a range of ip +# addresses, except for a few specific ips within that range. +# +# This can be used when you do not want users of the turn server to be able to access +# machines reachable by the turn server, but would otherwise be unreachable from the +# internet (e.g. when the turn server is sitting behind a NAT) +# +# Examples: +# denied-peer-ip=83.166.64.0-83.166.95.255 +# allowed-peer-ip=83.166.68.45 + +# File name to store the pid of the process. +# Default is /var/run/turnserver.pid (if superuser account is used) or +# /var/tmp/turnserver.pid . +# +#pidfile="/var/run/turnserver.pid" + +# Require authentication of the STUN Binding request. +# By default, the clients are allowed anonymous access to the STUN Binding functionality. +# +#secure-stun + +# Require SHA256 digest function to be used for the message integrity. +# By default, the server uses SHA1 (as per TURN standard specs). +# With this option, the server +# always requires the stronger SHA256 function. The client application +# must support SHA256 hash function if this option is used. If the server obtains +# a message from the client with a weaker (SHA1) hash function then the +# server returns error code 426. +# +#sha256 + +# Mobility with ICE (MICE) specs support. +# +#mobility + +# User name to run the process. After the initialization, the turnserver process +# will make an attempt to change the current user ID to that user. +# +#proc-user= + +# Group name to run the process. After the initialization, the turnserver process +# will make an attempt to change the current group ID to that group. +# +#proc-group= + +# Turn OFF the CLI support. +# By default it is always ON. +# See also options cli-ip and cli-port. +# +#no-cli + +#Local system IP address to be used for CLI server endpoint. Default value +# is 127.0.0.1. +# +#cli-ip=127.0.0.1 + +# CLI server port. Default is 5766. +# +#cli-port=5766 + +# CLI access password. Default is empty (no password). +# +#cli-password=logen + +# Server relay. NON-STANDARD AND DANGEROUS OPTION. +# Only for those applications when we want to run +# server applications on the relay endpoints. +# This option eliminates the IP permissions check on +# the packets incoming to the relay endpoints. +# +#server-relay + +# Maximum number of output sessions in ps CLI command. +# This value can be changed on-the-fly in CLI. The default value is 256. +# +#cli-max-output-sessions + +# Set network engine type for the process (for internal purposes). +# +#ne=[1|2|3] + +# Do not allow an SSL/TLS version of protocol +# +#no-sslv2 +#no-sslv3 +#no-tlsv1 +#no-tlsv1_1 +#no-tlsv1_2 diff --git a/examples/etc/turnuserdb.conf b/examples/etc/turnuserdb.conf new file mode 100644 index 00000000..340fd008 --- /dev/null +++ b/examples/etc/turnuserdb.conf @@ -0,0 +1,23 @@ +#This file can be used as user accounts storage for long-term credentials mechanism. +# +#username1:key1 +#username2:key2 +# OR: +#username1:password1 +#username2:password2 +# +# Keys must be generated by turnadmin utility. The key value depends +# on user name, realm, and password: +# +# Example: +# $ turnadmin -k -u ninefingers -r north.gov -p youhavetoberealistic +# Output: 0xbc807ee29df3c9ffa736523fb2c4e8ee +# ('0x' in the beginning of the key is what differentiates the key from +# password. If it has 0x then it is a key, otherwise it is a password). +# +# The corresponding user account entry in the userdb file will be: +# +#ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee +# Or, equivalently (less secure): +#ninefingers:youhavetoberealistic +# diff --git a/examples/scripts/basic/dos_attack.sh b/examples/scripts/basic/dos_attack.sh new file mode 100755 index 00000000..e6b3604d --- /dev/null +++ b/examples/scripts/basic/dos_attack.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# +# This is an example of a script for DOS attack emulation + +if [ -d examples ] ; then + cd examples +fi + +export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/ + +while [ 0 ] ; do + +PATH=examples/bin/:../bin/:bin/:${PATH} turnutils_uclient -O -D -G -n 1 -m 12 -e 127.0.0.1 -X -g $@ ::1 & + +PATH=examples/bin/:../bin/:bin/:${PATH} turnutils_uclient -O -G -n 1 -m 12 -y -s $@ 127.0.0.1 & + +PATH=examples/bin/:../bin:bin/:${PATH} turnutils_uclient -O -G -t -n 1 -m 12 -e 127.0.0.1 -X -g $@ ::1 & + +PATH=examples/bin/:../bin:bin/:${PATH} turnutils_uclient -O -G -T -n 1 -m 12 -y -s $@ 127.0.0.1 & + +sleep 1 + +type killall >>/dev/null 2>>/dev/null +ER=$? +if [ ${ER} -eq 0 ] ; then + killall turnutils_uclient >>/dev/null 2>>/dev/null +else + type pkill >>/dev/null 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + pkill turnutils_u >>/dev/null 2>>/dev/null + fi +fi + +done diff --git a/examples/scripts/basic/relay.sh b/examples/scripts/basic/relay.sh new file mode 100755 index 00000000..ee597c73 --- /dev/null +++ b/examples/scripts/basic/relay.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# non-secure mode (when authentication is not used). +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# Other options: +# set bandwidth limit on client session 3000000 bytes per second (--max-bps) +# use fingerprints (-f) +# use 3 relay threads (-m 3) +# use min UDP relay port 32355 and max UDP relay port 65535 +# --no-tls and --no-dtls mean that we are not trying to +# --no-auth means that no authentication to be used, +# allow anonymous users. +# start TLS and DTLS services. +# 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 -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 --no-tls --no-dtls --no-auth $@ + + + + diff --git a/examples/scripts/basic/tcp_client.sh b/examples/scripts/basic/tcp_client.sh new file mode 100755 index 00000000..a7ff1b22 --- /dev/null +++ b/examples/scripts/basic/tcp_client.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# +# This is an example of a script to run a "unsecure" TURN TCP client. +# Options: +# 1) -t is present, it means that TCP 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) -s option is absent - it means that the client will be using +# the "channel" mechanism for data. +# 11) -X means that IPv4 relay address is requested. +# 12) ::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 3037 -e 127.0.0.1 -g -X $@ ::1 + diff --git a/examples/scripts/basic/tcp_client_c2c_tcp_relay.sh b/examples/scripts/basic/tcp_client_c2c_tcp_relay.sh new file mode 100755 index 00000000..d67a1ad5 --- /dev/null +++ b/examples/scripts/basic/tcp_client_c2c_tcp_relay.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# +# This is an example of a script to run a "unsecure" TURN TCP client +# with TCP relay endpoints (RFC 6062). +# Options: +# 1) -T is present, it means that TCP networking is used with TCP relay endpoints. +# 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) ::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 $@ ::1 + diff --git a/examples/scripts/basic/udp_c2c_client.sh b/examples/scripts/basic/udp_c2c_client.sh new file mode 100755 index 00000000..9c6f48f4 --- /dev/null +++ b/examples/scripts/basic/udp_c2c_client.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# +# This is an example of a script to run a "unsecure" TURN UDP client, +# in client-to-client fashion (when client talks to another client +# through their corresponding allocated relayed endpoints). +# 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) -y means "client to client" communication pattern. +# the client calculates the peer address +# (which is the allocated relayed endpoint of the next client in array of clients). +# 8) -l 170 means that the payload size of the packets is 170 bytes +# like average audio RTP packet). +# 9) -s option is absent - it means that the client will be using +# the "channel" mechanism for data. +# 10) 127.0.0.1 (the last parameter) is the TURN Server IP address. +# 11) -z 5 means that we want 5 ms interval between the packets (per each session). +# + +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 -y -l 170 -z 15 $@ 127.0.0.1 + diff --git a/examples/scripts/basic/udp_client.sh b/examples/scripts/basic/udp_client.sh new file mode 100755 index 00000000..39615974 --- /dev/null +++ b/examples/scripts/basic/udp_client.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# +# This is an example of a script to run a "unsecure" TURN UDP client. +# Options: +# 0) -D means "mandatory padding", like pjnath does; +# 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 171 means that the payload size of the packets is 171 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) -s option is absent - it means that the client will be using +# the "channel" mechanism for data. +# 11) -X means that IPv4 relay address is requested. +# 12) 127.0.0.1 (the last parameter) is the TURN Server IP address. We use IPv4 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 -D -n 1000 -m 10 -l 171 -e 127.0.0.1 -g -X $@ 127.0.0.1 + diff --git a/examples/scripts/loadbalance/master_relay.sh b/examples/scripts/loadbalance/master_relay.sh new file mode 100755 index 00000000..f7d0e016 --- /dev/null +++ b/examples/scripts/loadbalance/master_relay.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# This is an example of a MASTER TURN server that distributes +# the load among several "slave" TURN servers. +# +# The TURN Server is started in +# secure mode (when authentication is used) - see option -a +# that means "use long-term credential mechanism". +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1. We use 127.0.0.1 as the relay address, too. +# +# 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) "-r north.gov" means "use authentication realm north.gov" +# 6) "--user=ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee" means +# "allow user 'ninefinger' with generated key '0xbc807ee29df3c9ffa736523fb2c4e8ee' ". +# 7) "--user=gorst:hero" means "allow user 'gorst' with password 'hero' ". +# 8) "--log-file=stdout" means that all log output will go to the stdout. +# 9) "-v" means normal verbose mode (with some moderate logging). +# 10) --no-dtls and --no-tls measn that we are not using DTLS & TLS protocols here +# (for the sake of simplicity). +# 11) --alternate-server options set the "slave" servers. +# 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 --syslog -a -L 127.0.0.1 -E 127.0.0.1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --user=ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee --user=gorst:hero -r north.gov --log-file=stdout -v --no-dtls --no-tls --alternate-server=127.0.0.1:3333 --alternate-server=127.0.0.1:4444 $@ + diff --git a/examples/scripts/loadbalance/slave_relay_1.sh b/examples/scripts/loadbalance/slave_relay_1.sh new file mode 100755 index 00000000..f924836b --- /dev/null +++ b/examples/scripts/loadbalance/slave_relay_1.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# This is an example of a SLAVE TURN server that accepts +# the redirected requests. +# +# The TURN Server is started in +# secure mode (when authentication is used) - see option -a +# that means "use long-term credential mechanism". +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1. We use 127.0.0.1 as the relay address, too. +# +# 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 10000 and max UDP relay port 19999 +# 5) "-r north.gov" means "use authentication realm north.gov" +# 6) "--user=ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee" means +# "allow user 'ninefinger' with generated key '0xbc807ee29df3c9ffa736523fb2c4e8ee' ". +# 7) "--user=gorst:hero" means "allow user 'gorst' with password 'hero' ". +# 8) "--log-file=stdout" means that all log output will go to the stdout. +# 9) "-v" means normal verbose mode (with some moderate logging). +# 10) --no-dtls and --no-tls measn that we are not using DTLS & TLS protocols here +# (for the sake of simplicity). +# 11) -p 3333 means that we are using UDP & TCP listening port 3333. +# 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 --syslog -a -L 127.0.0.1 -E 127.0.0.1 --max-bps=3000000 -f -m 3 --min-port=10000 --max-port=19999 --user=ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee --user=gorst:hero -r north.gov --log-file=stdout -v --no-dtls --no-tls -p 3333 --cli-port=5767 $@ diff --git a/examples/scripts/loadbalance/slave_relay_2.sh b/examples/scripts/loadbalance/slave_relay_2.sh new file mode 100755 index 00000000..f923da9d --- /dev/null +++ b/examples/scripts/loadbalance/slave_relay_2.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# This is an example of a SLAVE TURN server that accepts +# the redirected requests. +# +# The TURN Server is started in +# secure mode (when authentication is used) - see option -a +# that means "use long-term credential mechanism". +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1. We use 127.0.0.1 as the relay address, too. +# +# 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 20000 and max UDP relay port 29999 +# 5) "-r north.gov" means "use authentication realm north.gov" +# 6) "--user=ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee" means +# "allow user 'ninefinger' with generated key '0xbc807ee29df3c9ffa736523fb2c4e8ee' ". +# 7) "--user=gorst:hero" means "allow user 'gorst' with password 'hero' ". +# 8) "--log-file=stdout" means that all log output will go to the stdout. +# 9) "-v" means normal verbose mode (with some moderate logging). +# 10) --no-dtls and --no-tls measn that we are not using DTLS & TLS protocols here +# (for the sake of simplicity). +# 11) -p 4444 means that we are using UDP & TCP listening port 4444. +# 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 --syslog -a -L 127.0.0.1 -E 127.0.0.1 --max-bps=3000000 -f -m 3 --min-port=20000 --max-port=29999 --user=ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee --user=gorst:hero -r north.gov --log-file=stdout -v --no-dtls --no-tls -p 4444 --cli-port=5768 $@ diff --git a/examples/scripts/loadbalance/tcp_c2c_tcp_relay.sh b/examples/scripts/loadbalance/tcp_c2c_tcp_relay.sh new file mode 100755 index 00000000..b76a5548 --- /dev/null +++ b/examples/scripts/loadbalance/tcp_c2c_tcp_relay.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN TCP client +# with the long-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) -u gorst means that if the server challenges the client with +# authentication challenge, then we use account "gorst". +# 11) -w hero sets the password for the account as "hero". +# 12) 127.0.0.1 (the last parameter) is the TURN Server IP address. +# + +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 -u gorst -w hero $@ 127.0.0.1 diff --git a/examples/scripts/loadbalance/udp_c2c.sh b/examples/scripts/loadbalance/udp_c2c.sh new file mode 100755 index 00000000..52f21607 --- /dev/null +++ b/examples/scripts/loadbalance/udp_c2c.sh @@ -0,0 +1,31 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN UDP client +# with the long-term credentials mechanism, +# in client-to-client communication patter. +# +# 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) -y means that the clients will be connecting to each other and the peer will not be used. +# 9) -g means "set DONT_FRAGMENT parameter in TURN requests". +# 10) -u ninefingers means that if the server challenges the client with +# authentication challenge, then we use account "ninefingers". +# 11) -w youhavetoberealistic sets the password for the account as "youhavetoberealistic". +# 12) -s option is absent - it means that the client will be using +# the "channel" mechanism for data. +# 13) 127.0.0.1 (the last parameter) is the TURN Server IP address. +# + +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 -g -u ninefingers -w youhavetoberealistic -y $@ 127.0.0.1 diff --git a/examples/scripts/longtermsecure/secure_dos_attack.sh b/examples/scripts/longtermsecure/secure_dos_attack.sh new file mode 100755 index 00000000..c5ff18cf --- /dev/null +++ b/examples/scripts/longtermsecure/secure_dos_attack.sh @@ -0,0 +1,49 @@ +#!/bin/sh +# +# This is an example of a script to run a DOS attack in a +# "secure" environment +# + +if [ -d examples ] ; then + cd examples +fi + +export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/ + +while [ 0 ] ; do + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -O -n 10 -m 10 -l 170 -g -u ninefingers -w youhavetoberealistic -y $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -O -n 10 -m 10 -l 170 -e 127.0.0.1 -X -g -u ninefingers -w youhavetoberealistic $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -G -O -S -k turn_client_pkey.pem -n 10 -m 10 -l 170 -e ::1 -x -g -u ninefingers -w youhavetoberealistic -s $@ 127.0.0.1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -O -t -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -O -T -n 10 -m 10 -l 170 -y -g -u gorst -w hero $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -G -O -T -S -k turn_client_pkey.pem -n 10 -m 10 -l 170 -y -g -u gorst -w hero $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -G -O -t -S -k turn_client_pkey.pem -n 10 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 & + +sleep 2 + +type killall >>/dev/null 2>>/dev/null +ER=$? +if [ ${ER} -eq 0 ] ; then + killall turnutils_uclient >>/dev/null 2>>/dev/null +fi + +type pkill >>/dev/null 2>>/dev/null +ER=$? +if [ ${ER} -eq 0 ] ; then + pkill turnutils_u >>/dev/null 2>>/dev/null + pkill turnutils_uclie >>/dev/null 2>>/dev/null + pkill turnutils_uclient >>/dev/null 2>>/dev/null +else + sleep 10 +fi + +done + + diff --git a/examples/scripts/longtermsecure/secure_dtls_client.sh b/examples/scripts/longtermsecure/secure_dtls_client.sh new file mode 100755 index 00000000..c962b1d1 --- /dev/null +++ b/examples/scripts/longtermsecure/secure_dtls_client.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN DTLS client +# with the long-term credentials mechanism. +# +# Options: +# +# 1) -t is absent, it means that UDP networking is used. +# 2) -S means "SSL protocol with default encryption" +# 3) -i absent. +# 4) -k sets private key file for TLS. +# 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 IPv4 address 127.0.0.1. +# 9) -g means "set DONT_FRAGMENT parameter in TURN requests". +# 10) -u ninefingers means that if the server challenges the client with +# authentication challenge, then we use account "ninefingers". +# 11) -w youhavetoberealistic sets the password for the account. +# 12) -s option absent - that means that the client will be using +# the channel mechanism for data. +# 13) 127.0.0.1 (the last parameter) is the TURN Server IP address. +# We use IPv6 - to - IPv4 here to illustrate how the TURN Server +# converts 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 -S -k turn_client_pkey.pem -n 1000 -m 10 -l 170 -e 127.0.0.1 -X -g -u ninefingers -w youhavetoberealistic $@ 127.0.0.1 + diff --git a/examples/scripts/longtermsecure/secure_dtls_client_cert.sh b/examples/scripts/longtermsecure/secure_dtls_client_cert.sh new file mode 100755 index 00000000..a779ac68 --- /dev/null +++ b/examples/scripts/longtermsecure/secure_dtls_client_cert.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN DTLS client +# with the long-term credentials mechanism and with certificate check. +# +# Options: +# +# 1) -t is absent, it means that UDP networking is used. +# 2) -S means "SSL protocol with default encryption" +# 3) -i sets certificate file for TLS. -R sets certificate check mode. +# -E sets CA file for certificate check. +# 4) -k sets private key file for TLS. +# 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 IPv4 address 127.0.0.1. +# 9) -g means "set DONT_FRAGMENT parameter in TURN requests". +# 10) -u bolt means that if the server challenges the client with +# authentication challenge, then we use account "bolt". +# 11) -w kwyjibo sets the password for the account. +# 12) -s option means that the client will be using "send" mechanism for data. +# 13) 127.0.0.1 (the last parameter) is the TURN Server IP address. +# We use IPv6 - to - IPv4 here to illustrate how the TURN Server +# converts 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 -S -i turn_server_cert.pem -k turn_server_pkey.pem -E turn_server_cert.pem -n 1000 -m 10 -l 170 -e 127.0.0.1 -g -u bolt -w kwyjibo -s -X $@ 127.0.0.1 + diff --git a/examples/scripts/longtermsecure/secure_relay.sh b/examples/scripts/longtermsecure/secure_relay.sh new file mode 100755 index 00000000..d390265b --- /dev/null +++ b/examples/scripts/longtermsecure/secure_relay.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure mode (when authentication is used) - see option -a +# that means "use long-term credential mechanism". +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# Other options: +# +# 1) set bandwidth limit on client session 3000000 bytes per second (--max-bps). +# 2) use fingerprints (-f) +# 3) use 10 relay threads (-m 10) +# 4) use min UDP relay port 32355 and max UDP relay port 65535 +# 5) "-r north.gov" means "use authentication realm north.gov" +# 6) "--user=ninefingers:youhavetoberealistic" means +# "allow user 'ninefinger' with password 'youhavetoberealistic' ". +# 7) "--user=gorst:hero" means "allow user 'gorst' with password 'hero' ". +# 8) "--cert=turn_server_cert.pem" sets the OpenSSL certificate file name. +# 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 +# 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 --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 $@ diff --git a/examples/scripts/longtermsecure/secure_relay_cert.sh b/examples/scripts/longtermsecure/secure_relay_cert.sh new file mode 100755 index 00000000..9df3b4d7 --- /dev/null +++ b/examples/scripts/longtermsecure/secure_relay_cert.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure mode (when authentication is used) - see option -a +# that means "use long-term credential mechanism". +# +# This script shows how to use certificate check option. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# Other options: +# +# 1) set bandwidth limit on client session 3000000 bytes per second (--max-bps). +# 2) use fingerprints (-f) +# 3) use 10 relay threads (-m 10) +# 4) use min UDP relay port 32355 and max UDP relay port 65535 +# 5) "-r bolt.co" means "use authentication realm 'bolt.co'" +# 6) "--user=ninefingers:youhavetoberealistic" means "allow user +# 'ninefinger' with password 'youhavetoberealistic'.". +# 7) "--user=bolt:kwyjibo" means "allow user 'bolt' with password 'kwyjibo' ". +# 8) "--cert=..." sets the OpenSSL certificate file name. +# 9) "--pkey=..." sets the OpenSSL private key name. +# 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". +# 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 --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" $@ diff --git a/examples/scripts/longtermsecure/secure_tcp_client.sh b/examples/scripts/longtermsecure/secure_tcp_client.sh new file mode 100755 index 00000000..3e76efd5 --- /dev/null +++ b/examples/scripts/longtermsecure/secure_tcp_client.sh @@ -0,0 +1,31 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN TCP client +# with the long-term credentials mechanism. +# +# Options: +# +# 1) -t is present, it means that TCP 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) -u gorst means that if the server challenges the client with +# authentication challenge, then we use account "gorst". +# 11) -w hero sets the password for the account as "hero". +# 12) -s option is absent - it means that the client will be using +# the "channel" mechanism for data. +# 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 3000 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 diff --git a/examples/scripts/longtermsecure/secure_tcp_client_c2c_tcp_relay.sh b/examples/scripts/longtermsecure/secure_tcp_client_c2c_tcp_relay.sh new file mode 100755 index 00000000..68da930c --- /dev/null +++ b/examples/scripts/longtermsecure/secure_tcp_client_c2c_tcp_relay.sh @@ -0,0 +1,31 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN TCP client +# with the long-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) -u gorst means that if the server challenges the client with +# authentication challenge, then we use account "gorst". +# 11) -w hero sets the password for the account as "hero". +# 12) 127.0.0.1 (the last parameter) is the TURN Server IP address. We use IPv4 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 -u gorst -w hero $@ 127.0.0.1 + diff --git a/examples/scripts/longtermsecure/secure_tls_client.sh b/examples/scripts/longtermsecure/secure_tls_client.sh new file mode 100755 index 00000000..6eeef04d --- /dev/null +++ b/examples/scripts/longtermsecure/secure_tls_client.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN TLS client +# with the long-term credentials mechanism. +# +# Options: +# +# 1) -t is present, it means that TCP networking is used. +# 2) -S means "SSL/TLS protocol with default cipher". +# 3) -i absent. +# 4) -k sets private key file for TLS. +# 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) -u gorst means that if the server challenges the client with +# authentication challenge, then we use account "gorst". +# 11) -w hero sets the password for the account as "hero". +# 12) -s option means that the client will be using "send" mechanism for data. +# 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 -S -k turn_client_pkey.pem -n 1000 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 + diff --git a/examples/scripts/longtermsecure/secure_tls_client_c2c_tcp_relay.sh b/examples/scripts/longtermsecure/secure_tls_client_c2c_tcp_relay.sh new file mode 100755 index 00000000..ac6727fa --- /dev/null +++ b/examples/scripts/longtermsecure/secure_tls_client_c2c_tcp_relay.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN TLS client +# with the long-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. +# 2) -S means that "secure protocol", that is TLS in the case of TCP, +# will be used between the client and the TURN Server. +# 3) -i absent. +# 4) -k sets private key file for TLS. +# 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) -u gorst means that if the server challenges the client with +# authentication challenge, then we use account "gorst". +# 11) -w hero sets the password for the account as "hero". +# 12) ::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/:/usr/postgres/9.2-pgdg/lib + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -T -S -k turn_client_pkey.pem -n 1000 -m 10 -l 170 -y -g -u gorst -w hero $@ ::1 diff --git a/examples/scripts/longtermsecure/secure_tls_client_cert.sh b/examples/scripts/longtermsecure/secure_tls_client_cert.sh new file mode 100755 index 00000000..80d7db5e --- /dev/null +++ b/examples/scripts/longtermsecure/secure_tls_client_cert.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN DTLS client +# with the long-term credentials mechanism and with certificate check. +# +# Options: +# +# 1) -t means that TCP networking is used. +# 2) -S means "SSL protocol with default encryption" +# 3) -i sets certificate file for TLS. -R sets certificate check mode. +# -E sets CA file for certificate check. +# 4) -k sets private key file for TLS. +# 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 IPv4 address 127.0.0.1. +# 9) -g means "set DONT_FRAGMENT parameter in TURN requests". +# 10) -u bolt means that if the server challenges the client with +# authentication challenge, then we use account "bolt". +# 11) -w kwyjibo sets the password for the account. +# 12) -s option means that the client will be using "send" mechanism for data. +# 13) 127.0.0.1 (the last parameter) is the TURN Server IP address. +# We use IPv6 - to - IPv4 here to illustrate how the TURN Server +# converts 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 -S -i turn_server_cert.pem -k turn_server_pkey.pem -E turn_server_cert.pem -n 1000 -m 10 -l 170 -e 127.0.0.1 -X -g -u bolt -w kwyjibo -s $@ 127.0.0.1 + diff --git a/examples/scripts/longtermsecure/secure_udp_c2c.sh b/examples/scripts/longtermsecure/secure_udp_c2c.sh new file mode 100755 index 00000000..c58a023d --- /dev/null +++ b/examples/scripts/longtermsecure/secure_udp_c2c.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN UDP client +# with the long-term credentials mechanism, +# in client-to-client communication patter. +# +# 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) -y means that the clients will be connecting to each other and the peer will not be used. +# 9) -g means "set DONT_FRAGMENT parameter in TURN requests". +# 10) -u ninefingers means that if the server challenges the client with +# authentication challenge, then we use account "ninefingers". +# 11) -w youhavetoberealistic sets the password for the account as "youhavetoberealistic". +# 12) -s option is present - it means that the client will be using +# the DATA mechanism for data. +# 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 -s -n 1000 -m 10 -l 170 -g -u ninefingers -w youhavetoberealistic -y $@ ::1 diff --git a/examples/scripts/longtermsecure/secure_udp_client.sh b/examples/scripts/longtermsecure/secure_udp_client.sh new file mode 100755 index 00000000..3ac8f7c4 --- /dev/null +++ b/examples/scripts/longtermsecure/secure_udp_client.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN UDP client +# with the long-term credentials 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) -u ninefingers means that if the server challenges the client with +# authentication challenge, then we use account "ninefingers". +# 11) -w youhavetoberealistic sets the password for the account as "youhavetoberealistic". +# 12) -s option is absent - it means that the client will be using +# the "channel" mechanism for data. +# 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 -n 1000 -m 10 -l 170 -e 127.0.0.1 -X -g -u ninefingers -w youhavetoberealistic $@ ::1 + diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh new file mode 100755 index 00000000..e53c8ef5 --- /dev/null +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure mode with MySQL database for users +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) "-r north.gov" means "use authentication realm north.gov" +# 6) --mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" +# means that local MySQL database "coturn" will be used, with database user "turn" and +# database user password "turn", and connection timeout 30 seconds. +# 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 +# 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 -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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh new file mode 100755 index 00000000..4f1245d9 --- /dev/null +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure mode with Postgres database for users +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) "-r north.gov" means "use authentication realm north.gov" +# 6) --psql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" +# means that local database "coturn" will be used, with database user "turn" and database user +# password "turn". +# 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 +# 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 -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 $@ + +# Newer PostgreSQL style connection string example: +# 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 --psql-userdb=postgresql://turn:turn@/turn --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh new file mode 100755 index 00000000..9800883f --- /dev/null +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure mode with Redis database for users +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) "-r north.gov" means "use authentication realm north.gov" +# 6) --redis-userdb="ip=127.0.0.1 dbname=2 password=turn connect_timeout=30" +# means that local Redis database 0 will be used, +# database password is "turn", and connection timeout 30 seconds. +# 7) --redis-statsdb="ip=127.0.0.1 dbname=3 password=turn connect_timeout=30" +# means that we want to use Redis for status and statistics information, +# and this will be the database number 3. +# 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 +# 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 -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 $@ diff --git a/examples/scripts/mobile/mobile_dtls_client.sh b/examples/scripts/mobile/mobile_dtls_client.sh new file mode 100755 index 00000000..f8eed85e --- /dev/null +++ b/examples/scripts/mobile/mobile_dtls_client.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN DTLS client +# with "mobile" option and the long-term credentials mechanism. +# +# Options: +# +# 1) -t is absent, it means that UDP networking is used. +# 2) -S means "SSL protocol with default encryption" +# 3) -i absent. +# 4) -k sets private key file for TLS. +# 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 IPv4 address 127.0.0.1. +# 9) -g means "set DONT_FRAGMENT parameter in TURN requests". +# 10) -u ninefingers means that if the server challenges the client with +# authentication challenge, then we use account "ninefingers". +# 11) -w youhavetoberealistic sets the password for the account. +# 12) -s option means that the client will be using "send" mechanism for data. +# 13) -M turns on the Mobile ICE TURN functionality. +# 14) 127.0.0.1 (the last parameter) is the TURN Server IP address. +# We use IPv6 - to - IPv4 here to illustrate how the TURN Server +# converts 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 -S -k turn_client_pkey.pem -n 1000 -m 10 -l 170 -e 127.0.0.1 -X -g -u ninefingers -w youhavetoberealistic -s -M $@ 127.0.0.1 + diff --git a/examples/scripts/mobile/mobile_relay.sh b/examples/scripts/mobile/mobile_relay.sh new file mode 100755 index 00000000..b7ff83c1 --- /dev/null +++ b/examples/scripts/mobile/mobile_relay.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# This is an example how to start a "mobile" TURN Server in +# secure mode (when authentication is used) - see option -a +# that means "use long-term credential mechanism". +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# Other options: +# +# 1) set bandwidth limit on client session 3000000 bytes per second (--max-bps). +# 2) use fingerprints (-f) +# 3) use 10 relay threads (-m 10) +# 4) use min UDP relay port 32355 and max UDP relay port 65535 +# 5) "-r north.gov" means "use authentication realm north.gov" +# 6) "--user=ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee" means +# "allow user 'ninefinger' with generated key '0xbc807ee29df3c9ffa736523fb2c4e8ee' ". +# 7) "--user=gorst:hero" means "allow user 'gorst' with password 'hero' ". +# 8) "--cert=turn_server_cert.pem" sets the OpenSSL certificate file name. +# 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) "--mobility" turns on the Mobile ICE TURN functionality. +# 13) --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 --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 $@ diff --git a/examples/scripts/mobile/mobile_tcp_client.sh b/examples/scripts/mobile/mobile_tcp_client.sh new file mode 100755 index 00000000..4e186b37 --- /dev/null +++ b/examples/scripts/mobile/mobile_tcp_client.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" "mobile" +# TURN TCP client with the long-term credentials mechanism. +# +# Options: +# +# 1) -t is present, it means that TCP 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) -u gorst means that if the server challenges the client with +# authentication challenge, then we use account "gorst". +# 11) -w hero sets the password for the account as "hero". +# 12) -s option is absent - it means that the client will be using +# the "channel" mechanism for data. +# 13) -M turns on the Mobile ICE TURN functionality. +# 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 -t -n 3000 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero -M $@ ::1 diff --git a/examples/scripts/mobile/mobile_tls_client_c2c_tcp_relay.sh b/examples/scripts/mobile/mobile_tls_client_c2c_tcp_relay.sh new file mode 100755 index 00000000..bbb017c8 --- /dev/null +++ b/examples/scripts/mobile/mobile_tls_client_c2c_tcp_relay.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN TLS client +# with "mobile" option and with the long-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. +# 2) -S means that "secure protocol", that is TLS in the case of TCP, +# will be used between the client and the TURN Server. +# 3) -i absent. +# 4) -k sets private key file for TLS. +# 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) -u gorst means that if the server challenges the client with +# authentication challenge, then we use account "gorst". +# 11) -w hero sets the password for the account as "hero". +# 12) -M turns on the Mobile ICE TURN functionality. +# 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/:/usr/postgres/9.2-pgdg/lib + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -T -S -k turn_client_pkey.pem -n 1000 -m 10 -l 170 -y -g -u gorst -w hero -M $@ ::1 diff --git a/examples/scripts/mobile/mobile_udp_client.sh b/examples/scripts/mobile/mobile_udp_client.sh new file mode 100755 index 00000000..6f453df6 --- /dev/null +++ b/examples/scripts/mobile/mobile_udp_client.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN UDP client +# with "mobile" option and with the long-term credentials 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) -u ninefingers means that if the server challenges the client with +# authentication challenge, then we use account "ninefingers". +# 11) -w youhavetoberealistic sets the password for the account as "youhavetoberealistic". +# 12) -s option is absent - it means that the client will be using +# the "channel" mechanism for data. +# 13) -M turns on the Mobile ICE TURN functionality. +# 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 -u ninefingers -w youhavetoberealistic -M $@ ::1 + diff --git a/examples/scripts/peer.sh b/examples/scripts/peer.sh new file mode 100755 index 00000000..4e09f71b --- /dev/null +++ b/examples/scripts/peer.sh @@ -0,0 +1,16 @@ +#!/bin/sh +# +# This is a script for the peer application, +# for testing only purposes. It opens UDP echo-like sockets +# on IPv4 address 127.0.0.1 and IPv6 address ::1. +# The default port 3480 is used. +# + +if [ -d examples ] ; then + cd examples +fi + +export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/ +export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/ + +PATH=examples/bin/:bin/:../bin:${PATH} turnutils_peer -L 127.0.0.1 -L ::1 -L 0.0.0.0 $@ diff --git a/examples/scripts/readme.txt b/examples/scripts/readme.txt new file mode 100644 index 00000000..4514771a --- /dev/null +++ b/examples/scripts/readme.txt @@ -0,0 +1,26 @@ +This directory contains various example scripts for the TURN server +functionality illustration. + +1) peer.sh starts the "peer" application that serves as a peer for all examples. + +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). + +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" +directory. Of course, the database (PostgreSQL or MySQL) must 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 +ALTERNATE-SERVER functionality. + + + diff --git a/examples/scripts/restapi/secure_relay_secret.sh b/examples/scripts/restapi/secure_relay_secret.sh new file mode 100755 index 00000000..539742c4 --- /dev/null +++ b/examples/scripts/restapi/secure_relay_secret.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure 'static' 'secret' mode (see TURNServerRESTAPI.pdf) +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) --use-auth-secret means that we are using 'secret' authentication mode. +# 6) --static-auth-secret=logen means that we will be using 'static' secret value. +# 7) --realm=north.gov sets realm value as "north.gov". +# 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) "-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. +# 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 -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 $@ + diff --git a/examples/scripts/restapi/secure_relay_secret_with_db_mysql.sh b/examples/scripts/restapi/secure_relay_secret_with_db_mysql.sh new file mode 100755 index 00000000..eeab4d20 --- /dev/null +++ b/examples/scripts/restapi/secure_relay_secret_with_db_mysql.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure 'dynamic' 'secret' mode (see TURNServerRESTAPI.pdf) +# with MySQL database for users information +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) --use-auth-secret means that we are using 'secret' authentication mode. +# Absense of --static-auth-secret value means that we will be taking the secret value +# from the database ('dynamic' mode). +# 6) --realm=north.gov sets realm value as "north.gov". +# 7) --mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" +# means that local MySQL database "coturn" will be used, with database user "turn" and +# with database user password "turn", and connection timeout 30 seconds. +# 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 +# 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 -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 $@ diff --git a/examples/scripts/restapi/secure_relay_secret_with_db_psql.sh b/examples/scripts/restapi/secure_relay_secret_with_db_psql.sh new file mode 100755 index 00000000..c0637c0a --- /dev/null +++ b/examples/scripts/restapi/secure_relay_secret_with_db_psql.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure 'dynamic' 'secret' mode (see TURNServerRESTAPI.pdf) +# with PostgreSQL database for users information +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) --use-auth-secret means that we are using 'secret' authentication mode. +# Absense of --static-auth-secret value means that we will be taking the secret value +# from the database ('dynamic' mode). +# 6)--realm=north.gov sets realm value as "north.gov". +# 7) --psql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" +# means that local PostgreSQL database "coturn" will be used, with database user "turn" and +# with database user password "turn", and connection timeout 30 seconds. +# 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. +# 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 -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 $@ diff --git a/examples/scripts/restapi/secure_relay_secret_with_db_redis.sh b/examples/scripts/restapi/secure_relay_secret_with_db_redis.sh new file mode 100755 index 00000000..0b64d566 --- /dev/null +++ b/examples/scripts/restapi/secure_relay_secret_with_db_redis.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure 'dynamic' 'secret' mode (see TURNServerRESTAPI.pdf) +# with Redis database for users information +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) --use-auth-secret means that we are using 'secret' authentication mode. +# Absense of --static-auth-secret value means that we will be taking the secret value +# from the database ('dynamic' mode). +# 6) --realm=north.gov sets realm value as "north.gov". +# 7) --redis-userdb="ip=127.0.0.1 dbname=2 password=turn connect_timeout=30" +# means that local Redis database 0 will be used, with database +# password "turn", and connection timeout 30 seconds. +# 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. +# 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 -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 $@ diff --git a/examples/scripts/restapi/secure_udp_client_with_secret.sh b/examples/scripts/restapi/secure_udp_client_with_secret.sh new file mode 100755 index 00000000..fc5e0feb --- /dev/null +++ b/examples/scripts/restapi/secure_udp_client_with_secret.sh @@ -0,0 +1,31 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN UDP client +# with the long-term credentials mechanism and with +# secret-based authorization (see TURNServerRESTAPI.pdf document). +# +# 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) -u ninefingers means that if the server challenges the client with +# authentication challenge, then we use account "ninefingers". +# 11) -W logen sets the secret for the secret-based authentication as "logen". +# 12) -s option is absent - it means that the client will be using +# the "channel" mechanism for data. +# 13) ::1 (the last parameter) is the TURN Server IPv6 address. +# + +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 -z 5 -n 10000 -s -m 10 -l 170 -e 127.0.0.1 -X -g -u ninefingers -W logen $@ ::1 diff --git a/examples/scripts/restapi/shared_secret_maintainer.pl b/examples/scripts/restapi/shared_secret_maintainer.pl new file mode 100755 index 00000000..90c5d86b --- /dev/null +++ b/examples/scripts/restapi/shared_secret_maintainer.pl @@ -0,0 +1,105 @@ +#!/usr/bin/perl + +# +# This is an example of Perl script maintaining dynamic shared secret +# database for the REST API +# + +use strict; +use warnings; + +use DBI; +use HTTP::Request::Common; + +my $DBNAME="turn"; +my $DBUSERNAME="turn"; +my $DBPWD="turn"; +my $DBHOST="localhost"; + +my $webserver = 'http://example.com/'; + +my $old_secret = ""; +my $current_secret=""; + +my $INTERVAL=3600; + +my $dbh; + +$dbh = DBI->connect("DBI:mysql:$DBNAME;host=$DBHOST", $DBUSERNAME, $DBPWD) + || die "Could not connect to database: $DBI::errstr"; + +$dbh->do('CREATE TABLE IF NOT EXISTS turn_secret (value varchar(512))'); + +my $c = $dbh->do("delete from turn_secret"); +print "Deleted $c rows\n"; + +$dbh->disconnect(); + +do { + + $dbh = DBI->connect("DBI:mysql:$DBNAME;host=$DBHOST", $DBUSERNAME, $DBPWD) + || die "Could not connect to database: $DBI::errstr"; + + $dbh->do('CREATE TABLE IF NOT EXISTS turn_secret (value varchar(512))'); + + if(length($current_secret)) { + if(length($old_secret)) { + remove_secret($dbh, $old_secret); + } + $old_secret=$current_secret; + } + + print "CURRENT SECRET TO BE (RE)GENERATED\n"; + $current_secret = generate_secret(); + insert_secret($dbh, $current_secret); + + $dbh->disconnect(); + +# +# Web server interaction example: +# Here we can put code to submit this secret to the web server: +# + my $req = POST($webserver, Content => [param => $current_secret]); + + $req->method('PUT'); + + print $req->as_string,"\n"; + +# +# Alternatively, you can use this link for compute-on-demand: +# https://github.com/alfreddatakillen/computeengineondemand +# +# write your code here. +# + + sleep($INTERVAL); + +} while(1); + +sub remove_secret { + + my $dbh = shift; + my $secret=shift; + + my $c = $dbh->do("delete from turn_secret where value = '$secret'"); + print "Deleted $c rows\n"; + +} + +sub insert_secret { + + my $dbh = shift; + my $secret=shift; + + my $c = $dbh->do("insert into turn_secret values('$secret')"); + print "Inserted $c rows\n"; + +} + +sub generate_secret { + my @chars = ('0'..'9', 'A'..'F'); + my $len = 8; + my $string; + while($len--){ $string .= $chars[rand @chars] }; + return $string; +} diff --git a/examples/scripts/rfc5769.sh b/examples/scripts/rfc5769.sh new file mode 100755 index 00000000..afa36220 --- /dev/null +++ b/examples/scripts/rfc5769.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# +# This is a script for RFC 5769 STUN protocol check. +# It checks whether the main code was compiled correctly. +# + +if [ -d examples ] ; then + cd examples +fi + +export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/ +export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/ + +PATH=examples/bin/:bin/:../bin:${PATH} turnutils_rfc5769check $@ diff --git a/examples/scripts/selfloadbalance/secure_dos_attack.sh b/examples/scripts/selfloadbalance/secure_dos_attack.sh new file mode 100755 index 00000000..75189d66 --- /dev/null +++ b/examples/scripts/selfloadbalance/secure_dos_attack.sh @@ -0,0 +1,130 @@ +#!/bin/sh +# +# This is an example of a script to run a DOS attack +# in a "secure" environment on a server with +# self-load-balancing option +# + +if [ -d examples ] ; then + cd examples +fi + +export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/ + +export SLEEP_TIME=9 + +while [ 0 ] ; do + +rm -rf /var/log/turnserver/* + +########################## + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -n 30 -m 10 -l 170 -g -u ninefingers -w youhavetoberealistic -y $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u ninefingers -w youhavetoberealistic $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -G -S -k turn_client_pkey.pem -n 10 -m 10 -l 170 -e ::1 -x -g -u ninefingers -w youhavetoberealistic -s $@ 127.0.0.1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -t -n 50 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -T -n 30 -m 10 -l 170 -y -g -u gorst -w hero $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -G -T -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -y -g -u gorst -w hero $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -G -t -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -n 30 -m 10 -l 170 -g -u ninefingers -w youhavetoberealistic -y -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u ninefingers -w youhavetoberealistic -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -G -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -e ::1 -x -g -u ninefingers -w youhavetoberealistic -s -p 12345 $@ 127.0.0.1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -t -n 50 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -T -n 30 -m 10 -l 170 -y -g -u gorst -w hero -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -G -T -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -y -g -u gorst -w hero -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -G -t -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -n 30 -m 10 -l 170 -g -u ninefingers -w youhavetoberealistic -y -p 12346 $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u ninefingers -w youhavetoberealistic -p 12346 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -G -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -e ::1 -x -g -u ninefingers -w youhavetoberealistic -s -p 12346 $@ 127.0.0.1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -t -n 50 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero -p 12346 $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -G -T -n 30 -m 10 -l 170 -y -g -u gorst -w hero -p 12346 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -G -T -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -y -g -u gorst -w hero -p 12346 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -G -t -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero -p 12346 $@ ::1 & + +########################### + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -O -N -R -G -n 30 -m 10 -l 170 -g -u ninefingers -w youhavetoberealistic -y $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -O -N -R -G -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u ninefingers -w youhavetoberealistic $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -O -N -R -G -S -k turn_client_pkey.pem -n 10 -m 10 -l 170 -e ::1 -x -g -u ninefingers -w youhavetoberealistic -s $@ 127.0.0.1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -O -N -R -G -t -n 50 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -O -N -R -G -T -n 30 -m 10 -l 170 -y -g -u gorst -w hero $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -O -N -R -G -T -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -y -g -u gorst -w hero $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -O -N -R -G -t -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -O -N -R -G -n 30 -m 10 -l 170 -g -u ninefingers -w youhavetoberealistic -y -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -O -N -R -G -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u ninefingers -w youhavetoberealistic -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -O -N -R -G -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -e ::1 -x -g -u ninefingers -w youhavetoberealistic -s -p 12345 $@ 127.0.0.1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -O -N -R -G -t -n 50 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -O -N -R -G -T -n 30 -m 10 -l 170 -y -g -u gorst -w hero -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -O -N -R -G -T -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -y -g -u gorst -w hero -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -O -N -R -G -t -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -O -N -R -G -n 30 -m 10 -l 170 -g -u ninefingers -w youhavetoberealistic -y -p 12346 $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -O -N -R -G -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u ninefingers -w youhavetoberealistic -p 12346 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -O -N -R -G -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -e ::1 -x -g -u ninefingers -w youhavetoberealistic -s -p 12346 $@ 127.0.0.1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -O -N -R -G -t -n 50 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero -p 12346 $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -O -N -R -G -T -n 30 -m 10 -l 170 -y -g -u gorst -w hero -p 12346 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -O -N -R -G -T -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -y -g -u gorst -w hero -p 12346 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -O -N -R -G -t -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero -p 12346 $@ ::1 & + +######################### + +sleep ${SLEEP_TIME} + +type killall >>/dev/null 2>>/dev/null +ER=$? +if [ ${ER} -eq 0 ] ; then + killall turnutils_uclient >>/dev/null 2>>/dev/null +fi + +type pkill >>/dev/null 2>>/dev/null +ER=$? +if [ ${ER} -eq 0 ] ; then + pkill turnutils_u >>/dev/null 2>>/dev/null + pkill turnutils_uclie >>/dev/null 2>>/dev/null + pkill turnutils_uclient >>/dev/null 2>>/dev/null +else + sleep 10 +fi + +done + + diff --git a/examples/scripts/selfloadbalance/secure_relay.sh b/examples/scripts/selfloadbalance/secure_relay.sh new file mode 100755 index 00000000..a537ada9 --- /dev/null +++ b/examples/scripts/selfloadbalance/secure_relay.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server +# with self-udp-balancing, in secure mode +# (when authentication is used) - see option -a +# that means "use long-term credential mechanism". +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# Other options: +# +# 1) --aux-server=... options start two auxiliary severs on IP address 127.0.0.1 +# and ports 12345 and 12346, and two auxiliary servers on IP adress ::1 +# with the same ports. +# 2) --self-udp-balance option forces the server to distribute the load from the +# main server points to the auxiliary servers through the ALTERNATE-SERVER +# mechanism. +# 3) set bandwidth limit on client session 3000000 bytes per second (--max-bps). +# 4) use fingerprints (-f) +# 5) use 10 relay threads (-m 10) +# 6) use min UDP relay port 32355 and max UDP relay port 65535 +# 7) "-r north.gov" means "use authentication realm north.gov" +# 8) "--user=ninefingers:youhavetoberealistic" means +# "allow user 'ninefinger' with password 'youhavetoberealistic' ". +# 9) "--user=gorst:hero" means "allow user 'gorst' with password 'hero' ". +# 10) "--cert=example_turn_server_cert.pem" sets the OpenSSL certificate file name. +# 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. +# 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 --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 $@ diff --git a/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh b/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh new file mode 100755 index 00000000..e7cfeb56 --- /dev/null +++ b/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh @@ -0,0 +1,37 @@ +#!/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 short-term credentials mechanism must be used with PostgreSQL or +# MySQL database only, the flat file userdb cannot be used. +# +# 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) --mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" +# means that local MySQL database "coturn" will be used, with database user "turn" and +# database user password "turn", and connection timeout 30 seconds. +# 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 --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 -E 127.0.0.1 -E ::1 --cipher-list=ALL:SSLv2 $@ diff --git a/examples/scripts/shorttermsecure/secure_tcp_client_c2c_tcp_relay_short_term.sh b/examples/scripts/shorttermsecure/secure_tcp_client_c2c_tcp_relay_short_term.sh new file mode 100755 index 00000000..a68a079b --- /dev/null +++ b/examples/scripts/shorttermsecure/secure_tcp_client_c2c_tcp_relay_short_term.sh @@ -0,0 +1,31 @@ +#!/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 + diff --git a/examples/scripts/shorttermsecure/secure_udp_client_short_term.sh b/examples/scripts/shorttermsecure/secure_udp_client_short_term.sh new file mode 100755 index 00000000..792b4828 --- /dev/null +++ b/examples/scripts/shorttermsecure/secure_udp_client_short_term.sh @@ -0,0 +1,30 @@ +#!/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 diff --git a/make-man.sh b/make-man.sh new file mode 100755 index 00000000..a36132cc --- /dev/null +++ b/make-man.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +rm -rf man/man1/* + +txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -B "TURN Server" README.turnserver | sed -e 's/-/\\-/g' > man/man1/turnserver.1 + +txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -B "TURN Server" README.turnadmin | sed -e 's/-/\\-/g'> man/man1/turnadmin.1 + +txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -B "TURN Server" README.turnutils | sed -e 's/-/\\-/g' > man/man1/turnutils.1 + +cd man/man1; ln -s turnutils.1 turnutils_uclient.1;cd ../.. +cd man/man1; ln -s turnutils.1 turnutils_peer.1;cd ../.. +cd man/man1; ln -s turnutils.1 turnutils_stunclient.1;cd ../.. +cd man/man1; ln -s turnserver.1 coturn.1;cd ../.. + diff --git a/man/man1/coturn.1 b/man/man1/coturn.1 new file mode 120000 index 00000000..9db33eda --- /dev/null +++ b/man/man1/coturn.1 @@ -0,0 +1 @@ +turnserver.1 \ No newline at end of file diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 new file mode 100644 index 00000000..7537c852 --- /dev/null +++ b/man/man1/turnadmin.1 @@ -0,0 +1,325 @@ +.\" Text automatically generated by txt2man +.TH TURN 1 "20 April 2014" "" "" +.SH GENERAL INFORMATION + +\fIturnadmin\fP is a TURN administration tool. This tool can be used to manage +the user accounts (add/remove users, generate +TURN keys for the users). For security reasons, we do not recommend +storing passwords openly. The better option is to use pre\-processed "keys" +which are then used for authentication. These keys are generated by \fIturnadmin\fP. +Turnadmin is a link to \fIturnserver\fP binary, but \fIturnadmin\fP performs different +functions. +.PP +Options note: \fIturnadmin\fP has long and short option names, for most options. +Some options have only long form, some options have only short form. Their syntax +somewhat different, if an argument is required: +.PP +The short form must be used as this (for example): +.PP +.nf +.fam C + $ turnadmin \-u \.\.\. + +.fam T +.fi +The long form equivalent must use the "=" character: +.PP +.nf +.fam C + $ turnadmin \-\-user= \.\.\. + +.fam T +.fi +If this is a flag option (no argument required) then their usage are the same, for example: +.PP +.nf +.fam C + $ turnadmin \-k \.\.\. + +.fam T +.fi +is equivalent to: +.PP +.nf +.fam C + $ turnadmin \-\-key \.\.\. + +.fam T +.fi +You have always the use the \fB\-r\fP option with commands for long term credentials \- +because data for multiple realms can be stored in the same database. +.PP +===================================== +.SS NAME +\fB +\fBturnadmin \fP\- a TURN relay administration tool. +\fB +.SS SYNOPSIS + +$ \fIturnadmin\fP [command] [options] +.PP +$ \fIturnadmin\fP [ \fB\-h\fP | \fB\-\-help\fP] +.SS DESCRIPTION + +.TP +.B +Commands: +.TP +.B +\fB\-k\fP, \fB\-\-key\fP +Generate key for a long\-term credentials mechanism user. +.TP +.B +\fB\-a\fP, \fB\-\-add\fP +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. +.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. +.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. +.PP +\fB\-s\fP, \fB\-\-set\-secret\fP= Add shared secret for TURN RESP API +.TP +.B +\fB\-S\fP, \fB\-\-show\-secret\fP +Show stored shared secrets for TURN REST API +.PP +\fB\-X\fP, \fB\-\-delete\-secret\fP= Delete a shared secret. +.RS +.TP +.B +\fB\-\-delete\-all_secrets\fP +Delete all shared secrets for REST API. +.RE +.TP +.B +\fB\-O\fP, \fB\-\-add\-origin\fP +Add origin\-to\-realm relation. +.TP +.B +\fB\-R\fP, \fB\-\-del\-origin\fP +Delete origin\-to\-realm relation. +.TP +.B +\fB\-I\fP, \fB\-\-list\-origins\fP +List origin\-to\-realm relations. +.TP +.B +\fB\-g\fP, \fB\-\-set\-realm\-option\fP +Set realm params: max\-bps, total\-quota, user\-quota. +.TP +.B +\fB\-G\fP, \fB\-\-list\-realm\-options\fP +List realm params. +.PP +NOTE: if you are using the flat file for the user database, then you will have +to use a text editor to set or show the shared secrets. +.PP +NOTE: the origin functionality is not supported with flat user db file, +a "real" database must be used. +.TP +.B +Options with required values: +.TP +.B +\fB\-b\fP, \fB\-\-userdb\fP +File\-based user database file name (default \- turnuserdb.conf). +See the \fB\-\-userdb\fP option in the \fIturnserver\fP section. +.TP +.B +\fB\-e\fP, \fB\-\-psql\-userdb\fP +PostgreSQL user database connection string. +See the \fB\-\-psql\-userdb\fP option in the \fIturnserver\fP section. +.TP +.B +\fB\-M\fP, \fB\-\-mysql\-userdb\fP +MySQL user database connection string. +See the \fB\-\-mysql\-userdb\fP option in the \fIturnserver\fP section. +.TP +.B +\fB\-N\fP, \fB\-\-redis\-userdb\fP +Redis user database connection string. +See the \fB\-\-redis\-userdb\fP option in the \fIturnserver\fP section. +.TP +.B +\fB\-u\fP, \fB\-\-user\fP +User name. +.TP +.B +\fB\-r\fP, \fB\-\-realm\fP +Realm, for long\-term credentials mechanism only. +.TP +.B +\fB\-p\fP, \fB\-\-password\fP +Password. +.TP +.B +\fB\-o\fP, \fB\-\-origin\fP +Origin +.TP +.B +\fB\-H\fP, \fB\-\-sha256\fP +Use SHA256 as the keys hash function (a non\-standard feature). +By default, MD5 is used for the key storage encryption +(as required by the current STUN/TURNstandards). +.TP +.B +\fB\-\-max\-bps\fP +Set value of realm's max\-bps parameter. +.TP +.B +\fB\-\-total\-quota\fP +Set value of realm's total\-quota parameter. +.TP +.B +\fB\-\-user\-quota\fP +Set value of realm's user\-quota parameter. +.TP +.B +\fB\-h\fP, \fB\-\-help\fP +Help. +.TP +.B +Generate a key: +.PP +$ \fIturnadmin\fP \fB\-k\fP \fB\-u\fP \fB\-r\fP \fB\-p\fP +.PP +Add/update a user in the userdb file or in the database: +.PP +$ \fIturnadmin\fP \fB\-a\fP [\fB\-b\fP | \fB\-e\fP | \fB\-M\fP | \fB\-N\fP ] \fB\-u\fP \fB\-r\fP \fB\-p\fP +.PP +Delete a user from the userdb file or from the database: +.PP +$ \fIturnadmin\fP \fB\-d\fP [\fB\-b\fP | \fB\-e\fP | \fB\-M\fP | \fB\-N\fP ] \fB\-u\fP \fB\-r\fP +.PP +List all long\-term users in MySQL database: +.PP +$ \fIturnadmin\fP \fB\-l\fP \fB\-\-mysql\-userdb\fP="" \fB\-r\fP +.PP +List all short\-term users in Redis database: +.PP +$ \fIturnadmin\fP \fB\-L\fP \fB\-\-redis\-userdb\fP="" +.PP +Set secret in MySQL database: +.PP +$ \fIturnadmin\fP \fB\-s\fP \fB\-\-mysql\-userdb\fP="" \fB\-r\fP +.PP +Show secret stored in PostgreSQL database: +.PP +$ \fIturnadmin\fP \fB\-S\fP \fB\-\-psql\-userdb\fP="" \fB\-r\fP +.PP +Set origin\-to\-realm relation in MySQL database: +.PP +$ \fIturnadmin\fP \fB\-\-mysql\-userdb\fP="" \fB\-r\fP \fB\-o\fP +.PP +Delete origin\-to\-realm relation from Redis DB: +.PP +$ \fIturnadmin\fP \fB\-\-redis\-userdb\fP="" \fB\-o\fP +.PP +List all origin\-to\-realm relations in Redis DB: +.PP +$ \fIturnadmin\fP \fB\-\-redis\-userdb\fP="" \fB\-I\fP +.PP +List the origin\-to\-realm relations in PostgreSQL DB for a single realm: +.PP +$ \fIturnadmin\fP \fB\-\-psql\-userdb\fP="" \fB\-I\fP \fB\-r\fP +.TP +.B +Help: +.PP +$ \fIturnadmin\fP \fB\-h\fP +.PP +======================================= +.SS DOCS + +After installation, run the command: +.PP +$ man \fIturnadmin\fP +.PP +or in the project root directory: +.PP +$ man \fB\-M\fP man \fIturnadmin\fP +.PP +to see the man page. +.PP +===================================== +.SS FILES + +/etc/turnserver.conf +.PP +/etc/turnuserdb.conf +.PP +/usr/local/etc/turnserver.conf +.PP +/usr/local/etc/turnuserdb.conf +.PP +===================================== +.SS DIRECTORIES + +/usr/local/share/\fIturnserver\fP +.PP +/usr/local/share/doc/\fIturnserver\fP +.PP +/usr/local/share/examples/\fIturnserver\fP +.PP +====================================== +.SS SEE ALSO + +\fIturnserver\fP, \fIturnutils\fP +.RE +.PP +====================================== +.SS WEB RESOURCES + +project page: +.PP +http://code.google.com/p/coturn/ +.PP +Wiki page: +.PP +http://code.google.com/p/coturn/wiki/Readme +.PP +forum: +.PP +https://groups.google.com/forum/?fromgroups=#!forum/turn\-server\-project\-rfc5766\-turn\-server/ +.RE +.PP +====================================== +.SS AUTHORS + +Oleg Moskalenko +.PP +Gabor Kovesdan http://kovesdan.org/ +.PP +Daniel Pocock http://danielpocock.com/ +.PP +John Selbie (jselbie@gmail.com) +.PP +Lee Sylvester +.PP +Erik Johnston +.PP +Roman Lisagor +.PP +Vladimir Tsanev +.PP +Po\-sheng Lin +.PP +Peter Dunkley +.PP +Mutsutoshi Yoshimoto diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 new file mode 100644 index 00000000..ac25cd56 --- /dev/null +++ b/man/man1/turnserver.1 @@ -0,0 +1,1121 @@ +.\" Text automatically generated by txt2man +.TH TURN 1 "20 April 2014" "" "" +.SH GENERAL INFORMATION + +The \fBTURN Server\fP project contains the source code of a TURN server and TURN client +messaging library. Also, some extra programs provided, for testing\-only +purposes. +.PP +See the INSTALL file for the building instructions. +.PP +After the build, you will have the following binary images: +.TP +.B +1. +\fIturnserver\fP: \fBTURN Server\fP relay. +The compiled binary image of the \fBTURN Server\fP program is located in bin/ sub\-directory. +.TP +.B +2. +\fIturnadmin\fP: TURN administration tool. See README.turnadmin and \fIturnadmin\fP man page. +.TP +.B +3. +turnutils_uclient. See README.turnutils and \fIturnutils\fP man page. +.TP +.B +4. +turnutils_peer. See README.turnutils and \fIturnutils\fP man page. +.TP +.B +5. +turnutils_stunclient. See README.turnutils and \fIturnutils\fP man page. +.TP +.B +6. +turnutils_rfc5769check. See README.turnutils and \fIturnutils\fP man page. +.PP +In the "examples/scripts" sub\-directory, you will find the examples of command lines to be used +to run the programs. The scripts are meant to be run from examples/ sub\-directory, for example: +.PP +$ cd examples +$ ./scripts/secure_relay.sh +.SH RUNNING THE TURN SERVER + +Options note: \fIturnserver\fP has long and short option names, for most options. +Some options have only long form, some options have only short form. Their syntax +somewhat different, if an argument is required: +.PP +The short form must be used as this (for example): +.PP +.nf +.fam C + $ turnserver \-L 12.34.56.78 + +.fam T +.fi +The long form equivalent must use the "=" character: +.PP +.nf +.fam C + $ turnserver \-\-listening\-ip=12.34.56.78 + +.fam T +.fi +If this is a flag option (no argument required) then their usage are the same, for example: +.PP +.nf +.fam C + $ turnserver \-a + +.fam T +.fi +is equivalent to: +.PP +.nf +.fam C + $ turnserver \-\-lt\-cred\-mech + +.fam T +.fi +===================================== +.SS NAME +\fB +\fBturnserver \fP\- a TURN relay server implementation. +\fB +.SS SYNOPSIS +.nf +.fam C + +$ \fIturnserver\fP [\fB\-n\fP | \fB\-c\fP ] [\fIflags\fP] [ \fB\-\-userdb\fP= | \fB\-\-psql\-userdb\fP= | \fB\-\-mysql\-userdb\fP= | \fB\-\-redis\-userdb\fP= ] [\fB\-z\fP | \fB\-\-no\-auth\fP | \fB\-a\fP | \fB\-\-lt\-cred\-mech\fP ] [\fIoptions\fP] +$ \fIturnserver\fP \fB\-h\fP + +.fam T +.fi +.fam T +.fi +.SS DESCRIPTION + +.TP +.B +Config file settings: +.TP +.B +\fB\-n\fP +Do not use configuration file, use only command line parameters. +.TP +.B +\fB\-c\fP +Configuration file name (default \- turnserver.conf). +The format of config file can be seen in +the supplied examples/etc/turnserver.conf example file. Long +names of the \fIoptions\fP are used as the configuration +items names in the file. If not an absolute path is supplied, +then the file is searched in the following directories: +.RS +.IP \(bu 3 +current directory +.IP \(bu 3 +current directory etc/ sub\-directory +.IP \(bu 3 +upper directory level etc/ +.IP \(bu 3 +/etc/ +.IP \(bu 3 +/usr/local/etc/ +.IP \(bu 3 +installation directory /etc +.RE +.TP +.B +User database settings: +.TP +.B +\fB\-b\fP, \fB\-\-userdb\fP +User database file name (default \- turnuserdb.conf), +for long\-term credentials mechanism only. +This user file database is being dynamically checked while the \fIturnserver\fP +is working, and the user accounts can be changed dynamically by +editing the database. +.TP +.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 for secret\-based timed authentication in TURN RESP API. +The connection string format is like that: +.RS +.PP +"host= dbname= user= password= connect_timeout=" +(for 8.x or newer Postgres). +.PP +Or: +.PP +"postgresql://username:password@hostname:port/databasename" (for 9.x or newer Postgres). +See the INSTALL file for more explanations and examples. +.PP +Also, see http://www.PostgreSQL.org for full PostgreSQL documentation. +.RE +.TP +.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 secret\-based timed authentication in TURN RESP API. +The connection string format is like that: +.RS +.PP +"host= dbname= user= password= connect_timeout=" +See the INSTALL file for more explanations and examples. +.PP +Also, see http://www.mysql.org or http://mariadb.org +for full MySQL documentation. +.RE +.TP +.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 value for secret\-based timed authentication in TURN RESP API. +The connection string format is like that: +.RS +.PP +"ip= dbname= password= connect_timeout=" +See the INSTALL file for more explanations and examples. +.PP +Also, see http://redis.io for full Redis documentation. +.RE +.TP +.B +Flags: +.TP +.B +\fB\-v\fP, \fB\-\-verbose\fP +Moderate verbose mode. +.TP +.B +\fB\-V\fP, \fB\-\-Verbose\fP +Extra verbose mode, very annoying and not recommended. +.TP +.B +\fB\-o\fP, \fB\-\-daemon\fP +Run server as daemon. +.TP +.B +\fB\-f\fP, \fB\-\-fingerprint\fP +Use fingerprints in the TURN messages. If an incoming request +contains a fingerprint, then TURN server will always add +fingerprints to the messages in this session, regardless of the +per\-server setting. +.TP +.B +\fB\-a\fP, \fB\-\-lt\-cred\-mech\fP +Use long\-term credentials mechanism (this one you need for WebRTC usage). +This option can be used with either flat file user database or +PostgreSQL DB or MySQL DB or Redis for user keys storage. +.TP +.B +\fB\-A\fP, \fB\-\-st\-cred\-mech\fP +Use the short\-term credentials mechanism. This option requires +a PostgreSQL or MySQL or Redis DB for short term passwords storage. +.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 +authentication\-related \fIoptions\fP are set. +By default, no credential mechanism is used \- +any user is allowed. +.TP +.B +\fB\-\-use\-auth\-secret\fP +TURN REST API flag. +Flag that sets a special WebRTC authorization option +that is based upon authentication secret. The feature purpose +is to support "\fBTURN Server\fP REST API" as described in +the TURN REST API section below. +This option uses timestamp as part of combined username: +usercombo \-> "timestamp:username", +turn user \-> usercombo, +turn password \-> \fBbase64\fP(hmac(secret key, usercombo)). +This allows TURN credentials to be accounted for a specific user id. +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\-\-dh566\fP +Use 566 bits predefined DH TLS key. Default size of the key is 1066. +.TP +.B +\fB\-\-dh2066\fP +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 +.B +\fB\-\-no\-tlsv1\fP +Do not allow TLSv1 protocol. +.TP +.B +\fB\-\-no\-tlsv1_1\fP +Do not allow TLSv1.1 protocol. +.TP +.B +\fB\-\-no\-tlsv1_2\fP +Do not allow TLSv1.2 protocol. +.TP +.B +\fB\-\-no\-udp\fP +Do not start UDP client listeners. +.TP +.B +\fB\-\-no\-tcp\fP +Do not start TCP client listeners. +.TP +.B +\fB\-\-no\-tls\fP +Do not start TLS client listeners. +.TP +.B +\fB\-\-no\-dtls\fP +Do not start DTLS client listeners. +.TP +.B +\fB\-\-no\-udp\-relay\fP +Do not allow UDP relay endpoints defined in RFC 5766, +use only TCP relay endpoints as defined in RFC 6062. +.TP +.B +\fB\-\-no\-tcp\-relay\fP +Do not allow TCP relay endpoints defined in RFC 6062, +use only UDP relay endpoints as defined in RFC 5766. +.TP +.B +\fB\-\-stale\-nonce\fP +Use extra security with nonce value having limited lifetime (600 secs). +.TP +.B +\fB\-\-no\-stdout\-log\fP +Flag to prevent stdout log messages. +By default, all log messages are going to both stdout and to +the configured log file. With this option everything will be going to +the log file only (unless the log file itself is stdout). +.TP +.B +\fB\-\-syslog\fP +With this flag, all log will be redirected to the system log (syslog). +.TP +.B +\fB\-\-simple\-log\fP +This flag means that no log file rollover will be used, and the log file +name will be constructed as\-is, without PID and date appendage. +.TP +.B +\fB\-\-secure\-stun\fP +Require authentication of the STUN Binding request. +By default, the clients are allowed anonymous access to the STUN Binding functionality. +.TP +.B +\fB\-S\fP, \fB\-\-stun\-only\fP +Run as STUN server only, all TURN requests will be ignored. +Option to suppress TURN functionality, only STUN requests will be processed. +.TP +.B +\fB\-\-no\-stun\fP +Run as TURN server only, all STUN requests will be ignored. +Option to suppress STUN functionality, only TURN requests will be processed. +.TP +.B +\fB\-\-no\-loopback\-peers\fP +Disallow peers on the loopback addresses (127.x.x.x and ::1). +.TP +.B +\fB\-\-no\-multicast\-peers\fP +Disallow peers on well\-known broadcast addresses +(224.0.0.0 and above, and FFXX:*). +.TP +.B +\fB\-\-sha256\fP +Require SHA256 digest function to be used for the message integrity. +By default, the server uses SHA1 hashes. With this option, the server +requires the stronger SHA256 hashes. The client application must support +SHA256 hash function if this option is used. If the server obtains a message +from the client with a weaker (SHA1) hash function then the server returns +error code 426. +.TP +.B +\fB\-\-mobility\fP +Mobility with ICE (MICE) specs support. +.TP +.B +\fB\-\-no\-cli\fP +Turn OFF the CLI support. By default it is always ON. +See also \fIoptions\fP \fB\-\-cli\-ip\fP and \fB\-\-cli\-port\fP. +.TP +.B +\fB\-\-server\-relay\fP +Server relay. NON\-STANDARD AND DANGEROUS OPTION. +Only for those applications when we want to run +server applications on the relay endpoints. +This option eliminates the IP permissions check +on the packets incoming to the relay endpoints. +See http://tools.ietf.org/search/rfc5766#section\-17.2.3 . +.TP +.B +\fB\-\-udp\-self\-balance\fP +(recommended for older Linuxes only) +Automatically balance UDP traffic over auxiliary servers +(if configured). The load balancing is using the +ALTERNATE\-SERVER mechanism. The TURN client must support +300 ALTERNATE\-SERVER response for this functionality. +.TP +.B +\fB\-h\fP +Help. +.TP +.B +Options with required values: +.TP +.B +\fB\-d\fP, \fB\-\-listening\-device\fP +Listener interface device. +(NOT RECOMMENDED. Optional functionality, Linux only). +The \fIturnserver\fP process must have root privileges to bind the +listening endpoint to a device. If \fIturnserver\fP must run as a +process without root privileges, then just do not use this setting. +.TP +.B +\fB\-L\fP, \fB\-\-listening\-ip\fP +Listener IP address of relay server. +Multiple listeners can be specified, for example: +\fB\-L\fP ip1 \fB\-L\fP ip2 \fB\-L\fP ip3 +If no \fBIP\fP(s) specified, then all IPv4 and +IPv6 system IPs will be used for listening. +The same \fBip\fP(s) can be used as both listening and relay \fBip\fP(s). +.TP +.B +\fB\-p\fP, \fB\-\-listening\-port\fP +TURN listener port for UDP and TCP listeners (Default: 3478). +Note: actually, TLS & DTLS sessions can connect to the "plain" TCP & UDP +\fBport\fP(s), too \- if allowed by configuration. +.TP +.B +\fB\-\-tls\-listening\-port\fP +TURN listener port for TLS and DTLS listeners (Default: 5349). +Note: actually, "plain" TCP & UDP sessions can connect to the TLS & DTLS +\fBport\fP(s), too \- if allowed by configuration. The TURN server +"automatically" recognizes the type of traffic. Actually, two listening +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. +For secure UDP connections, we support DTLS version 1. +.TP +.B +\fB\-\-alt\-listening\-port\fP +Alternative listening port for UDP and TCP listeners; +default (or zero) value means "listening port plus one". +This is needed for STUN CHANGE_REQUEST \- in RFC 5780 sense +or in old RFC 3489 sense \- for NAT behavior discovery). The \fBTURN Server\fP +supports CHANGE_REQUEST only if it is started with more than one +listening IP address of the same family (IPv4 or IPv6). The CHANGE_REQUEST +is only supported by UDP protocol, other protocols are listening +on that endpoint only for "symmetry". +.TP +.B +\fB\-\-alt\-tls\-listening\-port\fP +Alternative listening port for TLS and DTLS protocols. +Default (or zero) value means "TLS listening port plus one". +.TP +.B +\fB\-\-aux\-server\fP +Auxiliary STUN/TURN server listening endpoint. +Aux servers have almost full TURN and STUN functionality. +The (minor) limitations are: +.RS +.IP 1) 4 +Auxiliary servers do not have alternative ports and +they do not support STUN RFC 5780 functionality (CHANGE REQUEST). +.IP 2) 4 +Auxiliary servers also are never returning ALTERNATIVE\-SERVER reply. +.RE +.PP +Valid formats are 1.2.3.4:5555 for IPv4 and [1:2::3:4]:5555 for IPv6. +There may be multiple aux\-server \fIoptions\fP, each will be used for listening +to client requests. +.TP +.B +\fB\-i\fP, \fB\-\-relay\-device\fP +Relay interface device for relay sockets +(NOT RECOMMENDED. Optional, Linux only). +.TP +.B +\fB\-E\fP, \fB\-\-relay\-ip\fP +Relay address (the local IP address that +will be used to relay the packets to the +peer). Multiple relay addresses may be used: +\fB\-E\fP ip1 \fB\-E\fP ip2 \fB\-E\fP ip3 +The same \fBIP\fP(s) can be used as both listening \fBIP\fP(s) and relay \fBIP\fP(s). +If no relay \fBIP\fP(s) specified, then the \fIturnserver\fP will apply the +default policy: it will decide itself which relay addresses to be +used, and it will always be using the client socket IP address as +the relay IP address of the TURN session (if the requested relay +address family is the same as the family of the client socket). +.TP +.B +\fB\-X\fP, \fB\-\-external\-ip\fP +\fBTURN Server\fP public/private address mapping, if the server is behind NAT. +In that situation, if a \fB\-X\fP is used in form "\fB\-X\fP " then that ip will be reported +as relay IP address of all allocations. This scenario works only in a simple case +when one single relay address is be used, and no CHANGE_REQUEST functionality is +required. That single relay address must be mapped by NAT to the 'external' IP. +The "external\-ip" value, if not empty, is returned in XOR\-RELAYED\-ADDRESS field. +For that 'external' IP, NAT must forward ports directly (relayed port 12345 +must be always mapped to the same 'external' port 12345). +In more complex case when more than one IP address is involved, +that option must be used several times, each entry must +have form "\fB\-X\fP ", to map all involved addresses. +CHANGE_REQUEST (RFC5780 or RFC3489) NAT discovery STUN functionality will work +correctly, if the addresses are mapped properly, even when the TURN server itself +is behind A NAT. +By default, this value is empty, and no address mapping is used. +.TP +.B +\fB\-m\fP, \fB\-\-relay\-threads\fP +Number of relay threads to handle the established connections +(in addition to authentication thread and the listener thread). +If set to 0 then application runs relay process in a single thread, +in the same thread with the listener process (the authentication thread will +still be a separate thread). In older systems (before Linux kernel 3.9), +the number of UDP threads is always one threads per network listening endpoint \- +unless "\fB\-m\fP 0" or "\fB\-m\fP 1" is set. +.TP +.B +\fB\-\-min\-port\fP +Lower bound of the UDP port range for relay +endpoints allocation. +Default value is 49152, according to RFC 5766. +.TP +.B +\fB\-\-max\-port\fP +Upper bound of the UDP port range for relay +endpoints allocation. +Default value is 65535, according to RFC 5766. +.TP +.B +\fB\-u\fP, \fB\-\-user\fP +Long\-term security mechanism credentials user account, +in the column\-separated form username:key. +Multiple user accounts may used in the command line. +The key is either the user password, or +the key is generated +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. +.TP +.B +\fB\-r\fP, \fB\-\-realm\fP +The default realm to be used for the users when no explicit +origin/realm relationship was found in the database, or if the TURN +server is not using any database (just the commands\-line settings +and the userdb file). Must be used with long\-term credentials +mechanism or with TURN REST API. +.TP +.B +\fB\-C\fP, \fB\-\-rest\-api\-separator\fP +This is the timestamp/username separator symbol (character) in TURN REST API. +The default value is :. +.TP +.B +\fB\-q\fP, \fB\-\-user\-quota\fP +Per\-user allocations quota: how many concurrent +allocations a user can create. This option can also be set +through the database, for a particular realm. +.TP +.B +\fB\-Q\fP, \fB\-\-total\-quota\fP +Total allocations quota: global limit on concurrent allocations. +This option can also be set through the database, for a particular realm. +.TP +.B +\fB\-s\fP, \fB\-\-max\-bps\fP +Max bytes\-per\-second bandwidth a TURN session is allowed to handle +(input and output network streams are treated separately). Anything above +that limit will be dropped or temporary suppressed (within the +available buffer limits). This option can also be set through the +database, for a particular realm. +.TP +.B +\fB\-\-static\-auth\-secret\fP +Static authentication secret value (a string) for TURN REST API only. +If not set, then the turn server will try to use the dynamic value +in turn_secret table in user database (if present). The database\-stored +value can be changed on\-the\-fly by a separate program, so this is why +that other mode is dynamic. Multiple shared secrets can be used +(both in the database and in the "static" fashion). +.TP +.B +\fB\-\-cert\fP +Certificate file, PEM format. Same file +search rules applied as for the configuration +file. If both \fB\-\-no\-tls\fP and \fB\-\-no\-dtls\fP \fIoptions\fP +are specified, then this parameter is not needed. +Default value is turn_server_cert.pem. +.TP +.B +\fB\-\-pkey\fP +Private key file, PEM format. Same file +search rules applied as for the configuration +file. If both \fB\-\-no\-tls\fP and \fB\-\-no\-dtls\fP \fIoptions\fP +are specified, then this parameter is not needed. +Default value is turn_server_pkey.pem. +.TP +.B +\fB\-\-pkey\-pwd\fP +If the private key file is encrypted, then this password to be used. +.TP +.B +\fB\-\-cipher\-list\fP +Allowed OpenSSL cipher list for TLS/DTLS connections. +Default value is "DEFAULT". +.TP +.B +\fB\-\-CA\-file\fP +CA file in OpenSSL format. +Forces TURN server to verify the client SSL certificates. +By default, no CA is set and no client certificate check is performed. +.TP +.B +\fB\-\-ec\-curve\-name\fP +Curve name for EC ciphers, if supported by OpenSSL library (TLS and DTLS). +The default value is prime256v1. +.TP +.B +\fB\-\-dh\-file\fP +Use custom DH TLS key, stored in PEM format in the file. +Flags \fB\-\-dh566\fP and \fB\-\-dh2066\fP are ignored when the DH key is taken from a file. +.TP +.B +\fB\-l\fP, \fB\-\-log\-file\fP +Option to set the full path name of the log file. +By default, the \fIturnserver\fP tries to open a log file in +/var/log/\fIturnserver\fP, /var/log, /var/tmp, /tmp and . (current) +directories (which file open operation succeeds +first that file will be used). With this option you can set the +definite log file name. +The special names are "stdout" and "\-" \- they will force everything +to the stdout. Also, "syslog" name will redirect everything into +the system log (syslog), as if the option "\fB\-\-syslog\fP" was set. +.TP +.B +\fB\-\-alternate\-server\fP +Option to set the "redirection" mode. The value of this option +will be the address of the alternate server for UDP & TCP service in form of +[:]. The server will send this value in the attribute +ALTERNATE\-SERVER, with error 300, on ALLOCATE request, to the client. +Client will receive only values with the same address family +as the client network endpoint address family. +See RFC 5389 and RFC 5766 for ALTERNATE\-SERVER functionality description. +The client must use the obtained value for subsequent TURN communications. +If more than one \fB\-\-alternate\-server\fP \fIoptions\fP are provided, then the functionality +can be more accurately described as "load\-balancing" than a mere "redirection". +If the port number is omitted, then the default port +number 3478 for the UDP/TCP protocols will be used. +Colon (:) characters in IPv6 addresses may conflict with the syntax of +the option. To alleviate this conflict, literal IPv6 addresses are enclosed +in square brackets in such resource identifiers, for example: +[2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478 . +Multiple alternate servers can be set. They will be used in the +round\-robin manner. All servers in the pool are considered of equal weight and +the load will be distributed equally. For example, if we have 4 alternate servers, +then each server will receive 25% of ALLOCATE requests. An alternate TURN server +address can be used more than one time with the alternate\-server option, so this +can emulate "weighting" of the servers. +.TP +.B +\fB\-\-tls\-alternate\-server\fP +Option to set alternative server for TLS & DTLS services in form of +:. If the port number is omitted, then the default port +number 5349 for the TLS/DTLS protocols will be used. See the previous option for the +functionality description. +.TP +.B +\fB\-O\fP, \fB\-\-redis\-statsdb\fP +Redis status and statistics database connection string, if used (default \- empty, +no Redis stats DB used). This database keeps allocations status information, and it can +be also used for publishing and delivering traffic and allocation event notifications. +This database option can be used independently of \fB\-\-redis\-userdb\fP option, +and actually Redis can be used for status/statistics and MySQL or PostgreSQL can +be used for the user database. +The connection string has the same parameters as redis\-userdb connection string. +.TP +.B +\fB\-\-max\-allocate\-timeout\fP +Max time, in seconds, allowed for full allocation establishment. +Default is 60 seconds. +.PP +\fB\-\-denied\-peer\-ip\fP= +.PP +\fB\-\-allowed\-peer\-ip\fP= Options to ban or allow specific ip addresses or ranges +of ip addresses. If an ip address is specified as both allowed and denied, then +the ip address is considered to be allowed. This is useful when you wish to ban +a range of ip addresses, except for a few specific ips within that range. +This can be used when you do not want users of the turn server to be able to access +machines reachable by the turn server, but would otherwise be unreachable from the +internet (e.g. when the turn server is sitting behind a NAT). The 'white" and "black" peer +IP ranges can also be dynamically changed in the database. +The allowed/denied addresses (white/black lists) rules are very simple: +.RS +.IP 1) 4 +If there is no rule for an address, then it is allowed; +.IP 2) 4 +If there is an "allowed" rule that fits the address then it is allowed \- no matter what; +.IP 3) 4 +If there is no "allowed" rule that fits the address, and if there is a "denied" rule that +fits the address, then it is denied. +.RE +.TP +.B +\fB\-\-pidfile\fP +File name to store the pid of the process. +Default is /var/run/turnserver.pid (if superuser account is used) or +/var/tmp/turnserver.pid . +.TP +.B +\fB\-\-proc\-user\fP +User name to run the process. After the initialization, the \fIturnserver\fP process +will make an attempt to change the current user ID to that user. +.TP +.B +\fB\-\-proc\-group\fP +Group name to run the process. After the initialization, the \fIturnserver\fP process +will make an attempt to change the current group ID to that group. +.TP +.B +\fB\-\-cli\-ip\fP +Local system IP address to be used for CLI management interface. +The \fIturnserver\fP process can be accessed for management with telnet, +at this IP address and on the CLI port (see the next parameter). +Default value is 127.0.0.1. You can use telnet or putty (in telnet mode) +to access the CLI management interface. +.TP +.B +\fB\-\-cli\-port\fP +CLI management interface listening port. Default is 5766. +.TP +.B +\fB\-\-cli\-password\fP +CLI access password. Default is empty (no password). +.TP +.B +\fB\-\-cli\-max\-output\-sessions\fP +Maximum number of output sessions in ps CLI command. +This value can be changed on\-the\-fly in CLI. The default value is 256. +.TP +.B +\fB\-\-ne\fP=[1|2|3] +Set network engine type for the process (for internal purposes). +.PP +================================== +.SH LOAD BALANCE AND PERFORMANCE TUNING + +This topic is covered in the wiki page: +.PP +http://code.google.com/p/coturn/wiki/turn_performance_and_load_balance +.PP +=================================== +.SH WEBRTC USAGE + +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 +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 +.nf +.fam C + a) command\-line options (\-u). + + b) userdb config file. + + c) a database table (PostgreSQL or MySQL). You will have to set keys with + turnadmin utility (see docs and wiki for turnadmin). You cannot use open passwords + in the database. + + d) Redis key/value pair(s), if Redis is used. You key use either keys or + open passwords with Redis; see turndb/testredisdbsetup.sh file. + + e) You also can use the TURN REST API. You will need shared secret(s) set + either through the command line option, or through the config file, or through + the database table or Redis key/value pairs. + +.fam T +.fi +.IP 2) 4 +Usually WebRTC uses fingerprinting (\fB\-f\fP). +.IP 3) 4 +\fB\-v\fP option may be nice to see the connected clients. +.IP 4) 4 +\fB\-X\fP is needed if you are running your TURN server behind a NAT. +.IP 5) 4 +\fB\-\-min\-port\fP and \fB\-\-max\-port\fP may be needed if you want to limit the relay endpoints ports +number range. +.PP +=================================== +.SH TURN REST API + +In WebRTC, the browser obtains the TURN connection information from the web +server. This information is a secure information \- because it contains the +necessary TURN credentials. As these credentials are transmitted over the +public networks, we have a potential security breach. +.PP +If we have to transmit a valuable information over the public network, +then this information has to have a limited lifetime. Then the guy who +obtains this information without permission will be able to perform +only limited damage. +.PP +This is how the idea of TURN REST API \- time\-limited TURN credentials \- +appeared. This security mechanism is based upon the long\-term credentials +mechanism. The main idea of the REST API is that the web server provides +the credentials to the client, but those credentials can be used only +limited time by an application that has to create a TURN server connection. +.PP +The "classic" long\-term credentials mechanism (LTCM) is described here: +.PP +http://tools.ietf.org/html/rfc5389#section\-10.2 +http://tools.ietf.org/html/rfc5389#section\-15.4 +.PP +For authentication, each user must know two things: the username and the +password. Optionally, the user must supply the ORIGIN value, so that the +server can figure out the realm to be used for the user. The nonce and +the realm values are supplied by the TURN server. But LTCM is not saying +anything about the nature and about the persistence +of the username and of the password; and this is used by the REST API. +.PP +In the TURN REST API, there is no persistent passwords for users. A user has +just the username. The password is always temporary, and it is generated by +the web server on\-demand, when the user accesses the WebRTC page. And, +actually, a temporary one\-time session only, username is provided to the user, +too. +.PP +The temporary user is generated as: +.PP +temporary\-username="timestamp" + ":" + "username" +.PP +where username is the persistent user name, and the timestamp format is just +seconds sinse 1970 \- the same value as \fBtime\fP(NULL) function returns. +.PP +The temporary password is obtained as HMAC\-SHA1 function over the temporary +username, with shared secret as the HMAC key, and then the result is encoded: +.PP +temporary\-password = \fBbase64_encode\fP(hmac\-sha1(shared\-secret, temporary\-username)) +.PP +Both the TURN server and the web server know the same shared secret. How the +shared secret is distributed among the involved entities is left to the WebRTC +deployment details \- this is beyond the scope of the TURN REST API. +.PP +So, a timestamp is used for the temporary password calculation, and this +timestamp can be retrieved from the temporary username. This information +is valuable, but only temporary, while the timestamp is not expired. Without +knowledge of the shared secret, a new temporary password cannot be generated. +.PP +This is all formally described in Justin's Uberti TURN REST API document +that can be obtained following the link "TURN REST API" in the \fBTURN Server\fP +project's page http://code.google.com/p/coturn/. +.PP +Once the temporary username and password are obtained by the client (browser) +application, then the rest is just 'classic" long\-term credentials mechanism. +For developers, we are going to describe it step\-by\-step below: +.RS +.IP \(bu 3 +a new TURN client sends a request command to the TURN server. +.IP \(bu 3 +TURN server sees that this is a new client and the message is not +authenticated. +.IP \(bu 3 +the TURN server generates a random nonce string, and return the +error 401 to the client, with nonce and realm included. +.IP \(bu 3 +the client sees the 401 error and it extracts two values from +the error response: the nonce and the realm. +.IP \(bu 3 +the client uses username, realm and password to produce a key: +.PP +.nf +.fam C + key = MD5(username ":" realm ":" SASLprep(password)) +.fam T +.fi +(SASLprep is described here: http://tools.ietf.org/html/rfc4013) +.IP \(bu 3 +the client forms a new request, adds username, realm and nonce to the +request. Then, the client calculates and adds the integrity field to +the request. This is the trickiest part of the process, and it is +described in the end of section 15.4: +http://tools.ietf.org/html/rfc5389#section\-15.4 +.IP \(bu 3 +the client, optionally, adds the fingerprint field. This may be also +a tricky procedure, described in section 15.5 of the same document. +WebRTC usually uses fingerprinted TURN messages. +.IP \(bu 3 +the TURN server receives the request, reads the username. +.IP \(bu 3 +then the TURN server checks that the nonce and the realm in the request +are the valid ones. +.IP \(bu 3 +then the TURN server calculates the key. +.IP \(bu 3 +then the TURN server calculates the integrity field. +.IP \(bu 3 +then the TURN server compares the calculated integrity field with the +received one \- they must be the same. If the integrity fields differ, +then the request is rejected. +.RE +.PP +In subsequent communications, the client may go with exactly the same +sequence, but for optimization usually the client, having already +information about realm and nonce, pre\-calculates the integrity string +for each request, so that the 401 error response becomes unnecessary. +The TURN server may use "\fB\-\-stale\-nonce\fP" option for extra security: in +some time, the nonce expires and the client will obtain 438 error response +with the new nonce, and the client will have to start using the new nonce. +.PP +In subsequent communications, the sever and the client will always assume +the same password \- the original password becomes the session parameter and +is never expiring. So the password is not changing while the session is valid +and unexpired. So, if the session is properly maintained, it may go forever, +even if the user password has been already changed (in the database). The +session simply is using the old password. Once the session got disconnected, +the client will have to use the new password to re\-connect (if the password +has been changed). +.PP +An example when a new shared secret is generated every hour by the TURN server +box and then supplied to the web server, remotely, is provided in the script +examples/scripts/restapi/shared_secret_maintainer.pl . +.PP +A very important thing is that the nonce must be totally random and it must be +different for different clients and different sessions. +.PP +=================================== +.SH DATABASES + +For the user database, the \fIturnserver\fP has the following \fIoptions\fP: +.IP 1) 4 +Users can be set in the command line, with multiple \fB\-u\fP or \fB\-\-user\fP \fIoptions\fP. +Obviously, only a few users can be set that way, and their credentials are fixed +for the \fIturnserver\fP process lifetime. +.IP 2) 4 +Users can be set in turnusers.conf flat file DB. The \fIturnserver\fP process periodically +re\-reads this file, so the user accounts may be changed while the \fIturnserver\fP is running. +But still a relatively small (up to a hundred ?) number of users can be handled that way. +.IP 3) 4 +Users can be stored in PostgreSQL database, if the \fIturnserver\fP was compiled with PostgreSQL +support. Each time \fIturnserver\fP checks user credentials, it reads the database (asynchronously, +of course, so that the current flow of packets is not delayed in any way), so any change in the +database content is immediately visible by the \fIturnserver\fP. This is the way if you need the +best scalability. The schema for the database can be found in schema.sql file. +For long\-term credentials, you have to set the "keys" for the users; the "keys" are generated +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. +.IP 4) 4 +The same is true for MySQL database. The same schema file is applicable. +The same considerations are applicable. +.IP 5) 4 +The same is true for the Redis database, but the Redis database has aa different schema \- +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. +.IP 6) 4 +Of course, the \fIturnserver\fP can be used in non\-secure mode, when users are allowed to establish +sessions anonymously. But in most cases (like WebRTC) that will not work. +.PP +For the status and statistics database, there are two choices: +.IP 1) 4 +The simplest choice is not to use it. Do not set \fB\-\-redis\-statsdb\fP option, and this functionality +will be simply ignored. +.IP 2) 4 +If you choose to use it, then set the \fB\-\-redis\-statsdb\fP option. This may be the same database +as in \fB\-\-redis\-userdb\fP option, or it may be a different database. You may want to use different +database for security or convenience reasons. Also, you can use different database management +systems for the user database and for the ststus and statistics database. For example, you can use +MySQL as the user database, and you can use redis for the statistics. Or you can use Redis for both. +.PP +So, we have 6 choices for the user management, and 2 choices for the statistics management. These +two are totally independent. So, you have overall 6*2=12 ways to handle persistent information, +choose any for your convenience. +.PP +You do not have to handle the database information "manually" \- the \fIturnadmin\fP program can handle +everything for you. For PostgreSQL and MySQL you will just have to create an empty database +with schema.sql SQL script. With Redis, you do not have to do even that \- just run \fIturnadmin\fP and +it will set the users for you (see the \fIturnadmin\fP manuals). +.PP +================================= +.SH LIBRARIES + +In the lib/ sub\-directory the build process will create TURN client messaging library. +In the include/ sub\-directory, the necessary include files will be placed. +The C++ wrapper for the messaging functionality is located in TurnMsgLib.h header. +An example of C++ code can be found in stunclient.c file. +.PP +================================= +.SH DOCS + +After installation, run the command: +.PP +$ man \fIturnserver\fP +.PP +or in the project root directory: +.PP +$ man \fB\-M\fP man \fIturnserver\fP +.PP +to see the man page. +.PP +In the docs/html subdirectory of the original archive tree, you will find the client library +reference. After the installation, it will be placed in PREFIX/share/doc/\fIturnserver\fP/html. +.PP +================================= +.SH LOGS + +When the \fBTURN Server\fP starts, it makes efforts to create a log file turn_.log +in the following directories: +.RS +.IP \(bu 3 +/var/log +.IP \(bu 3 +/log/ +.IP \(bu 3 +/var/tmp +.IP \(bu 3 +/tmp +.IP \(bu 3 +current directory +.RE +.PP +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. +.PP +================================= +.SH TELNET CLI + +The \fIturnserver\fP process provides a telnet CLI access as statistics and basic management +interface. By default, the \fIturnserver\fP starts a telnet CLI listener on IP 127.0.0.1 and +port 5766. That can be changed by the command\-cline \fIoptions\fP of the \fIturnserver\fP process +(see \fB\-\-cli\-ip\fP and \fB\-\-cli\-port\fP \fIoptions\fP). The full list of telnet CLI commands is provided +in "help" command output in the telnet CLI. +.PP +================================= +.SH CLUSTERS + +\fBTURN Server\fP can be a part of the cluster installation. But, to support the "even port" functionality +(RTP/RTCP streams pairs) the client requests from a particular IP must be delivered to the same +\fBTURN Server\fP instance, so it requires some networking setup massaging for the cluster. The reason is that +the RTP and RTCP relaying endpoints must be allocated on the same relay IP. It would be possible +to design a scheme with the application\-level requests forwarding (and we may do that later) but +it would affect the performance. +.PP +================================= +.SH FILES + +/etc/turnserver.conf +.PP +/etc/turnuserdb.conf +.PP +/usr/local/etc/turnserver.conf +.PP +/usr/local/etc/turnuserdb.conf +.PP +================================= +.SH DIRECTORIES + +/usr/local/share/\fIturnserver\fP +.PP +/usr/local/share/doc/\fIturnserver\fP +.PP +/usr/local/share/examples/\fIturnserver\fP +.PP +================================= +.SH STANDARDS + +obsolete STUN RFC 3489 +.PP +new STUN RFC 5389 +.PP +TURN RFC 5766 +.PP +TURN\-TCP extension RFC 6062 +.PP +TURN IPv6 extension RFC 6156 +.PP +STUN/TURN test vectors RFC 5769 +.PP +STUN NAT behavior discovery RFC 5780 +.PP +================================= +.SH SEE ALSO + +\fIturnadmin\fP, \fIturnutils\fP +.RE +.PP +====================================== +.SS WEB RESOURCES + +project page: +.PP +http://code.google.com/p/coturn/ +.PP +Wiki page: +.PP +http://code.google.com/p/coturn/wiki/Readme +.PP +forum: +.PP +https://groups.google.com/forum/?fromgroups=#!forum/turn\-server\-project\-rfc5766\-turn\-server/ +.RE +.PP +====================================== +.SS AUTHORS + +Oleg Moskalenko +.PP +Gabor Kovesdan http://kovesdan.org/ +.PP +Daniel Pocock http://danielpocock.com/ +.PP +John Selbie (jselbie@gmail.com) +.PP +Lee Sylvester +.PP +Erik Johnston +.PP +Roman Lisagor +.PP +Vladimir Tsanev +.PP +Po\-sheng Lin +.PP +Peter Dunkley +.PP +Mutsutoshi Yoshimoto diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 new file mode 100644 index 00000000..1e2c93d9 --- /dev/null +++ b/man/man1/turnutils.1 @@ -0,0 +1,439 @@ +.\" Text automatically generated by txt2man +.TH TURN 1 "20 April 2014" "" "" +.SH GENERAL INFORMATION + +A set of turnutils_* programs provides some utility functionality to be used +for testing and for setting up the TURN server. +.TP +.B +1. +\fIturnutils_uclient\fP: emulates multiple UDP,TCP,TLS or DTLS clients. +(this program is provided for the testing purposes only !) +The compiled binary image of this program is located in bin/ +sub\-directory. +.PP +WARNING: the \fIturnutils_uclient\fP program is a primitive client application. +It does not implement the re\-transmission pattern that is necessary for +a correct TURN client implementation. In TURN, the retransmission burden +is lying almost entirely on the client application. We provide the messaging +functionality in the client library, but the client must implement +the correct Networking IO processing in the client program code. +.TP +.B +2. +\fIturnutils_peer\fP: a simple stateless UDP\-only "echo" server, +to be used as the final server in relay pattern ("peer"). For every incoming +UDP packet, it simply echoes it back. +(this program is provided for the testing purposes only !) +When the test clients are communicating in the client\-to\-client manner +(when the "\fIturnutils_uclient\fP" program is used with "\fB\-y\fP" option) then the +\fIturnutils_peer\fP is not needed. +.PP +The compiled binary image of this program is located in bin/ subdirectory. +.TP +.B +3. +\fIturnutils_stunclient\fP: a simple STUN client example. +The compiled binary image of this program is located in bin/ subdirectory. +.TP +.B +4. +\fIturnutils_rfc5769check\fP: a utility that checks the correctness of the +STUN/TURN protocol implementation. This utility is used only for the compilation +check procedure, it is not copied to the installation destination. +.RE +.PP + +.RS +In the "examples/scripts" subdirectory, you will find the examples of command lines to be used +to run the programs. The scripts are meant to be run from examples/ subdirectory, for example: +.PP +$ cd examples +.PP +$ ./scripts/secure_relay.sh +.PP +===================================== +.SS NAME +\fB +\fBturnutils_uclient \fP\- this client emulation application is supplied for the test purposes only. +\fB +.SS SYNOPSIS + +$ \fIturnutils_uclient\fP [\fB\-tTSvsyhcxg\fP] [options] +.SS DESCRIPTION + +It was designed to simulate multiple clients. It uses asynch IO API in +libevent to handle multiple clients. A client connects to the relay, +negotiates the session, and sends multiple (configured number) messages to the server (relay), +expecting the same number of replies. The length of the messages is configurable. +The message is an arbitrary octet stream, but it can be configured as a string. +The number of the messages to send is configurable. +.TP +.B +Flags: +.TP +.B +\fB\-t\fP +Use TCP for communications between client and TURN server (default is UDP). +.TP +.B +\fB\-T\fP +Use TCP for the relay transport (default \- UDP). Implies options \fB\-t\fP, \fB\-y\fP, \fB\-c\fP, +and ignores flags and options \fB\-s\fP, \fB\-e\fP, \fB\-r\fP and \fB\-g\fP. +.TP +.B +\fB\-P\fP +Passive TCP (RFC6062 with active peer). Implies \fB\-T\fP. +.TP +.B +\fB\-S\fP +Secure SSL connection: SSL/TLS for TCP, DTLS for UDP. +.TP +.B +\fB\-U\fP +Secure unencrypted connection (suite eNULL): SSL/TLS for TCP, DTLS for UDP. +.TP +.B +\fB\-v\fP +Verbose. +.TP +.B +\fB\-s\fP +Use "Send" method in TURN; by default, it uses TURN Channels. +.TP +.B +\fB\-y\fP +Use client\-to\-client connections: +RTP/RTCP pair of channels to another RTP/RTCP pair of channels. +with this option the \fIturnutils_peer\fP application is not used, +as the allocated relay endpoints are talking to each other. +.TP +.B +\fB\-h\fP +Hang on indefinitely after the last sent packet. +.TP +.B +\fB\-c\fP +Do not create rtcp connections. +.TP +.B +\fB\-x\fP +Request IPv6 relay address (RFC6156). +.TP +.B +\fB\-X\fP +IPv4 relay address explicitly requested. +.TP +.B +\fB\-g\fP +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 +.B +\fB\-N\fP +do negative tests (some limited cases only). +.TP +.B +\fB\-R\fP +do negative protocol tests. +.TP +.B +\fB\-O\fP +DOS attack mode. +.TP +.B +\fB\-H\fP +SHA256 digest function for message integrity calculation. +Without this option, by default, SHA1 is used. +.TP +.B +\fB\-M\fP +Use TURN ICE Mobility. +.TP +.B +\fB\-I\fP +Do not set permissions on TURN relay endpoints +(for testing the non\-standard server relay functionality). +.TP +.B +\fB\-G\fP +Generate extra requests (create permissions, channel bind). +.TP +.B +Options with required values: +.TP +.B +\fB\-l\fP +Message length (Default: 100 Bytes). +.TP +.B +\fB\-i\fP +Certificate file (for secure connections only, optional). +.TP +.B +\fB\-k\fP +Private key file (for secure connections only). +.TP +.B +\fB\-E\fP +CA file for server certificate verification, +if the server certificate to be verified. +.TP +.B +\fB\-p\fP +\fBTURN Server\fP port (Defaults: 3478 unsecure, 5349 secure). +.TP +.B +\fB\-n\fP +Number of messages to send (Default: 5). +.TP +.B +\fB\-d\fP +Local interface device (optional, Linux only). +.TP +.B +\fB\-L\fP +Local IP address (optional). +.TP +.B +\fB\-m\fP +Number of clients (Default: 1, 2 or 4, depending on options). +.TP +.B +\fB\-e\fP +Peer address. +.TP +.B +\fB\-r\fP +Peer port (Default: 3480). +.TP +.B +\fB\-z\fP +Per\-session packet interval in milliseconds (Default: 20). +.TP +.B +\fB\-u\fP +STUN/TURN user name. +.TP +.B +\fB\-w\fP +STUN/TURN user password. +.TP +.B +\fB\-W\fP +TURN REST API authentication secret. Is not compatible with \fB\-A\fP flag. +.TP +.B +\fB\-C\fP +This is the timestamp/username separator symbol (character) in +TURN REST API. The default value is :. +.TP +.B +\fB\-F\fP +Cipher suite for TLS/DTLS. Default value is DEFAULT. +.PP +See the examples in the "examples/scripts" directory. +.PP +====================================== +.SS NAME +\fB +\fBturnutils_peer \fP\- a simple UDP\-only echo backend server. +\fB +.SS SYNOPSYS + +$ \fIturnutils_peer\fP [\fB\-v\fP] [options] +.SS DESCRIPTION + +This application is used for the test purposes only, as a peer for the \fIturnutils_uclient\fP application. +.TP +.B +Options with required values: +.TP +.B +\fB\-p\fP +Listening UDP port (Default: 3480). +.TP +.B +\fB\-d\fP +Listening interface device (optional) +.TP +.B +\fB\-L\fP +Listening address of \fIturnutils_peer\fP server. Multiple listening addresses can be used, IPv4 and IPv6. +If no listener \fBaddress\fP(es) defined, then it listens on all IPv4 and IPv6 addresses. +.TP +.B +\fB\-v\fP +Verbose +.PP +======================================== +.SS NAME +\fB +\fBturnutils_stunclient \fP\- a basic STUN client. +\fB +.SS SYNOPSIS +.nf +.fam C + +$ \fIturnutils_stunclient\fP [\fIoptions\fP] + +.fam T +.fi +.fam T +.fi +.SS DESCRIPTION + +It sends a "new" STUN RFC 5389 request (over UDP) and shows the reply information. +.TP +.B +Options with required values: +.TP +.B +\fB\-p\fP +STUN server port (Default: 3478). +.TP +.B +\fB\-L\fP +Local address to use (optional). +.TP +.B +\fB\-f\fP +Force RFC 5780 processing. +.PP +The \fIturnutils_stunclient\fP program checks the results of the first request, +and if it finds that the STUN server supports RFC 5780 +(the binding response reveals that) then the \fIturnutils_stunclient\fP makes a couple more +requests with different parameters, to demonstrate the NAT discovery capabilities. +.PP +This utility does not support the "old" "classic" STUN protocol (RFC 3489). +.PP +===================================== +.SS NAME +\fB +\fBturnutils_rfc5769check \fP\- a utility that tests the correctness of STUN protocol implementation. +\fB +.SS SYNOPSIS +.nf +.fam C + +$ \fIturnutils_rfc5769check\fP + +.fam T +.fi +.fam T +.fi +.SS DESCRIPTION + +\fIturnutils_rfc5769check\fP tests the correctness of STUN protocol implementation +against the test vectors predefined in RFC 5769 and prints the results of the +tests on the screen. This utility is used only for the compilation +check procedure, it is not copied to the installation destination. +.TP +.B +Usage: +.PP +$ \fIturnutils_rfc5769check\fP +.PP +=================================== +.SH DOCS + +After installation, run the command: +.PP +$ man \fIturnutils\fP +.PP +or in the project root directory: +.PP +$ man \fB\-M\fP man \fIturnutils\fP +.PP +to see the man page. +.PP +===================================== +.SH FILES + +/etc/turnserver.conf +.PP +/etc/turnuserdb.conf +.PP +/usr/local/etc/turnserver.conf +.PP +/usr/local/etc/turnuserdb.conf +.PP +================================= +.SH DIRECTORIES + +/usr/local/share/\fIturnserver\fP +.PP +/usr/local/share/doc/\fIturnserver\fP +.PP +/usr/local/share/examples/\fIturnserver\fP +.PP +=================================== +.SH STANDARDS + +new STUN RFC 5389 +.PP +TURN RFC 5766 +.PP +TURN\-TCP extension RFC 6062 +.PP +TURN IPv6 extension RFC 6156 +.PP +STUN/TURN test vectors RFC 5769 +.PP +STUN NAT behavior discovery RFC 5780 +.PP +==================================== +.SH SEE ALSO + +\fIturnserver\fP, \fIturnadmin\fP +.RE +.PP +====================================== +.SS WEB RESOURCES + +project page: +.PP +http://code.google.com/p/coturn/ +.PP +Wiki page: +.PP +http://code.google.com/p/coturn/wiki/Readme +.PP +forum: +.PP +https://groups.google.com/forum/?fromgroups=#!forum/turn\-server\-project\-rfc5766\-turn\-server/ +.RE +.PP +====================================== +.SS AUTHORS + +Oleg Moskalenko +.PP +Gabor Kovesdan http://kovesdan.org/ +.PP +Daniel Pocock http://danielpocock.com/ +.PP +John Selbie (jselbie@gmail.com) +.PP +Lee Sylvester +.PP +Erik Johnston +.PP +Roman Lisagor +.PP +Vladimir Tsanev +.PP +Po\-sheng Lin +.PP +Peter Dunkley +.PP +Mutsutoshi Yoshimoto diff --git a/man/man1/turnutils_peer.1 b/man/man1/turnutils_peer.1 new file mode 120000 index 00000000..6996d67f --- /dev/null +++ b/man/man1/turnutils_peer.1 @@ -0,0 +1 @@ +turnutils.1 \ No newline at end of file diff --git a/man/man1/turnutils_stunclient.1 b/man/man1/turnutils_stunclient.1 new file mode 120000 index 00000000..6996d67f --- /dev/null +++ b/man/man1/turnutils_stunclient.1 @@ -0,0 +1 @@ +turnutils.1 \ No newline at end of file diff --git a/man/man1/turnutils_uclient.1 b/man/man1/turnutils_uclient.1 new file mode 120000 index 00000000..6996d67f --- /dev/null +++ b/man/man1/turnutils_uclient.1 @@ -0,0 +1 @@ +turnutils.1 \ No newline at end of file diff --git a/postinstall.txt b/postinstall.txt new file mode 100644 index 00000000..c05efceb --- /dev/null +++ b/postinstall.txt @@ -0,0 +1,35 @@ +================================================================== + +1) If you system supports automatic start-up system daemon services, +the, to enable the turnserver as an automatically started system +service, you have to: + + a) Create and edit /etc/turnserver.conf or + /usr/local/etc/turnserver.conf . + Use /usr/local/etc/turnserver.conf.default as an example. + + b) For user accounts settings, if using the turnserver + with authentication: create and edit /etc/turnuserdb.conf + file, or set up PostgreSQL or MySQL or Redis database for user accounts. + Use /usr/local/etc/turnuserdb.conf.default as example for flat file DB, + or use /usr/local/share/turnserver/schema.sql as SQL database schema, + or use /usr/local/share/turnserver/schema.userdb.redis as Redis + database schema description and/or /usr/local/share/turnserver/schema.stats.redis + as Redis status & statistics database schema description. + + c) add whatever is necessary to enable start-up daemon for the /usr/local/bin/turnserver. + +2) If you do not want the turnserver to be a system service, + then you can start/stop it "manually", using the "turnserver" + executable with appropriate options (see the documentation). + +3) To create database schema, use schema in file /usr/local/share/turnserver/schema.sql. + +4) For additional information, run: + + $ man turnserver + $ man turnadmin + $ man turnutils + +================================================================== + diff --git a/rpm/CentOS6.pre.build.sh b/rpm/CentOS6.pre.build.sh new file mode 100755 index 00000000..7a37ac2f --- /dev/null +++ b/rpm/CentOS6.pre.build.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +# CentOS6 preparation script. + +CPWD=`pwd` + +. ./common.pre.build.sh + +cd ${CPWD} + +EPELRPM=epel-release-6-8.noarch.rpm +LIBEVENT_MAJOR_VERSION=2 +LIBEVENT_VERSION=${LIBEVENT_MAJOR_VERSION}.0.21 +LIBEVENT_DISTRO=libevent-${LIBEVENT_VERSION}-stable.tar.gz +LIBEVENT_SPEC_DIR=libevent.rpm +LIBEVENTSPEC_SVN_URL=${TURNSERVER_SVN_URL}/${LIBEVENT_SPEC_DIR} +LIBEVENT_SPEC_FILE=libevent.spec + +# Common packs + +PACKS="mysql-devel" +sudo yum -y install ${PACKS} +ER=$? +if ! [ ${ER} -eq 0 ] ; then + echo "Cannot install package(s) ${PACKS}" + cd ${CPWD} + exit -1 +fi + +# Libevent2: + +cd ${BUILDDIR}/SOURCES +if ! [ -f ${LIBEVENT_DISTRO} ] ; then + wget ${WGETOPTIONS} https://github.com/downloads/libevent/libevent/${LIBEVENT_DISTRO} + ER=$? + if ! [ ${ER} -eq 0 ] ; then + cd ${CPWD} + exit -1 + fi +fi + +if ! [ -f ${BUILDDIR}/SPECS/${LIBEVENT_SPEC_FILE} ] ; then + cd ${BUILDDIR}/tmp + rm -rf ${LIBEVENT_SPEC_DIR} + svn export ${LIBEVENTSPEC_SVN_URL} ${LIBEVENT_SPEC_DIR} + ER=$? + if ! [ ${ER} -eq 0 ] ; then + cd ${CPWD} + exit -1 + fi + + if ! [ -f ${LIBEVENT_SPEC_DIR}/${LIBEVENT_SPEC_FILE} ] ; then + echo "ERROR: cannot download ${LIBEVENT_SPEC_FILE} file" + cd ${CPWD} + exit -1 + fi + + cp ${LIBEVENT_SPEC_DIR}/${LIBEVENT_SPEC_FILE} ${BUILDDIR}/SPECS +fi + +cd ${BUILDDIR}/SPECS +rpmbuild -ba ${BUILDDIR}/SPECS/${LIBEVENT_SPEC_FILE} +ER=$? +if ! [ ${ER} -eq 0 ] ; then + cd ${CPWD} + exit -1 +fi + +PACK=${BUILDDIR}/RPMS/${ARCH}/libevent-${LIBEVENT_MAJOR_VERSION}*.rpm +sudo rpm ${RPMOPTIONS} ${PACK} +ER=$? +if ! [ ${ER} -eq 0 ] ; then + echo "Cannot install packages ${PACK}" + cd ${CPWD} + exit -1 +fi + +PACK=${BUILDDIR}/RPMS/${ARCH}/libevent-devel*.rpm +sudo rpm ${RPMOPTIONS} ${PACK} +ER=$? +if ! [ ${ER} -eq 0 ] ; then + echo "Cannot install packages ${PACK}" + cd ${CPWD} + exit -1 +fi + +# EPEL (for hiredis) + +cd ${CPWD} +./epel.install.sh + +# Platform file + +echo "CentOS6.5" > ${BUILDDIR}/platform + +cp ${CPWD}/epel.install.sh ${BUILDDIR}/install.sh + +cd ${CPWD} diff --git a/rpm/Fedora.pre.build.sh b/rpm/Fedora.pre.build.sh new file mode 100755 index 00000000..a5e8bc87 --- /dev/null +++ b/rpm/Fedora.pre.build.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +CPWD=`pwd` + +# Fedora preparation script. + +. ./common.pre.build.sh + +PACKS="libevent-devel mariadb-devel" +sudo yum -y install ${PACKS} +ER=$? +if ! [ ${ER} -eq 0 ] ; then + echo "Cannot install package(s) ${PACKS}" + cd ${CPWD} + exit -1 +fi + +echo "Fedora20" > ${BUILDDIR}/platform + +cd ${CPWD} diff --git a/rpm/build.instructions.txt b/rpm/build.instructions.txt new file mode 100644 index 00000000..4bfbfaa2 --- /dev/null +++ b/rpm/build.instructions.txt @@ -0,0 +1,43 @@ +MANUAL PROCESS FOR CENTOS 6: + + +The first thing you need to build/use the TURN server with CentOS is to build and install libevent 2.x.x. CentOS 6 ships with libevent 1.x.x. You can find a .spec file to build libevent 2.x.x here: https://github.com/crocodilertc/libevent + +To build libevent: + + 1) Install the dependencies for building libevent: gcc, make, redhat-rpm-config, doxygen, openssl-devel, rpm-build + 2) $ mkdir ~/rpmbuild + 3) $ mkdir ~/rpmbuild/SOURCES + 4) $ mkdir ~/rpmbuild/SPECS + 5) Put the tarball for libevent (https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz) and put it into ~/rpmbuild/SOURCES + 6) Put the .spec for libevent (https://raw.github.com/crocodilertc/libevent/master/libevent.spec) into ~/rpmbuild/SPECS + 7) Build the RPMs, "rpmbuild -ba ~/rpmbuild/SPECS/libevent.spec" + + +To build the TURN server: + + 1) Install libevent and libevent-devel rpms + 2) Install EPEL (http://fedoraproject.org/wiki/EPEL) - needed for hiredis + 3) Install the dependencies for building the TURN server: gcc, make, redhat-rpm-config, openssl-devel, libevent-devel >= 2.0.0, + mysql-devel, postgresql-devel, hiredis-devel + 4) $ mkdir ~/rpmbuild + 5) $ mkdir ~/rpmbuild/SOURCES + 6) Export the TURN server from SVN, "svn export http://coturn.googlecode.com/svn/trunk/ turnserver-2.6.7.0" + 7) Create a tarball, "tar zcf ~/rpmbuild/SOURCES/turnserver-2.6.7.0.tar.gz turnserver-2.6.7.0" + 8) Build the RPMs, "rpmbuild -ta ~/rpmbuild/SOURCES/turnserver-2.6.7.0.tar.gz" + + +AUTOMATED PROCESS FOR CENTOS 6: + +$ cd <...>/coturn/rpm +$ ./CentOS6.pre.build.sh +$ ./build.sh +(then see the tarball in ~/rpmbuild/RPMS/) + +AUTOMATED PROCESS FOR Fedora: + +$ cd <...>/coturn/rpm +$ ./Fedora.pre.build.sh +$ ./build.sh +(then see the tarball in ~/rpmbuild/RPMS/) + diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh new file mode 100755 index 00000000..1e610702 --- /dev/null +++ b/rpm/build.settings.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# Common settings script. + +TURNVERSION=3.3.0.0 +BUILDDIR=~/rpmbuild +ARCH=`uname -p` +TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn +TURNSERVER_SVN_URL_VER=trunk + +WGETOPTIONS="--no-check-certificate" +RPMOPTIONS="-ivh --force" + + diff --git a/rpm/build.sh b/rpm/build.sh new file mode 100755 index 00000000..745f6928 --- /dev/null +++ b/rpm/build.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +CPWD=`pwd` + +. ./build.settings.sh + +# Required packages + +PACKS="postgresql-devel hiredis-devel" + +sudo yum -y install ${PACKS} +ER=$? +if ! [ ${ER} -eq 0 ] ; then + echo "Cannot install packages ${PACKS}" + cd ${CPWD} + exit -1 +fi + +# TURN + +cd ${BUILDDIR}/tmp +rm -rf turnserver-${TURNVERSION} +svn export ${TURNSERVER_SVN_URL}/${TURNSERVER_SVN_URL_VER}/ turnserver-${TURNVERSION} +ER=$? +if ! [ ${ER} -eq 0 ] ; then + cd ${CPWD} + exit -1 +fi + +tar zcf ${BUILDDIR}/SOURCES/turnserver-${TURNVERSION}.tar.gz turnserver-${TURNVERSION} +ER=$? +if ! [ ${ER} -eq 0 ] ; then + cd ${CPWD} + exit -1 +fi + +rpmbuild -ta ${BUILDDIR}/SOURCES/turnserver-${TURNVERSION}.tar.gz +ER=$? +if ! [ ${ER} -eq 0 ] ; then + cd ${CPWD} + exit -1 +fi + +# Make binary tarball + +cd ${BUILDDIR}/RPMS/${ARCH} +mkdir -p di +mv *debuginfo* di +mv *devel* di +rm -rf turnserver-${TURNVERSION} +mkdir turnserver-${TURNVERSION} +mv *.rpm turnserver-${TURNVERSION}/ + +rm -rf turnserver-${TURNVERSION}/install.sh + +if [ -f ${BUILDDIR}/install.sh ] ; then + cat ${BUILDDIR}/install.sh > turnserver-${TURNVERSION}/install.sh +else + echo "#!/bin/sh" > turnserver-${TURNVERSION}/install.sh +fi + +cat <>turnserver-${TURNVERSION}/install.sh + +sudo yum -y install openssl +sudo yum -y install telnet + +for i in *.rpm ; do + + sudo yum -y install \${i} + ER=\$? + if ! [ \${ER} -eq 0 ] ; then + sudo rpm -Uvh \${i} + ER=\$? + if ! [ \${ER} -eq 0 ] ; then + sudo rpm -ivh --force \${i} + ER=\$? + if ! [ \${ER} -eq 0 ] ; then + echo "ERROR: cannot install package \${i}" + exit -1 + fi + fi + fi +done + +echo SUCCESS ! + +EOF + +chmod a+x turnserver-${TURNVERSION}/install.sh + +cp ${CPWD}/uninstall.turnserver.sh turnserver-${TURNVERSION}/ +chmod a+x turnserver-${TURNVERSION}/uninstall.turnserver.sh + +PLATFORM=`cat ${BUILDDIR}/platform` + +tar cvfz turnserver-${TURNVERSION}-${PLATFORM}-${ARCH}.tar.gz turnserver-${TURNVERSION} + +cd ${CPWD} diff --git a/rpm/common.pre.build.sh b/rpm/common.pre.build.sh new file mode 100755 index 00000000..0bf831e6 --- /dev/null +++ b/rpm/common.pre.build.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Common preparation script. + +. ./build.settings.sh + +# DIRS + +rm -rf ${BUILDDIR} + +mkdir -p ${BUILDDIR} +mkdir -p ${BUILDDIR}/SOURCES +mkdir -p ${BUILDDIR}/SPECS +mkdir -p ${BUILDDIR}/RPMS +mkdir -p ${BUILDDIR}/tmp + +# Common packs + +PACKS="make gcc redhat-rpm-config rpm-build doxygen openssl-devel svn" +sudo yum -y install ${PACKS} +ER=$? +if ! [ ${ER} -eq 0 ] ; then + echo "Cannot install packages ${PACKS}" + exit -1 +fi + diff --git a/rpm/epel.install.sh b/rpm/epel.install.sh new file mode 100755 index 00000000..7cc2b1f4 --- /dev/null +++ b/rpm/epel.install.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +CPWD=`pwd` + +# Epel installation script + +EPEL=epel-release-6-8.noarch +EPELRPM=${EPEL}.rpm +BUILDDIR=~/rpmbuild +WGETOPTIONS="--no-check-certificate" +RPMOPTIONS="-ivh --force" + +mkdir -p ${BUILDDIR} +mkdir -p ${BUILDDIR}/RPMS + +sudo yum -y install wget + +cd ${BUILDDIR}/RPMS +if ! [ -f ${EPELRPM} ] ; then + wget ${WGETOPTIONS} http://download.fedoraproject.org/pub/epel/6/i386/${EPELRPM} + ER=$? + if ! [ ${ER} -eq 0 ] ; then + cd ${CPWD} + exit -1 + fi +fi + +PACK=${EPELRPM} +sudo rpm ${RPMOPTIONS} ${PACK} +ER=$? +if ! [ ${ER} -eq 0 ] ; then + echo "Cannot install package ${PACK}" + cd ${CPWD} + exit -1 +fi + +cd ${CPWD} + + diff --git a/rpm/turnserver.init.el b/rpm/turnserver.init.el new file mode 100644 index 00000000..724f87c3 --- /dev/null +++ b/rpm/turnserver.init.el @@ -0,0 +1,82 @@ +#!/bin/bash +# +# Startup script for TURN Server +# +# chkconfig: 345 85 15 +# description: RFC 5766 TURN Server +# +# processname: turnserver +# pidfile: /var/run/turnserver.pid +# config: /etc/turnserver/turnserver.conf +# +### BEGIN INIT INFO +# Provides: turnserver +# Required-Start: $local_fs $network +# Short-Description: RFC 5766 TURN Server +# Description: RFC 5766 TURN Server +### END INIT INFO + +# Source function library. +. /etc/rc.d/init.d/functions + +TURN=/usr/bin/turnserver +PROG=turnserver +TURNCFG=/etc/turnserver/$PROG.conf +PID_FILE=/var/run/$PROG.pid +LOCK_FILE=/var/lock/subsys/$PROG +DEFAULTS=/etc/sysconfig/$PROG +RETVAL=0 +USER=turnserver + +start() { + echo -n $"Starting $PROG: " + daemon --user=$USER $TURN $OPTIONS + RETVAL=$? + if [ $RETVAL = 0 ]; then + pidofproc $TURN > $PID_FILE + RETVAL=$? + [ $RETVAL = 0 ] && touch $LOCK_FILE && success + fi + echo + return $RETVAL +} + +stop() { + echo -n $"Stopping $PROG: " + killproc $TURN + RETVAL=$? + echo + [ $RETVAL = 0 ] && rm -f $LOCK_FILE $PID_FILE +} + +[ -f $DEFAULTS ] && . $DEFAULTS +OPTIONS="-o -c $TURNCFG $EXTRA_OPTIONS" + +# See how we were called. +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + status $TURN + RETVAL=$? + ;; + restart) + stop + start + ;; + condrestart) + if [ -f $PID_FILE ] ; then + stop + start + fi + ;; + *) + echo $"Usage: $PROG {start|stop|restart|condrestart|status|help}" + exit 1 +esac + +exit $RETVAL diff --git a/rpm/turnserver.service.fc b/rpm/turnserver.service.fc new file mode 100644 index 00000000..3ac4417b --- /dev/null +++ b/rpm/turnserver.service.fc @@ -0,0 +1,15 @@ +[Unit] +Description=coturn +Documentation=man:coturn(1) man:turnadmin(1) man:turnserver(1) +After=syslog.target network.target + +[Service] +Type=forking +EnvironmentFile=/etc/sysconfig/turnserver +PIDFile=/var/run/turnserver.pid +ExecStart=/usr/bin/turnserver -o -c /etc/turnserver/turnserver.conf $EXTRA_OPTIONS +ExecStopPost=/usr/bin/rm -f /var/run/turnserver.pid +Restart=on-abort + +[Install] +WantedBy=multi-user.target diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec new file mode 100644 index 00000000..b566e097 --- /dev/null +++ b/rpm/turnserver.spec @@ -0,0 +1,358 @@ +Name: turnserver +Version: 3.3.0.0 +Release: 0%{dist} +Summary: Coturn TURN Server + +Group: System Environment/Libraries +License: BSD +URL: https://code.google.com/p/coturn/ +Source0: http://turnserver.open-sys.org/downloads/v%{version}/%{name}-%{version}.tar.gz + +BuildRequires: gcc, make, redhat-rpm-config +BuildRequires: openssl-devel, libevent-devel >= 2.0.0, postgresql-devel +BuildRequires: hiredis-devel +Requires: openssl, libevent >= 2.0.0, mysql-libs, postgresql-libs +Requires: hiredis, perl-DBI, perl-libwww-perl +Requires: telnet +%if 0%{?el6} +BuildRequires: epel-release, mysql-devel +Requires: epel-release, mysql-libs +%else +BuildRequires: mariadb-devel +Requires: mariadb-libs +%endif + + +%description +The TURN Server is a VoIP media traffic NAT traversal server and gateway. It +can be used as a general-purpose network traffic TURN server/gateway, too. + +This implementation also includes some extra features. Supported RFCs: + +TURN specs: +- RFC 5766 - base TURN specs +- RFC 6062 - TCP relaying TURN extension +- RFC 6156 - IPv6 extension for TURN +- Experimental DTLS support as client protocol. + +STUN specs: +- RFC 3489 - "classic" STUN +- RFC 5389 - base "new" STUN specs +- RFC 5769 - test vectors for STUN protocol testing +- RFC 5780 - NAT behavior discovery support + +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 +- DTLS (experimental non-standard feature) + +Supported relay protocols: +- UDP (per RFC 5766) +- TCP (per RFC 6062) + +Supported user databases (for user repository, with passwords or keys, if +authentication is required): +- Flat files +- MySQL +- PostgreSQL +- Redis + +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) + +The load balancing can be implemented with the following tools (either one or a +combination of them): +- network load-balancer server +- DNS-based load balancing +- built-in ALTERNATE-SERVER mechanism. + + +%package utils +Summary: TURN client utils +Group: System Environment/Libraries +Requires: turnserver-client-libs = %{version}-%{release} + +%description utils +This package contains the TURN client utils. + +%package client-libs +Summary: TURN client library +Group: System Environment/Libraries +Requires: openssl, libevent >= 2.0.0 + +%description client-libs +This package contains the TURN client library. + +%package client-devel +Summary: TURN client development headers. +Group: Development/Libraries +Requires: turnserver-client-libs = %{version}-%{release} + +%description client-devel +This package contains the TURN client development headers. + +%prep +%setup -q -n %{name}-%{version} + +%build +PREFIX=%{_prefix} CONFDIR=%{_sysconfdir}/%{name} EXAMPLESDIR=%{_datadir}/%{name} \ + MANPREFIX=%{_datadir} LIBDIR=%{_libdir} MORECMD=cat ./configure +make + +%install +rm -rf $RPM_BUILD_ROOT +DESTDIR=$RPM_BUILD_ROOT make install +mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig +install -m644 rpm/turnserver.sysconfig \ + $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig/turnserver +mv $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/turnuserdb.conf.default \ + $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/turnuserdb.conf +%if 0%{?el6} +cat $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/turnserver.conf.default | \ + sed s/#syslog/syslog/g | \ + sed s/#no-stdout-log/no-stdout-log/g > \ + $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/turnserver.conf +mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/rc.d/init.d +install -m755 rpm/turnserver.init.el \ + $RPM_BUILD_ROOT/%{_sysconfdir}/rc.d/init.d/turnserver +%else +cat $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/turnserver.conf.default | \ + sed s/#syslog/syslog/g | \ + sed s/#no-stdout-log/no-stdout-log/g | \ + sed s/#pidfile/pidfile/g > \ + $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/turnserver.conf +mkdir -p $RPM_BUILD_ROOT/%{_unitdir} +install -m755 rpm/turnserver.service.fc \ + $RPM_BUILD_ROOT/%{_unitdir}/turnserver.service +%endif +rm -rf $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/turnserver.conf.default + +%clean +rm -rf "$RPM_BUILD_ROOT" + +%pre +%{_sbindir}/groupadd -r turnserver 2> /dev/null || : +%{_sbindir}/useradd -r -g turnserver -s /bin/false -c "TURN Server daemon" -d \ + %{_datadir}/%{name} turnserver 2> /dev/null || : + +%post +%if 0%{?el6} +/sbin/chkconfig --add turnserver +%else +/bin/systemctl --system daemon-reload +%endif + +%preun +if [ $1 = 0 ]; then +%if 0%{?el6} + /sbin/service turnserver stop > /dev/null 2>&1 + /sbin/chkconfig --del turnserver +%else + /bin/systemctl stop turnserver.service + /bin/systemctl disable turnserver.service 2> /dev/null +%endif +fi + +%postun +%if 0%{?fedora} +/bin/systemctl --system daemon-reload +%endif + +%files +%defattr(-,root,root) +%{_bindir}/turnserver +%{_bindir}/turnadmin +%{_mandir}/man1/coturn.1.gz +%{_mandir}/man1/turnserver.1.gz +%{_mandir}/man1/turnadmin.1.gz +%dir %attr(-,turnserver,turnserver) %{_sysconfdir}/%{name} +%config(noreplace) %attr(0644,turnserver,turnserver) %{_sysconfdir}/%{name}/turnserver.conf +%config(noreplace) %attr(0644,turnserver,turnserver) %{_sysconfdir}/%{name}/turnuserdb.conf +%config(noreplace) %{_sysconfdir}/sysconfig/turnserver +%if 0%{?el6} +%config %{_sysconfdir}/rc.d/init.d/turnserver +%else +%config %{_unitdir}/turnserver.service +%endif +%dir %{_docdir}/%{name} +%{_docdir}/%{name}/LICENSE +%{_docdir}/%{name}/INSTALL +%{_docdir}/%{name}/postinstall.txt +%{_docdir}/%{name}/README.turnadmin +%{_docdir}/%{name}/README.turnserver +%{_docdir}/%{name}/schema.sql +%{_docdir}/%{name}/schema.stats.redis +%{_docdir}/%{name}/schema.userdb.redis +%dir %{_datadir}/%{name} +%{_datadir}/%{name}/schema.sql +%{_datadir}/%{name}/schema.stats.redis +%{_datadir}/%{name}/schema.userdb.redis +%{_datadir}/%{name}/testredisdbsetup.sh +%{_datadir}/%{name}/testsqldbsetup.sql +%dir %{_datadir}/%{name}/etc +%{_datadir}/%{name}/etc/turn_server_cert.pem +%{_datadir}/%{name}/etc/turn_server_pkey.pem +%{_datadir}/%{name}/etc/turnserver.conf +%{_datadir}/%{name}/etc/turnuserdb.conf +%dir %{_datadir}/%{name}/scripts +%{_datadir}/%{name}/scripts/peer.sh +%{_datadir}/%{name}/scripts/readme.txt +%dir %{_datadir}/%{name}/scripts/basic +%{_datadir}/%{name}/scripts/basic/dos_attack.sh +%{_datadir}/%{name}/scripts/basic/relay.sh +%{_datadir}/%{name}/scripts/basic/tcp_client.sh +%{_datadir}/%{name}/scripts/basic/tcp_client_c2c_tcp_relay.sh +%{_datadir}/%{name}/scripts/basic/udp_c2c_client.sh +%{_datadir}/%{name}/scripts/basic/udp_client.sh +%dir %{_datadir}/%{name}/scripts/loadbalance +%{_datadir}/%{name}/scripts/loadbalance/master_relay.sh +%{_datadir}/%{name}/scripts/loadbalance/slave_relay_1.sh +%{_datadir}/%{name}/scripts/loadbalance/slave_relay_2.sh +%{_datadir}/%{name}/scripts/loadbalance/tcp_c2c_tcp_relay.sh +%{_datadir}/%{name}/scripts/loadbalance/udp_c2c.sh +%dir %{_datadir}/%{name}/scripts/longtermsecure +%{_datadir}/%{name}/scripts/longtermsecure/secure_dos_attack.sh +%{_datadir}/%{name}/scripts/longtermsecure/secure_dtls_client.sh +%{_datadir}/%{name}/scripts/longtermsecure/secure_dtls_client_cert.sh +%{_datadir}/%{name}/scripts/longtermsecure/secure_tls_client_cert.sh +%{_datadir}/%{name}/scripts/longtermsecure/secure_relay.sh +%{_datadir}/%{name}/scripts/longtermsecure/secure_relay_cert.sh +%{_datadir}/%{name}/scripts/longtermsecure/secure_tcp_client.sh +%{_datadir}/%{name}/scripts/longtermsecure/secure_tcp_client_c2c_tcp_relay.sh +%{_datadir}/%{name}/scripts/longtermsecure/secure_tls_client.sh +%{_datadir}/%{name}/scripts/longtermsecure/secure_tls_client_c2c_tcp_relay.sh +%{_datadir}/%{name}/scripts/longtermsecure/secure_udp_c2c.sh +%{_datadir}/%{name}/scripts/longtermsecure/secure_udp_client.sh +%dir %{_datadir}/%{name}/scripts/longtermsecuredb +%{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh +%{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_psql.sh +%{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_redis.sh +%dir %{_datadir}/%{name}/scripts/restapi +%{_datadir}/%{name}/scripts/restapi/secure_relay_secret.sh +%{_datadir}/%{name}/scripts/restapi/secure_relay_secret_with_db_mysql.sh +%{_datadir}/%{name}/scripts/restapi/secure_relay_secret_with_db_psql.sh +%{_datadir}/%{name}/scripts/restapi/secure_relay_secret_with_db_redis.sh +%{_datadir}/%{name}/scripts/restapi/secure_udp_client_with_secret.sh +%{_datadir}/%{name}/scripts/restapi/shared_secret_maintainer.pl +%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 +%{_datadir}/%{name}/scripts/mobile/mobile_tcp_client.sh +%{_datadir}/%{name}/scripts/mobile/mobile_tls_client_c2c_tcp_relay.sh +%{_datadir}/%{name}/scripts/mobile/mobile_udp_client.sh + +%files utils +%defattr(-,root,root) +%{_bindir}/turnutils_peer +%{_bindir}/turnutils_stunclient +%{_bindir}/turnutils_uclient +%{_mandir}/man1/turnutils.1.gz +%{_mandir}/man1/turnutils_peer.1.gz +%{_mandir}/man1/turnutils_stunclient.1.gz +%{_mandir}/man1/turnutils_uclient.1.gz +%dir %{_docdir}/%{name} +%{_docdir}/%{name}/LICENSE +%{_docdir}/%{name}/README.turnutils +%dir %{_datadir}/%{name} +%dir %{_datadir}/%{name}/etc +%{_datadir}/%{name}/etc/turn_client_cert.pem +%{_datadir}/%{name}/etc/turn_client_pkey.pem + +%files client-libs +%{_docdir}/%{name}/LICENSE +%{_libdir}/libturnclient.a + +%files client-devel +%{_docdir}/%{name}/LICENSE +%dir %{_includedir}/turn +%{_includedir}/turn/ns_turn_defs.h +%dir %{_includedir}/turn/client +%{_includedir}/turn/client/ns_turn_ioaddr.h +%{_includedir}/turn/client/ns_turn_msg_addr.h +%{_includedir}/turn/client/ns_turn_msg_defs.h +%{_includedir}/turn/client/ns_turn_msg.h +%{_includedir}/turn/client/TurnMsgLib.h + +%changelog +* Sun Feb 09 2014 Oleg Moskalenko + - Sync to 3.3.0.0 +* Tue Feb 04 2014 Oleg Moskalenko + - Sync to 3.2.2.6 +* Sat Jan 25 2014 Oleg Moskalenko + - Sync to 3.2.2.5 +* Fri Jan 24 2014 Oleg Moskalenko + - Sync to 3.2.2.4 +* Thu Jan 23 2014 Oleg Moskalenko + - Sync to 3.2.2.3 +* Tue Jan 21 2014 Oleg Moskalenko + - Sync to 3.2.2.2 +* Sat Jan 11 2014 Oleg Moskalenko + - CPU optimization, added to 3.2.2.1 +* Mon Jan 06 2014 Oleg Moskalenko + - Linux epoll performance improvements, added to 3.2.1.4 +* Mon Jan 06 2014 Oleg Moskalenko + - Telnet client installation added to 3.2.1.3 +* Sun Jan 05 2014 Oleg Moskalenko + - Sync to 3.2.1.2 +* Fri Jan 03 2014 Oleg Moskalenko + - Sync to 3.2.1.1 +* Thu Dec 26 2013 Oleg Moskalenko + - Sync to 3.2.1.0 +* Wed Dec 25 2013 Oleg Moskalenko + - Sync to 3.1.6.0 +* Mon Dec 23 2013 Oleg Moskalenko + - Sync to 3.1.5.3 +* Fri Dec 20 2013 Oleg Moskalenko + - Sync to 3.1.5.1 +* Thu Dec 19 2013 Oleg Moskalenko + - Sync to 3.1.4.2 +* Sat Dec 14 2013 Oleg Moskalenko + - Sync to 3.1.3.1 +* Wed Dec 11 2013 Oleg Moskalenko + - OpenSSL installation fixed 3.1.2.3 +* Tue Dec 10 2013 Oleg Moskalenko + - Updated to version 3.1.2.2 +* Mon Dec 09 2013 Oleg Moskalenko + - Updated to version 3.1.2.1 +* Sun Dec 01 2013 Oleg Moskalenko + - Updated to version 3.1.1.0 +* Sat Nov 30 2013 Oleg Moskalenko + - Updated to version 3.0.2.1. +* Thu Nov 28 2013 Oleg Moskalenko + - Config file setting fixed: version 3.0.1.4. +* Wed Nov 27 2013 Oleg Moskalenko + - Config file setting fixed: version 3.0.1.3. +* Mon Nov 25 2013 Oleg Moskalenko + - Updated to version 3.0.1.2 +* Sun Nov 10 2013 Oleg Moskalenko + - Updated to version 3.0.0.0 +* Fri Nov 8 2013 Oleg Moskalenko + - Updated to version 2.6.7.2 +* Thu Nov 7 2013 Oleg Moskalenko + - Updated to version 2.6.7.1 +* Sun Nov 3 2013 Oleg Moskalenko + - Updated to version 2.6.7.0 +* Sat Nov 2 2013 Peter Dunkley + - Added Fedora support +* Thu Oct 31 2013 Oleg Moskalenko + - Updated to version 2.6.6.2 +* Sun Oct 27 2013 Oleg Moskalenko + - Updated to version 2.6.6.1 +* Sun Oct 27 2013 Peter Dunkley + - Updated to version 2.6.6.0 +* Fri May 3 2013 Peter Dunkley + - First version diff --git a/rpm/turnserver.sysconfig b/rpm/turnserver.sysconfig new file mode 100644 index 00000000..cc587bbd --- /dev/null +++ b/rpm/turnserver.sysconfig @@ -0,0 +1,5 @@ +# +# TURN Server startup options +# + +EXTRA_OPTIONS="" diff --git a/rpm/uninstall.turnserver.sh b/rpm/uninstall.turnserver.sh new file mode 100755 index 00000000..01cd3643 --- /dev/null +++ b/rpm/uninstall.turnserver.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +for i in `rpm -q -a | grep turnserver-utils-3` +do + echo $i + sudo rpm -e $i +done + +for i in `rpm -q -a | grep turnserver-client-libs-3` +do + echo $i + sudo rpm -e $i +done + +for i in `rpm -q -a | grep turnserver.*-3` +do + echo $i + sudo rpm -e $i +done diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c new file mode 100644 index 00000000..0ef52c05 --- /dev/null +++ b/src/apps/common/apputils.c @@ -0,0 +1,902 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "ns_turn_utils.h" +#include "ns_turn_msg.h" + +#include "apputils.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +/************************/ + +int IS_TURN_SERVER = 0; + +/*********************** Sockets *********************************/ + +int socket_set_nonblocking(evutil_socket_t fd) +{ +#if defined(WIN32) + unsigned long nonblocking = 1; + ioctlsocket(fd, FIONBIO, (unsigned long*) &nonblocking); +#else + if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { + perror("O_NONBLOCK"); + return -1; + } +#endif + return 0; +} + +void read_spare_buffer(evutil_socket_t fd) +{ + if(fd >= 0) { + static char buffer[65536]; + recv(fd, buffer, sizeof(buffer), MSG_DONTWAIT); + } +} + +int set_sock_buf_size(evutil_socket_t fd, int sz0) +{ + int sz; + + sz = sz0; + while (sz > 0) { + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const void*) (&sz), (socklen_t) sizeof(sz)) < 0) { + sz = sz / 2; + } else { + break; + } + } + + if (sz < 1) { + perror("Cannot set socket rcv size"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Cannot set rcv sock size %d on fd %d\n", sz0, fd); + } + + sz = sz0; + while (sz > 0) { + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void*) (&sz), (socklen_t) sizeof(sz)) < 0) { + sz = sz / 2; + } else { + break; + } + } + + if (sz < 1) { + perror("Cannot set socket snd size"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Cannot set snd sock size %d on fd %d\n", sz0, fd); + } + + return 0; +} + +int socket_tcp_set_keepalive(evutil_socket_t fd) +{ +#ifdef SO_KEEPALIVE + /* Set the keepalive option active */ + { + int on = 1; + setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const void*)&on, (socklen_t) sizeof(on)); + } +#else + UNUSED_ARG(fd); +#endif + +#ifdef SO_NOSIGPIPE + { + int on = 1; + setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (const void*)&on, (socklen_t) sizeof(on)); + } +#endif + + return 0; +} + +int socket_set_reusable(evutil_socket_t fd, int flag) +{ + + if (fd < 0) + return -1; + else { + +#if defined(WIN32) + int use_reuseaddr = IS_TURN_SERVER; +#else + int use_reuseaddr = 1; +#endif + +#if defined(SO_REUSEPORT) + if (use_reuseaddr) { + int on = flag; + setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) &on, (socklen_t) sizeof(on)); + } +#endif + +#if defined(SO_REUSEADDR) + if (use_reuseaddr) { + int on = flag; + int ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &on, (socklen_t) sizeof(on)); + if (ret < 0) + perror("SO_REUSEADDR"); + } +#endif + + return 0; + } +} + +int sock_bind_to_device(evutil_socket_t fd, const unsigned char* ifname) { + + if (fd >= 0 && ifname && ifname[0]) { + +#if defined(SO_BINDTODEVICE) + + struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); + + strncpy(ifr.ifr_name, (const char*) ifname, sizeof(ifr.ifr_name)); + + if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *) &ifr, sizeof(ifr)) < 0) { + if (errno == EPERM) + perror("You must obtain superuser privileges to bind a socket to device"); + else + perror("Cannot bind socket to device"); + + return -1; + } + + return 0; + +#endif + + } + + return 0; +} + +int addr_connect(evutil_socket_t fd, const ioa_addr* addr, int *out_errno) +{ + if (!addr || fd < 0) + return -1; + else { + int err = 0; + do { + if (addr->ss.sa_family == AF_INET) { + err = connect(fd, (const struct sockaddr *) addr, sizeof(struct sockaddr_in)); + } else if (addr->ss.sa_family == AF_INET6) { + err = connect(fd, (const struct sockaddr *) addr, sizeof(struct sockaddr_in6)); + } else { + return -1; + } + } while (err < 0 && errno == EINTR); + + if(out_errno) + *out_errno = errno; + + if (err < 0 && errno != EINPROGRESS) + perror("Connect"); + + return err; + } +} + +int addr_bind(evutil_socket_t fd, const ioa_addr* addr, int reusable) +{ + if (!addr || fd < 0) { + + return -1; + + } else { + + int ret = -1; + + socket_set_reusable(fd, reusable); + + if (addr->ss.sa_family == AF_INET) { + do { + ret = bind(fd, (const struct sockaddr *) addr, sizeof(struct sockaddr_in)); + } while (ret < 0 && errno == EINTR); + } else if (addr->ss.sa_family == AF_INET6) { + const int off = 0; + setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *) &off, sizeof(off)); + do { + ret = bind(fd, (const struct sockaddr *) addr, sizeof(struct sockaddr_in6)); + } while (ret < 0 && errno == EINTR); + } else { + return -1; + } + if(ret<0) { + int err = errno; + perror("bind"); + char str[129]; + addr_to_string(addr,(u08bits*)str); + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "Trying to bind fd %d to <%s>: errno=%d\n", fd, str, err); + } + return ret; + } +} + +int addr_get_from_sock(evutil_socket_t fd, ioa_addr *addr) +{ + + if (fd < 0 || !addr) + return -1; + else { + + ioa_addr a; + a.ss.sa_family = AF_INET6; + socklen_t socklen = get_ioa_addr_len(&a); + if (getsockname(fd, (struct sockaddr*) &a, &socklen) < 0) { + a.ss.sa_family = AF_INET; + socklen = get_ioa_addr_len(&a); + if (getsockname(fd, (struct sockaddr*) &a, &socklen) < 0) { + return -1; + } + } + + addr_cpy(addr, &a); + + return 0; + } +} + +/////////////////// MTU ///////////////////////////////////////// + +int set_socket_df(evutil_socket_t fd, int family, int value) +{ + + int ret=0; + +#if defined(IP_DONTFRAG) && defined(IPPROTO_IP) //BSD + { + const int val=value; + /* kernel sets DF bit on outgoing IP packets */ + if(family==AF_INET) { + ret = setsockopt(fd, IPPROTO_IP, IP_DONTFRAG, &val, sizeof(val)); + } else { +#if defined(IPV6_DONTFRAG) && defined(IPPROTO_IPV6) + ret = setsockopt(fd, IPPROTO_IPV6, IPV6_DONTFRAG, &val, sizeof(val)); +#else +#error CANNOT SET IPV6 SOCKET DF FLAG (1) +#endif + } + if(ret<0) { + int err=errno; + perror("set socket df:"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: set sockopt failed: fd=%d, err=%d, family=%d\n",__FUNCTION__,fd,err,family); + } + } +#elif defined(IPPROTO_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) && defined(IP_PMTUDISC_DONT) //LINUX + { + /* kernel sets DF bit on outgoing IP packets */ + if(family==AF_INET) { + int val=IP_PMTUDISC_DO; + if(!value) val=IP_PMTUDISC_DONT; + ret = setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val)); + } else { +#if defined(IPPROTO_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) && defined(IPV6_PMTUDISC_DONT) + int val=IPV6_PMTUDISC_DO; + if(!value) val=IPV6_PMTUDISC_DONT; + ret = setsockopt(fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &val, sizeof(val)); +#else +#error CANNOT SET IPV6 SOCKET DF FLAG (2) +#endif + } + if(ret<0) { + perror("set DF"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: set sockopt failed\n",__FUNCTION__); + } + } +#else +//CANNOT SET SOCKET DF FLAG (3) : UNKNOWN PLATFORM + UNUSED_ARG(fd); + UNUSED_ARG(family); + UNUSED_ARG(value); +#endif + + return ret; +} + +static int get_mtu_from_ssl(SSL* ssl) +{ + int ret = SOSO_MTU; +#if !defined(TURN_NO_DTLS) + if(ssl) + ret = BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); +#else + UNUSED_ARG(ssl); +#endif + return ret; +} + +static void set_query_mtu(SSL* ssl) { + if(ssl) { +#if defined(SSL_OP_NO_QUERY_MTU) + SSL_set_options(ssl, SSL_OP_NO_QUERY_MTU); +#else + ; +#endif + } +} + +int decrease_mtu(SSL* ssl, int mtu, int verbose) +{ + + if (!ssl) + return mtu; + + int new_mtu = get_mtu_from_ssl(ssl); + + if (new_mtu < 1) + new_mtu = mtu; + + if (new_mtu > MAX_MTU) + mtu = MAX_MTU; + if (new_mtu > 0 && new_mtu < MIN_MTU) + mtu = MIN_MTU; + else if (new_mtu < mtu) + mtu = new_mtu; + else + mtu -= MTU_STEP; + + if (mtu < MIN_MTU) + mtu = MIN_MTU; + + set_query_mtu(ssl); + if (verbose) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "1. mtu to use: %d\n", mtu); + +#if !defined(TURN_NO_DTLS) + SSL_set_mtu(ssl,mtu); + BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_SET_MTU, mtu, NULL); +#endif + + return mtu; +} + +int set_mtu_df(SSL* ssl, evutil_socket_t fd, int family, int mtu, int df_value, int verbose) { + + if(!ssl || fd<0) return 0; + + int ret=set_socket_df(fd, family, df_value); + + if(!mtu) mtu=SOSO_MTU; + else if(mtuMAX_MTU) mtu=MAX_MTU; + + set_query_mtu(ssl); + if(verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"3. mtu to use: %d\n",mtu); + +#if !defined(TURN_NO_DTLS) + + SSL_set_mtu(ssl,mtu); + + BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_SET_MTU, mtu, NULL); + +#endif + + if(verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"4. new mtu: %d\n",get_mtu_from_ssl(ssl)); + + return ret; +} + +int get_socket_mtu(evutil_socket_t fd, int family, int verbose) +{ + + int ret = 0; + + UNUSED_ARG(fd); + UNUSED_ARG(family); + UNUSED_ARG(verbose); + +#if defined(IP_MTU) + int val = 0; + socklen_t slen=sizeof(val); + if(family==AF_INET) { + ret = getsockopt(fd, IPPROTO_IP, IP_MTU, &val, &slen); + } else { +#if defined(IPPROTO_IPV6) && defined(IPV6_MTU) + ret = getsockopt(fd, IPPROTO_IPV6, IPV6_MTU, &val, &slen); +#endif + ; + } + + ret = val; +#endif + + if (verbose) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: final=%d\n", __FUNCTION__, ret); + + return ret; +} + +//////////////////// socket error handle //////////////////// + +int handle_socket_error() { + switch (errno) { + case EINTR: + /* Interrupted system call. + * Just ignore. + */ + return 1; + case ENOBUFS: + /* No buffers, temporary condition. + * Just ignore and try later. + */ + return 1; + case EAGAIN: +#if defined(EWOULDBLOCK) +#if (EWOULDBLOCK != EAGAIN) + case EWOULDBLOCK: +#endif +#endif + return 1; + case EMSGSIZE: + return 1; + case EBADF: + /* Invalid socket. + * Must close connection. + */ + return 0; + case EHOSTDOWN: + /* Host is down. + * Just ignore, might be an attacker + * sending fake ICMP messages. + */ + return 1; + case ECONNRESET: + case ECONNREFUSED: + /* Connection reset by peer. */ + return 0; + case ENOMEM: + /* Out of memory. + * Must close connection. + */ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Out of memory!\n"); + return 0; + case EACCES: + /* Permission denied. + * Just ignore, we might be blocked + * by some firewall policy. Try again + * and hope for the best. + */ + return 1; + default: + /* Something unexpected happened */ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Unexpected error! (errno = %d)\n", errno); + return 0; + } +} + +//////////////////// Misc utils ////////////////////////////// + +char *skip_blanks(char* s) +{ + while(*s==' ' || *s=='\t' || *s=='\n') + ++s; + + return s; +} + +//////////////////// Config file search ////////////////////// + +#define Q(x) #x +#define QUOTE(x) Q(x) + +#define ETCDIR INSTALL_PREFIX/etc/ +#define QETCDIR QUOTE(ETCDIR) + +#define ETCDIR1 INSTALL_PREFIX/etc/turnserver/ +#define QETCDIR1 QUOTE(ETCDIR1) + +#define ETCDIR2 INSTALL_PREFIX/etc/coturn/ +#define QETCDIR2 QUOTE(ETCDIR2) + +static const char *config_file_search_dirs[] = {"./", "./turnserver/", "./coturn/", "./etc/", "./etc/turnserver/", "./etc/coturn/", "../etc/", "../etc/turnserver/", "../etc/coturn/", "/etc/", "/etc/turnserver/", "/etc/coturn/", "/usr/local/etc/", "/usr/local/etc/turnserver/", "/usr/local/etc/coturn/", QETCDIR, QETCDIR1, QETCDIR2, NULL }; +static char *c_execdir=NULL; + +void set_execdir(void) +{ + /* On some systems, this may give us the execution path */ + char *_var = getenv("_"); + if(_var && *_var) { + _var = strdup(_var); + char *edir=_var; + if(edir[0]!='.') + edir = strstr(edir,"/"); + if(edir && *edir) + edir = dirname(edir); + else + edir = dirname(_var); + if(c_execdir) + turn_free(c_execdir,strlen(c_execdir)+1); + c_execdir = strdup(edir); + turn_free(_var,strlen(_var)+1); + } +} + +void print_abs_file_name(const char *msg1, const char *msg2, const char *fn) +{ + char absfn[1025]; + absfn[0]=0; + + if(fn) { + while(fn[0] && fn[0]==' ') ++fn; + if(fn[0]) { + if(fn[0]=='/') { + STRCPY(absfn,fn); + } else { + if(fn[0]=='.' && fn[1]=='/') + fn+=2; + if(!getcwd(absfn,sizeof(absfn)-1)) + absfn[0]=0; + size_t blen=strlen(absfn); + if(blen0)) { + rlim.rlim_cur = rlim.rlim_cur>>1; + } + return (unsigned long)rlim.rlim_cur; + } + } + + return 0; +} + +////////////////////// Base 64 //////////////////////////// + +static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/'}; +static char *decoding_table = NULL; +static size_t mod_table[] = {0, 2, 1}; + +char *base64_encode(const unsigned char *data, + size_t input_length, + size_t *output_length) { + + *output_length = 4 * ((input_length + 2) / 3); + + char *encoded_data = (char*)turn_malloc(*output_length+1); + if (encoded_data == NULL) return NULL; + + size_t i,j; + for (i = 0, j = 0; i < input_length;) { + + u32bits octet_a = i < input_length ? data[i++] : 0; + u32bits octet_b = i < input_length ? data[i++] : 0; + u32bits octet_c = i < input_length ? data[i++] : 0; + + u32bits triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; + + encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F]; + encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F]; + encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F]; + encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F]; + } + + for (i = 0; i < mod_table[input_length % 3]; i++) + encoded_data[*output_length - 1 - i] = '='; + + encoded_data[*output_length]=0; + + return encoded_data; +} + +void build_base64_decoding_table() { + + decoding_table = (char*)turn_malloc(256); + ns_bzero(decoding_table,256); + + int i; + for (i = 0; i < 64; i++) + decoding_table[(unsigned char) encoding_table[i]] = (char)i; +} + +unsigned char *base64_decode(const char *data, + size_t input_length, + size_t *output_length) { + + if (decoding_table == NULL) build_base64_decoding_table(); + + if (input_length % 4 != 0) return NULL; + + *output_length = input_length / 4 * 3; + if (data[input_length - 1] == '=') (*output_length)--; + if (data[input_length - 2] == '=') (*output_length)--; + + unsigned char *decoded_data = (unsigned char*)turn_malloc(*output_length); + if (decoded_data == NULL) return NULL; + + int i; + size_t j; + for (i = 0, j = 0; i < (int)input_length;) { + + uint32_t sextet_a = + data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]]; + uint32_t sextet_b = + data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]]; + uint32_t sextet_c = + data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]]; + uint32_t sextet_d = + data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]]; + + uint32_t triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + + (sextet_c << 1 * 6) + (sextet_d << 0 * 6); + + if (j < *output_length) + decoded_data[j++] = (triple >> 2 * 8) & 0xFF; + if (j < *output_length) + decoded_data[j++] = (triple >> 1 * 8) & 0xFF; + if (j < *output_length) + decoded_data[j++] = (triple >> 0 * 8) & 0xFF; + + } + + return decoded_data; +} + +////////////////// SSL ///////////////////// + +static const char* turn_get_method(const SSL_METHOD *method, const char* mdefault) +{ + { + if(!method) + 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()) { + return "SSLv3"; + } else if(method == SSLv23_server_method()) { + return "SSLv23"; + } else if(method == SSLv23_client_method()) { + return "SSLv23"; + } else if(method == TLSv1_server_method()) { + return "TLSv1.0"; + } else if(method == TLSv1_client_method()) { + return "TLSv1.0"; +#if defined(SSL_TXT_TLSV1_1) + } else if(method == TLSv1_1_server_method()) { + return "TLSv1.1"; + } else if(method == TLSv1_1_client_method()) { + return "TLSv1.1"; +#if defined(SSL_TXT_TLSV1_2) + } else if(method == TLSv1_2_server_method()) { + return "TLSv1.2"; + } else if(method == TLSv1_2_client_method()) { + return "TLSv1.2"; +#endif +#endif +#if !defined(TURN_NO_DTLS) + } else if(method == DTLSv1_server_method()) { + return "DTLSv1.0"; + } else if(method == DTLSv1_client_method()) { + return "DTLSv1.0"; +#endif + } else { + if(mdefault) + return mdefault; + return "UNKNOWN"; + } + } + } + +} + +const char* turn_get_ssl_method(SSL *ssl, const char* mdefault) +{ + if(!ssl) + return mdefault; + else { + const SSL_METHOD *method = SSL_get_ssl_method(ssl); + if(!method) + return mdefault; + else + return turn_get_method(method, mdefault); + } +} + +//////////// EVENT BASE /////////////// + +struct event_base *turn_event_base_new(void) +{ + struct event_config *cfg = event_config_new(); + + event_config_set_flag(cfg,EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST); + + return event_base_new_with_config(cfg); +} + +////////////////////////////////////////////////////////////// diff --git a/src/apps/common/apputils.h b/src/apps/common/apputils.h new file mode 100644 index 00000000..21815c4c --- /dev/null +++ b/src/apps/common/apputils.h @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2011, 2012, 2013 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 __APP_LIB__ +#define __APP_LIB__ + +#include + +#include + +#include "ns_turn_ioaddr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//////////// Common defines /////////////////////////// + +#define PEER_DEFAULT_PORT (3480) + +#define DTLS_MAX_RECV_TIMEOUT (5) + +#define UR_CLIENT_SOCK_BUF_SIZE (65536) +#define UR_SERVER_SOCK_BUF_SIZE (UR_CLIENT_SOCK_BUF_SIZE * 32) + +extern int IS_TURN_SERVER; + +/////////// SSL ////////////////////////// + +enum _TURN_TLS_TYPE { + TURN_TLS_NO=0, + TURN_TLS_SSL23, + TURN_TLS_v1_0, +#if defined(SSL_TXT_TLSV1_1) + TURN_TLS_v1_1, +#if defined(SSL_TXT_TLSV1_2) + TURN_TLS_v1_2, +#endif +#endif + TURN_TLS_TOTAL +}; + +typedef enum _TURN_TLS_TYPE TURN_TLS_TYPE; + +////////////////////////////////////////// + +#define EVENT_DEL(ev) if(ev) { event_del(ev); event_free(ev); ev=NULL; } + +////////////////////////////////////////// + +#define ioa_socket_raw int + +///////////////////////// Sockets /////////////////////////////// + +#if defined(WIN32) +/** Do the platform-specific call needed to close a socket returned from + socket() or accept(). */ +#define socket_closesocket(s) closesocket(s) +#else +/** Do the platform-specific call needed to close a socket returned from + socket() or accept(). */ +#define socket_closesocket(s) close(s) +#endif + +void read_spare_buffer(evutil_socket_t fd); + +int set_sock_buf_size(evutil_socket_t fd, int sz); + +int socket_set_reusable(evutil_socket_t fd, int reusable); +int sock_bind_to_device(evutil_socket_t fd, const unsigned char* ifname); +int socket_set_nonblocking(evutil_socket_t fd); +int socket_tcp_set_keepalive(evutil_socket_t fd); + +int addr_connect(evutil_socket_t fd, const ioa_addr* addr, int *out_errno); + +int addr_bind(evutil_socket_t fd, const ioa_addr* addr, int reusable); + +int addr_get_from_sock(evutil_socket_t fd, ioa_addr *addr); + +int handle_socket_error(void); + +/////////////////////// SYS ///////////////////// + +void ignore_sigpipe(void); +unsigned long set_system_parameters(int max_resources); + +///////////////////////// MTU ////////////////////////// + +#define MAX_MTU (1500 - 20 - 8) +#define MIN_MTU (576 - 20 - 8) +#define SOSO_MTU (1300) + +#define MTU_STEP (68) + +int set_socket_df(evutil_socket_t fd, int family, int value); +int set_mtu_df(SSL* ssl, evutil_socket_t fd, int family, int mtu, int df_value, int verbose); +int decrease_mtu(SSL* ssl, int mtu, int verbose); +int get_socket_mtu(evutil_socket_t fd, int family, int verbose); + +////////////////// Misc utils ///////////////////////// + +char *skip_blanks(char* s); + +////////////////// File search //////////////////////// + +char* find_config_file(const char *config_file, int print_file_name); +void set_execdir(void); +void print_abs_file_name(const char *msg1, const char *msg2, const char *fn); + +////////////////// Base64 ///////////////////////////// + +char *base64_encode(const unsigned char *data, + size_t input_length, + size_t *output_length); + +void build_base64_decoding_table(void); + +unsigned char *base64_decode(const char *data, + size_t input_length, + size_t *output_length); + +///////////// SSL //////////////// + +const char* turn_get_ssl_method(SSL *ssl, const char* mdefault); + +//////////// Event Base ///////////////////// + +struct event_base *turn_event_base_new(void); + +/////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__APP_LIB__ diff --git a/src/apps/common/hiredis_libevent2.c b/src/apps/common/hiredis_libevent2.c new file mode 100644 index 00000000..2b6837eb --- /dev/null +++ b/src/apps/common/hiredis_libevent2.c @@ -0,0 +1,383 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include +#include + +#if !defined(TURN_NO_HIREDIS) + +#include "hiredis_libevent2.h" +#include "ns_turn_utils.h" + +#include +#include + +#include +#include + +//////////////// Libevent context /////////////////////// + +struct redisLibeventEvents +{ + redisAsyncContext *context; + int invalid; + int allocated; + struct event_base *base; + struct event *rev, *wev; + int rev_set, wev_set; + char *ip; + int port; + char *pwd; + int db; +}; + +///////////// Messages //////////////////////////// + +struct redis_message +{ + char format[513]; + char arg[513]; +}; + +/////////////////// forward declarations /////////////// + +static void redis_reconnect(struct redisLibeventEvents *e); + +////////////////////////////////////////////////////////// + +static int redis_le_valid(struct redisLibeventEvents *e) +{ + return (e && !(e->invalid) && (e->context)); +} + +/////////////////// Callbacks //////////////////////////// + +static void redisLibeventReadEvent(int fd, short event, void *arg) { + ((void)fd); ((void)event); + struct redisLibeventEvents *e = (struct redisLibeventEvents*)arg; + if(redis_le_valid(e)) { + { + char buf[8]; + int len = 0; + do { + len = recv(fd,buf,sizeof(buf),MSG_PEEK); + } while((len<0)&&(errno == EINTR)); + if(len<1) { + e->invalid = 1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis connection broken: e=0x%lx\n", __FUNCTION__, (unsigned long)e); + } + } + if(redis_le_valid(e)) { + redisAsyncHandleRead(e->context); + } + } +} + +static void redisLibeventWriteEvent(int fd, short event, void *arg) { + ((void)fd); ((void)event); + struct redisLibeventEvents *e = (struct redisLibeventEvents*)arg; + if(redis_le_valid(e)) { + redisAsyncHandleWrite(e->context); + } +} + +static void redisLibeventAddRead(void *privdata) { + struct redisLibeventEvents *e = (struct redisLibeventEvents*)privdata; + if(e && (e->rev) && !(e->rev_set)) { + event_add(e->rev,NULL); + e->rev_set = 1; + } +} + +static void redisLibeventDelRead(void *privdata) { + struct redisLibeventEvents *e = (struct redisLibeventEvents*)privdata; + if(e && e->rev && e->rev_set) { + event_del(e->rev); + e->rev_set = 0; + } +} + +static void redisLibeventAddWrite(void *privdata) { + struct redisLibeventEvents *e = (struct redisLibeventEvents*)privdata; + if(e && (e->wev) && !(e->wev_set)) { + event_add(e->wev,NULL); + e->wev_set = 1; + } +} + +static void redisLibeventDelWrite(void *privdata) { + struct redisLibeventEvents *e = (struct redisLibeventEvents*)privdata; + if(e && e->wev && e->wev_set) { + event_del(e->wev); + e->wev_set = 0; + } +} + +static void redisLibeventCleanup(void *privdata) +{ + + if (privdata) { + + struct redisLibeventEvents *e = (struct redisLibeventEvents *) privdata; + if (e->allocated) { + if (e->rev) { + if(e->rev_set) + event_del(e->rev); + event_free(e->rev); + e->rev = NULL; + } + e->rev_set = 0; + if (e->wev) { + if(e->wev_set) + event_del(e->wev); + event_free(e->wev); + e->wev = NULL; + } + e->wev_set = 0; + e->context = NULL; + } + } +} + +///////////////////////// Send-receive /////////////////////////// + +void redis_async_init(void) +{ + ; +} + +int is_redis_asyncconn_good(redis_context_handle rch) +{ + if(rch) { + struct redisLibeventEvents *e = (struct redisLibeventEvents*)rch; + if(redis_le_valid(e)) + return 1; + } + return 0; +} + +void send_message_to_redis(redis_context_handle rch, const char *command, const char *key, const char *format,...) +{ + if(!rch) { + return; + } else { + + struct redisLibeventEvents *e = (struct redisLibeventEvents*)rch; + + if(!redis_le_valid(e)) { + redis_reconnect(e); + } + + if(!redis_le_valid(e)) { + ; + } else { + + redisAsyncContext *ac=e->context; + + struct redis_message rm; + + snprintf(rm.format,sizeof(rm.format)-3,"%s %s ", command, key); + strcpy(rm.format+strlen(rm.format),"%s"); + + va_list args; + va_start (args, format); + vsnprintf(rm.arg, sizeof(rm.arg)-1, format, args); + va_end (args); + + if((redisAsyncCommand(ac, NULL, e, rm.format, rm.arg)!=REDIS_OK)) { + e->invalid = 1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis connection broken: ac=0x%lx, e=0x%x\n", __FUNCTION__,(unsigned long)ac,(unsigned long)e); + } + } + } +} + +///////////////////////// Attach ///////////////////////////////// + +redis_context_handle redisLibeventAttach(struct event_base *base, char *ip0, int port0, char *pwd, int db) +{ + + struct redisLibeventEvents *e = NULL; + redisAsyncContext *ac = NULL; + + char ip[256]; + if(ip0 && ip0[0]) + STRCPY(ip,ip0); + else + STRCPY(ip,"127.0.0.1"); + + int port = DEFAULT_REDIS_PORT; + if(port0>0) + port=port0; + + ac = redisAsyncConnect(ip, port); + if (!ac) { + fprintf(stderr,"Error: %s:%s\n", ac->errstr, ac->c.errstr); + return NULL; + } + + /* Create container for context and r/w events */ + e = (struct redisLibeventEvents*)turn_malloc(sizeof(struct redisLibeventEvents)); + ns_bzero(e,sizeof(struct redisLibeventEvents)); + + e->allocated = 1; + e->context = ac; + e->base = base; + e->ip = strdup(ip); + e->port = port; + if(pwd) + e->pwd = strdup(pwd); + e->db = db; + + /* Register functions to start/stop listening for events */ + ac->ev.addRead = redisLibeventAddRead; + ac->ev.delRead = redisLibeventDelRead; + ac->ev.addWrite = redisLibeventAddWrite; + ac->ev.delWrite = redisLibeventDelWrite; + ac->ev.cleanup = redisLibeventCleanup; + + ac->ev.data = e; + + /* Initialize and install read/write events */ + e->rev = event_new(e->base,e->context->c.fd, + EV_READ,redisLibeventReadEvent, + e); + + e->wev = event_new(e->base,e->context->c.fd, + EV_WRITE,redisLibeventWriteEvent, + e); + + if (e->rev == NULL || e->wev == NULL) { + turn_free(e, sizeof(struct redisLibeventEvents)); + return NULL; + } + + event_add(e->wev, NULL); + e->wev_set = 1; + + //Authentication + if(redis_le_valid(e) && pwd) { + if(redisAsyncCommand(ac, NULL, e, "AUTH %s", pwd)!=REDIS_OK) { + e->invalid = 1; + } + } + + if(redis_le_valid(e)) { + if(redisAsyncCommand(ac, NULL, e, "SELECT %d", db)!=REDIS_OK) { + e->invalid = 1; + } + } + + return (redis_context_handle)e; +} + +static void redis_reconnect(struct redisLibeventEvents *e) +{ + if(!e || !(e->allocated)) + return; + + if (e->rev) { + if(e->rev_set) + event_del(e->rev); + event_free(e->rev); + e->rev = NULL; + } + e->rev_set = 0; + + if (e->wev) { + if(e->wev_set) + event_del(e->wev); + event_free(e->wev); + e->wev = NULL; + } + e->wev_set = 0; + + redisAsyncContext *ac = NULL; + + if(e->context) { + e->context = NULL; + } + + ac = redisAsyncConnect(e->ip, e->port); + if(!ac) { + return; + } + + e->context = ac; + + /* Register functions to start/stop listening for events */ + ac->ev.addRead = redisLibeventAddRead; + ac->ev.delRead = redisLibeventDelRead; + ac->ev.addWrite = redisLibeventAddWrite; + ac->ev.delWrite = redisLibeventDelWrite; + ac->ev.cleanup = redisLibeventCleanup; + + ac->ev.data = e; + + /* Initialize and install read/write events */ + e->rev = event_new(e->base,e->context->c.fd, + EV_READ,redisLibeventReadEvent, + e); + + e->wev = event_new(e->base,e->context->c.fd, + EV_WRITE,redisLibeventWriteEvent, + e); + + if (e->rev == NULL || e->wev == NULL) { + return; + } + + event_add(e->wev, NULL); + e->wev_set = 1; + e->invalid = 0; + + //Authentication + if(redis_le_valid(e) && e->pwd) { + if(redisAsyncCommand(ac, NULL, e, "AUTH %s", e->pwd)!=REDIS_OK) { + e->invalid = 1; + } + } + + if(redis_le_valid(e)) { + if(redisAsyncCommand(ac, NULL, e, "SELECT %d", e->db)!=REDIS_OK) { + e->invalid = 1; + } + } + + if(redis_le_valid(e)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Re-connected to redis, async\n", __FUNCTION__); + } +} + +///////////////////////////////////////////////////////// + +#endif +/* TURN_NO_HIREDIS */ + diff --git a/src/apps/common/hiredis_libevent2.h b/src/apps/common/hiredis_libevent2.h new file mode 100644 index 00000000..54d8864f --- /dev/null +++ b/src/apps/common/hiredis_libevent2.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2011, 2012, 2013 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 __HIREDIS_LIBEVENT_H__ + +#define __HIREDIS_LIBEVENT_H__ + +#if !defined(TURN_NO_HIREDIS) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////////////// + +#define DEFAULT_REDIS_PORT (6379) + +typedef void* redis_context_handle; + +////////////////////////////////////// + +void redis_async_init(void); + +redis_context_handle redisLibeventAttach(struct event_base *base, char *ip, int port, char *pwd, int db); + +void send_message_to_redis(redis_context_handle rch, const char *command, const char *key, const char *format,...); + +int is_redis_asyncconn_good(redis_context_handle rch); + +#ifdef __cplusplus +} +#endif + +#endif +/* TURN_NO_HIREDIS */ + +#endif +/*__HIREDIS_LIBEVENT_H__*/ diff --git a/src/apps/common/ns_turn_utils.c b/src/apps/common/ns_turn_utils.c new file mode 100644 index 00000000..652d2006 --- /dev/null +++ b/src/apps/common/ns_turn_utils.c @@ -0,0 +1,643 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "ns_turn_utils.h" +#include "ns_turn_ioalib.h" +#include "ns_turn_msg_defs.h" + +#include + +#include + +#include +#include + +#include +#include + +////////// LOG TIME OPTIMIZATION /////////// + +static volatile turn_time_t log_start_time = 0; +volatile int _log_time_value_set = 0; +volatile turn_time_t _log_time_value = 0; + +static inline turn_time_t log_time(void) +{ + if(!log_start_time) + log_start_time = turn_time(); + + if(_log_time_value_set) + return (_log_time_value - log_start_time); + + return (turn_time() - log_start_time); +} + +////////// MUTEXES ///////////// + +#define MAGIC_CODE (0xEFCD1983) + +int turn_mutex_lock(const turn_mutex *mutex) { + if(mutex && mutex->mutex && (mutex->data == MAGIC_CODE)) { + int ret = 0; + ret = pthread_mutex_lock((pthread_mutex_t*)mutex->mutex); + if(ret<0) { + perror("Mutex lock"); + } + return ret; + } else { + printf("Uninitialized mutex\n"); + return -1; + } +} + +int turn_mutex_unlock(const turn_mutex *mutex) { + if(mutex && mutex->mutex && (mutex->data == MAGIC_CODE)) { + int ret = 0; + ret = pthread_mutex_unlock((pthread_mutex_t*)mutex->mutex); + if(ret<0) { + perror("Mutex unlock"); + } + return ret; + } else { + printf("Uninitialized mutex\n"); + return -1; + } +} + +int turn_mutex_init(turn_mutex* mutex) { + if(mutex) { + mutex->data=MAGIC_CODE; + mutex->mutex=turn_malloc(sizeof(pthread_mutex_t)); + pthread_mutex_init((pthread_mutex_t*)mutex->mutex,NULL); + return 0; + } else { + return -1; + } +} + +int turn_mutex_init_recursive(turn_mutex* mutex) { + int ret = -1; + if (mutex) { + pthread_mutexattr_t attr; + if (pthread_mutexattr_init(&attr) < 0) { + perror("Cannot init mutex attr"); + } else { + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) < 0) { + perror("Cannot set type on mutex attr"); + } else { + mutex->mutex = turn_malloc(sizeof(pthread_mutex_t)); + mutex->data = MAGIC_CODE; + if ((ret = pthread_mutex_init((pthread_mutex_t*) mutex->mutex, + &attr)) < 0) { + perror("Cannot init mutex"); + mutex->data = 0; + turn_free(mutex->mutex,sizeof(pthread_mutex_t)); + mutex->mutex = NULL; + } + } + pthread_mutexattr_destroy(&attr); + } + } + return ret; +} + +int turn_mutex_destroy(turn_mutex* mutex) { + if(mutex && mutex->mutex && mutex->data == MAGIC_CODE) { + int ret = 0; + ret = pthread_mutex_destroy((pthread_mutex_t*)(mutex->mutex)); + turn_free(mutex->mutex, sizeof(pthread_mutex_t)); + mutex->mutex=NULL; + mutex->data=0; + return ret; + } else { + return 0; + } +} + +///////////////////////// LOG /////////////////////////////////// + +#if defined(TURN_LOG_FUNC_IMPL) +extern void TURN_LOG_FUNC_IMPL(TURN_LOG_LEVEL level, const s08bits* format, va_list args); +#endif + +static int no_stdout_log = 0; + +void set_no_stdout_log(int val) +{ + no_stdout_log = val; +} + +void turn_log_func_default(TURN_LOG_LEVEL level, const s08bits* format, ...) +{ +#if !defined(TURN_LOG_FUNC_IMPL) + { + va_list args; + va_start(args,format); + vrtpprintf(level, format, args); + va_end(args); + } +#endif + + { + va_list args; + va_start(args,format); +#if defined(TURN_LOG_FUNC_IMPL) + TURN_LOG_FUNC_IMPL(level,format,args); +#else +#define MAX_RTPPRINTF_BUFFER_SIZE (1024) + char s[MAX_RTPPRINTF_BUFFER_SIZE+1]; +#undef MAX_RTPPRINTF_BUFFER_SIZE + if (level == TURN_LOG_LEVEL_ERROR) { + snprintf(s,sizeof(s)-100,"%lu: ERROR: ",(unsigned long)log_time()); + size_t slen = strlen(s); + vsnprintf(s+slen,sizeof(s)-slen-1,format, args); + fwrite(s,strlen(s),1,stdout); + } else if(!no_stdout_log) { + snprintf(s,sizeof(s)-100,"%lu: ",(unsigned long)log_time()); + size_t slen = strlen(s); + vsnprintf(s+slen,sizeof(s)-slen-1,format, args); + fwrite(s,strlen(s),1,stdout); + } +#endif + va_end(args); + } +} + +void addr_debug_print(int verbose, const ioa_addr *addr, const s08bits* s) +{ + if (verbose) { + if (!addr) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: EMPTY\n", s); + } else { + s08bits addrbuf[INET6_ADDRSTRLEN]; + if (!s) + s = ""; + if (addr->ss.sa_family == AF_INET) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "IPv4. %s: %s:%d\n", s, inet_ntop(AF_INET, + &addr->s4.sin_addr, addrbuf, INET6_ADDRSTRLEN), + nswap16(addr->s4.sin_port)); + } else if (addr->ss.sa_family == AF_INET6) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "IPv6. %s: %s:%d\n", s, inet_ntop(AF_INET6, + &addr->s6.sin6_addr, addrbuf, INET6_ADDRSTRLEN), + nswap16(addr->s6.sin6_port)); + } else { + if (addr_any_no_port(addr)) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_INFO, + "IP. %s: 0.0.0.0:%d\n", + s, + nswap16(addr->s4.sin_port)); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: wrong IP address family: %d\n", s, + (int) (addr->ss.sa_family)); + } + } + } + } +} + +/*************************************/ + +#define FILE_STR_LEN (1025) + +static FILE* _rtpfile = NULL; +static int to_syslog = 0; +static int simple_log = 0; +static char log_fn[FILE_STR_LEN]="\0"; +static char log_fn_base[FILE_STR_LEN]="\0"; + +static turn_mutex log_mutex; +static int log_mutex_inited = 0; + +static void log_lock(void) { + if(!log_mutex_inited) { + log_mutex_inited=1; + turn_mutex_init_recursive(&log_mutex); + } + turn_mutex_lock(&log_mutex); +} + +static void log_unlock(void) { + turn_mutex_unlock(&log_mutex); +} + +static void get_date(char *s, size_t sz) { + time_t curtm; + struct tm* tm_info; + + curtm = time(NULL); + tm_info = localtime(&curtm); + + strftime(s, sz, "%F", tm_info); +} + +void set_logfile(const char *fn) +{ + if(fn) { + log_lock(); + if(strcmp(fn,log_fn_base)) { + reset_rtpprintf(); + STRCPY(log_fn_base,fn); + } + log_unlock(); + } +} + +void reset_rtpprintf(void) +{ + log_lock(); + if(_rtpfile) { + if(_rtpfile != stdout) + fclose(_rtpfile); + _rtpfile = NULL; + } + log_unlock(); +} + +static void set_log_file_name(char *base, char *f) +{ + if(simple_log) { + STRCPY(f,base); + return; + } + + char logdate[125]; + char *tail=strdup(".log"); + + get_date(logdate,sizeof(logdate)); + + char *base1=strdup(base); + + int len=(int)strlen(base1); + + --len; + + while(len>=0) { + if((base1[len]==' ')||(base1[len]=='\t')) { + base1[len]='_'; + } + --len; + } + + len=(int)strlen(base1); + + while(len>=0) { + if(base1[len]=='/') + break; + else if(base1[len]=='.') { + turn_free(tail,strlen(tail)+1); + tail=strdup(base1+len); + base1[len]=0; + if(strlen(tail)<2) { + turn_free(tail,strlen(tail)+1); + tail = strdup(".log"); + } + break; + } + --len; + } + + len=(int)strlen(base1); + if(len>0 && (base1[len-1]!='/') && (base1[len-1]!='-') && (base1[len-1]!='_')) { + snprintf(f, FILE_STR_LEN, "%s_%s%s", base1,logdate,tail); + } else { + snprintf(f, FILE_STR_LEN, "%s%s%s", base1,logdate,tail); + } + + turn_free(base1,strlen(base1)+1); + turn_free(tail,strlen(tail)+1); +} + +static void set_rtpfile(void) +{ + if(to_syslog) { + return; + } else if (!_rtpfile) { + if(log_fn_base[0]) { + if(!strcmp(log_fn_base,"syslog")) { + _rtpfile = stdout; + to_syslog = 1; + } else if(!strcmp(log_fn_base,"stdout")|| !strcmp(log_fn_base,"-")) { + _rtpfile = stdout; + no_stdout_log = 1; + } else { + set_log_file_name(log_fn_base,log_fn); + _rtpfile = fopen(log_fn, "w"); + if(_rtpfile) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "log file opened: %s\n", log_fn); + } + if (!_rtpfile) { + fprintf(stderr,"ERROR: Cannot open log file for writing: %s\n",log_fn); + } else { + return; + } + } + } + + if(!_rtpfile) { + + char logbase[FILE_STR_LEN]; + char logtail[FILE_STR_LEN]; + char logf[FILE_STR_LEN]; + + if(simple_log) + snprintf(logtail, FILE_STR_LEN, "turn.log"); + else + snprintf(logtail, FILE_STR_LEN, "turn_%d_", (int)getpid()); + + snprintf(logbase, FILE_STR_LEN, "/var/log/turnserver/%s", logtail); + + set_log_file_name(logbase, logf); + + _rtpfile = fopen(logf, "w"); + if(_rtpfile) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "log file opened: %s\n", logf); + else { + snprintf(logbase, FILE_STR_LEN, "/var/log/%s", logtail); + + set_log_file_name(logbase, logf); + _rtpfile = fopen(logf, "w"); + if(_rtpfile) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "log file opened: %s\n", logf); + else { + snprintf(logbase, FILE_STR_LEN, "/var/tmp/%s", logtail); + set_log_file_name(logbase, logf); + _rtpfile = fopen(logf, "w"); + if(_rtpfile) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "log file opened: %s\n", logf); + else { + snprintf(logbase, FILE_STR_LEN, "/tmp/%s", logtail); + set_log_file_name(logbase, logf); + _rtpfile = fopen(logf, "w"); + if(_rtpfile) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "log file opened: %s\n", logf); + else { + snprintf(logbase, FILE_STR_LEN, "%s", logtail); + set_log_file_name(logbase, logf); + _rtpfile = fopen(logf, "w"); + if(_rtpfile) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "log file opened: %s\n", logf); + else { + _rtpfile = stdout; + return; + } + } + } + } + } + + STRCPY(log_fn_base,logbase); + STRCPY(log_fn,logf); + } +} + +void set_log_to_syslog(int val) +{ + to_syslog = val; +} + +void set_simple_log(int val) +{ + simple_log = val; +} + +#define Q(x) #x +#define QUOTE(x) Q(x) + +void rollover_logfile(void) +{ + if(to_syslog || !(log_fn[0])) + return; + + { + FILE *f = fopen(log_fn,"r"); + if(!f) { + fprintf(stderr, "log file is damaged\n"); + reset_rtpprintf(); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "log file reopened: %s\n", log_fn); + return; + } else { + fclose(f); + } + } + + if(simple_log) + return; + + log_lock(); + if(_rtpfile && log_fn[0] && (_rtpfile != stdout)) { + char logf[FILE_STR_LEN]; + + set_log_file_name(log_fn_base,logf); + if(strcmp(log_fn,logf)) { + fclose(_rtpfile); + log_fn[0]=0; + _rtpfile = fopen(logf, "w"); + if(_rtpfile) { + STRCPY(log_fn,logf); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "log file opened: %s\n", log_fn); + } else { + _rtpfile = stdout; + } + } + } + log_unlock(); +} + +static int get_syslog_level(TURN_LOG_LEVEL level) +{ + switch(level) { + case TURN_LOG_LEVEL_CONTROL: + return LOG_NOTICE; + case TURN_LOG_LEVEL_WARNING: + return LOG_WARNING; + case TURN_LOG_LEVEL_ERROR: + return LOG_ERR; + default: + ; + }; + return LOG_INFO; +} + +int vrtpprintf(TURN_LOG_LEVEL level, const char *format, va_list args) +{ + /* Fix for Issue 24, raised by John Selbie: */ +#define MAX_RTPPRINTF_BUFFER_SIZE (1024) + char s[MAX_RTPPRINTF_BUFFER_SIZE+1]; +#undef MAX_RTPPRINTF_BUFFER_SIZE + + size_t sz; + + snprintf(s, sizeof(s), "%lu: ",(unsigned long)log_time()); + sz=strlen(s); + vsnprintf(s+sz, sizeof(s)-1-sz, format, args); + s[sizeof(s)-1]=0; + + if(to_syslog) { + syslog(get_syslog_level(level),"%s",s); + } else { + log_lock(); + set_rtpfile(); + if(fprintf(_rtpfile,"%s",s)<0) { + reset_rtpprintf(); + } else if(fflush(_rtpfile)<0) { + reset_rtpprintf(); + } + log_unlock(); + } + + return 0; +} + +void rtpprintf(const char *format, ...) +{ + va_list args; + va_start (args, format); + vrtpprintf(TURN_LOG_LEVEL_INFO, format, args); + va_end (args); +} + +///////////// ORIGIN /////////////////// + +int get_default_protocol_port(const char* scheme, size_t slen) +{ + if(scheme && (slen>0)) { + switch(slen) { + case 3: + if(!memcmp("ftp",scheme,3)) + return 21; + if(!memcmp("svn",scheme,3)) + return 3690; + if(!memcmp("ssh",scheme,4)) + return 22; + if(!memcmp("sip",scheme,3)) + return 5060; + break; + case 4: + if(!memcmp("http",scheme,4)) + return 80; + if(!memcmp("ldap",scheme,4)) + return 389; + if(!memcmp("sips",scheme,4)) + return 5061; + if(!memcmp("turn",scheme,4)) + return 3478; + if(!memcmp("stun",scheme,4)) + return 3478; + break; + case 5: + if(!memcmp("https",scheme,5)) + return 443; + if(!memcmp("ldaps",scheme,5)) + return 636; + if(!memcmp("turns",scheme,5)) + return 5349; + if(!memcmp("stuns",scheme,5)) + return 5349; + break; + case 6: + if(!memcmp("telnet",scheme,6)) + return 23; + if(!memcmp("radius",scheme,6)) + return 1645; + break; + case 7: + if(!memcmp("svn+ssh",scheme,7)) + return 22; + break; + default: + return 0; + }; + } + return 0; +} + +int get_canonic_origin(const char* o, char *co, int sz) +{ + int ret = -1; + + if(o && o[0] && co) { + co[0]=0; + struct evhttp_uri *uri = evhttp_uri_parse(o); + if(uri) { + const char *scheme = evhttp_uri_get_scheme(uri); + if(scheme && scheme[0]) { + size_t schlen = strlen(scheme); + if((schlen<(size_t)sz) && (schlen0) + snprintf(otmp+schlen,sizeof(otmp)-schlen-1,"://%s:%d",host,port); + else + snprintf(otmp+schlen,sizeof(otmp)-schlen-1,"://%s",host); + + { + char *s = otmp + schlen + 3; + while(*s) { + *s = (char)tolower(*s); + ++s; + } + } + + strncpy(co,otmp,sz); + co[sz]=0; + ret = 0; + } + } + } + evhttp_uri_free(uri); + } + } + + if(ret<0) { + strncpy(co,o,sz); + co[sz]=0; + } + + return ret; +} + +////////////////////////////////////////////////////////////////// diff --git a/src/apps/common/ns_turn_utils.h b/src/apps/common/ns_turn_utils.h new file mode 100644 index 00000000..3b0a92e6 --- /dev/null +++ b/src/apps/common/ns_turn_utils.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2011, 2012, 2013 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_ULIB__ +#define __TURN_ULIB__ + +#if !defined(TURN_LOG_FUNC) +#define TURN_LOG_FUNC turn_log_func_default +#endif + +#include "ns_turn_ioaddr.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////// LOG ////////////////////////// + +typedef enum { + TURN_LOG_LEVEL_INFO = 0, + TURN_LOG_LEVEL_CONTROL, + TURN_LOG_LEVEL_WARNING, + TURN_LOG_LEVEL_ERROR +} TURN_LOG_LEVEL; + +#define TURN_VERBOSE_NONE (0) +#define TURN_VERBOSE_NORMAL (1) +#define TURN_VERBOSE_EXTRA (2) + +#define eve(v) ((v)==TURN_VERBOSE_EXTRA) + +void set_no_stdout_log(int val); +void set_log_to_syslog(int val); +void set_simple_log(int val); + +void turn_log_func_default(TURN_LOG_LEVEL level, const s08bits* format, ...); + +void addr_debug_print(int verbose, const ioa_addr *addr, const s08bits* s); + +/* Log */ + +extern volatile int _log_time_value_set; +extern volatile turn_time_t _log_time_value; + +void rtpprintf(const char *format, ...); +int vrtpprintf(TURN_LOG_LEVEL level, const char *format, va_list args); +void reset_rtpprintf(void); +void set_logfile(const char *fn); +void rollover_logfile(void); + +/////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__TURN_ULIB__ diff --git a/src/apps/common/stun_buffer.c b/src/apps/common/stun_buffer.c new file mode 100644 index 00000000..eac2fc01 --- /dev/null +++ b/src/apps/common/stun_buffer.c @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "stun_buffer.h" + +////////////////////// BUFFERS /////////////////////////// + +int stun_init_buffer(stun_buffer *buf) { + if(!buf) return -1; + ns_bzero(buf->buf,sizeof(buf->buf)); + buf->len=0; + buf->offset=0; + buf->coffset=0; + return 0; +} + +int stun_get_size(const stun_buffer *buf) { + if(!buf) return 0; + return sizeof(buf->buf); +} + +//////////////////////////////////////////////////////////// + +void stun_tid_from_message(const stun_buffer *buf, stun_tid* id) { + stun_tid_from_message_str(buf->buf,(size_t)(buf->len), id); +} + +void stun_tid_generate_in_message(stun_buffer* buf, stun_tid* id) { + if(buf) { + stun_tid_generate_in_message_str(buf->buf, id); + } +} + +//////////////////////////////////////////////////////// + +static inline int is_channel_msg(const stun_buffer* buf) { + if(buf && buf->len>0) { + return is_channel_msg_str(buf->buf, (size_t)(buf->len)); + } + return 0; +} + +int stun_is_command_message(const stun_buffer* buf) { + if(!buf || buf->len<=0) + return 0; + else + return stun_is_command_message_str(buf->buf,(size_t)(buf->len)); +} + +int stun_is_request(const stun_buffer* buf) { + return stun_is_request_str(buf->buf,(size_t)buf->len); +} + +int stun_is_success_response(const stun_buffer* buf) { + return stun_is_success_response_str(buf->buf, (size_t)(buf->len)); +} + +int stun_is_error_response(const stun_buffer* buf, int *err_code, u08bits *err_msg, size_t err_msg_size) { + return stun_is_error_response_str(buf->buf, (size_t)(buf->len), err_code, err_msg, err_msg_size); +} + +int stun_is_response(const stun_buffer* buf) { + return stun_is_response_str(buf->buf,(size_t)(buf->len)); +} + +int stun_is_indication(const stun_buffer* buf) { + if(is_channel_msg(buf)) return 0; + return IS_STUN_INDICATION(stun_get_msg_type(buf)); +} + +u16bits stun_get_method(const stun_buffer* buf) { + return stun_get_method_str(buf->buf, (size_t)(buf->len)); +} + +u16bits stun_get_msg_type(const stun_buffer* buf) { + if(!buf) return (u16bits)-1; + return stun_get_msg_type_str(buf->buf,(size_t)buf->len); +} + +//////////////////////////////////////////////////////////// + +static void stun_init_command(u16bits message_type, stun_buffer* buf) { + buf->len=stun_get_size(buf); + stun_init_command_str(message_type, buf->buf, (size_t*)(&(buf->len))); +} + +void stun_init_request(u16bits method, stun_buffer* buf) { + stun_init_command(stun_make_request(method), buf); +} + +void stun_init_indication(u16bits method, stun_buffer* buf) { + stun_init_command(stun_make_indication(method), buf); +} + +void stun_init_success_response(u16bits method, stun_buffer* buf, stun_tid* id) { + buf->len=stun_get_size(buf); + stun_init_success_response_str(method, buf->buf, (size_t*)(&(buf->len)), id); +} + +void stun_init_error_response(u16bits method, stun_buffer* buf, u16bits error_code, const u08bits *reason, stun_tid* id) { + buf->len=stun_get_size(buf); + stun_init_error_response_str(method, buf->buf, (size_t*)(&(buf->len)), error_code, reason, id); +} + +/////////////////////////////////////////////////////////////////////////////// + +int stun_get_command_message_len(const stun_buffer* buf) { + return stun_get_command_message_len_str(buf->buf, (size_t)(buf->len)); +} + +/////////////////////////////////////////////////////////////////////////////// + +int stun_init_channel_message(u16bits chnumber, stun_buffer* buf, int length, int do_padding) { + return stun_init_channel_message_str(chnumber, buf->buf, (size_t*)(&(buf->len)), length, do_padding); +} + +int stun_is_channel_message(stun_buffer* buf, u16bits* chnumber, int is_padding_mandatory) { + if(!buf) return 0; + size_t blen = (size_t)buf->len; + int ret = stun_is_channel_message_str(buf->buf, &blen, chnumber, is_padding_mandatory); + if(ret) { + buf->len=(ssize_t)blen; + } + return ret; +} + +/////////////////////////////////////////////////////////////////////////////// + +int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int address_family, u08bits transport, int mobile) { + return stun_set_allocate_request_str(buf->buf, (size_t*)(&(buf->len)), lifetime, address_family, transport, mobile); +} + +int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid, + const ioa_addr *relayed_addr, const ioa_addr *reflexive_addr, + u32bits lifetime, int error_code, const u08bits *reason, + u64bits reservation_token, char *mobile_id) { + + return stun_set_allocate_response_str(buf->buf, (size_t*)(&(buf->len)), tid, + relayed_addr, reflexive_addr, + lifetime, error_code, reason, + reservation_token, mobile_id); + +} + +/////////////////////////////////////////////////////////////////////////////// + +u16bits stun_set_channel_bind_request(stun_buffer* buf, + const ioa_addr* peer_addr, u16bits channel_number) { + + return stun_set_channel_bind_request_str(buf->buf,(size_t*)(&(buf->len)), peer_addr, channel_number); +} + +void stun_set_channel_bind_response(stun_buffer* buf, stun_tid* tid, int error_code, const u08bits *reason) { + stun_set_channel_bind_response_str(buf->buf, (size_t*)(&(buf->len)), tid, error_code, reason); +} + +//////////////////////////////////////////////////////////////// + +stun_attr_ref stun_attr_get_first(const stun_buffer* buf) { + return stun_attr_get_first_str(buf->buf, (size_t)(buf->len)); +} + +stun_attr_ref stun_attr_get_next(const stun_buffer* buf, stun_attr_ref prev) { + return stun_attr_get_next_str(buf->buf, (size_t)(buf->len), prev); +} + +int stun_attr_add(stun_buffer* buf, u16bits attr, const s08bits* avalue, int alen) { + return stun_attr_add_str(buf->buf, (size_t*)(&(buf->len)), attr, (const u08bits *)avalue, alen); +} + +int stun_attr_add_channel_number(stun_buffer* buf, u16bits chnumber) { + return stun_attr_add_channel_number_str(buf->buf, (size_t *)(&(buf->len)), chnumber); +} + +int stun_attr_add_addr(stun_buffer *buf,u16bits attr_type, const ioa_addr* ca) { + return stun_attr_add_addr_str(buf->buf,(size_t*)(&(buf->len)), attr_type, ca); +} + +int stun_attr_get_addr(const stun_buffer *buf, stun_attr_ref attr, ioa_addr* ca, + const ioa_addr *default_addr) { + + return stun_attr_get_addr_str(buf->buf, (size_t)(buf->len), attr, ca, default_addr); +} + +int stun_attr_get_first_addr(const stun_buffer *buf, u16bits attr_type, ioa_addr* ca, + const ioa_addr *default_addr) { + + return stun_attr_get_first_addr_str(buf->buf, (size_t)(buf->len), attr_type, ca, default_addr); +} + +int stun_attr_add_even_port(stun_buffer* buf, uint8_t value) { + if(value) value=0x80; + return stun_attr_add(buf,STUN_ATTRIBUTE_EVEN_PORT,(const s08bits*)&value,1); +} + +u16bits stun_attr_get_first_channel_number(const stun_buffer *buf) { + return stun_attr_get_first_channel_number_str(buf->buf, (size_t)(buf->len)); +} + +stun_attr_ref stun_attr_get_first_by_type(const stun_buffer* buf, u16bits attr_type) { + return stun_attr_get_first_by_type_str(buf->buf, (size_t)(buf->len), attr_type); +} + +/////////////////////////////////////////////////////////////////////////////// + +void stun_set_binding_request(stun_buffer* buf) { + stun_set_binding_request_str(buf->buf, (size_t*)(&(buf->len))); +} + +int stun_set_binding_response(stun_buffer* buf, stun_tid* tid, + const ioa_addr *reflexive_addr, int error_code, const u08bits *reason) { + return stun_set_binding_response_str(buf->buf, (size_t*)(&(buf->len)), tid, + reflexive_addr, error_code, reason, + 0,0); +} + +void stun_prepare_binding_request(stun_buffer* buf) { + stun_set_binding_request_str(buf->buf, (size_t*)(&(buf->len))); +} + +int stun_is_binding_response(const stun_buffer* buf) { + return stun_is_binding_response_str(buf->buf, (size_t)(buf->len)); +} + +/////////////////////////////////////////////////////// diff --git a/src/apps/common/stun_buffer.h b/src/apps/common/stun_buffer.h new file mode 100644 index 00000000..7a4e0fe5 --- /dev/null +++ b/src/apps/common/stun_buffer.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2011, 2012, 2013 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_STUN_BUF__ +#define __TURN_STUN_BUF__ + +#include "ns_turn_msg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////// + +typedef struct _stun_buffer { + u08bits channel[STUN_CHANNEL_HEADER_LENGTH]; + u08bits buf[STUN_BUFFER_SIZE]; + size_t len; + u16bits offset; + u08bits coffset; +} stun_buffer; + +////////////////////////////////////////////////////////////// + +int stun_init_buffer(stun_buffer *buf); +int stun_get_size(const stun_buffer *buf); + +////////////////////////////////////////////////////////////// + +void stun_tid_generate_in_message(stun_buffer* buf, stun_tid* id); +void stun_tid_from_message(const stun_buffer *buf, stun_tid* id); + +/////////////////////////////////////////////////////////////// + +int stun_is_command_message(const stun_buffer* buf); +int stun_is_request(const stun_buffer* buf); +int stun_is_response(const stun_buffer* buf); +int stun_is_success_response(const stun_buffer* buf); +int stun_is_error_response(const stun_buffer* buf, int *err_code, u08bits *err_msg, size_t err_msg_size); +int stun_is_indication(const stun_buffer* buf); +u16bits stun_get_method(const stun_buffer* buf); +u16bits stun_get_msg_type(const stun_buffer* buf); + +/////////////////////////////////////////////////////////////// + +void stun_init_request(u16bits method, stun_buffer* buf); +void stun_init_indication(u16bits method, stun_buffer* buf); +void stun_init_success_response(u16bits method, stun_buffer* buf, stun_tid* id); +void stun_init_error_response(u16bits method, stun_buffer* buf, u16bits error_code, const u08bits *reason, stun_tid* id); + +/////////////////////////////////////////////////////////////// + +int stun_attr_add(stun_buffer* buf, u16bits attr, const s08bits* avalue, int alen); +int stun_attr_add_channel_number(stun_buffer* buf, u16bits chnumber); +int stun_attr_add_addr(stun_buffer *buf,u16bits attr_type, const ioa_addr* ca); + +stun_attr_ref stun_attr_get_first(const stun_buffer* buf); +stun_attr_ref stun_attr_get_first_by_type(const stun_buffer* buf, u16bits attr_type); +stun_attr_ref stun_attr_get_next(const stun_buffer* buf, stun_attr_ref prev); +int stun_attr_get_addr(const stun_buffer *buf, stun_attr_ref attr, ioa_addr* ca, const ioa_addr *default_addr); +int stun_attr_add_even_port(stun_buffer* buf, uint8_t value); + +int stun_attr_get_first_addr(const stun_buffer *buf, u16bits attr_type, ioa_addr* ca, const ioa_addr *default_addr); +u16bits stun_attr_get_first_channel_number(const stun_buffer *buf); + +/////////////////////////////////////////////////////////////// + +int stun_get_command_message_len(const stun_buffer* buf); + +/////////////////////////////////////////////////////////////// + +int stun_init_channel_message(u16bits chnumber, stun_buffer* buf, int length, int do_padding); +int stun_is_channel_message(stun_buffer* buf, u16bits* chnumber, int is_padding_madatory); + +/////////////////////////////////////////////////////////////// + +int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int address_family, u08bits transport, int mobile); +int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid, + const ioa_addr *relayed_addr, const ioa_addr *reflexive_addr, + u32bits lifetime, + int error_code, const u08bits *reason, + u64bits reservation_token, char *mobile_id); + +/////////////////////////////////////////////////////////////// + +void stun_set_binding_request(stun_buffer* buf); +int stun_set_binding_response(stun_buffer* buf, stun_tid* tid, + const ioa_addr *reflexive_addr, int error_code, const u08bits *reason); + +void stun_prepare_binding_request(stun_buffer* buf); +int stun_is_binding_response(const stun_buffer* buf); + +/////////////////////////////////////////////////////////////// + +u16bits stun_set_channel_bind_request(stun_buffer* buf, const ioa_addr* peer_addr, u16bits channel_number); +void stun_set_channel_bind_response(stun_buffer* buf, stun_tid* tid, int error_code, const u08bits *reason); + +/////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__TURN_STUN_BUF__ diff --git a/src/apps/peer/mainudpserver.c b/src/apps/peer/mainudpserver.c new file mode 100644 index 00000000..2c500d78 --- /dev/null +++ b/src/apps/peer/mainudpserver.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "ns_turn_utils.h" +#include "udpserver.h" +#include "apputils.h" + +#include +#include +#include +#include +#include + +//////////////// local definitions ///////////////// + +static char Usage[] = + "Usage: server [options]\n" + "Options:\n" + " -p Listening UDP port (Default: 3480)\n" + " -d Listening interface device (optional)\n" + " -L Listening address\n" + " -v verbose\n"; + + +////////////////////////////////////////////////// + +int main(int argc, char **argv) +{ + int port = PEER_DEFAULT_PORT; + char **local_addr_list=NULL; + size_t las = 0; + int verbose = TURN_VERBOSE_NONE; + int c; + char ifname[1025] = "\0"; + + IS_TURN_SERVER = 1; + + set_logfile("stdout"); + set_system_parameters(0); + + while ((c = getopt(argc, argv, "d:p:L:v")) != -1) + switch (c){ + case 'd': + STRCPY(ifname, optarg); + break; + case 'p': + port = atoi(optarg); + break; + case 'L': + local_addr_list = (char**)realloc(local_addr_list,++las*sizeof(char*)); + local_addr_list[las-1]=strdup(optarg); + break; + case 'v': + verbose = TURN_VERBOSE_NORMAL; + break; + default: + fprintf(stderr, "%s\n", Usage); + exit(1); + } + + if(las<1) { + local_addr_list = (char**)realloc(local_addr_list,++las*sizeof(char*)); + local_addr_list[las-1]=strdup("0.0.0.0"); + local_addr_list = (char**)realloc(local_addr_list,++las*sizeof(char*)); + local_addr_list[las-1]=strdup("::"); + } + + + server_type* server = start_udp_server(verbose, ifname, local_addr_list, las, port); + run_udp_server(server); + clean_udp_server(server); + + return 0; +} + diff --git a/src/apps/peer/udpserver.c b/src/apps/peer/udpserver.c new file mode 100644 index 00000000..9e6e3fde --- /dev/null +++ b/src/apps/peer/udpserver.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "apputils.h" +#include "udpserver.h" +#include "stun_buffer.h" + +/////////////// io handlers /////////////////// + +static void udp_server_input_handler(evutil_socket_t fd, short what, void* arg) { + + if(!(what&EV_READ)) return; + + ioa_addr *addr = (ioa_addr*)arg; + + int len = 0; + int slen = get_ioa_addr_len(addr); + stun_buffer buffer; + ioa_addr remote_addr; + + do { + len = recvfrom(fd, buffer.buf, sizeof(buffer.buf)-1, 0, (struct sockaddr*) &remote_addr, (socklen_t*) &slen); + } while(len<0 && (errno==EINTR)); + + buffer.len=len; + + if(len>=0) { + do { + len = sendto(fd, buffer.buf, buffer.len, 0, (const struct sockaddr*) &remote_addr, (socklen_t) slen); + } while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN))); + } +} + +///////////////////// operations ////////////////////////// + +static int udp_create_server_socket(server_type* server, + const char* ifname, const char *local_address, int port) { + + FUNCSTART; + + if(!server) return -1; + + evutil_socket_t udp_fd = -1; + ioa_addr *server_addr = (ioa_addr*)turn_malloc(sizeof(ioa_addr)); + + STRCPY(server->ifname,ifname); + + if(make_ioa_addr((const u08bits*)local_address, port, server_addr)<0) return -1; + + udp_fd = socket(server_addr->ss.sa_family, SOCK_DGRAM, 0); + if (udp_fd < 0) { + perror("socket"); + return -1; + } + + if(sock_bind_to_device(udp_fd, (unsigned char*)server->ifname)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind udp server socket to device %s\n",server->ifname); + } + + set_sock_buf_size(udp_fd,UR_SERVER_SOCK_BUF_SIZE); + + if(addr_bind(udp_fd,server_addr,1)<0) return -1; + + socket_set_nonblocking(udp_fd); + + struct event *udp_ev = event_new(server->event_base,udp_fd,EV_READ|EV_PERSIST, + udp_server_input_handler,server_addr); + + event_add(udp_ev,NULL); + + FUNCEND; + + return 0; +} + +static server_type* init_server(int verbose, const char* ifname, char **local_addresses, size_t las, int port) { + + server_type* server=(server_type*)turn_malloc(sizeof(server_type)); + + if(!server) return server; + + ns_bzero(server,sizeof(server_type)); + + server->verbose=verbose; + + server->event_base = turn_event_base_new(); + + while(las) { + udp_create_server_socket(server, ifname, local_addresses[--las], port); + udp_create_server_socket(server, ifname, local_addresses[las], port+1); + } + + return server; +} + +static int clean_server(server_type* server) { + if(server) { + if(server->event_base) event_base_free(server->event_base); + turn_free(server,sizeof(server_type)); + } + return 0; +} + +/////////////////////////////////////////////////////////// + +static void run_events(server_type* server) { + + if(!server) return; + + struct timeval timeout; + + timeout.tv_sec=0; + timeout.tv_usec=100000; + + event_base_loopexit(server->event_base, &timeout); + event_base_dispatch(server->event_base); +} + +///////////////////////////////////////////////////////////// + + +server_type* start_udp_server(int verbose, const char* ifname, char **local_addresses, size_t las, int port) { + return init_server(verbose, ifname, local_addresses, las, port); +} + +void run_udp_server(server_type* server) { + + if(server) { + + unsigned int cycle=0; + + while (1) { + + cycle++; + + run_events(server); + } + } +} + +void clean_udp_server(server_type* server) { + if(server) clean_server(server); +} + +////////////////////////////////////////////////////////////////// diff --git a/src/apps/peer/udpserver.h b/src/apps/peer/udpserver.h new file mode 100644 index 00000000..bd482c49 --- /dev/null +++ b/src/apps/peer/udpserver.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2011, 2012, 2013 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 __UDP_SERVER__ +#define __UDP_SERVER__ + +////////////////////////////// + +#include "ns_turn_utils.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////// + +struct server_info; +typedef struct server_info server_type; + +/////////////////////////////////////////////////// + +#define FUNCSTART if(server && server->verbose) turn_log_func_default(TURN_LOG_LEVEL_INFO,"%s:%d:start\n",__FUNCTION__,__LINE__) +#define FUNCEND if(server && server->verbose) turn_log_func_default(TURN_LOG_LEVEL_INFO,"%s:%d:end\n",__FUNCTION__,__LINE__) + +/////////////////////////////////////////////////////// + +struct server_info { + char ifname[1025]; + struct event_base* event_base; + int verbose; +}; + +////////////////////////////// + +server_type* start_udp_server(int verbose, const char* ifname, char **local_addresses, size_t las, int port); + +void run_udp_server(server_type* server); + +void clean_udp_server(server_type* server); + +/////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__UDP_SERVER__ diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c new file mode 100644 index 00000000..7d38778f --- /dev/null +++ b/src/apps/relay/dtls_listener.c @@ -0,0 +1,954 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "apputils.h" +#include "mainrelay.h" + +#include "dtls_listener.h" +#include "ns_ioalib_impl.h" + +#include +#include +#include +#include + +#include + +/* #define REQUEST_CLIENT_CERT */ + +/////////////////////////////////////////////////// + +#define FUNCSTART if(server && eve(server->verbose)) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s:%d:start\n",__FUNCTION__,__LINE__) +#define FUNCEND if(server && eve(server->verbose)) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s:%d:end\n",__FUNCTION__,__LINE__) + +#define COOKIE_SECRET_LENGTH (32) + +#define MAX_SINGLE_UDP_BATCH (16) + +struct dtls_listener_relay_server_info { + char ifname[1025]; + ioa_addr addr; + ioa_engine_handle e; + turn_turnserver *ts; + int verbose; + SSL_CTX *dtls_ctx; + struct event *udp_listen_ev; + ioa_socket_handle udp_listen_s; + ur_addr_map *children_ss; /* map of socket children on remote addr */ + struct message_to_relay sm; + int slen0; + ioa_engine_new_connection_event_handler connect_cb; +}; + +///////////// forward declarations //////// + +static int create_server_socket(dtls_listener_relay_server_type* server, int report_creation); +static int clean_server(dtls_listener_relay_server_type* server); +static int reopen_server_socket(dtls_listener_relay_server_type* server, evutil_socket_t fd); + +///////////// dtls message types ////////// + +int is_dtls_handshake_message(const unsigned char* buf, int len); +int is_dtls_data_message(const unsigned char* buf, int len); +int is_dtls_alert_message(const unsigned char* buf, int len); +int is_dtls_cipher_change_message(const unsigned char* buf, int len); + +int is_dtls_message(const unsigned char* buf, int len); + +int is_dtls_handshake_message(const unsigned char* buf, int len) { + return (buf && len>3 && buf[0]==0x16 && buf[1]==0xfe && buf[2]==0xff); +} + +int is_dtls_data_message(const unsigned char* buf, int len) { + return (buf && len>3 && buf[0]==0x17 && buf[1]==0xfe && buf[2]==0xff); +} + +int is_dtls_alert_message(const unsigned char* buf, int len) { + return (buf && len>3 && buf[0]==0x15 && buf[1]==0xfe && buf[2]==0xff); +} + +int is_dtls_cipher_change_message(const unsigned char* buf, int len) { + return (buf && len>3 && buf[0]==0x14 && buf[1]==0xfe && buf[2]==0xff); +} + +int is_dtls_message(const unsigned char* buf, int len) { + if(buf && (len>3) && (buf[1])==0xfe && (buf[2]==0xff)) { + switch (buf[0]) { + case 0x14: + case 0x15: + case 0x16: + case 0x17: + return 1; + default: + ; + } + } + return 0; +} + +///////////// utils ///////////////////// + +#if !defined(TURN_NO_DTLS) + +static void calculate_cookie(SSL* ssl, unsigned char *cookie_secret, unsigned int cookie_length) { + long rv=(long)ssl; + long inum=(cookie_length-(((long)cookie_secret)%sizeof(long)))/sizeof(long); + long i=0; + long *ip=(long*)cookie_secret; + for(i=0;ifd, ssl, nbh, server->verbose); + + if (rc < 0) + return NULL; + + addr_debug_print(server->verbose, remote_addr, "Accepted connection from"); + + ioa_socket_handle ioas = create_ioa_socket_from_ssl(server->e, sock, ssl, DTLS_SOCKET, CLIENT_SOCKET, remote_addr, local_addr); + if(ioas) { + + ioas->listener_server = server; + + addr_cpy(&(server->sm.m.sm.nd.src_addr),remote_addr); + server->sm.m.sm.nd.recv_ttl = TTL_IGNORE; + server->sm.m.sm.nd.recv_tos = TOS_IGNORE; + server->sm.m.sm.s = ioas; + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot create ioa_socket from SSL\n"); + } + + FUNCEND ; + + return ioas; +} + +static ioa_socket_handle dtls_server_input_handler(dtls_listener_relay_server_type* server, + ioa_socket_handle s, + ioa_network_buffer_handle nbh) +{ + FUNCSTART; + + if (!server || !nbh) { + return NULL; + } + + SSL* connecting_ssl = NULL; + + BIO *wbio = NULL; + struct timeval timeout; + + /* Create BIO */ + wbio = BIO_new_dgram(s->fd, BIO_NOCLOSE); + (void)BIO_dgram_set_peer(wbio, (struct sockaddr*) &(server->sm.m.sm.nd.src_addr)); + + /* Set and activate timeouts */ + timeout.tv_sec = DTLS_MAX_RECV_TIMEOUT; + timeout.tv_usec = 0; + BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); + + connecting_ssl = SSL_new(server->dtls_ctx); + + SSL_set_accept_state(connecting_ssl); + + SSL_set_bio(connecting_ssl, NULL, wbio); + SSL_set_options(connecting_ssl, SSL_OP_COOKIE_EXCHANGE); + + SSL_set_max_cert_list(connecting_ssl, 655350); + + ioa_socket_handle rc = dtls_accept_client_connection(server, s, connecting_ssl, + &(server->sm.m.sm.nd.src_addr), + &(server->addr), + nbh); + + if (!rc) { + if (!(SSL_get_shutdown(connecting_ssl) & SSL_SENT_SHUTDOWN)) { + SSL_set_shutdown(connecting_ssl, SSL_RECEIVED_SHUTDOWN); + SSL_shutdown(connecting_ssl); + } + SSL_free(connecting_ssl); + } + + return rc; +} + +#endif + +static int handle_udp_packet(dtls_listener_relay_server_type *server, + struct message_to_relay *sm, + ioa_engine_handle ioa_eng, turn_turnserver *ts) +{ + int verbose = ioa_eng->verbose; + ioa_socket_handle s = sm->m.sm.s; + + ur_addr_map_value_type mvt = 0; + if(!(server->children_ss)) { + server->children_ss = (ur_addr_map*)allocate_super_memory_engine(server->e, sizeof(ur_addr_map)); + ur_addr_map_init(server->children_ss); + } + ur_addr_map *amap = server->children_ss; + + ioa_socket_handle chs = NULL; + if ((ur_addr_map_get(amap, &(sm->m.sm.nd.src_addr), &mvt) > 0) && mvt) { + chs = (ioa_socket_handle) mvt; + } + + if (chs && !ioa_socket_tobeclosed(chs) + && (chs->sockets_container == amap) + && (chs->magic == SOCKET_MAGIC)) { + s = chs; + sm->m.sm.s = s; + if(s->ssl) { + int sslret = ssl_read(s->fd, s->ssl, sm->m.sm.nd.nbh, verbose); + if(sslret < 0) { + ioa_network_buffer_delete(ioa_eng, sm->m.sm.nd.nbh); + sm->m.sm.nd.nbh = NULL; + ts_ur_super_session *ss = (ts_ur_super_session *) s->session; + if (ss) { + turn_turnserver *server = (turn_turnserver *) ss->server; + if (server) { + shutdown_client_connection(server, ss, 0, "SSL read error"); + } + } else { + close_ioa_socket(s); + } + ur_addr_map_del(amap, &(sm->m.sm.nd.src_addr), NULL); + sm->m.sm.s = NULL; + s = NULL; + chs = NULL; + } else if(ioa_network_buffer_get_size(sm->m.sm.nd.nbh)>0) { + ; + } else { + ioa_network_buffer_delete(ioa_eng, sm->m.sm.nd.nbh); + sm->m.sm.nd.nbh = NULL; + } + } + + if (s && s->read_cb && sm->m.sm.nd.nbh) { + s->e = ioa_eng; + s->read_cb(s, IOA_EV_READ, &(sm->m.sm.nd), s->read_ctx); + ioa_network_buffer_delete(ioa_eng, sm->m.sm.nd.nbh); + sm->m.sm.nd.nbh = NULL; + + if (ioa_socket_tobeclosed(s)) { + ts_ur_super_session *ss = (ts_ur_super_session *) s->session; + if (ss) { + turn_turnserver *server = (turn_turnserver *) ss->server; + if (server) { + shutdown_client_connection(server, ss, 0, "UDP packet processing error"); + } + } + } + } + } else { + if (chs && ioa_socket_tobeclosed(chs)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: socket to be closed\n", __FUNCTION__); + { + u08bits saddr[129]; + u08bits rsaddr[129]; + long thrid = (long) pthread_self(); + addr_to_string(get_local_addr_from_ioa_socket(chs),saddr); + addr_to_string(get_remote_addr_from_ioa_socket(chs),rsaddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: 111.111: thrid=0x%lx: Amap = 0x%lx, socket container=0x%lx, local addr %s, remote addr %s, s=0x%lx, done=%d, tbc=%d\n", + __FUNCTION__, thrid, (long) amap, + (long) (chs->sockets_container), (char*) saddr, + (char*) rsaddr, (long) s, (int) (chs->done), + (int) (chs->tobeclosed)); + } + } + + if (chs && (chs->magic != SOCKET_MAGIC)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: wrong socket magic\n", __FUNCTION__); + } + + if (chs && (chs->sockets_container != amap)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: wrong socket container\n", __FUNCTION__); + { + u08bits saddr[129]; + u08bits rsaddr[129]; + long thrid = (long) pthread_self(); + addr_to_string(get_local_addr_from_ioa_socket(chs),saddr); + addr_to_string(get_remote_addr_from_ioa_socket(chs),rsaddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: 111.222: thrid=0x%lx: Amap = 0x%lx, socket container=0x%lx, local addr %s, remote addr %s, s=0x%lx, done=%d, tbc=%d, st=%d, sat=%d\n", + __FUNCTION__, thrid, (long) amap, + (long) (chs->sockets_container), (char*) saddr, + (char*) rsaddr, (long) chs, (int) (chs->done), + (int) (chs->tobeclosed), (int) (chs->st), + (int) (chs->sat)); + } + } + + chs = NULL; + +#if !defined(TURN_NO_DTLS) + if (!turn_params.no_dtls && + is_dtls_handshake_message(ioa_network_buffer_data(sm->m.sm.nd.nbh), + (int)ioa_network_buffer_get_size(sm->m.sm.nd.nbh))) { + chs = dtls_server_input_handler(server,s, sm->m.sm.nd.nbh); + ioa_network_buffer_delete(server->e, sm->m.sm.nd.nbh); + sm->m.sm.nd.nbh = NULL; + } +#endif + + if(!chs) { + chs = create_ioa_socket_from_fd(ioa_eng, s->fd, s, + UDP_SOCKET, CLIENT_SOCKET, &(sm->m.sm.nd.src_addr), + get_local_addr_from_ioa_socket(s)); + } + + s = chs; + sm->m.sm.s = s; + + if (s) { + if(verbose) { + u08bits saddr[129]; + u08bits rsaddr[129]; + addr_to_string(get_local_addr_from_ioa_socket(s),saddr); + addr_to_string(get_remote_addr_from_ioa_socket(s),rsaddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: New UDP endpoint: local addr %s, remote addr %s\n", + __FUNCTION__, (char*) saddr,(char*) rsaddr); + } + s->e = ioa_eng; + s->listener_server = server; + add_socket_to_map(s, amap); + open_client_connection_session(ts, &(sm->m.sm)); + } + } + + return 0; +} + +static int create_new_connected_udp_socket( + dtls_listener_relay_server_type* server, ioa_socket_handle s) +{ + + evutil_socket_t udp_fd = socket(s->local_addr.ss.sa_family, SOCK_DGRAM, 0); + if (udp_fd < 0) { + perror("socket"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Cannot allocate new socket\n", + __FUNCTION__); + return -1; + } + + if (sock_bind_to_device(udp_fd, (unsigned char*) (s->e->relay_ifname)) + < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Cannot bind udp server socket to device %s\n", + (char*) (s->e->relay_ifname)); + } + + ioa_socket_handle ret = (ioa_socket*) turn_malloc(sizeof(ioa_socket)); + if (!ret) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: Cannot allocate new socket structure\n", __FUNCTION__); + close(udp_fd); + return -1; + } + + ns_bzero(ret, sizeof(ioa_socket)); + + ret->magic = SOCKET_MAGIC; + + ret->fd = udp_fd; + + ret->family = s->family; + ret->st = s->st; + ret->sat = CLIENT_SOCKET; + ret->local_addr_known = 1; + addr_cpy(&(ret->local_addr), &(s->local_addr)); + + if (addr_bind(udp_fd,&(s->local_addr),1) < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Cannot bind new detached udp server socket to local addr\n"); + IOA_CLOSE_SOCKET(ret); + return -1; + } + ret->bound = 1; + + { + int connect_err = 0; + if (addr_connect(udp_fd, &(server->sm.m.sm.nd.src_addr), &connect_err) < 0) { + char sl[129]; + char sr[129]; + addr_to_string(&(ret->local_addr),(u08bits*)sl); + addr_to_string(&(server->sm.m.sm.nd.src_addr),(u08bits*)sr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Cannot connect new detached udp client socket from local addr %s to remote addr %s\n",sl,sr); + IOA_CLOSE_SOCKET(ret); + return -1; + } + } + ret->connected = 1; + addr_cpy(&(ret->remote_addr), &(server->sm.m.sm.nd.src_addr)); + + set_socket_options(ret); + + ret->current_ttl = s->current_ttl; + ret->default_ttl = s->default_ttl; + + ret->current_tos = s->current_tos; + ret->default_tos = s->default_tos; + +#if !defined(TURN_NO_DTLS) + if (!turn_params.no_dtls + && is_dtls_handshake_message( + ioa_network_buffer_data(server->sm.m.sm.nd.nbh), + (int) ioa_network_buffer_get_size( + server->sm.m.sm.nd.nbh))) { + + SSL* connecting_ssl = NULL; + + BIO *wbio = NULL; + struct timeval timeout; + + /* Create BIO */ + wbio = BIO_new_dgram(ret->fd, BIO_NOCLOSE); + (void) BIO_dgram_set_peer(wbio, (struct sockaddr*) &(server->sm.m.sm.nd.src_addr)); + + BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &(server->sm.m.sm.nd.src_addr)); + + /* Set and activate timeouts */ + timeout.tv_sec = DTLS_MAX_RECV_TIMEOUT; + timeout.tv_usec = 0; + BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); + + connecting_ssl = SSL_new(server->dtls_ctx); + + SSL_set_accept_state(connecting_ssl); + + SSL_set_bio(connecting_ssl, NULL, wbio); + + SSL_set_options(connecting_ssl, SSL_OP_COOKIE_EXCHANGE); + SSL_set_max_cert_list(connecting_ssl, 655350); + int rc = ssl_read(ret->fd, connecting_ssl, server->sm.m.sm.nd.nbh, + server->verbose); + + if (rc < 0) { + if (!(SSL_get_shutdown(connecting_ssl) & SSL_SENT_SHUTDOWN)) { + SSL_set_shutdown(connecting_ssl, SSL_RECEIVED_SHUTDOWN); + SSL_shutdown(connecting_ssl); + } + SSL_free(connecting_ssl); + IOA_CLOSE_SOCKET(ret); + return -1; + } + + addr_debug_print(server->verbose, &(server->sm.m.sm.nd.src_addr), + "Accepted DTLS connection from"); + + ret->ssl = connecting_ssl; + ret->listener_server = server; + + ioa_network_buffer_delete(server->e, server->sm.m.sm.nd.nbh); + server->sm.m.sm.nd.nbh = NULL; + } +#endif + + server->sm.m.sm.s = ret; + return server->connect_cb(server->e, &(server->sm)); +} + +static void udp_server_input_handler(evutil_socket_t fd, short what, void* arg) +{ + int cycle = 0; + + ioa_socket_handle s = (ioa_socket_handle)arg; + + dtls_listener_relay_server_type* server = (dtls_listener_relay_server_type*)s->listener_server; + + FUNCSTART; + + if (!(what & EV_READ)) { + return; + } + + //printf_server_socket(server, fd); + + ioa_network_buffer_handle *elem = NULL; + + start_udp_cycle: + + elem = (ioa_network_buffer_handle *)ioa_network_buffer_allocate(server->e); + + server->sm.m.sm.nd.nbh = elem; + server->sm.m.sm.nd.recv_ttl = TTL_IGNORE; + server->sm.m.sm.nd.recv_tos = TOS_IGNORE; + + addr_set_any(&(server->sm.m.sm.nd.src_addr)); + + int slen = server->slen0; + ssize_t bsize = 0; + + int flags = 0; + + do { + bsize = recvfrom(fd, ioa_network_buffer_data(elem), ioa_network_buffer_get_capacity_udp(), flags, (struct sockaddr*) &(server->sm.m.sm.nd.src_addr), (socklen_t*) &slen); + } while (bsize < 0 && (errno == EINTR)); + + int conn_reset = is_connreset(); + int to_block = would_block(); + + if (bsize < 0) { + + if(to_block) { + ioa_network_buffer_delete(server->e, server->sm.m.sm.nd.nbh); + server->sm.m.sm.nd.nbh = NULL; + FUNCEND; + return; + } + + #if defined(MSG_ERRQUEUE) + + //Linux + int eflags = MSG_ERRQUEUE | MSG_DONTWAIT; + static s08bits buffer[65535]; + u32bits errcode = 0; + ioa_addr orig_addr; + int ttl = 0; + int tos = 0; + udp_recvfrom(fd, &orig_addr, &(server->addr), buffer, + (int) sizeof(buffer), &ttl, &tos, server->e->cmsg, eflags, + &errcode); + //try again... + do { + bsize = recvfrom(fd, ioa_network_buffer_data(elem), ioa_network_buffer_get_capacity_udp(), flags, (struct sockaddr*) &(server->sm.m.sm.nd.src_addr), (socklen_t*) &slen); + } while (bsize < 0 && (errno == EINTR)); + + conn_reset = is_connreset(); + to_block = would_block(); + + #endif + + if(conn_reset) { + ioa_network_buffer_delete(server->e, server->sm.m.sm.nd.nbh); + server->sm.m.sm.nd.nbh = NULL; + reopen_server_socket(server,fd); + FUNCEND; + return; + } + } + + if(bsize<0) { + if(!to_block && !conn_reset) { + int ern=errno; + perror(__FUNCTION__); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: recvfrom error %d\n",__FUNCTION__,ern); + } + ioa_network_buffer_delete(server->e, server->sm.m.sm.nd.nbh); + server->sm.m.sm.nd.nbh = NULL; + FUNCEND; + return; + } + + if (bsize > 0) { + + int rc = 0; + ioa_network_buffer_set_size(elem, (size_t)bsize); + + if(server->connect_cb) { + + rc = create_new_connected_udp_socket(server, s); + if(rc<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot handle UDP packet, size %d\n",(int)bsize); + } + + } else { + server->sm.m.sm.s = s; + rc = handle_udp_packet(server, &(server->sm), server->e, server->ts); + } + + if(rc < 0) { + if(eve(server->e->verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot handle UDP event\n"); + } + } + } + + ioa_network_buffer_delete(server->e, server->sm.m.sm.nd.nbh); + server->sm.m.sm.nd.nbh = NULL; + + if((bsize>0) && (cycle++addr.ss.sa_family, SOCK_DGRAM, 0); + if (udp_listen_fd < 0) { + perror("socket"); + return -1; + } + + server->udp_listen_s = create_ioa_socket_from_fd(server->e, udp_listen_fd, NULL, UDP_SOCKET, LISTENER_SOCKET, NULL, &(server->addr)); + + server->udp_listen_s->listener_server = server; + + set_sock_buf_size(udp_listen_fd,UR_SERVER_SOCK_BUF_SIZE); + + if(sock_bind_to_device(udp_listen_fd, (unsigned char*)server->ifname)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind listener socket to device %s\n",server->ifname); + } + + { + const int max_binding_time = 60; + int addr_bind_cycle = 0; + retry_addr_bind: + + if(addr_bind(udp_listen_fd,&server->addr,1)<0) { + perror("Cannot bind local socket to addr"); + char saddr[129]; + addr_to_string(&server->addr,(u08bits*)saddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,"Cannot bind UDP/DTLS listener socket to addr %s\n",saddr); + if(addr_bind_cycle++udp_listen_ev = event_new(server->e->event_base,udp_listen_fd, + EV_READ|EV_PERSIST,udp_server_input_handler, + server->udp_listen_s); + + event_add(server->udp_listen_ev,NULL); + } + + if(report_creation) { + if(!turn_params.no_udp && !turn_params.no_dtls) + addr_debug_print(server->verbose, &server->addr,"UDP/DTLS listener opened on"); + else if(!turn_params.no_dtls) + addr_debug_print(server->verbose, &server->addr,"DTLS listener opened on"); + else if(!turn_params.no_udp) + addr_debug_print(server->verbose, &server->addr,"UDP listener opened on"); + } + + FUNCEND; + + return 0; +} + +static int reopen_server_socket(dtls_listener_relay_server_type* server, evutil_socket_t fd) +{ + UNUSED_ARG(fd); + + if(!server) + return 0; + + FUNCSTART; + + { + EVENT_DEL(server->udp_listen_ev); + + if(server->udp_listen_s->fd>=0) { + socket_closesocket(server->udp_listen_s->fd); + server->udp_listen_s->fd = -1; + } + + if (!(server->udp_listen_s)) { + return create_server_socket(server,1); + } + + ioa_socket_raw udp_listen_fd = socket(server->addr.ss.sa_family, SOCK_DGRAM, 0); + if (udp_listen_fd < 0) { + perror("socket"); + FUNCEND; + return -1; + } + + server->udp_listen_s->fd = udp_listen_fd; + + /* some UDP sessions may fail due to the race condition here */ + + set_socket_options(server->udp_listen_s); + + set_sock_buf_size(udp_listen_fd, UR_SERVER_SOCK_BUF_SIZE); + + if (sock_bind_to_device(udp_listen_fd, (unsigned char*) server->ifname) < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "Cannot bind listener socket to device %s\n", + server->ifname); + } + + if(addr_bind(udp_listen_fd,&server->addr,1)<0) { + perror("Cannot bind local socket to addr"); + char saddr[129]; + addr_to_string(&server->addr,(u08bits*)saddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind listener socket to addr %s\n",saddr); + return -1; + } + + server->udp_listen_ev = event_new(server->e->event_base, udp_listen_fd, + EV_READ | EV_PERSIST, udp_server_input_handler, + server->udp_listen_s); + + event_add(server->udp_listen_ev, NULL ); + } + + if (!turn_params.no_udp && !turn_params.no_dtls) + addr_debug_print(server->verbose, &server->addr, + "UDP/DTLS listener opened on "); + else if (!turn_params.no_dtls) + addr_debug_print(server->verbose, &server->addr, + "DTLS listener opened on "); + else if (!turn_params.no_udp) + addr_debug_print(server->verbose, &server->addr, + "UDP listener opened on "); + + FUNCEND; + + return 0; +} + +#if defined(REQUEST_CLIENT_CERT) + +static int dtls_verify_callback (int ok, X509_STORE_CTX *ctx) { + /* This function should ask the user + * if he trusts the received certificate. + * Here we always trust. + */ + if(ok && ctx) return 1; + return -1; +} + +#endif + +static int init_server(dtls_listener_relay_server_type* server, + const char* ifname, + const char *local_address, + int port, + int verbose, + ioa_engine_handle e, + turn_turnserver *ts, + int report_creation, + ioa_engine_new_connection_event_handler send_socket) { + + if(!server) return -1; + + server->dtls_ctx = e->dtls_ctx; + server->ts = ts; + server->connect_cb = send_socket; + + if(ifname) STRCPY(server->ifname,ifname); + + if(make_ioa_addr((const u08bits*)local_address, port, &server->addr)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot create a UDP/DTLS listener for address: %s\n",local_address); + return -1; + } + + server->slen0 = get_ioa_addr_len(&(server->addr)); + + server->verbose=verbose; + + server->e = e; + + if(server->dtls_ctx) { + +#if defined(REQUEST_CLIENT_CERT) + /* If client has to authenticate, then */ + SSL_CTX_set_verify(server->dtls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, dtls_verify_callback); +#endif + + SSL_CTX_set_read_ahead(server->dtls_ctx, 1); + +#if !defined(TURN_NO_DTLS) + SSL_CTX_set_cookie_generate_cb(server->dtls_ctx, generate_cookie); + SSL_CTX_set_cookie_verify_cb(server->dtls_ctx, verify_cookie); +#endif + } + + return create_server_socket(server, report_creation); +} + +static int clean_server(dtls_listener_relay_server_type* server) { + if(server) { + EVENT_DEL(server->udp_listen_ev); + close_ioa_socket(server->udp_listen_s); + server->udp_listen_s = NULL; + } + return 0; +} + +/////////////////////////////////////////////////////////// + +dtls_listener_relay_server_type* create_dtls_listener_server(const char* ifname, + const char *local_address, + int port, + int verbose, + ioa_engine_handle e, + turn_turnserver *ts, + int report_creation, + ioa_engine_new_connection_event_handler send_socket) { + + dtls_listener_relay_server_type* server=(dtls_listener_relay_server_type*) + allocate_super_memory_engine(e,sizeof(dtls_listener_relay_server_type)); + + if(init_server(server, + ifname, local_address, port, + verbose, + e, ts, report_creation, send_socket)<0) { + return NULL; + } else { + return server; + } +} + +ioa_engine_handle get_engine(dtls_listener_relay_server_type* server) +{ + if(server) + return server->e; + return NULL; +} + +//////////// UDP send //////////////// + +void udp_send_message(dtls_listener_relay_server_type *server, ioa_network_buffer_handle nbh, ioa_addr *dest) +{ + if(server && dest && nbh && (server->udp_listen_s)) + udp_send(server->udp_listen_s, dest, (s08bits*)ioa_network_buffer_data(nbh), (int)ioa_network_buffer_get_size(nbh)); +} + +////////////////////////////////////////////////////////////////// diff --git a/src/apps/relay/dtls_listener.h b/src/apps/relay/dtls_listener.h new file mode 100644 index 00000000..9d7cab68 --- /dev/null +++ b/src/apps/relay/dtls_listener.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2011, 2012, 2013 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 __DTLS_LISTENER__ +#define __DTLS_LISTENER__ + +#include "ns_turn_utils.h" + +#include "ns_ioalib_impl.h" + +#include "ns_turn_server.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////// + +struct dtls_listener_relay_server_info; +typedef struct dtls_listener_relay_server_info dtls_listener_relay_server_type; + +/////////////////////////////////////////// + +dtls_listener_relay_server_type* create_dtls_listener_server(const char* ifname, + const char *local_address, + int port, + int verbose, + ioa_engine_handle e, + turn_turnserver *ts, + int report_creation, + ioa_engine_new_connection_event_handler send_socket); + +void udp_send_message(dtls_listener_relay_server_type *server, ioa_network_buffer_handle nbh, ioa_addr *dest); + +ioa_engine_handle get_engine(dtls_listener_relay_server_type* server); + +/////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__DTLS_LISTENER__ diff --git a/src/apps/relay/libtelnet.c b/src/apps/relay/libtelnet.c new file mode 100644 index 00000000..694a3d79 --- /dev/null +++ b/src/apps/relay/libtelnet.c @@ -0,0 +1,1545 @@ +/* + * libtelnet - TELNET protocol handling library + * + * Sean Middleditch + * sean@sourcemud.org + * + * The author or authors of this code dedicate any and all copyright interest + * in this code to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and successors. We + * intend this dedication to be an overt act of relinquishment in perpetuity of + * all present and future rights to this code under copyright law. + */ + +/** + * Minor fixes by Oleg Moskalenko + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include + +/* Win32 compatibility */ +#if defined(_WIN32) +# define vsnprintf _vsnprintf +# define __func__ __FUNCTION__ +# define ZLIB_WINAPI 1 +#endif + +#if defined(HAVE_ZLIB) +# include +#endif + +#include "libtelnet.h" + +/* inlinable functions */ +#if defined(__GNUC__) || __STDC_VERSION__ >= 199901L +# define INLINE __inline__ +#else +# define INLINE +#endif + +/* helper for Q-method option tracking */ +#define Q_US(q) ((q).state & 0x0F) +#define Q_HIM(q) (((q).state & 0xF0) >> 4) +#define Q_MAKE(us,him) ((us) | ((him) << 4)) + +/* helper for the negotiation routines */ +#define NEGOTIATE_EVENT(telnet,cmd,opt) \ + ev.type = (cmd); \ + ev.neg.telopt = (opt); \ + (telnet)->eh((telnet), &ev, (telnet)->ud); + +/* telnet state codes */ +enum telnet_state_t { + TELNET_STATE_DATA = 0, + TELNET_STATE_IAC, + TELNET_STATE_WILL, + TELNET_STATE_WONT, + TELNET_STATE_DO, + TELNET_STATE_DONT, + TELNET_STATE_SB, + TELNET_STATE_SB_DATA, + TELNET_STATE_SB_DATA_IAC +}; +typedef enum telnet_state_t telnet_state_t; + +/* telnet state tracker */ +struct telnet_t { + /* user data */ + void *ud; + /* telopt support table */ + const telnet_telopt_t *telopts; + /* event handler */ + telnet_event_handler_t eh; +#if defined(HAVE_ZLIB) + /* zlib (mccp2) compression */ + z_stream *z; +#endif + /* RFC1143 option negotiation states */ + struct telnet_rfc1143_t *q; + /* sub-request buffer */ + char *buffer; + /* current size of the buffer */ + size_t buffer_size; + /* current buffer write position (also length of buffer data) */ + size_t buffer_pos; + /* current state */ + enum telnet_state_t state; + /* option flags */ + unsigned char flags; + /* current subnegotiation telopt */ + unsigned char sb_telopt; + /* length of RFC1143 queue */ + unsigned char q_size; +}; + +/* RFC1143 option negotiation state */ +typedef struct telnet_rfc1143_t { + unsigned char telopt; + unsigned char state; +} telnet_rfc1143_t; + +/* RFC1143 state names */ +#define Q_NO 0 +#define Q_YES 1 +#define Q_WANTNO 2 +#define Q_WANTYES 3 +#define Q_WANTNO_OP 4 +#define Q_WANTYES_OP 5 + +/* buffer sizes */ +static const size_t _buffer_sizes[] = { 0, 512, 2048, 8192, 16384, }; +static const size_t _buffer_sizes_count = sizeof(_buffer_sizes) / + sizeof(_buffer_sizes[0]); + +/* error generation function */ +static telnet_error_t _error(telnet_t *telnet, unsigned line, + const char* func, telnet_error_t err, int fatal, const char *fmt, + ...) { + telnet_event_t ev; + char buffer[512]; + va_list va; + + /* format informational text */ + va_start(va, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, va); + va_end(va); + + /* send error event to the user */ + ev.type = fatal ? TELNET_EV_ERROR : TELNET_EV_WARNING; + ev.error.file = __FILE__; + ev.error.func = func; + ev.error.line = line; + ev.error.msg = buffer; + telnet->eh(telnet, &ev, telnet->ud); + + return err; +} + +#if defined(HAVE_ZLIB) +/* initialize the zlib box for a telnet box; if deflate is non-zero, it + * initializes zlib for delating (compression), otherwise for inflating + * (decompression). returns TELNET_EOK on success, something else on + * failure. + */ +telnet_error_t _init_zlib(telnet_t *telnet, int deflate, int err_fatal) { + z_stream *z; + int rs; + + /* if compression is already enabled, fail loudly */ + if (telnet->z != 0) + return _error(telnet, __LINE__, __func__, TELNET_EBADVAL, + err_fatal, "cannot initialize compression twice"); + + /* allocate zstream box */ + if ((z= (z_stream *)calloc(1, sizeof(z_stream))) == 0) + return _error(telnet, __LINE__, __func__, TELNET_ENOMEM, err_fatal, + "malloc() failed: %s", strerror(errno)); + + /* initialize */ + if (deflate) { + if ((rs = deflateInit(z, Z_DEFAULT_COMPRESSION)) != Z_OK) { + free(z); + return _error(telnet, __LINE__, __func__, TELNET_ECOMPRESS, + err_fatal, "deflateInit() failed: %s", zError(rs)); + } + telnet->flags |= TELNET_PFLAG_DEFLATE; + } else { + if ((rs = inflateInit(z)) != Z_OK) { + free(z); + return _error(telnet, __LINE__, __func__, TELNET_ECOMPRESS, + err_fatal, "inflateInit() failed: %s", zError(rs)); + } + telnet->flags &= ~TELNET_PFLAG_DEFLATE; + } + + telnet->z = z; + + return TELNET_EOK; +} +#endif /* defined(HAVE_ZLIB) */ + +/* push bytes out, compressing them first if need be */ +static void _send(telnet_t *telnet, const char *buffer, + size_t size) { + telnet_event_t ev; + +#if defined(HAVE_ZLIB) + /* if we have a deflate (compression) zlib box, use it */ + if (telnet->z != 0 && telnet->flags & TELNET_PFLAG_DEFLATE) { + char deflate_buffer[1024]; + int rs; + + /* initialize z state */ + telnet->z->next_in = (unsigned char *)buffer; + telnet->z->avail_in = size; + telnet->z->next_out = (unsigned char *)deflate_buffer; + telnet->z->avail_out = sizeof(deflate_buffer); + + /* deflate until buffer exhausted and all output is produced */ + while (telnet->z->avail_in > 0 || telnet->z->avail_out == 0) { + /* compress */ + if ((rs = deflate(telnet->z, Z_SYNC_FLUSH)) != Z_OK) { + _error(telnet, __LINE__, __func__, TELNET_ECOMPRESS, 1, + "deflate() failed: %s", zError(rs)); + deflateEnd(telnet->z); + free(telnet->z); + telnet->z = 0; + break; + } + + /* send event */ + ev.type = TELNET_EV_SEND; + ev.data.buffer = deflate_buffer; + ev.data.size = sizeof(deflate_buffer) - telnet->z->avail_out; + telnet->eh(telnet, &ev, telnet->ud); + + /* prepare output buffer for next run */ + telnet->z->next_out = (unsigned char *)deflate_buffer; + telnet->z->avail_out = sizeof(deflate_buffer); + } + + /* do not continue with remaining code */ + return; + } +#endif /* defined(HAVE_ZLIB) */ + + ev.type = TELNET_EV_SEND; + ev.data.buffer = buffer; + ev.data.size = size; + telnet->eh(telnet, &ev, telnet->ud); +} + +/* to send bags of unsigned chars */ +#define _sendu(t, d, s) _send((t), (const char*)(d), (s)) + +/* check if we support a particular telopt; if us is non-zero, we + * check if we (local) supports it, otherwise we check if he (remote) + * supports it. return non-zero if supported, zero if not supported. + */ +static INLINE int _check_telopt(telnet_t *telnet, unsigned char telopt, + int us) { + int i; + + /* if we have no telopts table, we obviously don't support it */ + if (telnet->telopts == 0) + return 0; + + /* loop unti found or end marker (us and him both 0) */ + for (i = 0; telnet->telopts[i].telopt != -1; ++i) { + if (telnet->telopts[i].telopt == telopt) { + if (us && telnet->telopts[i].us == TELNET_WILL) + return 1; + else if (!us && telnet->telopts[i].him == TELNET_DO) + return 1; + else + return 0; + } + } + + /* not found, so not supported */ + return 0; +} + +/* retrieve RFC1143 option state */ +static INLINE telnet_rfc1143_t _get_rfc1143(telnet_t *telnet, + unsigned char telopt) { + telnet_rfc1143_t empty; + int i; + + /* search for entry */ + for (i = 0; i != telnet->q_size; ++i) { + if (telnet->q[i].telopt == telopt) { + return telnet->q[i]; + } + } + + /* not found, return empty value */ + empty.telopt = telopt; + empty.state = 0; + return empty; +} + +/* save RFC1143 option state */ +static INLINE void _set_rfc1143(telnet_t *telnet, unsigned char telopt, + char us, char him) { + telnet_rfc1143_t *qtmp; + int i; + + /* search for entry */ + for (i = 0; i != telnet->q_size; ++i) { + if (telnet->q[i].telopt == telopt) { + telnet->q[i].state = Q_MAKE(us,him); + return; + } + } + + /* we're going to need to track state for it, so grow the queue + * by 4 (four) elements and put the telopt into it; bail on allocation + * error. we go by four because it seems like a reasonable guess as + * to the number of enabled options for most simple code, and it + * allows for an acceptable number of reallocations for complex code. + */ + if ((qtmp = (telnet_rfc1143_t *)realloc(telnet->q, + sizeof(telnet_rfc1143_t) * (telnet->q_size + 4))) == 0) { + _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0, + "realloc() failed: %s", strerror(errno)); + return; + } + memset(&qtmp[telnet->q_size], 0, sizeof(telnet_rfc1143_t) * 4); + telnet->q = qtmp; + telnet->q[telnet->q_size].telopt = telopt; + telnet->q[telnet->q_size].state = Q_MAKE(us, him); + telnet->q_size += 4; +} + +/* send negotiation bytes */ +static INLINE void _send_negotiate(telnet_t *telnet, unsigned char cmd, + unsigned char telopt) { + unsigned char bytes[3]; + bytes[0] = TELNET_IAC; + bytes[1] = cmd; + bytes[2] = telopt; + _sendu(telnet, bytes, 3); +} + +/* negotiation handling magic for RFC1143 */ +static void _negotiate(telnet_t *telnet, unsigned char telopt) { + telnet_event_t ev; + telnet_rfc1143_t q; + + /* in PROXY mode, just pass it thru and do nothing */ + if (telnet->flags & TELNET_FLAG_PROXY) { + switch ((int)telnet->state) { + case TELNET_STATE_WILL: + NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt); + break; + case TELNET_STATE_WONT: + NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt); + break; + case TELNET_STATE_DO: + NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt); + break; + case TELNET_STATE_DONT: + NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt); + break; + } + return; + } + + /* lookup the current state of the option */ + q = _get_rfc1143(telnet, telopt); + + /* start processing... */ + switch ((int)telnet->state) { + /* request to enable option on remote end or confirm DO */ + case TELNET_STATE_WILL: + switch (Q_HIM(q)) { + case Q_NO: + if (_check_telopt(telnet, telopt, 0)) { + _set_rfc1143(telnet, telopt, Q_US(q), Q_YES); + _send_negotiate(telnet, TELNET_DO, telopt); + NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt); + } else + _send_negotiate(telnet, TELNET_DONT, telopt); + break; + case Q_WANTNO: + _set_rfc1143(telnet, telopt, Q_US(q), Q_NO); + NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt); + _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0, + "DONT answered by WILL"); + break; + case Q_WANTNO_OP: + _set_rfc1143(telnet, telopt, Q_US(q), Q_YES); + NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt); + _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0, + "DONT answered by WILL"); + break; + case Q_WANTYES: + _set_rfc1143(telnet, telopt, Q_US(q), Q_YES); + NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt); + break; + case Q_WANTYES_OP: + _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTNO); + _send_negotiate(telnet, TELNET_DONT, telopt); + NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt); + break; + } + break; + + /* request to disable option on remote end, confirm DONT, reject DO */ + case TELNET_STATE_WONT: + switch (Q_HIM(q)) { + case Q_YES: + _set_rfc1143(telnet, telopt, Q_US(q), Q_NO); + _send_negotiate(telnet, TELNET_DONT, telopt); + NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt); + break; + case Q_WANTNO: + _set_rfc1143(telnet, telopt, Q_US(q), Q_NO); + NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt); + break; + case Q_WANTNO_OP: + _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTYES); + NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt); + break; + case Q_WANTYES: + case Q_WANTYES_OP: + _set_rfc1143(telnet, telopt, Q_US(q), Q_NO); + break; + } + break; + + /* request to enable option on local end or confirm WILL */ + case TELNET_STATE_DO: + switch (Q_US(q)) { + case Q_NO: + if (_check_telopt(telnet, telopt, 1)) { + _set_rfc1143(telnet, telopt, Q_YES, Q_HIM(q)); + _send_negotiate(telnet, TELNET_WILL, telopt); + NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt); + } else + _send_negotiate(telnet, TELNET_WONT, telopt); + break; + case Q_WANTNO: + _set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q)); + NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt); + _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0, + "WONT answered by DO"); + break; + case Q_WANTNO_OP: + _set_rfc1143(telnet, telopt, Q_YES, Q_HIM(q)); + NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt); + _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0, + "WONT answered by DO"); + break; + case Q_WANTYES: + _set_rfc1143(telnet, telopt, Q_YES, Q_HIM(q)); + NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt); + break; + case Q_WANTYES_OP: + _set_rfc1143(telnet, telopt, Q_WANTNO, Q_HIM(q)); + _send_negotiate(telnet, TELNET_WONT, telopt); + NEGOTIATE_EVENT(telnet, TELNET_EV_DO, telopt); + break; + } + break; + + /* request to disable option on local end, confirm WONT, reject WILL */ + case TELNET_STATE_DONT: + switch (Q_US(q)) { + case Q_YES: + _set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q)); + _send_negotiate(telnet, TELNET_WONT, telopt); + NEGOTIATE_EVENT(telnet, TELNET_EV_DONT, telopt); + break; + case Q_WANTNO: + _set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q)); + NEGOTIATE_EVENT(telnet, TELNET_EV_WONT, telopt); + break; + case Q_WANTNO_OP: + _set_rfc1143(telnet, telopt, Q_WANTYES, Q_HIM(q)); + _send_negotiate(telnet, TELNET_WILL, telopt); + NEGOTIATE_EVENT(telnet, TELNET_EV_WILL, telopt); + break; + case Q_WANTYES: + case Q_WANTYES_OP: + _set_rfc1143(telnet, telopt, Q_NO, Q_HIM(q)); + break; + } + break; + } +} + +/* process an ENVIRON/NEW-ENVIRON subnegotiation buffer + * + * the algorithm and approach used here is kind of a hack, + * but it reduces the number of memory allocations we have + * to make. + * + * we copy the bytes back into the buffer, starting at the very + * beginning, which makes it easy to handle the ENVIRON ESC + * escape mechanism as well as ensure the variable name and + * value strings are NUL-terminated, all while fitting inside + * of the original buffer. + */ +static int _environ_telnet(telnet_t *telnet, unsigned char type, + char* buffer, size_t size) { + telnet_event_t ev; + struct telnet_environ_t *values = 0; + char *c, *last, *out; + size_t index, count; + + /* if we have no data, just pass it through */ + if (size == 0) { + return 0; + } + + /* first byte must be a valid command */ + if ((unsigned)buffer[0] != TELNET_ENVIRON_SEND && + (unsigned)buffer[0] != TELNET_ENVIRON_IS && + (unsigned)buffer[0] != TELNET_ENVIRON_INFO) { + _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0, + "telopt %d subneg has invalid command", type); + return 0; + } + + /* store ENVIRON command */ + ev.environ.cmd = buffer[0]; + + /* if we have no arguments, send an event with no data end return */ + if (size == 1) { + /* no list of variables given */ + ev.environ.values = 0; + ev.environ.size = 0; + + /* invoke event with our arguments */ + ev.type = TELNET_EV_ENVIRON; + telnet->eh(telnet, &ev, telnet->ud); + + return 1; + } + + /* very second byte must be VAR or USERVAR, if present */ + if ((unsigned)buffer[1] != TELNET_ENVIRON_VAR && + (unsigned)buffer[1] != TELNET_ENVIRON_USERVAR) { + _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0, + "telopt %d subneg missing variable type", type); + return 0; + } + + /* ensure last byte is not an escape byte (makes parsing later easier) */ + if ((unsigned)buffer[size - 1] == TELNET_ENVIRON_ESC) { + _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0, + "telopt %d subneg ends with ESC", type); + return 0; + } + + /* count arguments; each valid entry starts with VAR or USERVAR */ + count = 0; + for (c = buffer + 1; c < buffer + size; ++c) { + if (*c == TELNET_ENVIRON_VAR || *c == TELNET_ENVIRON_USERVAR) { + ++count; + } else if (*c == TELNET_ENVIRON_ESC) { + /* skip the next byte */ + ++c; + } + } + + /* allocate argument array, bail on error */ + if ((values = (struct telnet_environ_t *)calloc(count, + sizeof(struct telnet_environ_t))) == 0) { + _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0, + "calloc() failed: %s", strerror(errno)); + return 0; + } + + /* parse argument array strings */ + out = buffer; + c = buffer + 1; + for (index = 0; index != count; ++index) { + /* remember the variable type (will be VAR or USERVAR) */ + values[index].type = *c++; + + /* scan until we find an end-marker, and buffer up unescaped + * bytes into our buffer */ + last = out; + while (c < buffer + size) { + /* stop at the next variable or at the value */ + if ((unsigned)*c == TELNET_ENVIRON_VAR || + (unsigned)*c == TELNET_ENVIRON_VALUE || + (unsigned)*c == TELNET_ENVIRON_USERVAR) { + break; + } + + /* buffer next byte (taking into account ESC) */ + if (*c == TELNET_ENVIRON_ESC) { + ++c; + } + + *out++ = *c++; + } + *out++ = '\0'; + + /* store the variable name we have just received */ + values[index].var = last; + values[index].value = ""; + + /* if we got a value, find the next end marker and + * store the value; otherwise, store empty string */ + if (c < buffer + size && *c == TELNET_ENVIRON_VALUE) { + ++c; + last = out; + while (c < buffer + size) { + /* stop when we find the start of the next variable */ + if ((unsigned)*c == TELNET_ENVIRON_VAR || + (unsigned)*c == TELNET_ENVIRON_USERVAR) { + break; + } + + /* buffer next byte (taking into account ESC) */ + if (*c == TELNET_ENVIRON_ESC) { + ++c; + } + + *out++ = *c++; + } + *out++ = '\0'; + + /* store the variable value */ + values[index].value = last; + } + } + + /* pass values array and count to event */ + ev.environ.values = values; + ev.environ.size = count; + + /* invoke event with our arguments */ + ev.type = TELNET_EV_ENVIRON; + telnet->eh(telnet, &ev, telnet->ud); + + /* clean up */ + free(values); + return 1; +} + +/* process an MSSP subnegotiation buffer */ +static int _mssp_telnet(telnet_t *telnet, char* buffer, size_t size) { + telnet_event_t ev; + struct telnet_environ_t *values; + char *var = 0; + char *c, *last, *out; + size_t i, count; + unsigned char next_type; + + /* if we have no data, just pass it through */ + if (size == 0) { + return 0; + } + + /* first byte must be a VAR */ + if ((unsigned)buffer[0] != TELNET_MSSP_VAR) { + _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0, + "MSSP subnegotiation has invalid data"); + return 0; + } + + /* count the arguments, any part that starts with VALUE */ + for (count = 0, i = 0; i != size; ++i) { + if ((unsigned)buffer[i] == TELNET_MSSP_VAL) { + ++count; + } + } + + /* allocate argument array, bail on error */ + if ((values = (struct telnet_environ_t *)calloc(count, + sizeof(struct telnet_environ_t))) == 0) { + _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0, + "calloc() failed: %s", strerror(errno)); + return 0; + } + + ev.mssp.values = values; + ev.mssp.size = count; + + /* allocate strings in argument array */ + out = last = buffer; + next_type = buffer[0]; + for (i = 0, c = buffer + 1; c < buffer + size;) { + /* search for end marker */ + while (c < buffer + size && (unsigned)*c != TELNET_MSSP_VAR && + (unsigned)*c != TELNET_MSSP_VAL) { + *out++ = *c++; + } + *out++ = '\0'; + + /* if it's a variable name, just store the name for now */ + if (next_type == TELNET_MSSP_VAR) { + var = last; + } else if (next_type == TELNET_MSSP_VAL && var != 0) { + values[i].var = var; + values[i].value = last; + ++i; + } else { + _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0, + "invalid MSSP subnegotiation data"); + free(values); + return 0; + } + + /* remember our next type and increment c for next loop run */ + last = out; + next_type = *c++; + } + + /* invoke event with our arguments */ + ev.type = TELNET_EV_MSSP; + telnet->eh(telnet, &ev, telnet->ud); + + /* clean up */ + free(values); + + return 0; +} + +/* parse ZMP command subnegotiation buffers */ +static int _zmp_telnet(telnet_t *telnet, const char* buffer, size_t size) { + telnet_event_t ev; + const char **argv; + const char *c; + size_t i, argc; + + /* make sure this is a valid ZMP buffer */ + if (size == 0 || buffer[size - 1] != 0) { + _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0, + "incomplete ZMP frame"); + return 0; + } + + /* count arguments */ + for (argc = 0, c = buffer; c != buffer + size; ++argc) + c += strlen(c) + 1; + + /* allocate argument array, bail on error */ + if ((argv = (const char **)calloc(argc, sizeof(char *))) == 0) { + _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0, + "calloc() failed: %s", strerror(errno)); + return 0; + } + + /* populate argument array */ + for (i = 0, c = buffer; i != argc; ++i) { + argv[i] = c; + c += strlen(c) + 1; + } + + /* invoke event with our arguments */ + ev.type = TELNET_EV_ZMP; + ev.zmp.argv = argv; + ev.zmp.argc = argc; + telnet->eh(telnet, &ev, telnet->ud); + + /* clean up */ + free(argv); + return 0; +} + +/* parse TERMINAL-TYPE command subnegotiation buffers */ +static int _ttype_telnet(telnet_t *telnet, const char* buffer, size_t size) { + telnet_event_t ev; + + /* make sure request is not empty */ + if (size == 0) { + _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0, + "incomplete TERMINAL-TYPE request"); + return 0; + } + + /* make sure request has valid command type */ + if (buffer[0] != TELNET_TTYPE_IS && + buffer[0] != TELNET_TTYPE_SEND) { + _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0, + "TERMINAL-TYPE request has invalid type"); + return 0; + } + + /* send proper event */ + if (buffer[0] == TELNET_TTYPE_IS) { + char *name; + + /* allocate space for name */ + if ((name = (char *)malloc(size)) == 0) { + _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0, + "malloc() failed: %s", strerror(errno)); + return 0; + } + memcpy(name, buffer + 1, size - 1); + name[size - 1] = '\0'; + + ev.type = TELNET_EV_TTYPE; + ev.ttype.cmd = TELNET_TTYPE_IS; + ev.ttype.name = name; + telnet->eh(telnet, &ev, telnet->ud); + + /* clean up */ + free(name); + } else { + ev.type = TELNET_EV_TTYPE; + ev.ttype.cmd = TELNET_TTYPE_SEND; + ev.ttype.name = 0; + telnet->eh(telnet, &ev, telnet->ud); + } + + return 0; +} + +/* process a subnegotiation buffer; return non-zero if the current buffer + * must be aborted and reprocessed due to COMPRESS2 being activated + */ +static int _subnegotiate(telnet_t *telnet) { + telnet_event_t ev; + + /* standard subnegotiation event */ + ev.type = TELNET_EV_SUBNEGOTIATION; + ev.sub.telopt = telnet->sb_telopt; + ev.sub.buffer = telnet->buffer; + ev.sub.size = telnet->buffer_pos; + telnet->eh(telnet, &ev, telnet->ud); + + switch (telnet->sb_telopt) { +#if defined(HAVE_ZLIB) + /* received COMPRESS2 begin marker, setup our zlib box and + * start handling the compressed stream if it's not already. + */ + case TELNET_TELOPT_COMPRESS2: + if (telnet->sb_telopt == TELNET_TELOPT_COMPRESS2) { + if (_init_zlib(telnet, 0, 1) != TELNET_EOK) + return 0; + + /* notify app that compression was enabled */ + ev.type = TELNET_EV_COMPRESS; + ev.compress.state = 1; + telnet->eh(telnet, &ev, telnet->ud); + return 1; + } + return 0; +#endif /* defined(HAVE_ZLIB) */ + + /* specially handled subnegotiation telopt types */ + case TELNET_TELOPT_ZMP: + return _zmp_telnet(telnet, telnet->buffer, telnet->buffer_pos); + case TELNET_TELOPT_TTYPE: + return _ttype_telnet(telnet, telnet->buffer, telnet->buffer_pos); + case TELNET_TELOPT_ENVIRON: + case TELNET_TELOPT_NEW_ENVIRON: + return _environ_telnet(telnet, telnet->sb_telopt, telnet->buffer, + telnet->buffer_pos); + case TELNET_TELOPT_MSSP: + return _mssp_telnet(telnet, telnet->buffer, telnet->buffer_pos); + default: + return 0; + } +} + +/* initialize a telnet state tracker */ +telnet_t *telnet_init(const telnet_telopt_t *telopts, + telnet_event_handler_t eh, unsigned char flags, void *user_data) { + /* allocate structure */ + struct telnet_t *telnet = (telnet_t*)calloc(1, sizeof(telnet_t)); + if (telnet == 0) + return 0; + + /* initialize data */ + telnet->ud = user_data; + telnet->telopts = telopts; + telnet->eh = eh; + telnet->flags = flags; + + return telnet; +} + +/* free up any memory allocated by a state tracker */ +void telnet_free(telnet_t *telnet) { + /* free sub-request buffer */ + if (telnet->buffer != 0) { + free(telnet->buffer); + telnet->buffer = 0; + telnet->buffer_size = 0; + telnet->buffer_pos = 0; + } + +#if defined(HAVE_ZLIB) + /* free zlib box */ + if (telnet->z != 0) { + if (telnet->flags & TELNET_PFLAG_DEFLATE) + deflateEnd(telnet->z); + else + inflateEnd(telnet->z); + free(telnet->z); + telnet->z = 0; + } +#endif /* defined(HAVE_ZLIB) */ + + /* free RFC1143 queue */ + if (telnet->q) { + free(telnet->q); + telnet->q = 0; + telnet->q_size = 0; + } + + /* free the telnet structure itself */ + free(telnet); +} + +/* push a byte into the telnet buffer */ +static telnet_error_t _buffer_byte(telnet_t *telnet, + unsigned char byte) { + char *new_buffer; + size_t i; + + /* check if we're out of room */ + if (telnet->buffer_pos == telnet->buffer_size) { + /* find the next buffer size */ + for (i = 0; i != _buffer_sizes_count; ++i) { + if (_buffer_sizes[i] == telnet->buffer_size) { + break; + } + } + + /* overflow -- can't grow any more */ + if (i >= _buffer_sizes_count - 1) { + _error(telnet, __LINE__, __func__, TELNET_EOVERFLOW, 0, + "subnegotiation buffer size limit reached"); + return TELNET_EOVERFLOW; + } + + /* (re)allocate buffer */ + new_buffer = (char *)realloc(telnet->buffer, _buffer_sizes[i + 1]); + if (new_buffer == 0) { + _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0, + "realloc() failed"); + return TELNET_ENOMEM; + } + + telnet->buffer = new_buffer; + telnet->buffer_size = _buffer_sizes[i + 1]; + } + + /* push the byte, all set */ + telnet->buffer[telnet->buffer_pos++] = byte; + return TELNET_EOK; +} + +static void _process(telnet_t *telnet, const char *buffer, size_t size) { + telnet_event_t ev; + unsigned char byte; + size_t i, start; + for (i = start = 0; i != size; ++i) { + byte = buffer[i]; + switch (telnet->state) { + /* regular data */ + case TELNET_STATE_DATA: + /* on an IAC byte, pass through all pending bytes and + * switch states */ + if (byte == TELNET_IAC) { + if (i != start) { + ev.type = TELNET_EV_DATA; + ev.data.buffer = buffer + start; + ev.data.size = i - start; + telnet->eh(telnet, &ev, telnet->ud); + } + telnet->state = TELNET_STATE_IAC; + } + break; + + /* IAC command */ + case TELNET_STATE_IAC: + switch (byte) { + /* subnegotiation */ + case TELNET_SB: + telnet->state = TELNET_STATE_SB; + break; + /* negotiation commands */ + case TELNET_WILL: + telnet->state = TELNET_STATE_WILL; + break; + case TELNET_WONT: + telnet->state = TELNET_STATE_WONT; + break; + case TELNET_DO: + telnet->state = TELNET_STATE_DO; + break; + case TELNET_DONT: + telnet->state = TELNET_STATE_DONT; + break; + /* IAC escaping */ + case TELNET_IAC: + /* event */ + ev.type = TELNET_EV_DATA; + ev.data.buffer = (char*)&byte; + ev.data.size = 1; + telnet->eh(telnet, &ev, telnet->ud); + + /* state update */ + start = i + 1; + telnet->state = TELNET_STATE_DATA; + break; + /* some other command */ + default: + /* event */ + ev.type = TELNET_EV_IAC; + ev.iac.cmd = byte; + telnet->eh(telnet, &ev, telnet->ud); + + /* state update */ + start = i + 1; + telnet->state = TELNET_STATE_DATA; + } + break; + + /* negotiation commands */ + case TELNET_STATE_WILL: + case TELNET_STATE_WONT: + case TELNET_STATE_DO: + case TELNET_STATE_DONT: + _negotiate(telnet, byte); + start = i + 1; + telnet->state = TELNET_STATE_DATA; + break; + + /* subnegotiation -- determine subnegotiation telopt */ + case TELNET_STATE_SB: + telnet->sb_telopt = byte; + telnet->buffer_pos = 0; + telnet->state = TELNET_STATE_SB_DATA; + break; + + /* subnegotiation -- buffer bytes until end request */ + case TELNET_STATE_SB_DATA: + /* IAC command in subnegotiation -- either IAC SE or IAC IAC */ + if (byte == TELNET_IAC) { + telnet->state = TELNET_STATE_SB_DATA_IAC; + /* buffer the byte, or bail if we can't */ + } else if (_buffer_byte(telnet, byte) != TELNET_EOK) { + start = i + 1; + telnet->state = TELNET_STATE_DATA; + } + break; + + /* IAC escaping inside a subnegotiation */ + case TELNET_STATE_SB_DATA_IAC: + switch (byte) { + /* end subnegotiation */ + case TELNET_SE: + /* return to default state */ + start = i + 1; + telnet->state = TELNET_STATE_DATA; + + /* process subnegotiation */ + if (_subnegotiate(telnet) != 0) { + /* any remaining bytes in the buffer are compressed. + * we have to re-invoke telnet_recv to get those + * bytes inflated and abort trying to process the + * remaining compressed bytes in the current _process + * buffer argument + */ + telnet_recv(telnet, &buffer[start], size - start); + return; + } + break; + /* escaped IAC byte */ + case TELNET_IAC: + /* push IAC into buffer */ + if (_buffer_byte(telnet, TELNET_IAC) != + TELNET_EOK) { + start = i + 1; + telnet->state = TELNET_STATE_DATA; + } else { + telnet->state = TELNET_STATE_SB_DATA; + } + break; + /* something else -- protocol error. attempt to process + * content in subnegotiation buffer, then evaluate the + * given command as an IAC code. + */ + default: + _error(telnet, __LINE__, __func__, TELNET_EPROTOCOL, 0, + "unexpected byte after IAC inside SB: %d", + byte); + + /* enter IAC state */ + start = i + 1; + telnet->state = TELNET_STATE_IAC; + + /* process subnegotiation; see comment in + * TELNET_STATE_SB_DATA_IAC about invoking telnet_recv() + */ + if (_subnegotiate(telnet) != 0) { + telnet_recv(telnet, &buffer[start], size - start); + return; + } else { + /* recursive call to get the current input byte processed + * as a regular IAC command. we could use a goto, but + * that would be gross. + */ + _process(telnet, (char *)&byte, 1); + } + break; + } + break; + } + } + + /* pass through any remaining bytes */ + if (telnet->state == TELNET_STATE_DATA && i != start) { + ev.type = TELNET_EV_DATA; + ev.data.buffer = buffer + start; + ev.data.size = i - start; + telnet->eh(telnet, &ev, telnet->ud); + } +} + +/* push a bytes into the state tracker */ +void telnet_recv(telnet_t *telnet, const char *buffer, + size_t size) { +#if defined(HAVE_ZLIB) + /* if we have an inflate (decompression) zlib stream, use it */ + if (telnet->z != 0 && !(telnet->flags & TELNET_PFLAG_DEFLATE)) { + char inflate_buffer[1024]; + int rs; + + /* initialize zlib state */ + telnet->z->next_in = (unsigned char*)buffer; + telnet->z->avail_in = size; + telnet->z->next_out = (unsigned char *)inflate_buffer; + telnet->z->avail_out = sizeof(inflate_buffer); + + /* inflate until buffer exhausted and all output is produced */ + while (telnet->z->avail_in > 0 || telnet->z->avail_out == 0) { + /* reset output buffer */ + + /* decompress */ + rs = inflate(telnet->z, Z_SYNC_FLUSH); + + /* process the decompressed bytes on success */ + if (rs == Z_OK || rs == Z_STREAM_END) + _process(telnet, inflate_buffer, sizeof(inflate_buffer) - + telnet->z->avail_out); + else + _error(telnet, __LINE__, __func__, TELNET_ECOMPRESS, 1, + "inflate() failed: %s", zError(rs)); + + /* prepare output buffer for next run */ + telnet->z->next_out = (unsigned char *)inflate_buffer; + telnet->z->avail_out = sizeof(inflate_buffer); + + /* on error (or on end of stream) disable further inflation */ + if (rs != Z_OK) { + telnet_event_t ev; + + /* disable compression */ + inflateEnd(telnet->z); + free(telnet->z); + telnet->z = 0; + + /* send event */ + ev.type = TELNET_EV_COMPRESS; + ev.compress.state = 0; + telnet->eh(telnet, &ev, telnet->ud); + + break; + } + } + + /* COMPRESS2 is not negotiated, just process */ + } else +#endif /* defined(HAVE_ZLIB) */ + _process(telnet, buffer, size); +} + +/* send an iac command */ +void telnet_iac(telnet_t *telnet, unsigned char cmd) { + unsigned char bytes[2]; + bytes[0] = TELNET_IAC; + bytes[1] = cmd; + _sendu(telnet, bytes, 2); +} + +/* send negotiation */ +void telnet_negotiate(telnet_t *telnet, unsigned char cmd, + unsigned char telopt) { + telnet_rfc1143_t q; + + /* if we're in proxy mode, just send it now */ + if (telnet->flags & TELNET_FLAG_PROXY) { + unsigned char bytes[3]; + bytes[0] = TELNET_IAC; + bytes[1] = cmd; + bytes[2] = telopt; + _sendu(telnet, bytes, 3); + return; + } + + /* get current option states */ + q = _get_rfc1143(telnet, telopt); + + switch (cmd) { + /* advertise willingess to support an option */ + case TELNET_WILL: + switch (Q_US(q)) { + case Q_NO: + _set_rfc1143(telnet, telopt, Q_WANTYES, Q_HIM(q)); + _send_negotiate(telnet, TELNET_WILL, telopt); + break; + case Q_WANTNO: + _set_rfc1143(telnet, telopt, Q_WANTNO_OP, Q_HIM(q)); + break; + case Q_WANTYES_OP: + _set_rfc1143(telnet, telopt, Q_WANTYES, Q_HIM(q)); + break; + } + break; + + /* force turn-off of locally enabled option */ + case TELNET_WONT: + switch (Q_US(q)) { + case Q_YES: + _set_rfc1143(telnet, telopt, Q_WANTNO, Q_HIM(q)); + _send_negotiate(telnet, TELNET_WONT, telopt); + break; + case Q_WANTYES: + _set_rfc1143(telnet, telopt, Q_WANTYES_OP, Q_HIM(q)); + break; + case Q_WANTNO_OP: + _set_rfc1143(telnet, telopt, Q_WANTNO, Q_HIM(q)); + break; + } + break; + + /* ask remote end to enable an option */ + case TELNET_DO: + switch (Q_HIM(q)) { + case Q_NO: + _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTYES); + _send_negotiate(telnet, TELNET_DO, telopt); + break; + case Q_WANTNO: + _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTNO_OP); + break; + case Q_WANTYES_OP: + _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTYES); + break; + } + break; + + /* demand remote end disable an option */ + case TELNET_DONT: + switch (Q_HIM(q)) { + case Q_YES: + _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTNO); + _send_negotiate(telnet, TELNET_DONT, telopt); + break; + case Q_WANTYES: + _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTYES_OP); + break; + case Q_WANTNO_OP: + _set_rfc1143(telnet, telopt, Q_US(q), Q_WANTNO); + break; + } + break; + } +} + +/* send non-command data (escapes IAC bytes) */ +void telnet_send(telnet_t *telnet, const char *buffer, + size_t size) { + size_t i, l; + + for (l = i = 0; i != size; ++i) { + /* dump prior portion of text, send escaped bytes */ + if (buffer[i] == (char)TELNET_IAC) { + /* dump prior text if any */ + if (i != l) { + _send(telnet, buffer + l, i - l); + } + l = i + 1; + + /* send escape */ + telnet_iac(telnet, TELNET_IAC); + } + } + + /* send whatever portion of buffer is left */ + if (i != l) { + _send(telnet, buffer + l, i - l); + } +} + +/* send subnegotiation header */ +void telnet_begin_sb(telnet_t *telnet, unsigned char telopt) { + unsigned char sb[3]; + sb[0] = TELNET_IAC; + sb[1] = TELNET_SB; + sb[2] = telopt; + _sendu(telnet, sb, 3); +} + + +/* send complete subnegotiation */ +void telnet_subnegotiation(telnet_t *telnet, unsigned char telopt, + const char *buffer, size_t size) { + unsigned char bytes[5]; + bytes[0] = TELNET_IAC; + bytes[1] = TELNET_SB; + bytes[2] = telopt; + bytes[3] = TELNET_IAC; + bytes[4] = TELNET_SE; + + _sendu(telnet, bytes, 3); + telnet_send(telnet, buffer, size); + _sendu(telnet, bytes + 3, 2); + +#if defined(HAVE_ZLIB) + /* if we're a proxy and we just sent the COMPRESS2 marker, we must + * make sure all further data is compressed if not already. + */ + if (telnet->flags & TELNET_FLAG_PROXY && + telopt == TELNET_TELOPT_COMPRESS2) { + telnet_event_t ev; + + if (_init_zlib(telnet, 1, 1) != TELNET_EOK) + return; + + /* notify app that compression was enabled */ + ev.type = TELNET_EV_COMPRESS; + ev.compress.state = 1; + telnet->eh(telnet, &ev, telnet->ud); + } +#endif /* defined(HAVE_ZLIB) */ +} + +void telnet_begin_compress2(telnet_t *telnet) { + UNUSED_ARG(telnet); +#if defined(HAVE_ZLIB) + static const unsigned char compress2[] = { TELNET_IAC, TELNET_SB, + TELNET_TELOPT_COMPRESS2, TELNET_IAC, TELNET_SE }; + + telnet_event_t ev; + + /* attempt to create output stream first, bail if we can't */ + if (_init_zlib(telnet, 1, 0) != TELNET_EOK) + return; + + /* send compression marker. we send directly to the event handler + * instead of passing through _send because _send would result in + * the compress marker itself being compressed. + */ + ev.type = TELNET_EV_SEND; + ev.data.buffer = (const char*)compress2; + ev.data.size = sizeof(compress2); + telnet->eh(telnet, &ev, telnet->ud); + + /* notify app that compression was successfully enabled */ + ev.type = TELNET_EV_COMPRESS; + ev.compress.state = 1; + telnet->eh(telnet, &ev, telnet->ud); +#endif /* defined(HAVE_ZLIB) */ +} + +/* send formatted data with \r and \n translation in addition to IAC IAC */ +int telnet_vprintf(telnet_t *telnet, const char *fmt, va_list va) { + static const char CRLF[] = { '\r', '\n' }; + static const char CRNUL[] = { '\r', '\0' }; + char buffer[1024]; + char *output = buffer; + int rs, i, l; + + /* format */ + rs = vsnprintf(buffer, sizeof(buffer), fmt, va); + if ((size_t)rs >= sizeof(buffer)) { + output = (char*)malloc(rs + 1); + if (output == 0) { + _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0, + "malloc() failed: %s", strerror(errno)); + return -1; + } + rs = vsnprintf(output, rs + 1, fmt, va); + } + + /* send */ + for (l = i = 0; i != rs; ++i) { + /* special characters */ + if (output[i] == (char)TELNET_IAC || output[i] == '\r' || + output[i] == '\n') { + /* dump prior portion of text */ + if (i != l) + _send(telnet, output + l, i - l); + l = i + 1; + + /* IAC -> IAC IAC */ + if (output[i] == (char)TELNET_IAC) + telnet_iac(telnet, TELNET_IAC); + /* automatic translation of \r -> CRNUL */ + else if (output[i] == '\r') + _send(telnet, CRNUL, 2); + /* automatic translation of \n -> CRLF */ + else if (output[i] == '\n') + _send(telnet, CRLF, 2); + } + } + + /* send whatever portion of output is left */ + if (i != l) { + _send(telnet, output + l, i - l); + } + + /* free allocated memory, if any */ + if (output != buffer) { + free(output); + } + + return rs; +} + +/* see telnet_vprintf */ +int telnet_printf(telnet_t *telnet, const char *fmt, ...) { + va_list va; + int rs; + + va_start(va, fmt); + rs = telnet_vprintf(telnet, fmt, va); + va_end(va); + + return rs; +} + +/* send formatted data through telnet_send */ +int telnet_raw_vprintf(telnet_t *telnet, const char *fmt, va_list va) { + char buffer[1024]; + char *output = buffer; + int rs; + + /* format; allocate more space if necessary */ + rs = vsnprintf(buffer, sizeof(buffer), fmt, va); + if ((size_t)rs >= sizeof(buffer)) { + output = (char*)malloc(rs + 1); + if (output == 0) { + _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0, + "malloc() failed: %s", strerror(errno)); + return -1; + } + rs = vsnprintf(output, rs + 1, fmt, va); + } + + /* send out the formatted data */ + telnet_send(telnet, output, rs); + + /* release allocated memory, if any */ + if (output != buffer) { + free(output); + } + + return rs; +} + +/* see telnet_raw_vprintf */ +int telnet_raw_printf(telnet_t *telnet, const char *fmt, ...) { + va_list va; + int rs; + + va_start(va, fmt); + rs = telnet_raw_vprintf(telnet, fmt, va); + va_end(va); + + return rs; +} + +/* begin NEW-ENVIRON subnegotation */ +void telnet_begin_newenviron(telnet_t *telnet, unsigned char cmd) { + telnet_begin_sb(telnet, TELNET_TELOPT_NEW_ENVIRON); + telnet_send(telnet, (char*)&cmd, 1); +} + +/* send a NEW-ENVIRON value */ +void telnet_newenviron_value(telnet_t *telnet, unsigned char type, + const char *string) { + telnet_send(telnet, (char*)&type, 1); + + if (string != 0) { + telnet_send(telnet, string, strlen(string)); + } +} + +/* send TERMINAL-TYPE SEND command */ +void telnet_ttype_send(telnet_t *telnet) { + static const unsigned char SEND[] = { TELNET_IAC, TELNET_SB, + TELNET_TELOPT_TTYPE, TELNET_TTYPE_SEND, TELNET_IAC, TELNET_SE }; + _sendu(telnet, SEND, sizeof(SEND)); +} + +/* send TERMINAL-TYPE IS command */ +void telnet_ttype_is(telnet_t *telnet, const char* ttype) { + static const unsigned char IS[] = { TELNET_IAC, TELNET_SB, + TELNET_TELOPT_TTYPE, TELNET_TTYPE_IS }; + _sendu(telnet, IS, sizeof(IS)); + _send(telnet, ttype, strlen(ttype)); + telnet_finish_sb(telnet); +} + +/* send ZMP data */ +void telnet_send_zmp(telnet_t *telnet, size_t argc, const char **argv) { + size_t i; + + /* ZMP header */ + telnet_begin_zmp(telnet, argv[0]); + + /* send out each argument, including trailing NUL byte */ + for (i = 1; i != argc; ++i) + telnet_zmp_arg(telnet, argv[i]); + + /* ZMP footer */ + telnet_finish_zmp(telnet); +} + +/* send ZMP data using varargs */ +void telnet_send_vzmpv(telnet_t *telnet, va_list va) { + const char* arg; + + /* ZMP header */ + telnet_begin_sb(telnet, TELNET_TELOPT_ZMP); + + /* send out each argument, including trailing NUL byte */ + while ((arg = va_arg(va, const char *)) != 0) + telnet_zmp_arg(telnet, arg); + + /* ZMP footer */ + telnet_finish_zmp(telnet); +} + +/* see telnet_send_vzmpv */ +void telnet_send_zmpv(telnet_t *telnet, ...) { + va_list va; + + va_start(va, telnet); + telnet_send_vzmpv(telnet, va); + va_end(va); +} + +/* begin a ZMP command */ +void telnet_begin_zmp(telnet_t *telnet, const char *cmd) { + telnet_begin_sb(telnet, TELNET_TELOPT_ZMP); + telnet_zmp_arg(telnet, cmd); +} + +/* send a ZMP argument */ +void telnet_zmp_arg(telnet_t *telnet, const char* arg) { + telnet_send(telnet, arg, strlen(arg) + 1); +} diff --git a/src/apps/relay/libtelnet.h b/src/apps/relay/libtelnet.h new file mode 100644 index 00000000..b36cc874 --- /dev/null +++ b/src/apps/relay/libtelnet.h @@ -0,0 +1,677 @@ +/*! + * \brief libtelnet - TELNET protocol handling library + * + * SUMMARY: + * + * libtelnet is a library for handling the TELNET protocol. It includes + * routines for parsing incoming data from a remote peer as well as formatting + * data to send to the remote peer. + * + * libtelnet uses a callback-oriented API, allowing application-specific + * handling of various events. The callback system is also used for buffering + * outgoing protocol data, allowing the application to maintain control over + * the actual socket connection. + * + * Features supported include the full TELNET protocol, Q-method option + * negotiation, ZMP, MCCP2, MSSP, and NEW-ENVIRON. + * + * CONFORMS TO: + * + * RFC854 - http://www.faqs.org/rfcs/rfc854.html + * RFC855 - http://www.faqs.org/rfcs/rfc855.html + * RFC1091 - http://www.faqs.org/rfcs/rfc1091.html + * RFC1143 - http://www.faqs.org/rfcs/rfc1143.html + * RFC1408 - http://www.faqs.org/rfcs/rfc1408.html + * RFC1572 - http://www.faqs.org/rfcs/rfc1572.html + * + * LICENSE: + * + * The author or authors of this code dedicate any and all copyright interest + * in this code to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and successors. We + * intend this dedication to be an overt act of relinquishment in perpetuity of + * all present and future rights to this code under copyright law. + * + * \file libtelnet.h + * + * \version 0.21 + * + * \author Sean Middleditch + */ + +/** + * Minor fixes by Oleg Moskalenko + */ + +#if !defined(LIBTELNET_INCLUDE) +#define LIBTELNET_INCLUDE 1 + +/* standard C headers necessary for the libtelnet API */ +#include + +/* C++ support */ +#if defined(__cplusplus) +extern "C" { +#endif + +/* printf type checking feature in GCC and some other compilers */ +#if __GNUC__ +# define TELNET_GNU_PRINTF(f,a) __attribute__((format(printf, f, a))) /*!< internal helper */ +#else +# define TELNET_GNU_PRINTF(f,a) /*!< internal helper */ +#endif + +/*! Telnet state tracker object type. */ +typedef struct telnet_t telnet_t; + +/*! Telnet event object type. */ +typedef union telnet_event_t telnet_event_t; + +/*! Telnet option table element type. */ +typedef struct telnet_telopt_t telnet_telopt_t; + +/*! \name Telnet commands */ +/*@{*/ +/*! Telnet commands and special values. */ +#define TELNET_IAC 255 +#define TELNET_DONT 254 +#define TELNET_DO 253 +#define TELNET_WONT 252 +#define TELNET_WILL 251 +#define TELNET_SB 250 +#define TELNET_GA 249 +#define TELNET_EL 248 +#define TELNET_EC 247 +#define TELNET_AYT 246 +#define TELNET_AO 245 +#define TELNET_IP 244 +#define TELNET_BREAK 243 +#define TELNET_DM 242 +#define TELNET_NOP 241 +#define TELNET_SE 240 +#define TELNET_EOR 239 +#define TELNET_ABORT 238 +#define TELNET_SUSP 237 +#define TELNET_EOF 236 +/*@}*/ + +/*! \name Telnet option values. */ +/*@{*/ +/*! Telnet options. */ +#define TELNET_TELOPT_BINARY 0 +#define TELNET_TELOPT_ECHO 1 +#define TELNET_TELOPT_RCP 2 +#define TELNET_TELOPT_SGA 3 +#define TELNET_TELOPT_NAMS 4 +#define TELNET_TELOPT_STATUS 5 +#define TELNET_TELOPT_TM 6 +#define TELNET_TELOPT_RCTE 7 +#define TELNET_TELOPT_NAOL 8 +#define TELNET_TELOPT_NAOP 9 +#define TELNET_TELOPT_NAOCRD 10 +#define TELNET_TELOPT_NAOHTS 11 +#define TELNET_TELOPT_NAOHTD 12 +#define TELNET_TELOPT_NAOFFD 13 +#define TELNET_TELOPT_NAOVTS 14 +#define TELNET_TELOPT_NAOVTD 15 +#define TELNET_TELOPT_NAOLFD 16 +#define TELNET_TELOPT_XASCII 17 +#define TELNET_TELOPT_LOGOUT 18 +#define TELNET_TELOPT_BM 19 +#define TELNET_TELOPT_DET 20 +#define TELNET_TELOPT_SUPDUP 21 +#define TELNET_TELOPT_SUPDUPOUTPUT 22 +#define TELNET_TELOPT_SNDLOC 23 +#define TELNET_TELOPT_TTYPE 24 +#define TELNET_TELOPT_EOR 25 +#define TELNET_TELOPT_TUID 26 +#define TELNET_TELOPT_OUTMRK 27 +#define TELNET_TELOPT_TTYLOC 28 +#define TELNET_TELOPT_3270REGIME 29 +#define TELNET_TELOPT_X3PAD 30 +#define TELNET_TELOPT_NAWS 31 +#define TELNET_TELOPT_TSPEED 32 +#define TELNET_TELOPT_LFLOW 33 +#define TELNET_TELOPT_LINEMODE 34 +#define TELNET_TELOPT_XDISPLOC 35 +#define TELNET_TELOPT_ENVIRON 36 +#define TELNET_TELOPT_AUTHENTICATION 37 +#define TELNET_TELOPT_ENCRYPT 38 +#define TELNET_TELOPT_NEW_ENVIRON 39 +#define TELNET_TELOPT_MSSP 70 +#define TELNET_TELOPT_COMPRESS2 86 +#define TELNET_TELOPT_ZMP 93 +#define TELNET_TELOPT_EXOPL 255 + +#define TELNET_TELOPT_MCCP2 86 +/*@}*/ + +/*! \name Protocol codes for TERMINAL-TYPE commands. */ +/*@{*/ +/*! TERMINAL-TYPE codes. */ +#define TELNET_TTYPE_IS 0 +#define TELNET_TTYPE_SEND 1 +/*@}*/ + +/*! \name Protocol codes for NEW-ENVIRON/ENVIRON commands. */ +/*@{*/ +/*! NEW-ENVIRON/ENVIRON codes. */ +#define TELNET_ENVIRON_IS 0 +#define TELNET_ENVIRON_SEND 1 +#define TELNET_ENVIRON_INFO 2 +#define TELNET_ENVIRON_VAR 0 +#define TELNET_ENVIRON_VALUE 1 +#define TELNET_ENVIRON_ESC 2 +#define TELNET_ENVIRON_USERVAR 3 +/*@}*/ + +/*! \name Protocol codes for MSSP commands. */ +/*@{*/ +/*! MSSP codes. */ +#define TELNET_MSSP_VAR 1 +#define TELNET_MSSP_VAL 2 +/*@}*/ + +/*! \name Telnet state tracker flags. */ +/*@{*/ +/*! Control behavior of telnet state tracker. */ +#define TELNET_FLAG_PROXY (1<<0) + +#define TELNET_PFLAG_DEFLATE (1<<7) +/*@}*/ + +#if !defined(UNUSED_ARG) +#define UNUSED_ARG(A) do { A=A; } while(0) +#endif + +/*! + * error codes + */ +enum telnet_error_t { + TELNET_EOK = 0, /*!< no error */ + TELNET_EBADVAL, /*!< invalid parameter, or API misuse */ + TELNET_ENOMEM, /*!< memory allocation failure */ + TELNET_EOVERFLOW, /*!< data exceeds buffer size */ + TELNET_EPROTOCOL, /*!< invalid sequence of special bytes */ + TELNET_ECOMPRESS /*!< error handling compressed streams */ +}; +typedef enum telnet_error_t telnet_error_t; /*!< Error code type. */ + +/*! + * event codes + */ +enum telnet_event_type_t { + TELNET_EV_DATA = 0, /*!< raw text data has been received */ + TELNET_EV_SEND, /*!< data needs to be sent to the peer */ + TELNET_EV_IAC, /*!< generic IAC code received */ + TELNET_EV_WILL, /*!< WILL option negotiation received */ + TELNET_EV_WONT, /*!< WONT option neogitation received */ + TELNET_EV_DO, /*!< DO option negotiation received */ + TELNET_EV_DONT, /*!< DONT option negotiation received */ + TELNET_EV_SUBNEGOTIATION, /*!< sub-negotiation data received */ + TELNET_EV_COMPRESS, /*!< compression has been enabled */ + TELNET_EV_ZMP, /*!< ZMP command has been received */ + TELNET_EV_TTYPE, /*!< TTYPE command has been received */ + TELNET_EV_ENVIRON, /*!< ENVIRON command has been received */ + TELNET_EV_MSSP, /*!< MSSP command has been received */ + TELNET_EV_WARNING, /*!< recoverable error has occured */ + TELNET_EV_ERROR /*!< non-recoverable error has occured */ +}; +typedef enum telnet_event_type_t telnet_event_type_t; /*!< Telnet event type. */ + +/*! + * environ/MSSP command information + */ +struct telnet_environ_t { + unsigned char type; /*!< either TELNET_ENVIRON_VAR or TELNET_ENVIRON_USERVAR */ + const char *var; /*!< name of the variable being set */ + const char *value; /*!< value of variable being set; empty string if no value */ +}; + +/*! + * event information + */ +union telnet_event_t { + /*! + * \brief Event type + * + * The type field will determine which of the other event structure fields + * have been filled in. For instance, if the event type is TELNET_EV_ZMP, + * then the zmp event field (and ONLY the zmp event field) will be filled + * in. + */ + enum telnet_event_type_t type; + + /*! + * data event: for DATA and SEND events + */ + struct data_t { + enum telnet_event_type_t _type; /*!< alias for type */ + const char *buffer; /*!< byte buffer */ + size_t size; /*!< number of bytes in buffer */ + } data; + + /*! + * WARNING and ERROR events + */ + struct error_t { + enum telnet_event_type_t _type; /*!< alias for type */ + const char *file; /*!< file the error occured in */ + const char *func; /*!< function the error occured in */ + const char *msg; /*!< error message string */ + int line; /*!< line of file error occured on */ + telnet_error_t errcode; /*!< error code */ + } error; + + /*! + * command event: for IAC + */ + struct iac_t { + enum telnet_event_type_t _type; /*!< alias for type */ + unsigned char cmd; /*!< telnet command received */ + } iac; + + /*! + * negotiation event: WILL, WONT, DO, DONT + */ + struct negotiate_t { + enum telnet_event_type_t _type; /*!< alias for type */ + unsigned char telopt; /*!< option being negotiated */ + } neg; + + /*! + * subnegotiation event + */ + struct subnegotiate_t { + enum telnet_event_type_t _type; /*!< alias for type */ + const char *buffer; /*!< data of sub-negotiation */ + size_t size; /*!< number of bytes in buffer */ + unsigned char telopt; /*!< option code for negotiation */ + } sub; + + /*! + * ZMP event + */ + struct zmp_t { + enum telnet_event_type_t _type; /*!< alias for type */ + const char **argv; /*!< array of argument string */ + size_t argc; /*!< number of elements in argv */ + } zmp; + + /*! + * TTYPE event + */ + struct ttype_t { + enum telnet_event_type_t _type; /*!< alias for type */ + unsigned char cmd; /*!< TELNET_TTYPE_IS or TELNET_TTYPE_SEND */ + const char* name; /*!< terminal type name (IS only) */ + } ttype; + + /*! + * COMPRESS event + */ + struct compress_t { + enum telnet_event_type_t _type; /*!< alias for type */ + unsigned char state; /*!< 1 if compression is enabled, + 0 if disabled */ + } compress; + + /*! + * ENVIRON/NEW-ENVIRON event + */ + struct environ_t { + enum telnet_event_type_t _type; /*!< alias for type */ + const struct telnet_environ_t *values; /*!< array of variable values */ + size_t size; /*!< number of elements in values */ + unsigned char cmd; /*!< SEND, IS, or INFO */ + } environ; + + /*! + * MSSP event + */ + struct mssp_t { + enum telnet_event_type_t _type; /*!< alias for type */ + const struct telnet_environ_t *values; /*!< array of variable values */ + size_t size; /*!< number of elements in values */ + } mssp; +}; + +/*! + * \brief event handler + * + * This is the type of function that must be passed to + * telnet_init() when creating a new telnet object. The + * function will be invoked once for every event generated + * by the libtelnet protocol parser. + * + * \param telnet The telnet object that generated the event + * \param event Event structure with details about the event + * \param user_data User-supplied pointer + */ +typedef void (*telnet_event_handler_t)(telnet_t *telnet, + telnet_event_t *event, void *user_data); + +/*! + * telopt support table element; use telopt of -1 for end marker + */ +struct telnet_telopt_t { + short telopt; /*!< one of the TELOPT codes or -1 */ + unsigned char us; /*!< TELNET_WILL or TELNET_WONT */ + unsigned char him; /*!< TELNET_DO or TELNET_DONT */ +}; + +/*! + * state tracker -- private data structure + */ +struct telnet_t; + +/*! + * \brief Initialize a telnet state tracker. + * + * This function initializes a new state tracker, which is used for all + * other libtelnet functions. Each connection must have its own + * telnet state tracker object. + * + * \param telopts Table of TELNET options the application supports. + * \param eh Event handler function called for every event. + * \param flags 0 or TELNET_FLAG_PROXY. + * \param user_data Optional data pointer that will be passsed to eh. + * \return Telent state tracker object. + */ +extern telnet_t* telnet_init(const telnet_telopt_t *telopts, + telnet_event_handler_t eh, unsigned char flags, void *user_data); + +/*! + * \brief Free up any memory allocated by a state tracker. + * + * This function must be called when a telnet state tracker is no + * longer needed (such as after the connection has been closed) to + * release any memory resources used by the state tracker. + * + * \param telnet Telnet state tracker object. + */ +extern void telnet_free(telnet_t *telnet); + +/*! + * \brief Push a byte buffer into the state tracker. + * + * Passes one or more bytes to the telnet state tracker for + * protocol parsing. The byte buffer is most often going to be + * the buffer that recv() was called for while handling the + * connection. + * + * \param telnet Telnet state tracker object. + * \param buffer Pointer to byte buffer. + * \param size Number of bytes pointed to by buffer. + */ +extern void telnet_recv(telnet_t *telnet, const char *buffer, + size_t size); + +/*! + * \brief Send a telnet command. + * + * \param telnet Telnet state tracker object. + * \param cmd Command to send. + */ +extern void telnet_iac(telnet_t *telnet, unsigned char cmd); + +/*! + * \brief Send negotiation command. + * + * Internally, libtelnet uses RFC1143 option negotiation rules. + * The negotiation commands sent with this function may be ignored + * if they are determined to be redundant. + * + * \param telnet Telnet state tracker object. + * \param cmd TELNET_WILL, TELNET_WONT, TELNET_DO, or TELNET_DONT. + * \param opt One of the TELNET_TELOPT_* values. + */ +extern void telnet_negotiate(telnet_t *telnet, unsigned char cmd, + unsigned char opt); + +/*! + * Send non-command data (escapes IAC bytes). + * + * \param telnet Telnet state tracker object. + * \param buffer Buffer of bytes to send. + * \param size Number of bytes to send. + */ +extern void telnet_send(telnet_t *telnet, + const char *buffer, size_t size); + +/*! + * \brief Begin a sub-negotiation command. + * + * Sends IAC SB followed by the telopt code. All following data sent + * will be part of the sub-negotiation, until telnet_finish_sb() is + * called. + * + * \param telnet Telnet state tracker object. + * \param telopt One of the TELNET_TELOPT_* values. + */ +extern void telnet_begin_sb(telnet_t *telnet, + unsigned char telopt); + +/*! + * \brief Finish a sub-negotiation command. + * + * This must be called after a call to telnet_begin_sb() to finish a + * sub-negotiation command. + * + * \param telnet Telnet state tracker object. + */ +#define telnet_finish_sb(telnet) telnet_iac((telnet), TELNET_SE) + +/*! + * \brief Shortcut for sending a complete subnegotiation buffer. + * + * Equivalent to: + * telnet_begin_sb(telnet, telopt); + * telnet_send(telnet, buffer, size); + * telnet_finish_sb(telnet); + * + * \param telnet Telnet state tracker format. + * \param telopt One of the TELNET_TELOPT_* values. + * \param buffer Byte buffer for sub-negotiation data. + * \param size Number of bytes to use for sub-negotiation data. + */ +extern void telnet_subnegotiation(telnet_t *telnet, unsigned char telopt, + const char *buffer, size_t size); + +/*! + * \brief Begin sending compressed data. + * + * This function will begein sending data using the COMPRESS2 option, + * which enables the use of zlib to compress data sent to the client. + * The client must offer support for COMPRESS2 with option negotiation, + * and zlib support must be compiled into libtelnet. + * + * Only the server may call this command. + * + * \param telnet Telnet state tracker object. + */ +extern void telnet_begin_compress2(telnet_t *telnet); + +/*! + * \brief Send formatted data. + * + * This function is a wrapper around telnet_send(). It allows using + * printf-style formatting. + * + * Additionally, this function will translate \\r to the CR NUL construct and + * \\n with CR LF, as well as automatically escaping IAC bytes like + * telnet_send(). + * + * \param telnet Telnet state tracker object. + * \param fmt Format string. + * \return Number of bytes sent. + */ +extern int telnet_printf(telnet_t *telnet, const char *fmt, ...) + TELNET_GNU_PRINTF(2, 3); + +/*! + * \brief Send formatted data. + * + * See telnet_printf(). + */ +extern int telnet_vprintf(telnet_t *telnet, const char *fmt, va_list va); + +/*! + * \brief Send formatted data (no newline escaping). + * + * This behaves identically to telnet_printf(), except that the \\r and \\n + * characters are not translated. The IAC byte is still escaped as normal + * with telnet_send(). + * + * \param telnet Telnet state tracker object. + * \param fmt Format string. + * \return Number of bytes sent. + */ +extern int telnet_raw_printf(telnet_t *telnet, const char *fmt, ...) + TELNET_GNU_PRINTF(2, 3); + +/*! + * \brief Send formatted data (no newline escaping). + * + * See telnet_raw_printf(). + */ +extern int telnet_raw_vprintf(telnet_t *telnet, const char *fmt, va_list va); + +/*! + * \brief Begin a new set of NEW-ENVIRON values to request or send. + * + * This function will begin the sub-negotiation block for sending or + * requesting NEW-ENVIRON values. + * + * The telnet_finish_newenviron() macro must be called after this + * function to terminate the NEW-ENVIRON command. + * + * \param telnet Telnet state tracker object. + * \param type One of TELNET_ENVIRON_SEND, TELNET_ENVIRON_IS, or + * TELNET_ENVIRON_INFO. + */ +extern void telnet_begin_newenviron(telnet_t *telnet, unsigned char type); + +/*! + * \brief Send a NEW-ENVIRON variable name or value. + * + * This can only be called between calls to telnet_begin_newenviron() and + * telnet_finish_newenviron(). + * + * \param telnet Telnet state tracker object. + * \param type One of TELNET_ENVIRON_VAR, TELNET_ENVIRON_USERVAR, or + * TELNET_ENVIRON_VALUE. + * \param string Variable name or value. + */ +extern void telnet_newenviron_value(telnet_t* telnet, unsigned char type, + const char *string); + +/*! + * \brief Finish a NEW-ENVIRON command. + * + * This must be called after a call to telnet_begin_newenviron() to finish a + * NEW-ENVIRON variable list. + * + * \param telnet Telnet state tracker object. + */ +#define telnet_finish_newenviron(telnet) telnet_finish_sb((telnet)) + +/*! + * \brief Send the TERMINAL-TYPE SEND command. + * + * Sends the sequence IAC TERMINAL-TYPE SEND. + * + * \param telnet Telnet state tracker object. + */ +extern void telnet_ttype_send(telnet_t *telnet); + +/*! + * \brief Send the TERMINAL-TYPE IS command. + * + * Sends the sequence IAC TERMINAL-TYPE IS "string". + * + * According to the RFC, the recipient of a TERMINAL-TYPE SEND shall + * send the next possible terminal-type the client supports. Upon sending + * the type, the client should switch modes to begin acting as the terminal + * type is just sent. + * + * The server may continue sending TERMINAL-TYPE IS until it receives a + * terminal type is understands. To indicate to the server that it has + * reached the end of the available optoins, the client must send the last + * terminal type a second time. When the server receives the same terminal + * type twice in a row, it knows it has seen all available terminal types. + * + * After the last terminal type is sent, if the client receives another + * TERMINAL-TYPE SEND command, it must begin enumerating the available + * terminal types from the very beginning. This allows the server to + * scan the available types for a preferred terminal type and, if none + * is found, to then ask the client to switch to an acceptable + * alternative. + * + * Note that if the client only supports a single terminal type, then + * simply sending that one type in response to every SEND will satisfy + * the behavior requirements. + * + * \param telnet Telnet state tracker object. + * \param ttype Name of the terminal-type being sent. + */ +extern void telnet_ttype_is(telnet_t *telnet, const char* ttype); + +/*! + * \brief Send a ZMP command. + * + * \param telnet Telnet state tracker object. + * \param argc Number of ZMP commands being sent. + * \param argv Array of argument strings. + */ +extern void telnet_send_zmp(telnet_t *telnet, size_t argc, const char **argv); + +/*! + * \brief Send a ZMP command. + * + * Arguments are listed out in var-args style. After the last argument, a + * NULL pointer must be passed in as a sentinel value. + * + * \param telnet Telnet state tracker object. + */ +extern void telnet_send_zmpv(telnet_t *telnet, ...); + +/*! + * \brief Send a ZMP command. + * + * See telnet_send_zmpv(). + */ +extern void telnet_send_vzmpv(telnet_t *telnet, va_list va); + +/*! + * \brief Begin sending a ZMP command + * + * \param telnet Telnet state tracker object. + * \param cmd The first argument (command name) for the ZMP command. + */ +extern void telnet_begin_zmp(telnet_t *telnet, const char *cmd); + +/*! + * \brief Send a ZMP command argument. + * + * \param telnet Telnet state tracker object. + * \param arg Telnet argument string. + */ +extern void telnet_zmp_arg(telnet_t *telnet, const char *arg); + +/*! + * \brief Finish a ZMP command. + * + * This must be called after a call to telnet_begin_zmp() to finish a + * ZMP argument list. + * + * \param telnet Telnet state tracker object. + */ +#define telnet_finish_zmp(telnet) telnet_finish_sb((telnet)) + +/* C++ support */ +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +#endif /* !defined(LIBTELNET_INCLUDE) */ diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c new file mode 100644 index 00000000..9c6bc2c0 --- /dev/null +++ b/src/apps/relay/mainrelay.c @@ -0,0 +1,2376 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "mainrelay.h" + +////// TEMPORARY data ////////// + +static int use_lt_credentials = 0; +static int use_st_credentials = 0; +static int anon_credentials = 0; + +//////TURN PARAMS STRUCTURE DEFINITION ////// + +#define DEFAULT_GENERAL_RELAY_SERVERS_NUMBER (1) + +turn_params_t turn_params = { + +NULL, NULL, + +#if defined(SSL_TXT_TLSV1_1) + NULL, +#if defined(SSL_TXT_TLSV1_2) + NULL, +#endif +#endif + +NULL, + +DH_1066, "", DEFAULT_EC_CURVE_NAME, "", +"turn_server_cert.pem","turn_server_pkey.pem", "", "", +0,0,0,0,0, +#if defined(TURN_NO_TLS) +1, +#else +0, +#endif + +#if defined(TURN_NO_DTLS) +1, +#else +0, +#endif + +TURN_VERBOSE_NONE,0,0, +"/var/run/turnserver.pid", +DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,1, +0,0,0,0, +"", +#if !defined(TURN_NO_HIREDIS) +"",0, +#endif +{ + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,NULL,NULL,NULL +}, +{NULL, NULL, 0},{NULL, NULL, 0}, +NEV_UNKNOWN, +{ "Unknown", "UDP listening socket per session", "UDP thread per network endpoint", "UDP thread per CPU core" }, +//////////////// Relay servers ////////////////////////////////// +LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,"", +0,NULL,0,NULL,DEFAULT_GENERAL_RELAY_SERVERS_NUMBER,0, +////////////// Auth server ///////////////////////////////////// +{NULL,NULL,NULL,0 +#if !defined(TURN_NO_HIREDIS) +,NULL +#endif +}, +/////////////// AUX SERVERS //////////////// +{NULL,0,{0,NULL}},0, +/////////////// ALTERNATE SERVERS //////////////// +{NULL,0,{0,NULL}},{NULL,0,{0,NULL}}, +/////////////// stop server //////////////// +0, +/////////////// MISC PARAMS //////////////// +0,0,0,0,0,SHATYPE_SHA1,':',0,0,TURN_CREDENTIALS_NONE,0,0,0,0, +///////////// Users DB ////////////// +{ TURN_USERDB_TYPE_FILE, {"\0",NULL}, {0,NULL,NULL, {NULL,0}} } + +}; + +//////////////// OpenSSL Init ////////////////////// + +static void openssl_setup(void); + +/* + * openssl genrsa -out pkey 2048 + * openssl req -new -key pkey -out cert.req + * openssl x509 -req -days 365 -in cert.req -signkey pkey -out cert + * +*/ + +//////////// Common static process params //////// + +static gid_t procgroupid = 0; +static uid_t procuserid = 0; +static gid_t procgroupid_set = 0; +static uid_t procuserid_set = 0; +static char procusername[1025]="\0"; +static char procgroupname[1025]="\0"; + +////////////// Configuration functionality //////////////////////////////// + +static void read_config_file(int argc, char **argv, int pass); + +////////////////////////////////////////////////// + +static int make_local_listeners_list(void) +{ + int ret = 0; + + struct ifaddrs * ifs = NULL; + struct ifaddrs * ifa = NULL; + + char saddr[INET6_ADDRSTRLEN] = ""; + + if((getifaddrs(&ifs) == 0) && ifs) { + + for (ifa = ifs; ifa != NULL; ifa = ifa->ifa_next) { + + if(!(ifa->ifa_flags & IFF_UP)) + continue; + + if(!(ifa->ifa_addr)) + continue; + + if (ifa ->ifa_addr->sa_family == AF_INET) { + if(!inet_ntop(AF_INET, &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr, saddr, + INET_ADDRSTRLEN)) + continue; + if(strstr(saddr,"169.254.") == saddr) + continue; + if(!strcmp(saddr,"0.0.0.0")) + continue; + } else if (ifa->ifa_addr->sa_family == AF_INET6) { + if(!inet_ntop(AF_INET6, &((struct sockaddr_in6 *) ifa->ifa_addr)->sin6_addr, saddr, + INET6_ADDRSTRLEN)) + continue; + if(strstr(saddr,"fe80") == saddr) + continue; + if(!strcmp(saddr,"::")) + continue; + } else { + continue; + } + + add_listener_addr(saddr); + + if(!(ifa->ifa_flags & IFF_LOOPBACK)) + ret++; + } + freeifaddrs(ifs); + } + + return ret; +} + +static int make_local_relays_list(int allow_local, int family) +{ + struct ifaddrs * ifs = NULL; + struct ifaddrs * ifa = NULL; + + char saddr[INET6_ADDRSTRLEN] = ""; + + getifaddrs(&ifs); + + int counter = 0; + + if (ifs) { + for (ifa = ifs; ifa != NULL; ifa = ifa->ifa_next) { + + if(!(ifa->ifa_flags & IFF_UP)) + continue; + + if(!(ifa->ifa_name)) + continue; + if(!(ifa ->ifa_addr)) + continue; + + if(!allow_local && (ifa->ifa_flags & IFF_LOOPBACK)) + continue; + + if (ifa ->ifa_addr->sa_family == AF_INET) { + + if(family != AF_INET) + continue; + + if(!inet_ntop(AF_INET, &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr, saddr, + INET_ADDRSTRLEN)) + continue; + if(strstr(saddr,"169.254.") == saddr) + continue; + if(!strcmp(saddr,"0.0.0.0")) + continue; + } else if (ifa->ifa_addr->sa_family == AF_INET6) { + + if(family != AF_INET6) + continue; + + if(!inet_ntop(AF_INET6, &((struct sockaddr_in6 *) ifa->ifa_addr)->sin6_addr, saddr, + INET6_ADDRSTRLEN)) + continue; + if(strstr(saddr,"fe80") == saddr) + continue; + if(!strcmp(saddr,"::")) + continue; + } else + continue; + + if(add_relay_addr(saddr)>0) { + counter += 1; + } + } + freeifaddrs(ifs); + } + + return counter; +} + +int get_a_local_relay(int family, ioa_addr *relay_addr) +{ + struct ifaddrs * ifs = NULL; + + int allow_local = 0; + + int ret = -1; + + char saddr[INET6_ADDRSTRLEN] = ""; + + getifaddrs(&ifs); + + if (ifs) { + + galr_start: + + { + struct ifaddrs *ifa = NULL; + + for (ifa = ifs; ifa != NULL ; ifa = ifa->ifa_next) { + + if (!(ifa->ifa_flags & IFF_UP)) + continue; + + if (!(ifa->ifa_name)) + continue; + if (!(ifa->ifa_addr)) + continue; + + if (!allow_local && (ifa->ifa_flags & IFF_LOOPBACK)) + continue; + + if (ifa->ifa_addr->sa_family == AF_INET) { + + if (family != AF_INET) + continue; + + if (!inet_ntop(AF_INET, + &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr, + saddr, INET_ADDRSTRLEN)) + continue; + if (strstr(saddr, "169.254.") == saddr) + continue; + if (!strcmp(saddr, "0.0.0.0")) + continue; + } else if (ifa->ifa_addr->sa_family == AF_INET6) { + + if (family != AF_INET6) + continue; + + if (!inet_ntop(AF_INET6, + &((struct sockaddr_in6 *) ifa->ifa_addr)->sin6_addr, + saddr, INET6_ADDRSTRLEN)) + continue; + if (strstr(saddr, "fe80") == saddr) + continue; + if (!strcmp(saddr, "::")) + continue; + } else + continue; + + if (make_ioa_addr((const u08bits*) saddr, 0, relay_addr) < 0) { + continue; + } else { + ret = 0; + break; + } + } + } + + if(ret<0 && !allow_local) { + allow_local = 1; + goto galr_start; + } + + freeifaddrs(ifs); + } + + return -1; +} + +////////////////////////////////////////////////// + +static char Usage[] = "Usage: turnserver [options]\n" +"Options:\n" +" -d, --listening-device Listener interface device (NOT RECOMMENDED. Optional, Linux only).\n" +" -p, --listening-port TURN listener port (Default: 3478).\n" +" Note: actually, TLS & DTLS sessions can connect to the \"plain\" TCP & UDP port(s), too,\n" +" if allowed by configuration.\n" +" --tls-listening-port TURN listener port for TLS & DTLS listeners\n" +" (Default: 5349).\n" +" Note: actually, \"plain\" TCP & UDP sessions can connect to the TLS & DTLS port(s), too,\n" +" if allowed by configuration. The TURN server\n" +" \"automatically\" recognizes the type of traffic. Actually, two listening\n" +" endpoints (the \"plain\" one and the \"tls\" one) are equivalent in terms of\n" +" functionality; but we keep both endpoints to satisfy the RFC 5766 specs.\n" +" For secure TCP connections, we currently support SSL version 3 and\n" +" TLS versions 1.0, 1.1 and 1.2. For secure UDP connections, we support\n" +" DTLS version 1.\n" +" --alt-listening-port Alternative listening port for STUN CHANGE_REQUEST (in RFC 5780 sense, \n" +" or in old RFC 3489 sense, default is \"listening port plus one\").\n" +" --alt-tls-listening-port Alternative listening port for TLS and DTLS,\n" +" the default is \"TLS/DTLS port plus one\".\n" +" -L, --listening-ip Listener IP address of relay server. Multiple listeners can be specified.\n" +" --aux-server Auxiliary STUN/TURN server listening endpoint.\n" +" Auxiliary servers do not have alternative ports and\n" +" they do not support RFC 5780 functionality (CHANGE REQUEST).\n" +" Valid formats are 1.2.3.4:5555 for IPv4 and [1:2::3:4]:5555 for IPv6.\n" +" --udp-self-balance (recommended for older Linuxes only) Automatically balance UDP traffic\n" +" over auxiliary servers (if configured).\n" +" The load balancing is using the ALTERNATE-SERVER mechanism.\n" +" The TURN client must support 300 ALTERNATE-SERVER response for this functionality.\n" +" -i, --relay-device Relay interface device for relay sockets (NOT RECOMMENDED. Optional, Linux only).\n" +" -E, --relay-ip Relay address (the local IP address that will be used to relay the\n" +" packets to the peer).\n" +" Multiple relay addresses may be used.\n" +" The same IP(s) can be used as both listening IP(s) and relay IP(s).\n" +" If no relay IP(s) specified, then the turnserver will apply the default\n" +" policy: it will decide itself which relay addresses to be used, and it\n" +" will always be using the client socket IP address as the relay IP address\n" +" of the TURN session (if the requested relay address family is the same\n" +" as the family of the client socket).\n" +" -X, --external-ip TURN Server public/private address mapping, if the server is behind NAT.\n" +" In that situation, if a -X is used in form \"-X ip\" then that ip will be reported\n" +" as relay IP address of all allocations. This scenario works only in a simple case\n" +" when one single relay address is be used, and no STUN CHANGE_REQUEST functionality is required.\n" +" That single relay address must be mapped by NAT to the 'external' IP.\n" +" For that 'external' IP, NAT must forward ports directly (relayed port 12345\n" +" must be always mapped to the same 'external' port 12345).\n" +" In more complex case when more than one IP address is involved,\n" +" that option must be used several times in the command line, each entry must\n" +" have form \"-X public-ip/private-ip\", to map all involved addresses.\n" +" --no-loopback-peers Disallow peers on the loopback addresses (127.x.x.x and ::1).\n" +" --no-multicast-peers Disallow peers on well-known broadcast addresses (224.0.0.0 and above, and FFXX:*).\n" +" -m, --relay-threads Number of relay threads to handle the established connections\n" +" (in addition to authentication thread and the listener thread).\n" +" If set to 0 then application runs in single-threaded mode.\n" +" The default thread number is the number of CPUs.\n" +" In older systems (pre-Linux 3.9) the number of UDP relay threads always equals\n" +" the number of listening endpoints (unless -m 0 is set).\n" +" --min-port Lower bound of the UDP port range for relay endpoints allocation.\n" +" Default value is 49152, according to RFC 5766.\n" +" --max-port Upper bound of the UDP port range for relay endpoints allocation.\n" +" Default value is 65535, according to RFC 5766.\n" +" -v, --verbose 'Moderate' verbose mode.\n" +" -V, --Verbose Extra verbose mode, very annoying (for debug purposes only).\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. This option can be used with either\n" +" flat file user database or PostgreSQL DB or MySQL DB for user keys storage.\n" +" -A, --st-cred-mech Use the short-term credential mechanism. This option requires\n" +" a PostgreSQL or MySQL DB for short term passwords storage.\n" +" -z, --no-auth Do not use any credential mechanism, allow anonymous access.\n" +" -u, --user User account, in form 'username:password', for long-term credentials.\n" +" Cannot be used with TURN REST API or with short-term credentials.\n" +" -r, --realm The default realm to be used for the users when no explicit\n" +" origin/realm relationship was found in the database, or if the TURN\n" +" server is not using any database (just the commands-line settings\n" +" and the userdb file). Must be used with long-term credentials \n" +" mechanism or with TURN REST API.\n" +" -q, --user-quota Per-user allocation quota: how many concurrent allocations a user can create.\n" +" This option can also be set through the database, for a particular realm.\n" +" -Q, --total-quota Total allocations quota: global limit on concurrent allocations.\n" +" This option can also be set through the database, for a particular realm.\n" +" -s, --max-bps Max bytes-per-second bandwidth a TURN session is allowed to handle\n" +" (input and output network streams are treated separately). Anything above\n" +" that limit will be dropped or temporary suppressed\n" +" (within the available buffer limits).\n" +" This option can also be set through the database, for a particular realm.\n" +" -c Configuration file name (default - turnserver.conf).\n" +" -b, --userdb User database file name (default - turnuserdb.conf) for long-term credentials only.\n" +#if !defined(TURN_NO_PQ) +" -e, --psql-userdb, --sql-userdb 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" +" 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" +" http://www.postgresql.org/docs/9.2/static/libpq-connect.html#LIBPQ-CONNSTRING\n" +" for 9.x and newer connection string formats.\n" +#endif +#if !defined(TURN_NO_MYSQL) +" -M, --mysql-userdb 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" +" 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= dbname= user= \\\n password= port= connect_timeout=\".\n" +" All parameters are optional.\n" +#endif +#if !defined(TURN_NO_HIREDIS) +" -N, --redis-userdb 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" +" 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= dbname= \\\n password= port= connect_timeout=\".\n" +" All parameters are optional.\n" +" -O, --redis-statsdb Redis status and statistics database connection string, if used \n" +" (default - empty, no Redis stats DB used).\n" +" This database keeps allocations status information, and it can be also used for publishing\n" +" and delivering traffic and allocation event notifications.\n" +" The connection string has the same parameters as redis-userdb connection string.\n" +#endif +" --use-auth-secret TURN REST API flag.\n" +" Flag that sets a special authorization option that is based upon authentication secret\n" +" (TURN Server REST API, see TURNServerRESTAPI.pdf). This option is used with timestamp.\n" +" --static-auth-secret 'Static' authentication secret value (a string) for TURN REST API only.\n" +" If not set, then the turn server will try to use the 'dynamic' value\n" +" in turn_secret table in user database (if present).\n" +" That database value can be changed on-the-fly\n" +" by a separate program, so this is why it is 'dynamic'.\n" +" Multiple shared secrets can be used (both in the database and in the \"static\" fashion).\n" +" -n Do not use configuration file, take all parameters from the command line only.\n" +" --cert Certificate file, PEM format. Same file search rules\n" +" applied as for the configuration file.\n" +" If both --no-tls and --no_dtls options\n" +" are specified, then this parameter is not needed.\n" +" --pkey Private key file, PEM format. Same file search rules\n" +" applied as for the configuration file.\n" +" If both --no-tls and --no-dtls options\n" +" --pkey-pwd If the private key file is encrypted, then this password to be used.\n" +" --cipher-list <\"cipher-string\"> Allowed OpenSSL cipher list for TLS/DTLS connections.\n" +" Default value is \"DEFAULT\".\n" +" --CA-file CA file in OpenSSL format.\n" +" Forces TURN server to verify the client SSL certificates.\n" +" By default, no CA is set and no client certificate check is performed.\n" +" --ec-curve-name Curve name for EC ciphers, if supported by OpenSSL library\n" +" (TLS and DTLS). The default value is prime256v1.\n" +" --dh566 Use 566 bits predefined DH TLS key. Default size of the predefined key is 1066.\n" +" --dh2066 Use 2066 bits predefined DH TLS key. Default size of the predefined key is 1066.\n" +" --dh-file 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 protocol.\n" +" --no-tlsv1_1 Do not allow TLSv1.1 protocol.\n" +" --no-tlsv1_2 Do not allow TLSv1.2 protocol.\n" +" --no-udp Do not start UDP client listeners.\n" +" --no-tcp Do not start TCP client listeners.\n" +" --no-tls Do not start TLS client listeners.\n" +" --no-dtls Do not start DTLS client listeners.\n" +" --no-udp-relay Do not allow UDP relay endpoints, use only TCP relay option.\n" +" --no-tcp-relay Do not allow TCP relay endpoints, use only UDP relay options.\n" +" -l, --log-file Option to set the full path name of the log file.\n" +" By default, the turnserver tries to open a log file in\n" +" /var/log/turnserver/, /var/log, /var/tmp, /tmp and . (current) directories\n" +" (which open operation succeeds first that file will be used).\n" +" With this option you can set the definite log file name.\n" +" The special names are \"stdout\" and \"-\" - they will force everything\n" +" to the stdout; and \"syslog\" name will force all output to the syslog.\n" +" --no-stdout-log Flag to prevent stdout log messages.\n" +" By default, all log messages are going to both stdout and to\n" +" a log file. With this option everything will be going to the log file only\n" +" (unless the log file itself is stdout).\n" +" --syslog Output all log information into the system log (syslog), do not use the file output.\n" +" --simple-log This flag means that no log file rollover will be used, and the log file\n" +" name will be constructed as-is, without PID and date appendage.\n" +" --stale-nonce Use extra security with nonce value having limited lifetime (600 secs).\n" +" -S, --stun-only Option to set standalone STUN operation only, all TURN requests will be ignored.\n" +" --no-stun Option to suppress STUN functionality, only TURN requests will be processed.\n" +" --alternate-server Set the TURN server to redirect the allocate requests (UDP and TCP services).\n" +" Multiple alternate-server options can be set for load balancing purposes.\n" +" See the docs for more information.\n" +" --tls-alternate-server Set the TURN server to redirect the allocate requests (DTLS and TLS services).\n" +" Multiple alternate-server options can be set for load balancing purposes.\n" +" See the docs for more information.\n" +" -C, --rest-api-separator This is the timestamp/username separator symbol (character) in TURN REST API.\n" +" The default value is ':'.\n" +" --max-allocate-timeout= Max time, in seconds, allowed for full allocation establishment. Default is 60.\n" +" --allowed-peer-ip= Specifies an ip or range of ips that are explicitly allowed to connect to the \n" +" turn server. Multiple allowed-peer-ip can be set.\n" +" --denied-peer-ip= Specifies an ip or range of ips that are not allowed to connect to the turn server.\n" +" Multiple denied-peer-ip can be set.\n" +" --pidfile <\"pid-file-name\"> File name to store the pid of the process.\n" +" Default is /var/run/turnserver.pid (if superuser account is used) or\n" +" /var/tmp/turnserver.pid .\n" +" --secure-stun Require authentication of the STUN Binding request.\n" +" By default, the clients are allowed anonymous access to the STUN Binding functionality.\n" +" --sha256 Require SHA256 digest function to be used for the message integrity.\n" +" By default, the server SHA1 (as per TURN standard specs).\n" +" With this option, the server\n" +" requires the stronger SHA256 function. The client application must\n" +" support SHA256 hash function if this option is used. If the server obtains\n" +" a message from the client with a weaker (SHA1) hash function then the server\n" +" returns error code 426.\n" +" --proc-user User name to run the turnserver process.\n" +" After the initialization, the turnserver process\n" +" will make an attempt to change the current user ID to that user.\n" +" --proc-group Group name to run the turnserver process.\n" +" After the initialization, the turnserver process\n" +" will make an attempt to change the current group ID to that group.\n" +" --mobility Mobility with ICE (MICE) specs support.\n" +" --no-cli Turn OFF the CLI support. By default it is always ON.\n" +" --cli-ip= Local system IP address to be used for CLI server endpoint. Default value\n" +" is 127.0.0.1.\n" +" --cli-port= CLI server port. Default is 5766.\n" +" --cli-password= CLI access password. Default is empty (no password).\n" +" --server-relay Server relay. NON-STANDARD AND DANGEROUS OPTION. Only for those applications\n" +" when we want to run server applications on the relay endpoints.\n" +" This option eliminates the IP permissions check on the packets\n" +" incoming to the relay endpoints.\n" +" --cli-max-output-sessions Maximum number of output sessions in ps CLI command.\n" +" This value can be changed on-the-fly in CLI. The default value is 256.\n" +" --ne=[1|2|3] Set network engine type for the process (for internal purposes).\n" +" -h Help\n" +"\n" +" For more information, see the wiki pages:\n" +"\n" +" http://code.google.com/p/coturn/w/list\n" +"\n"; + +static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" + "Commands:\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" + " -d, --delete delete a long-term mechanism user\n" + " -D, --delete-st delete a short-term mechanism user\n" + " -l, --list list all long-term mechanism users\n" + " -L, --list-st list all short-term mechanism users\n" +#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_HIREDIS) + " -s, --set-secret= Add shared secret for TURN RESP API\n" + " -S, --show-secret Show stored shared secrets for TURN REST API\n" + " -X, --delete-secret= Delete a shared secret\n" + " --delete-all-secrets Delete all shared secrets for REST API\n" + " -O, --add-origin Add origin-to-realm relation.\n" + " -R, --del-origin Delete origin-to-realm relation.\n" + " -I, --list-origins List origin-to-realm relations.\n" + " -g, --set-realm-option Set realm params: max-bps, total-quota, user-quota.\n" + " -G, --list-realm-options List realm params.\n" +#endif + "Options with mandatory values:\n" + " -b, --userdb User database file, if flat DB file is used.\n" +#if !defined(TURN_NO_PQ) + " -e, --psql-userdb, --sql-userdb PostgreSQL user database connection string, if PostgreSQL DB is used.\n" +#endif +#if !defined(TURN_NO_MYSQL) + " -M, --mysql-userdb MySQL user database connection string, if MySQL DB is used.\n" +#endif +#if !defined(TURN_NO_HIREDIS) + " -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" + " -p, --password Password\n" +#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_HIREDIS) + " -o, --origin Origin\n" +#endif + " -H, --sha256 Use SHA256 digest function to be used for the message integrity.\n" + " By default, the server SHA1 (as per TURN standard specs).\n" + " --max-bps Set value of realm's max-bps parameter.\n" + " Setting to zero value means removal of the option.\n" + " --total-quota Set value of realm's total-quota parameter.\n" + " Setting to zero value means removal of the option.\n" + " --user-quota Set value of realm's user-quota parameter.\n" + " Setting to zero value means removal of the option.\n" + " -h, --help Help\n"; + +#define OPTIONS "c:d:p:L:E:X:i:m:l:r:u:b:e:M:N:O:q:Q:s:C:vVofhznaAS" + +#define ADMIN_OPTIONS "gGORIHlLkaADSdb:e:M:N:u:r:p:s:X:o:h" + +enum EXTRA_OPTS { + NO_UDP_OPT=256, + NO_TCP_OPT, + NO_TLS_OPT, + NO_DTLS_OPT, + NO_UDP_RELAY_OPT, + NO_TCP_RELAY_OPT, + TLS_PORT_OPT, + ALT_PORT_OPT, + ALT_TLS_PORT_OPT, + CERT_FILE_OPT, + PKEY_FILE_OPT, + PKEY_PWD_OPT, + MIN_PORT_OPT, + MAX_PORT_OPT, + STALE_NONCE_OPT, + AUTH_SECRET_OPT, + DEL_ALL_AUTH_SECRETS_OPT, + STATIC_AUTH_SECRET_VAL_OPT, + AUTH_SECRET_TS_EXP, /* deprecated */ + NO_STDOUT_LOG_OPT, + SYSLOG_OPT, + SIMPLE_LOG_OPT, + AUX_SERVER_OPT, + UDP_SELF_BALANCE_OPT, + ALTERNATE_SERVER_OPT, + TLS_ALTERNATE_SERVER_OPT, + NO_MULTICAST_PEERS_OPT, + NO_LOOPBACK_PEERS_OPT, + MAX_ALLOCATE_TIMEOUT_OPT, + ALLOWED_PEER_IPS, + DENIED_PEER_IPS, + CIPHER_LIST_OPT, + PIDFILE_OPT, + SECURE_STUN_OPT, + CA_FILE_OPT, + DH_FILE_OPT, + SHA256_OPT, + NO_STUN_OPT, + PROC_USER_OPT, + PROC_GROUP_OPT, + MOBILITY_OPT, + NO_CLI_OPT, + CLI_IP_OPT, + CLI_PORT_OPT, + CLI_PASSWORD_OPT, + SERVER_RELAY_OPT, + CLI_MAX_SESSIONS_OPT, + EC_CURVE_NAME_OPT, + DH566_OPT, + DH2066_OPT, + NE_TYPE_OPT, + NO_SSLV2_OPT, + NO_SSLV3_OPT, + NO_TLSV1_OPT, + NO_TLSV1_1_OPT, + NO_TLSV1_2_OPT, + ADMIN_MAX_BPS_OPT, + ADMIN_TOTAL_QUOTA_OPT, + ADMIN_USER_QUOTA_OPT +}; + +static struct option long_options[] = { + { "listening-device", required_argument, NULL, 'd' }, + { "listening-port", required_argument, NULL, 'p' }, + { "tls-listening-port", required_argument, NULL, TLS_PORT_OPT }, + { "alt-listening-port", required_argument, NULL, ALT_PORT_OPT }, + { "alt-tls-listening-port", required_argument, NULL, ALT_TLS_PORT_OPT }, + { "listening-ip", required_argument, NULL, 'L' }, + { "relay-device", required_argument, NULL, 'i' }, + { "relay-ip", required_argument, NULL, 'E' }, + { "external-ip", required_argument, NULL, 'X' }, + { "relay-threads", required_argument, NULL, 'm' }, + { "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' }, + { "userdb", required_argument, NULL, 'b' }, +#if !defined(TURN_NO_PQ) + { "psql-userdb", required_argument, NULL, 'e' }, + { "sql-userdb", required_argument, NULL, 'e' }, +#endif +#if !defined(TURN_NO_MYSQL) + { "mysql-userdb", required_argument, NULL, 'M' }, +#endif +#if !defined(TURN_NO_HIREDIS) + { "redis-userdb", required_argument, NULL, 'N' }, + { "redis-statsdb", required_argument, NULL, 'O' }, +#endif + { "use-auth-secret", optional_argument, NULL, AUTH_SECRET_OPT }, + { "static-auth-secret", required_argument, NULL, STATIC_AUTH_SECRET_VAL_OPT }, +/* deprecated: */ { "secret-ts-exp-time", optional_argument, NULL, AUTH_SECRET_TS_EXP }, + { "realm", required_argument, NULL, 'r' }, + { "user-quota", required_argument, NULL, 'q' }, + { "total-quota", required_argument, NULL, 'Q' }, + { "max-bps", required_argument, NULL, 's' }, + { "verbose", optional_argument, NULL, 'v' }, + { "Verbose", optional_argument, NULL, 'V' }, + { "daemon", optional_argument, NULL, 'o' }, + { "fingerprint", optional_argument, NULL, 'f' }, + { "no-udp", optional_argument, NULL, NO_UDP_OPT }, + { "no-tcp", optional_argument, NULL, NO_TCP_OPT }, + { "no-tls", optional_argument, NULL, NO_TLS_OPT }, + { "no-dtls", optional_argument, NULL, NO_DTLS_OPT }, + { "no-udp-relay", optional_argument, NULL, NO_UDP_RELAY_OPT }, + { "no-tcp-relay", optional_argument, NULL, NO_TCP_RELAY_OPT }, + { "stale-nonce", optional_argument, NULL, STALE_NONCE_OPT }, + { "stun-only", optional_argument, NULL, 'S' }, + { "no-stun", optional_argument, NULL, NO_STUN_OPT }, + { "cert", required_argument, NULL, CERT_FILE_OPT }, + { "pkey", required_argument, NULL, PKEY_FILE_OPT }, + { "pkey-pwd", required_argument, NULL, PKEY_PWD_OPT }, + { "log-file", required_argument, NULL, 'l' }, + { "no-stdout-log", optional_argument, NULL, NO_STDOUT_LOG_OPT }, + { "syslog", optional_argument, NULL, SYSLOG_OPT }, + { "simple-log", optional_argument, NULL, SIMPLE_LOG_OPT }, + { "aux-server", required_argument, NULL, AUX_SERVER_OPT }, + { "udp-self-balance", optional_argument, NULL, UDP_SELF_BALANCE_OPT }, + { "alternate-server", required_argument, NULL, ALTERNATE_SERVER_OPT }, + { "tls-alternate-server", required_argument, NULL, TLS_ALTERNATE_SERVER_OPT }, + { "rest-api-separator", required_argument, NULL, 'C' }, + { "max-allocate-timeout", required_argument, NULL, MAX_ALLOCATE_TIMEOUT_OPT }, + { "no-multicast-peers", optional_argument, NULL, NO_MULTICAST_PEERS_OPT }, + { "no-loopback-peers", optional_argument, NULL, NO_LOOPBACK_PEERS_OPT }, + { "allowed-peer-ip", required_argument, NULL, ALLOWED_PEER_IPS }, + { "denied-peer-ip", required_argument, NULL, DENIED_PEER_IPS }, + { "cipher-list", required_argument, NULL, CIPHER_LIST_OPT }, + { "pidfile", required_argument, NULL, PIDFILE_OPT }, + { "secure-stun", optional_argument, NULL, SECURE_STUN_OPT }, + { "CA-file", required_argument, NULL, CA_FILE_OPT }, + { "dh-file", required_argument, NULL, DH_FILE_OPT }, + { "sha256", optional_argument, NULL, SHA256_OPT }, + { "proc-user", required_argument, NULL, PROC_USER_OPT }, + { "proc-group", required_argument, NULL, PROC_GROUP_OPT }, + { "mobility", optional_argument, NULL, MOBILITY_OPT }, + { "no-cli", optional_argument, NULL, NO_CLI_OPT }, + { "cli-ip", required_argument, NULL, CLI_IP_OPT }, + { "cli-port", required_argument, NULL, CLI_PORT_OPT }, + { "cli-password", required_argument, NULL, CLI_PASSWORD_OPT }, + { "server-relay", optional_argument, NULL, SERVER_RELAY_OPT }, + { "cli-max-output-sessions", required_argument, NULL, CLI_MAX_SESSIONS_OPT }, + { "ec-curve-name", required_argument, NULL, EC_CURVE_NAME_OPT }, + { "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-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 }, + { "no-tlsv1_2", optional_argument, NULL, NO_TLSV1_2_OPT }, + { NULL, no_argument, NULL, 0 } +}; + +static struct option admin_long_options[] = { + { "key", no_argument, NULL, 'k' }, + { "add", no_argument, NULL, 'a' }, + { "delete", no_argument, NULL, 'd' }, + { "list", no_argument, NULL, 'l' }, + { "list-st", no_argument, NULL, 'L' }, +#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_HIREDIS) + { "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 }, +#endif + { "add-st", no_argument, NULL, 'A' }, + { "delete-st", no_argument, NULL, 'D' }, + { "userdb", required_argument, NULL, 'b' }, +#if !defined(TURN_NO_PQ) + { "psql-userdb", required_argument, NULL, 'e' }, + { "sql-userdb", required_argument, NULL, 'e' }, +#endif +#if !defined(TURN_NO_MYSQL) + { "mysql-userdb", required_argument, NULL, 'M' }, +#endif +#if !defined(TURN_NO_HIREDIS) + { "redis-userdb", required_argument, NULL, 'N' }, +#endif + { "user", required_argument, NULL, 'u' }, + { "realm", required_argument, NULL, 'r' }, + { "password", required_argument, NULL, 'p' }, + { "sha256", no_argument, NULL, 'H' }, +#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_HIREDIS) + { "add-origin", no_argument, NULL, 'O' }, + { "del-origin", no_argument, NULL, 'R' }, + { "list-origins", required_argument, NULL, 'I' }, + { "origin", required_argument, NULL, 'o' }, + { "set-realm-option", no_argument, NULL, 'g' }, + { "list-realm-option", no_argument, NULL, 'G' }, + { "user-quota", required_argument, NULL, ADMIN_USER_QUOTA_OPT }, + { "total-quota", required_argument, NULL, ADMIN_TOTAL_QUOTA_OPT }, + { "max-bps", required_argument, NULL, ADMIN_MAX_BPS_OPT }, +#endif + { "help", no_argument, NULL, 'h' }, + { NULL, no_argument, NULL, 0 } +}; + +static int get_bool_value(const char* s) +{ + if(!s || !(s[0])) return 1; + if(s[0]=='0' || s[0]=='n' || s[0]=='N' || s[0]=='f' || s[0]=='F') return 0; + if(s[0]=='y' || s[0]=='Y' || s[0]=='t' || s[0]=='T') return 1; + if(s[0]>'0' && s[0]<='9') return 1; + if(!strcmp(s,"off") || !strcmp(s,"OFF") || !strcmp(s,"Off")) return 0; + if(!strcmp(s,"on") || !strcmp(s,"ON") || !strcmp(s,"On")) return 1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown boolean value: %s. You can use on/off, yes/no, 1/0, true/false.\n",s); + exit(-1); +} + +static void set_option(int c, char *value) +{ + if(value && value[0]=='=') { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: option -%c is possibly used incorrectly. The short form of the option must be used as this: -%c , no \'equals\' sign may be used, that sign is used only with long form options (like --user=).\n",(char)c,(char)c); + } + + switch (c) { + case NO_SSLV2_OPT: + turn_params.no_sslv2 = get_bool_value(value); + break; + case NO_SSLV3_OPT: + turn_params.no_sslv3 = get_bool_value(value); + break; + case NO_TLSV1_OPT: + turn_params.no_tlsv1 = get_bool_value(value); + break; + case NO_TLSV1_1_OPT: + turn_params.no_tlsv1_1 = get_bool_value(value); + break; + case NO_TLSV1_2_OPT: + turn_params.no_tlsv1_2 = get_bool_value(value); + break; + case NE_TYPE_OPT: + { + int ne = atoi(value); + if((ne<(int)NEV_MIN)||(ne>(int)NEV_MAX)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "ERROR: wrong version of the network engine: %d\n",ne); + } + turn_params.net_engine_version = (NET_ENG_VERSION)ne; + } + break; + case DH566_OPT: + if(get_bool_value(value)) + turn_params.dh_key_size = DH_566; + break; + case DH2066_OPT: + if(get_bool_value(value)) + turn_params.dh_key_size = DH_2066; + break; + case EC_CURVE_NAME_OPT: + STRCPY(turn_params.ec_curve_name,value); + break; + case CLI_MAX_SESSIONS_OPT: + cli_max_output_sessions = atoi(value); + break; + case SERVER_RELAY_OPT: + turn_params.server_relay = get_bool_value(value); + break; + case MOBILITY_OPT: + turn_params.mobility = get_bool_value(value); + break; + case NO_CLI_OPT: + use_cli = !get_bool_value(value); + break; + case CLI_IP_OPT: + if(make_ioa_addr((const u08bits*)value,0,&cli_addr)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot set cli address: %s\n",value); + } else{ + cli_addr_set = 1; + } + break; + case CLI_PORT_OPT: + cli_port = atoi(value); + break; + case CLI_PASSWORD_OPT: + STRCPY(cli_password,value); + break; + case PROC_USER_OPT: { + struct passwd* pwd = getpwnam(value); + if(!pwd) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown user name: %s\n",value); + exit(-1); + } else { + procuserid = pwd->pw_uid; + procuserid_set = 1; + STRCPY(procusername,value); + } + } + break; + case PROC_GROUP_OPT: { + struct group* gr = getgrnam(value); + if(!gr) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown group name: %s\n",value); + exit(-1); + } else { + procgroupid = gr->gr_gid; + procgroupid_set = 1; + STRCPY(procgroupname,value); + } + } + break; + case 'i': + STRCPY(turn_params.relay_ifname, value); + break; + case 'm': +#if defined(OPENSSL_THREADS) + if(atoi(value)>MAX_NUMBER_OF_GENERAL_RELAY_SERVERS) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: max number of relay threads is 128.\n"); + turn_params.general_relay_servers_number = MAX_NUMBER_OF_GENERAL_RELAY_SERVERS; + } else if(atoi(value)<=0) { + turn_params.general_relay_servers_number = 0; + } else { + turn_params.general_relay_servers_number = atoi(value); + } +#else + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: OpenSSL version is too old OR does not support threading,\n I am using single thread for relaying.\n"); +#endif + break; + case 'd': + STRCPY(turn_params.listener_ifname, value); + break; + case 'p': + turn_params.listener_port = atoi(value); + break; + case TLS_PORT_OPT: + turn_params.tls_listener_port = atoi(value); + break; + case ALT_PORT_OPT: + turn_params.alt_listener_port = atoi(value); + break; + case ALT_TLS_PORT_OPT: + turn_params.alt_tls_listener_port = atoi(value); + break; + case MIN_PORT_OPT: + turn_params.min_port = atoi(value); + break; + case MAX_PORT_OPT: + turn_params.max_port = atoi(value); + break; + case SECURE_STUN_OPT: + turn_params.secure_stun = get_bool_value(value); + break; + case SHA256_OPT: + if(get_bool_value(value)) + turn_params.shatype = SHATYPE_SHA256; + else + turn_params.shatype = SHATYPE_SHA1; + break; + case NO_MULTICAST_PEERS_OPT: + turn_params.no_multicast_peers = get_bool_value(value); + break; + case NO_LOOPBACK_PEERS_OPT: + turn_params.no_loopback_peers = get_bool_value(value); + break; + case STALE_NONCE_OPT: + turn_params.stale_nonce = get_bool_value(value); + break; + case MAX_ALLOCATE_TIMEOUT_OPT: + TURN_MAX_ALLOCATE_TIMEOUT = atoi(value); + TURN_MAX_ALLOCATE_TIMEOUT_STUN_ONLY = atoi(value); + break; + case 'S': + turn_params.stun_only = get_bool_value(value); + break; + case NO_STUN_OPT: + turn_params.no_stun = get_bool_value(value); + break; + case 'L': + add_listener_addr(value); + break; + case 'E': + add_relay_addr(value); + break; + case 'X': + if(value) { + char *div = strchr(value,'/'); + if(div) { + char *nval=strdup(value); + div = strchr(nval,'/'); + div[0]=0; + ++div; + ioa_addr apub,apriv; + if(make_ioa_addr((const u08bits*)nval,0,&apub)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"-X : Wrong address format: %s\n",nval); + } else { + if(make_ioa_addr((const u08bits*)div,0,&apriv)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"-X : Wrong address format: %s\n",div); + } else { + ioa_addr_add_mapping(&apub,&apriv); + } + } + turn_free(nval,strlen(nval)+1); + } else { + if(turn_params.external_ip) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "You cannot define external IP more than once in the configuration\n"); + } else { + turn_params.external_ip = (ioa_addr*)allocate_super_memory_engine(turn_params.listener.ioa_eng, sizeof(ioa_addr)); + if(make_ioa_addr((const u08bits*)value,0,turn_params.external_ip)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"-X : Wrong address format: %s\n",value); + turn_free(turn_params.external_ip,sizeof(ioa_addr)); + turn_params.external_ip = NULL; + } + } + } + } + break; + case 'v': + if(get_bool_value(value)) { + turn_params.verbose = TURN_VERBOSE_NORMAL; + } else { + turn_params.verbose = TURN_VERBOSE_NONE; + } + break; + case 'V': + if(get_bool_value(value)) { + turn_params.verbose = TURN_VERBOSE_EXTRA; + } + break; + case 'o': + turn_params.turn_daemon = get_bool_value(value); + break; + case 'a': + if (get_bool_value(value)) { + turn_params.ct = TURN_CREDENTIALS_LONG_TERM; + use_lt_credentials=1; + } else { + turn_params.ct = TURN_CREDENTIALS_UNDEFINED; + 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; + anon_credentials = 0; + } else { + turn_params.ct = TURN_CREDENTIALS_NONE; + anon_credentials = 1; + } + break; + case 'f': + turn_params.fingerprint = get_bool_value(value); + break; + case 'u': + add_user_account(value,0); + break; + case 'b': + STRCPY(turn_params.default_users_db.persistent_users_db.userdb, value); + turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_FILE; + break; +#if !defined(TURN_NO_PQ) + case 'e': + STRCPY(turn_params.default_users_db.persistent_users_db.userdb, value); + turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_PQ; + break; +#endif +#if !defined(TURN_NO_MYSQL) + case 'M': + STRCPY(turn_params.default_users_db.persistent_users_db.userdb, value); + turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MYSQL; + break; +#endif +#if !defined(TURN_NO_HIREDIS) + case 'N': + STRCPY(turn_params.default_users_db.persistent_users_db.userdb, value); + turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_REDIS; + break; + case 'O': + STRCPY(turn_params.redis_statsdb, value); + turn_params.use_redis_statsdb = 1; + break; +#endif + case AUTH_SECRET_OPT: + turn_params.use_auth_secret_with_timestamp = 1; + break; + case STATIC_AUTH_SECRET_VAL_OPT: + add_to_secrets_list(&turn_params.default_users_db.ram_db.static_auth_secrets,value); + turn_params.use_auth_secret_with_timestamp = 1; + break; + case AUTH_SECRET_TS_EXP: + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: Option --secret-ts-exp-time deprecated and has no effect.\n"); + break; + case 'r': + set_default_realm_name(value); + break; + case 'q': + turn_params.total_quota = (vint)atoi(value); + get_realm(NULL)->options.perf_options.user_quota = atoi(value); + break; + case 'Q': + turn_params.user_quota = (vint)atoi(value); + get_realm(NULL)->options.perf_options.total_quota = atoi(value); + break; + case 's': + turn_params.max_bps = (band_limit_t)atoi(value); + get_realm(NULL)->options.perf_options.max_bps = atoi(value); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%lu bytes per second allowed per session\n",(unsigned long)turn_params.max_bps); + break; + case NO_UDP_OPT: + turn_params.no_udp = get_bool_value(value); + break; + case NO_TCP_OPT: + turn_params.no_tcp = get_bool_value(value); + break; + case NO_UDP_RELAY_OPT: + turn_params.no_udp_relay = get_bool_value(value); + break; + case NO_TCP_RELAY_OPT: + turn_params.no_tcp_relay = get_bool_value(value); + break; + case NO_TLS_OPT: +#if defined(TURN_NO_TLS) + turn_params.no_tls = 1; +#else + turn_params.no_tls = get_bool_value(value); +#endif + break; + case NO_DTLS_OPT: +#if !defined(TURN_NO_DTLS) + turn_params.no_dtls = get_bool_value(value); +#else + turn_params.no_dtls = 1; +#endif + break; + case CERT_FILE_OPT: + STRCPY(turn_params.cert_file,value); + break; + case CA_FILE_OPT: + STRCPY(turn_params.ca_cert_file,value); + break; + case DH_FILE_OPT: + STRCPY(turn_params.dh_file,value); + break; + case PKEY_FILE_OPT: + STRCPY(turn_params.pkey_file,value); + break; + case PKEY_PWD_OPT: + STRCPY(turn_params.tls_password,value); + break; + case ALTERNATE_SERVER_OPT: + add_alternate_server(value); + break; + case AUX_SERVER_OPT: + add_aux_server(value); + break; + case UDP_SELF_BALANCE_OPT: + turn_params.udp_self_balance = get_bool_value(value); + break; + case TLS_ALTERNATE_SERVER_OPT: + add_tls_alternate_server(value); + break; + case ALLOWED_PEER_IPS: + if (add_ip_list_range(value, &turn_params.ip_whitelist) == 0) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "White listing: %s\n", value); + break; + case DENIED_PEER_IPS: + if (add_ip_list_range(value, &turn_params.ip_blacklist) == 0) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Black listing: %s\n", value); + break; + case CIPHER_LIST_OPT: + STRCPY(turn_params.cipher_list,value); + break; + case PIDFILE_OPT: + STRCPY(turn_params.pidfile,value); + break; + case 'C': + if(value && *value) { + turn_params.rest_api_separator=*value; + } + break; + /* these options have been already taken care of before: */ + case 'l': + case NO_STDOUT_LOG_OPT: + case SYSLOG_OPT: + case SIMPLE_LOG_OPT: + case 'c': + case 'n': + case 'h': + break; + default: + fprintf(stderr,"\n%s\n", Usage); + exit(-1); + } +} + +static int parse_arg_string(char *sarg, int *c, char **value) +{ + int i = 0; + char *name = sarg; + while(*sarg) { + if((*sarg==' ') || (*sarg=='=') || (*sarg=='\t')) { + *sarg=0; + do { + ++sarg; + } while((*sarg==' ') || (*sarg=='=') || (*sarg=='\t')); + *value = sarg; + break; + } + ++sarg; + *value=sarg; + } + + + if(value && *value && **value=='\"') { + *value += 1; + size_t len = strlen(*value); + while(len>0 && ( + ((*value)[len-1]=='\n') || + ((*value)[len-1]=='\r') || + ((*value)[len-1]==' ') || + ((*value)[len-1]=='\t') + ) ) { + (*value)[--len]=0; + } + if(len>0 && (*value)[len-1]=='\"') { + (*value)[--len]=0; + } + } + + while(long_options[i].name) { + if(strcmp(long_options[i].name,name)) { + ++i; + continue; + } + *c=long_options[i].val; + return 0; + } + + return -1; +} + +static void read_config_file(int argc, char **argv, int pass) +{ + static char config_file[1025] = DEFAULT_CONFIG_FILE; + + if(pass == 0) { + + if (argv) { + int i = 0; + for (i = 0; i < argc; i++) { + if (!strcmp(argv[i], "-c")) { + if (i < argc - 1) { + STRCPY(config_file, argv[i + 1]); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "Wrong usage of -c option\n"); + } + } else if (!strcmp(argv[i], "-n")) { + turn_params.do_not_use_config_file = 1; + config_file[0]=0; + return; + } else if (!strcmp(argv[i], "-h")) { + printf("\n%s\n",Usage); + exit(0); + } + } + } + } + + if (!turn_params.do_not_use_config_file && config_file[0]) { + + FILE *f = NULL; + char *full_path_to_config_file = NULL; + + full_path_to_config_file = find_config_file(config_file, 1); + if (full_path_to_config_file) + f = fopen(full_path_to_config_file, "r"); + + if (f && full_path_to_config_file) { + + char sbuf[1025]; + char sarg[1035]; + + for (;;) { + char *s = fgets(sbuf, sizeof(sbuf) - 1, f); + if (!s) + break; + s = skip_blanks(s); + if (s[0] == '#') + continue; + if (!s[0]) + continue; + size_t slen = strlen(s); + while (slen && ((s[slen - 1] == 10) || (s[slen - 1] == 13))) + s[--slen] = 0; + if (slen) { + int c = 0; + char *value = NULL; + STRCPY(sarg, s); + if (parse_arg_string(sarg, &c, &value) < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "Bad configuration format: %s\n", + sarg); + } else if((pass == 0) && (c == 'l')) { + set_logfile(value); + } else if((pass==0) && (c==NO_STDOUT_LOG_OPT)) { + set_no_stdout_log(get_bool_value(value)); + } else if((pass==0) && (c==SYSLOG_OPT)) { + set_log_to_syslog(get_bool_value(value)); + } else if((pass==0) && (c==SIMPLE_LOG_OPT)) { + set_simple_log(get_bool_value(value)); + } else if((pass == 0) && (c != 'u')) { + set_option(c, value); + } else if((pass > 0) && (c == 'u')) { + set_option(c, value); + } + } + } + + fclose(f); + + } else + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: Cannot find config file: %s. Default and command-line settings will be used.\n", + config_file); + } +} + +static int adminmain(int argc, char **argv) +{ + int c = 0; + + TURNADMIN_COMMAND_TYPE ct = TA_COMMAND_UNKNOWN; + int is_st = 0; + + u08bits user[STUN_MAX_USERNAME_SIZE+1]=""; + u08bits realm[STUN_MAX_REALM_SIZE+1]=""; + u08bits pwd[STUN_MAX_PWD_SIZE+1]=""; + u08bits secret[AUTH_SECRET_SIZE+1]=""; + u08bits origin[STUN_MAX_ORIGIN_SIZE+1]=""; + perf_options_t po = {-1,-1,-1}; + + while (((c = getopt_long(argc, argv, ADMIN_OPTIONS, admin_long_options, NULL)) != -1)) { + switch (c){ + case 'g': + ct = TA_SET_REALM_OPTION; + break; + case 'G': + ct = TA_LIST_REALM_OPTIONS; + break; + case ADMIN_USER_QUOTA_OPT: + po.user_quota = (vint)atoi(optarg); + break; + case ADMIN_TOTAL_QUOTA_OPT: + po.total_quota = (vint)atoi(optarg); + break; + case ADMIN_MAX_BPS_OPT: + po.max_bps = (vint)atoi(optarg); + break; + case 'O': + ct = TA_ADD_ORIGIN; + break; + case 'R': + ct = TA_DEL_ORIGIN; + break; + case 'I': + ct = TA_LIST_ORIGINS; + break; + case 'o': + STRCPY(origin,optarg); + break; + case 'k': + ct = TA_PRINT_KEY; + break; + case 'a': + ct = TA_UPDATE_USER; + break; + case 'd': + ct = TA_DELETE_USER; + break; + case 'A': + ct = TA_UPDATE_USER; + is_st = 1; + break; + case 'D': + ct = TA_DELETE_USER; + is_st = 1; + break; + case 'l': + ct = TA_LIST_USERS; + break; + case 'L': + ct = TA_LIST_USERS; + is_st = 1; + break; +#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_HIREDIS) + case 's': + ct = TA_SET_SECRET; + STRCPY(secret,optarg); + break; + case 'S': + ct = TA_SHOW_SECRET; + break; + case 'X': + ct = TA_DEL_SECRET; + if(optarg) + STRCPY(secret,optarg); + break; + case DEL_ALL_AUTH_SECRETS_OPT: + ct = TA_DEL_SECRET; + break; +#endif + case 'b': + STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg); + turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_FILE; + break; +#if !defined(TURN_NO_PQ) + case 'e': + STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg); + turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_PQ; + break; +#endif +#if !defined(TURN_NO_MYSQL) + case 'M': + STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg); + turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MYSQL; + break; +#endif +#if !defined(TURN_NO_HIREDIS) + case 'N': + STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg); + turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_REDIS; + break; +#endif + case 'u': + STRCPY(user,optarg); + if(SASLprep((u08bits*)user)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong user name: %s\n",user); + exit(-1); + } + break; + case 'r': + set_default_realm_name(optarg); + STRCPY(realm,optarg); + if(SASLprep((u08bits*)realm)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong realm: %s\n",realm); + exit(-1); + } + break; + case 'p': + STRCPY(pwd,optarg); + if(SASLprep((u08bits*)pwd)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong password: %s\n",pwd); + exit(-1); + } + break; + case 'H': + if(get_bool_value(optarg)) + turn_params.shatype = SHATYPE_SHA256; + else + turn_params.shatype = SHATYPE_SHA1; + break; + case 'h': + printf("\n%s\n", AdminUsage); + exit(0); + break; + default: + fprintf(stderr,"\n%s\n", AdminUsage); + exit(-1); + } + } + + if(is_st && (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_FILE)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "ERROR: you have to use a PostgreSQL or MySQL database with short-term credentials\n"); + exit(-1); + } + + if(!strlen(turn_params.default_users_db.persistent_users_db.userdb) && (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_FILE)) + STRCPY(turn_params.default_users_db.persistent_users_db.userdb,DEFAULT_USERDB_FILE); + + if(ct == TA_COMMAND_UNKNOWN) { + fprintf(stderr,"\n%s\n", AdminUsage); + exit(-1); + } + + argc -= optind; + argv += optind; + + if(argc != 0) { + fprintf(stderr,"\n%s\n", AdminUsage); + exit(-1); + } + + return adminuser(user, realm, pwd, secret, origin, ct, is_st, &po); +} + +static void print_features(unsigned long mfn) +{ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\nRFC 3489/5389/5766/5780/6062/6156 STUN/TURN Server\nVersion %s\n",TURN_SOFTWARE); + + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\nMax number of open files/sockets allowed for this process: %lu\n",mfn); + if(turn_params.net_engine_version == 1) + mfn = mfn/3; + else + mfn = mfn/2; + mfn = ((unsigned long)(mfn/500))*500; + if(mfn<500) + mfn = 500; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\nDue to the open files/sockets limitation,\nmax supported number of TURN Sessions possible is: %lu (approximately)\n",mfn); + + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\n\n==== Show him the instruments, Practical Frost: ====\n\n"); + +#if defined(TURN_NO_TLS) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS is not supported\n"); +#else + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS supported\n"); +#endif + +#if defined(TURN_NO_DTLS) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS is not supported\n"); +#else + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS supported\n"); +#endif + +#if !defined(TURN_NO_HIREDIS) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis supported\n"); +#else + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis is not supported\n"); +#endif + +#if !defined(TURN_NO_PQ) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "PostgreSQL supported\n"); +#else + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "PostgreSQL is not supported\n"); +#endif + +#if !defined(TURN_NO_MYSQL) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MySQL supported\n"); +#else + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MySQL is not supported\n"); +#endif + +#if defined(OPENSSL_THREADS) + //TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL multithreading supported\n"); +#else + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "OpenSSL multithreading is not supported (?!)\n"); +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL version: fresh enough\n"); +#else + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL version: antique\n"); +#endif + + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Default Net Engine version: %d (%s)\n\n=====================================================\n\n", (int)turn_params.net_engine_version, turn_params.net_engine_version_txt[(int)turn_params.net_engine_version]); + +} + +#if defined(__linux__) || defined(__LINUX__) || defined(__linux) || defined(linux__) || defined(LINUX) || defined(__LINUX) || defined(LINUX__) +#include +#endif + +static void set_network_engine(void) +{ + if(turn_params.net_engine_version != NEV_UNKNOWN) + return; + turn_params.net_engine_version = NEV_UDP_SOCKET_PER_ENDPOINT; +#if defined(SO_REUSEPORT) +#if defined(__linux__) || defined(__LINUX__) || defined(__linux) || defined(linux__) || defined(LINUX) || defined(__LINUX) || defined(LINUX__) + turn_params.net_engine_version = NEV_UDP_SOCKET_PER_THREAD; +#else /* BSD ? */ + turn_params.net_engine_version = NEV_UDP_SOCKET_PER_SESSION; +#endif /* Linux */ +#else /* defined(SO_REUSEPORT) */ +#if defined(__linux__) || defined(__LINUX__) || defined(__linux) || defined(linux__) || defined(LINUX) || defined(__LINUX) || defined(LINUX__) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) + //net_engine_version = NEV_UDP_SOCKET_PER_SESSION; + turn_params.net_engine_version = NEV_UDP_SOCKET_PER_ENDPOINT; +#else + turn_params.net_engine_version = NEV_UDP_SOCKET_PER_ENDPOINT; +#endif /* Linux version */ +#endif /* Linux */ +#endif /* defined(SO_REUSEPORT) */ + +} + +static void drop_privileges(void) +{ + if(procgroupid_set) { + if(getgid() != procgroupid) { + if (setgid(procgroupid) != 0) { + perror("setgid: Unable to change group privileges"); + exit(-1); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "New GID: %s(%lu)\n", procgroupname, (unsigned long)procgroupid); + } + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Keep GID: %s(%lu)\n", procgroupname, (unsigned long)procgroupid); + } + } + + if(procuserid_set) { + if(procuserid != getuid()) { + if (setuid(procuserid) != 0) { + perror("setuid: Unable to change user privileges"); + exit(-1); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "New UID: %s(%lu)\n", procusername, (unsigned long)procuserid); + } + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Keep UID: %s(%lu)\n", procusername, (unsigned long)procuserid); + } + } +} + +int main(int argc, char **argv) +{ + int c = 0; + + IS_TURN_SERVER = 1; + + set_execdir(); + + init_super_memory(); + +#if !defined(TURN_NO_HIREDIS) + redis_async_init(); +#endif + + create_new_realm(NULL); + + init_turn_server_addrs_list(&turn_params.alternate_servers_list); + init_turn_server_addrs_list(&turn_params.tls_alternate_servers_list); + init_turn_server_addrs_list(&turn_params.aux_servers_list); + + set_network_engine(); + + init_listener(); + init_secrets_list(&turn_params.default_users_db.ram_db.static_auth_secrets); + init_dynamic_ip_lists(); + + if (!strstr(argv[0], "turnadmin")) { + while (((c = getopt_long(argc, argv, OPTIONS, long_options, NULL)) != -1)) { + switch (c){ + case 'l': + set_logfile(optarg); + break; + case NO_STDOUT_LOG_OPT: + set_no_stdout_log(get_bool_value(optarg)); + break; + case SYSLOG_OPT: + set_log_to_syslog(get_bool_value(optarg)); + break; + case SIMPLE_LOG_OPT: + set_simple_log(get_bool_value(optarg)); + break; + default: + ; + } + } + } + + optind = 0; + +#if defined(TURN_NO_TLS) + turn_params.no_tls = 1; +#endif + +#if defined(TURN_NO_DTLS) + turn_params.no_dtls = 1; +#endif + +#if defined(_SC_NPROCESSORS_ONLN) + + { + long cpus = (long)sysconf(_SC_NPROCESSORS_CONF); + + if(cpus<1) + cpus = 1; + else if(cpus>MAX_NUMBER_OF_GENERAL_RELAY_SERVERS) + cpus = MAX_NUMBER_OF_GENERAL_RELAY_SERVERS; + + turn_params.general_relay_servers_number = (turnserver_id)cpus; + } + +#endif + + 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(free); + turn_params.default_users_db.ram_db.dynamic_accounts = ur_string_map_create(free); + + if(strstr(argv[0],"turnadmin")) + return adminmain(argc,argv); + + { + unsigned long mfn = set_system_parameters(1); + + print_features(mfn); + } + + read_config_file(argc,argv,0); + + while (((c = getopt_long(argc, argv, OPTIONS, long_options, NULL)) != -1)) { + if(c != 'u') + set_option(c,optarg); + } + + read_config_file(argc,argv,1); + + optind = 0; + + while (((c = getopt_long(argc, argv, OPTIONS, long_options, NULL)) != -1)) { + if(c == 'u') { + set_option(c,optarg); + } + } + + if(turn_params.no_udp_relay && turn_params.no_tcp_relay) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nCONFIG ERROR: --no-udp-relay and --no-tcp-relay options cannot be used together.\n"); + exit(-1); + } + + if(turn_params.no_udp_relay) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\nCONFIG: --no-udp-relay: UDP relay endpoints are not allowed.\n"); + } + + if(turn_params.no_tcp_relay) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\nCONFIG: --no-tcp-relay: TCP relay endpoints are not allowed.\n"); + } + + if(turn_params.server_relay) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "\nCONFIG: WARNING: --server-relay: NON-STANDARD AND DANGEROUS OPTION.\n"); + } + + if(!strlen(turn_params.default_users_db.persistent_users_db.userdb) && (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_FILE)) + STRCPY(turn_params.default_users_db.persistent_users_db.userdb,DEFAULT_USERDB_FILE); + + read_userdb_file(0); + update_white_and_black_lists(); + + argc -= optind; + argv += optind; + + if(argc>0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nCONFIGURATION ALERT: Unknown argument: %s\n",argv[argc-1]); + } + + if(use_lt_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_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(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; + use_lt_credentials=1; + } else { + turn_params.ct = TURN_CREDENTIALS_NONE; + use_lt_credentials=0; + } + } + + if(use_lt_credentials) { + if(!turn_params.default_users_db.ram_db.users_number && (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_FILE) && !turn_params.use_auth_secret_with_timestamp) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "\nCONFIGURATION ALERT: you did not specify any user account, (-u option) \n but you did specified a long-term credentials mechanism option (-a option).\n The TURN Server will be inaccessible.\n Check your configuration.\n"); + } else if(!get_realm(NULL)->options.name[0]) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "\nCONFIGURATION ALERT: you did specify the long-term credentials usage\n but you did not specify the default realm option (-r option).\n Check your configuration.\n"); + } + } + + if(anon_credentials) { + if(turn_params.default_users_db.ram_db.users_number) { + 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; + if (!turn_params.listener.addrs_number) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "NO EXPLICIT LISTENER ADDRESS(ES) ARE CONFIGURED\n"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "===========Discovering listener addresses: =========\n"); + int maddrs = make_local_listeners_list(); + if((maddrs<1) || !turn_params.listener.addrs_number) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot configure any meaningful IP listener address\n", __FUNCTION__); + fprintf(stderr,"\n%s\n", Usage); + exit(-1); + } + local_listeners = 1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "=====================================================\n"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Total: %d 'real' addresses discovered\n",maddrs); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "=====================================================\n"); + } + + if (!turn_params.relays_number) { + if(!local_listeners && turn_params.listener.addrs_number && turn_params.listener.addrs) { + size_t la = 0; + for(la=0;la0) + exit(0); + if(pid<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "ERROR: Cannot start daemon process\n"); + exit(-1); + } +#else + if(daemon(1,0)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "ERROR: Cannot start daemon process\n"); + exit(-1); + } + reset_rtpprintf(); +#endif + } + + if(turn_params.pidfile[0]) { + + char s[2049]; + FILE *f = fopen(turn_params.pidfile,"w"); + if(f) { + STRCPY(s,turn_params.pidfile); + } else { + snprintf(s,sizeof(s),"Cannot create pid file: %s",turn_params.pidfile); + perror(s); + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "%s\n", s); + + { + const char *pfs[] = {"/var/run/turnserver.pid", + "/var/spool/turnserver.pid", + "/var/turnserver.pid", + "/var/tmp/turnserver.pid", + "/tmp/turnserver.pid", + "turnserver.pid", + NULL}; + const char **ppfs = pfs; + while(*ppfs) { + f = fopen(*ppfs,"w"); + if(f) { + STRCPY(s,*ppfs); + break; + } else { + ++ppfs; + } + } + } + } + + if(f) { + fprintf(f,"%lu\n",(unsigned long)getpid()); + fclose(f); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "pid file created: %s\n", s); + } + } + + setup_server(); + + drop_privileges(); + + run_listener_server(&(turn_params.listener)); + + return 0; +} + +////////// OpenSSL locking //////////////////////////////////////// + +#if defined(OPENSSL_THREADS) + +static pthread_mutex_t* mutex_buf = NULL; + +static void locking_function(int mode, int n, const char *file, int line) { + UNUSED_ARG(file); + UNUSED_ARG(line); + if (mode & CRYPTO_LOCK) + pthread_mutex_lock(&mutex_buf[n]); + else + pthread_mutex_unlock(&mutex_buf[n]); +} + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L +static void id_function(CRYPTO_THREADID *ctid) +{ + CRYPTO_THREADID_set_numeric(ctid, (unsigned long)pthread_self()); +} +#else +static unsigned long id_function(void) +{ + return (unsigned long)pthread_self(); +} +#endif + +#endif + +static int THREAD_setup(void) { + +#if defined(OPENSSL_THREADS) + + int i; + + mutex_buf = (pthread_mutex_t*) turn_malloc(CRYPTO_num_locks() + * sizeof(pthread_mutex_t)); + if (!mutex_buf) + return 0; + for (i = 0; i < CRYPTO_num_locks(); i++) + pthread_mutex_init(&mutex_buf[i], NULL); + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + CRYPTO_THREADID_set_callback(id_function); +#else + CRYPTO_set_id_callback(id_function); +#endif + + CRYPTO_set_locking_callback(locking_function); +#endif + + return 1; +} + +int THREAD_cleanup(void); +int THREAD_cleanup(void) { + +#if defined(OPENSSL_THREADS) + + int i; + + if (!mutex_buf) + return 0; + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + CRYPTO_THREADID_set_callback(NULL); +#else + CRYPTO_set_id_callback(NULL); +#endif + + CRYPTO_set_locking_callback(NULL); + for (i = 0; i < CRYPTO_num_locks(); i++) + pthread_mutex_destroy(&mutex_buf[i]); + turn_free(mutex_buf,sizeof(pthread_mutex_t)); + mutex_buf = NULL; + +#endif + + return 1; +} + +static void adjust_key_file_name(char *fn, const char* file_title, int critical) +{ + char *full_path_to_file = NULL; + + if(!fn[0]) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"\nERROR: you must set the %s file parameter\n",file_title); + goto keyerr; + } else { + + full_path_to_file = find_config_file(fn, 1); + { + FILE *f = full_path_to_file ? fopen(full_path_to_file,"r") : NULL; + if(!f) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,"WARNING: cannot find %s file: %s (1)\n",file_title,fn); + goto keyerr; + } else { + fclose(f); + } + } + + if(!full_path_to_file) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,"WARNING: cannot find %s file: %s (2)\n",file_title,fn); + goto keyerr; + } + + strncpy(fn,full_path_to_file,sizeof(turn_params.cert_file)-1); + fn[sizeof(turn_params.cert_file)-1]=0; + + if(full_path_to_file) + turn_free(full_path_to_file,strlen(full_path_to_file)+1); + return; + } + + keyerr: + { + if(critical) { + turn_params.no_tls = 1; + turn_params.no_dtls = 1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,"WARNING: cannot start TLS and DTLS listeners because %s file is not set properly\n",file_title); + } + if(full_path_to_file) + turn_free(full_path_to_file,strlen(full_path_to_file)+1); + return; + } +} + +static void adjust_key_file_names(void) +{ + if(turn_params.ca_cert_file[0]) + adjust_key_file_name(turn_params.ca_cert_file,"CA",1); + adjust_key_file_name(turn_params.cert_file,"certificate",1); + adjust_key_file_name(turn_params.pkey_file,"private key",1); + if(turn_params.dh_file[0]) + adjust_key_file_name(turn_params.dh_file,"DH key",0); +} + +static DH *get_dh566(void) { + + unsigned char dh566_p[] = { + 0x36,0x53,0xA8,0x9C,0x3C,0xF1,0xD1,0x1B,0x2D,0xA2,0x64,0xDE, + 0x59,0x3B,0xE3,0x8C,0x27,0x74,0xC2,0xBE,0x9B,0x6D,0x56,0xE7, + 0xDF,0xFF,0x67,0x6A,0xD2,0x0C,0xE8,0x9E,0x52,0x00,0x05,0xB3, + 0x53,0xF7,0x1C,0x41,0xB2,0xAC,0x38,0x16,0x32,0x3A,0x8E,0x90, + 0x6C,0x7E,0xD1,0x44,0xCB,0xF9,0x2D,0x1E,0x4A,0x9A,0x32,0x81, + 0x58,0xE1,0xE1,0x17,0xC1,0x9C,0xF1,0x1E,0x96,0x2D,0x5F + }; + +// -----BEGIN DH PARAMETERS----- +//MEwCRzZTqJw88dEbLaJk3lk744wndMK+m21W59//Z2rSDOieUgAFs1P3HEGyrDgW +//MjqOkGx+0UTL+S0eSpoygVjh4RfBnPEeli1fAgEF +// -----END DH PARAMETERS----- + + unsigned char dh566_g[] = { 0x05 }; + DH *dh; + + if ((dh = DH_new()) == NULL ) + return (NULL ); + dh->p = BN_bin2bn(dh566_p, sizeof(dh566_p), NULL ); + dh->g = BN_bin2bn(dh566_g, sizeof(dh566_g), NULL ); + if ((dh->p == NULL )|| (dh->g == NULL)){ DH_free(dh); return(NULL);} + return (dh); +} + +static DH *get_dh1066(void) { + + unsigned char dh1066_p[] = { + 0x02,0x0E,0x26,0x6F,0xAA,0x9F,0xA8,0xE5,0x3F,0x70,0x88,0xF1, + 0xA9,0x29,0xAE,0x1A,0x2B,0xA8,0x2F,0xE8,0xE5,0x0E,0x81,0x78, + 0xD7,0x12,0x41,0xDC,0xE2,0xD5,0x10,0x6F,0x8A,0x35,0x23,0xCE, + 0x66,0x93,0x67,0x14,0xEA,0x0A,0x61,0xD4,0x43,0x63,0x5C,0xDF, + 0xDE,0xF5,0xB9,0xC6,0xB4,0x8C,0xBA,0x1A,0x25,0x9F,0x73,0x0F, + 0x1E,0x1A,0x97,0x42,0x2E,0x60,0x9E,0x4C,0x3C,0x70,0x6A,0xFB, + 0xDD,0xAA,0x7A,0x48,0xA5,0x1E,0x87,0xC8,0xA3,0x5E,0x26,0x40, + 0x1B,0xDE,0x08,0x5E,0xA2,0xB8,0xE8,0x76,0x43,0xE8,0xF1,0x4B, + 0x35,0x4C,0x38,0x92,0xB9,0xFF,0x61,0xE6,0x6C,0xBA,0xF9,0x16, + 0x36,0x3C,0x69,0x2D,0x57,0x90,0x62,0x8A,0xD0,0xD4,0xFB,0xB2, + 0x5A,0x61,0x99,0xA9,0xE8,0x93,0x80,0xA2,0xB7,0xDC,0xB1,0x6A, + 0xAF,0xE3 + }; + +// -----BEGIN DH PARAMETERS----- +// MIGMAoGGAg4mb6qfqOU/cIjxqSmuGiuoL+jlDoF41xJB3OLVEG+KNSPOZpNnFOoK +// YdRDY1zf3vW5xrSMuholn3MPHhqXQi5gnkw8cGr73ap6SKUeh8ijXiZAG94IXqK4 +// 6HZD6PFLNUw4krn/YeZsuvkWNjxpLVeQYorQ1PuyWmGZqeiTgKK33LFqr+MCAQI= +// -----END DH PARAMETERS----- + + unsigned char dh1066_g[] = { 0x02 }; + DH *dh; + + if ((dh = DH_new()) == NULL ) + return (NULL ); + dh->p = BN_bin2bn(dh1066_p, sizeof(dh1066_p), NULL ); + dh->g = BN_bin2bn(dh1066_g, sizeof(dh1066_g), NULL ); + if ((dh->p == NULL )|| (dh->g == NULL)){ DH_free(dh); return(NULL);} + return (dh); +} + +static DH *get_dh2066(void) { + + unsigned char dh2066_p[] = { + 0x03,0x31,0x77,0x20,0x58,0xA6,0x69,0xA3,0x9D,0x2D,0x5E,0xE0, + 0x5C,0x46,0x82,0x0F,0x9E,0x80,0xF0,0x00,0x2A,0xF9,0x0F,0x62, + 0x1F,0x89,0xCE,0x7D,0x2A,0xFD,0xC5,0x9A,0x7C,0x6A,0x60,0x2C, + 0xF1,0xDD,0xD4,0x4D,0x6B,0xCD,0xE9,0x95,0xDB,0x42,0x97,0xBA, + 0xE4,0xAF,0x41,0x38,0x8F,0x57,0x31,0xA4,0x39,0xDD,0x31,0xC3, + 0x6F,0x98,0x0E,0xE3,0xB1,0x43,0xD1,0x36,0xB0,0x01,0x28,0x42, + 0x71,0xD3,0xB0,0x36,0xA0,0x47,0x99,0x25,0x9B,0x32,0xF5,0x86, + 0xB1,0x13,0x5C,0x24,0x8D,0x8D,0x7F,0xE2,0x7F,0x9A,0xC1,0x52, + 0x58,0xC0,0x63,0xAA,0x00,0x7C,0x1F,0x11,0xBD,0xAC,0x4C,0x2D, + 0xE0,0xA2,0x9D,0x4E,0x21,0xE4,0x0B,0xCD,0x24,0x92,0xD2,0x37, + 0x27,0x84,0x59,0x90,0x46,0x2F,0xD5,0xB9,0x27,0x93,0x18,0x88, + 0xBD,0x91,0x5B,0x87,0x55,0x56,0xD8,0x1B,0xE4,0xCF,0x1C,0xAA, + 0xBC,0xCF,0x80,0x1E,0x35,0x2D,0xB1,0xBC,0x35,0x31,0x92,0x62, + 0x3C,0x91,0x8D,0x62,0xDA,0xCF,0x83,0x63,0x12,0x4B,0x30,0x80, + 0xEE,0x82,0x3C,0x2C,0xD2,0x17,0x13,0x1F,0xF9,0x62,0x33,0x5C, + 0x63,0xD8,0x75,0x5B,0xAA,0x16,0x5A,0x36,0x49,0x17,0x77,0xB7, + 0x74,0xBD,0x3E,0x3F,0x98,0x20,0x59,0x5E,0xC7,0x72,0xE8,0xA3, + 0x89,0x21,0xB4,0x3C,0x25,0xF4,0xF4,0x21,0x96,0x5A,0xA6,0x77, + 0xFF,0x2C,0x3A,0xFC,0x98,0x5F,0xC1,0xBF,0x2A,0xCF,0xB8,0x62, + 0x67,0x23,0xE8,0x2F,0xCC,0x7B,0x32,0x1B,0x6B,0x33,0x67,0x0A, + 0xCB,0xD0,0x1F,0x65,0xD7,0x84,0x54,0xF6,0xF1,0x88,0xB5,0xBB, + 0x0C,0x63,0x65,0x34,0xE4,0x66,0x4B + }; + +// -----BEGIN DH PARAMETERS----- +//MIIBCgKCAQMDMXcgWKZpo50tXuBcRoIPnoDwACr5D2Ific59Kv3FmnxqYCzx3dRN +//a83pldtCl7rkr0E4j1cxpDndMcNvmA7jsUPRNrABKEJx07A2oEeZJZsy9YaxE1wk +//jY1/4n+awVJYwGOqAHwfEb2sTC3gop1OIeQLzSSS0jcnhFmQRi/VuSeTGIi9kVuH +//VVbYG+TPHKq8z4AeNS2xvDUxkmI8kY1i2s+DYxJLMIDugjws0hcTH/liM1xj2HVb +//qhZaNkkXd7d0vT4/mCBZXsdy6KOJIbQ8JfT0IZZapnf/LDr8mF/BvyrPuGJnI+gv +//zHsyG2szZwrL0B9l14RU9vGItbsMY2U05GZLAgEF +// -----END DH PARAMETERS----- + + unsigned char dh2066_g[] = { 0x05 }; + DH *dh; + + if ((dh = DH_new()) == NULL ) + return (NULL ); + dh->p = BN_bin2bn(dh2066_p, sizeof(dh2066_p), NULL ); + dh->g = BN_bin2bn(dh2066_g, sizeof(dh2066_g), NULL ); + if ((dh->p == NULL )|| (dh->g == NULL)){ DH_free(dh); return(NULL);} + return (dh); +} + +static int pem_password_func(char *buf, int size, int rwflag, void *password) +{ + UNUSED_ARG(rwflag); + + strncpy(buf, (char * )(password), size); + buf[size - 1] = 0; + return (strlen(buf)); +} + +static void set_ctx(SSL_CTX* ctx, const char *protocol) +{ + SSL_CTX_set_default_passwd_cb_userdata(ctx, turn_params.tls_password); + + SSL_CTX_set_default_passwd_cb(ctx, pem_password_func); + + if(!(turn_params.cipher_list[0])) + STRCPY(turn_params.cipher_list,DEFAULT_CIPHER_LIST); + + SSL_CTX_set_cipher_list(ctx, turn_params.cipher_list); + SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); + + if (!SSL_CTX_use_certificate_chain_file(ctx, turn_params.cert_file)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: no certificate found\n", protocol); + } else { + print_abs_file_name(protocol, ": Certificate", turn_params.cert_file); + } + + if (!SSL_CTX_use_PrivateKey_file(ctx, turn_params.pkey_file, SSL_FILETYPE_PEM)) { + if (!SSL_CTX_use_RSAPrivateKey_file(ctx, turn_params.pkey_file, SSL_FILETYPE_PEM)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: no valid private key found, or invalid private key password provided\n", protocol); + } else { + print_abs_file_name(protocol, ": Private RSA key", turn_params.pkey_file); + } + } else { + print_abs_file_name(protocol, ": Private key", turn_params.pkey_file); + } + + if (!SSL_CTX_check_private_key(ctx)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: invalid private key\n", protocol); + } + + if(turn_params.ca_cert_file[0]) { + + if (!SSL_CTX_load_verify_locations(ctx, turn_params.ca_cert_file, NULL )) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot load CA from file: %s\n", turn_params.ca_cert_file); + } + + SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(turn_params.ca_cert_file)); + + /* Set to require peer (client) certificate verification */ + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, NULL); + + /* Set the verification depth to 9 */ + SSL_CTX_set_verify_depth(ctx, 9); + + } else { + SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); + } + +#if !defined(OPENSSL_NO_EC) && defined(OPENSSL_EC_NAMED_CURVE) + { //Elliptic curve algorithms: + int nid = NID_X9_62_prime256v1; + + if (turn_params.ec_curve_name[0]) { + nid = OBJ_sn2nid(turn_params.ec_curve_name); + if (nid == 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"unknown curve name (%s), using NID_X9_62_prime256v1\n",turn_params.ec_curve_name); + nid = NID_X9_62_prime256v1; + } + } + + EC_KEY *ecdh = EC_KEY_new_by_curve_name(nid); + if (!ecdh) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: ERROR: allocate EC suite\n"); + } else { + SSL_CTX_set_tmp_ecdh(ctx, ecdh); + EC_KEY_free(ecdh); + } + } +#endif + + {//DH algorithms: + + DH *dh = NULL; + if(turn_params.dh_file[0]) { + FILE *paramfile = fopen(turn_params.dh_file, "r"); + if (!paramfile) { + perror("Cannot open DH file"); + } else { + dh = PEM_read_DHparams(paramfile, NULL, NULL, NULL); + fclose(paramfile); + if(dh) { + turn_params.dh_key_size = DH_CUSTOM; + } + } + } + + if(!dh) { + if(turn_params.dh_key_size == DH_566) + dh = get_dh566(); + else if(turn_params.dh_key_size == DH_2066) + dh = get_dh2066(); + else + dh = get_dh1066(); + } + + if(!dh) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot allocate DH suite\n"); + } else { + if (1 != SSL_CTX_set_tmp_dh (ctx, dh)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot set DH\n"); + } + DH_free (dh); + } + } + + { + int op = 0; + +#if defined(SSL_OP_NO_SSLv2) + if(turn_params.no_sslv2) + op |= SSL_OP_NO_SSLv2; +#endif + if(turn_params.no_sslv3) + op |= SSL_OP_NO_SSLv3; + + if(turn_params.no_tlsv1) + op |= SSL_OP_NO_TLSv1; + +#if defined(SSL_OP_NO_TLSv1_1) + if(turn_params.no_tlsv1_1) + op |= SSL_OP_NO_TLSv1_1; +#endif +#if defined(SSL_OP_NO_TLSv1_2) + if(turn_params.no_tlsv1_2) + op |= SSL_OP_NO_TLSv1_2; +#endif + +#if defined(SSL_OP_CIPHER_SERVER_PREFERENCE) + op |= SSL_OP_CIPHER_SERVER_PREFERENCE; +#endif + +#if defined(SSL_OP_SINGLE_DH_USE) + op |= SSL_OP_SINGLE_DH_USE; +#endif + +#if defined(SSL_OP_SINGLE_ECDH_USE) + op |= SSL_OP_SINGLE_ECDH_USE; +#endif + + SSL_CTX_set_options(ctx, op); + } +} + +static void openssl_setup(void) +{ + THREAD_setup(); + SSL_load_error_strings(); + OpenSSL_add_ssl_algorithms(); + +#if defined(TURN_NO_TLS) + if(!turn_params.no_tls) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "WARNING: TLS is not supported\n"); + turn_params.no_tls = 1; + } +#endif + + if(!(turn_params.no_tls && turn_params.no_dtls) && !turn_params.cert_file[0]) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,"\nWARNING: certificate file is not specified, I cannot start TLS/DTLS services.\nOnly 'plain' UDP/TCP listeners can be started.\n"); + turn_params.no_tls = 1; + turn_params.no_dtls = 1; + } + + if(!(turn_params.no_tls && turn_params.no_dtls) && !turn_params.pkey_file[0]) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,"\nWARNING: private key file is not specified, I cannot start TLS/DTLS services.\nOnly 'plain' UDP/TCP listeners can be started.\n"); + turn_params.no_tls = 1; + turn_params.no_dtls = 1; + } + + if(!(turn_params.no_tls && turn_params.no_dtls)) { + adjust_key_file_names(); + } + + if(!turn_params.no_tls) { + turn_params.tls_ctx_ssl23 = SSL_CTX_new(SSLv23_server_method()); /*compatibility mode */ + set_ctx(turn_params.tls_ctx_ssl23,"SSL23"); + if(!turn_params.no_tlsv1) { + turn_params.tls_ctx_v1_0 = SSL_CTX_new(TLSv1_server_method()); + set_ctx(turn_params.tls_ctx_v1_0,"TLS1.0"); + } +#if defined(SSL_TXT_TLSV1_1) + if(!turn_params.no_tlsv1_1) { + turn_params.tls_ctx_v1_1 = SSL_CTX_new(TLSv1_1_server_method()); + set_ctx(turn_params.tls_ctx_v1_1,"TLS1.1"); + } +#if defined(SSL_TXT_TLSV1_2) + if(!turn_params.no_tlsv1_2) { + turn_params.tls_ctx_v1_2 = SSL_CTX_new(TLSv1_2_server_method()); + set_ctx(turn_params.tls_ctx_v1_2,"TLS1.2"); + } +#endif +#endif + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS cipher suite: %s\n",turn_params.cipher_list); + } + + if(!turn_params.no_dtls) { +#if defined(TURN_NO_DTLS) + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "ERROR: DTLS is not supported.\n"); +#else + 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); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS cipher suite: %s\n",turn_params.cipher_list); +#endif + } +} + +/////////////////////////////// diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h new file mode 100644 index 00000000..a76c1b32 --- /dev/null +++ b/src/apps/relay/mainrelay.h @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#if !defined(__MAIN_RELAY__) +#define __MAIN_RELAY__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "ns_turn_utils.h" +#include "ns_turn_khash.h" + +#include "userdb.h" +#include "turncli.h" + +#include "tls_listener.h" +#include "dtls_listener.h" + +#include "ns_turn_server.h" +#include "ns_turn_maps.h" + +#include "apputils.h" + +#include "ns_ioalib_impl.h" + +#if !defined(TURN_NO_HIREDIS) +#include "hiredis_libevent2.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +////////////// DEFINES //////////////////////////// + +#define DEFAULT_CONFIG_FILE "turnserver.conf" + +#define DEFAULT_CIPHER_LIST "DEFAULT" +/* "ALL:eNULL:aNULL:NULL" */ + +#define DEFAULT_EC_CURVE_NAME "prime256v1" + +#define MAX_NUMBER_OF_GENERAL_RELAY_SERVERS ((u08bits)(0x80)) + +#define TURNSERVER_ID_BOUNDARY_BETWEEN_TCP_AND_UDP MAX_NUMBER_OF_GENERAL_RELAY_SERVERS +#define TURNSERVER_ID_BOUNDARY_BETWEEN_UDP_AND_TCP TURNSERVER_ID_BOUNDARY_BETWEEN_TCP_AND_UDP + +/////////// TYPES /////////////////////////////////// + +enum _DH_KEY_SIZE { + DH_566, + DH_1066, + DH_2066, + DH_CUSTOM +}; + +typedef enum _DH_KEY_SIZE DH_KEY_SIZE; + +///////// LISTENER SERVER TYPES ///////////////////// + +struct message_to_listener_to_client { + ioa_addr origin; + ioa_addr destination; + ioa_network_buffer_handle nbh; +}; + +enum _MESSAGE_TO_LISTENER_TYPE { + LMT_UNKNOWN, + LMT_TO_CLIENT +}; +typedef enum _MESSAGE_TO_LISTENER_TYPE MESSAGE_TO_LISTENER_TYPE; + +struct message_to_listener { + MESSAGE_TO_LISTENER_TYPE t; + union { + struct message_to_listener_to_client tc; + } m; +}; + +struct listener_server { + rtcp_map* rtcpmap; + turnipports* tp; + struct event_base* event_base; + ioa_engine_handle ioa_eng; + struct bufferevent *in_buf; + struct bufferevent *out_buf; + char **addrs; + ioa_addr **encaddrs; + size_t addrs_number; + size_t services_number; + dtls_listener_relay_server_type ***udp_services; + dtls_listener_relay_server_type ***dtls_services; + dtls_listener_relay_server_type ***aux_udp_services; +}; + +enum _NET_ENG_VERSION { + NEV_UNKNOWN=0, + NEV_MIN, + NEV_UDP_SOCKET_PER_SESSION=NEV_MIN, + NEV_UDP_SOCKET_PER_ENDPOINT, + NEV_UDP_SOCKET_PER_THREAD, + NEV_MAX=NEV_UDP_SOCKET_PER_THREAD, + NEV_TOTAL +}; + +typedef enum _NET_ENG_VERSION NET_ENG_VERSION; + +////////////// Auth Server Types //////////////// + +struct auth_server { + struct event_base* event_base; + struct bufferevent *in_buf; + struct bufferevent *out_buf; + pthread_t thr; +#if !defined(TURN_NO_HIREDIS) + redis_context_handle rch; +#endif +}; + +/////////// PARAMS ////////////////////////////////// + +typedef struct _turn_params_ { + +//////////////// OpenSSL group ////////////////////// + + SSL_CTX *tls_ctx_ssl23; + + SSL_CTX *tls_ctx_v1_0; + +#if defined(SSL_TXT_TLSV1_1) + SSL_CTX *tls_ctx_v1_1; +#if defined(SSL_TXT_TLSV1_2) + SSL_CTX *tls_ctx_v1_2; +#endif +#endif + + SSL_CTX *dtls_ctx; + + DH_KEY_SIZE dh_key_size; + + char cipher_list[1025]; + char ec_curve_name[33]; + + char ca_cert_file[1025]; + char cert_file[1025]; + char pkey_file[1025]; + char tls_password[513]; + char dh_file[1025]; + + int no_sslv2; + int no_sslv3; + int no_tlsv1; + int no_tlsv1_1; + int no_tlsv1_2; + int no_tls; + int no_dtls; + +//////////////// Common params //////////////////// + + int verbose; + int turn_daemon; + + int do_not_use_config_file; + + char pidfile[1025]; + + //////////////// Listener server ///////////////// + + int listener_port; + int tls_listener_port; + int alt_listener_port; + int alt_tls_listener_port; + int rfc5780; + + int no_udp; + int no_tcp; + + vint no_tcp_relay; + vint no_udp_relay; + + char listener_ifname[1025]; + +#if !defined(TURN_NO_HIREDIS) + char redis_statsdb[1025]; + int use_redis_statsdb; +#endif + + struct listener_server listener; + + ip_range_list_t ip_whitelist; + ip_range_list_t ip_blacklist; + + NET_ENG_VERSION net_engine_version; + const char* net_engine_version_txt[NEV_TOTAL]; + +//////////////// Relay servers ///////////// + + u16bits min_port; + u16bits max_port; + + vint no_multicast_peers; + vint no_loopback_peers; + + char relay_ifname[1025]; + + size_t relays_number; + char **relay_addrs; + int default_relays; + + // Single global public IP. + // If multiple public IPs are used + // then ioa_addr mapping must be used. + ioa_addr *external_ip; + + turnserver_id general_relay_servers_number; + turnserver_id udp_relay_servers_number; + +////////////// Auth server //////////////// + + struct auth_server authserver; + +/////////////// AUX SERVERS //////////////// + + turn_server_addrs_list_t aux_servers_list; + int udp_self_balance; + +/////////////// ALTERNATE SERVERS //////////////// + + turn_server_addrs_list_t alternate_servers_list; + turn_server_addrs_list_t tls_alternate_servers_list; + + int stop_turn_server; + +////////////// MISC PARAMS //////////////// + + vint stun_only; + vint no_stun; + vint secure_stun; + int server_relay; + int fingerprint; + SHATYPE shatype; + char rest_api_separator; + vint stale_nonce; + vint mobility; + turn_credential_type ct; + int use_auth_secret_with_timestamp; + band_limit_t max_bps; + vint total_quota; + vint user_quota; + +/////// Users DB /////////// + + default_users_db_t default_users_db; + +} turn_params_t; + +extern turn_params_t turn_params; + +//////////////// Listener server ///////////////// + +static inline int get_alt_listener_port(void) { + if(turn_params.alt_listener_port<1) + return turn_params.listener_port + 1; + return turn_params.alt_listener_port; +} + +static inline int get_alt_tls_listener_port(void) { + if(turn_params.alt_tls_listener_port<1) + return turn_params.tls_listener_port + 1; + return turn_params.alt_tls_listener_port; +} + +void add_aux_server(const char *saddr); + +void add_alternate_server(const char *saddr); +void del_alternate_server(const char *saddr); +void add_tls_alternate_server(const char *saddr); +void del_tls_alternate_server(const char *saddr); + +////////// Addrs //////////////////// + +void add_listener_addr(const char* addr); +int add_relay_addr(const char* addr); + +///////// Auth //////////////// + +void send_auth_message_to_auth_server(struct auth_message *am); + +/////////// Setup server //////// + +void init_listener(void); +void setup_server(void); +void run_listener_server(struct listener_server *ls); + +/////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__MAIN_RELAY__ diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c new file mode 100644 index 00000000..326adaca --- /dev/null +++ b/src/apps/relay/netengine.c @@ -0,0 +1,1573 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "mainrelay.h" + +//////////// Barrier for the threads ////////////// + +#if !defined(TURN_NO_THREAD_BARRIERS) +static unsigned int barrier_count = 0; +static pthread_barrier_t barrier; +#endif + +////////////////////////////////////////////// + +#define get_real_general_relay_servers_number() (turn_params.general_relay_servers_number > 1 ? turn_params.general_relay_servers_number : 1) +#define get_real_udp_relay_servers_number() (turn_params.udp_relay_servers_number > 1 ? turn_params.udp_relay_servers_number : 1) + +static struct relay_server **general_relay_servers = NULL; +static struct relay_server **udp_relay_servers = NULL; + +////////////////////////////////////////////// + +static void run_events(struct event_base *eb, ioa_engine_handle e); +static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int to_set_rfc5780); + +/////////////// BARRIERS /////////////////// + +#if !defined(PTHREAD_BARRIER_SERIAL_THREAD) +#define PTHREAD_BARRIER_SERIAL_THREAD (-1) +#endif + +static void barrier_wait_func(const char* func, int line) +{ +#if !defined(TURN_NO_THREAD_BARRIERS) + int br = 0; + do { + br = pthread_barrier_wait(&barrier); + if ((br < 0)&&(br != PTHREAD_BARRIER_SERIAL_THREAD)) { + int err = errno; + perror("barrier wait"); + printf("%s:%s:%d: %d\n", __FUNCTION__, func,line,err); + } + } while (((br < 0)&&(br != PTHREAD_BARRIER_SERIAL_THREAD)) && (errno == EINTR)); +#else + UNUSED_ARG(func); + UNUSED_ARG(line); + sleep(5); +#endif +} + +#define barrier_wait() barrier_wait_func(__FUNCTION__,__LINE__) + +/////////////// AUX SERVERS //////////////// + +static void add_aux_server_list(const char *saddr, turn_server_addrs_list_t *list) +{ + if(saddr && list) { + ioa_addr addr; + if(make_ioa_addr_from_full_string((const u08bits*)saddr, 0, &addr)!=0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong full address format: %s\n",saddr); + } else { + list->addrs = (ioa_addr*)realloc(list->addrs,sizeof(ioa_addr)*(list->size+1)); + addr_cpy(&(list->addrs[(list->size)++]),&addr); + { + u08bits s[1025]; + addr_to_string(&addr, s); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Aux server: %s\n",s); + } + } + } +} + +void add_aux_server(const char *saddr) +{ + add_aux_server_list(saddr,&turn_params.aux_servers_list); +} + +/////////////// ALTERNATE SERVERS //////////////// + +static void add_alt_server(const char *saddr, int default_port, turn_server_addrs_list_t *list) +{ + if(saddr && list) { + ioa_addr addr; + + turn_mutex_lock(&(list->m)); + + if(make_ioa_addr_from_full_string((const u08bits*)saddr, default_port, &addr)!=0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong IP address format: %s\n",saddr); + } else { + list->addrs = (ioa_addr*)realloc(list->addrs,sizeof(ioa_addr)*(list->size+1)); + addr_cpy(&(list->addrs[(list->size)++]),&addr); + { + u08bits s[1025]; + addr_to_string(&addr, s); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Alternate server added: %s\n",s); + } + } + + turn_mutex_unlock(&(list->m)); + } +} + +static void del_alt_server(const char *saddr, int default_port, turn_server_addrs_list_t *list) +{ + if(saddr && list && list->size && list->addrs) { + + ioa_addr addr; + + turn_mutex_lock(&(list->m)); + + if(make_ioa_addr_from_full_string((const u08bits*)saddr, default_port, &addr)!=0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong IP address format: %s\n",saddr); + } else { + + size_t i; + int found = 0; + for(i=0;isize;++i) { + if(addr_eq(&(list->addrs[i]),&addr)) { + found = 1; + break; + } + } + + if(found) { + + size_t j; + ioa_addr *new_addrs = (ioa_addr*)malloc(sizeof(ioa_addr)*(list->size-1)); + for(j=0;jaddrs[j])); + } + for(j=i;jsize-1;++j) { + addr_cpy(&(new_addrs[j]),&(list->addrs[j+1])); + } + + free(list->addrs); + list->addrs = new_addrs; + list->size -= 1; + + { + u08bits s[1025]; + addr_to_string(&addr, s); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Alternate server removed: %s\n",s); + } + + del_alt_server(saddr, default_port, list); + } + } + + turn_mutex_unlock(&(list->m)); + } +} + +void add_alternate_server(const char *saddr) +{ + add_alt_server(saddr,DEFAULT_STUN_PORT,&turn_params.alternate_servers_list); +} + +void del_alternate_server(const char *saddr) +{ + del_alt_server(saddr,DEFAULT_STUN_PORT,&turn_params.alternate_servers_list); +} + +void add_tls_alternate_server(const char *saddr) +{ + add_alt_server(saddr,DEFAULT_STUN_TLS_PORT,&turn_params.tls_alternate_servers_list); +} + +void del_tls_alternate_server(const char *saddr) +{ + del_alt_server(saddr,DEFAULT_STUN_TLS_PORT,&turn_params.tls_alternate_servers_list); +} + +////////////////////////////////////////////////// + +void add_listener_addr(const char* addr) { + ioa_addr baddr; + if(make_ioa_addr((const u08bits*)addr,0,&baddr)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot add a listener address: %s\n",addr); + } else { + size_t i = 0; + for(i=0;i=0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, " relay %s initialization...\n",turn_params.relay_addrs[i]); + turnipports_add_ip(STUN_ATTRIBUTE_TRANSPORT_UDP_VALUE, &baddr); + turnipports_add_ip(STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE, &baddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, " relay %s initialization done\n",turn_params.relay_addrs[i]); + } + } + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Relay ports initialization done\n"); +} + +////////////////////////////////////////////////// + +// communications between listener and relays ==>> + +static int handle_relay_message(relay_server_handle rs, struct message_to_relay *sm); + +void send_auth_message_to_auth_server(struct auth_message *am) +{ + struct evbuffer *output = bufferevent_get_output(turn_params.authserver.out_buf); + if(evbuffer_add(output,am,sizeof(struct auth_message))<0) { + fprintf(stderr,"%s: Weird buffer error\n",__FUNCTION__); + } +} + +static void auth_server_receive_message(struct bufferevent *bev, void *ptr) +{ + UNUSED_ARG(ptr); + + struct auth_message am; + int n = 0; + struct evbuffer *input = bufferevent_get_input(bev); + + while ((n = evbuffer_remove(input, &am, sizeof(struct auth_message))) > 0) { + if (n != sizeof(struct auth_message)) { + fprintf(stderr,"%s: Weird buffer error: size=%d\n",__FUNCTION__,n); + continue; + } + + if(am.ct == TURN_CREDENTIALS_SHORT_TERM) { + st_password_t pwd; + 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.username,am.realm,key,am.in_buffer.nbh)<0) { + am.success = 0; + } else { + ns_bcopy(key,am.key,sizeof(hmackey_t)); + am.success = 1; + } + } + + size_t dest = am.id; + + struct evbuffer *output = NULL; + + if(dest>=TURNSERVER_ID_BOUNDARY_BETWEEN_TCP_AND_UDP) { + dest -= TURNSERVER_ID_BOUNDARY_BETWEEN_TCP_AND_UDP; + if(dest >= get_real_udp_relay_servers_number()) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Too large UDP relay number: %d\n", + __FUNCTION__,(int)dest); + } else { + output = bufferevent_get_output(udp_relay_servers[dest]->auth_out_buf); + } + } else { + if(dest >= get_real_general_relay_servers_number()) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Too large general relay number: %d\n", + __FUNCTION__,(int)dest); + } else { + output = bufferevent_get_output(general_relay_servers[dest]->auth_out_buf); + } + } + + if(output) + evbuffer_add(output,&am,sizeof(struct auth_message)); + else { + ioa_network_buffer_delete(NULL, am.in_buffer.nbh); + am.in_buffer.nbh = NULL; + } + } +} + +static int send_socket_to_general_relay(ioa_engine_handle e, struct message_to_relay *sm) +{ + struct relay_server *rdest = sm->relay_server; + + if(!rdest) { + size_t dest = (hash_int32(addr_get_port(&(sm->m.sm.nd.src_addr)))) % get_real_general_relay_servers_number(); + rdest = general_relay_servers[dest]; + } + + struct message_to_relay *smptr = sm; + + smptr->t = RMT_SOCKET; + + { + struct evbuffer *output = NULL; + int success = 0; + + output = bufferevent_get_output(rdest->out_buf); + + if(output) { + + if(evbuffer_add(output,smptr,sizeof(struct message_to_relay))<0) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Cannot add message to relay output buffer\n", + __FUNCTION__); + } else { + + success = 1; + smptr->m.sm.nd.nbh=NULL; + } + + } + + if(!success) { + ioa_network_buffer_delete(e, smptr->m.sm.nd.nbh); + smptr->m.sm.nd.nbh=NULL; + + IOA_CLOSE_SOCKET(smptr->m.sm.s); + + return -1; + } + } + + return 0; +} + +static int send_socket_to_relay(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 ret = 0; + + struct message_to_relay sm; + ns_bzero(&sm,sizeof(struct message_to_relay)); + sm.t = rmt; + + struct relay_server *rs = NULL; + if(id>=TURNSERVER_ID_BOUNDARY_BETWEEN_TCP_AND_UDP) { + size_t dest = id-TURNSERVER_ID_BOUNDARY_BETWEEN_TCP_AND_UDP; + if(dest >= get_real_udp_relay_servers_number()) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Too large UDP relay number: %d, rmt=%d\n", + __FUNCTION__,(int)dest,(int)rmt); + ret = -1; + goto err; + } + rs = udp_relay_servers[dest]; + } else { + size_t dest = id; + if(dest >= get_real_general_relay_servers_number()) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Too large general relay number: %d, rmt=%d\n", + __FUNCTION__,(int)dest,(int)rmt); + ret = -1; + goto err; + } + rs = general_relay_servers[dest]; + } + + switch (rmt) { + case(RMT_CB_SOCKET): { + + sm.m.cb_sm.id = id; + sm.m.cb_sm.connection_id = (tcp_connection_id)cid; + stun_tid_cpy(&(sm.m.cb_sm.tid),tid); + sm.m.cb_sm.s = s; + sm.m.cb_sm.message_integrity = message_integrity; + + break; + } + case (RMT_MOBILE_SOCKET): { + + if(nd && nd->nbh) { + sm.m.sm.s = s; + addr_cpy(&(sm.m.sm.nd.src_addr),&(nd->src_addr)); + sm.m.sm.nd.recv_tos = nd->recv_tos; + sm.m.sm.nd.recv_ttl = nd->recv_ttl; + sm.m.sm.nd.nbh = nd->nbh; + nd->nbh = NULL; + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Empty buffer with mobile socket\n",__FUNCTION__); + ret = -1; + } + + break; + } + default: { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: UNKNOWN RMT message: %d\n",__FUNCTION__,(int)rmt); + ret = -1; + } + } + + if(ret == 0) { + + struct evbuffer *output = bufferevent_get_output(rs->out_buf); + if(output) { + evbuffer_add(output,&sm,sizeof(struct message_to_relay)); + } else { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Empty output buffer\n", + __FUNCTION__); + ret = -1; + } + } + + err: + if(ret < 0) { + IOA_CLOSE_SOCKET(s); + if(nd) { + ioa_network_buffer_delete(NULL, nd->nbh); + nd->nbh = NULL; + } + if(rmt == RMT_MOBILE_SOCKET) { + ioa_network_buffer_delete(NULL, sm.m.sm.nd.nbh); + sm.m.sm.nd.nbh = NULL; + } + } + + return ret; +} + +static int handle_relay_message(relay_server_handle rs, struct message_to_relay *sm) +{ + if(rs && sm) { + + switch (sm->t) { + + case RMT_SOCKET: { + + if (sm->m.sm.s->defer_nbh) { + if (!sm->m.sm.nd.nbh) { + sm->m.sm.nd.nbh = sm->m.sm.s->defer_nbh; + sm->m.sm.s->defer_nbh = NULL; + } else { + ioa_network_buffer_delete(rs->ioa_eng, sm->m.sm.s->defer_nbh); + sm->m.sm.s->defer_nbh = NULL; + } + } + + ioa_socket_handle s = sm->m.sm.s; + + if (!s) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: socket EMPTY\n",__FUNCTION__); + } else if (s->read_event || s->bev) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: socket wrongly preset: 0x%lx : 0x%lx\n", + __FUNCTION__, (long) s->read_event, (long) s->bev); + IOA_CLOSE_SOCKET(s); + } else { + s->e = rs->ioa_eng; + open_client_connection_session(&(rs->server), &(sm->m.sm)); + } + + ioa_network_buffer_delete(rs->ioa_eng, sm->m.sm.nd.nbh); + sm->m.sm.nd.nbh = NULL; + } + break; + case RMT_CB_SOCKET: + + turnserver_accept_tcp_client_data_connection(&(rs->server), sm->m.cb_sm.connection_id, + &(sm->m.cb_sm.tid), sm->m.cb_sm.s, sm->m.cb_sm.message_integrity); + + break; + case RMT_MOBILE_SOCKET: { + + ioa_socket_handle s = sm->m.sm.s; + + if (!s) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: mobile socket EMPTY\n",__FUNCTION__); + } else if (s->read_event || s->bev) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: mobile socket wrongly preset: 0x%lx : 0x%lx\n", + __FUNCTION__, (long) s->read_event, (long) s->bev); + IOA_CLOSE_SOCKET(s); + } else { + s->e = rs->ioa_eng; + open_client_connection_session(&(rs->server), &(sm->m.sm)); + } + + ioa_network_buffer_delete(rs->ioa_eng, sm->m.sm.nd.nbh); + sm->m.sm.nd.nbh = NULL; + break; + } + default: { + perror("Weird buffer type\n"); + } + } + } + + return 0; +} + +static void handle_relay_auth_message(struct relay_server *rs, struct auth_message *am) +{ + am->resume_func(am->success, am->key, am->pwd, + &(rs->server), am->ctxkey, &(am->in_buffer)); + if (am->in_buffer.nbh) { + ioa_network_buffer_delete(rs->ioa_eng, am->in_buffer.nbh); + am->in_buffer.nbh = NULL; + } +} + +static void relay_receive_message(struct bufferevent *bev, void *ptr) +{ + struct message_to_relay sm; + int n = 0; + struct evbuffer *input = bufferevent_get_input(bev); + struct relay_server *rs = (struct relay_server *)ptr; + + while ((n = evbuffer_remove(input, &sm, sizeof(struct message_to_relay))) > 0) { + + if (n != sizeof(struct message_to_relay)) { + perror("Weird buffer error\n"); + continue; + } + + handle_relay_message(rs, &sm); + } +} + +static void relay_receive_auth_message(struct bufferevent *bev, void *ptr) +{ + struct auth_message am; + int n = 0; + struct evbuffer *input = bufferevent_get_input(bev); + struct relay_server *rs = (struct relay_server *)ptr; + + while ((n = evbuffer_remove(input, &am, sizeof(struct auth_message))) > 0) { + + if (n != sizeof(struct auth_message)) { + perror("Weird auth_buffer error\n"); + continue; + } + + handle_relay_auth_message(rs, &am); + } +} + +static int send_message_from_listener_to_client(ioa_engine_handle e, ioa_network_buffer_handle nbh, ioa_addr *origin, ioa_addr *destination) +{ + + struct message_to_listener mm; + mm.t = LMT_TO_CLIENT; + addr_cpy(&(mm.m.tc.origin),origin); + addr_cpy(&(mm.m.tc.destination),destination); + mm.m.tc.nbh = ioa_network_buffer_allocate(e); + ioa_network_buffer_header_init(mm.m.tc.nbh); + ns_bcopy(ioa_network_buffer_data(nbh),ioa_network_buffer_data(mm.m.tc.nbh),ioa_network_buffer_get_size(nbh)); + ioa_network_buffer_set_size(mm.m.tc.nbh,ioa_network_buffer_get_size(nbh)); + + struct evbuffer *output = bufferevent_get_output(turn_params.listener.out_buf); + + evbuffer_add(output,&mm,sizeof(struct message_to_listener)); + + return 0; +} + +static void listener_receive_message(struct bufferevent *bev, void *ptr) +{ + UNUSED_ARG(ptr); + + struct message_to_listener mm; + int n = 0; + struct evbuffer *input = bufferevent_get_input(bev); + + while ((n = evbuffer_remove(input, &mm, sizeof(struct message_to_listener))) > 0) { + if (n != sizeof(struct message_to_listener)) { + perror("Weird buffer error\n"); + continue; + } + + if (mm.t != LMT_TO_CLIENT) { + perror("Weird buffer type\n"); + continue; + } + + size_t relay_thread_index = 0; + + if(turn_params.net_engine_version == NEV_UDP_SOCKET_PER_THREAD) { + size_t ri; + for(ri=0;rithr == pthread_self()) { + relay_thread_index=ri; + break; + } + } + } + + size_t i; + int found = 0; + for(i=0;i1) { + + /* UDP: */ + if(!turn_params.no_udp) { + + barrier_count += turn_params.listener.addrs_number; + + if(turn_params.rfc5780) { + barrier_count += turn_params.listener.addrs_number; + } + } + + if(!turn_params.no_dtls && (turn_params.no_udp || (turn_params.listener_port != turn_params.tls_listener_port))) { + + barrier_count += turn_params.listener.addrs_number; + + if(turn_params.rfc5780) { + barrier_count += turn_params.listener.addrs_number; + } + } + + if(!turn_params.no_udp || !turn_params.no_dtls) { + barrier_count += (unsigned int)turn_params.aux_servers_list.size; + } + } +#endif + +#if !defined(TURN_NO_THREAD_BARRIERS) + { + if(pthread_barrier_init(&barrier,NULL,barrier_count)<0) + perror("barrier init"); + } + +#endif +} + +static void setup_socket_per_endpoint_udp_listener_servers(void) +{ + size_t i = 0; + + /* Adjust udp relay number */ + + if(turn_params.general_relay_servers_number>1) { + + if (!turn_params.no_udp) { + + turn_params.udp_relay_servers_number += turn_params.listener.addrs_number; + + if (turn_params.rfc5780) { + turn_params.udp_relay_servers_number += turn_params.listener.addrs_number; + } + } + + if (!turn_params.no_dtls && (turn_params.no_udp || (turn_params.listener_port != turn_params.tls_listener_port))) { + + turn_params.udp_relay_servers_number += turn_params.listener.addrs_number; + + if (turn_params.rfc5780) { + turn_params.udp_relay_servers_number += turn_params.listener.addrs_number; + } + } + + if (!turn_params.no_udp || !turn_params.no_dtls) { + turn_params.udp_relay_servers_number += (unsigned int) turn_params.aux_servers_list.size; + } + } + + { + if (!turn_params.no_udp || !turn_params.no_dtls) { + udp_relay_servers = (struct relay_server**) allocate_super_memory_engine(turn_params.listener.ioa_eng, sizeof(struct relay_server *)*get_real_udp_relay_servers_number()); + + for (i = 0; i < get_real_udp_relay_servers_number(); i++) { + + ioa_engine_handle e = turn_params.listener.ioa_eng; + int is_5780 = turn_params.rfc5780; + + if(turn_params.general_relay_servers_number<=1) { + while(!(general_relay_servers[0]->ioa_eng)) + sched_yield(); + udp_relay_servers[i] = general_relay_servers[0]; + continue; + } else if(turn_params.general_relay_servers_number>1) { + e = create_new_listener_engine(); + is_5780 = is_5780 && (i >= (size_t) (turn_params.aux_servers_list.size)); + } + + super_memory_t *sm = new_super_memory_region(); + struct relay_server* udp_rs = (struct relay_server*) allocate_super_memory_region(sm, sizeof(struct relay_server)); + udp_rs->id = (turnserver_id) i + TURNSERVER_ID_BOUNDARY_BETWEEN_TCP_AND_UDP; + udp_rs->sm = sm; + setup_relay_server(udp_rs, e, is_5780); + udp_relay_servers[i] = udp_rs; + } + } + } + + int udp_relay_server_index = 0; + + /* Create listeners */ + + /* Aux UDP servers */ + for(i=0; iioa_eng, sizeof(dtls_listener_relay_server_type*)); + turn_params.listener.aux_udp_services[index][0] = create_dtls_listener_server(turn_params.listener_ifname, saddr, port, turn_params.verbose, udp_relay_servers[udp_relay_server_index]->ioa_eng, &(udp_relay_servers[udp_relay_server_index]->server), 1, NULL); + + if(turn_params.general_relay_servers_number>1) { + ++udp_relay_server_index; + pthread_t thr; + if(pthread_create(&thr, NULL, run_udp_listener_thread, turn_params.listener.aux_udp_services[index][0])<0) { + perror("Cannot create aux listener thread\n"); + exit(-1); + } + pthread_detach(thr); + } + } + } + + /* Main servers */ + for(i=0; iioa_eng, sizeof(dtls_listener_relay_server_type*)); + turn_params.listener.udp_services[index][0] = create_dtls_listener_server(turn_params.listener_ifname, turn_params.listener.addrs[i], turn_params.listener_port, turn_params.verbose, udp_relay_servers[udp_relay_server_index]->ioa_eng, &(udp_relay_servers[udp_relay_server_index]->server), 1, NULL); + + if(turn_params.general_relay_servers_number>1) { + ++udp_relay_server_index; + pthread_t thr; + if(pthread_create(&thr, NULL, run_udp_listener_thread, turn_params.listener.udp_services[index][0])<0) { + perror("Cannot create listener thread\n"); + exit(-1); + } + pthread_detach(thr); + } + + if(turn_params.rfc5780) { + + turn_params.listener.udp_services[index+1] = (dtls_listener_relay_server_type**)allocate_super_memory_engine(udp_relay_servers[udp_relay_server_index]->ioa_eng, sizeof(dtls_listener_relay_server_type*)); + turn_params.listener.udp_services[index+1][0] = create_dtls_listener_server(turn_params.listener_ifname, turn_params.listener.addrs[i], get_alt_listener_port(), turn_params.verbose, udp_relay_servers[udp_relay_server_index]->ioa_eng, &(udp_relay_servers[udp_relay_server_index]->server), 1, NULL); + + if(turn_params.general_relay_servers_number>1) { + ++udp_relay_server_index; + pthread_t thr; + if(pthread_create(&thr, NULL, run_udp_listener_thread, turn_params.listener.udp_services[index+1][0])<0) { + perror("Cannot create listener thread\n"); + exit(-1); + } + pthread_detach(thr); + } + } + } else { + turn_params.listener.udp_services[index] = NULL; + if(turn_params.rfc5780) + turn_params.listener.udp_services[index+1] = NULL; + } + if(!turn_params.no_dtls && (turn_params.no_udp || (turn_params.listener_port != turn_params.tls_listener_port))) { + + turn_params.listener.dtls_services[index] = (dtls_listener_relay_server_type**)allocate_super_memory_engine(udp_relay_servers[udp_relay_server_index]->ioa_eng, sizeof(dtls_listener_relay_server_type*)); + turn_params.listener.dtls_services[index][0] = create_dtls_listener_server(turn_params.listener_ifname, turn_params.listener.addrs[i], turn_params.tls_listener_port, turn_params.verbose, udp_relay_servers[udp_relay_server_index]->ioa_eng, &(udp_relay_servers[udp_relay_server_index]->server), 1, NULL); + + if(turn_params.general_relay_servers_number>1) { + ++udp_relay_server_index; + pthread_t thr; + if(pthread_create(&thr, NULL, run_udp_listener_thread, turn_params.listener.dtls_services[index][0])<0) { + perror("Cannot create listener thread\n"); + exit(-1); + } + pthread_detach(thr); + } + + if(turn_params.rfc5780) { + + turn_params.listener.dtls_services[index+1] = (dtls_listener_relay_server_type**)allocate_super_memory_engine(udp_relay_servers[udp_relay_server_index]->ioa_eng, sizeof(dtls_listener_relay_server_type*)); + turn_params.listener.dtls_services[index+1][0] = create_dtls_listener_server(turn_params.listener_ifname, turn_params.listener.addrs[i], get_alt_tls_listener_port(), turn_params.verbose, udp_relay_servers[udp_relay_server_index]->ioa_eng, &(udp_relay_servers[udp_relay_server_index]->server), 1, NULL); + + if(turn_params.general_relay_servers_number>1) { + ++udp_relay_server_index; + pthread_t thr; + if(pthread_create(&thr, NULL, run_udp_listener_thread, turn_params.listener.dtls_services[index+1][0])<0) { + perror("Cannot create listener thread\n"); + exit(-1); + } + pthread_detach(thr); + } + } + } else { + turn_params.listener.dtls_services[index] = NULL; + if(turn_params.rfc5780) + turn_params.listener.dtls_services[index+1] = NULL; + } + } +} + +static void setup_socket_per_thread_udp_listener_servers(void) +{ + size_t i = 0; + size_t relayindex = 0; + + /* Create listeners */ + + for(relayindex=0;relayindexioa_eng) || !(general_relay_servers[relayindex]->server.e)) + sched_yield(); + } + + /* Aux UDP servers */ + for(i=0; iioa_eng, &(general_relay_servers[relayindex]->server), !relayindex, NULL); + } + } + } + + /* Main servers */ + for(i=0; iioa_eng, &(general_relay_servers[relayindex]->server), !relayindex, NULL); + } + + if(turn_params.rfc5780) { + + turn_params.listener.udp_services[index+1] = (dtls_listener_relay_server_type**)allocate_super_memory_engine(turn_params.listener.ioa_eng, sizeof(dtls_listener_relay_server_type*) * get_real_general_relay_servers_number()); + + for(relayindex=0;relayindexioa_eng, &(general_relay_servers[relayindex]->server), !relayindex, NULL); + } + } + } else { + turn_params.listener.udp_services[index] = NULL; + if(turn_params.rfc5780) + turn_params.listener.udp_services[index+1] = NULL; + } + if(!turn_params.no_dtls && (turn_params.no_udp || (turn_params.listener_port != turn_params.tls_listener_port))) { + + turn_params.listener.dtls_services[index] = (dtls_listener_relay_server_type**)allocate_super_memory_engine(turn_params.listener.ioa_eng, sizeof(dtls_listener_relay_server_type*) * get_real_general_relay_servers_number()); + + for(relayindex=0;relayindexioa_eng, &(general_relay_servers[relayindex]->server), !relayindex, NULL); + } + + if(turn_params.rfc5780) { + + turn_params.listener.dtls_services[index+1] = (dtls_listener_relay_server_type**)allocate_super_memory_engine(turn_params.listener.ioa_eng, sizeof(dtls_listener_relay_server_type*) * get_real_general_relay_servers_number()); + + for(relayindex=0;relayindexioa_eng, &(general_relay_servers[relayindex]->server), !relayindex, NULL); + } + } + } else { + turn_params.listener.dtls_services[index] = NULL; + if(turn_params.rfc5780) + turn_params.listener.dtls_services[index+1] = NULL; + } + } +} + +static void setup_socket_per_session_udp_listener_servers(void) +{ + size_t i = 0; + + /* Aux UDP servers */ + for(i=0; iss.sa_family == turn_params.listener.encaddrs[i]->ss.sa_family) { + index=i; + break; + } + } + } + if(index!=0xffff) { + for(i=0;iss.sa_family == addr->ss.sa_family) { + addr_cpy(alt_addr,caddr); + addr_set_port(alt_addr, alt_port); + return 0; + } + } + } + } + } + + return -1; +} + +static void run_events(struct event_base *eb, ioa_engine_handle e) +{ + if(!eb && e) + eb = e->event_base; + + if (!eb) + return; + + struct timeval timeout; + + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + event_base_loopexit(eb, &timeout); + + event_base_dispatch(eb); + + +#if !defined(TURN_NO_HIREDIS) + if(e) + send_message_to_redis(e->rch, "publish", "__XXX__", "__YYY__"); +#endif +} + +void run_listener_server(struct listener_server *ls) +{ + unsigned int cycle = 0; + while (!turn_params.stop_turn_server) { + + if (eve(turn_params.verbose)) { + if ((cycle++ & 15) == 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cycle=%u\n", __FUNCTION__, cycle); + } + } + + run_events(ls->event_base, ls->ioa_eng); + + rollover_logfile(); + } +} + +static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int to_set_rfc5780) +{ + struct bufferevent *pair[2]; + int opts = BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS; + + if(e) { + rs->event_base = e->event_base; + rs->ioa_eng = e; + } else { + rs->event_base = turn_event_base_new(); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (general relay thread): %s\n",event_base_get_method(rs->event_base)); + rs->ioa_eng = create_ioa_engine(rs->sm, rs->event_base, turn_params.listener.tp, turn_params.relay_ifname, + turn_params.relays_number, turn_params.relay_addrs, turn_params.default_relays, turn_params.verbose, turn_params.max_bps +#if !defined(TURN_NO_HIREDIS) + ,turn_params.redis_statsdb +#endif + ); + set_ssl_ctx(rs->ioa_eng, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0, +#if defined(SSL_TXT_TLSV1_1) + turn_params.tls_ctx_v1_1, +#if defined(SSL_TXT_TLSV1_2) + turn_params.tls_ctx_v1_2, +#endif +#endif + turn_params.dtls_ctx); + ioa_engine_set_rtcp_map(rs->ioa_eng, turn_params.listener.rtcpmap); + } + + opts |= BEV_OPT_THREADSAFE; + + bufferevent_pair_new(rs->event_base, opts, pair); + rs->in_buf = pair[0]; + rs->out_buf = pair[1]; + bufferevent_setcb(rs->in_buf, relay_receive_message, NULL, NULL, rs); + bufferevent_enable(rs->in_buf, EV_READ); + + bufferevent_pair_new(rs->event_base, opts, pair); + rs->auth_in_buf = pair[0]; + rs->auth_out_buf = pair[1]; + bufferevent_setcb(rs->auth_in_buf, relay_receive_auth_message, NULL, NULL, rs); + bufferevent_enable(rs->auth_in_buf, EV_READ); + + init_turn_server(&(rs->server), + rs->id, turn_params.verbose, + rs->ioa_eng, turn_params.ct, 0, + turn_params.fingerprint, DONT_FRAGMENT_SUPPORTED, + start_user_check, + check_new_allocation_quota, + release_allocation_quota, + turn_params.external_ip, + &turn_params.no_tcp_relay, + &turn_params.no_udp_relay, + &turn_params.stale_nonce, + &turn_params.stun_only, + &turn_params.no_stun, + &turn_params.alternate_servers_list, + &turn_params.tls_alternate_servers_list, + &turn_params.aux_servers_list, + turn_params.udp_self_balance, + &turn_params.no_multicast_peers, &turn_params.no_loopback_peers, + &turn_params.ip_whitelist, &turn_params.ip_blacklist, + send_socket_to_relay, + &turn_params.secure_stun, turn_params.shatype, &turn_params.mobility, + turn_params.server_relay, + send_turn_session_info); + + if(to_set_rfc5780) { + set_rfc5780(&(rs->server), get_alt_addr, send_message_from_listener_to_client); + } + + if(turn_params.net_engine_version == NEV_UDP_SOCKET_PER_THREAD) { + setup_tcp_listener_servers(rs->ioa_eng, rs); + } +} + +static void *run_general_relay_thread(void *arg) +{ + static int always_true = 1; + struct relay_server *rs = (struct relay_server *)arg; + + int udp_reuses_the_same_relay_server = (turn_params.general_relay_servers_number<=1) || (turn_params.net_engine_version == NEV_UDP_SOCKET_PER_THREAD) || (turn_params.net_engine_version == NEV_UDP_SOCKET_PER_SESSION); + + int we_need_rfc5780 = udp_reuses_the_same_relay_server && turn_params.rfc5780; + + ignore_sigpipe(); + + setup_relay_server(rs, NULL, we_need_rfc5780); + + barrier_wait(); + + while(always_true) { + run_events(rs->event_base, rs->ioa_eng); + } + + return arg; +} + +static void setup_general_relay_servers(void) +{ + size_t i = 0; + + general_relay_servers = (struct relay_server**)allocate_super_memory_engine(turn_params.listener.ioa_eng, sizeof(struct relay_server *)*get_real_general_relay_servers_number()); + + for(i=0;iid = (turnserver_id)i; + general_relay_servers[i]->sm = NULL; + setup_relay_server(general_relay_servers[i], turn_params.listener.ioa_eng, ((turn_params.net_engine_version == NEV_UDP_SOCKET_PER_THREAD) || (turn_params.net_engine_version == NEV_UDP_SOCKET_PER_SESSION)) && turn_params.rfc5780); + general_relay_servers[i]->thr = pthread_self(); + } else { + super_memory_t *sm = new_super_memory_region(); + general_relay_servers[i] = (struct relay_server*)allocate_super_memory_region(sm,sizeof(struct relay_server)); + general_relay_servers[i]->id = (turnserver_id)i; + general_relay_servers[i]->sm = sm; + if(pthread_create(&(general_relay_servers[i]->thr), NULL, run_general_relay_thread, general_relay_servers[i])<0) { + perror("Cannot create relay thread\n"); + exit(-1); + } + pthread_detach(general_relay_servers[i]->thr); + } + } +} + +static int run_auth_server_flag = 1; + +static void* run_auth_server_thread(void *arg) +{ + ignore_sigpipe(); + + ns_bzero(&turn_params.authserver,sizeof(struct auth_server)); + + turn_params.authserver.event_base = turn_event_base_new(); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (auth thread): %s\n",event_base_get_method(turn_params.authserver.event_base)); + + struct bufferevent *pair[2]; + int opts = BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS; + + opts |= BEV_OPT_THREADSAFE; + + bufferevent_pair_new(turn_params.authserver.event_base, opts, pair); + turn_params.authserver.in_buf = pair[0]; + turn_params.authserver.out_buf = pair[1]; + bufferevent_setcb(turn_params.authserver.in_buf, auth_server_receive_message, NULL, NULL, &turn_params.authserver); + bufferevent_enable(turn_params.authserver.in_buf, EV_READ); + +#if !defined(TURN_NO_HIREDIS) + turn_params.authserver.rch = get_redis_async_connection(turn_params.authserver.event_base, turn_params.redis_statsdb, 1); +#endif + + struct auth_server *authserver = &turn_params.authserver; + struct event_base *eb = authserver->event_base; + + barrier_wait(); + + while(run_auth_server_flag) { + reread_realms(); + run_events(eb,NULL); + read_userdb_file(0); + update_white_and_black_lists(); + auth_ping( +#if !defined(TURN_NO_HIREDIS) + authserver->rch +#endif + ); + } + + return arg; +} + +static void setup_auth_server(void) +{ + if(pthread_create(&(turn_params.authserver.thr), NULL, run_auth_server_thread, NULL)<0) { + perror("Cannot create auth thread\n"); + exit(-1); + } + pthread_detach(turn_params.authserver.thr); +} + +static void* run_cli_server_thread(void *arg) +{ + ignore_sigpipe(); + + setup_cli_thread(); + + barrier_wait(); + + while(cliserver.event_base) { + run_events(cliserver.event_base,NULL); + } + + return arg; +} + +static void setup_cli_server(void) +{ + ns_bzero(&cliserver,sizeof(struct cli_server)); + cliserver.listen_fd = -1; + cliserver.verbose = turn_params.verbose; + + if(pthread_create(&(cliserver.thr), NULL, run_cli_server_thread, &cliserver)<0) { + perror("Cannot create cli thread\n"); + exit(-1); + } + + pthread_detach(cliserver.thr); +} + +void setup_server(void) +{ + evthread_use_pthreads(); + +#if !defined(TURN_NO_THREAD_BARRIERS) + + /* relay threads plus auth thread plus main listener thread */ + /* udp address listener thread(s) will start later */ + barrier_count = turn_params.general_relay_servers_number+2; + + if(use_cli) { + barrier_count += 1; + } + +#endif + + setup_listener(); + allocate_relay_addrs_ports(); + setup_barriers(); + setup_general_relay_servers(); + + if(turn_params.net_engine_version == NEV_UDP_SOCKET_PER_THREAD) + setup_socket_per_thread_udp_listener_servers(); + else if(turn_params.net_engine_version == NEV_UDP_SOCKET_PER_ENDPOINT) + setup_socket_per_endpoint_udp_listener_servers(); + else if(turn_params.net_engine_version == NEV_UDP_SOCKET_PER_SESSION) + setup_socket_per_session_udp_listener_servers(); + + if(turn_params.net_engine_version != NEV_UDP_SOCKET_PER_THREAD) { + setup_tcp_listener_servers(turn_params.listener.ioa_eng, NULL); + } + + setup_auth_server(); + if(use_cli) + setup_cli_server(); + + barrier_wait(); +} + +void init_listener(void) +{ + ns_bzero(&turn_params.listener,sizeof(struct listener_server)); +} + +/////////////////////////////// diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c new file mode 100644 index 00000000..5afe397f --- /dev/null +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -0,0 +1,3654 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "ns_turn_utils.h" +#include "ns_turn_session.h" +#include "ns_turn_server.h" +#include "ns_turn_khash.h" + +#include "stun_buffer.h" +#include "apputils.h" + +#include "ns_ioalib_impl.h" + +#if !defined(TURN_NO_TLS) +#include +#endif + +#include + +#include + +#if !defined(TURN_NO_HIREDIS) +#include "hiredis_libevent2.h" +#endif + +/* Compilation test: +#if defined(IP_RECVTTL) +#undef IP_RECVTTL +#endif +#if defined(IPV6_RECVHOPLIMIT) +#undef IPV6_RECVHOPLIMIT +#endif +#if defined(IP_RECVTOS) +#undef IP_RECVTOS +#endif +#if defined(IPV6_RECVTCLASS) +#undef IPV6_RECVTCLASS +#endif +*/ + +#define MAX_ERRORS_IN_UDP_BATCH (1024) + +struct turn_sock_extended_err { + uint32_t ee_errno; /* error number */ + uint8_t ee_origin; /* where the error originated */ + uint8_t ee_type; /* type */ + uint8_t ee_code; /* code */ + uint8_t ee_pad; /* padding */ + uint32_t ee_info; /* additional information */ + uint32_t ee_data; /* other data */ +/* More data may follow */ +}; + +#define TRIAL_EFFORTS_TO_SEND (2) + +const int predef_timer_intervals[PREDEF_TIMERS_NUM] = {30,60,90,120,240,300,360,540,600,700,800,900,1800,3600}; + +/************** Forward function declarations ******/ + +static int socket_readerr(evutil_socket_t fd, ioa_addr *orig_addr); + +static void socket_input_handler(evutil_socket_t fd, short what, void* arg); +static void socket_output_handler_bev(struct bufferevent *bev, void* arg); +static void socket_input_handler_bev(struct bufferevent *bev, void* arg); +static void eventcb_bev(struct bufferevent *bev, short events, void *arg); + +static int send_ssl_backlog_buffers(ioa_socket_handle s); + +static int set_accept_cb(ioa_socket_handle s, accept_cb acb, void *arg); + +static void close_socket_net_data(ioa_socket_handle s); + +/************** Utils **************************/ + +static const int tcp_congestion_control = 1; +static const int udp_congestion_control = 1; + +static int bufferevent_enabled(struct bufferevent *bufev, short flags) +{ + return (bufferevent_get_enabled(bufev) & flags); +} + +static int is_socket_writeable(ioa_socket_handle s, size_t sz, const char *msg, int option) +{ + UNUSED_ARG(s); + UNUSED_ARG(sz); + UNUSED_ARG(msg); + UNUSED_ARG(option); + + if(!(s->done) && !(s->broken) && !(s->tobeclosed)) { + + switch(s->st) { + + case TCP_SOCKET: + case TLS_SOCKET: + if(s->bev) { + + struct evbuffer *evb = bufferevent_get_output(s->bev); + + if(evb) { + size_t bufsz = evbuffer_get_length(evb); + size_t newsz = bufsz + sz; + + switch(s->sat) { + case TCP_CLIENT_DATA_SOCKET: + case TCP_RELAY_DATA_SOCKET: + + switch(option) { + case 0: + case 1: + if(newsz >= BUFFEREVENT_MAX_TCP_TO_TCP_WRITE) { + return 0; + } + break; + case 3: + case 4: + if(newsz >= BUFFEREVENT_MAX_TCP_TO_TCP_WRITE) { + return 0; + } + break; + default: + return 1; + }; + break; + default: + if(option == 2) { + if(newsz >= BUFFEREVENT_MAX_UDP_TO_TCP_WRITE) { + return 0; + } + } + }; + } + } + break; + default: + ; + }; + } + + return 1; +} + +static void log_socket_event(ioa_socket_handle s, const char *msg, int error) { + if(s && (error || (s->e && s->e->verbose))) { + if(!msg) + msg = "General socket event"; + turnsession_id id = 0; + { + ts_ur_super_session *ss = s->session; + if (ss) { + id = ss->id; + } else{ + return; + } + } + + TURN_LOG_LEVEL ll = TURN_LOG_LEVEL_INFO; + if(error) + ll = TURN_LOG_LEVEL_ERROR; + + { + char sraddr[129]="\0"; + char sladdr[129]="\0"; + addr_to_string(&(s->remote_addr),(u08bits*)sraddr); + addr_to_string(&(s->local_addr),(u08bits*)sladdr); + + if(EVUTIL_SOCKET_ERROR()) { + TURN_LOG_FUNC(ll,"session %018llu: %s: %s (local %s, remote %s)\n",(unsigned long long)id, + msg, evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()), + sladdr,sraddr); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: %s (local %s, remote %s)\n", + (unsigned long long)id,msg,sladdr,sraddr); + } + } + } +} + +int set_df_on_ioa_socket(ioa_socket_handle s, int value) +{ + if(!s) + return 0; + + if(s->parent_s) + return 0; + + if (s->do_not_use_df) + value = 0; + + if (s->current_df_relay_flag != value) { + s->current_df_relay_flag = value; + return set_socket_df(s->fd, s->family, value); + } + + return 0; +} + +void set_do_not_use_df(ioa_socket_handle s) +{ + if(s->parent_s) + return; + + s->do_not_use_df = 1; + s->current_df_relay_flag = 1; + set_socket_df(s->fd, s->family, 0); +} + +/************** Buffer List ********************/ + +static int buffer_list_empty(stun_buffer_list *bufs) +{ + if(bufs && bufs->head && bufs->tsz) + return 0; + return 1; +} + +static stun_buffer_list_elem *get_elem_from_buffer_list(stun_buffer_list *bufs) +{ + stun_buffer_list_elem *ret = NULL; + + if(bufs && bufs->head && bufs->tsz) { + + ret=bufs->head; + bufs->head=ret->next; + --bufs->tsz; + + ret->next=NULL; + ret->buf.len = 0; + ret->buf.offset = 0; + ret->buf.coffset = 0; + } + + return ret; +} + +static void pop_elem_from_buffer_list(stun_buffer_list *bufs) +{ + if(bufs && bufs->head && bufs->tsz) { + + stun_buffer_list_elem *ret = bufs->head; + bufs->head=ret->next; + --bufs->tsz; + turn_free(ret,sizeof(stun_buffer_list_elem)); + } +} + + + +static stun_buffer_list_elem *new_blist_elem(ioa_engine_handle e) +{ + stun_buffer_list_elem *ret = get_elem_from_buffer_list(&(e->bufs)); + + if(!ret) { + ret = (stun_buffer_list_elem *)turn_malloc(sizeof(stun_buffer_list_elem)); + ret->buf.len = 0; + ret->buf.offset = 0; + ret->buf.coffset = 0; + ret->next = NULL; + } + + return ret; +} + +static inline void add_elem_to_buffer_list(stun_buffer_list *bufs, stun_buffer_list_elem *buf_elem) +{ + buf_elem->next = bufs->head; + bufs->head = buf_elem; + bufs->tsz += 1; +} + +static void add_buffer_to_buffer_list(stun_buffer_list *bufs, s08bits *buf, size_t len) +{ + if(bufs && buf && (bufs->tszbuf.buf,len); + buf_elem->buf.len = len; + buf_elem->buf.offset = 0; + buf_elem->buf.coffset = 0; + add_elem_to_buffer_list(bufs,buf_elem); + } +} + +static void free_blist_elem(ioa_engine_handle e, stun_buffer_list_elem *buf_elem) +{ + if(buf_elem) { + if(e && (e->bufs.tszbufs), buf_elem); + } else { + turn_free(buf_elem,sizeof(stun_buffer_list_elem)); + } + } +} + +/************** ENGINE *************************/ + +#define TURN_JIFFIE_SIZE (3) +#define TURN_JIFFIE_LENGTH (1<<(TURN_JIFFIE_SIZE)) + +static void timer_handler(ioa_engine_handle e, void* arg) { + + UNUSED_ARG(arg); + + _log_time_value = turn_time(); + _log_time_value_set = 1; + + e->jiffie = _log_time_value >> TURN_JIFFIE_SIZE; +} + +ioa_engine_handle create_ioa_engine(super_memory_t *sm, + struct event_base *eb, turnipports *tp, const s08bits* relay_ifname, + size_t relays_number, s08bits **relay_addrs, int default_relays, + int verbose, band_limit_t max_bps +#if !defined(TURN_NO_HIREDIS) + ,const char* redis_report_connection_string +#endif + ) +{ + static int capabilities_checked = 0; + + if(!capabilities_checked) { + capabilities_checked = 1; +#if !defined(CMSG_SPACE) + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "On this platform, I am using alternative behavior of TTL/TOS according to RFC 5766.\n"); +#endif +#if !defined(IP_RECVTTL) + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv4: On this platform, I am using alternative behavior of TTL according to RFC 5766.\n"); +#endif +#if !defined(IPV6_RECVHOPLIMIT) + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv6: On this platform, I am using alternative behavior of TTL (HOPLIMIT) according to RFC 6156.\n"); +#endif +#if !defined(IP_RECVTOS) + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv4: On this platform, I am using alternative behavior of TOS according to RFC 5766.\n"); +#endif +#if !defined(IPV6_RECVTCLASS) + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv6: On this platform, I am using alternative behavior of TRAFFIC CLASS according to RFC 6156.\n"); +#endif + } + + if (!relays_number || !relay_addrs || !tp) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot create TURN engine\n", __FUNCTION__); + return NULL; + } else { + ioa_engine_handle e = (ioa_engine_handle)allocate_super_memory_region(sm, sizeof(ioa_engine)); + + e->sm = sm; + e->default_relays = default_relays; + e->max_bpj = max_bps; + e->verbose = verbose; + e->tp = tp; + if (eb) { + e->event_base = eb; + e->deallocate_eb = 0; + } else { + e->event_base = turn_event_base_new(); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (engine own thread): %s\n",event_base_get_method(e->event_base)); + e->deallocate_eb = 1; + } + +#if !defined(TURN_NO_HIREDIS) + if(redis_report_connection_string && *redis_report_connection_string) { + e->rch = get_redis_async_connection(e->event_base, redis_report_connection_string, 0); + } +#endif + + { + int t; + for(t=0;tevent_base, &duration); + if(!ptv) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"FATAL: cannot create preferable timeval for %d secs (%d number)\n",predef_timer_intervals[t],t); + exit(-1); + } else { + ns_bcopy(ptv,&(e->predef_timers[t]),sizeof(struct timeval)); + e->predef_timer_intervals[t] = predef_timer_intervals[t]; + } + } + } + + + if (relay_ifname) + STRCPY(e->relay_ifname, relay_ifname); + { + size_t i = 0; + e->relay_addrs = (ioa_addr*)allocate_super_memory_region(sm, relays_number * sizeof(ioa_addr)+8); + for (i = 0; i < relays_number; i++) { + if(make_ioa_addr((u08bits*) relay_addrs[i], 0, &(e->relay_addrs[i]))<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot add a relay address: %s\n",relay_addrs[i]); + } + } + e->relays_number = relays_number; + } + e->relay_addr_counter = (unsigned short) turn_random(); + timer_handler(e,e); + e->timer_ev = set_ioa_timer(e, 1, 0, timer_handler, e, 1, "timer_handler"); + return e; + } +} + +void set_ssl_ctx(ioa_engine_handle e, + SSL_CTX *tls_ctx_ssl23, + SSL_CTX *tls_ctx_v1_0, +#if defined(SSL_TXT_TLSV1_1) + SSL_CTX *tls_ctx_v1_1, +#if defined(SSL_TXT_TLSV1_2) + SSL_CTX *tls_ctx_v1_2, +#endif +#endif + SSL_CTX *dtls_ctx) +{ + e->tls_ctx_ssl23 = tls_ctx_ssl23; + e->tls_ctx_v1_0 = tls_ctx_v1_0; +#if defined(SSL_TXT_TLSV1_1) + e->tls_ctx_v1_1 = tls_ctx_v1_1; +#if defined(SSL_TXT_TLSV1_2) + e->tls_ctx_v1_2 = tls_ctx_v1_2; +#endif +#endif + e->dtls_ctx = dtls_ctx; +} + +void ioa_engine_set_rtcp_map(ioa_engine_handle e, rtcp_map *rtcpmap) +{ + if(e) + e->map_rtcp = rtcpmap; +} + +static const ioa_addr* ioa_engine_get_relay_addr(ioa_engine_handle e, ioa_socket_handle client_s, + int address_family, int *err_code) +{ + if(e) { + + int family = AF_INET; + if(address_family == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6) + family = AF_INET6; + + + if(e->default_relays) { + + //No relay addrs defined - just return the client address if appropriate: + + ioa_addr *client_addr = get_local_addr_from_ioa_socket(client_s); + if(client_addr) { + switch(address_family) { + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: + if (client_addr->ss.sa_family == AF_INET) + return client_addr; + break; + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: + if (client_addr->ss.sa_family == AF_INET6) + return client_addr; + break; + default: + return client_addr; + }; + } + } + + if (e->relays_number>0) { + + size_t i = 0; + + //Default recommended behavior: + + for(i=0; irelays_number; i++) { + + if(e->relay_addr_counter >= e->relays_number) + e->relay_addr_counter = 0; + ioa_addr *relay_addr = &(e->relay_addrs[e->relay_addr_counter++]); + + if(addr_any_no_port(relay_addr)) + get_a_local_relay(family, relay_addr); + + switch (address_family){ + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT: + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: + if (relay_addr->ss.sa_family == AF_INET) + return relay_addr; + break; + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: + if (relay_addr->ss.sa_family == AF_INET6) + return relay_addr; + break; + default: + ; + }; + } + + if(address_family == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT) { + + //Fallback to "find whatever is available": + + if(e->relay_addr_counter >= e->relays_number) + e->relay_addr_counter = 0; + const ioa_addr *relay_addr = &(e->relay_addrs[e->relay_addr_counter++]); + return relay_addr; + } + + *err_code = 440; + } + } + return NULL; +} + +/******************** Timers ****************************/ + +static void timer_event_handler(evutil_socket_t fd, short what, void* arg) +{ + timer_event* te = (timer_event*)arg; + + if(!te) + return; + + UNUSED_ARG(fd); + + if (!(what & EV_TIMEOUT)) + return; + + if(te->e && eve(te->e->verbose)) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: timeout 0x%lx: %s\n", __FUNCTION__,(long)te, te->txt); + + ioa_timer_event_handler cb = te->cb; + ioa_engine_handle e = te->e; + void *ctx = te->ctx; + + cb(e, ctx); +} + +ioa_timer_handle set_ioa_timer(ioa_engine_handle e, int secs, int ms, ioa_timer_event_handler cb, void* ctx, int persist, const s08bits *txt) +{ + ioa_timer_handle ret = NULL; + + if (e && cb && secs > 0) { + + timer_event * te = (timer_event*) turn_malloc(sizeof(timer_event)); + int flags = EV_TIMEOUT; + if (persist) + flags |= EV_PERSIST; + struct event *ev = event_new(e->event_base, -1, flags, timer_event_handler, te); + struct timeval tv; + + tv.tv_sec = secs; + + te->ctx = ctx; + te->e = e; + te->ev = ev; + te->cb = cb; + te->txt = strdup(txt); + + if(!ms) { + tv.tv_usec = 0; + int found = 0; + int t; + for(t=0;tpredef_timer_intervals[t] == secs) { + evtimer_add(ev,&(e->predef_timers[t])); + found = 1; + break; + } + } + if(!found) { + evtimer_add(ev,&tv); + } + } else { + tv.tv_usec = ms * 1000; + evtimer_add(ev,&tv); + } + + ret = te; + } + + return ret; +} + +void stop_ioa_timer(ioa_timer_handle th) +{ + if (th) { + timer_event *te = (timer_event *)th; + EVENT_DEL(te->ev); + } +} + +void delete_ioa_timer(ioa_timer_handle th) +{ + if (th) { + stop_ioa_timer(th); + timer_event *te = (timer_event *)th; + if(te->txt) { + turn_free(te->txt,strlen(te->txt)+1); + te->txt = NULL; + } + turn_free(th,sizeof(timer_event)); + } +} + +/************** SOCKETS HELPERS ***********************/ + +static int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read) +{ + if(s && (s->e) && sz && (s->sat == CLIENT_SOCKET) && (s->session)) { + + band_limit_t max_bps = s->e->max_bpj; + band_limit_t s_max_bps = s->session->realm_options.perf_options.max_bps; + if(s_max_bps>0) + max_bps = s_max_bps; + + if(max_bps<1) + return 1; + + max_bps = max_bps<jiffie != s->e->jiffie) { + + s->jiffie = s->e->jiffie; + s->jiffie_bytes_read = 0; + s->jiffie_bytes_write = 0; + + if(bsz > max_bps) { + + return 0; + + } else { + if(read) + s->jiffie_bytes_read = bsz; + else + s->jiffie_bytes_write = bsz; + return 1; + } + } else { + band_limit_t nsz; + if(read) + nsz = s->jiffie_bytes_read + bsz; + else + nsz = s->jiffie_bytes_write + bsz; + if(nsz > max_bps) { + return 0; + } else { + if(read) + s->jiffie_bytes_read = nsz; + else + s->jiffie_bytes_write = nsz; + return 1; + } + } + } + + return 1; +} + +int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_token, ioa_socket_handle *s) +{ + if (e && in_reservation_token && s) { + *s = rtcp_map_get(e->map_rtcp, in_reservation_token); + if (*s) { + rtcp_map_del_savefd(e->map_rtcp, in_reservation_token); + return 0; + } + } + return -1; +} + +/* Socket options helpers ==>> */ + +#define CORRECT_RAW_TTL(ttl) do { if(ttl<0 || ttl>255) ttl=TTL_DEFAULT; } while(0) +#define CORRECT_RAW_TOS(tos) do { if(tos<0 || tos>255) tos=TOS_DEFAULT; } while(0) + +static int get_raw_socket_ttl(evutil_socket_t fd, int family) +{ + int ttl = 0; + + if(family == AF_INET6) { +#if !defined(IPV6_RECVHOPLIMIT) + UNUSED_ARG(fd); + do { return TTL_IGNORE; } while(0); +#else + socklen_t slen = (socklen_t)sizeof(ttl); + if(getsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,&slen)<0) { + perror("get HOPLIMIT on socket"); + return TTL_IGNORE; + } +#endif + } else { +#if !defined(IP_RECVTTL) + UNUSED_ARG(fd); + do { return TTL_IGNORE; } while(0); +#else + socklen_t slen = (socklen_t)sizeof(ttl); + if(getsockopt(fd, IPPROTO_IP, IP_TTL, &ttl,&slen)<0) { + perror("get TTL on socket"); + return TTL_IGNORE; + } +#endif + } + + CORRECT_RAW_TTL(ttl); + + return ttl; +} + +static int get_raw_socket_tos(evutil_socket_t fd, int family) +{ + int tos = 0; + + if(family == AF_INET6) { +#if !defined(IPV6_RECVTCLASS) + UNUSED_ARG(fd); + do { return TOS_IGNORE; } while(0); +#else + socklen_t slen = (socklen_t)sizeof(tos); + if(getsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos,&slen)<0) { + perror("get TCLASS on socket"); + return -1; + } +#endif + } else { +#if !defined(IP_RECVTOS) + UNUSED_ARG(fd); + do { return TOS_IGNORE; } while(0); +#else + socklen_t slen = (socklen_t)sizeof(tos); + if(getsockopt(fd, IPPROTO_IP, IP_TOS, &tos,&slen)<0) { + perror("get TOS on socket"); + return -1; + } +#endif + } + + CORRECT_RAW_TOS(tos); + + return tos; +} + +static int set_raw_socket_ttl(evutil_socket_t fd, int family, int ttl) +{ + + if(family == AF_INET6) { +#if !defined(IPV6_RECVHOPLIMIT) + UNUSED_ARG(fd); + UNUSED_ARG(ttl); +#else + CORRECT_RAW_TTL(ttl); + if(setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,sizeof(ttl))<0) { + perror("set HOPLIMIT on socket"); + return -1; + } +#endif + } else { +#if !defined(IP_RECVTTL) + UNUSED_ARG(fd); + UNUSED_ARG(ttl); +#else + CORRECT_RAW_TTL(ttl); + if(setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl,sizeof(ttl))<0) { + perror("set TTL on socket"); + return -1; + } +#endif + } + + return 0; +} + +static int set_raw_socket_tos(evutil_socket_t fd, int family, int tos) +{ + + if(family == AF_INET6) { +#if !defined(IPV6_RECVTCLASS) + UNUSED_ARG(fd); + UNUSED_ARG(tos); +#else + CORRECT_RAW_TOS(tos); + if(setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos,sizeof(tos))<0) { + perror("set TCLASS on socket"); + return -1; + } +#endif + } else { +#if !defined(IPV6_RECVTOS) + UNUSED_ARG(fd); + UNUSED_ARG(tos); +#else + if(setsockopt(fd, IPPROTO_IP, IP_TOS, &tos,sizeof(tos))<0) { + perror("set TOS on socket"); + return -1; + } +#endif + } + + return 0; +} + +static int set_socket_ttl(ioa_socket_handle s, int ttl) +{ + if(s->default_ttl < 0) //Unsupported + return -1; + + if(ttl < 0) + ttl = s->default_ttl; + + CORRECT_RAW_TTL(ttl); + + if(ttl > s->default_ttl) + ttl=s->default_ttl; + + if(s->current_ttl != ttl) { + int ret = set_raw_socket_ttl(s->fd, s->family, ttl); + s->current_ttl = ttl; + return ret; + } + + return 0; +} + +static int set_socket_tos(ioa_socket_handle s, int tos) +{ + if(s->default_tos < 0) //Unsupported + return -1; + + if(tos < 0) + tos = s->default_tos; + + CORRECT_RAW_TOS(tos); + + if(s->current_tos != tos) { + int ret = set_raw_socket_tos(s->fd, s->family, tos); + s->current_tos = tos; + return ret; + } + + return 0; +} + +int set_raw_socket_ttl_options(evutil_socket_t fd, int family) +{ + if (family == AF_INET6) { +#if !defined(IPV6_RECVHOPLIMIT) + UNUSED_ARG(fd); +#else + int recv_ttl_on = 1; + if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &recv_ttl_on, + sizeof(recv_ttl_on)) < 0) { + perror("cannot set recvhoplimit\n"); + } +#endif + } else { +#if !defined(IP_RECVTTL) + UNUSED_ARG(fd); +#else + int recv_ttl_on = 1; + if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &recv_ttl_on, + sizeof(recv_ttl_on)) < 0) { + perror("cannot set recvttl\n"); + } +#endif + } + + return 0; +} + +int set_raw_socket_tos_options(evutil_socket_t fd, int family) +{ + if (family == AF_INET6) { +#if !defined(IPV6_RECVTCLASS) + UNUSED_ARG(fd); +#else + int recv_tos_on = 1; + if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVTCLASS, &recv_tos_on, + sizeof(recv_tos_on)) < 0) { + perror("cannot set recvtclass\n"); + } +#endif + } else { +#if !defined(IP_RECVTOS) + UNUSED_ARG(fd); +#else + int recv_tos_on = 1; + if (setsockopt(fd, IPPROTO_IP, IP_RECVTOS, &recv_tos_on, + sizeof(recv_tos_on)) < 0) { + perror("cannot set recvtos\n"); + } +#endif + } + + return 0; +} + +int set_socket_options_fd(evutil_socket_t fd, int tcp, int family) +{ + + if(fd<0) + return 0; + + set_sock_buf_size(fd,UR_CLIENT_SOCK_BUF_SIZE); + + if(tcp) { + struct linger so_linger; + so_linger.l_onoff = 1; + so_linger.l_linger = 0; + if(setsockopt(fd, + SOL_SOCKET, + SO_LINGER, + &so_linger, + sizeof(so_linger))<1) { + //perror("setsolinger") + ; + } + } + + socket_set_nonblocking(fd); + + if (!tcp) { + set_raw_socket_ttl_options(fd, family); + set_raw_socket_tos_options(fd, family); + +#ifdef IP_RECVERR + if (family != AF_INET6) { + int on = 0; +#ifdef TURN_IP_RECVERR + on = 1; +#endif + if(setsockopt(fd, IPPROTO_IP, IP_RECVERR, (void *)&on, sizeof(on))<0) + perror("IP_RECVERR"); + } +#endif + +#ifdef IPV6_RECVERR + if (family == AF_INET6) { + int on = 0; +#ifdef TURN_IP_RECVERR + on = 1; +#endif + if(setsockopt(fd, IPPROTO_IPV6, IPV6_RECVERR, (void *)&on, sizeof(on))<0) + perror("IPV6_RECVERR"); + } +#endif + + } else { + int flag = 1; + int result = setsockopt(fd, /* socket affected */ + IPPROTO_TCP, /* set option at TCP level */ + TCP_NODELAY, /* name of option */ + (char*)&flag, /* value */ + sizeof(int)); /* length of option value */ + if (result < 0) + perror("TCP_NODELAY"); + + socket_tcp_set_keepalive(fd); + } + + return 0; +} + +int set_socket_options(ioa_socket_handle s) +{ + if(!s || (s->parent_s)) + return 0; + + set_socket_options_fd(s->fd,((s->st == TCP_SOCKET) || (s->st == TLS_SOCKET) || (s->st == TENTATIVE_TCP_SOCKET)),s->family); + + s->default_ttl = get_raw_socket_ttl(s->fd, s->family); + s->current_ttl = s->default_ttl; + + s->default_tos = get_raw_socket_tos(s->fd, s->family); + s->current_tos = s->default_tos; + + return 0; +} + +/* <<== Socket options helpers */ + +ioa_socket_handle create_unbound_ioa_socket(ioa_engine_handle e, ioa_socket_handle parent_s, int family, SOCKET_TYPE st, SOCKET_APP_TYPE sat) +{ + evutil_socket_t fd = -1; + ioa_socket_handle ret = NULL; + + if(!parent_s) { + switch (st){ + case UDP_SOCKET: + fd = socket(family, SOCK_DGRAM, 0); + if (fd < 0) { + perror("UDP socket"); + return NULL; + } + set_sock_buf_size(fd, UR_CLIENT_SOCK_BUF_SIZE); + break; + case TCP_SOCKET: + fd = socket(family, SOCK_STREAM, 0); + if (fd < 0) { + perror("TCP socket"); + return NULL; + } + set_sock_buf_size(fd, UR_CLIENT_SOCK_BUF_SIZE); + break; + default: + /* we do not support other sockets in the relay position */ + return NULL; + } + } + + ret = (ioa_socket*)turn_malloc(sizeof(ioa_socket)); + ns_bzero(ret,sizeof(ioa_socket)); + + ret->magic = SOCKET_MAGIC; + + ret->fd = fd; + ret->family = family; + ret->st = st; + ret->sat = sat; + ret->e = e; + + if(parent_s) { + add_socket_to_parent(parent_s, ret); + } else { + set_socket_options(ret); + } + + return ret; +} + +static int bind_ioa_socket(ioa_socket_handle s, const ioa_addr* local_addr, int reusable) +{ + if(!s || (s->parent_s)) + return 0; + + if (s && s->fd >= 0 && s->e && local_addr) { + + int res = addr_bind(s->fd, local_addr, reusable); + if (res >= 0) { + s->bound = 1; + addr_cpy(&(s->local_addr), local_addr); + if(addr_get_port(local_addr)<1) { + ioa_addr tmpaddr; + addr_get_from_sock(s->fd, &tmpaddr); + if(addr_any(&(s->local_addr))) { + addr_cpy(&(s->local_addr),&tmpaddr); + } else { + addr_set_port(&(s->local_addr),addr_get_port(&tmpaddr)); + } + } + s->local_addr_known = 1; + return 0; + } + } + return -1; +} + +int create_relay_ioa_sockets(ioa_engine_handle e, + ioa_socket_handle client_s, + int address_family, u08bits transport, + int even_port, ioa_socket_handle *rtp_s, + ioa_socket_handle *rtcp_s, uint64_t *out_reservation_token, + int *err_code, const u08bits **reason, + accept_cb acb, void *acbarg) +{ + + *rtp_s = NULL; + if (rtcp_s) + *rtcp_s = NULL; + + turnipports* tp = e->tp; + + size_t iip = 0; + + for (iip = 0; iip < e->relays_number; ++iip) { + + ioa_addr relay_addr; + const ioa_addr *ra = ioa_engine_get_relay_addr(e, client_s, address_family, err_code); + if(ra) + addr_cpy(&relay_addr, ra); + + if(*err_code) { + if(*err_code == 440) + *reason = (const u08bits *) "Unsupported address family"; + return -1; + } + + int rtcp_port = -1; + + IOA_CLOSE_SOCKET(*rtp_s); + if(rtcp_s) + IOA_CLOSE_SOCKET(*rtcp_s); + + ioa_addr rtcp_local_addr; + addr_cpy(&rtcp_local_addr, &relay_addr); + + int i = 0; + int port = 0; + ioa_addr local_addr; + addr_cpy(&local_addr, &relay_addr); + for (i = 0; i < 0xFFFF; i++) { + port = 0; + rtcp_port = -1; + if (even_port < 0) { + port = turnipports_allocate(tp, transport, &relay_addr); + } else { + + port = turnipports_allocate_even(tp, &relay_addr, even_port, out_reservation_token); + if (port >= 0 && even_port > 0) { + + IOA_CLOSE_SOCKET(*rtcp_s); + *rtcp_s = create_unbound_ioa_socket(e, NULL, relay_addr.ss.sa_family, UDP_SOCKET, RELAY_RTCP_SOCKET); + if (*rtcp_s == NULL) { + perror("socket"); + IOA_CLOSE_SOCKET(*rtp_s); + addr_set_port(&local_addr, port); + turnipports_release(tp, transport, &local_addr); + rtcp_port = port + 1; + addr_set_port(&rtcp_local_addr, rtcp_port); + turnipports_release(tp, transport, &rtcp_local_addr); + return -1; + } + sock_bind_to_device((*rtcp_s)->fd, (unsigned char*)e->relay_ifname); + + rtcp_port = port + 1; + addr_set_port(&rtcp_local_addr, rtcp_port); + if (bind_ioa_socket(*rtcp_s, &rtcp_local_addr, + (transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE)) < 0) { + addr_set_port(&local_addr, port); + turnipports_release(tp, transport, &local_addr); + turnipports_release(tp, transport, &rtcp_local_addr); + rtcp_port = -1; + IOA_CLOSE_SOCKET(*rtcp_s); + continue; + } + } + } + if (port < 0) { + IOA_CLOSE_SOCKET(*rtp_s); + if (rtcp_s) + IOA_CLOSE_SOCKET(*rtcp_s); + rtcp_port = -1; + break; + } else { + + IOA_CLOSE_SOCKET(*rtp_s); + + *rtp_s = create_unbound_ioa_socket(e, NULL, relay_addr.ss.sa_family, + (transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) ? TCP_SOCKET : UDP_SOCKET, + RELAY_SOCKET); + if (*rtp_s == NULL) { + if (rtcp_s) + IOA_CLOSE_SOCKET(*rtcp_s); + addr_set_port(&local_addr, port); + turnipports_release(tp, transport, &local_addr); + if (rtcp_port >= 0) + turnipports_release(tp, transport, &rtcp_local_addr); + perror("socket"); + return -1; + } + + sock_bind_to_device((*rtp_s)->fd, (unsigned char*)e->relay_ifname); + + addr_set_port(&local_addr, port); + if (bind_ioa_socket(*rtp_s, &local_addr, + (transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE)) >= 0) { + break; + } else { + IOA_CLOSE_SOCKET(*rtp_s); + if (rtcp_s) + IOA_CLOSE_SOCKET(*rtcp_s); + addr_set_port(&local_addr, port); + turnipports_release(tp, transport, &local_addr); + if (rtcp_port >= 0) + turnipports_release(tp, transport, &rtcp_local_addr); + rtcp_port = -1; + } + } + } + + if(i>=0xFFFF) { + IOA_CLOSE_SOCKET(*rtp_s); + if (rtcp_s) + IOA_CLOSE_SOCKET(*rtcp_s); + } + + if (*rtp_s) { + addr_set_port(&local_addr, port); + addr_debug_print(e->verbose, &local_addr, "Local relay addr"); + if (rtcp_s && *rtcp_s) { + addr_set_port(&local_addr, port+1); + addr_debug_print(e->verbose, &local_addr, "Local reserved relay addr"); + } + break; + } + } + + if (!(*rtp_s)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: no available ports 3\n", __FUNCTION__); + IOA_CLOSE_SOCKET(*rtp_s); + if (rtcp_s) + IOA_CLOSE_SOCKET(*rtcp_s); + return -1; + } + + set_accept_cb(*rtp_s, acb, acbarg); + + if (rtcp_s && *rtcp_s && out_reservation_token && *out_reservation_token) { + if (rtcp_map_put(e->map_rtcp, *out_reservation_token, *rtcp_s) < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: cannot update RTCP map\n", __FUNCTION__); + IOA_CLOSE_SOCKET(*rtp_s); + if (rtcp_s) + IOA_CLOSE_SOCKET(*rtcp_s); + return -1; + } + } + + return 0; +} + +/* RFC 6062 ==>> */ + +static void tcp_listener_input_handler(struct evconnlistener *l, evutil_socket_t fd, + struct sockaddr *sa, int socklen, void *arg) +{ + UNUSED_ARG(l); + + ioa_socket_handle list_s = (ioa_socket_handle) arg; + + ioa_addr client_addr; + ns_bcopy(sa,&client_addr,socklen); + + addr_debug_print(((list_s->e) && list_s->e->verbose), &client_addr,"tcp accepted from"); + + ioa_socket_handle s = + create_ioa_socket_from_fd( + list_s->e, + fd, + NULL, + TCP_SOCKET, + TCP_RELAY_DATA_SOCKET, + &client_addr, + &(list_s->local_addr)); + + if (s) { + if(list_s->acb) { + list_s->acb(s,list_s->acbarg); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Do not know what to do with accepted TCP socket\n"); + close_ioa_socket(s); + } + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Cannot create ioa_socket from FD\n"); + socket_closesocket(fd); + } +} + +static int set_accept_cb(ioa_socket_handle s, accept_cb acb, void *arg) +{ + if(!s || s->parent_s) + return -1; + + if(s->st == TCP_SOCKET) { + s->list_ev = evconnlistener_new(s->e->event_base, + tcp_listener_input_handler, s, + LEV_OPT_REUSEABLE, + 1024, s->fd); + if(!(s->list_ev)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: cannot start TCP listener\n", __FUNCTION__); + return -1; + } + s->acb = acb; + s->acbarg = arg; + } + return 0; +} + +static void connect_eventcb(struct bufferevent *bev, short events, void *ptr) +{ + UNUSED_ARG(bev); + + ioa_socket_handle ret = (ioa_socket_handle) ptr; + if (ret) { + connect_cb cb = ret->conn_cb; + void *arg = ret->conn_arg; + if (events & BEV_EVENT_CONNECTED) { + ret->conn_cb = NULL; + ret->conn_arg = NULL; + if(ret->conn_bev) { + bufferevent_disable(ret->conn_bev,EV_READ|EV_WRITE); + bufferevent_free(ret->conn_bev); + ret->conn_bev=NULL; + } + ret->connected = 1; + if(cb) { + cb(1,arg); + } + } else if (events & BEV_EVENT_ERROR) { + /* An error occured while connecting. */ + ret->conn_cb = NULL; + ret->conn_arg = NULL; + if(ret->conn_bev) { + bufferevent_disable(ret->conn_bev,EV_READ|EV_WRITE); + bufferevent_free(ret->conn_bev); + ret->conn_bev=NULL; + } + if(cb) { + cb(0,arg); + } + } + } +} + +ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, ioa_addr *peer_addr, connect_cb cb, void *arg) +{ + ioa_socket_handle ret = create_unbound_ioa_socket(s->e, NULL, s->family, s->st, TCP_RELAY_DATA_SOCKET); + + if(!ret) { + return NULL; + } + + ioa_addr new_local_addr; + addr_cpy(&new_local_addr, &(s->local_addr)); + +#if !defined(SO_REUSEPORT) + /* + * trick for OSes which do not support SO_REUSEPORT. + * Section 5.2 of RFC 6062 will not work correctly + * for those OSes (for example, Linux pre-3.9 kernel). + */ +#if !defined(__CYGWIN__) && !defined(__CYGWIN32__) && !defined(__CYGWIN64__) + close_socket_net_data(s); +#else + addr_set_port(&new_local_addr,0); +#endif +#endif + + if(bind_ioa_socket(ret, &new_local_addr,1)<0) { + IOA_CLOSE_SOCKET(ret); + ret = NULL; + goto ccs_end; + } + + addr_cpy(&(ret->remote_addr), peer_addr); + + set_ioa_socket_session(ret, s->session); + + if(ret->conn_bev) { + bufferevent_disable(ret->conn_bev,EV_READ|EV_WRITE); + bufferevent_free(ret->conn_bev); + ret->conn_bev=NULL; + } + + ret->conn_bev = bufferevent_socket_new(ret->e->event_base, + ret->fd, + BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + bufferevent_setcb(ret->conn_bev, NULL, NULL, connect_eventcb, ret); + + ret->conn_arg = arg; + ret->conn_cb = cb; + + if (bufferevent_socket_connect(ret->conn_bev, (struct sockaddr *) peer_addr, get_ioa_addr_len(peer_addr)) < 0) { + /* Error starting connection */ + set_ioa_socket_session(ret, NULL); + IOA_CLOSE_SOCKET(ret); + ret = NULL; + goto ccs_end; + } + + ccs_end: + +#if !defined(SO_REUSEPORT) +#if !defined(__CYGWIN__) && !defined(__CYGWIN32__) && !defined(__CYGWIN64__) + /* + * trick for OSes which do not support SO_REUSEPORT. + * Section 5.2 of RFC 6062 will not work correctly + * for those OSes (for example, Linux pre-3.9 kernel). + */ + s->fd = socket(s->family, SOCK_STREAM, 0); + if (s->fd < 0) { + perror("TCP socket"); + if(ret) { + set_ioa_socket_session(ret, NULL); + IOA_CLOSE_SOCKET(ret); + ret = NULL; + } + } else { + set_socket_options(s); + sock_bind_to_device(s->fd, (unsigned char*)s->e->relay_ifname); + if(bind_ioa_socket(s, &new_local_addr, 1)<0) { + if(ret) { + set_ioa_socket_session(ret, NULL); + IOA_CLOSE_SOCKET(ret); + ret = NULL; + } + } else { + set_accept_cb(s, s->acb, s->acbarg); + } + } +#endif +#endif + + return ret; +} + +/* <<== RFC 6062 */ + +void add_socket_to_parent(ioa_socket_handle parent_s, ioa_socket_handle s) +{ + if(parent_s && s) { + delete_socket_from_parent(s); + s->parent_s = parent_s; + s->fd = parent_s->fd; + } +} + +void delete_socket_from_parent(ioa_socket_handle s) +{ + if(s && s->parent_s) { + s->parent_s = NULL; + s->fd = -1; + } +} + +void add_socket_to_map(ioa_socket_handle s, ur_addr_map *amap) +{ + if(amap && s && (s->sockets_container != amap)) { + delete_socket_from_map(s); + ur_addr_map_del(amap, &(s->remote_addr),NULL); + ur_addr_map_put(amap, + &(s->remote_addr), + (ur_addr_map_value_type)s); + s->sockets_container = amap; + } +} + +void delete_socket_from_map(ioa_socket_handle s) +{ + if(s && s->sockets_container) { + ur_addr_map_del(s->sockets_container, + &(s->remote_addr), + NULL); + s->sockets_container = NULL; + } +} + +ioa_socket_handle create_ioa_socket_from_fd(ioa_engine_handle e, + ioa_socket_raw fd, ioa_socket_handle parent_s, + SOCKET_TYPE st, SOCKET_APP_TYPE sat, + const ioa_addr *remote_addr, const ioa_addr *local_addr) +{ + ioa_socket_handle ret = NULL; + + if ((fd < 0) && !parent_s) { + return NULL; + } + + ret = (ioa_socket*)turn_malloc(sizeof(ioa_socket)); + ns_bzero(ret,sizeof(ioa_socket)); + + ret->magic = SOCKET_MAGIC; + + ret->fd = fd; + ret->family = local_addr->ss.sa_family; + ret->st = st; + ret->sat = sat; + ret->e = e; + + if (local_addr) { + ret->bound = 1; + addr_cpy(&(ret->local_addr), local_addr); + } + + if (remote_addr) { + ret->connected = 1; + addr_cpy(&(ret->remote_addr), remote_addr); + } + + if(parent_s) { + add_socket_to_parent(parent_s, ret); + } else { + set_socket_options(ret); + } + + return ret; +} + +/* Only must be called for DTLS_SOCKET */ +ioa_socket_handle create_ioa_socket_from_ssl(ioa_engine_handle e, ioa_socket_handle parent_s, SSL* ssl, SOCKET_TYPE st, SOCKET_APP_TYPE sat, const ioa_addr *remote_addr, const ioa_addr *local_addr) +{ + ioa_socket_handle ret = create_ioa_socket_from_fd(e, parent_s->fd, parent_s, st, sat, remote_addr, local_addr); + + if(ret) { + ret->ssl = ssl; + if(st == DTLS_SOCKET) + STRCPY(ret->orig_ctx_type,"DTLSv1.0"); + } + + return ret; +} + +static void close_socket_net_data(ioa_socket_handle s) +{ + if(s) { + + EVENT_DEL(s->read_event); + if(s->list_ev) { + evconnlistener_free(s->list_ev); + s->list_ev = NULL; + } + if(s->conn_bev) { + bufferevent_disable(s->conn_bev,EV_READ|EV_WRITE); + bufferevent_free(s->conn_bev); + s->conn_bev=NULL; + } + if(s->bev) { + bufferevent_disable(s->bev,EV_READ|EV_WRITE); + bufferevent_free(s->bev); + s->bev=NULL; + } + + if (s->ssl) { + if (!s->broken) { + if(!(SSL_get_shutdown(s->ssl) & SSL_SENT_SHUTDOWN)) { + /* + * SSL_RECEIVED_SHUTDOWN tells SSL_shutdown to act as if we had already + * received a close notify from the other end. SSL_shutdown will then + * send the final close notify in reply. The other end will receive the + * close notify and send theirs. By this time, we will have already + * closed the socket and the other end's real close notify will never be + * received. In effect, both sides will think that they have completed a + * clean shutdown and keep their sessions valid. This strategy will fail + * if the socket is not ready for writing, in which case this hack will + * lead to an unclean shutdown and lost session on the other end. + */ + SSL_set_shutdown(s->ssl, SSL_RECEIVED_SHUTDOWN); + SSL_shutdown(s->ssl); + log_socket_event(s, "SSL shutdown received, socket to be closed",0); + } + } + SSL_free(s->ssl); + s->ssl = NULL; + } + + if (s->fd >= 0) { + socket_closesocket(s->fd); + s->fd = -1; + } + } +} + +void detach_socket_net_data(ioa_socket_handle s) +{ + if(s) { + EVENT_DEL(s->read_event); + s->read_cb = NULL; + s->read_ctx = NULL; + if(s->list_ev) { + evconnlistener_free(s->list_ev); + s->list_ev = NULL; + s->acb = NULL; + s->acbarg = NULL; + } + if(s->conn_bev) { + bufferevent_disable(s->conn_bev,EV_READ|EV_WRITE); + bufferevent_free(s->conn_bev); + s->conn_bev=NULL; + s->conn_arg=NULL; + s->conn_cb=NULL; + } + if(s->bev) { + bufferevent_disable(s->bev,EV_READ|EV_WRITE); + bufferevent_free(s->bev); + s->bev=NULL; + } + } +} + +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; + } + + if(s->done) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s double free on socket: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)s, s->st, s->sat); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s); + return; + } + + s->done = 1; + + while(!buffer_list_empty(&(s->bufs))) + pop_elem_from_buffer_list(&(s->bufs)); + + ioa_network_buffer_delete(s->e, s->defer_nbh); + + if(s->bound && s->e && s->e->tp) { + turnipports_release(s->e->tp, + ((s->st == TCP_SOCKET) ? STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE : STUN_ATTRIBUTE_TRANSPORT_UDP_VALUE), + &(s->local_addr)); + } + + delete_socket_from_map(s); + delete_socket_from_parent(s); + + close_socket_net_data(s); + + s->session = NULL; + s->sub_session = NULL; + s->magic = 0; + + turn_free(s,sizeof(ioa_socket)); + } +} + +ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach) +{ + ioa_socket_handle ret = NULL; + + if (!s) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Detaching NULL socket\n"); + } else { + if((s->magic != SOCKET_MAGIC)||(s->done)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s detach on bad socket: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)s, s->st, s->sat); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s); + return ret; + } + if(s->tobeclosed) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s detach on tobeclosed socket: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)s, s->st, s->sat); + return ret; + } + if(!(s->e)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s detach on socket without engine: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)s, s->st, s->sat); + return ret; + } + + s->tobeclosed = 1; + + if(s->parent_s) { + if((s->st != UDP_SOCKET) && (s->st != DTLS_SOCKET)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s detach on non-UDP child socket: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)s, s->st, s->sat); + return ret; + } + } + + evutil_socket_t udp_fd = -1; + + if(full_detach && s->parent_s) { + + udp_fd = socket(s->local_addr.ss.sa_family, SOCK_DGRAM, 0); + if (udp_fd < 0) { + perror("socket"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"%s: Cannot allocate new socket\n",__FUNCTION__); + return ret; + } + } + + detach_socket_net_data(s); + + while(!buffer_list_empty(&(s->bufs))) + pop_elem_from_buffer_list(&(s->bufs)); + + ioa_network_buffer_delete(s->e, s->defer_nbh); + + ret = (ioa_socket*)turn_malloc(sizeof(ioa_socket)); + if(!ret) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"%s: Cannot allocate new socket structure\n",__FUNCTION__); + if(udp_fd>=0) + close(udp_fd); + return ret; + } + + ns_bzero(ret,sizeof(ioa_socket)); + + ret->magic = SOCKET_MAGIC; + + ret->username_hash = s->username_hash; + ret->realm_hash = s->realm_hash; + + ret->ssl = s->ssl; + ret->fd = s->fd; + + ret->family = s->family; + ret->st = s->st; + ret->sat = s->sat; + ret->bound = s->bound; + ret->local_addr_known = s->local_addr_known; + addr_cpy(&(ret->local_addr),&(s->local_addr)); + ret->connected = s->connected; + ioa_socket_handle parent_s = s->parent_s; + addr_cpy(&(ret->remote_addr),&(s->remote_addr)); + + ur_addr_map *sockets_container = s->sockets_container; + + delete_socket_from_map(s); + delete_socket_from_parent(s); + + if(full_detach && parent_s) { + + ret->fd = udp_fd; + + if(sock_bind_to_device(udp_fd, (unsigned char*)(s->e->relay_ifname))<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind udp server socket to device %s\n",(char*)(s->e->relay_ifname)); + } + + if(addr_bind(udp_fd,&(s->local_addr),1)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind new detached udp server socket to local addr\n"); + IOA_CLOSE_SOCKET(ret); + return ret; + } + + int connect_err=0; + if(addr_connect(udp_fd, &(s->remote_addr), &connect_err)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot connect new detached udp server socket to remote addr\n"); + IOA_CLOSE_SOCKET(ret); + return ret; + } + + set_socket_options(ret); + + } else { + add_socket_to_parent(parent_s, ret); + add_socket_to_map(ret,sockets_container); + } + + ret->current_ttl = s->current_ttl; + ret->default_ttl = s->default_ttl; + + ret->current_tos = s->current_tos; + ret->default_tos = s->default_tos; + + s->ssl = NULL; + s->fd = -1; + } + + return ret; +} + +ts_ur_super_session *get_ioa_socket_session(ioa_socket_handle s) +{ + if(s) + return s->session; + return NULL; +} + +void set_ioa_socket_session(ioa_socket_handle s, ts_ur_super_session *ss) +{ + if(s) + s->session = ss; +} + +void clear_ioa_socket_session_if(ioa_socket_handle s, void *ss) +{ + if(s && ((void*)(s->session)==ss)) { + s->session=NULL; + } +} + +tcp_connection *get_ioa_socket_sub_session(ioa_socket_handle s) +{ + if(s) + return s->sub_session; + return NULL; +} + +void set_ioa_socket_sub_session(ioa_socket_handle s, tcp_connection *tc) +{ + if(s) + s->sub_session = tc; +} + +int get_ioa_socket_address_family(ioa_socket_handle s) { + if(!s) { + return AF_INET; + } else if(s->parent_s) { + return s->parent_s->family; + } else { + return s->family; + } +} + +SOCKET_TYPE get_ioa_socket_type(ioa_socket_handle s) +{ + if(s) + return s->st; + + return UNKNOWN_SOCKET; +} + +SOCKET_APP_TYPE get_ioa_socket_app_type(ioa_socket_handle s) +{ + if(s) + return s->sat; + return UNKNOWN_APP_SOCKET; +} + +void set_ioa_socket_app_type(ioa_socket_handle s, SOCKET_APP_TYPE sat) { + if(s) + s->sat = sat; +} + +ioa_addr* get_local_addr_from_ioa_socket(ioa_socket_handle s) +{ + if (s) { + + if(s->parent_s) { + return get_local_addr_from_ioa_socket(s->parent_s); + } else if (s->local_addr_known) { + return &(s->local_addr); + } else if (s->bound && (addr_get_port(&(s->local_addr)) > 0)) { + s->local_addr_known = 1; + return &(s->local_addr); + } else { + ioa_addr tmpaddr; + if (addr_get_from_sock(s->fd, &tmpaddr) == 0) { + if(addr_get_port(&tmpaddr)>0) { + s->local_addr_known = 1; + s->bound = 1; + if(addr_any(&(s->local_addr))) { + addr_cpy(&(s->local_addr),&tmpaddr); + } else { + addr_set_port(&(s->local_addr),addr_get_port(&tmpaddr)); + } + return &(s->local_addr); + } + if(addr_any(&(s->local_addr))) { + addr_cpy(&(s->local_addr),&tmpaddr); + } + return &(s->local_addr); + } + } + } + return NULL; +} + +ioa_addr* get_remote_addr_from_ioa_socket(ioa_socket_handle s) +{ + if (s) { + + if (s->connected) { + return &(s->remote_addr); + } + } + return NULL; +} + +int get_local_mtu_ioa_socket(ioa_socket_handle s) +{ + if(s) { + if(s->parent_s) + return get_local_mtu_ioa_socket(s->parent_s); + + return get_socket_mtu(s->fd, s->family, (s->e && eve(s->e->verbose))); + } + return -1; +} + +/* + * Return: -1 - error, 0 or >0 - OK + * *read_len -1 - no data, >=0 - data available + */ +int ssl_read(evutil_socket_t fd, SSL* ssl, ioa_network_buffer_handle nbh, int verbose) +{ + int ret = 0; + + if (!ssl || !nbh) + return -1; + + s08bits* buffer = (s08bits*)ioa_network_buffer_data(nbh); + int buf_size = (int)ioa_network_buffer_get_capacity_udp(); + int read_len = (int)ioa_network_buffer_get_size(nbh); + + if(read_len < 1) + return -1; + + s08bits *new_buffer = buffer + buf_size; + int old_buffer_len = read_len; + + int len = 0; + + if (eve(verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: before read...\n", __FUNCTION__); + } + + BIO *wbio = SSL_get_wbio(ssl); + if(wbio) { + BIO_set_fd(wbio,fd,BIO_NOCLOSE); + } + + BIO* rbio = BIO_new_mem_buf(buffer, old_buffer_len); + BIO_set_mem_eof_return(rbio, -1); + + ssl->rbio = rbio; + + int if1 = SSL_is_init_finished(ssl); + + do { + len = SSL_read(ssl, new_buffer, buf_size); + } while (len < 0 && (errno == EINTR)); + + int if2 = SSL_is_init_finished(ssl); + + if (eve(verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: after read: %d\n", __FUNCTION__, len); + } + + if(SSL_get_shutdown(ssl)) { + + ret = -1; + + } else if (!if1 && if2) { + + if(verbose && SSL_get_peer_certificate(ssl)) { + printf("\n------------------------------------------------------------\n"); + X509_NAME_print_ex_fp(stdout, X509_get_subject_name(SSL_get_peer_certificate(ssl)), 1, + XN_FLAG_MULTILINE); + printf("\n\n Cipher: %s\n", SSL_CIPHER_get_name(SSL_get_current_cipher(ssl))); + printf("\n------------------------------------------------------------\n\n"); + } + + ret = 0; + + } else if (len < 0 && ((errno == ENOBUFS) || (errno == EAGAIN))) { + if (eve(verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: ENOBUFS/EAGAIN\n", __FUNCTION__); + } + ret = 0; + } else { + + if (eve(verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: read %d bytes\n", __FUNCTION__, (int) len); + } + + if (len >= 0) { + ret = len; + } else { + switch (SSL_get_error(ssl, len)){ + case SSL_ERROR_NONE: + //??? + ret = 0; + break; + case SSL_ERROR_WANT_READ: + ret = 0; + break; + case SSL_ERROR_WANT_WRITE: + ret = 0; + break; + case SSL_ERROR_ZERO_RETURN: + ret = 0; + break; + case SSL_ERROR_SYSCALL: + { + int err = errno; + if (handle_socket_error()) { + ret = 0; + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS Socket read error: %d\n", err); + ret = -1; + } + break; + } + case SSL_ERROR_SSL: + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SSL read error: "); + s08bits buf[65536]; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s (%d)\n", ERR_error_string(ERR_get_error(), buf), SSL_get_error(ssl, len)); + } + if (verbose) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SSL connection closed.\n"); + ret = -1; + break; + default: + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Unexpected error while reading!\n"); + } + ret = -1; + } + } + } + + if(ret>0) { + ioa_network_buffer_add_offset_size(nbh, (u16bits)buf_size, 0, (size_t)ret); + } + + BIO_free(rbio); + ssl->rbio = NULL; + + return ret; +} + +static int socket_readerr(evutil_socket_t fd, ioa_addr *orig_addr) +{ + if ((fd < 0) || !orig_addr) + return -1; + +#if defined(CMSG_SPACE) && defined(MSG_ERRQUEUE) && defined(IP_RECVERR) + + u08bits ecmsg[TURN_CMSG_SZ+1]; + int flags = MSG_ERRQUEUE; + int len = 0; + + struct msghdr msg; + struct iovec iov; + char buffer[65536]; + + char *cmsg = (char*)ecmsg; + + msg.msg_control = cmsg; + msg.msg_controllen = TURN_CMSG_SZ; + /* CMSG_SPACE(sizeof(recv_ttl)+sizeof(recv_tos)) */ + + msg.msg_name = orig_addr; + msg.msg_namelen = (socklen_t)get_ioa_addr_len(orig_addr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_iov->iov_base = buffer; + msg.msg_iov->iov_len = sizeof(buffer); + msg.msg_flags = 0; + + int try_cycle = 0; + + do { + + do { + len = recvmsg(fd,&msg,flags); + } while (len < 0 && (errno == EINTR)); + + } while((len>0)&&(try_cycle++iov_base = buffer; + msg.msg_iov->iov_len = (size_t)buf_size; + msg.msg_flags = 0; + +#if defined(MSG_ERRQUEUE) + int try_cycle = 0; + try_again: +#endif + + do { + len = recvmsg(fd,&msg,flags); + } while (len < 0 && (errno == EINTR)); + +#if defined(MSG_ERRQUEUE) + + if(flags & MSG_ERRQUEUE) { + if((len>0)&&(try_cycle++= 0) { + + struct cmsghdr *cmsgh; + + // Receive auxiliary data in msg + for (cmsgh = CMSG_FIRSTHDR(&msg); cmsgh != NULL; cmsgh + = CMSG_NXTHDR(&msg,cmsgh)) { + int l = cmsgh->cmsg_level; + int t = cmsgh->cmsg_type; + + switch(l) { + case IPPROTO_IP: + switch(t) { +#if defined(IP_RECVTTL) + case IP_RECVTTL: + case IP_TTL: + recv_ttl = *((recv_ttl_t *) CMSG_DATA(cmsgh)); + break; +#endif +#if defined(IP_RECVTOS) + case IP_RECVTOS: + case IP_TOS: + recv_tos = *((recv_tos_t *) CMSG_DATA(cmsgh)); + break; +#endif +#if defined(IP_RECVERR) + case IP_RECVERR: + { + struct turn_sock_extended_err *e=(struct turn_sock_extended_err*) CMSG_DATA(cmsgh); + if(errcode) + *errcode = e->ee_errno; + } + break; +#endif + default: + ; + /* no break */ + }; + break; + case IPPROTO_IPV6: + switch(t) { +#if defined(IPV6_RECVHOPLIMIT) + case IPV6_RECVHOPLIMIT: + case IPV6_HOPLIMIT: + recv_ttl = *((recv_ttl_t *) CMSG_DATA(cmsgh)); + break; +#endif +#if defined(IPV6_RECVTCLASS) + case IPV6_RECVTCLASS: + case IPV6_TCLASS: + recv_tos = *((recv_tos_t *) CMSG_DATA(cmsgh)); + break; +#endif +#if defined(IPV6_RECVERR) + case IPV6_RECVERR: + { + struct turn_sock_extended_err *e=(struct turn_sock_extended_err*) CMSG_DATA(cmsgh); + if(errcode) + *errcode = e->ee_errno; + } + break; +#endif + default: + ; + /* no break */ + }; + break; + default: + ; + /* no break */ + }; + } + } + +#endif + + *ttl = recv_ttl; + + CORRECT_RAW_TTL(*ttl); + + *tos = recv_tos; + + CORRECT_RAW_TOS(*tos); + + return len; +} + +#if !defined(TURN_NO_TLS) +static TURN_TLS_TYPE check_tentative_tls(ioa_socket_raw fd) +{ + TURN_TLS_TYPE ret = TURN_TLS_NO; + + char s[12]; + int len = 0; + + do { + len = (int)recv(fd, s, sizeof(s), MSG_PEEK); + } while (len < 0 && (errno == EINTR)); + + if(len>0 && ((size_t)len == sizeof(s))) { + 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)); + 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 */ + } + } + + return ret; +} +#endif + +static int socket_input_worker(ioa_socket_handle s) +{ + int len = 0; + int ret = 0; + size_t app_msg_len = 0; + int ttl = TTL_IGNORE; + int tos = TOS_IGNORE; + ioa_addr remote_addr; + + int try_again = 0; + int try_ok = 0; + int try_cycle = 0; + const int MAX_TRIES = 16; + + if(!s) + return 0; + + if((s->magic != SOCKET_MAGIC)||(s->done)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!!%s on socket: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)s, s->st, s->sat); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s); + return -1; + } + + if(!(s->e)) + return 0; + + if(s->tobeclosed) + return 0; + + if(s->connected) + addr_cpy(&remote_addr,&(s->remote_addr)); + + if(tcp_congestion_control && s->sub_session && s->bev) { + if(s == s->sub_session->client_s) { + if(!is_socket_writeable(s->sub_session->peer_s, STUN_BUFFER_SIZE,__FUNCTION__,0)) { + if(bufferevent_enabled(s->bev,EV_READ)) { + bufferevent_disable(s->bev,EV_READ); + } + } + } else if(s == s->sub_session->peer_s) { + if(!is_socket_writeable(s->sub_session->client_s, STUN_BUFFER_SIZE,__FUNCTION__,1)) { + if(bufferevent_enabled(s->bev,EV_READ)) { + bufferevent_disable(s->bev,EV_READ); + } + } + } + } + + if(s->st == TLS_SOCKET) { +#if !defined(TURN_NO_TLS) + SSL *ctx = bufferevent_openssl_get_ssl(s->bev); + if(!ctx || SSL_get_shutdown(ctx)) { + s->tobeclosed = 1; + return 0; + } +#endif + } else if(s->st == DTLS_SOCKET) { + if(!(s->ssl) || SSL_get_shutdown(s->ssl)) { + s->tobeclosed = 1; + return 0; + } + } + + if(!(s->e)) + return 0; + + if(s->st == TENTATIVE_TCP_SOCKET) { + EVENT_DEL(s->read_event); +#if !defined(TURN_NO_TLS) + TURN_TLS_TYPE tls_type = check_tentative_tls(s->fd); + if(tls_type) { + s->st = TLS_SOCKET; + if(s->ssl) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!!%s on socket: 0x%lx, st=%d, sat=%d: ssl already exist\n", __FUNCTION__,(long)s, s->st, s->sat); + } + if(s->bev) { + 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); + } + switch(tls_type) { +#if defined(SSL_TXT_TLSV1_2) + case TURN_TLS_v1_2: + if(s->e->tls_ctx_v1_2) { + s->ssl = SSL_new(s->e->tls_ctx_v1_2); + STRCPY(s->orig_ctx_type,"TLSv1.2"); + break; + } +#endif +#if defined(SSL_TXT_TLSV1_1) + case TURN_TLS_v1_1: + if(s->e->tls_ctx_v1_1) { + s->ssl = SSL_new(s->e->tls_ctx_v1_1); + STRCPY(s->orig_ctx_type,"TLSv1.1"); + break; + } + +#endif + case TURN_TLS_v1_0: + if(s->e->tls_ctx_v1_0) { + s->ssl = SSL_new(s->e->tls_ctx_v1_0); + STRCPY(s->orig_ctx_type,"TLSv1.0"); + break; + } + default: + if(s->e->tls_ctx_ssl23) { + s->ssl = SSL_new(s->e->tls_ctx_ssl23); + STRCPY(s->orig_ctx_type,"SSLv23"); + } else { + s->tobeclosed = 1; + return 0; + } + }; + s->bev = bufferevent_openssl_socket_new(s->e->event_base, + s->fd, + s->ssl, + BUFFEREVENT_SSL_ACCEPTING, + BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + 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. */ + } else +#endif //TURN_NO_TLS + { + s->st = TCP_SOCKET; + if(s->bev) { + 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, + BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + 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. */ + } + } + + try_start: + + if(!(s->e)) + return 0; + + try_again=0; + try_ok=0; + + stun_buffer_list_elem *buf_elem = new_blist_elem(s->e); + len = -1; + + if(s->bev) { /* TCP & TLS */ + struct evbuffer *inbuf = bufferevent_get_input(s->bev); + if(inbuf) { + ev_ssize_t blen = evbuffer_copyout(inbuf, buf_elem->buf.buf, STUN_BUFFER_SIZE); + if(blen>0) { + int mlen = 0; + + if(blen>(ev_ssize_t)STUN_BUFFER_SIZE) + blen=(ev_ssize_t)STUN_BUFFER_SIZE; + + if(((s->st == TCP_SOCKET)||(s->st == TLS_SOCKET)) && ((s->sat == TCP_CLIENT_DATA_SOCKET)||(s->sat==TCP_RELAY_DATA_SOCKET))) { + mlen = blen; + } else { + mlen = stun_get_message_len_str(buf_elem->buf.buf, blen, 1, &app_msg_len); + } + + if(mlen>0 && mlen<=(int)blen) { + len = (int)bufferevent_read(s->bev, buf_elem->buf.buf, mlen); + if(len < 0) { + ret = -1; + s->tobeclosed = 1; + s->broken = 1; + log_socket_event(s, "socket read failed, to be closed",1); + } else if(s->st == TLS_SOCKET) { +#if !defined(TURN_NO_TLS) + SSL *ctx = bufferevent_openssl_get_ssl(s->bev); + if(!ctx || SSL_get_shutdown(ctx)) { + ret = -1; + s->tobeclosed = 1; + } +#endif + } + if(ret != -1) { + ret = len; + } + } + + } else if(blen<0) { + s->tobeclosed = 1; + s->broken = 1; + ret = -1; + log_socket_event(s, "socket buffer copy failed, to be closed",1); + } + } else { + s->tobeclosed = 1; + s->broken = 1; + ret = -1; + log_socket_event(s, "socket input failed, socket to be closed",1); + } + + if(len == 0) + len = -1; + } else if(s->fd>=0){ /* UDP and DTLS */ + ret = udp_recvfrom(s->fd, &remote_addr, &(s->local_addr), (s08bits*)(buf_elem->buf.buf), UDP_STUN_BUFFER_SIZE, &ttl, &tos, s->e->cmsg, 0, NULL); + len = ret; + if(s->ssl && (len>0)) { /* DTLS */ + send_ssl_backlog_buffers(s); + buf_elem->buf.len = (size_t)len; + ret = ssl_read(s->fd, s->ssl, (ioa_network_buffer_handle)buf_elem, ((s->e) && s->e->verbose)); + addr_cpy(&remote_addr,&(s->remote_addr)); + if(ret < 0) { + len = -1; + s->tobeclosed = 1; + s->broken = 1; + log_socket_event(s, "SSL read failed, to be closed",0); + } else { + len = (int)ioa_network_buffer_get_size((ioa_network_buffer_handle)buf_elem); + } + if((ret!=-1)&&(len>0)) + try_again = 1; + } else { /* UDP */ + if(ret>=0) + try_again = 1; + } + } else { + s->tobeclosed = 1; + s->broken = 1; + ret = -1; + log_socket_event(s, "socket unknown error, to be closed",1); + } + + if ((ret!=-1) && (len >= 0)) { + if(ioa_socket_check_bandwidth(s,(size_t)len,1)) { + if(app_msg_len) + buf_elem->buf.len = app_msg_len; + else + buf_elem->buf.len = len; + + if(s->read_cb) { + ioa_net_data nd; + + ns_bzero(&nd,sizeof(ioa_net_data)); + addr_cpy(&(nd.src_addr),&remote_addr); + nd.nbh = buf_elem; + nd.recv_ttl = ttl; + nd.recv_tos = tos; + + s->read_cb(s, IOA_EV_READ, &nd, s->read_ctx); + + if(nd.nbh) + free_blist_elem(s->e,buf_elem); + + buf_elem = NULL; + + try_ok = 1; + + } else { + ioa_network_buffer_delete(s->e, s->defer_nbh); + s->defer_nbh = buf_elem; + buf_elem = NULL; + } + } + } + + if(buf_elem) { + free_blist_elem(s->e,buf_elem); + buf_elem = NULL; + } + + if(try_again && try_ok && !(s->done) && + !(s->tobeclosed) && ((++try_cycle)parent_s)) { + goto try_start; + } + + return len; +} + +static void socket_input_handler(evutil_socket_t fd, short what, void* arg) +{ + + if (!(what & EV_READ)) + return; + + if(!arg) { + read_spare_buffer(fd); + return; + } + + ioa_socket_handle s = (ioa_socket_handle)arg; + + if(!s) + return; + + if((s->magic != SOCKET_MAGIC)||(s->done)) { + read_spare_buffer(fd); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!!%s on bad socket, ev=%d: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(int)what,(long)s, s->st, s->sat); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s); + return; + } + + if(fd != s->fd) { + read_spare_buffer(fd); + return; + } + + if (!ioa_socket_tobeclosed(s)) + socket_input_worker(s); + + if((s->magic != SOCKET_MAGIC)||(s->done)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!!%s (1) on socket, ev=%d: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(int)what,(long)s, s->st, s->sat); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s); + return; + } + + close_ioa_socket_after_processing_if_necessary(s); +} + +void close_ioa_socket_after_processing_if_necessary(ioa_socket_handle s) +{ + if (s && ioa_socket_tobeclosed(s)) { + switch (s->sat){ + case TCP_CLIENT_DATA_SOCKET: + case TCP_RELAY_DATA_SOCKET: + { + tcp_connection *tc = s->sub_session; + if (tc) { + delete_tcp_connection(tc); + } + } + break; + default: + { + ts_ur_super_session *ss = s->session; + if (ss) { + turn_turnserver *server = (turn_turnserver *) ss->server; + if (server) { + shutdown_client_connection(server, ss, 0, "general"); + } + } + } + } + } +} + +static void socket_output_handler_bev(struct bufferevent *bev, void* arg) +{ + + UNUSED_ARG(bev); + UNUSED_ARG(arg); + + if (tcp_congestion_control) { + + if (bev && arg) { + + ioa_socket_handle s = (ioa_socket_handle) arg; + + if ((s->magic != SOCKET_MAGIC)||(s->done)||ioa_socket_tobeclosed(s)||(bev != s->bev)) { + return; + } + + if (s->sub_session) { + + if (s == s->sub_session->client_s) { + if (s->sub_session->peer_s && s->sub_session->peer_s->bev) { + if (!bufferevent_enabled(s->sub_session->peer_s->bev, + EV_READ)) { + if (is_socket_writeable(s->sub_session->peer_s, + STUN_BUFFER_SIZE, __FUNCTION__, 3)) { + bufferevent_enable(s->sub_session->peer_s->bev,EV_READ); + socket_input_handler_bev( + s->sub_session->peer_s->bev, + s->sub_session->peer_s); + } + } + } + } else if (s == s->sub_session->peer_s) { + if (s->sub_session->client_s + && s->sub_session->client_s->bev) { + if (!bufferevent_enabled(s->sub_session->client_s->bev, + EV_READ)) { + if (is_socket_writeable(s->sub_session->client_s, + STUN_BUFFER_SIZE, __FUNCTION__, 4)) { + bufferevent_enable(s->sub_session->client_s->bev, EV_READ); + socket_input_handler_bev( + s->sub_session->client_s->bev, + s->sub_session->client_s); + } + } + } + } + } + } + } +} + +static void socket_input_handler_bev(struct bufferevent *bev, void* arg) +{ + + if (bev && arg) { + + ioa_socket_handle s = (ioa_socket_handle) arg; + + if(bev != s->bev) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx: wrong bev\n", __FUNCTION__,(long)s); + return; + } + + if((s->magic != SOCKET_MAGIC)||(s->done)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!!%s on socket: 0x%lx, st=%d, sat=%d\n", __FUNCTION__, (long) s, s->st, s->sat); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s); + return; + } + + while (!ioa_socket_tobeclosed(s)) { + if (socket_input_worker(s) <= 0) + break; + } + + if((s->magic != SOCKET_MAGIC)||(s->done)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!!%s (1) on socket: 0x%lx, st=%d, sat=%d\n", __FUNCTION__, (long) s, s->st, s->sat); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s); + return; + } + + if (ioa_socket_tobeclosed(s)) { + switch(s->sat) { + case TCP_CLIENT_DATA_SOCKET: + case TCP_RELAY_DATA_SOCKET: + { + tcp_connection *tc = s->sub_session; + if(tc) { + delete_tcp_connection(tc); + } + } + break; + default: + { + ts_ur_super_session *ss = s->session; + if (ss) { + turn_turnserver *server = (turn_turnserver *)ss->server; + if (server) { + shutdown_client_connection(server, ss, 0, "TCP socket buffer operation error (input handler)"); + } + } + } + } + } + } +} + +static void eventcb_bev(struct bufferevent *bev, short events, void *arg) +{ + UNUSED_ARG(bev); + + if (events & BEV_EVENT_CONNECTED) { + // Connect okay + } else if (events & (BEV_EVENT_ERROR | BEV_EVENT_EOF)) { + if (arg) { + ioa_socket_handle s = (ioa_socket_handle) arg; + + if((s->st != TCP_SOCKET)&&(s->st != TLS_SOCKET)&&(s->st != TENTATIVE_TCP_SOCKET)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s: socket type is wrong on the socket: 0x%lx, st=%d, sat=%d\n",__FUNCTION__,(long)s,s->st,s->sat); + return; + } + + if(s->magic != SOCKET_MAGIC) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s: magic is wrong on the socket: 0x%lx, st=%d, sat=%d\n",__FUNCTION__,(long)s,s->st,s->sat); + return; + } + + if (s->done) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s: closed socket: 0x%lx (1): done=%d, fd=%d, br=%d, st=%d, sat=%d, tbc=%d\n", __FUNCTION__, (long) s, (int) s->done, + (int) s->fd, s->broken, s->st, s->sat, s->tobeclosed); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s); + return; + } + + if (events & BEV_EVENT_ERROR) + s->broken = 1; + + s->tobeclosed = 1; + + switch (s->sat){ + case TCP_CLIENT_DATA_SOCKET: + case TCP_RELAY_DATA_SOCKET: + { + tcp_connection *tc = s->sub_session; + if (tc) { + delete_tcp_connection(tc); + } + } + break; + default: + { + ts_ur_super_session *ss = s->session; + if (ss) { + turn_turnserver *server = (turn_turnserver *) ss->server; + if (server) { + + + { + char sraddr[129]="\0"; + addr_to_string(&(s->remote_addr),(u08bits*)sraddr); + if (events & BEV_EVENT_EOF) { + if(server->verbose) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: TCP socket closed remotely %s\n",(unsigned long long)(ss->id),sraddr); + if(s == ss->client_session.s) { + shutdown_client_connection(server, ss, 0, "TCP connection closed by client (callback)"); + } else if(s == ss->alloc.relay_session.s) { + shutdown_client_connection(server, ss, 0, "TCP connection closed by peer (callback)"); + } else { + shutdown_client_connection(server, ss, 0, "TCP connection closed by remote party (callback)"); + } + } else if (events & BEV_EVENT_ERROR) { + if(EVUTIL_SOCKET_ERROR()) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"session %018llu: TCP socket error: %s %s\n",(unsigned long long)(ss->id), + evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()), sraddr); + } else if(server->verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: TCP socket disconnected: %s\n",(unsigned long long)(ss->id),sraddr); + } + shutdown_client_connection(server, ss, 0, "TCP socket buffer operation error (callback)"); + } + } + } + } + } + }; + } + } +} + +static int ssl_send(ioa_socket_handle s, const s08bits* buffer, int len, int verbose) +{ + + if (!s || !(s->ssl) || !buffer || (s->fd<0)) + return -1; + + SSL *ssl = s->ssl; + + if (eve(verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: before write: buffer=0x%lx, len=%d\n", __FUNCTION__,(long)buffer,len); + } + + if(s->parent_s) { + /* Trick only for "children" sockets: */ + BIO *wbio = SSL_get_wbio(ssl); + if(!wbio) + return -1; + int fd = BIO_get_fd(wbio,0); + int sfd = s->parent_s->fd; + if(sfd >= 0) { + if(fd != sfd) { + BIO_set_fd(wbio,sfd,BIO_NOCLOSE); + } + } + } else { + BIO *wbio = SSL_get_wbio(ssl); + if(!wbio) + return -1; + int fd = BIO_get_fd(wbio,0); + if(fd != s->fd) { + BIO_set_fd(wbio,s->fd,BIO_NOCLOSE); + } + } + + int rc = 0; + int try_again = 1; + +#if !defined(TURN_IP_RECVERR) + try_again = 0; +#endif + + try_start: + + do { + rc = SSL_write(ssl, buffer, len); + } while (rc < 0 && errno == EINTR); + + if (eve(verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: after write: %d\n", __FUNCTION__,rc); + } + + if (rc < 0 && ((errno == ENOBUFS) || (errno == EAGAIN))) { + if (eve(verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: ENOBUFS/EAGAIN\n", __FUNCTION__); + } + return 0; + } + + if (rc >= 0) { + + if (eve(verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: wrote %d bytes\n", __FUNCTION__, (int) rc); + } + + return rc; + + } else { + + if (eve(verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: failure: rc=%d, err=%d\n", __FUNCTION__, (int)rc,(int)SSL_get_error(ssl, rc)); + } + + switch (SSL_get_error(ssl, rc)){ + case SSL_ERROR_NONE: + //??? + if (eve(verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "wrote %d bytes\n", (int) rc); + } + return 0; + case SSL_ERROR_WANT_WRITE: + return 0; + case SSL_ERROR_WANT_READ: + return 0; + case SSL_ERROR_SYSCALL: + { + int err = errno; + if (!handle_socket_error()) { + if(s->st == DTLS_SOCKET) { + if(is_connreset()) { + if(try_again) { + BIO *wbio = SSL_get_wbio(ssl); + if(wbio) { + int fd = BIO_get_fd(wbio,0); + if(fd>=0) { + try_again = 0; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS Socket, tring to recover write operation...\n"); + socket_readerr(fd, &(s->local_addr)); + goto try_start; + } + } + } + } + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS Socket lost packet... fine\n"); + return 0; + } + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS Socket write error unrecoverable: %d; buffer=0x%lx, len=%d, ssl=0x%lx\n", err, (long)buffer, (int)len, (long)ssl); + return -1; + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS Socket write error recoverable: %d\n", err); + return 0; + } + } + case SSL_ERROR_SSL: + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SSL write error: "); + s08bits buf[65536]; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s (%d)\n", ERR_error_string(ERR_get_error(), buf), + SSL_get_error(ssl, rc)); + } + return -1; + default: + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Unexpected error while writing!\n"); + } + return -1; + } + } +} + +static int send_ssl_backlog_buffers(ioa_socket_handle s) +{ + int ret = 0; + if(s) { + stun_buffer_list_elem *buf_elem = s->bufs.head; + while(buf_elem) { + int rc = ssl_send(s, (s08bits*)buf_elem->buf.buf + buf_elem->buf.offset - buf_elem->buf.coffset, (size_t)buf_elem->buf.len, ((s->e) && s->e->verbose)); + if(rc<1) + break; + ++ret; + pop_elem_from_buffer_list(&(s->bufs)); + buf_elem = s->bufs.head; + } + } + + return ret; +} + +int is_connreset(void) { + switch (errno) { + case ECONNRESET: + case ECONNREFUSED: + return 1; + default: + ; + } + return 0; +} + +int would_block(void) { +#if defined(EWOULDBLOCK) + if(errno == EWOULDBLOCK) + return 1; +#endif + return (errno == EAGAIN); +} + +int udp_send(ioa_socket_handle s, const ioa_addr* dest_addr, const s08bits* buffer, int len) +{ + int rc = 0; + evutil_socket_t fd = -1; + + if(!s) + return -1; + + if(s->parent_s) + fd = s->parent_s->fd; + else + fd = s->fd; + + if(fd>=0) { + + int try_again = 1; + + int cycle; + +#if !defined(TURN_IP_RECVERR) + try_again = 0; +#endif + + try_start: + + cycle = 0; + + if (dest_addr) { + + int slen = get_ioa_addr_len(dest_addr); + + do { + rc = sendto(fd, buffer, len, 0, (const struct sockaddr*) dest_addr, (socklen_t) slen); + } while ( + ((rc < 0) && (errno == EINTR)) || + ((rc<0) && is_connreset() && (++cyclelocal_addr)); + goto try_start; + } + //Lost packet - sent to nowhere... fine. + rc = len; + } + } + } + + return rc; +} + +int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, + ioa_network_buffer_handle nbh, + int ttl, int tos) +{ + int ret = -1; + + if(!s) { + ioa_network_buffer_delete(NULL, nbh); + return -1; + } + + if (s->done || (s->fd == -1)) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_INFO, + "!!! %s: (1) Trying to send data from closed 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 (nbh) { + if(!ioa_socket_check_bandwidth(s,ioa_network_buffer_get_size(nbh),0)) { + /* Bandwidth exhausted, we pretend everything is fine: */ + ret = (int)(ioa_network_buffer_get_size(nbh)); + } else { + if (!ioa_socket_tobeclosed(s) && s->e) { + + if (!(s->done || (s->fd == -1))) { + set_socket_ttl(s, ttl); + set_socket_tos(s, tos); + + if (s->connected && s->bev) { + if (s->st == TLS_SOCKET) { +#if !defined(TURN_NO_TLS) + 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) ioa_network_buffer_get_size(nbh); + + if(!udp_congestion_control || is_socket_writeable(s,(size_t)ret,__FUNCTION__,2)) { + if (bufferevent_write( + s->bev, + ioa_network_buffer_data(nbh), + ioa_network_buffer_get_size(nbh)) + < 0) { + ret = -1; + perror("bufev send"); + log_socket_event(s, "socket write failed, to be closed",1); + s->tobeclosed = 1; + s->broken = 1; + } + } else { + //drop the packet + ; + } + } + } else if (s->ssl) { + send_ssl_backlog_buffers(s); + ret = ssl_send( + s, + (s08bits*) ioa_network_buffer_data(nbh), + ioa_network_buffer_get_size(nbh), + ((s->e) && s->e->verbose)); + if (ret < 0) + s->tobeclosed = 1; + else if (ret == 0) + add_buffer_to_buffer_list( + &(s->bufs), + (s08bits*) ioa_network_buffer_data(nbh), + ioa_network_buffer_get_size(nbh)); + } else if (s->fd >= 0) { + + if (s->connected && !(s->parent_s)) { + dest_addr = NULL; /* ignore dest_addr */ + } else if (!dest_addr) { + dest_addr = &(s->remote_addr); + } + + ret = udp_send(s, + dest_addr, + (s08bits*) ioa_network_buffer_data(nbh),ioa_network_buffer_get_size(nbh)); + if (ret < 0) { + s->tobeclosed = 1; +#if defined(EADDRNOTAVAIL) + int perr=errno; +#endif + perror("udp send"); +#if defined(EADDRNOTAVAIL) + if(dest_addr && (perr==EADDRNOTAVAIL)) { + char sfrom[129]; + addr_to_string(&(s->local_addr), (u08bits*)sfrom); + char sto[129]; + addr_to_string(dest_addr, (u08bits*)sto); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: network error: address unreachable from %s to %s\n", + __FUNCTION__,sfrom,sto); + } +#endif + } + } + } + } + } + } + + ioa_network_buffer_delete(s->e, nbh); + + return ret; +} + +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) { + + if (event_type & IOA_EV_READ) { + + if(e) + s->e = e; + + if(s->e && !(s->parent_s)) { + + switch(s->st) { + case DTLS_SOCKET: + case UDP_SOCKET: + if(s->read_event) { + if(!clean_preexisting) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: software error: buffer preset 1\n", __FUNCTION__); + return -1; + } + } else { + s->read_event = event_new(s->e->event_base,s->fd, EV_READ|EV_PERSIST, socket_input_handler, s); + event_add(s->read_event,NULL); + } + break; + case TENTATIVE_TCP_SOCKET: + if(s->bev) { + if(!clean_preexisting) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: software error: buffer preset 2\n", __FUNCTION__); + return -1; + } + } else if(s->read_event) { + if(!clean_preexisting) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: software error: buffer preset 3\n", __FUNCTION__); + return -1; + } + } else { + s->read_event = event_new(s->e->event_base,s->fd, EV_READ|EV_PERSIST, socket_input_handler, s); + event_add(s->read_event,NULL); + } + break; + case TCP_SOCKET: + if(s->bev) { + if(!clean_preexisting) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: software error: buffer preset 4\n", __FUNCTION__); + return -1; + } + } else { + s->bev = bufferevent_socket_new(s->e->event_base, + s->fd, + BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + 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: + if(s->bev) { + if(!clean_preexisting) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: software error: buffer preset 5\n", __FUNCTION__); + return -1; + } + } else { +#if !defined(TURN_NO_TLS) + if(!(s->ssl)) { + //??? how we can get to this point ??? + s->ssl = SSL_new(e->tls_ctx_ssl23); + STRCPY(s->orig_ctx_type,"SSLv23"); + s->bev = bufferevent_openssl_socket_new(s->e->event_base, + s->fd, + s->ssl, + BUFFEREVENT_SSL_ACCEPTING, + BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + } else { + s->bev = bufferevent_openssl_socket_new(s->e->event_base, + s->fd, + s->ssl, + BUFFEREVENT_SSL_OPEN, + BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + } + 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. */ +#endif + } + break; + default: + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: software error: unknown socket type: %d\n", __FUNCTION__,(int)(s->st)); + return -1; + } + } + + s->read_cb = cb; + s->read_ctx = ctx; + return 0; + } + } + + /* unsupported event or else */ + return -1; +} + +int ioa_socket_tobeclosed(ioa_socket_handle s) +{ + if(s) { + if(s->magic != SOCKET_MAGIC) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s: magic is wrong on the socket: 0x%lx, st=%d, sat=%d\n",__FUNCTION__,(long)s,s->st,s->sat); + return 1; + } + + if(s->done) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s: ceck on already closed socket: 0x%lx, st=%d, sat=%d\n",__FUNCTION__,(long)s,s->st,s->sat); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s); + return 1; + } + if(s->broken) { + log_socket_event(s, "socket broken", 0); + return 1; + } else if(s->tobeclosed) { + log_socket_event(s, "socket to be closed", 0); + return 1; + } else if(s->fd < 0) { + log_socket_event(s, "socket fd<0", 0); + return 1; + } else if(s->ssl) { + if(SSL_get_shutdown(s->ssl)) { + log_socket_event(s, "socket SSL shutdown", 0); + return 1; + } + } + } + return 0; +} + +void set_ioa_socket_tobeclosed(ioa_socket_handle s) +{ + if(s) + s->tobeclosed = 1; +} + +static u32bits string_hash(const u08bits *str) { + + u32bits hash = 0; + int c = 0; + + while ((c = *str++)) + hash = c + (hash << 6) + (hash << 16) - hash; + + return hash; +} + +int check_username_hash(ioa_socket_handle s, u08bits *username, u08bits *realm) +{ + if(s) { + if(username && username[0]) { + if(s->username_hash != string_hash(username)) { + return 0; + } + } + if(realm && realm[0]) { + if(s->realm_hash != string_hash(realm)) { + return 0; + } + } + } + return 1; +} + +void set_username_hash(ioa_socket_handle s, u08bits *username, u08bits *realm) +{ + if(s) { + if(username && username[0]) { + s->username_hash = string_hash(username); + } + if(realm && realm[0]) { + s->realm_hash = string_hash(realm); + } + } +} + +/* + * Network buffer functions + */ +ioa_network_buffer_handle ioa_network_buffer_allocate(ioa_engine_handle e) +{ + stun_buffer_list_elem *buf_elem = new_blist_elem(e); + buf_elem->buf.len = 0; + buf_elem->buf.offset = 0; + buf_elem->buf.coffset = 0; + return buf_elem; +} + +/* We do not use special header in this simple implementation */ +void ioa_network_buffer_header_init(ioa_network_buffer_handle nbh) +{ + UNUSED_ARG(nbh); +} + +u08bits *ioa_network_buffer_data(ioa_network_buffer_handle nbh) +{ + stun_buffer_list_elem *buf_elem = (stun_buffer_list_elem *)nbh; + return buf_elem->buf.buf + buf_elem->buf.offset - buf_elem->buf.coffset; +} + +size_t ioa_network_buffer_get_size(ioa_network_buffer_handle nbh) +{ + if(!nbh) + return 0; + else { + stun_buffer_list_elem *buf_elem = (stun_buffer_list_elem *)nbh; + return (size_t)(buf_elem->buf.len); + } +} + +size_t ioa_network_buffer_get_capacity(ioa_network_buffer_handle nbh) +{ + if(!nbh) + return 0; + else { + stun_buffer_list_elem *buf_elem = (stun_buffer_list_elem *)nbh; + if(buf_elem->buf.offset < STUN_BUFFER_SIZE) { + return (STUN_BUFFER_SIZE - buf_elem->buf.offset); + } + return 0; + } +} + +size_t ioa_network_buffer_get_capacity_udp(void) +{ + return UDP_STUN_BUFFER_SIZE; +} + +void ioa_network_buffer_set_size(ioa_network_buffer_handle nbh, size_t len) +{ + stun_buffer_list_elem *buf_elem = (stun_buffer_list_elem *)nbh; + buf_elem->buf.len=(size_t)len; +} + +void ioa_network_buffer_add_offset_size(ioa_network_buffer_handle nbh, u16bits offset, u08bits coffset, size_t len) +{ + stun_buffer_list_elem *buf_elem = (stun_buffer_list_elem *)nbh; + buf_elem->buf.len=(size_t)len; + buf_elem->buf.offset += offset; + buf_elem->buf.coffset += coffset; + + if((buf_elem->buf.offset + buf_elem->buf.len - buf_elem->buf.coffset)>=sizeof(buf_elem->buf.buf) || + (buf_elem->buf.offset + sizeof(buf_elem->buf.channel) < buf_elem->buf.coffset) + ) { + buf_elem->buf.coffset = 0; + buf_elem->buf.len = 0; + buf_elem->buf.offset = 0; + } +} + +u16bits ioa_network_buffer_get_offset(ioa_network_buffer_handle nbh) +{ + stun_buffer_list_elem *buf_elem = (stun_buffer_list_elem *)nbh; + return buf_elem->buf.offset; +} + +u08bits ioa_network_buffer_get_coffset(ioa_network_buffer_handle nbh) +{ + stun_buffer_list_elem *buf_elem = (stun_buffer_list_elem *)nbh; + return buf_elem->buf.coffset; +} + +void ioa_network_buffer_delete(ioa_engine_handle e, ioa_network_buffer_handle nbh) { + stun_buffer_list_elem *buf_elem = (stun_buffer_list_elem *)nbh; + free_blist_elem(e,buf_elem); +} + +/////////// REPORTING STATUS ///////////////////// + +void turn_report_allocation_set(void *a, turn_time_t lifetime, int refresh) +{ + if(a) { + ts_ur_super_session *ss = (ts_ur_super_session*)(((allocation*)a)->owner); + if(ss) { + const char* status="new"; + if(refresh) + status="refreshed"; + turn_turnserver *server = (turn_turnserver*)ss->server; + if(server) { + ioa_engine_handle e = turn_server_get_engine(server); + if(e && e->verbose) { + if(ss->client_session.s->ssl) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: %s, realm=<%s>, username=<%s>, lifetime=%lu, cipher=%s, method=%s (%s)\n", (unsigned long long)ss->id, status, (char*)ss->realm_options.name, (char*)ss->username, (unsigned long)lifetime, SSL_get_cipher(ss->client_session.s->ssl), + turn_get_ssl_method(ss->client_session.s->ssl, ss->client_session.s->orig_ctx_type),ss->client_session.s->orig_ctx_type); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: %s, realm=<%s>, username=<%s>, lifetime=%lu\n", (unsigned long long)ss->id, status, (char*)ss->realm_options.name, (char*)ss->username, (unsigned long)lifetime); + } + } +#if !defined(TURN_NO_HIREDIS) + { + char key[1024]; + if(ss->realm_options.name[0]) { + snprintf(key,sizeof(key),"turn/realm/%s/user/%s/allocation/%018llu/status",ss->realm_options.name,(char*)ss->username, (unsigned long long)ss->id); + } else { + snprintf(key,sizeof(key),"turn/user/%s/allocation/%018llu/status",(char*)ss->username, (unsigned long long)ss->id); + } + send_message_to_redis(e->rch, "set", key, "%s lifetime=%lu", status, (unsigned long)lifetime); + send_message_to_redis(e->rch, "publish", key, "%s lifetime=%lu", status, (unsigned long)lifetime); + } +#endif + } + } + } +} + +void turn_report_allocation_delete(void *a) +{ + if(a) { + ts_ur_super_session *ss = (ts_ur_super_session*)(((allocation*)a)->owner); + if(ss) { + turn_turnserver *server = (turn_turnserver*)ss->server; + if(server) { + ioa_engine_handle e = turn_server_get_engine(server); + if(e && e->verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: delete: realm=<%s>, username=<%s>\n", (unsigned long long)ss->id, (char*)ss->realm_options.name, (char*)ss->username); + } +#if !defined(TURN_NO_HIREDIS) + { + char key[1024]; + if(ss->realm_options.name[0]) { + snprintf(key,sizeof(key),"turn/realm/%s/user/%s/allocation/%018llu/status",ss->realm_options.name,(char*)ss->username, (unsigned long long)ss->id); + } else { + snprintf(key,sizeof(key),"turn/user/%s/allocation/%018llu/status",(char*)ss->username, (unsigned long long)ss->id); + } + send_message_to_redis(e->rch, "del", key, ""); + send_message_to_redis(e->rch, "publish", key, "deleted"); + } +#endif + } + } + } +} + +void turn_report_session_usage(void *session) +{ + if(session) { + ts_ur_super_session *ss = (ts_ur_super_session *)session; + turn_turnserver *server = (turn_turnserver*)ss->server; + if(server && (ss->received_packets || ss->sent_packets)) { + ioa_engine_handle e = turn_server_get_engine(server); + if(((ss->received_packets+ss->sent_packets)&2047)==0) { + if(e && e->verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: usage: realm=<%s>, username=<%s>, rp=%lu, rb=%lu, sp=%lu, sb=%lu\n", (unsigned long long)(ss->id), (char*)ss->realm_options.name, (char*)ss->username, (unsigned long)(ss->received_packets), (unsigned long)(ss->received_bytes),(unsigned long)(ss->sent_packets),(unsigned long)(ss->sent_bytes)); + } +#if !defined(TURN_NO_HIREDIS) + { + char key[1024]; + if(ss->realm_options.name[0]) { + snprintf(key,sizeof(key),"turn/realm/%s/user/%s/allocation/%018llu/traffic",ss->realm_options.name,(char*)ss->username, (unsigned long long)(ss->id)); + } else { + snprintf(key,sizeof(key),"turn/user/%s/allocation/%018llu/traffic",(char*)ss->username, (unsigned long long)(ss->id)); + } + send_message_to_redis(e->rch, "publish", key, "rcvp=%lu, rcvb=%lu, sentp=%lu, sentb=%lu",(unsigned long)(ss->received_packets), (unsigned long)(ss->received_bytes),(unsigned long)(ss->sent_packets),(unsigned long)(ss->sent_bytes)); + } +#endif + ss->t_received_packets += ss->received_packets; + ss->t_received_bytes += ss->received_bytes; + ss->t_sent_packets += ss->sent_packets; + ss->t_sent_bytes += ss->sent_bytes; + + { + turn_time_t ct = get_turn_server_time(server); + if(ct != ss->start_time) { + ct = ct - ss->start_time; + ss->received_rate = (u32bits)(ss->t_received_bytes / ct); + ss->sent_rate = (u32bits)(ss->t_sent_bytes / ct); + ss->total_rate = ss->received_rate + ss->sent_rate; + } + } + + report_turn_session_info(server,ss,0); + + ss->received_packets=0; + ss->received_bytes=0; + ss->sent_packets=0; + ss->sent_bytes=0; + } + } + } +} + +/////////////// SSL /////////////////// + + +const char* get_ioa_socket_tls_cipher(ioa_socket_handle s) +{ + if(s && (s->ssl)) + return SSL_get_cipher(s->ssl); + return ""; +} + +const char* get_ioa_socket_tls_method(ioa_socket_handle s) +{ + if(s && (s->ssl)) + return turn_get_ssl_method(s->ssl,"UNKNOWN"); + return ""; +} + +///////////// Super Memory Region ////////////// + +#define TURN_SM_SIZE (1024<<11) + +struct _super_memory { + pthread_mutex_t mutex_sm; + char **super_memory; + size_t *sm_allocated; + size_t sm_total_sz; + size_t sm_chunk; + u32bits id; +}; + +static void init_super_memory_region(super_memory_t *r) +{ + if(r) { + ns_bzero(r,sizeof(super_memory_t)); + + r->super_memory = (char**)malloc(sizeof(char*)); + r->super_memory[0] = (char*)malloc(TURN_SM_SIZE); + ns_bzero(r->super_memory[0],TURN_SM_SIZE); + + r->sm_allocated = (size_t*)malloc(sizeof(size_t*)); + r->sm_allocated[0] = 0; + + r->sm_total_sz = TURN_SM_SIZE; + r->sm_chunk = 0; + + while(r->id == 0) + r->id = (u32bits)random(); + + pthread_mutex_init(&r->mutex_sm, NULL); + } +} + +void init_super_memory(void) +{ + ; +} + +super_memory_t* new_super_memory_region(void) +{ + super_memory_t* r = (super_memory_t*)malloc(sizeof(super_memory_t)); + init_super_memory_region(r); + return r; +} + +void* allocate_super_memory_region_func(super_memory_t *r, size_t size, const char* file, const char* func, int line) +{ + UNUSED_ARG(file); + UNUSED_ARG(func); + UNUSED_ARG(line); + + if(!r) + return malloc(size); + + void *ret = NULL; + + pthread_mutex_lock(&r->mutex_sm); + + size = ((size_t)((size+sizeof(void*))/(sizeof(void*)))) * sizeof(void*); + + if(size>=TURN_SM_SIZE) { + + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"(%s:%s:%d): Size too large for super memory: region id = %u, chunk=%lu, total=%lu, allocated=%lu, want=%lu\n",file,func,line,(unsigned int)r->id, (unsigned long)r->sm_chunk, (unsigned long)r->sm_total_sz, (unsigned long)r->sm_allocated[r->sm_chunk],(unsigned long)size); + + } else { + + size_t i = 0; + char *region = NULL; + size_t *rsz = NULL; + for(i=0;i<=r->sm_chunk;++i) { + + size_t left = (size_t)r->sm_total_sz - r->sm_allocated[i]; + + if(leftsuper_memory[i]; + rsz = r->sm_allocated + i; + break; + } + } + + if(!region) { + r->sm_chunk += 1; + r->super_memory = (char**)realloc(r->super_memory,(r->sm_chunk+1) * sizeof(char*)); + r->super_memory[r->sm_chunk] = (char*)malloc(TURN_SM_SIZE); + ns_bzero(r->super_memory[r->sm_chunk],TURN_SM_SIZE); + r->sm_allocated = (size_t*)realloc(r->sm_allocated,(r->sm_chunk+1) * sizeof(size_t*)); + r->sm_allocated[r->sm_chunk] = 0; + region = r->super_memory[r->sm_chunk]; + rsz = r->sm_allocated + r->sm_chunk; + } + + { + char* ptr = region + *rsz; + + ns_bzero(ptr, size); + + *rsz += size; + + ret = ptr; + } + } + + pthread_mutex_unlock(&r->mutex_sm); + + if(!ret) + ret = malloc(size); + + return ret; +} + +void* allocate_super_memory_engine_func(ioa_engine_handle e, size_t size, const char* file, const char* func, int line) +{ + if(e) + return allocate_super_memory_region_func(e->sm,size,file,func,line); + return allocate_super_memory_region_func(NULL,size,file,func,line); +} + +////////////////////////////////////////////////// diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h new file mode 100644 index 00000000..3fe3529f --- /dev/null +++ b/src/apps/relay/ns_ioalib_impl.h @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +/* + * IO Abstraction library + */ + +#ifndef __IOA_LIBIMPL__ +#define __IOA_LIBIMPL__ + +#include +#include +#include + +#include + +#include + +#include "ns_turn_ioalib.h" +#include "turn_ports.h" +#include "ns_turn_maps_rtcp.h" +#include "ns_turn_maps.h" +#include "ns_turn_server.h" + +#include "apputils.h" +#include "stun_buffer.h" +#include "userdb.h" + +#include "ns_sm.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////////////////////////////// + +#define MAX_BUFFER_QUEUE_SIZE_PER_ENGINE (64) +#define MAX_SOCKET_BUFFER_BACKLOG (16) + +#define BUFFEREVENT_HIGH_WATERMARK (128<<10) +#define BUFFEREVENT_MAX_UDP_TO_TCP_WRITE (64<<9) +#define BUFFEREVENT_MAX_TCP_TO_TCP_WRITE (192<<10) + +typedef struct _stun_buffer_list_elem { + struct _stun_buffer_list_elem *next; + stun_buffer buf; +} stun_buffer_list_elem; + +typedef struct _stun_buffer_list { + stun_buffer_list_elem *head; + size_t tsz; +} stun_buffer_list; + +typedef vint band_limit_t; + +/* + * New connection callback + */ + +struct cb_socket_message { + turnserver_id id; + tcp_connection_id connection_id; + stun_tid tid; + ioa_socket_handle s; + int message_integrity; +}; + +struct relay_server { + turnserver_id id; + super_memory_t* sm; + struct event_base* event_base; + struct bufferevent *in_buf; + struct bufferevent *out_buf; + struct bufferevent *auth_in_buf; + struct bufferevent *auth_out_buf; + ioa_engine_handle ioa_eng; + turn_turnserver server; + pthread_t thr; +}; + +struct message_to_relay { + MESSAGE_TO_RELAY_TYPE t; + struct relay_server *relay_server; + union { + struct socket_message sm; + struct cb_socket_message cb_sm; + } m; +}; + +struct relay_server; +typedef struct relay_server *relay_server_handle; + +typedef int (*ioa_engine_new_connection_event_handler)(ioa_engine_handle e, struct message_to_relay *sm); +typedef int (*ioa_engine_udp_event_handler)(relay_server_handle rs, struct message_to_relay *sm); + +#define TURN_CMSG_SZ (65536) + +#define PREDEF_TIMERS_NUM (14) +extern const int predef_timer_intervals[PREDEF_TIMERS_NUM]; + +struct _ioa_engine +{ + super_memory_t *sm; + struct event_base *event_base; + int deallocate_eb; + int verbose; + turnipports* tp; + rtcp_map *map_rtcp; + stun_buffer_list bufs; + SSL_CTX *tls_ctx_ssl23; + SSL_CTX *tls_ctx_v1_0; +#if defined(SSL_TXT_TLSV1_1) + SSL_CTX *tls_ctx_v1_1; +#if defined(SSL_TXT_TLSV1_2) + SSL_CTX *tls_ctx_v1_2; +#endif +#endif + SSL_CTX *dtls_ctx; + turn_time_t jiffie; /* bandwidth check interval */ + band_limit_t max_bpj; + ioa_timer_handle timer_ev; + s08bits cmsg[TURN_CMSG_SZ+1]; + int predef_timer_intervals[PREDEF_TIMERS_NUM]; + struct timeval predef_timers[PREDEF_TIMERS_NUM]; + /* Relays */ + s08bits relay_ifname[1025]; + int default_relays; + size_t relays_number; + size_t relay_addr_counter; + ioa_addr *relay_addrs; +#if !defined(TURN_NO_HIREDIS) + redis_context_handle rch; +#endif +}; + +#define SOCKET_MAGIC (0xABACADEF) + +struct _ioa_socket +{ + evutil_socket_t fd; + struct _ioa_socket *parent_s; + void *listener_server; + u32bits magic; + ur_addr_map *sockets_container; /* relay container for UDP sockets */ + struct bufferevent *bev; + ioa_network_buffer_handle defer_nbh; + int family; + SOCKET_TYPE st; + SOCKET_APP_TYPE sat; + SSL* ssl; + char orig_ctx_type[16]; + int bound; + int local_addr_known; + ioa_addr local_addr; + int connected; + ioa_addr remote_addr; + ioa_engine_handle e; + struct event *read_event; + ioa_net_event_handler read_cb; + void *read_ctx; + int done; + ts_ur_super_session* session; + int current_df_relay_flag; + /* RFC6156: if IPv6 is involved, do not use DF: */ + int do_not_use_df; + int tobeclosed; + int broken; + int default_ttl; + int current_ttl; + int default_tos; + int current_tos; + stun_buffer_list bufs; + turn_time_t jiffie; /* bandwidth check interval */ + band_limit_t jiffie_bytes_read; + band_limit_t jiffie_bytes_write; + /* RFC 6062 ==>> */ + //Connection session: + tcp_connection *sub_session; + //Connect: + struct bufferevent *conn_bev; + connect_cb conn_cb; + void *conn_arg; + //Transferable sockets user data + u32bits username_hash; + u32bits realm_hash; + //Accept: + struct evconnlistener *list_ev; + accept_cb acb; + void *acbarg; + /* <<== RFC 6062 */ +}; + +typedef struct _timer_event +{ + struct event *ev; + ioa_engine_handle e; + ioa_timer_event_handler cb; + void *ctx; + s08bits* txt; +} timer_event; + +/////////////////////////////////// + +/* realm */ + +void create_new_realm(char* name); +int get_realm_data(char* name, realm_params_t* rp); + +/* engine handling */ + +ioa_engine_handle create_ioa_engine(super_memory_t *sm, + struct event_base *eb, turnipports* tp, + const s08bits* relay_if, + size_t relays_number, s08bits **relay_addrs, int default_relays, + int verbose, band_limit_t max_bps +#if !defined(TURN_NO_HIREDIS) + ,const char* redis_report_connection_string +#endif + ); + +void set_ssl_ctx(ioa_engine_handle e, + SSL_CTX *tls_ctx_ssl23, + SSL_CTX *tls_ctx_v1_0, +#if defined(SSL_TXT_TLSV1_1) + SSL_CTX *tls_ctx_v1_1, +#if defined(SSL_TXT_TLSV1_2) + SSL_CTX *tls_ctx_v1_2, +#endif +#endif + SSL_CTX *dtls_ctx); + +void ioa_engine_set_rtcp_map(ioa_engine_handle e, rtcp_map *rtcpmap); + +ioa_socket_handle create_ioa_socket_from_fd(ioa_engine_handle e, ioa_socket_raw fd, ioa_socket_handle parent_s, SOCKET_TYPE st, SOCKET_APP_TYPE sat, const ioa_addr *remote_addr, const ioa_addr *local_addr); +ioa_socket_handle create_ioa_socket_from_ssl(ioa_engine_handle e, ioa_socket_handle parent_s, SSL* ssl, SOCKET_TYPE st, SOCKET_APP_TYPE sat, const ioa_addr *remote_addr, const ioa_addr *local_addr); + +int get_a_local_relay(int family, ioa_addr *relay_addr); + +void add_socket_to_parent(ioa_socket_handle parent_s, ioa_socket_handle s); +void delete_socket_from_parent(ioa_socket_handle s); + +void add_socket_to_map(ioa_socket_handle s, ur_addr_map *amap); +void delete_socket_from_map(ioa_socket_handle s); + +int is_connreset(void); +int would_block(void); +int udp_send(ioa_socket_handle s, const ioa_addr* dest_addr, const s08bits* buffer, int len); +int udp_recvfrom(evutil_socket_t fd, ioa_addr* orig_addr, const ioa_addr *like_addr, s08bits* buffer, int buf_size, int *ttl, int *tos, s08bits *ecmsg, int flags, u32bits *errcode); +int ssl_read(evutil_socket_t fd, SSL* ssl, ioa_network_buffer_handle nbh, int verbose); + +int set_raw_socket_ttl_options(evutil_socket_t fd, int family); +int set_raw_socket_tos_options(evutil_socket_t fd, int family); + +int set_socket_options_fd(evutil_socket_t fd, int tcp, int family); +int set_socket_options(ioa_socket_handle s); + +///////////////////////// SUPER MEMORY //////// + +#define allocate_super_memory_engine(e,size) allocate_super_memory_engine_func(e, size, __FILE__, __FUNCTION__, __LINE__) +void* allocate_super_memory_engine_func(ioa_engine_handle e, size_t size, const char* file, const char* func, int line); + +///////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* __IOA_LIBIMPL__ */ diff --git a/src/apps/relay/ns_sm.h b/src/apps/relay/ns_sm.h new file mode 100644 index 00000000..dfa366e8 --- /dev/null +++ b/src/apps/relay/ns_sm.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +/* + * IO Abstraction library + */ + +#ifndef __IOA_SM__ +#define __IOA_SM__ + +#include "ns_turn_ioalib.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////////////////////////////// + +struct _super_memory; +typedef struct _super_memory super_memory_t; + +////////////////////////////////////////////////////// + +void init_super_memory(void); + +super_memory_t* new_super_memory_region(void); + +#define allocate_super_memory_region(region,size) allocate_super_memory_region_func(region, size, __FILE__, __FUNCTION__, __LINE__) +void* allocate_super_memory_region_func(super_memory_t *region, size_t size, const char* file, const char* func, int line); + +///////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* __IOA_SM__ */ diff --git a/src/apps/relay/tls_listener.c b/src/apps/relay/tls_listener.c new file mode 100644 index 00000000..f887f166 --- /dev/null +++ b/src/apps/relay/tls_listener.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "apputils.h" +#include "mainrelay.h" + +#include "ns_turn_utils.h" + +#include "tls_listener.h" +#include "ns_ioalib_impl.h" + +#include + +/////////////////////////////////////////////////// + +#define FUNCSTART if(server && eve(server->verbose)) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s:%d:start\n",__FUNCTION__,__LINE__) +#define FUNCEND if(server && eve(server->verbose)) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s:%d:end\n",__FUNCTION__,__LINE__) + +struct tls_listener_relay_server_info +{ + char ifname[1025]; + ioa_addr addr; + ioa_engine_handle e; + int verbose; + struct evconnlistener *l; + struct message_to_relay sm; + ioa_engine_new_connection_event_handler connect_cb; + struct relay_server *relay_server; +}; + +/////////////// io handlers /////////////////// + +static void server_input_handler(struct evconnlistener *l, evutil_socket_t fd, + struct sockaddr *sa, int socklen, void *arg) +{ + + UNUSED_ARG(l); + + tls_listener_relay_server_type * server = (tls_listener_relay_server_type*) arg; + + if(!(server->connect_cb)) { + socket_closesocket(fd); + return; + } + + FUNCSTART; + + if (!server) + return; + + ns_bcopy(sa,&(server->sm.m.sm.nd.src_addr),socklen); + + addr_debug_print(server->verbose, &(server->sm.m.sm.nd.src_addr),"tcp or tls connected to"); + + SOCKET_TYPE st = TENTATIVE_TCP_SOCKET; + + if(turn_params.no_tls) + st = TCP_SOCKET; + else if(turn_params.no_tcp) + st = TLS_SOCKET; + + ioa_socket_handle ioas = + create_ioa_socket_from_fd( + server->e, + fd, + NULL, + st, + CLIENT_SOCKET, + &(server->sm.m.sm.nd.src_addr), + &(server->addr)); + + if (ioas) { + + ioas->listener_server = server; + + server->sm.m.sm.nd.recv_ttl = TTL_IGNORE; + server->sm.m.sm.nd.recv_tos = TOS_IGNORE; + server->sm.m.sm.nd.nbh = NULL; + server->sm.m.sm.s = ioas; + server->sm.relay_server = server->relay_server; + + int rc = server->connect_cb(server->e, &(server->sm)); + + if (rc < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Cannot create tcp or tls session\n"); + } + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Cannot create ioa_socket from FD\n"); + socket_closesocket(fd); + } + + FUNCEND ; +} + +///////////////////// operations ////////////////////////// + +static int create_server_listener(tls_listener_relay_server_type* server) { + + FUNCSTART; + + if(!server) return -1; + + evutil_socket_t tls_listen_fd = -1; + + tls_listen_fd = socket(server->addr.ss.sa_family, SOCK_STREAM, 0); + if (tls_listen_fd < 0) { + perror("socket"); + return -1; + } + + if(sock_bind_to_device(tls_listen_fd, (unsigned char*)server->ifname)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind listener socket to device %s\n",server->ifname); + } + + { + const int max_binding_time = 60; + int addr_bind_cycle = 0; + retry_addr_bind: + + if(addr_bind(tls_listen_fd,&server->addr,1)<0) { + perror("Cannot bind local socket to addr"); + char saddr[129]; + addr_to_string(&server->addr,(u08bits*)saddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,"Cannot bind TCP/TLS listener socket to addr %s\n",saddr); + if(addr_bind_cycle++l = evconnlistener_new(server->e->event_base, + server_input_handler, server, + LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, + 1024, tls_listen_fd); + + if(!(server->l)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot create TLS listener\n"); + socket_closesocket(tls_listen_fd); + return -1; + } + + if(!turn_params.no_tcp && !turn_params.no_tls) + addr_debug_print(server->verbose, &server->addr,"TCP/TLS listener opened on "); + else if(!turn_params.no_tls) + addr_debug_print(server->verbose, &server->addr,"TLS listener opened on "); + else if(!turn_params.no_tcp) + addr_debug_print(server->verbose, &server->addr,"TCP listener opened on "); + + FUNCEND; + + return 0; +} + +static int init_server(tls_listener_relay_server_type* server, + const char* ifname, + const char *local_address, + int port, + int verbose, + ioa_engine_handle e, + ioa_engine_new_connection_event_handler send_socket, + struct relay_server *relay_server) { + + if(!server) return -1; + + server->connect_cb = send_socket; + server->relay_server = relay_server; + + if(ifname) STRCPY(server->ifname,ifname); + + if(make_ioa_addr((const u08bits*)local_address, port, &server->addr)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot create a TCP/TLS listener for address: %s\n",local_address); + return -1; + } + + server->verbose=verbose; + + server->e = e; + + return create_server_listener(server); +} + +/////////////////////////////////////////////////////////// + + +tls_listener_relay_server_type* create_tls_listener_server(const char* ifname, + const char *local_address, int port, int verbose, + ioa_engine_handle e, + ioa_engine_new_connection_event_handler send_socket, + struct relay_server *relay_server) +{ + + tls_listener_relay_server_type* server = + (tls_listener_relay_server_type*) allocate_super_memory_engine(e,sizeof(tls_listener_relay_server_type)); + + if (init_server(server, ifname, local_address, port, verbose, e, + send_socket, relay_server) < 0) { + return NULL ; + } else { + return server; + } +} + +////////////////////////////////////////////////////////////////// diff --git a/src/apps/relay/tls_listener.h b/src/apps/relay/tls_listener.h new file mode 100644 index 00000000..fda420a1 --- /dev/null +++ b/src/apps/relay/tls_listener.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011, 2012, 2013 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 __TLS_LISTENER__ +#define __TLS_LISTENER__ + +#include + +#include "ns_turn_utils.h" + +#include "ns_ioalib_impl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////// + +struct tls_listener_relay_server_info; +typedef struct tls_listener_relay_server_info tls_listener_relay_server_type; + +/////////////////////////////////////////// + +tls_listener_relay_server_type* create_tls_listener_server(const char* ifname, + const char *local_address, int port, int verbose, + ioa_engine_handle e, + ioa_engine_new_connection_event_handler send_socket, + struct relay_server *relay_server); + +/////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__TLS_LISTENER__ diff --git a/src/apps/relay/turn_ports.c b/src/apps/relay/turn_ports.c new file mode 100644 index 00000000..9db5a928 --- /dev/null +++ b/src/apps/relay/turn_ports.c @@ -0,0 +1,417 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "ns_turn_maps.h" +#include "ns_turn_msg_defs.h" + +#include "ns_turn_ioalib.h" +#include "ns_ioalib_impl.h" + +#include "turn_ports.h" + +////////// DATA //////////////////////////////////////////// + +#define PORTS_SIZE (0xFFFF+1) +#define TPS_OUT_OF_RANGE ((u32bits)(-1)) +#define TPS_TAKEN_SINGLE ((u32bits)(-2)) +#define TPS_TAKEN_EVEN ((u32bits)(-3)) +#define TPS_TAKEN_ODD ((u32bits)(-4)) + +struct _turnports { + u32bits status[PORTS_SIZE]; + u32bits low; + u32bits high; + u16bits range_start; + u16bits range_stop; + u16bits ports[PORTS_SIZE]; + TURN_MUTEX_DECLARE(mutex) +}; +typedef struct _turnports turnports; + +/////////////// TURNPORTS statics ////////////////////////// + +static turnports* turnports_create(super_memory_t *sm, u16bits start, u16bits end); +static u16bits turnports_size(turnports* tp); + +static int turnports_allocate(turnports* tp); +static int turnports_allocate_even(turnports* tp, int allocate_rtcp, u64bits *reservation_token); + +static void turnports_release(turnports* tp, u16bits port); + +static int turnports_is_allocated(turnports* tp, u16bits port); +static int turnports_is_available(turnports* tp, u16bits port); + +/////////////// UTILS ////////////////////////////////////// + +static int is_taken(u32bits status) { + int ret = -1; + switch (status) { + case TPS_TAKEN_SINGLE : + case TPS_TAKEN_EVEN : + case TPS_TAKEN_ODD : + ret = 1; + break; + default: + ret = 0; + }; + return ret; +} + +static void turnports_randomize(turnports* tp) { + if(tp) { + unsigned int size=(unsigned int)(tp->high-tp->low); + unsigned int i=0; + unsigned int cycles=size*10; + for(i=0;ilow + (u16bits)(((unsigned long)random())%((unsigned long)size))); + u16bits port2 = (u16bits)(tp->low + (u16bits)(((unsigned long)random())%((unsigned long)size))); + if(port1!=port2) { + int pos1=tp->status[port1]; + int pos2=tp->status[port2]; + int tmp=(int)tp->status[port1]; + tp->status[port1]=tp->status[port2]; + tp->status[port2]=(u32bits)tmp; + tmp=(int)tp->ports[pos1]; + tp->ports[pos1]=tp->ports[pos2]; + tp->ports[pos2]=(u16bits)tmp; + } + } + } +} + +static void turnports_init(turnports* tp, u16bits start, u16bits end) { + + tp->low=start; + tp->high=((u32bits)end)+1; + + tp->range_start=start; + tp->range_stop=end; + + int i=0; + for(i=0;istatus[i]=TPS_OUT_OF_RANGE; + tp->ports[i]=(u16bits)i; + } + for(i=start;i<=end;i++) { + tp->status[i]=(u32bits)i; + tp->ports[i]=(u16bits)i; + } + for(i=((int)end)+1;istatus[i]=TPS_OUT_OF_RANGE; + tp->ports[i]=(u16bits)i; + } + + turnports_randomize(tp); + + TURN_MUTEX_INIT_RECURSIVE(&(tp->mutex)); +} + +/////////////// FUNC /////////////////////////////////////// + +turnports* turnports_create(super_memory_t *sm, u16bits start, u16bits end) { + + if(start>end) return NULL; + + turnports* ret=(turnports*)allocate_super_memory_region(sm, sizeof(turnports)); + turnports_init(ret,start,end); + + return ret; +} + +u16bits turnports_size(turnports* tp) { + if(!tp) return 0; + else { + TURN_MUTEX_LOCK(&tp->mutex); + u16bits ret = (u16bits)((tp->high-tp->low)); + TURN_MUTEX_UNLOCK(&tp->mutex); + return ret; + } +} + +int turnports_allocate(turnports* tp) { + + int port=-1; + + TURN_MUTEX_LOCK(&tp->mutex); + + if(tp) { + + while(1) { + + if(tp->high <= tp->low) { + TURN_MUTEX_UNLOCK(&tp->mutex); + return -1; + } + + int position=(u16bits)(tp->low & 0x0000FFFF); + + port=(int)tp->ports[position]; + if(port<(int)(tp->range_start) || port>((int)(tp->range_stop))) { + TURN_MUTEX_UNLOCK(&tp->mutex); + return -1; + } + if(is_taken(tp->status[port])) { + ++(tp->low); + continue; + } + if(tp->status[port]!=tp->low) { + ++(tp->low); + continue; + } + tp->status[port]=TPS_TAKEN_SINGLE; + ++(tp->low); + break; + } + } + + TURN_MUTEX_UNLOCK(&tp->mutex); + + return port; +} + +void turnports_release(turnports* tp, u16bits port) { + TURN_MUTEX_LOCK(&tp->mutex); + if(tp && port>=tp->range_start && port<=tp->range_stop) { + u16bits position=(u16bits)(tp->high & 0x0000FFFF); + if(is_taken(tp->status[port])) { + tp->status[port]=tp->high; + tp->ports[position]=port; + ++(tp->high); + } + } + TURN_MUTEX_UNLOCK(&tp->mutex); +} + +int turnports_allocate_even(turnports* tp, int allocate_rtcp, u64bits *reservation_token) { + if(tp) { + TURN_MUTEX_LOCK(&tp->mutex); + u16bits size = turnports_size(tp); + if(size>1) { + u16bits i=0; + for(i=0;imutex); + return port; + } else { + int rtcp_port=port+1; + if(rtcp_port>tp->range_stop) { + turnports_release(tp,port); + } else if(!turnports_is_available(tp,rtcp_port)) { + turnports_release(tp,port); + } else { + tp->status[port]=TPS_TAKEN_EVEN; + tp->status[rtcp_port]=TPS_TAKEN_ODD; + if(reservation_token) { + u16bits *v16=(u16bits*)reservation_token; + u32bits *v32=(u32bits*)reservation_token; + v16[0]=(u16bits)(tp->ports[(u16bits)(tp->low & 0x0000FFFF)]); + v16[1]=(u16bits)(tp->ports[(u16bits)(tp->high & 0x0000FFFF)]); + v32[1]=(u32bits)turn_random(); + } + TURN_MUTEX_UNLOCK(&tp->mutex); + return port; + } + } + } + } + } + TURN_MUTEX_UNLOCK(&tp->mutex); + } + return -1; +} + +int turnports_is_allocated(turnports* tp, u16bits port) { + if(!tp) return 0; + else { + TURN_MUTEX_LOCK(&tp->mutex); + int ret = is_taken(tp->status[port]); + TURN_MUTEX_UNLOCK(&tp->mutex); + return ret; + } +} + +int turnports_is_available(turnports* tp, u16bits port) { + if(tp) { + TURN_MUTEX_LOCK(&tp->mutex); + u32bits status = tp->status[port]; + if((status!=TPS_OUT_OF_RANGE) && !is_taken(status)) { + u16bits position=(u16bits)(status & 0x0000FFFF); + if(tp->ports[position]==port) { + TURN_MUTEX_UNLOCK(&tp->mutex); + return 1; + } + } + TURN_MUTEX_UNLOCK(&tp->mutex); + } + return 0; +} + +/////////////////// IP-mapped PORTS ///////////////////////////////////// + +struct _turnipports +{ + super_memory_t *sm; + u16bits start; + u16bits end; + ur_addr_map ip_to_turnports_udp; + ur_addr_map ip_to_turnports_tcp; + TURN_MUTEX_DECLARE(mutex) +}; + +////////////////////////////////////////////////// + +static ur_addr_map *get_map(turnipports *tp, u08bits transport) +{ + if(transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) + return &(tp->ip_to_turnports_tcp); + return &(tp->ip_to_turnports_udp); +} +////////////////////////////////////////////////// + +static turnipports* turnipports_singleton = NULL; + +turnipports* turnipports_create(super_memory_t *sm, u16bits start, u16bits end) +{ + turnipports *ret = (turnipports*) allocate_super_memory_region(sm, sizeof(turnipports)); + ret->sm = sm; + ur_addr_map_init(&(ret->ip_to_turnports_udp)); + ur_addr_map_init(&(ret->ip_to_turnports_tcp)); + ret->start = start; + ret->end = end; + TURN_MUTEX_INIT_RECURSIVE(&(ret->mutex)); + turnipports_singleton = ret; + return ret; +} + +static turnports* turnipports_add(turnipports* tp, u08bits transport, const ioa_addr *backend_addr) +{ + ur_addr_map_value_type t = 0; + if (tp && backend_addr) { + ioa_addr ba; + addr_cpy(&ba, backend_addr); + addr_set_port(&ba, 0); + TURN_MUTEX_LOCK((const turn_mutex*)&(tp->mutex)); + if (!ur_addr_map_get(get_map(tp, transport), &ba, &t)) { + t = (ur_addr_map_value_type) turnports_create(tp->sm, tp->start, tp->end); + ur_addr_map_put(get_map(tp, transport), &ba, t); + } + TURN_MUTEX_UNLOCK((const turn_mutex*)&(tp->mutex)); + } + return (turnports*) t; +} + +void turnipports_add_ip(u08bits transport, const ioa_addr *backend_addr) +{ + turnipports_add(turnipports_singleton, transport, backend_addr); +} + +int turnipports_allocate(turnipports* tp, u08bits transport, const ioa_addr *backend_addr) +{ + int ret = -1; + if (tp && backend_addr) { + TURN_MUTEX_LOCK((const turn_mutex*)&(tp->mutex)); + turnports *t = turnipports_add(tp, transport, backend_addr); + ret = turnports_allocate(t); + TURN_MUTEX_UNLOCK((const turn_mutex*)&(tp->mutex)); + } + return ret; +} + +int turnipports_allocate_even(turnipports* tp, const ioa_addr *backend_addr, int allocate_rtcp, + u64bits *reservation_token) +{ + int ret = -1; + if (tp && backend_addr) { + TURN_MUTEX_LOCK((const turn_mutex*)&(tp->mutex)); + turnports *t = turnipports_add(tp, STUN_ATTRIBUTE_TRANSPORT_UDP_VALUE, backend_addr); + ret = turnports_allocate_even(t, allocate_rtcp, reservation_token); + TURN_MUTEX_UNLOCK((const turn_mutex*)&(tp->mutex)); + } + return ret; +} + +void turnipports_release(turnipports* tp, u08bits transport, const ioa_addr *socket_addr) +{ + if (tp && socket_addr) { + ioa_addr ba; + ur_addr_map_value_type t; + addr_cpy(&ba, socket_addr); + addr_set_port(&ba, 0); + TURN_MUTEX_LOCK((const turn_mutex*)&(tp->mutex)); + if (ur_addr_map_get(get_map(tp, transport), &ba, &t)) { + turnports_release((turnports*) t, addr_get_port(socket_addr)); + } + TURN_MUTEX_UNLOCK((const turn_mutex*)&(tp->mutex)); + } +} + +int turnipports_is_allocated(turnipports* tp, u08bits transport, const ioa_addr *backend_addr, u16bits port) +{ + int ret = 0; + if (tp && backend_addr) { + ioa_addr ba; + ur_addr_map_value_type t; + addr_cpy(&ba, backend_addr); + addr_set_port(&ba, 0); + TURN_MUTEX_LOCK((const turn_mutex*)&(tp->mutex)); + if (ur_addr_map_get(get_map(tp,transport), &ba, &t)) { + ret = turnports_is_allocated((turnports*) t, port); + } + TURN_MUTEX_UNLOCK((const turn_mutex*)&(tp->mutex)); + } + return ret; +} + +int turnipports_is_available(turnipports* tp, u08bits transport, const ioa_addr *backend_addr, u16bits port) +{ + int ret = 0; + if (tp && backend_addr) { + ioa_addr ba; + ur_addr_map_value_type t; + addr_cpy(&ba, backend_addr); + addr_set_port(&ba, 0); + TURN_MUTEX_LOCK((const turn_mutex*)&(tp->mutex)); + if (!ur_addr_map_get(get_map(tp,transport), &ba, &t)) { + ret = 1; + } else { + ret = turnports_is_available((turnports*) t, port); + } + TURN_MUTEX_UNLOCK((const turn_mutex*)&(tp->mutex)); + } + return ret; +} + +////////////////////////////////////////////////////////////////// + + diff --git a/src/apps/relay/turn_ports.h b/src/apps/relay/turn_ports.h new file mode 100644 index 00000000..6b059afb --- /dev/null +++ b/src/apps/relay/turn_ports.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011, 2012, 2013 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_PORTS__ +#define __TURN_PORTS__ + +#include "ns_turn_ioaddr.h" + +#include "ns_sm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////////////////////////// + +#define LOW_DEFAULT_PORTS_BOUNDARY (49152) +#define HIGH_DEFAULT_PORTS_BOUNDARY (65535) + +////////////////////////////////////////////////// + +struct _turnipports; +typedef struct _turnipports turnipports; + +////////////////////////////////////////////////// + +turnipports* turnipports_create(super_memory_t *sm, u16bits start, u16bits end); + +void turnipports_add_ip(u08bits transport, const ioa_addr *backend_addr); + +int turnipports_allocate(turnipports* tp, u08bits transport, const ioa_addr *backend_addr); +int turnipports_allocate_even(turnipports* tp, const ioa_addr *backend_addr, + int allocate_rtcp, u64bits *reservation_token); + +void turnipports_release(turnipports* tp, u08bits transport, const ioa_addr *socket_addr); + +int turnipports_is_allocated(turnipports* tp, u08bits transport, const ioa_addr *backend_addr, u16bits port); +int turnipports_is_available(turnipports* tp, u08bits transport, const ioa_addr *backend_addr, u16bits port); + +////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__TURN_PORTS__ diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c new file mode 100644 index 00000000..ce1185bf --- /dev/null +++ b/src/apps/relay/turncli.c @@ -0,0 +1,1261 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "libtelnet.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include "userdb.h" +#include "mainrelay.h" + +#include "ns_turn_utils.h" + +#include "ns_turn_server.h" +#include "ns_turn_maps.h" + +#include "apputils.h" + +#include "turncli.h" + +/////////////////////////////// + +struct cli_server cliserver; + +int use_cli = 1; + +ioa_addr cli_addr; +int cli_addr_set = 0; + +int cli_port = CLI_DEFAULT_PORT; + +char cli_password[CLI_PASSWORD_LENGTH] = ""; + +int cli_max_output_sessions = DEFAULT_CLI_MAX_OUTPUT_SESSIONS; + +/////////////////////////////// + +struct cli_session { + evutil_socket_t fd; + int auth_completed; + size_t cmds; + struct bufferevent *bev; + ioa_addr addr; + telnet_t *ts; + FILE* f; + char realm[STUN_MAX_REALM_SIZE+1]; + char origin[STUN_MAX_ORIGIN_SIZE+1]; + realm_params_t *rp; +}; + +/////////////////////////////// + +#define CLI_PASSWORD_TRY_NUMBER (5) + +static const char *CLI_HELP_STR[] = + {"", + " ?, h, help - print this text", + "", + " quit, q, exit, bye - end CLI session", + "", + " stop, shutdown, halt - shutdown TURN Server", + "", + " pc - print configuration", + "", + " sr - set CLI session realm", + "", + " ur - unset CLI session realm", + "", + " so - set CLI session origin", + "", + " uo - unset CLI session origin", + "", + " tc - toggle a configuration parameter", + " (see pc command output for togglable param names)", + "", + " cc - change a configuration parameter", + " (see pc command output for changeable param names)", + "", + " ps [username] - print sessions, with optional exact user match", + "", + " psp - print sessions, with partial user string match", + "", + " psd - dump ps command output into file on the TURN server system", + "", + " pu [udp|tcp|dtls|tls]- print current users", + "", + " aas ip[:port} - add an alternate server reference", + " das ip[:port] - delete an alternate server reference", + " atas ip[:port] - add a TLS alternate server reference", + " dtas ip[:port] - delete a TLS alternate server reference", + "", + NULL}; + +static const char *CLI_GREETING_STR[] = { + "TURN Server", + TURN_SOFTWARE, + NULL}; + +static char CLI_CURSOR[] = "> "; + +static const telnet_telopt_t cli_telopts[] = { + { TELNET_TELOPT_ECHO, TELNET_WONT, TELNET_DONT }, + { TELNET_TELOPT_TTYPE, TELNET_WONT, TELNET_DONT }, + { TELNET_TELOPT_COMPRESS2, TELNET_WONT, TELNET_DONT }, + { TELNET_TELOPT_ZMP, TELNET_WONT, TELNET_DONT }, + { TELNET_TELOPT_MSSP, TELNET_WONT, TELNET_DONT }, + { TELNET_TELOPT_BINARY, TELNET_WONT, TELNET_DONT }, + { TELNET_TELOPT_NAWS, TELNET_WONT, TELNET_DONT }, + { -1, 0, 0 } + }; + +struct toggleable_command { + const char *cmd; + vintp data; +}; + +struct toggleable_command tcmds[] = { + {"stale-nonce",&turn_params.stale_nonce}, + {"stun-only",&turn_params.stun_only}, + {"no-stun",&turn_params.no_stun}, + {"secure-stun",&turn_params.secure_stun}, + {"no-udp-relay",&turn_params.no_udp_relay}, + {"no-tcp-relay",&turn_params.no_tcp_relay}, + {"no-multicast-peers",&turn_params.no_multicast_peers}, + {"no-loopback-peers",&turn_params.no_loopback_peers}, + {"mobility",&turn_params.mobility}, + {NULL,NULL} +}; + +/////////////////////////////// + +static void myprintf(struct cli_session *cs, const char *format, ...) +{ + if(cs && format) { + va_list args; + va_start (args, format); + if(cs->f) { + vfprintf(cs->f, format, args); + } else { + telnet_vprintf(cs->ts, format, args); + } + va_end (args); + } +} + +static void print_str_array(struct cli_session* cs, const char** sa) +{ + if(cs && sa) { + int i=0; + while(sa[i]) { + myprintf(cs,"%s\n",sa[i]); + i++; + } + } +} + +static const char* get_flag(int val) +{ + if(val) + return "ON"; + return "OFF"; +} + +static void cli_print_flag(struct cli_session* cs, int flag, const char* name, int changeable) +{ + if(cs && cs->ts && name) { + const char *sc=""; + if(changeable) + sc=" (*)"; + myprintf(cs," %s: %s%s\n",name,get_flag(flag),sc); + } +} + +static void cli_print_uint(struct cli_session* cs, unsigned long value, const char* name, int changeable) +{ + if(cs && cs->ts && name) { + const char *sc=""; + if(changeable==1) + sc=" (*)"; + else if(changeable==2) + sc=" (**)"; + myprintf(cs," %s: %lu%s\n",name,value,sc); + } +} + +static void cli_print_str(struct cli_session* cs, const char *value, const char* name, int changeable) +{ + if(cs && cs->ts && name && value) { + if(value[0] == 0) + value="empty"; + const char *sc=""; + if(changeable==1) + sc=" (*)"; + else if(changeable==2) + sc=" (**)"; + myprintf(cs," %s: %s%s\n",name,value,sc); + } +} + +static void cli_print_addr(struct cli_session* cs, ioa_addr *value, int use_port, const char* name, int changeable) +{ + if(cs && cs->ts && name && value) { + const char *sc=""; + if(changeable==1) + sc=" (*)"; + else if(changeable==2) + sc=" (**)"; + char s[256]; + if(!use_port) + addr_to_string_no_port(value,(u08bits*)s); + else + addr_to_string(value,(u08bits*)s); + myprintf(cs," %s: %s%s\n",name,s,sc); + } +} + +static void cli_print_addr_list(struct cli_session* cs, turn_server_addrs_list_t *value, int use_port, const char* name, int changeable) +{ + if(cs && cs->ts && name && value && value->size && value->addrs) { + const char *sc=""; + if(changeable==1) + sc=" (*)"; + else if(changeable==2) + sc=" (**)"; + char s[256]; + size_t i; + for(i=0;isize;i++) { + if(!use_port) + addr_to_string_no_port(&(value->addrs[i]),(u08bits*)s); + else + addr_to_string(&(value->addrs[i]),(u08bits*)s); + myprintf(cs," %s: %s%s\n",name,s,sc); + } + } +} + +static void cli_print_str_array(struct cli_session* cs, char **value, size_t sz, const char* name, int changeable) +{ + if(cs && cs->ts && name && value && sz) { + const char *sc=""; + if(changeable==1) + sc=" (*)"; + else if(changeable==2) + sc=" (**)"; + size_t i; + for(i=0;its && name && value && value->ranges_number && value->ranges) { + const char *sc=""; + if(changeable==1) + sc=" (*)"; + else if(changeable==2) + sc=" (**)"; + size_t i; + for(i=0;iranges_number;++i) { + if(value->ranges[i]) + myprintf(cs," %s: %s%s\n",name,value->ranges[i],sc); + } + } +} + +static void toggle_cli_param(struct cli_session* cs, const char* pn) +{ + if(cs && cs->ts && pn) { + + int i=0; + + while(tcmds[i].cmd && tcmds[i].data) { + if(strcmp(tcmds[i].cmd,pn) == 0) { + *(tcmds[i].data) = !(*(tcmds[i].data)); + cli_print_flag(cs,*(tcmds[i].data),tcmds[i].cmd,0); + return; + } + ++i; + } + + myprintf(cs, "\n"); + myprintf(cs, " Error: unknown or constant parameter: %s.\n",pn); + myprintf(cs, " You can toggle only the following parameters:\n"); + myprintf(cs, "\n"); + + i=0; + + while(tcmds[i].cmd && tcmds[i].data) { + cli_print_flag(cs,*(tcmds[i].data),tcmds[i].cmd,0); + ++i; + } + + myprintf(cs,"\n"); + } +} + +static void change_cli_param(struct cli_session* cs, const char* pn) +{ + if(cs && cs->ts && pn) { + + if(strstr(pn,"total-quota")==pn) { + int new_quota = change_total_quota(cs->realm, atoi(pn+strlen("total-quota"))); + cli_print_uint(cs,(unsigned long)new_quota,"total-quota",2); + return; + } else if(strstr(pn,"user-quota")==pn) { + int new_quota = change_user_quota(cs->realm, atoi(pn+strlen("user-quota"))); + cli_print_uint(cs,(unsigned long)new_quota,"user-quota",2); + return; + } else if(strstr(pn,"cli-max-output-sessions")==pn) { + cli_max_output_sessions = atoi(pn+strlen("cli-max-output-sessions")); + cli_print_uint(cs,(unsigned long)cli_max_output_sessions,"cli-max-output-sessions",2); + return; + } + + myprintf(cs, "\n"); + myprintf(cs, " Error: unknown or constant parameter: %s.\n",pn); + myprintf(cs, "\n"); + } +} + +struct ps_arg { + struct cli_session* cs; + size_t counter; + turn_time_t ct; + const char *username; + const char *pname; + int exact_match; + ur_string_map* users; + size_t *user_counters; + char **user_names; + size_t users_number; +}; + +static const char* pname(SOCKET_TYPE st) +{ + switch(st) { + case TCP_SOCKET: + return "TCP"; + case UDP_SOCKET: + return "UDP"; + case TLS_SOCKET: + return "TLS"; + case DTLS_SOCKET: + return "DTLS"; + case TENTATIVE_TCP_SOCKET: + return "TCP/TLS"; + default: + ; + }; + return "UNKNOWN"; +} + +static int print_session(ur_map_key_type key, ur_map_value_type value, void *arg) +{ + if(key && value && arg) { + struct ps_arg *csarg = (struct ps_arg*)arg; + struct cli_session* cs = csarg->cs; + struct turn_session_info *tsi = (struct turn_session_info *)value; + + if(cs->realm[0] && strcmp(cs->realm,tsi->realm)) + return 0; + + if(cs->origin[0] && strcmp(cs->origin,tsi->origin)) + return 0; + + if(csarg->users) { + ur_string_map_value_type value; + if(!ur_string_map_get(csarg->users, (ur_string_map_key_type)(char*)tsi->username, &value)) { + const char *pn=csarg->pname; + if(pn[0]) { + if(!strcmp(pn,"TLS") || !strcmp(pn,"tls") || !strcmp(pn,"Tls")) { + if(tsi->client_protocol != TLS_SOCKET) + return 0; + } else if(!strcmp(pn,"DTLS") || !strcmp(pn,"dtls") || !strcmp(pn,"Dtls")) { + if(tsi->client_protocol != DTLS_SOCKET) + return 0; + } else if(!strcmp(pn,"TCP") || !strcmp(pn,"tcp") || !strcmp(pn,"Tcp")) { + if(tsi->client_protocol != TCP_SOCKET) + return 0; + } else if(!strcmp(pn,"UDP") || !strcmp(pn,"udp") || !strcmp(pn,"Udp")) { + if(tsi->client_protocol != UDP_SOCKET) + return 0; + } else { + return 0; + } + } + value = (ur_string_map_value_type)csarg->users_number; + csarg->users_number += 1; + csarg->user_counters = (size_t*)turn_realloc(csarg->user_counters, + (size_t)value * sizeof(size_t), + csarg->users_number * sizeof(size_t)); + csarg->user_names = (char**)turn_realloc(csarg->user_names, + (size_t)value * sizeof(char*), + csarg->users_number * sizeof(char*)); + csarg->user_names[(size_t)value] = strdup((char*)tsi->username); + csarg->user_counters[(size_t)value] = 0; + ur_string_map_put(csarg->users, (ur_string_map_key_type)(char*)tsi->username, value); + } + csarg->user_counters[(size_t)value] += 1; + } else { + if(csarg->username[0]) { + if(csarg->exact_match) { + if(strcmp((char*)tsi->username, csarg->username)) + return 0; + } else { + if(!strstr((char*)tsi->username, csarg->username)) + return 0; + } + } + if(cs->f || (unsigned long)csarg->counter<(unsigned long)cli_max_output_sessions) { + myprintf(cs, "\n"); + myprintf(cs," %lu) id=%018llu, user <%s>:\n", + (unsigned long)(csarg->counter+1), + (unsigned long long)tsi->id, + tsi->username); + if(tsi->realm[0]) + myprintf(cs," realm: %s\n",tsi->realm); + if(tsi->origin[0]) + myprintf(cs," origin: %s\n",tsi->origin); + if(turn_time_before(csarg->ct, tsi->start_time)) { + myprintf(cs," started: undefined time\n"); + } else { + myprintf(cs," started %lu secs ago\n",(unsigned long)(csarg->ct - tsi->start_time)); + } + if(turn_time_before(tsi->expiration_time,csarg->ct)) { + myprintf(cs," expired\n"); + } else { + myprintf(cs," expiring in %lu secs\n",(unsigned long)(tsi->expiration_time - csarg->ct)); + } + myprintf(cs," client protocol %s, relay protocol %s\n",pname(tsi->client_protocol),pname(tsi->peer_protocol)); + { + if(!tsi->local_addr_data.saddr[0]) + addr_to_string(&(tsi->local_addr_data.addr),(u08bits*)tsi->local_addr_data.saddr); + if(!tsi->remote_addr_data.saddr[0]) + addr_to_string(&(tsi->remote_addr_data.addr),(u08bits*)tsi->remote_addr_data.saddr); + if(!tsi->relay_addr_data.saddr[0]) + addr_to_string(&(tsi->relay_addr_data.addr),(u08bits*)tsi->relay_addr_data.saddr); + myprintf(cs," client addr %s, server addr %s\n", + tsi->remote_addr_data.saddr, + tsi->local_addr_data.saddr); + myprintf(cs," relay addr %s\n", + tsi->relay_addr_data.saddr); + } + myprintf(cs," fingerprints enforced: %s\n",get_flag(tsi->enforce_fingerprints)); + myprintf(cs," mobile: %s\n",get_flag(tsi->is_mobile)); + if(tsi->tls_method[0]) { + myprintf(cs," TLS method: %s\n",tsi->tls_method); + myprintf(cs," TLS cipher: %s\n",tsi->tls_cipher); + } + myprintf(cs," usage: rp=%lu, rb=%lu, sp=%lu, sb=%lu\n",(unsigned long)(tsi->received_packets), (unsigned long)(tsi->received_bytes),(unsigned long)(tsi->sent_packets),(unsigned long)(tsi->sent_bytes)); + myprintf(cs," rate: r=%lu, s=%lu, total=%lu (bytes per sec)\n",(unsigned long)(tsi->received_rate), (unsigned long)(tsi->sent_rate),(unsigned long)(tsi->total_rate)); + if(tsi->main_peers_size) { + myprintf(cs," peers:\n"); + size_t i; + for(i=0;imain_peers_size;++i) { + if(!(tsi->main_peers_data[i].saddr[0])) + addr_to_string(&(tsi->main_peers_data[i].addr),(u08bits*)tsi->main_peers_data[i].saddr); + myprintf(cs," %s\n",tsi->main_peers_data[i].saddr); + } + if(tsi->extra_peers_size && tsi->extra_peers_data) { + for(i=0;iextra_peers_size;++i) { + if(!(tsi->extra_peers_data[i].saddr[0])) + addr_to_string(&(tsi->extra_peers_data[i].addr),(u08bits*)tsi->extra_peers_data[i].saddr); + myprintf(cs," %s\n",tsi->extra_peers_data[i].saddr); + } + } + } + } + } + + csarg->counter += 1; + } + return 0; +} + +static void print_sessions(struct cli_session* cs, const char* pn, int exact_match, int print_users) +{ + if(cs && cs->ts && pn) { + + while(pn[0] == ' ') ++pn; + if(pn[0] == '*') ++pn; + + const char *uname=""; + if(!print_users) { + uname = pn; + pn = ""; + } + + struct ps_arg arg = {cs,0,0,uname,pn,exact_match,NULL,NULL,NULL,0}; + + arg.ct = turn_time(); + + if(print_users) { + arg.users = ur_string_map_create(NULL); + } + + ur_map_foreach_arg(cliserver.sessions, (foreachcb_arg_type)print_session, &arg); + + myprintf(cs,"\n"); + + if(!print_users && !(cs->f)) { + if((unsigned long)arg.counter > (unsigned long)cli_max_output_sessions) { + myprintf(cs,"...\n"); + myprintf(cs,"\n"); + } + } else if(arg.user_counters && arg.user_names) { + size_t i; + for(i=0;i, %lu sessions\n", + arg.user_names[i], + (unsigned long)arg.user_counters[i]); + } + } + myprintf(cs,"\n"); + } + + { + char ts[1025]; + snprintf(ts,sizeof(ts)," Total sessions"); + if(cs->realm[0]) { + snprintf(ts+strlen(ts),sizeof(ts)-strlen(ts)," for realm %s",cs->realm); + if(cs->origin[0]) + snprintf(ts+strlen(ts),sizeof(ts)-strlen(ts)," and for origin %s",cs->origin); + } else { + if(cs->origin[0]) + snprintf(ts+strlen(ts),sizeof(ts)-strlen(ts)," for origin %s",cs->origin); + } + snprintf(ts+strlen(ts),sizeof(ts)-strlen(ts),": %lu", (unsigned long)arg.counter); + myprintf(cs,"%s\n", ts); + myprintf(cs,"\n"); + } + + if(!print_users && !(cs->f)) { + if((unsigned long)arg.counter > (unsigned long)cli_max_output_sessions) { + myprintf(cs," Warning: too many output sessions, more than the\n"); + myprintf(cs," current value of cli-max-output-sessions CLI parameter.\n"); + myprintf(cs," Refine your request or increase cli-max-output-sessions value.\n"); + myprintf(cs,"\n"); + } + } + + if(arg.user_counters) + turn_free(arg.user_counters,sizeof(size_t)*arg.users_number); + if(arg.user_names) { + size_t i; + for(i=0;ioptions.name; + if(rn[0]) + cli_print_str(cs,rn,"Default realm",0); + } + if(cs->realm[0]) + cli_print_str(cs,cs->realm,"CLI session realm",0); + else + cli_print_str(cs,get_realm(NULL)->options.name,"CLI session realm",0); + if(cs->origin[0]) + cli_print_str(cs,cs->origin,"CLI session origin",0); + if(turn_params.ct == TURN_CREDENTIALS_LONG_TERM) + cli_print_flag(cs,1,"Long-term authorization mechanism",0); + else if(turn_params.ct == TURN_CREDENTIALS_SHORT_TERM) + cli_print_flag(cs,1,"Short-term authorization mechanism",0); + else + cli_print_flag(cs,1,"Anonymous credentials",0); + cli_print_flag(cs,turn_params.use_auth_secret_with_timestamp,"REST API support",0); + if(turn_params.use_auth_secret_with_timestamp && turn_params.rest_api_separator) + cli_print_uint(cs,turn_params.rest_api_separator,"REST API separator ASCII number",0); + + myprintf(cs,"\n"); + + cli_print_uint(cs,(unsigned long)cs->rp->status.total_current_allocs,"total-current-allocs",0); + + cli_print_uint(cs,(unsigned long)cs->rp->options.perf_options.total_quota,"total-quota",2); + cli_print_uint(cs,(unsigned long)cs->rp->options.perf_options.user_quota,"user-quota",2); + cli_print_uint(cs,(unsigned long)cs->rp->options.perf_options.max_bps,"max-bps",0); + + myprintf(cs,"\n"); + + cli_print_uint(cs,(unsigned long)cli_max_output_sessions,"cli-max-output-sessions",2); + + { + myprintf(cs,"\n"); + const char *str=" (Note 1: parameters with (*) are toggleable)"; + myprintf(cs,"%s\n",str); + myprintf(cs,"\n"); + str=" (Note 2: parameters with (**) are changeable)"; + myprintf(cs,"%s\n",str); + myprintf(cs,"\n"); + } + } +} + +static void close_cli_session(struct cli_session* cs); + +static int run_cli_output(struct cli_session* cs, const char *buf, unsigned int len) +{ + if(cs && buf && len) { + if(bufferevent_write(cs->bev, buf, len)< 0) { + return -1; + } + return 0; + } + return -1; +} + +static void close_cli_session(struct cli_session* cs) +{ + if(cs) { + + addr_debug_print(cliserver.verbose, &(cs->addr),"CLI session disconnected from"); + + if(cs->ts) { + telnet_free(cs->ts); + cs->ts = NULL; + } + + if(cs->bev) { + bufferevent_flush(cs->bev,EV_READ|EV_WRITE,BEV_FLUSH); + bufferevent_disable(cs->bev,EV_READ|EV_WRITE); + bufferevent_free(cs->bev); + cs->bev=NULL; + } + + if(cs->fd>=0) { + close(cs->fd); + cs->fd = -1; + } + + turn_free(cs,sizeof(struct cli_session)); + } +} + +static void type_cli_cursor(struct cli_session* cs) +{ + if(cs && (cs->bev)) { + myprintf(cs, "%s", CLI_CURSOR); + } +} + +static void cli_add_alternate_server(struct cli_session* cs, const char* pn) +{ + if(cs && cs->ts && pn && *pn) { + add_alternate_server(pn); + } +} + +static void cli_add_tls_alternate_server(struct cli_session* cs, const char* pn) +{ + if(cs && cs->ts && pn && *pn) { + add_tls_alternate_server(pn); + } +} + +static void cli_del_alternate_server(struct cli_session* cs, const char* pn) +{ + if(cs && cs->ts && pn && *pn) { + del_alternate_server(pn); + } +} + +static void cli_del_tls_alternate_server(struct cli_session* cs, const char* pn) +{ + if(cs && cs->ts && pn && *pn) { + del_tls_alternate_server(pn); + } +} + +static int run_cli_input(struct cli_session* cs, const char *buf0, unsigned int len) +{ + int ret = 0; + + if(cs && buf0 && cs->ts && cs->bev) { + + char *buf = (char*)malloc(len+1); + ns_bcopy(buf0,buf,len); + buf[len]=0; + + char *cmd = buf; + + while((cmd[0]==' ') || (cmd[0]=='\t')) ++cmd; + + size_t sl = strlen(cmd); + + while(sl) { + char c = cmd[sl-1]; + if((c==10)||(c==13)) { + cmd[sl-1]=0; + --sl; + } else { + break; + } + } + + if(sl) { + cs->cmds += 1; + if(cli_password[0] && !(cs->auth_completed)) { + if(strcmp(cmd,cli_password)) { + if(cs->cmds>=CLI_PASSWORD_TRY_NUMBER) { + addr_debug_print(1, &(cs->addr),"CLI authentication error"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"CLI authentication error\n"); + close_cli_session(cs); + } else { + const char* ipwd="Enter password: "; + myprintf(cs,"%s\n",ipwd); + } + } else { + cs->auth_completed = 1; + addr_debug_print(1, &(cs->addr),"CLI authentication success"); + type_cli_cursor(cs); + } + } else if((strcmp(cmd,"bye") == 0)||(strcmp(cmd,"quit") == 0)||(strcmp(cmd,"exit") == 0)||(strcmp(cmd,"q") == 0)) { + const char* str="Bye !"; + myprintf(cs,"%s\n",str); + close_cli_session(cs); + ret = -1; + } else if((strcmp(cmd,"halt") == 0)||(strcmp(cmd,"shutdown") == 0)||(strcmp(cmd,"stop") == 0)) { + addr_debug_print(1, &(cs->addr),"Shutdown command received from CLI user"); + const char* str="TURN server is shutting down"; + myprintf(cs,"%s\n",str); + close_cli_session(cs); + turn_params.stop_turn_server = 1; + sleep(10); + exit(0); + } else if((strcmp(cmd,"?") == 0)||(strcmp(cmd,"h") == 0)||(strcmp(cmd,"help") == 0)) { + print_str_array(cs, CLI_GREETING_STR); + print_str_array(cs, CLI_HELP_STR); + type_cli_cursor(cs); + } else if(strcmp(cmd,"pc")==0) { + cli_print_configuration(cs); + type_cli_cursor(cs); + } else if(strstr(cmd,"tc ") == cmd) { + toggle_cli_param(cs,cmd+3); + } else if(strstr(cmd,"sr ") == cmd) { + STRCPY(cs->realm,cmd+3); + cs->rp = get_realm(cs->realm); + type_cli_cursor(cs); + } else if(strcmp(cmd,"ur") == 0) { + cs->realm[0]=0; + cs->rp = get_realm(NULL); + type_cli_cursor(cs); + } else if(strstr(cmd,"so ") == cmd) { + STRCPY(cs->origin,cmd+3); + type_cli_cursor(cs); + } else if(strcmp(cmd,"uo") == 0) { + cs->origin[0]=0; + type_cli_cursor(cs); + } else if(strstr(cmd,"tc") == cmd) { + toggle_cli_param(cs,cmd+2); + type_cli_cursor(cs); + } else if(strstr(cmd,"psp") == cmd) { + print_sessions(cs,cmd+3,0,0); + type_cli_cursor(cs); + } else if(strstr(cmd,"psd") == cmd) { + cmd += 3; + while(cmd[0]==' ') ++cmd; + if(!(cmd[0])) { + const char* str="You have to provide file name for ps dump\n"; + myprintf(cs,"%s\n",str); + } else { + cs->f = fopen(cmd,"w"); + if(!(cs->f)) { + const char* str="Cannot open file for writing\n"; + myprintf(cs,"%s\n",str); + } else { + print_sessions(cs,"",1,0); + fclose(cs->f); + cs->f = NULL; + } + } + type_cli_cursor(cs); + } else if(strstr(cmd,"pu ") == cmd) { + print_sessions(cs,cmd+3,0,1); + type_cli_cursor(cs); + } else if(!strcmp(cmd,"pu")) { + print_sessions(cs,cmd+2,0,1); + type_cli_cursor(cs); + } else if(strstr(cmd,"ps") == cmd) { + print_sessions(cs,cmd+2,1,0); + type_cli_cursor(cs); + } else if(strstr(cmd,"cc ") == cmd) { + change_cli_param(cs,cmd+3); + type_cli_cursor(cs); + } else if(strstr(cmd,"cc") == cmd) { + change_cli_param(cs,cmd+2); + type_cli_cursor(cs); + } else if(strstr(cmd,"aas ") == cmd) { + cli_add_alternate_server(cs,cmd+4); + type_cli_cursor(cs); + } else if(strstr(cmd,"atas ") == cmd) { + cli_add_tls_alternate_server(cs,cmd+5); + type_cli_cursor(cs); + } else if(strstr(cmd,"das ") == cmd) { + cli_del_alternate_server(cs,cmd+4); + type_cli_cursor(cs); + } else if(strstr(cmd,"dtas ") == cmd) { + cli_del_tls_alternate_server(cs,cmd+5); + type_cli_cursor(cs); + } else { + const char* str="Unknown command\n"; + myprintf(cs,"%s\n",str); + type_cli_cursor(cs); + } + } else { + type_cli_cursor(cs); + } + + free(buf); + } + + return ret; +} + +static void cli_socket_input_handler_bev(struct bufferevent *bev, void* arg) +{ + if (bev && arg) { + + struct cli_session* cs = (struct cli_session*) arg; + + if(!(cs->ts)) + return; + + stun_buffer buf; + + if(cs->bev) { + + int len = (int)bufferevent_read(cs->bev, buf.buf, STUN_BUFFER_SIZE-1); + if(len < 0) { + close_cli_session(cs); + return; + } else if(len == 0) { + return; + } + + buf.len = len; + buf.offset = 0; + buf.buf[len]=0; + + telnet_recv(cs->ts, (const char *)buf.buf, (unsigned int)(buf.len)); + } + } +} + +static void cli_eventcb_bev(struct bufferevent *bev, short events, void *arg) +{ + UNUSED_ARG(bev); + + if (events & BEV_EVENT_CONNECTED) { + // Connect okay + } else if (events & (BEV_EVENT_ERROR | BEV_EVENT_EOF)) { + if (arg) { + + struct cli_session* cs = (struct cli_session*) arg; + + close_cli_session(cs); + } + } +} + +static void cli_telnet_event_handler(telnet_t *telnet, telnet_event_t *event, void *user_data) +{ + if (user_data && telnet) { + + struct cli_session *cs = (struct cli_session *) user_data; + + switch (event->type){ + case TELNET_EV_DATA: + run_cli_input(cs, event->data.buffer, event->data.size); + break; + case TELNET_EV_SEND: + run_cli_output(cs, event->data.buffer, event->data.size); + break; + case TELNET_EV_ERROR: + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TELNET error: %s", event->error.msg); + break; + default: + ; + }; + } +} + +static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd, + struct sockaddr *sa, int socklen, void *arg) +{ + UNUSED_ARG(l); + UNUSED_ARG(arg); + UNUSED_ARG(socklen); + + addr_debug_print(cliserver.verbose, (ioa_addr*)sa,"CLI connected to"); + + struct cli_session *clisession = (struct cli_session*)turn_malloc(sizeof(struct cli_session)); + ns_bzero(clisession,sizeof(struct cli_session)); + + clisession->rp = get_realm(NULL); + + set_socket_options_fd(fd, 1, sa->sa_family); + + clisession->fd = fd; + + addr_cpy(&(clisession->addr),(ioa_addr*)sa); + + clisession->bev = bufferevent_socket_new(cliserver.event_base, + fd, + BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + bufferevent_setcb(clisession->bev, cli_socket_input_handler_bev, NULL, + cli_eventcb_bev, clisession); + bufferevent_setwatermark(clisession->bev, EV_READ|EV_WRITE, 0, BUFFEREVENT_HIGH_WATERMARK); + bufferevent_enable(clisession->bev, EV_READ); /* Start reading. */ + + clisession->ts = telnet_init(cli_telopts, cli_telnet_event_handler, 0, clisession); + + if(!(clisession->ts)) { + const char *str = "Cannot open telnet session\n"; + addr_debug_print(cliserver.verbose, (ioa_addr*)sa,str); + close_cli_session(clisession); + } else { + print_str_array(clisession, CLI_GREETING_STR); + telnet_printf(clisession->ts,"\n"); + telnet_printf(clisession->ts,"Type '?' for help\n"); + if(cli_password[0]) { + const char* ipwd="Enter password: "; + telnet_printf(clisession->ts,"%s\n",ipwd); + } else { + type_cli_cursor(clisession); + } + } +} + +void setup_cli_thread(void) +{ + cliserver.event_base = turn_event_base_new(); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (cli thread): %s\n",event_base_get_method(cliserver.event_base)); + + struct bufferevent *pair[2]; + int opts = BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS; + + opts |= BEV_OPT_THREADSAFE; + + bufferevent_pair_new(cliserver.event_base, opts, pair); + cliserver.in_buf = pair[0]; + cliserver.out_buf = pair[1]; + bufferevent_setcb(cliserver.in_buf, cli_server_receive_message, NULL, NULL, &cliserver); + bufferevent_enable(cliserver.in_buf, EV_READ); + + if(!cli_addr_set) { + if(make_ioa_addr((const u08bits*)CLI_DEFAULT_IP,0,&cli_addr)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot set cli address %s\n",CLI_DEFAULT_IP); + return; + } + } + + addr_set_port(&cli_addr,cli_port); + + cliserver.listen_fd = socket(cli_addr.ss.sa_family, SOCK_STREAM, 0); + if (cliserver.listen_fd < 0) { + perror("socket"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot open CLI socket\n"); + return; + } + + if(addr_bind(cliserver.listen_fd,&cli_addr,1)<0) { + perror("Cannot bind CLI socket to addr"); + char saddr[129]; + addr_to_string(&cli_addr,(u08bits*)saddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind CLI listener socket to addr %s\n",saddr); + socket_closesocket(cliserver.listen_fd); + return; + } + + socket_tcp_set_keepalive(cliserver.listen_fd); + + socket_set_nonblocking(cliserver.listen_fd); + + cliserver.l = evconnlistener_new(cliserver.event_base, + cliserver_input_handler, &cliserver, + LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, + 1024, cliserver.listen_fd); + + if(!(cliserver.l)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot create CLI listener\n"); + socket_closesocket(cliserver.listen_fd); + return; + } + + cliserver.sessions = ur_map_create(); + + addr_debug_print(cliserver.verbose, &cli_addr,"CLI listener opened on "); +} + +void cli_server_receive_message(struct bufferevent *bev, void *ptr) +{ + UNUSED_ARG(ptr); + + struct turn_session_info *tsi = (struct turn_session_info*)turn_malloc(sizeof(struct turn_session_info)); + turn_session_info_init(tsi); + int n = 0; + struct evbuffer *input = bufferevent_get_input(bev); + + while ((n = evbuffer_remove(input, tsi, sizeof(struct turn_session_info))) > 0) { + if (n != sizeof(struct turn_session_info)) { + fprintf(stderr,"%s: Weird CLI buffer error: size=%d\n",__FUNCTION__,n); + continue; + } + + ur_map_value_type t = 0; + if (ur_map_get(cliserver.sessions, (ur_map_key_type)tsi->id, &t) && t) { + struct turn_session_info *old = (struct turn_session_info*)t; + turn_session_info_clean(old); + turn_free(old,sizeof(struct turn_session_info)); + ur_map_del(cliserver.sessions, (ur_map_key_type)tsi->id, NULL); + } + + if(tsi->valid) { + ur_map_put(cliserver.sessions, (ur_map_key_type)tsi->id, (ur_map_value_type)tsi); + tsi = (struct turn_session_info*)turn_malloc(sizeof(struct turn_session_info)); + turn_session_info_init(tsi); + } else { + turn_session_info_clean(tsi); + } + } + + if(tsi) { + turn_session_info_clean(tsi); + turn_free(tsi,sizeof(struct turn_session_info)); + } +} + +int send_turn_session_info(struct turn_session_info* tsi) +{ + int ret = -1; + + if(!use_cli) + return ret; + + if(tsi) { + struct evbuffer *output = bufferevent_get_output(cliserver.out_buf); + if(output) { + if(evbuffer_add(output,tsi,sizeof(struct turn_session_info))>=0) { + ret = 0; + } + } + } + + return ret; +} + +/////////////////////////////// diff --git a/src/apps/relay/turncli.h b/src/apps/relay/turncli.h new file mode 100644 index 00000000..6a432441 --- /dev/null +++ b/src/apps/relay/turncli.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2011, 2012, 2013 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 __TURNCLI__ +#define __TURNCLI__ + +#include +#include + +#include + +#include +#include + +#include "ns_turn_utils.h" +#include "ns_turn_maps.h" +#include "ns_turn_server.h" + +#include "apputils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////// + +struct cli_server { + evutil_socket_t listen_fd; + struct event_base* event_base; + int verbose; + struct evconnlistener *l; + struct bufferevent *in_buf; + struct bufferevent *out_buf; + ur_map *sessions; + pthread_t thr; +}; + +/////////////////////////////////////////// + +extern struct cli_server cliserver; + +extern int use_cli; + +#define CLI_DEFAULT_IP ("127.0.0.1") +extern ioa_addr cli_addr; +extern int cli_addr_set; + +#define CLI_DEFAULT_PORT (5766) +extern int cli_port; + +#define CLI_PASSWORD_LENGTH (129) +extern char cli_password[CLI_PASSWORD_LENGTH]; + +#define DEFAULT_CLI_MAX_OUTPUT_SESSIONS (256) +extern int cli_max_output_sessions; + +//////////////////////////////////////////// + +void setup_cli_thread(void); + +void cli_server_receive_message(struct bufferevent *bev, void *ptr); + +int send_turn_session_info(struct turn_session_info* tsi); + +//////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif +/// __TURNCLI__/// + diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c new file mode 100644 index 00000000..a45b5c0e --- /dev/null +++ b/src/apps/relay/userdb.c @@ -0,0 +1,3595 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(TURN_NO_PQ) +#include +#endif + +#if !defined(TURN_NO_MYSQL) +#include +#endif + +#if !defined(TURN_NO_HIREDIS) +#include "hiredis_libevent2.h" +#include +#endif + +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include "userdb.h" +#include "mainrelay.h" + +#include "ns_turn_utils.h" + +#include "ns_turn_server.h" +#include "ns_turn_maps.h" + +#include "apputils.h" + +//////////// USER DB ////////////////////////////// + +#define LONG_STRING_SIZE (TURN_LONG_STRING_SIZE) + +static int donot_print_connection_success=0; + +//////////// REALM ////////////// + +static realm_params_t *default_realm_params_ptr = NULL; +static const realm_params_t _default_realm_params = +{ + 1, + { + "\0", /* name */ + {0,0,0} + }, + {0,NULL} +}; + +static ur_string_map *realms = NULL; +static turn_mutex o_to_realm_mutex; +static ur_string_map *o_to_realm = NULL; +static secrets_list_t realms_list; + +void create_new_realm(char* name) +{ + realm_params_t *ret = NULL; + + if((name == NULL)||(name[0]==0)) { + if(default_realm_params_ptr) { + return; + } + /* init everything: */ + TURN_MUTEX_INIT_RECURSIVE(&o_to_realm_mutex); + init_secrets_list(&realms_list); + o_to_realm = ur_string_map_create(free); + default_realm_params_ptr = (realm_params_t*)malloc(sizeof(realm_params_t)); + ns_bcopy(&_default_realm_params,default_realm_params_ptr,sizeof(realm_params_t)); + realms = ur_string_map_create(NULL); + ur_string_map_lock(realms); + ret = default_realm_params_ptr; + } else { + ur_string_map_value_type value = 0; + ur_string_map_lock(realms); + if (!ur_string_map_get(realms, (const ur_string_map_key_type) name, &value)) { + ret = (realm_params_t*)turn_malloc(sizeof(realm_params_t)); + ns_bcopy(default_realm_params_ptr,ret,sizeof(realm_params_t)); + STRCPY(ret->options.name,name); + value = (ur_string_map_value_type)ret; + ur_string_map_put(realms, (const ur_string_map_key_type) name, value); + add_to_secrets_list(&realms_list, name); + } else { + ur_string_map_unlock(realms); + return; + } + } + + ret->status.alloc_counters = ur_string_map_create(NULL); + ur_string_map_unlock(realms); +} + +void get_default_realm_options(realm_options_t* ro) +{ + if(ro) { + ur_string_map_lock(realms); + ns_bcopy(&(default_realm_params_ptr->options),ro,sizeof(realm_options_t)); + ur_string_map_unlock(realms); + } +} + +void set_default_realm_name(char *realm) { + ur_string_map_lock(realms); + ur_string_map_value_type value = (ur_string_map_value_type)default_realm_params_ptr; + STRCPY(default_realm_params_ptr->options.name,realm); + ur_string_map_put(realms, (ur_string_map_key_type)default_realm_params_ptr->options.name, value); + add_to_secrets_list(&realms_list, realm); + ur_string_map_unlock(realms); +} + +realm_params_t* get_realm(char* name) +{ + if(name && name[0]) { + ur_string_map_lock(realms); + ur_string_map_value_type value = 0; + ur_string_map_key_type key = (ur_string_map_key_type)name; + if (ur_string_map_get(realms, key, &value)) { + ur_string_map_unlock(realms); + return (realm_params_t*)value; + } else { + realm_params_t *ret = (realm_params_t*)turn_malloc(sizeof(realm_params_t)); + ns_bcopy(default_realm_params_ptr,ret,sizeof(realm_params_t)); + STRCPY(ret->options.name,name); + value = (ur_string_map_value_type)ret; + ur_string_map_put(realms, key, value); + ret->status.alloc_counters = ur_string_map_create(NULL); + add_to_secrets_list(&realms_list, name); + ur_string_map_unlock(realms); + return ret; + } + } + + return default_realm_params_ptr; +} + +int get_realm_data(char* name, realm_params_t* rp) +{ + ur_string_map_lock(realms); + ns_bcopy(get_realm(name),rp,sizeof(realm_params_t)); + ur_string_map_unlock(realms); + return 0; +} + +void get_realm_options_by_origin(char *origin, realm_options_t* ro) +{ + ur_string_map_value_type value = 0; + TURN_MUTEX_LOCK(&o_to_realm_mutex); + if (ur_string_map_get(o_to_realm, (ur_string_map_key_type) origin, &value) && value) { + char *realm = strdup((char*)value); + TURN_MUTEX_UNLOCK(&o_to_realm_mutex); + realm_params_t rp; + get_realm_data(realm, &rp); + ns_bcopy(&(rp.options),ro,sizeof(realm_options_t)); + free(realm); + } else { + TURN_MUTEX_UNLOCK(&o_to_realm_mutex); + get_default_realm_options(ro); + } +} + +void get_realm_options_by_name(char *realm, realm_options_t* ro) +{ + realm_params_t rp; + get_realm_data(realm, &rp); + ns_bcopy(&(rp.options),ro,sizeof(realm_options_t)); +} + +int change_total_quota(char *realm, int value) +{ + int ret = value; + ur_string_map_lock(realms); + realm_params_t* rp = get_realm(realm); + rp->options.perf_options.total_quota = value; + ur_string_map_unlock(realms); + return ret; +} + +int change_user_quota(char *realm, int value) +{ + int ret = value; + ur_string_map_lock(realms); + realm_params_t* rp = get_realm(realm); + rp->options.perf_options.user_quota = value; + ur_string_map_unlock(realms); + return ret; +} + +static void must_set_admin_realm(void *realm0) +{ + char* realm = (char*)realm0; + if(!realm || !realm[0]) { + fprintf(stderr, "The operation cannot be completed: the realm must be set.\n"); + exit(-1); + } +} + +static void must_set_admin_user(void *user0) +{ + char* user = (char*)user0; + if(!user || !user[0]) { + fprintf(stderr, "The operation cannot be completed: the user must be set.\n"); + exit(-1); + } +} + +static void must_set_admin_pwd(void *pwd0) +{ + char* pwd = (char*)pwd0; + if(!pwd || !pwd[0]) { + fprintf(stderr, "The operation cannot be completed: the password must be set.\n"); + exit(-1); + } +} + +static void must_set_admin_origin(void *origin0) +{ + char* origin = (char*)origin0; + if(!origin || !origin[0]) { + fprintf(stderr, "The operation cannot be completed: the origin must be set.\n"); + exit(-1); + } +} + +/////////// SHARED SECRETS ///////////////// + +void init_secrets_list(secrets_list_t *sl) +{ + if(sl) { + ns_bzero(sl,sizeof(secrets_list_t)); + } +} + +void clean_secrets_list(secrets_list_t *sl) +{ + if(sl) { + if(sl->secrets) { + size_t i = 0; + for(i = 0;isz;++i) { + if(sl->secrets[i]) { + turn_free(sl->secrets[i], strlen(sl->secrets[i])+1); + } + } + turn_free(sl->secrets,(sl->sz)*sizeof(char*)); + sl->secrets = NULL; + sl->sz = 0; + } + } +} + +size_t get_secrets_list_size(secrets_list_t *sl) +{ + if(sl && sl->secrets) { + return sl->sz; + } + return 0; +} + +const char* get_secrets_list_elem(secrets_list_t *sl, size_t i) +{ + if(get_secrets_list_size(sl)>i) { + return sl->secrets[i]; + } + return NULL; +} + +void add_to_secrets_list(secrets_list_t *sl, const char* elem) +{ + if(sl && elem) { + sl->secrets = (char**)realloc(sl->secrets,(sizeof(char*)*(sl->sz+1))); + sl->secrets[sl->sz] = strdup(elem); + sl->sz += 1; + } +} + +/////////// USER DB CHECK ////////////////// + +static persistent_users_db_t* get_persistent_users_db(void) +{ + return &(turn_params.default_users_db.persistent_users_db); +} + +static int convert_string_key_to_binary(char* keysource, hmackey_t key, size_t sz) { + { + char is[3]; + size_t i; + unsigned int v; + is[2]=0; + for(i=0;iconnection); + if(pqdbconnection) { + ConnStatusType status = PQstatus(pqdbconnection); + if(status != CONNECTION_OK) { + PQfinish(pqdbconnection); + pqdbconnection = NULL; + } + } + if(!pqdbconnection) { + char *errmsg=NULL; + PQconninfoOption *co = PQconninfoParse(pud->userdb, &errmsg); + if(!co) { + if(errmsg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg); + turn_free(errmsg,strlen(errmsg)+1); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, unknown connection string format error\n",pud->userdb); + } + } else { + PQconninfoFree(co); + if(errmsg) + turn_free(errmsg,strlen(errmsg)+1); + pqdbconnection = PQconnectdb(pud->userdb); + if(!pqdbconnection) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb); + } else { + ConnStatusType status = PQstatus(pqdbconnection); + if(status != CONNECTION_OK) { + PQfinish(pqdbconnection); + pqdbconnection = NULL; + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb); + } else if(!donot_print_connection_success){ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "PostgreSQL DB connection success: %s\n",pud->userdb); + } + } + } + pud->connection = pqdbconnection; + } + return pqdbconnection; +} + +#endif + +#if !defined(TURN_NO_MYSQL) + +struct _Myconninfo { + char *host; + char *dbname; + char *user; + char *password; + unsigned int port; + unsigned int connect_timeout; +}; + +typedef struct _Myconninfo Myconninfo; + +static void MyconninfoFree(Myconninfo *co) { + if(co) { + if(co->host) turn_free(co->host,strlen(co->host)+1); + if(co->dbname) turn_free(co->dbname, strlen(co->dbname)+1); + if(co->user) turn_free(co->user, strlen(co->user)+1); + if(co->password) turn_free(co->password, strlen(co->password)+1); + ns_bzero(co,sizeof(Myconninfo)); + } +} + +static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) +{ + Myconninfo *co = (Myconninfo*)turn_malloc(sizeof(Myconninfo)); + ns_bzero(co,sizeof(Myconninfo)); + if(userdb) { + char *s0=strdup(userdb); + char *s = s0; + + while(s && *s) { + + while(*s && (*s==' ')) ++s; + char *snext = strstr(s," "); + if(snext) { + *snext = 0; + ++snext; + } + + char* seq = strstr(s,"="); + if(!seq) { + MyconninfoFree(co); + co = NULL; + if(errmsg) { + *errmsg = strdup(s); + } + break; + } + + *seq = 0; + if(!strcmp(s,"host")) + co->host = strdup(seq+1); + else if(!strcmp(s,"ip")) + co->host = strdup(seq+1); + else if(!strcmp(s,"addr")) + co->host = strdup(seq+1); + else if(!strcmp(s,"ipaddr")) + co->host = strdup(seq+1); + else if(!strcmp(s,"hostaddr")) + co->host = strdup(seq+1); + else if(!strcmp(s,"dbname")) + co->dbname = strdup(seq+1); + else if(!strcmp(s,"db")) + co->dbname = strdup(seq+1); + else if(!strcmp(s,"database")) + co->dbname = strdup(seq+1); + else if(!strcmp(s,"user")) + co->user = strdup(seq+1); + else if(!strcmp(s,"uname")) + co->user = strdup(seq+1); + else if(!strcmp(s,"name")) + co->user = strdup(seq+1); + else if(!strcmp(s,"username")) + co->user = strdup(seq+1); + else if(!strcmp(s,"password")) + co->password = strdup(seq+1); + else if(!strcmp(s,"pwd")) + co->password = strdup(seq+1); + else if(!strcmp(s,"passwd")) + co->password = strdup(seq+1); + else if(!strcmp(s,"secret")) + co->password = strdup(seq+1); + else if(!strcmp(s,"port")) + co->port = (unsigned int)atoi(seq+1); + else if(!strcmp(s,"p")) + co->port = (unsigned int)atoi(seq+1); + else if(!strcmp(s,"connect_timeout")) + co->connect_timeout = (unsigned int)atoi(seq+1); + else if(!strcmp(s,"timeout")) + co->connect_timeout = (unsigned int)atoi(seq+1); + else { + MyconninfoFree(co); + co = NULL; + if(errmsg) { + *errmsg = strdup(s); + } + break; + } + + s = snext; + } + + turn_free(s0, strlen(s0)+1); + } + + if(!(co->dbname)) + co->dbname=strdup("0"); + if(!(co->host)) + co->host=strdup("127.0.0.1"); + if(!(co->user)) + co->user=strdup(""); + if(!(co->password)) + co->password=strdup(""); + + return co; +} + +static MYSQL *get_mydb_connection(void) +{ + + if(!is_mysql_userdb()) + return NULL; + + persistent_users_db_t *pud = get_persistent_users_db(); + + MYSQL *mydbconnection = (MYSQL*)(pud->connection); + + if(mydbconnection) { + if(mysql_ping(mydbconnection)) { + mysql_close(mydbconnection); + mydbconnection=NULL; + } + } + + if(!mydbconnection) { + char *errmsg=NULL; + Myconninfo *co=MyconninfoParse(pud->userdb, &errmsg); + if(!co) { + if(errmsg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg); + turn_free(errmsg,strlen(errmsg)+1); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection <%s>, connection string format error\n",pud->userdb); + } + } else if(errmsg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg); + turn_free(errmsg,strlen(errmsg)+1); + MyconninfoFree(co); + } else if(!(co->dbname)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "MySQL Database name is not provided: <%s>\n",pud->userdb); + MyconninfoFree(co); + } else { + mydbconnection = mysql_init(NULL); + if(!mydbconnection) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize MySQL DB connection\n"); + } else { + if(co->connect_timeout) + mysql_options(mydbconnection,MYSQL_OPT_CONNECT_TIMEOUT,&(co->connect_timeout)); + MYSQL *conn = mysql_real_connect(mydbconnection, co->host, co->user, co->password, co->dbname, co->port, NULL, CLIENT_IGNORE_SIGPIPE); + if(!conn) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection: <%s>, runtime error\n",pud->userdb); + mysql_close(mydbconnection); + mydbconnection=NULL; + } else if(mysql_select_db(mydbconnection, co->dbname)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot connect to MySQL DB: %s\n",co->dbname); + mysql_close(mydbconnection); + mydbconnection=NULL; + } else if(!donot_print_connection_success) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MySQL DB connection success: %s\n",pud->userdb); + } + } + MyconninfoFree(co); + } + pud->connection = mydbconnection; + } + return mydbconnection; +} + +#endif + + +#if !defined(TURN_NO_HIREDIS) + +static void turnFreeRedisReply(void *reply) +{ + if(reply) { + freeReplyObject(reply); + } +} + +struct _Ryconninfo { + char *host; + char *dbname; + char *password; + unsigned int connect_timeout; + unsigned int port; +}; + +typedef struct _Ryconninfo Ryconninfo; + +static void RyconninfoFree(Ryconninfo *co) { + if(co) { + if(co->host) turn_free(co->host, strlen(co->host)+1); + if(co->dbname) turn_free(co->dbname, strlen(co->username)+1); + if(co->password) turn_free(co->password, strlen(co->password)+1); + ns_bzero(co,sizeof(Ryconninfo)); + } +} + +static Ryconninfo *RyconninfoParse(const char *userdb, char **errmsg) +{ + Ryconninfo *co = (Ryconninfo*) turn_malloc(sizeof(Ryconninfo)); + ns_bzero(co,sizeof(Ryconninfo)); + if (userdb) { + char *s0 = strdup(userdb); + char *s = s0; + + while (s && *s) { + + while (*s && (*s == ' ')) + ++s; + char *snext = strstr(s, " "); + if (snext) { + *snext = 0; + ++snext; + } + + char* seq = strstr(s, "="); + if (!seq) { + RyconninfoFree(co); + co = NULL; + if (errmsg) { + *errmsg = strdup(s); + } + break; + } + + *seq = 0; + if (!strcmp(s, "host")) + co->host = strdup(seq + 1); + else if (!strcmp(s, "ip")) + co->host = strdup(seq + 1); + else if (!strcmp(s, "addr")) + co->host = strdup(seq + 1); + else if (!strcmp(s, "ipaddr")) + co->host = strdup(seq + 1); + else if (!strcmp(s, "hostaddr")) + co->host = strdup(seq + 1); + else if (!strcmp(s, "dbname")) + co->dbname = strdup(seq + 1); + else if (!strcmp(s, "db")) + co->dbname = strdup(seq + 1); + else if (!strcmp(s, "database")) + co->dbname = strdup(seq + 1); + else if (!strcmp(s, "user")) + ; + else if (!strcmp(s, "uname")) + ; + else if (!strcmp(s, "name")) + ; + else if (!strcmp(s, "username")) + ; + else if (!strcmp(s, "password")) + co->password = strdup(seq + 1); + else if (!strcmp(s, "pwd")) + co->password = strdup(seq + 1); + else if (!strcmp(s, "passwd")) + co->password = strdup(seq + 1); + else if (!strcmp(s, "secret")) + co->password = strdup(seq + 1); + else if (!strcmp(s, "port")) + co->port = (unsigned int) atoi(seq + 1); + else if (!strcmp(s, "p")) + co->port = (unsigned int) atoi(seq + 1); + else if (!strcmp(s, "connect_timeout")) + co->connect_timeout = (unsigned int) atoi(seq + 1); + else if (!strcmp(s, "timeout")) + co->connect_timeout = (unsigned int) atoi(seq + 1); + else { + RyconninfoFree(co); + co = NULL; + if (errmsg) { + *errmsg = strdup(s); + } + break; + } + + s = snext; + } + + turn_free(s0, strlen(s0)+1); + } + + if(!(co->dbname)) + co->dbname=strdup("0"); + if(!(co->host)) + co->host=strdup("127.0.0.1"); + if(!(co->password)) + co->password=strdup(""); + + return co; +} + +redis_context_handle get_redis_async_connection(struct event_base *base, const char* connection_string, int delete_keys) +{ + redis_context_handle ret = NULL; + + char *errmsg = NULL; + if(base && connection_string && connection_string[0]) { + Ryconninfo *co = RyconninfoParse(connection_string, &errmsg); + if (!co) { + if (errmsg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", connection_string, errmsg); + turn_free(errmsg,strlen(errmsg)+1); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error\n", connection_string); + } + } else if (errmsg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", connection_string, errmsg); + turn_free(errmsg,strlen(errmsg)+1); + RyconninfoFree(co); + } else { + + if(delete_keys) { + + redisContext *rc = NULL; + + char ip[256] = "\0"; + int port = DEFAULT_REDIS_PORT; + if (co->host) + STRCPY(ip,co->host); + if (!ip[0]) + STRCPY(ip,"127.0.0.1"); + + if (co->port) + port = (int) (co->port); + + if (co->connect_timeout) { + struct timeval tv; + tv.tv_usec = 0; + tv.tv_sec = (time_t) (co->connect_timeout); + rc = redisConnectWithTimeout(ip, port, tv); + } else { + rc = redisConnect(ip, port); + } + + if (!rc) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB async connection\n"); + } else { + if (co->password) { + turnFreeRedisReply(redisCommand(rc, "AUTH %s", co->password)); + } + if (co->dbname) { + turnFreeRedisReply(redisCommand(rc, "select %s", co->dbname)); + } + { + redisReply *reply = (redisReply*)redisCommand(rc, "keys turn/*/allocation/*/status"); + if(reply) { + secrets_list_t keys; + size_t isz = 0; + char s[513]; + + init_secrets_list(&keys); + + 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); + } + } + + for(isz=0;iszhost, co->port, co->password, atoi(co->dbname)); + + if (!ret) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB connection\n"); + } else if (is_redis_asyncconn_good(ret) && !donot_print_connection_success) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis DB async connection to be used: %s\n", connection_string); + } + RyconninfoFree(co); + } + } + + return ret; +} + +static redisContext *get_redis_connection(void) +{ + if(!is_redis_userdb()) + return NULL; + + persistent_users_db_t *pud = get_persistent_users_db(); + + redisContext *redisconnection = (redisContext*)(pud->connection); + + if(redisconnection) { + if(redisconnection->err) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot connect to redis, err=%d, flags=0x%x\n", __FUNCTION__,(int)redisconnection->err,(unsigned long)redisconnection->flags); + redisFree(redisconnection); + pud->connection = NULL; + redisconnection = NULL; + } + } + + if (!redisconnection) { + + char *errmsg = NULL; + Ryconninfo *co = RyconninfoParse(pud->userdb, &errmsg); + if (!co) { + if (errmsg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", pud->userdb, errmsg); + turn_free(errmsg,strlen(errmsg)+1); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error\n", pud->userdb); + } + } else if (errmsg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", pud->userdb, errmsg); + turn_free(errmsg,strlen(errmsg)+1); + RyconninfoFree(co); + } else { + char ip[256] = "\0"; + int port = DEFAULT_REDIS_PORT; + if (co->host) + STRCPY(ip,co->host); + if (!ip[0]) + STRCPY(ip,"127.0.0.1"); + + if (co->port) + port = (int) (co->port); + + if (co->connect_timeout) { + struct timeval tv; + tv.tv_usec = 0; + tv.tv_sec = (time_t) (co->connect_timeout); + redisconnection = redisConnectWithTimeout(ip, port, tv); + } else { + redisconnection = redisConnect(ip, port); + } + + if (!redisconnection) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB connection\n"); + } else { + if (co->password) { + turnFreeRedisReply(redisCommand(redisconnection, "AUTH %s", co->password)); + } + if (co->dbname) { + turnFreeRedisReply(redisCommand(redisconnection, "select %s", co->dbname)); + } + if (!donot_print_connection_success) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis DB sync connection success: %s\n", pud->userdb); + } + } + RyconninfoFree(co); + } + pud->connection = redisconnection; + + pud = get_persistent_users_db(); + + redisconnection = (redisContext*)(pud->connection); + } + + return redisconnection; +} + +#endif + +static int get_auth_secrets(secrets_list_t *sl, u08bits *realm) +{ + int ret = -1; + + clean_secrets_list(sl); + + if(get_secrets_list_size(&turn_params.default_users_db.ram_db.static_auth_secrets)) { + size_t i = 0; + for(i=0;itype == 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); + } + } + + for(isz=0;isztype == 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 { + add_to_secrets_list(sl,rget->str); + } + turnFreeRedisReply(rget); + } + } + + clean_secrets_list(&keys); + + ret = 0; + + turnFreeRedisReply(reply); + } + } +#endif + + return ret; +} + +/* + * Timestamp retrieval + */ +static turn_time_t get_rest_api_timestamp(char *usname) +{ + turn_time_t ts = 0; + int ts_set = 0; + + char *col = strchr(usname,turn_params.rest_api_separator); + + if(col) { + if(col == usname) { + usname +=1; + } else { + char *ptr = usname; + int found_non_figure = 0; + while(ptr < col) { + if(!(ptr[0]>='0' && ptr[0]<='9')) { + found_non_figure=1; + break; + } + ++ptr; + } + if(found_non_figure) { + ts = (turn_time_t)atol(col+1); + ts_set = 1; + } else { + *col=0; + ts = (turn_time_t)atol(usname); + ts_set = 1; + *col=turn_params.rest_api_separator; + } + } + } + + if(!ts_set) { + ts = (turn_time_t)atol(usname); + } + + return ts; +} + +static char *get_real_username(char *usname) +{ + if(turn_params.use_auth_secret_with_timestamp) { + char *col=strchr(usname,turn_params.rest_api_separator); + if(col) { + if(col == usname) { + usname +=1; + } else { + char *ptr = usname; + int found_non_figure = 0; + while(ptr < col) { + if(!(ptr[0]>='0' && ptr[0]<='9')) { + found_non_figure=1; + break; + } + ++ptr; + } + if(!found_non_figure) { + usname = col+1; + } else { + *col=0; + usname = strdup(usname); + *col=turn_params.rest_api_separator; + return usname; + } + } + } + } + + return strdup(usname); +} + +/* + * Long-term mechanism password retrieval + */ +int get_user_key(u08bits *usname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh) +{ + int ret = -1; + + if(turn_params.use_auth_secret_with_timestamp) { + + turn_time_t ctime = (turn_time_t) time(NULL); + turn_time_t ts = 0; + secrets_list_t sl; + size_t sll = 0; + + init_secrets_list(&sl); + + if(get_auth_secrets(&sl, realm)<0) + return ret; + + ts = get_rest_api_timestamp((char*)usname); + + if(!turn_time_before(ts, ctime)) { + + u08bits hmac[MAXSHASIZE]; + unsigned int hmac_len; + st_password_t pwdtmp; + + hmac[0] = 0; + + stun_attr_ref sar = stun_attr_get_first_by_type_str(ioa_network_buffer_data(nbh), + ioa_network_buffer_get_size(nbh), + STUN_ATTRIBUTE_MESSAGE_INTEGRITY); + if (!sar) + return -1; + + int sarlen = stun_attr_get_len(sar); + switch(sarlen) { + case SHA1SIZEBYTES: + if(turn_params.shatype != SHATYPE_SHA1) + return -1; + hmac_len = SHA1SIZEBYTES; + break; + case SHA256SIZEBYTES: + if(turn_params.shatype != SHATYPE_SHA256) + return -1; + hmac_len = SHA256SIZEBYTES; + break; + default: + return -1; + }; + + for(sll=0;sll=0) { + size_t pwd_length = 0; + char *pwd = base64_encode(hmac,hmac_len,&pwd_length); + + if(pwd) { + if(pwd_length<1) { + turn_free(pwd,strlen(pwd)+1); + } else { + if(stun_produce_integrity_key_str((u08bits*)usname, realm, (u08bits*)pwd, key, turn_params.shatype)>=0) { + + if(stun_check_message_integrity_by_key_str(TURN_CREDENTIALS_LONG_TERM, + ioa_network_buffer_data(nbh), + ioa_network_buffer_get_size(nbh), + key, + pwdtmp, + turn_params.shatype,NULL)>0) { + + ret = 0; + } + } + turn_free(pwd,pwd_length); + + if(ret==0) + break; + } + } + } + } + } + } + + clean_secrets_list(&sl); + + return ret; + } + + ur_string_map_value_type ukey = NULL; + 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); + + if(ret==0) { + size_t sz = get_hmackey_size(turn_params.shatype); + ns_bcopy(ukey,key,sz); + return 0; + } + +#if !defined(TURN_NO_PQ) + { + PGconn * pqc = get_pqdb_connection(); + if(pqc) { + char statement[LONG_STRING_SIZE]; + snprintf(statement,sizeof(statement),"select hmackey from turnusers_lt where name='%s' and realm='%s'",usname,realm); + 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); + int len = PQgetlength(res,0,0); + if(kval) { + size_t sz = get_hmackey_size(turn_params.shatype); + if(((size_t)lentype == 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 { + size_t sz = get_hmackey_size(turn_params.shatype); + if(strlen(rget->str)str,usname); + } else if(convert_string_key_to_binary(rget->str, key, sz)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key: %s, user %s\n",rget->str,usname); + } else { + ret = 0; + } + } + 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); + } + } + } + } +#endif + + return ret; +} + +/* + * Short-term mechanism password retrieval + */ +int get_user_pwd(u08bits *usname, st_password_t pwd) +{ + int ret = -1; + + UNUSED_ARG(pwd); + + char statement[LONG_STRING_SIZE]; + snprintf(statement,sizeof(statement),"select password from turnusers_st where name='%s'",usname); + + { +#if !defined(TURN_NO_PQ) + 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); + } + } +#endif +#if !defined(TURN_NO_MYSQL) + 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); + } + } +#endif +#if !defined(TURN_NO_HIREDIS) + { + redisContext * rc = get_redis_connection(); + if(rc) { + char s[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); + } + } + } +#endif + } + + return ret; +} + +u08bits *start_user_check(turnserver_id id, turn_credential_type ct, u08bits *usname, u08bits *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, u64bits ctxkey, int *postpone_reply) +{ + *postpone_reply = 1; + + struct auth_message am; + ns_bzero(&am,sizeof(struct auth_message)); + am.id = id; + am.ct = ct; + STRCPY(am.username,usname); + STRCPY(am.realm,realm); + am.resume_func = resume; + memcpy(&(am.in_buffer),in_buffer,sizeof(ioa_net_data)); + in_buffer->nbh = NULL; + am.ctxkey = ctxkey; + + send_auth_message_to_auth_server(&am); + + return NULL; +} + +int check_new_allocation_quota(u08bits *user, u08bits *realm) +{ + int ret = 0; + if (user) { + u08bits *username = (u08bits*)get_real_username((char*)user); + realm_params_t *rp = get_realm((char*)realm); + ur_string_map_lock(rp->status.alloc_counters); + if (rp->options.perf_options.total_quota && (rp->status.total_current_allocs >= rp->options.perf_options.total_quota)) { + ret = -1; + } else if(username[0]){ + ur_string_map_value_type value = 0; + if (!ur_string_map_get(rp->status.alloc_counters, (ur_string_map_key_type) username, &value)) { + value = (ur_string_map_value_type) 1; + ur_string_map_put(rp->status.alloc_counters, (ur_string_map_key_type) username, value); + ++(rp->status.total_current_allocs); + } else { + if ((rp->options.perf_options.user_quota) && ((size_t) value >= (size_t)(rp->options.perf_options.user_quota))) { + ret = -1; + } else { + value = (ur_string_map_value_type)(((size_t)value) + 1); + ur_string_map_put(rp->status.alloc_counters, (ur_string_map_key_type) username, value); + ++(rp->status.total_current_allocs); + } + } + } else { + ++(rp->status.total_current_allocs); + } + turn_free(username,strlen(username)+1); + ur_string_map_unlock(rp->status.alloc_counters); + } + return ret; +} + +void release_allocation_quota(u08bits *user, u08bits *realm) +{ + if (user) { + u08bits *username = (u08bits*)get_real_username((char*)user); + realm_params_t *rp = get_realm((char*)realm); + ur_string_map_lock(rp->status.alloc_counters); + ur_string_map_value_type value = 0; + ur_string_map_get(rp->status.alloc_counters, (ur_string_map_key_type) username, &value); + if (value) { + value = (ur_string_map_value_type)(((size_t)value) - 1); + ur_string_map_put(rp->status.alloc_counters, (ur_string_map_key_type) username, value); + } + if (rp->status.total_current_allocs) + --(rp->status.total_current_allocs); + ur_string_map_unlock(rp->status.alloc_counters); + turn_free(username, strlen(username)+1); + } +} + +////////////////////////////////// + +void read_userdb_file(int to_print) +{ + static char *full_path_to_userdb_file = NULL; + static int first_read = 1; + static turn_time_t mtime = 0; + + if(turn_params.default_users_db.userdb_type != TURN_USERDB_TYPE_FILE) + return; + if(turn_params.use_auth_secret_with_timestamp) + return; + + FILE *f = NULL; + + persistent_users_db_t *pud = get_persistent_users_db(); + + if(full_path_to_userdb_file) { + struct stat sb; + if(stat(full_path_to_userdb_file,&sb)<0) { + perror("File statistics"); + } else { + turn_time_t newmtime = (turn_time_t)(sb.st_mtime); + if(mtime == newmtime) + return; + mtime = newmtime; + + } + } + + if (!full_path_to_userdb_file) + full_path_to_userdb_file = find_config_file(pud->userdb, first_read); + + if (full_path_to_userdb_file) + f = fopen(full_path_to_userdb_file, "r"); + + if (f) { + + char sbuf[LONG_STRING_SIZE]; + + ur_string_map_lock(turn_params.default_users_db.ram_db.dynamic_accounts); + + ur_string_map_clean(turn_params.default_users_db.ram_db.dynamic_accounts); + + for (;;) { + char *s = fgets(sbuf, sizeof(sbuf) - 1, f); + if (!s) + break; + s = skip_blanks(s); + if (s[0] == '#') + continue; + if (!s[0]) + continue; + size_t slen = strlen(s); + while (slen && (s[slen - 1] == 10 || s[slen - 1] == 13)) + s[--slen] = 0; + if (slen) { + if(to_print) { + char* sc=strstr(s,":"); + if(sc) + sc[0]=0; + printf("%s\n",s); + } else { + add_user_account(s,1); + } + } + } + + ur_string_map_unlock(turn_params.default_users_db.ram_db.dynamic_accounts); + + fclose(f); + + } else if (first_read) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: Cannot find userdb file: %s: going without flat file user database.\n", pud->userdb); + } + + first_read = 0; +} + +int add_user_account(char *user, int dynamic) +{ + /* Realm is either default or empty for users taken from file or command-line */ + if(user && !turn_params.use_auth_secret_with_timestamp) { + char *s = strstr(user, ":"); + if(!s || (s==user) || (strlen(s)<2)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong user account: %s\n",user); + } else { + size_t ulen = s-user; + char *usname = (char*)turn_malloc(sizeof(char)*(ulen+1)); + strncpy(usname,user,ulen); + usname[ulen]=0; + if(SASLprep((u08bits*)usname)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong user name: %s\n",user); + turn_free(usname,sizeof(char)*(ulen+1)); + return -1; + } + s = skip_blanks(s+1); + hmackey_t *key = (hmackey_t*)turn_malloc(sizeof(hmackey_t)); + if(strstr(s,"0x")==s) { + char *keysource = s + 2; + size_t sz = get_hmackey_size(turn_params.shatype); + if(strlen(keysource)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); + } + turn_params.default_users_db.ram_db.users_number++; + free(usname); + return 0; + } + } + + return -1; +} + +////////////////// Admin ///////////////////////// + +static int list_users(int is_st, u08bits *realm) +{ + donot_print_connection_success = 1; + + if(is_pqsql_userdb()){ +#if !defined(TURN_NO_PQ) + char statement[LONG_STRING_SIZE]; + 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]) { + snprintf(statement,sizeof(statement),"select name from turnusers_lt where realm='%s' order by name",realm); + } else { + snprintf(statement,sizeof(statement),"select name from turnusers_lt order by 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; + for(i=0;itype == 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); + } + + 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); + } + } + + for(isz=0;isztype == 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); + } + } + + for(isz=0;isztype == 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 { + printf("%s\n",rget->str); + } + } + turnFreeRedisReply(rget); + } + + clean_secrets_list(&keys); + + turnFreeRedisReply(reply); + } + } +#endif + } + + return 0; +} + +static int del_secret(u08bits *secret, u08bits *realm) { + + UNUSED_ARG(secret); + + must_set_admin_realm(realm); + + donot_print_connection_success=1; + + if (is_pqsql_userdb()) { +#if !defined(TURN_NO_PQ) + char statement[LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if (pqc) { + if(!secret || (secret[0]==0)) + snprintf(statement,sizeof(statement),"delete from turn_secret where realm='%s'",realm); + else + snprintf(statement,sizeof(statement),"delete from turn_secret where value='%s' and realm='%s'",secret,realm); + + PGresult *res = PQexec(pqc, statement); + if (res) { + PQclear(res); + } + } +#endif + } else if (is_mysql_userdb()) { +#if !defined(TURN_NO_MYSQL) + char statement[LONG_STRING_SIZE]; + MYSQL * myc = get_mydb_connection(); + if (myc) { + if(!secret || (secret[0]==0)) + snprintf(statement,sizeof(statement),"delete from turn_secret where realm='%s'",realm); + else + snprintf(statement,sizeof(statement),"delete from turn_secret where value='%s' and realm='%s'",secret,realm); + mysql_query(myc, statement); + } +#endif + } else if(is_redis_userdb()) { +#if !defined(TURN_NO_HIREDIS) + redisContext *rc = get_redis_connection(); + if(rc) { + redisReply *reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/secret/*", (char*)realm); + if(reply) { + secrets_list_t keys; + size_t isz = 0; + char s[LONG_STRING_SIZE]; + + init_secrets_list(&keys); + + 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); + } + } + + for(isz=0;isztype == 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(!strcmp((char*)secret,rget->str)) { + snprintf(s,sizeof(s),"del %s", keys.secrets[isz]); + turnFreeRedisReply(redisCommand(rc, s)); + } + } + turnFreeRedisReply(rget); + } + } + } + + turnFreeRedisReply(redisCommand(rc, "save")); + + clean_secrets_list(&keys); + + turnFreeRedisReply(reply); + } + } +#endif + } + + return 0; +} + +static int set_secret(u08bits *secret, u08bits *realm) { + + if(!secret || (secret[0]==0)) + return 0; + + must_set_admin_realm(realm); + + donot_print_connection_success = 1; + + del_secret(secret, realm); + + if (is_pqsql_userdb()) { +#if !defined(TURN_NO_PQ) + char statement[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_LEVEL_ERROR, + "Error inserting/updating secret key information: %s\n", + PQerrorMessage(pqc)); + } + if (res) { + PQclear(res); + } + } +#endif + } else if (is_mysql_userdb()) { +#if !defined(TURN_NO_MYSQL) + char statement[LONG_STRING_SIZE]; + MYSQL * myc = get_mydb_connection(); + if (myc) { + snprintf(statement,sizeof(statement),"insert into turn_secret (realm,value) values('%s','%s')",realm,secret); + int res = mysql_query(myc, statement); + if (res) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "Error inserting/updating secret key information: %s\n", + mysql_error(myc)); + } + } +#endif + } else if(is_redis_userdb()) { +#if !defined(TURN_NO_HIREDIS) + redisContext *rc = get_redis_connection(); + if(rc) { + char s[LONG_STRING_SIZE]; + + del_secret(secret, realm); + + snprintf(s,sizeof(s),"set turn/realm/%s/secret/%lu %s", (char*)realm, (unsigned long)turn_time(), secret); + + turnFreeRedisReply(redisCommand(rc, s)); + turnFreeRedisReply(redisCommand(rc, "save")); + } +#endif + } + + return 0; +} + +static int add_origin(u08bits *origin0, u08bits *realm) +{ + UNUSED_ARG(realm); + UNUSED_ARG(origin0); + char origin[STUN_MAX_ORIGIN_SIZE+1]; + get_canonic_origin((char*)origin0, origin, sizeof(origin)-1); +#if !defined(TURN_NO_PQ) + if(is_pqsql_userdb()) { + char statement[LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if(pqc) { + snprintf(statement,sizeof(statement),"insert into turn_origin_to_realm (origin,realm) values('%s','%s')",origin,realm); + PGresult *res = PQexec(pqc, statement); + if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting origin information: %s\n",PQerrorMessage(pqc)); + } + if(res) { + PQclear(res); + } + } + } +#endif + +#if !defined(TURN_NO_MYSQL) + if (is_mysql_userdb()) { + char statement[LONG_STRING_SIZE]; + MYSQL * myc = get_mydb_connection(); + if (myc) { + snprintf(statement,sizeof(statement),"insert into turn_origin_to_realm (origin,realm) values('%s','%s')",origin,realm); + int res = mysql_query(myc, statement); + if (res) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "Error inserting origin information: %s\n", + mysql_error(myc)); + } + } + } +#endif + +#if !defined(TURN_NO_HIREDIS) + if(is_redis_userdb()) { + redisContext *rc = get_redis_connection(); + if(rc) { + char s[LONG_STRING_SIZE]; + + snprintf(s,sizeof(s),"set turn/origin/%s %s", (char*)origin, (char*)realm); + + turnFreeRedisReply(redisCommand(rc, s)); + turnFreeRedisReply(redisCommand(rc, "save")); + } + } +#endif + return 0; +} + +static int del_origin(u08bits *origin0) +{ + UNUSED_ARG(origin0); + char origin[STUN_MAX_ORIGIN_SIZE+1]; + get_canonic_origin((char*)origin0, origin, sizeof(origin)-1); +#if !defined(TURN_NO_PQ) + if(is_pqsql_userdb()) { + char statement[LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if(pqc) { + snprintf(statement,sizeof(statement),"delete from turn_origin_to_realm where origin='%s'",origin); + PGresult *res = PQexec(pqc, statement); + if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting origin information: %s\n",PQerrorMessage(pqc)); + } + if(res) { + PQclear(res); + } + } + } +#endif + +#if !defined(TURN_NO_MYSQL) + if (is_mysql_userdb()) { + char statement[LONG_STRING_SIZE]; + MYSQL * myc = get_mydb_connection(); + if (myc) { + snprintf(statement,sizeof(statement),"delete from turn_origin_to_realm where origin='%s'",origin); + int res = mysql_query(myc, statement); + if (res) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "Error deleting origin information: %s\n", + mysql_error(myc)); + } + } + } +#endif + +#if !defined(TURN_NO_HIREDIS) + if(is_redis_userdb()) { + redisContext *rc = get_redis_connection(); + if(rc) { + char s[LONG_STRING_SIZE]; + + snprintf(s,sizeof(s),"del turn/origin/%s", (char*)origin); + + turnFreeRedisReply(redisCommand(rc, s)); + turnFreeRedisReply(redisCommand(rc, "save")); + } + } +#endif + return 0; +} + +static int list_origins(u08bits *realm) +{ + donot_print_connection_success = 1; + + if(is_pqsql_userdb()){ +#if !defined(TURN_NO_PQ) + char statement[LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if(pqc) { + 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"); + } + 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; + for(i=0;i> %s\n",oval,rval); + } + } + } + } + if(res) { + PQclear(res); + } + } +#endif + } else if(is_mysql_userdb()){ +#if !defined(TURN_NO_MYSQL) + char statement[LONG_STRING_SIZE]; + MYSQL * myc = get_mydb_connection(); + if(myc) { + 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"); + } + 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 { + for(;;) { + MYSQL_ROW row = mysql_fetch_row(mres); + if(!row) { + break; + } else { + if(row[0] && row[1]) { + printf("%s ==>> %s\n",row[0],row[1]); + } + } + } + } + + if(mres) + mysql_free_result(mres); + } + } +#endif + } else if(is_redis_userdb()) { +#if !defined(TURN_NO_HIREDIS) + redisContext *rc = get_redis_connection(); + if(rc) { + secrets_list_t keys; + size_t isz = 0; + + init_secrets_list(&keys); + + redisReply *reply = NULL; + + { + reply = (redisReply*)redisCommand(rc, "keys turn/origin/*"); + 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; + size_t offset = strlen("turn/origin/"); + for (i = 0; i < reply->elements; ++i) { + add_to_secrets_list(&keys,reply->element[i]->str+offset); + } + } + turnFreeRedisReply(reply); + } + } + + for(isz=0;isztype == REDIS_REPLY_ERROR) + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str); + else if (reply->type != REDIS_REPLY_STRING) { + if (reply->type != REDIS_REPLY_NIL) + 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); + } + } + turnFreeRedisReply(reply); + } + } + + clean_secrets_list(&keys); + } +#endif + } + + return 0; +} + +static int set_realm_option_one(u08bits *realm, vint value, const char* opt) +{ + UNUSED_ARG(realm); + UNUSED_ARG(value); + UNUSED_ARG(opt); + if(value<0) + return 0; +#if !defined(TURN_NO_PQ) + if(is_pqsql_userdb()) { + char statement[LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if(pqc) { + { + snprintf(statement,sizeof(statement),"delete from turn_realm_option where realm='%s' and opt='%s'",realm,opt); + PGresult *res = PQexec(pqc, statement); + if(res) { + PQclear(res); + } + } + if(value>0) { + snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%d')",realm,opt,(int)value); + PGresult *res = PQexec(pqc, statement); + if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting realm option information: %s\n",PQerrorMessage(pqc)); + } + if(res) { + PQclear(res); + } + } + } + } +#endif + +#if !defined(TURN_NO_MYSQL) + if (is_mysql_userdb()) { + char statement[LONG_STRING_SIZE]; + MYSQL * myc = get_mydb_connection(); + if (myc) { + { + snprintf(statement,sizeof(statement),"delete from turn_realm_option where realm='%s' and opt='%s'",realm,opt); + mysql_query(myc, statement); + } + if(value>0) { + snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%d')",realm,opt,(int)value); + int res = mysql_query(myc, statement); + if (res) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "Error inserting realm option information: %s\n", + mysql_error(myc)); + } + } + } + } +#endif + +#if !defined(TURN_NO_HIREDIS) + if(is_redis_userdb()) { + redisContext *rc = get_redis_connection(); + if(rc) { + char s[LONG_STRING_SIZE]; + + if(value>0) + snprintf(s,sizeof(s),"set turn/realm/%s/%s %d", (char*)realm, opt, (int)value); + else + snprintf(s,sizeof(s),"del turn/realm/%s/%s", (char*)realm, opt); + + turnFreeRedisReply(redisCommand(rc, s)); + turnFreeRedisReply(redisCommand(rc, "save")); + } + } +#endif + return 0; +} + +static int set_realm_option(u08bits *realm, perf_options_t *po) +{ + set_realm_option_one(realm,po->max_bps,"max-bps"); + set_realm_option_one(realm,po->user_quota,"user-quota"); + set_realm_option_one(realm,po->total_quota,"total-quota"); + return 0; +} + +static int list_realm_options(u08bits *realm) +{ + donot_print_connection_success = 1; + + if(is_pqsql_userdb()){ +#if !defined(TURN_NO_PQ) + char statement[LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if(pqc) { + if(realm && realm[0]) { + snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option where realm='%s' order by realm,opt",realm); + } else { + snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option order by realm,opt"); + } + 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; + for(i=0;itype == 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) { + if(strstr(reply->element[i]->str,"/max-bps")|| + strstr(reply->element[i]->str,"/total-quota")|| + strstr(reply->element[i]->str,"/user-quota")) { + add_to_secrets_list(&keys,reply->element[i]->str); + } + } + } + turnFreeRedisReply(reply); + } + } + + size_t offset = strlen("turn/realm/"); + + for(isz=0;isztype == REDIS_REPLY_ERROR) + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str); + else if (reply->type != REDIS_REPLY_STRING) { + if (reply->type != REDIS_REPLY_NIL) + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type); + } else { + printf("%s = %s\n",o+offset,reply->str); + } + turnFreeRedisReply(reply); + } + } + + clean_secrets_list(&keys); + } +#endif + } + + 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) +{ + hmackey_t key; + char skey[sizeof(hmackey_t)*2+1]; + + donot_print_connection_success = 1; + + st_password_t passwd; + + if(ct == TA_LIST_USERS) { + return list_users(is_st, realm); + } + + if(ct == TA_LIST_ORIGINS) { + return list_origins(realm); + } + + if(ct == TA_SHOW_SECRET) { + return show_secret(realm); + } + + if(ct == TA_SET_SECRET) { + return set_secret(secret, realm); + } + + if(ct == TA_DEL_SECRET) { + return del_secret(secret, realm); + } + + if(ct == TA_ADD_ORIGIN) { + must_set_admin_origin(origin); + must_set_admin_realm(realm); + return add_origin(origin,realm); + } + + if(ct == TA_DEL_ORIGIN) { + must_set_admin_origin(origin); + return del_origin(origin); + } + + if(ct == TA_SET_REALM_OPTION) { + must_set_admin_realm(realm); + if(!(po && (po->max_bps>=0 || po->total_quota>=0 || po->user_quota>=0))) { + fprintf(stderr, "The operation cannot be completed: a realm option must be set.\n"); + exit(-1); + } + return set_realm_option(realm,po); + } + + if(ct == TA_LIST_REALM_OPTIONS) { + return list_realm_options(realm); + } + + must_set_admin_user(user); + + if(ct != TA_DELETE_USER) { + + 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); + int maxsz = (int)(sz*2)+1; + char *s=skey; + for(i=0;(i2);i++) { + snprintf(s,(size_t)(sz*2),"%02x",(unsigned int)key[i]); + maxsz-=2; + s+=2; + } + skey[sz*2]=0; + } + } + + if(ct == TA_PRINT_KEY) { + + if(!is_st) { + printf("0x%s\n",skey); + } + + } else if(is_pqsql_userdb()){ + +#if !defined(TURN_NO_PQ) + + if(!is_st) { + must_set_admin_realm(realm); + } + + char statement[LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if(pqc) { + if(ct == TA_DELETE_USER) { + if(is_st) { + snprintf(statement,sizeof(statement),"delete from turnusers_st where name='%s'",user); + } else { + snprintf(statement,sizeof(statement),"delete from turnusers_lt where name='%s' and realm='%s'",user,realm); + } + PGresult *res = PQexec(pqc, statement); + if(res) { + PQclear(res); + } + } + + if(ct == TA_UPDATE_USER) { + if(is_st) { + snprintf(statement,sizeof(statement),"insert into turnusers_st values('%s','%s')",user,passwd); + } else { + snprintf(statement,sizeof(statement),"insert into turnusers_lt (realm,name,hmackey) values('%s','%s','%s')",realm,user,skey); + } + PGresult *res = PQexec(pqc, statement); + if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { + if(res) { + PQclear(res); + } + if(is_st) { + snprintf(statement,sizeof(statement),"update turnusers_st set password='%s' where name='%s'",passwd,user); + } else { + snprintf(statement,sizeof(statement),"update turnusers_lt set hmackey='%s' where name='%s' and realm='%s'",skey,user,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)); + } + } + if(res) { + PQclear(res); + } + } + } +#endif + } else if(is_mysql_userdb()){ + +#if !defined(TURN_NO_MYSQL) + + if(!is_st) { + must_set_admin_realm(realm); + } + + char statement[LONG_STRING_SIZE]; + MYSQL * myc = get_mydb_connection(); + if(myc) { + if(ct == TA_DELETE_USER) { + if(is_st) { + snprintf(statement,sizeof(statement),"delete from turnusers_st where name='%s'",user); + } else { + snprintf(statement,sizeof(statement),"delete from turnusers_lt where name='%s' and realm='%s'",user,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)); + } + } + + if(ct == TA_UPDATE_USER) { + if(is_st) { + snprintf(statement,sizeof(statement),"insert into turnusers_st values('%s','%s')",user,passwd); + } else { + snprintf(statement,sizeof(statement),"insert into turnusers_lt (realm,name,hmackey) values('%s','%s','%s')",realm,user,skey); + } + int res = mysql_query(myc, statement); + if(res) { + if(is_st) { + snprintf(statement,sizeof(statement),"update turnusers_st set password='%s' where name='%s'",passwd,user); + } else { + snprintf(statement,sizeof(statement),"update turnusers_lt set hmackey='%s' where name='%s' and realm='%s'",skey,user,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)); + } + } + } + } +#endif + } else if(is_redis_userdb()) { + +#if !defined(TURN_NO_HIREDIS) + + if(!is_st) { + must_set_admin_realm(realm); + } + + redisContext *rc = get_redis_connection(); + if(rc) { + char statement[LONG_STRING_SIZE]; + + if(ct == TA_DELETE_USER) { + if(is_st) { + snprintf(statement,sizeof(statement),"del turn/user/%s/password",user); + turnFreeRedisReply(redisCommand(rc, statement)); + } else { + snprintf(statement,sizeof(statement),"del turn/realm/%s/user/%s/key",(char*)realm,user); + turnFreeRedisReply(redisCommand(rc, statement)); + snprintf(statement,sizeof(statement),"del turn/realm/%s/user/%s/password",(char*)realm,user); + turnFreeRedisReply(redisCommand(rc, statement)); + } + } + + if(ct == TA_UPDATE_USER) { + if(is_st) { + snprintf(statement,sizeof(statement),"set turn/user/%s/password %s",user,passwd); + turnFreeRedisReply(redisCommand(rc, statement)); + } else { + snprintf(statement,sizeof(statement),"set turn/realm/%s/user/%s/key %s",(char*)realm,user,skey); + turnFreeRedisReply(redisCommand(rc, statement)); + snprintf(statement,sizeof(statement),"del turn/realm/%s/user/%s/password",(char*)realm,user); + turnFreeRedisReply(redisCommand(rc, statement)); + } + } + + turnFreeRedisReply(redisCommand(rc, "save")); + } +#endif + } else if(!is_st) { + + persistent_users_db_t *pud = get_persistent_users_db(); + char *full_path_to_userdb_file = find_config_file(pud->userdb, 1); + FILE *f = full_path_to_userdb_file ? fopen(full_path_to_userdb_file,"r") : NULL; + int found = 0; + char us[LONG_STRING_SIZE]; + size_t i = 0; + char **content = NULL; + size_t csz = 0; + + STRCPY(us, (char*) user); + strncpy(us + strlen(us), ":", sizeof(us)-1-strlen(us)); + us[sizeof(us)-1]=0; + + if (!f) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "File %s not found, will be created.\n",pud->userdb); + } else { + + char sarg[LONG_STRING_SIZE]; + char sbuf[LONG_STRING_SIZE]; + + for (;;) { + char *s0 = fgets(sbuf, sizeof(sbuf) - 1, f); + if (!s0) + break; + + size_t slen = strlen(s0); + while (slen && (s0[slen - 1] == 10 || s0[slen - 1] == 13)) + s0[--slen] = 0; + + char *s = skip_blanks(s0); + + if (s[0] == '#') + goto add_and_cont; + if (!s[0]) + goto add_and_cont; + + STRCPY(sarg, s); + if (strstr(sarg, us) == sarg) { + if (ct == TA_DELETE_USER) + continue; + + if (found) + continue; + found = 1; + STRCPY(us, (char*) user); + strncpy(us + strlen(us), ":0x", sizeof(us)-1-strlen(us)); + us[sizeof(us)-1]=0; + size_t sz = get_hmackey_size(turn_params.shatype); + for (i = 0; i < sz; i++) { + snprintf( + us + strlen(us), + sizeof(us)-strlen(us), + "%02x", + (unsigned int) key[i]); + } + + s0 = us; + } + + add_and_cont: + content = (char**)realloc(content, sizeof(char*) * (++csz)); + content[csz - 1] = strdup(s0); + } + + fclose(f); + } + + if(!found && (ct == TA_UPDATE_USER)) { + STRCPY(us,(char*)user); + strncpy(us+strlen(us),":0x",sizeof(us)-1-strlen(us)); + us[sizeof(us)-1]=0; + size_t sz = get_hmackey_size(turn_params.shatype); + for(i=0;iuserdb); + + size_t dirsz = strlen(full_path_to_userdb_file)+21; + char *dir = (char*)turn_malloc(dirsz+1); + strncpy(dir,full_path_to_userdb_file,dirsz); + dir[dirsz]=0; + size_t dlen = strlen(dir); + while(dlen) { + if(dir[dlen-1]=='/') + break; + dir[--dlen]=0; + } + strncpy(dir+strlen(dir),".tmp_userdb",dirsz-strlen(dir)); + + f = fopen(dir,"w"); + if(!f) { + perror("file open"); + exit(-1); + } + + for(i=0;itype == 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); + } + } + + for(isz=0;isztype == 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 { + add_ip_list_range(rget->str,ret); + } + turnFreeRedisReply(rget); + } + } + + clean_secrets_list(&keys); + + turnFreeRedisReply(reply); + } + } +#endif + + return ret; +} + +static void ip_list_free(ip_range_list_t *l) +{ + if(l) { + size_t i; + for(i=0;iranges_number;++i) { + if(l->ranges && l->ranges[i]) + free(l->ranges[i]); + if(l->encaddrsranges && l->encaddrsranges[i]) + free(l->encaddrsranges[i]); + } + if(l->ranges) + free(l->ranges); + if(l->encaddrsranges) + free(l->encaddrsranges); + free(l); + } +} + +void update_white_and_black_lists(void) +{ + { + ip_range_list_t *wl = get_ip_list("allowed"); + ip_range_list_t *owl = NULL; + ioa_wrlock_whitelist(NULL); + owl = ipwhitelist; + ipwhitelist = wl; + ioa_unlock_whitelist(NULL); + ip_list_free(owl); + } + { + ip_range_list_t *bl = get_ip_list("denied"); + ip_range_list_t *obl = NULL; + ioa_wrlock_blacklist(NULL); + obl = ipblacklist; + ipblacklist = bl; + ioa_unlock_blacklist(NULL); + ip_list_free(obl); + } +} + +/////////////// add ACL record /////////////////// + +int add_ip_list_range(char* range, ip_range_list_t * list) +{ + 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 format: %s\n", range); + return -1; + } + + if (separator) { + if (make_ioa_addr((const u08bits*) separator + 1, 0, &max) < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong address format: %s\n", separator + 1); + 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 = '-'; + + ++(list->ranges_number); + list->ranges = (char**) realloc(list->ranges, sizeof(char*) * list->ranges_number); + list->ranges[list->ranges_number - 1] = strdup(range); + list->encaddrsranges = (ioa_addr_range**) realloc(list->encaddrsranges, sizeof(ioa_addr_range*) * list->ranges_number); + + list->encaddrsranges[list->ranges_number - 1] = (ioa_addr_range*) turn_malloc(sizeof(ioa_addr_range)); + + ioa_addr_range_set(list->encaddrsranges[list->ranges_number - 1], &min, &max); + + return 0; +} + +/////////// REALM ////////////// + +#if !defined(TURN_NO_HIREDIS) +static int set_redis_realm_opt(char *realm, const char* key, vint *value) +{ + int found = 0; + + redisContext *rc = get_redis_connection(); + + if(rc) { + redisReply *rget = NULL; + + char s[1025]; + + snprintf(s, sizeof(s), "get turn/realm/%s/%s", realm, key); + + 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 { + ur_string_map_lock(realms); + *value = atoi(rget->str); + ur_string_map_unlock(realms); + found = 1; + } + turnFreeRedisReply(rget); + } + } + + return found; +} +#endif + +void reread_realms(void) +{ +#if !defined(TURN_NO_PQ) + PGconn * pqc = get_pqdb_connection(); + if(pqc) { + char statement[LONG_STRING_SIZE]; + + { + snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm"); + PGresult *res = PQexec(pqc, statement); + + if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) { + + ur_string_map *o_to_realm_new = ur_string_map_create(free); + + int i = 0; + for(i=0;ioptions.perf_options.max_bps = turn_params.max_bps; + ur_string_map_unlock(realms); + + ur_string_map_lock(realms); + rp->options.perf_options.total_quota = turn_params.total_quota; + ur_string_map_unlock(realms); + + ur_string_map_lock(realms); + rp->options.perf_options.user_quota = turn_params.user_quota; + ur_string_map_unlock(realms); + + } + } + + snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option"); + PGresult *res = PQexec(pqc, statement); + + if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) { + + int i = 0; + for(i=0;ioptions.perf_options.max_bps = (vint)atoi(vval); + else if(!strcmp(oval,"total-quota")) + rp->options.perf_options.total_quota = (vint)atoi(vval); + else if(!strcmp(oval,"user-quota")) + rp->options.perf_options.user_quota = (vint)atoi(vval); + else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", oval); + } + } + } + } + + if(res) { + PQclear(res); + } + } + } +#endif + +#if !defined(TURN_NO_MYSQL) + MYSQL * myc = get_mydb_connection(); + if(myc) { + char statement[LONG_STRING_SIZE]; + { + snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm"); + int res = mysql_query(myc, statement); + if(res == 0) { + MYSQL_RES *mres = mysql_store_result(myc); + if(mres && mysql_field_count(myc)==2) { + + ur_string_map *o_to_realm_new = ur_string_map_create(free); + + for(;;) { + MYSQL_ROW row = mysql_fetch_row(mres); + if(!row) { + break; + } else { + if(row[0] && row[1]) { + unsigned long *lengths = mysql_fetch_lengths(mres); + if(lengths) { + size_t sz = lengths[0]; + char oval[513]; + ns_bcopy(row[0],oval,sz); + oval[sz]=0; + char *rval=strdup(row[1]); + get_realm(rval); + ur_string_map_value_type value = strdup(rval); + ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) oval, value); + } + } + } + } + + TURN_MUTEX_LOCK(&o_to_realm_mutex); + ur_string_map_free(&o_to_realm); + o_to_realm = o_to_realm_new; + TURN_MUTEX_UNLOCK(&o_to_realm_mutex); + } + + if(mres) + mysql_free_result(mres); + } + } + { + size_t i = 0; + size_t rlsz = 0; + + ur_string_map_lock(realms); + rlsz = realms_list.sz; + ur_string_map_unlock(realms); + + for (i = 0; ioptions.perf_options.max_bps = turn_params.max_bps; + ur_string_map_unlock(realms); + + ur_string_map_lock(realms); + rp->options.perf_options.total_quota = turn_params.total_quota; + ur_string_map_unlock(realms); + + ur_string_map_lock(realms); + rp->options.perf_options.user_quota = turn_params.user_quota; + ur_string_map_unlock(realms); + + } + } + + snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option"); + int res = mysql_query(myc, statement); + if(res == 0) { + MYSQL_RES *mres = mysql_store_result(myc); + if(mres && mysql_field_count(myc)==3) { + + for(;;) { + MYSQL_ROW row = mysql_fetch_row(mres); + if(!row) { + break; + } else { + if(row[0] && row[1] && row[2]) { + unsigned long *lengths = mysql_fetch_lengths(mres); + if(lengths) { + char rval[513]; + size_t sz = lengths[0]; + ns_bcopy(row[0],rval,sz); + rval[sz]=0; + char oval[513]; + sz = lengths[1]; + ns_bcopy(row[1],oval,sz); + oval[sz]=0; + char vval[513]; + sz = lengths[2]; + ns_bcopy(row[2],vval,sz); + vval[sz]=0; + realm_params_t* rp = get_realm(rval); + if(!strcmp(oval,"max-bps")) + rp->options.perf_options.max_bps = (vint)atoi(vval); + else if(!strcmp(oval,"total-quota")) + rp->options.perf_options.total_quota = (vint)atoi(vval); + else if(!strcmp(oval,"user-quota")) + rp->options.perf_options.user_quota = (vint)atoi(vval); + else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", oval); + } + } + } + } + } + } + + if(mres) + mysql_free_result(mres); + } + } +#endif + +#if !defined(TURN_NO_HIREDIS) + if (is_redis_userdb()) { + redisContext *rc = get_redis_connection(); + if (rc) { + + redisReply *reply = (redisReply*) redisCommand(rc, "keys turn/origin/*"); + if (reply) { + + ur_string_map *o_to_realm_new = ur_string_map_create(free); + + secrets_list_t keys; + + init_secrets_list(&keys); + + size_t isz = 0; + + char s[1025]; + + 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); + } + } + + size_t offset = strlen("turn/origin/"); + + for (isz = 0; isz < keys.sz; ++isz) { + char *origin = keys.secrets[isz] + offset; + snprintf(s, sizeof(s), "get %s", keys.secrets[isz]); + 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 { + get_realm(rget->str); + ur_string_map_value_type value = strdup(rget->str); + ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) origin, value); + } + turnFreeRedisReply(rget); + } + } + + clean_secrets_list(&keys); + + TURN_MUTEX_LOCK(&o_to_realm_mutex); + ur_string_map_free(&o_to_realm); + o_to_realm = o_to_realm_new; + TURN_MUTEX_UNLOCK(&o_to_realm_mutex); + + turnFreeRedisReply(reply); + } + + { + size_t i = 0; + size_t rlsz = 0; + + ur_string_map_lock(realms); + rlsz = realms_list.sz; + ur_string_map_unlock(realms); + + for (i = 0; ioptions.perf_options.max_bps))) { + ur_string_map_lock(realms); + rp->options.perf_options.max_bps = turn_params.max_bps; + ur_string_map_unlock(realms); + } + if(!set_redis_realm_opt(realm,"total-quota",&(rp->options.perf_options.total_quota))) { + ur_string_map_lock(realms); + rp->options.perf_options.total_quota = turn_params.total_quota; + ur_string_map_unlock(realms); + } + if(!set_redis_realm_opt(realm,"user-quota",&(rp->options.perf_options.user_quota))) { + ur_string_map_lock(realms); + rp->options.perf_options.user_quota = turn_params.user_quota; + ur_string_map_unlock(realms); + } + } + } + } + } +#endif +} + +/////////////////////////////// diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h new file mode 100644 index 00000000..758166c2 --- /dev/null +++ b/src/apps/relay/userdb.h @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2011, 2012, 2013 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 __USERDB__ +#define __USERDB__ + +#include +#include + +#if !defined(TURN_NO_HIREDIS) +#include "hiredis_libevent2.h" +#endif + +#include "ns_turn_utils.h" +#include "ns_turn_maps.h" +#include "ns_turn_server.h" + +#include "apputils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//////////// Defines ////////////////////////////// + +#define DEFAULT_USERDB_FILE "turnuserdb.conf" + +#define AUTH_SECRET_SIZE (512) + +//////////// REALM ////////////// + +struct _realm_status_t; +typedef struct _realm_status_t realm_status_t; + +struct _realm_params_t; +typedef struct _realm_params_t realm_params_t; + +struct _realm_status_t { + + vint total_current_allocs; + ur_string_map *alloc_counters; + +}; + +struct _realm_params_t { + + int is_default_realm; + + realm_options_t options; + + realm_status_t status; + +}; + +//////////// USER DB ////////////////////////////// + +struct auth_message { + turnserver_id id; + turn_credential_type ct; + u08bits username[STUN_MAX_USERNAME_SIZE + 1]; + u08bits realm[STUN_MAX_REALM_SIZE + 1]; + hmackey_t key; + st_password_t pwd; + get_username_resume_cb resume_func; + ioa_net_data in_buffer; + u64bits ctxkey; + int success; +}; + +enum _TURN_USERDB_TYPE { + TURN_USERDB_TYPE_FILE=0 +#if !defined(TURN_NO_PQ) + ,TURN_USERDB_TYPE_PQ +#endif +#if !defined(TURN_NO_MYSQL) + ,TURN_USERDB_TYPE_MYSQL +#endif +#if !defined(TURN_NO_HIREDIS) + ,TURN_USERDB_TYPE_REDIS +#endif +}; + +typedef enum _TURN_USERDB_TYPE TURN_USERDB_TYPE; + +enum _TURNADMIN_COMMAND_TYPE { + TA_COMMAND_UNKNOWN, + TA_PRINT_KEY, + TA_UPDATE_USER, + TA_DELETE_USER, + TA_LIST_USERS, + TA_SET_SECRET, + TA_SHOW_SECRET, + TA_DEL_SECRET, + TA_ADD_ORIGIN, + TA_DEL_ORIGIN, + TA_LIST_ORIGINS, + TA_SET_REALM_OPTION, + TA_LIST_REALM_OPTIONS +}; + +typedef enum _TURNADMIN_COMMAND_TYPE TURNADMIN_COMMAND_TYPE; + +/////////// SHARED SECRETS ////////////////// + +struct _secrets_list { + char **secrets; + size_t sz; +}; +typedef struct _secrets_list secrets_list_t; + +/////////// USERS PARAM ///////////////////// + +#define TURN_LONG_STRING_SIZE (1025) + +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; + +typedef struct _persistent_users_db_t { + + char userdb[TURN_LONG_STRING_SIZE]; + void *connection; + +} persistent_users_db_t; + +typedef struct _default_users_db_t +{ + TURN_USERDB_TYPE userdb_type; + + persistent_users_db_t persistent_users_db; + + ram_users_db_t ram_db; + +} default_users_db_t; + +///////////////////////////////////////////// + +realm_params_t* get_realm(char* name); +void set_default_realm_name(char *realm); +int change_total_quota(char *realm, int value); +int change_user_quota(char *realm, int value); + +///////////////////////////////////////////// + +void init_secrets_list(secrets_list_t *sl); +void init_dynamic_ip_lists(void); +void update_white_and_black_lists(void); +void clean_secrets_list(secrets_list_t *sl); +size_t get_secrets_list_size(secrets_list_t *sl); +const char* get_secrets_list_elem(secrets_list_t *sl, size_t i); +void add_to_secrets_list(secrets_list_t *sl, const char* elem); + +/////////// USER DB CHECK ////////////////// + +int get_user_key(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, 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, u08bits *realm); +void release_allocation_quota(u08bits *username, u08bits *realm); + +/////////// Handle user DB ///////////////// + +void read_userdb_file(int to_print); +void auth_ping( +#if !defined(TURN_NO_HIREDIS) + redis_context_handle rch +#else + void +#endif +); +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_ip_list_range(char* range, ip_range_list_t * list); + +///////////// Redis ////////////////////// + +#if !defined(TURN_NO_HIREDIS) +#include "hiredis_libevent2.h" +redis_context_handle get_redis_async_connection(struct event_base *base, const char* connection_string, int delete_keys); +#endif + +//////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif +/// __USERDB__/// + diff --git a/src/apps/rfc5769/rfc5769check.c b/src/apps/rfc5769/rfc5769check.c new file mode 100644 index 00000000..a8dc6cf0 --- /dev/null +++ b/src/apps/rfc5769/rfc5769check.c @@ -0,0 +1,405 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include +#include +#include +#include +#include +#include + +#include "ns_turn_utils.h" +#include "apputils.h" +#include "stun_buffer.h" + +////////////////////////////////////////////////// + +static SHATYPE shatype = SHATYPE_SHA1; + +int main(int argc, const char **argv) +{ + int res = -1; + + UNUSED_ARG(argc); + UNUSED_ARG(argv); + + set_logfile("stdout"); + set_system_parameters(0); + + { + const unsigned char reqstc[] = + "\x00\x01\x00\x58" + "\x21\x12\xa4\x42" + "\xb7\xe7\xa7\x01\xbc\x34\xd6\x86\xfa\x87\xdf\xae" + "\x80\x22\x00\x10" + "STUN test client" + "\x00\x24\x00\x04" + "\x6e\x00\x01\xff" + "\x80\x29\x00\x08" + "\x93\x2f\xf9\xb1\x51\x26\x3b\x36" + "\x00\x06\x00\x09" + "\x65\x76\x74\x6a\x3a\x68\x36\x76\x59\x20\x20\x20" + "\x00\x08\x00\x14" + "\x9a\xea\xa7\x0c\xbf\xd8\xcb\x56\x78\x1e\xf2\xb5" + "\xb2\xd3\xf2\x49\xc1\xb5\x71\xa2" + "\x80\x28\x00\x04" + "\xe5\x7a\x3b\xcf"; + + u08bits buf[sizeof(reqstc)]; + memcpy(buf, reqstc, sizeof(reqstc)); + + {//fingerprintfs etc + + res = stun_is_command_message_full_check_str(buf, sizeof(reqstc) - 1, 1, NULL); + printf("RFC 5769 message fingerprint test(0) result: "); + + if (res) { + printf("success\n"); + } else if (res == 0) { + printf("failure on fingerprint(0) check\n"); + exit(-1); + } + } + + {//short-term credentials + u08bits uname[33]; + u08bits realm[33]; + u08bits upwd[33]; + strcpy((char*) upwd, "VOkJxbRl1RmTxUk/WvJxBt"); + + res = stun_check_message_integrity_str(TURN_CREDENTIALS_SHORT_TERM, buf, sizeof(reqstc) - 1, uname, realm, upwd, shatype); + printf("RFC 5769 simple request short-term credentials and integrity test result: "); + + if (res > 0) { + printf("success\n"); + } else if (res == 0) { + printf("failure on integrity check\n"); + exit(-1); + } else { + printf("failure on message structure check\n"); + exit(-1); + } + } + + {//negative fingerprint + buf[27] = 23; + + res = stun_is_command_message_full_check_str(buf, sizeof(reqstc) - 1, 1, NULL); + printf("RFC 5769 NEGATIVE fingerprint test(0) result: "); + + if (!res) { + printf("success\n"); + } else if (res == 0) { + printf("failure on NEGATIVE fingerprint check\n"); + exit(-1); + } + } + } + + { + const unsigned char reqltc[] = "\x00\x01\x00\x60" + "\x21\x12\xa4\x42" + "\x78\xad\x34\x33\xc6\xad\x72\xc0\x29\xda\x41\x2e" + "\x00\x06\x00\x12" + "\xe3\x83\x9e\xe3\x83\x88\xe3\x83\xaa\xe3\x83\x83" + "\xe3\x82\xaf\xe3\x82\xb9\x00\x00" + "\x00\x15\x00\x1c" + "\x66\x2f\x2f\x34\x39\x39\x6b\x39\x35\x34\x64\x36" + "\x4f\x4c\x33\x34\x6f\x4c\x39\x46\x53\x54\x76\x79" + "\x36\x34\x73\x41" + "\x00\x14\x00\x0b" + "\x65\x78\x61\x6d\x70\x6c\x65\x2e\x6f\x72\x67\x00" + "\x00\x08\x00\x14" + "\xf6\x70\x24\x65\x6d\xd6\x4a\x3e\x02\xb8\xe0\x71" + "\x2e\x85\xc9\xa2\x8c\xa8\x96\x66"; + + u08bits user[] = "\xe3\x83\x9e\xe3\x83\x88\xe3\x83\xaa\xe3\x83\x83" + "\xe3\x82\xaf\xe3\x82\xb9"; + + u08bits realm[33]; + u08bits nonce[29]; + u08bits upwd[33]; + + u08bits buf[sizeof(reqltc)]; + memcpy(buf, reqltc, sizeof(reqltc)); + + u08bits uname[sizeof(user)]; + memcpy(uname, user, sizeof(user)); + + strcpy((char*) realm, "example.org"); + strcpy((char*) upwd, "TheMatrIX"); + strcpy((char*)nonce,"f//499k954d6OL34oL9FSTvy64sA"); + + res = stun_check_message_integrity_str(TURN_CREDENTIALS_LONG_TERM, buf, sizeof(reqltc) - 1, uname, realm, + upwd, shatype); + + printf("RFC 5769 message structure, long-term credentials and integrity test result: "); + + if (res > 0) { + printf("success\n"); + } else if (res == 0) { + printf("failure on integrity check\n"); + exit(-1); + } else { + printf("failure on message structure check\n"); + exit(-1); + } + + { //encoding test + printf("RFC 5769 message encoding test result: "); + size_t len = 0; + u16bits message_type = STUN_METHOD_BINDING; + stun_tid tid; + u16bits *buf16 = (u16bits*)buf; + u32bits *buf32 = (u32bits*)buf; + memcpy(tid.tsx_id,"\x78\xad\x34\x33\xc6\xad\x72\xc0\x29\xda\x41\x2e",12); + stun_init_buffer_str(buf,&len); + message_type &= (u16bits)(0x3FFF); + buf16[0]=nswap16(message_type); + buf16[1]=0; + buf32[1]=nswap32(STUN_MAGIC_COOKIE); + stun_tid_message_cpy(buf, &tid); + stun_attr_add_integrity_by_user_str(buf, &len, uname, realm, upwd, nonce, shatype); + if(len != (sizeof(reqltc)-1)) { + printf("failure: length %d, must be %d\n",(int)len,(int)(sizeof(reqltc)-1)); + exit(-1); + } + if(memcmp(buf,reqltc,len)) { + printf("failure: wrong message content\n"); + { + int lines = 29; + int line = 0; + int col = 0; + int cols = 4; + for(line = 0;line 0) { + printf("success\n"); + } else if (res == 0) { + printf("failure on integrity check\n"); + exit(-1); + } else { + printf("failure on message structure check\n"); + exit(-1); + } + } + + {//negative fingerprint + buf[27] = 23; + + res = stun_is_command_message_full_check_str(buf, sizeof(respv4) - 1, 1, NULL); + printf("RFC 5769 NEGATIVE fingerprint test(1) result: "); + + if (!res) { + printf("success\n"); + } else if (res == 0) { + printf("failure on NEGATIVE fingerprint check\n"); + exit(-1); + } + } + + {//IPv4 addr + ioa_addr addr4; + ioa_addr addr4_test; + + printf("RFC 5769 IPv4 encoding result: "); + + res = stun_attr_get_first_addr_str(buf, sizeof(respv4)-1, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &addr4, NULL); + if(res < 0) { + printf("failure on message structure check\n"); + exit(-1); + } + + make_ioa_addr((const u08bits*)"192.0.2.1", 32853, &addr4_test); + if(addr_eq(&addr4,&addr4_test)) { + printf("success\n"); + } else { + printf("failure on IPv4 deconding check\n"); + exit(-1); + } + } + } + + { + const unsigned char respv6[] = "\x01\x01\x00\x48" + "\x21\x12\xa4\x42" + "\xb7\xe7\xa7\x01\xbc\x34\xd6\x86\xfa\x87\xdf\xae" + "\x80\x22\x00\x0b" + "\x74\x65\x73\x74\x20\x76\x65\x63\x74\x6f\x72\x20" + "\x00\x20\x00\x14" + "\x00\x02\xa1\x47" + "\x01\x13\xa9\xfa\xa5\xd3\xf1\x79" + "\xbc\x25\xf4\xb5\xbe\xd2\xb9\xd9" + "\x00\x08\x00\x14" + "\xa3\x82\x95\x4e\x4b\xe6\x7b\xf1\x17\x84\xc9\x7c" + "\x82\x92\xc2\x75\xbf\xe3\xed\x41" + "\x80\x28\x00\x04" + "\xc8\xfb\x0b\x4c"; + + u08bits buf[sizeof(respv6)]; + + { //decoding test + memcpy(buf, respv6, sizeof(respv6)); + + res = stun_is_command_message_full_check_str(buf, sizeof(respv6) - 1, 1, NULL); + printf("RFC 5769 message fingerprint test(2) result: "); + + if (res) { + printf("success\n"); + } else if (res == 0) { + printf("failure on fingerprint(2) check\n"); + exit(-1); + } + } + + {//short-term credentials test + u08bits uname[33]; + u08bits realm[33]; + u08bits upwd[33]; + strcpy((char*) upwd, "VOkJxbRl1RmTxUk/WvJxBt"); + + res = stun_check_message_integrity_str(TURN_CREDENTIALS_SHORT_TERM, buf, sizeof(respv6) - 1, uname, realm, upwd, shatype); + printf("RFC 5769 IPv6 response short-term credentials and integrity test result: "); + + if (res > 0) { + printf("success\n"); + } else if (res == 0) { + printf("failure on integrity check\n"); + exit(-1); + } else { + printf("failure on message structure check\n"); + exit(-1); + } + } + + {//negative decoding test + buf[27] = 23; + + res = stun_is_command_message_full_check_str(buf, sizeof(respv6) - 1, 1, NULL); + printf("RFC 5769 NEGATIVE fingerprint test(2) result: "); + + if (!res) { + printf("success\n"); + } else if (res == 0) { + printf("failure on NEGATIVE fingerprint check\n"); + exit(-1); + } + } + + {//IPv6 deconding test + ioa_addr addr6; + ioa_addr addr6_test; + + printf("RFC 5769 IPv6 encoding result: "); + + res = stun_attr_get_first_addr_str(buf, sizeof(respv6) - 1, + STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &addr6, NULL); + if (res < 0) { + printf("failure on message structure check\n"); + exit(-1); + } + + make_ioa_addr((const u08bits*) "2001:db8:1234:5678:11:2233:4455:6677", 32853, &addr6_test); + if (addr_eq(&addr6, &addr6_test)) { + printf("success\n"); + } else { + printf("failure on IPv6 deconding check\n"); + exit(-1); + } + } + } + + return 0; +} diff --git a/src/apps/stunclient/stunclient.c b/src/apps/stunclient/stunclient.c new file mode 100644 index 00000000..d7ff4c81 --- /dev/null +++ b/src/apps/stunclient/stunclient.c @@ -0,0 +1,466 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include +#include +#include +#include +#include +#include + +#include "ns_turn_utils.h" +#include "apputils.h" +#include "stun_buffer.h" + +#ifdef __cplusplus +#include "TurnMsgLib.h" +#endif + +//////////////////////////////////////////////////// + +static int udp_fd = -1; +static ioa_addr real_local_addr; +static int counter = 0; + +#ifdef __cplusplus + +static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, int response_port, int change_ip, int change_port, int padding) +{ + + ioa_addr remote_addr; + int new_udp_fd = -1; + + memset((void *) &remote_addr, 0, sizeof(ioa_addr)); + if (make_ioa_addr((const u08bits*) rip, rport, &remote_addr) < 0) + err(-1, NULL); + + if (udp_fd < 0) { + udp_fd = socket(remote_addr.ss.sa_family, SOCK_DGRAM, 0); + if (udp_fd < 0) + err(-1, NULL); + + if (!addr_any(&real_local_addr)) { + if (addr_bind(udp_fd, &real_local_addr,0) < 0) + err(-1, NULL); + } + } + + if (response_port >= 0) { + + new_udp_fd = socket(remote_addr.ss.sa_family, SOCK_DGRAM, 0); + if (new_udp_fd < 0) + err(-1, NULL); + + addr_set_port(&real_local_addr, response_port); + + if (addr_bind(new_udp_fd, &real_local_addr, 0) < 0) + err(-1, NULL); + } + + turn::StunMsgRequest req(STUN_METHOD_BINDING); + + req.constructBindingRequest(); + + if (response_port >= 0) { + turn::StunAttrResponsePort rpa; + rpa.setResponsePort((u16bits)response_port); + try { + req.addAttr(rpa); + } catch(turn::WrongStunAttrFormatException &ex1) { + printf("Wrong rp attr format\n"); + exit(-1); + } catch(turn::WrongStunBufferFormatException &ex2) { + printf("Wrong stun buffer format (1)\n"); + exit(-1); + } catch(...) { + printf("Wrong something (1)\n"); + exit(-1); + } + } + if (change_ip || change_port) { + turn::StunAttrChangeRequest cra; + cra.setChangeIp(change_ip); + cra.setChangePort(change_port); + try { + req.addAttr(cra); + } catch(turn::WrongStunAttrFormatException &ex1) { + printf("Wrong cr attr format\n"); + exit(-1); + } catch(turn::WrongStunBufferFormatException &ex2) { + printf("Wrong stun buffer format (2)\n"); + exit(-1); + } catch(...) { + printf("Wrong something (2)\n"); + exit(-1); + } + } + if (padding) { + turn::StunAttrPadding pa; + pa.setPadding(1500); + try { + req.addAttr(pa); + } catch(turn::WrongStunAttrFormatException &ex1) { + printf("Wrong p attr format\n"); + exit(-1); + } catch(turn::WrongStunBufferFormatException &ex2) { + printf("Wrong stun buffer format (3)\n"); + exit(-1); + } catch(...) { + printf("Wrong something (3)\n"); + exit(-1); + } + } + + { + int len = 0; + int slen = get_ioa_addr_len(&remote_addr); + + do { + len = sendto(udp_fd, req.getRawBuffer(), req.getSize(), 0, (struct sockaddr*) &remote_addr, (socklen_t) slen); + } while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN))); + + if (len < 0) + err(-1, NULL); + + } + + if (addr_get_from_sock(udp_fd, &real_local_addr) < 0) { + printf("%s: Cannot get address from local socket\n", __FUNCTION__); + } else { + *port = addr_get_port(&real_local_addr); + } + + { + if(new_udp_fd >= 0) { + close(udp_fd); + udp_fd = new_udp_fd; + new_udp_fd = -1; + } + } + + { + int len = 0; + stun_buffer buf; + u08bits *ptr = buf.buf; + int recvd = 0; + const int to_recv = sizeof(buf.buf); + + do { + len = recv(udp_fd, ptr, to_recv - recvd, 0); + if (len > 0) { + recvd += len; + ptr += len; + break; + } + } while (len < 0 && (errno == EINTR)); + + if (recvd > 0) + len = recvd; + buf.len = len; + + try { + turn::StunMsgResponse res(buf.buf, sizeof(buf.buf), (size_t)buf.len, true); + + if (res.isCommand()) { + + if(res.isSuccess()) { + + if (res.isBindingResponse()) { + + ioa_addr reflexive_addr; + addr_set_any(&reflexive_addr); + turn::StunAttrIterator iter(res,STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS); + if (!iter.eof()) { + + turn::StunAttrAddr addr(iter); + addr.getAddr(reflexive_addr); + + turn::StunAttrIterator iter1(res,STUN_ATTRIBUTE_OTHER_ADDRESS); + if (!iter1.eof()) { + *rfc5780 = 1; + printf("\n========================================\n"); + printf("RFC 5780 response %d\n",++counter); + ioa_addr other_addr; + turn::StunAttrAddr addr1(iter1); + addr1.getAddr(other_addr); + turn::StunAttrIterator iter2(res,STUN_ATTRIBUTE_RESPONSE_ORIGIN); + if (!iter2.eof()) { + ioa_addr response_origin; + turn::StunAttrAddr addr2(iter2); + addr2.getAddr(response_origin); + addr_debug_print(1, &response_origin, "Response origin: "); + } + addr_debug_print(1, &other_addr, "Other addr: "); + } + addr_debug_print(1, &reflexive_addr, "UDP reflexive addr"); + + } else { + printf("Cannot read the response\n"); + } + } else { + printf("Wrong type of response\n"); + } + } else { + int err_code = res.getError(); + std::string reason = res.getReason(); + + printf("The response is an error %d (%s)\n", err_code, reason.c_str()); + } + } else { + printf("The response is not a reponse message\n"); + } + } catch(...) { + printf("The response is not a well formed STUN message\n"); + } + } + + return 0; +} + +#else + +static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, int response_port, int change_ip, int change_port, int padding) +{ + + ioa_addr remote_addr; + int new_udp_fd = -1; + stun_buffer buf; + + ns_bzero(&remote_addr, sizeof(remote_addr)); + if (make_ioa_addr((const u08bits*) rip, rport, &remote_addr) < 0) + err(-1, NULL); + + if (udp_fd < 0) { + udp_fd = socket(remote_addr.ss.sa_family, SOCK_DGRAM, 0); + if (udp_fd < 0) + err(-1, NULL); + + if (!addr_any(&real_local_addr)) { + if (addr_bind(udp_fd, &real_local_addr,0) < 0) + err(-1, NULL); + } + } + + if (response_port >= 0) { + + new_udp_fd = socket(remote_addr.ss.sa_family, SOCK_DGRAM, 0); + if (new_udp_fd < 0) + err(-1, NULL); + + addr_set_port(&real_local_addr, response_port); + + if (addr_bind(new_udp_fd, &real_local_addr,0) < 0) + err(-1, NULL); + } + + stun_prepare_binding_request(&buf); + + if (response_port >= 0) { + stun_attr_add_response_port_str((u08bits*) (buf.buf), (size_t*) &(buf.len), (u16bits) response_port); + } + if (change_ip || change_port) { + stun_attr_add_change_request_str((u08bits*) buf.buf, (size_t*) &(buf.len), change_ip, change_port); + } + if (padding) { + if(stun_attr_add_padding_str((u08bits*) buf.buf, (size_t*) &(buf.len), 1500)<0) { + printf("%s: ERROR: Cannot add padding\n",__FUNCTION__); + } + } + + { + int len = 0; + int slen = get_ioa_addr_len(&remote_addr); + + do { + len = sendto(udp_fd, buf.buf, buf.len, 0, (struct sockaddr*) &remote_addr, (socklen_t) slen); + } while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN))); + + if (len < 0) + err(-1, NULL); + + } + + if (addr_get_from_sock(udp_fd, &real_local_addr) < 0) { + printf("%s: Cannot get address from local socket\n", __FUNCTION__); + } else { + *port = addr_get_port(&real_local_addr); + } + + { + if(new_udp_fd >= 0) { + socket_closesocket(udp_fd); + udp_fd = new_udp_fd; + new_udp_fd = -1; + } + } + + { + int len = 0; + u08bits *ptr = buf.buf; + int recvd = 0; + const int to_recv = sizeof(buf.buf); + + do { + len = recv(udp_fd, ptr, to_recv - recvd, 0); + if (len > 0) { + recvd += len; + ptr += len; + break; + } + } while (len < 0 && ((errno == EINTR) || (errno == EAGAIN))); + + if (recvd > 0) + len = recvd; + buf.len = len; + + if (stun_is_command_message(&buf)) { + + if (stun_is_response(&buf)) { + + if (stun_is_success_response(&buf)) { + + if (stun_is_binding_response(&buf)) { + + ioa_addr reflexive_addr; + addr_set_any(&reflexive_addr); + if (stun_attr_get_first_addr(&buf, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &reflexive_addr, NULL) >= 0) { + + stun_attr_ref sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_OTHER_ADDRESS); + if (sar) { + *rfc5780 = 1; + printf("\n========================================\n"); + printf("RFC 5780 response %d\n",++counter); + ioa_addr other_addr; + stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, &other_addr, NULL); + sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_RESPONSE_ORIGIN); + if (sar) { + ioa_addr response_origin; + stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, &response_origin, NULL); + addr_debug_print(1, &response_origin, "Response origin: "); + } + addr_debug_print(1, &other_addr, "Other addr: "); + } + addr_debug_print(1, &reflexive_addr, "UDP reflexive addr"); + + } else { + printf("Cannot read the response\n"); + } + } else { + printf("Wrong type of response\n"); + } + } else { + int err_code = 0; + u08bits err_msg[1025] = "\0"; + size_t err_msg_size = sizeof(err_msg); + if (stun_is_error_response(&buf, &err_code, err_msg, err_msg_size)) { + printf("The response is an error %d (%s)\n", err_code, (char*) err_msg); + } else { + printf("The response is an unrecognized error\n"); + } + } + } else { + printf("The response is not a reponse message\n"); + } + } else { + printf("The response is not a STUN message\n"); + } + } + + return 0; +} +#endif + +//////////////// local definitions ///////////////// + +static char Usage[] = + "Usage: stunclient [options] address\n" + "Options:\n" + " -p STUN server port (Default: 3478)\n" + " -L Local address to use (optional)\n" + " -f Force RFC 5780 processing\n"; + +////////////////////////////////////////////////// + +int main(int argc, char **argv) +{ + int port = DEFAULT_STUN_PORT; + char local_addr[256]="\0"; + int c=0; + int forceRfc5780 = 0; + + set_logfile("stdout"); + set_system_parameters(0); + + ns_bzero(local_addr, sizeof(local_addr)); + + while ((c = getopt(argc, argv, "p:L:f")) != -1) { + switch(c) { + case 'f': + forceRfc5780 = 1; + break; + case 'p': + port = atoi(optarg); + break; + case 'L': + STRCPY(local_addr, optarg); + break; + default: + fprintf(stderr,"%s\n", Usage); + exit(1); + } + } + + if(optind>=argc) { + fprintf(stderr, "%s\n", Usage); + exit(-1); + } + + addr_set_any(&real_local_addr); + + if(local_addr[0]) { + if(make_ioa_addr((const u08bits*)local_addr, 0, &real_local_addr)<0) { + err(-1,NULL); + } + } + + int local_port = -1; + int rfc5780 = 0; + + run_stunclient(argv[optind], port, &local_port, &rfc5780,-1,0,0,0); + + if(rfc5780 || forceRfc5780) { + run_stunclient(argv[optind], port, &local_port, &rfc5780,local_port+1,1,1,0); + run_stunclient(argv[optind], port, &local_port, &rfc5780,-1,1,1,1); + } + + socket_closesocket(udp_fd); + + return 0; +} diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c new file mode 100644 index 00000000..f7e8fb66 --- /dev/null +++ b/src/apps/uclient/mainuclient.c @@ -0,0 +1,532 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "apputils.h" +#include "uclient.h" +#include "ns_turn_utils.h" +#include "apputils.h" +#include "session.h" +#include "stun_buffer.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +/////////////// extern definitions ///////////////////// + +int clmessage_length=100; +int do_not_use_channel=0; +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; +char g_auth_secret[1025]="\0"; +int g_use_auth_secret_with_timestamp = 0; +int use_fingerprints = 1; + +static char ca_cert_file[1025]=""; +static char cipher_suite[1025]=""; +char cert_file[1025]=""; +char pkey_file[1025]=""; +SSL_CTX *root_tls_ctx[32]; +int root_tls_ctx_num = 0; + +u08bits relay_transport = STUN_ATTRIBUTE_TRANSPORT_UDP_VALUE; +unsigned char client_ifname[1025] = ""; +int passive_tcp = 0; +int mandatory_channel_padding = 0; +int negative_test = 0; +int negative_protocol_test = 0; +int dos = 0; + +SHATYPE shatype = SHATYPE_SHA1; + +int mobility = 0; + +int no_permissions = 0; + +int extra_requests = 0; + +char origin[STUN_MAX_ORIGIN_SIZE+1] = "\0"; + +//////////////// local definitions ///////////////// + +static char Usage[] = + "Usage: uclient [flags] [options] turn-server-ip-address\n" + "Flags:\n" + " -t TCP (default - UDP).\n" + " -T TCP relay transport (default - UDP). Implies options -t, -y, -c, and ignores \n" + " options -s, -e, -r and -g.\n" + " -P Passive TCP (RFC6062 with active peer). Implies -T.\n" + " -S Secure connection: TLS for TCP, DTLS for UDP.\n" + " -U Secure connection with eNULL cipher.\n" + " -v Verbose.\n" + " -s Use send method.\n" + " -y Use client-to-client connections.\n" + " -h Hang on indefinitely after the last sent packet.\n" + " -c No rtcp connections.\n" + " -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" + " -O DOS attack mode (quick connect and exit).\n" + " -H SHA256 digest function for message integrity calculation.\n" + " Without this option, by default, SHA1 is used.\n" + " -M ICE Mobility engaged.\n" + " -I Do not set permissions on TURN relay endpoints\n" + " (for testing the non-standard server relay functionality).\n" + " -G Generate extra requests (create permissions, channel bind).\n" + "Options:\n" + " -l Message length (Default: 100 Bytes).\n" + " -i Certificate file (for secure connections only, optional).\n" + " -k Private key file (for secure connections only).\n" + " -E CA file for server certificate verification, \n" + " if the server certificate to be verified.\n" + " -F Cipher suite for TLS/DTLS. Default value is DEFAULT.\n" + " -p TURN server port (Default: 3478 unsecure, 5349 secure).\n" + " -n Number of messages to send (Default: 5).\n" + " -d Local interface device (optional).\n" + " -L Local address.\n" + " -m Number of clients (default is 1).\n" + " -e Peer address.\n" + " -r Peer port (default 3480).\n" + " -z Per-session packet interval in milliseconds (default is 20 ms).\n" + " -u STUN/TURN user name.\n" + " -w STUN/TURN user password.\n" + " -W TURN REST API authentication secret. Is not compatible with -A option.\n" + " -C TURN REST API timestamp/username separator symbol (character). The default value is ':'.\n" + " -o - the ORIGIN STUN attribute value.\n"; + +////////////////////////////////////////////////// + +void recalculate_restapi_hmac(void) { + + if (g_use_auth_secret_with_timestamp) { + + u08bits hmac[MAXSHASIZE]; + unsigned int hmac_len; + + hmac_len = SHA256SIZEBYTES; + + hmac[0] = 0; + + if (stun_calculate_hmac(g_uname, strlen((char*) g_uname), + (u08bits*) g_auth_secret, strlen(g_auth_secret), hmac, + &hmac_len, SHATYPE_SHA256) >= 0) { + size_t pwd_length = 0; + char *pwd = base64_encode(hmac, hmac_len, &pwd_length); + + if (pwd) { + if (pwd_length > 0) { + ns_bcopy(pwd,g_upwd,pwd_length); + g_upwd[pwd_length] = 0; + } + } + free(pwd); + } + } +} + +int main(int argc, char **argv) +{ + int port = 0; + int messagenumber = 5; + char local_addr[256]; + int c; + int mclient = 1; + char peer_address[129] = "\0"; + int peer_port = PEER_DEFAULT_PORT; + + char rest_api_separator = ':'; + int use_null_cipher=0; + + set_logfile("stdout"); + + set_execdir(); + + set_system_parameters(0); + + ns_bzero(local_addr, sizeof(local_addr)); + + while ((c = getopt(argc, argv, "d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:vsyhcxXgtTSAPDNOUHMRIG")) != -1) { + switch (c){ + case 'o': + STRCPY(origin,optarg); + break; + case 'G': + extra_requests = 1; + break; + case 'F': + STRCPY(cipher_suite,optarg); + break; + case 'I': + no_permissions = 1; + break; + case 'M': + mobility = 1; + break; + case 'H': + shatype = SHATYPE_SHA256; + break; + case 'E': + { + char* fn = find_config_file(optarg,1); + if(!fn) { + fprintf(stderr,"ERROR: file %s not found\n",optarg); + exit(-1); + } + STRCPY(ca_cert_file,fn); + } + break; + case 'O': + dos = 1; + break; + case 'C': + rest_api_separator=*optarg; + break; + case 'D': + mandatory_channel_padding = 1; + break; + case 'N': + negative_test = 1; + break; + case 'R': + negative_protocol_test = 1; + break; + case 'z': + RTP_PACKET_INTERVAL = atoi(optarg); + break; + case 'A': + use_short_term = 1; + break; + case 'u': + STRCPY(g_uname, optarg); + break; + case 'w': + STRCPY(g_upwd, optarg); + break; + case 'g': + dont_fragment = 1; + break; + case 'd': + STRCPY(client_ifname, optarg); + break; + case 'x': + default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; + break; + case 'X': + default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4; + break; + case 'l': + clmessage_length = atoi(optarg); + break; + case 's': + do_not_use_channel = 1; + break; + case 'n': + messagenumber = atoi(optarg); + break; + case 'p': + port = atoi(optarg); + break; + case 'L': + STRCPY(local_addr, optarg); + break; + case 'e': + STRCPY(peer_address, optarg); + break; + case 'r': + peer_port = atoi(optarg); + break; + case 'v': + clnet_verbose = TURN_VERBOSE_NORMAL; + break; + case 'h': + hang_on = 1; + break; + case 'c': + no_rtcp = 1; + break; + case 'm': + mclient = atoi(optarg); + break; + case 'y': + c2c = 1; + break; + case 't': + use_tcp = 1; + break; + case 'P': + passive_tcp = 1; + /* implies 'T': */ + case 'T': + relay_transport = STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE; + break; + case 'U': + use_null_cipher = 1; + /* implies 'S' */ + /* no break */ + case 'S': + use_secure = 1; + break; + case 'W': + g_use_auth_secret_with_timestamp = 1; + STRCPY(g_auth_secret,optarg); + break; + case 'i': + { + char* fn = find_config_file(optarg,1); + if(!fn) { + fprintf(stderr,"ERROR: file %s not found\n",optarg); + exit(-1); + } + STRCPY(cert_file,fn); + free(fn); + } + break; + case 'k': + { + char* fn = find_config_file(optarg,1); + if(!fn) { + fprintf(stderr,"ERROR: file %s not found\n",optarg); + exit(-1); + } + STRCPY(pkey_file,fn); + free(fn); + } + break; + default: + fprintf(stderr, "%s\n", Usage); + exit(1); + } + } + + 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 */ + if(g_uname[0]) { + snprintf(new_uname,sizeof(new_uname),"%lu%c%s",(unsigned long)time(NULL) + exp_time,rest_api_separator, (char*)g_uname); + } else { + snprintf(new_uname,sizeof(new_uname),"%lu", (unsigned long)time(NULL) + exp_time); + } + STRCPY(g_uname,new_uname); + } + { + u08bits hmac[MAXSHASIZE]; + unsigned int hmac_len; + + switch(shatype) { + case SHATYPE_SHA256: + hmac_len = SHA256SIZEBYTES; + break; + default: + hmac_len = SHA1SIZEBYTES; + }; + + hmac[0]=0; + + if(stun_calculate_hmac(g_uname, strlen((char*)g_uname), (u08bits*)g_auth_secret, strlen(g_auth_secret), hmac, &hmac_len, shatype)>=0) { + size_t pwd_length = 0; + char *pwd = base64_encode(hmac,hmac_len,&pwd_length); + + if(pwd) { + if(pwd_length>0) { + ns_bcopy(pwd,g_upwd,pwd_length); + g_upwd[pwd_length]=0; + } + } + free(pwd); + } + } + } + + if(is_TCP_relay()) { + dont_fragment = 0; + no_rtcp = 1; + c2c = 1; + use_tcp = 1; + do_not_use_channel = 1; + } + + if(port == 0) { + if(use_secure) + port = DEFAULT_STUN_TLS_PORT; + else + port = DEFAULT_STUN_PORT; + } + + if (clmessage_length < (int) sizeof(message_info)) + clmessage_length = (int) sizeof(message_info); + + const int max_header = 100; + if(clmessage_length > (int)(STUN_BUFFER_SIZE-max_header)) { + fprintf(stderr,"Message length was corrected to %d\n",(STUN_BUFFER_SIZE-max_header)); + clmessage_length = (int)(STUN_BUFFER_SIZE-max_header); + } + + if (optind >= argc) { + fprintf(stderr, "%s\n", Usage); + exit(-1); + } + + if (!c2c) { + if (make_ioa_addr((const u08bits*) peer_address, peer_port, &peer_addr) < 0) + return -1; + if(peer_addr.ss.sa_family == AF_INET6) + default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; + + } + + /* SSL Init ==>> */ + + if(use_secure) { + + SSL_load_error_strings(); + OpenSSL_add_ssl_algorithms(); + + const char *csuite = "ALL:SSLv2"; //"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++; + root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(SSLv3_client_method()); + SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); + root_tls_ctx_num++; + root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_client_method()); + SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); + root_tls_ctx_num++; +#if defined(SSL_TXT_TLSV1_1) + root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_1_client_method()); + SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); + root_tls_ctx_num++; +#if defined(SSL_TXT_TLSV1_2) + root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_2_client_method()); + SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); + root_tls_ctx_num++; +#endif +#endif + } else { +#if defined(TURN_NO_DTLS) + fprintf(stderr,"ERROR: DTLS is not supported.\n"); + exit(-1); +#else + if(OPENSSL_VERSION_NUMBER < 0x10000000L) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: OpenSSL version is rather old, DTLS may not be working correctly.\n"); + } + root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_client_method()); + SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); + root_tls_ctx_num++; +#endif + } + + int sslind = 0; + for(sslind = 0; sslind +#include + +#include "ns_turn_ioaddr.h" +#include "ns_turn_utils.h" + +#include "stun_buffer.h" +#include "apputils.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +///////// types //////////// + +enum _UR_STATE { + UR_STATE_UNKNOWN=0, + UR_STATE_READY, + UR_STATE_DONE +}; + +typedef enum _UR_STATE UR_STATE; + +//////////////// session info ////////////////////// + +typedef struct +{ + /* RFC 6062 */ + u32bits cid; + ioa_addr tcp_data_local_addr; + ioa_socket_raw tcp_data_fd; + SSL *tcp_data_ssl; + int tcp_data_bound; +} app_tcp_conn_info; + +typedef struct { + ioa_addr local_addr; + char lsaddr[129]; + ioa_addr remote_addr; + char rsaddr[129]; + char ifname[129]; + ioa_addr peer_addr; + ioa_socket_raw fd; + SSL *ssl; + int broken; + u08bits nonce[STUN_MAX_NONCE_SIZE+1]; + u08bits realm[STUN_MAX_REALM_SIZE+1]; + /* RFC 6062 */ + app_tcp_conn_info **tcp_conn; + size_t tcp_conn_number; + int is_peer; + SHATYPE shatype; + char s_mobile_id[33]; +} app_ur_conn_info; + +typedef struct { + app_ur_conn_info pinfo; + UR_STATE state; + unsigned int ctime; + uint16_t chnum; + int wait_cycles; + int timer_cycle; + int known_mtu; + int completed; + struct event *input_ev; + struct event *input_tcp_data_ev; + stun_buffer in_buffer; + stun_buffer out_buffer; + u32bits refresh_time; + u32bits finished_time; + //Msg counters: + int tot_msgnum; + int wmsgnum; + int rmsgnum; + int recvmsgnum; + u32bits recvtimems; + u32bits to_send_timems; + //Statistics: + size_t loss; + u64bits latency; + u64bits jitter; +} app_ur_session; + +/////////////////////////////////////////////////////// + +typedef struct _message_info { + int msgnum; + u64bits mstime; +} message_info; + +/////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__SESSION__ diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c new file mode 100644 index 00000000..35016c8a --- /dev/null +++ b/src/apps/uclient/startuclient.c @@ -0,0 +1,1548 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include + +#include "apputils.h" +#include "ns_turn_utils.h" +#include "startuclient.h" +#include "ns_turn_msg.h" +#include "uclient.h" +#include "session.h" + +#include + +///////////////////////////////////////// + +#define MAX_CONNECT_EFFORTS (77) +#define DTLS_MAX_CONNECT_TIMEOUT (30) +#define EXTRA_CREATE_PERMS (25) + +static uint64_t current_reservation_token = 0; +static int allocate_rtcp = 0; +static const int never_allocate_rtcp = 0; + +///////////////////////////////////////// + +int rare_event(void) +{ + if(dos) + return (((unsigned long)random()) %1000 == 777); + return 0; +} + +int not_rare_event(void) +{ + if(dos) + return ((((unsigned long)random()) %1000) < 200); + return 0; +} + +static int get_allocate_address_family(ioa_addr *relay_addr) { + if(relay_addr->ss.sa_family == AF_INET) + return STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT; + else if(relay_addr->ss.sa_family == AF_INET6) + return STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; + else + return STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_INVALID; +} + +///////////////////////////////////////// + +static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr) +{ + int ctxtype = (int)(((unsigned long)random())%root_tls_ctx_num); + + SSL *ssl = SSL_new(root_tls_ctx[ctxtype]); + + if(use_tcp) { + SSL_set_fd(ssl, fd); + } else { +#if defined(TURN_NO_DTLS) + UNUSED_ARG(remote_addr); + fprintf(stderr,"ERROR: DTLS is not supported.\n"); + exit(-1); +#else + /* Create BIO, connect and set to already connected */ + BIO *bio = BIO_new_dgram(fd, BIO_CLOSE); + //bio = BIO_new_socket(fd, BIO_CLOSE); + + BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &remote_addr->ss); + + SSL_set_bio(ssl, bio, bio); + + { + struct timeval timeout; + /* Set and activate timeouts */ + timeout.tv_sec = DTLS_MAX_CONNECT_TIMEOUT; + timeout.tv_usec = 0; + BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); + } + + set_mtu_df(ssl, fd, remote_addr->ss.sa_family, SOSO_MTU, !use_tcp, clnet_verbose); +#endif + } + + SSL_set_max_cert_list(ssl, 655350); + + if (clnet_verbose) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "call SSL_connect...\n"); + + int rc = 0; + + do { + do { + rc = SSL_connect(ssl); + } while (rc < 0 && errno == EINTR); + if (rc > 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: client session connected with cipher %s, method=%s\n",__FUNCTION__, + SSL_get_cipher(ssl),turn_get_ssl_method(ssl,NULL)); + if(clnet_verbose && SSL_get_peer_certificate(ssl)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "------------------------------------------------------------\n"); + X509_NAME_print_ex_fp(stdout, X509_get_subject_name(SSL_get_peer_certificate(ssl)), 1, + XN_FLAG_MULTILINE); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\n\n Cipher: %s\n", SSL_CIPHER_get_name(SSL_get_current_cipher(ssl))); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\n------------------------------------------------------------\n\n"); + } + break; + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot connect\n", + __FUNCTION__); + switch (SSL_get_error(ssl, rc)) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + if(!dos) usleep(1000); + continue; + default: { + char buf[1025]; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s (%d)\n", + ERR_error_string(ERR_get_error(), buf), SSL_get_error( + ssl, rc)); + exit(-1); + } + }; + } + } while (1); + + if (clnet_verbose && SSL_get_peer_certificate(ssl)) { + if(use_tcp) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "------TLS---------------------------------------------------\n"); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "------DTLS---------------------------------------------------\n"); + } + X509_NAME_print_ex_fp(stdout, X509_get_subject_name( + SSL_get_peer_certificate(ssl)), 1, XN_FLAG_MULTILINE); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\n\n Cipher: %s\n", + SSL_CIPHER_get_name(SSL_get_current_cipher(ssl))); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "\n------------------------------------------------------------\n\n"); + } + + return ssl; +} + +int socket_connect(evutil_socket_t clnet_fd, ioa_addr *remote_addr, int *connect_err) +{ + if (addr_connect(clnet_fd, remote_addr, connect_err) < 0) { + if(*connect_err == EINPROGRESS) + return 0; + if (*connect_err == EADDRINUSE) + return +1; + perror("connect"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot connect to remote addr: %d\n", __FUNCTION__,*connect_err); + exit(-1); + } + + return 0; +} + +static int clnet_connect(uint16_t clnet_remote_port, const char *remote_address, + const unsigned char* ifname, const char *local_address, int verbose, + app_ur_conn_info *clnet_info) { + + ioa_addr local_addr; + evutil_socket_t clnet_fd; + int connect_err; + + ioa_addr remote_addr; + + start_socket: + + clnet_fd = -1; + connect_err = 0; + + ns_bzero(&remote_addr, sizeof(ioa_addr)); + if (make_ioa_addr((const u08bits*) remote_address, clnet_remote_port, + &remote_addr) < 0) + return -1; + + ns_bzero(&local_addr, sizeof(ioa_addr)); + + clnet_fd = socket(remote_addr.ss.sa_family, use_tcp ? SOCK_STREAM : SOCK_DGRAM, 0); + if (clnet_fd < 0) { + perror("socket"); + exit(-1); + } + + if (sock_bind_to_device(clnet_fd, ifname) < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "Cannot bind client socket to device %s\n", ifname); + } + + set_sock_buf_size(clnet_fd, UR_CLIENT_SOCK_BUF_SIZE); + + if(clnet_info->is_peer && (*local_address==0)) { + + if(remote_addr.ss.sa_family == AF_INET6) { + if (make_ioa_addr((const u08bits*) "::1", 0, &local_addr) < 0) { + return -1; + } + } else { + if (make_ioa_addr((const u08bits*) "127.0.0.1", 0, &local_addr) < 0) { + return -1; + } + } + + addr_bind(clnet_fd, &local_addr, 0); + + } else if (strlen(local_address) > 0) { + + if (make_ioa_addr((const u08bits*) local_address, 0, + &local_addr) < 0) + return -1; + + addr_bind(clnet_fd, &local_addr,0); + } + + if(clnet_info->is_peer) { + ; + } else if(socket_connect(clnet_fd, &remote_addr, &connect_err)>0) + goto start_socket; + + if (clnet_info) { + addr_cpy(&(clnet_info->remote_addr), &remote_addr); + addr_cpy(&(clnet_info->local_addr), &local_addr); + clnet_info->fd = clnet_fd; + addr_get_from_sock(clnet_fd, &(clnet_info->local_addr)); + STRCPY(clnet_info->lsaddr,local_address); + STRCPY(clnet_info->rsaddr,remote_address); + STRCPY(clnet_info->ifname,(const char*)ifname); + } + + if (use_secure) { + clnet_info->ssl = tls_connect(clnet_info->fd, &remote_addr); + if (!clnet_info->ssl) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot SSL connect to remote addr\n", __FUNCTION__); + exit(-1); + } + } + + if(verbose && clnet_info) { + addr_debug_print(verbose, &(clnet_info->local_addr), "Connected from"); + addr_debug_print(verbose, &remote_addr, "Connected to"); + } + + if(!dos) usleep(500); + + return 0; +} + +int read_mobility_ticket(app_ur_conn_info *clnet_info, stun_buffer *message) +{ + int ret = 0; + if(clnet_info && message) { + stun_attr_ref s_mobile_id_sar = stun_attr_get_first_by_type(message, STUN_ATTRIBUTE_MOBILITY_TICKET); + if(s_mobile_id_sar) { + int smid_len = stun_attr_get_len(s_mobile_id_sar); + if(smid_len>0 && (((size_t)smid_len)s_mobile_id))) { + const u08bits* smid_val = stun_attr_get_value(s_mobile_id_sar); + if(smid_val) { + ns_bcopy(smid_val, clnet_info->s_mobile_id, (size_t)smid_len); + clnet_info->s_mobile_id[smid_len] = 0; + if (clnet_verbose) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: smid=%s\n", __FUNCTION__, clnet_info->s_mobile_id); + } + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: ERROR: smid_len=%d\n", __FUNCTION__, smid_len); + ret = -1; + } + } + } + return ret; +} + +static int clnet_allocate(int verbose, + app_ur_conn_info *clnet_info, + ioa_addr *relay_addr, + int af, + char *turn_addr, u16bits *turn_port) { + + int af_cycle = 0; + int reopen_socket = 0; + + int allocate_finished; + + beg_allocate: + + allocate_finished=0; + + while (!allocate_finished && af_cycle++ < 32) { + + int allocate_sent = 0; + + if(reopen_socket && !use_tcp) { + socket_closesocket(clnet_info->fd); + clnet_info->fd = -1; + if (clnet_connect(addr_get_port(&(clnet_info->remote_addr)), clnet_info->rsaddr, (u08bits*)clnet_info->ifname, clnet_info->lsaddr, + verbose, clnet_info) < 0) { + exit(-1); + } + reopen_socket = 0; + } + + stun_buffer message; + if(current_reservation_token) + af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT; + + if(!dos) + stun_set_allocate_request(&message, 800, af, relay_transport, mobility); + else + stun_set_allocate_request(&message, 300, af, relay_transport, mobility); + if(dont_fragment) + stun_attr_add(&message, STUN_ATTRIBUTE_DONT_FRAGMENT, NULL, 0); + if(!no_rtcp) { + if (!never_allocate_rtcp && allocate_rtcp) { + uint64_t reservation_token = ioa_ntoh64(current_reservation_token); + stun_attr_add(&message, STUN_ATTRIBUTE_RESERVATION_TOKEN, + (char*) (&reservation_token), 8); + } else { + stun_attr_add_even_port(&message, 1); + } + } + + if(origin[0]) + stun_attr_add(&message, STUN_ATTRIBUTE_ORIGIN, origin, strlen(origin)); + + if(add_integrity(clnet_info, &message)<0) return -1; + + stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); + + while (!allocate_sent) { + + int len = send_buffer(clnet_info, &message,0,0); + + if (len > 0) { + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "allocate sent\n"); + } + allocate_sent = 1; + } else { + perror("send"); + exit(1); + } + } + + ////////////<<==allocate send + + if(not_rare_event()) return 0; + + ////////allocate response==>> + { + int allocate_received = 0; + stun_buffer message; + while (!allocate_received) { + + int len = recv_buffer(clnet_info, &message, 1, 0); + + if (len > 0) { + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "allocate response received: \n"); + } + message.len = len; + int err_code = 0; + u08bits err_msg[129]; + if (stun_is_success_response(&message)) { + allocate_received = 1; + allocate_finished = 1; + + if(clnet_info->nonce[0] || use_short_term) { + SHATYPE sht = clnet_info->shatype; + if(stun_check_message_integrity_str(get_turn_credentials_type(), + message.buf, (size_t)(message.len), g_uname, + clnet_info->realm, g_upwd, sht)<1) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in allocate message received from server\n"); + return -1; + } + } + + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); + } + if (stun_attr_get_first_addr(&message, + STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, relay_addr, + NULL) < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: !!!: relay addr cannot be received\n", + __FUNCTION__); + return -1; + } else { + if (verbose) { + ioa_addr remote_addr; + memcpy(&remote_addr, relay_addr, + sizeof(ioa_addr)); + addr_debug_print(verbose, &remote_addr, + "Received relay addr"); + } + } + stun_attr_ref rt_sar = stun_attr_get_first_by_type( + &message, STUN_ATTRIBUTE_RESERVATION_TOKEN); + uint64_t rtv = stun_attr_get_reservation_token_value(rt_sar); + current_reservation_token = rtv; + if (verbose) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: rtv=%llu\n", __FUNCTION__, rtv); + + read_mobility_ticket(clnet_info, &message); + + } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, + &err_code,err_msg,sizeof(err_msg), + clnet_info->realm,clnet_info->nonce)) { + if(err_code == SHA_TOO_WEAK && (clnet_info->shatype == SHATYPE_SHA1)) { + clnet_info->shatype = SHATYPE_SHA256; + recalculate_restapi_hmac(); + } + goto beg_allocate; + } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { + + if(err_code == SHA_TOO_WEAK && (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) { + SHATYPE sht = clnet_info->shatype; + if(stun_check_message_integrity_str(get_turn_credentials_type(), + message.buf, (size_t)(message.len), g_uname, + clnet_info->realm, g_upwd, sht)<1) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in allocate message received from server\n"); + return -1; + } + } + + ioa_addr alternate_server; + if(stun_attr_get_first_addr(&message, STUN_ATTRIBUTE_ALTERNATE_SERVER, &alternate_server, NULL)==-1) { + //error + } else if(turn_addr && turn_port){ + addr_to_string_no_port(&alternate_server, (u08bits*)turn_addr); + *turn_port = (u16bits)addr_get_port(&alternate_server); + } + + } + + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "error %d (%s)\n", + err_code,(char*)err_msg); + if (err_code != 437) { + allocate_finished = 1; + current_reservation_token = 0; + return -1; + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "trying allocate again...\n", err_code); + sleep(1); + reopen_socket = 1; + } + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "unknown allocate response\n"); + /* Try again ? */ + } + } else { + perror("recv"); + exit(-1); + break; + } + } + } + } + ////////////<<== allocate response received + + if(rare_event()) return 0; + + if(!allocate_finished) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Cannot complete Allocation\n"); + exit(-1); + } + + allocate_rtcp = !allocate_rtcp; + + if (1) { + + af_cycle = 0; + + if(clnet_info->s_mobile_id[0]) { + + int fd = clnet_info->fd; + SSL* ssl = clnet_info->ssl; + + int close_now = (int)(random()%2); + + if(close_now) { + int close_socket = (int)(random()%2); + if(ssl && !close_socket) { + SSL_shutdown(ssl); + SSL_free(ssl); + ssl = NULL; + fd = -1; + } else if(fd>=0) { + close(fd); + fd = -1; + ssl = NULL; + } + } + + app_ur_conn_info ci; + ns_bcopy(clnet_info,&ci,sizeof(ci)); + ci.fd = -1; + ci.ssl = NULL; + clnet_info->fd = -1; + clnet_info->ssl = NULL; + //Reopen: + if(clnet_connect(addr_get_port(&(ci.remote_addr)), ci.rsaddr, + (unsigned char*)ci.ifname, ci.lsaddr, clnet_verbose, + clnet_info)<0) { + exit(-1); + } + + if(ssl) { + SSL_shutdown(ssl); + SSL_free(ssl); + } else if(fd>=0) { + close(fd); + } + } + + beg_refresh: + + if(af_cycle++>32) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Cannot complete Refresh\n"); + exit(-1); + } + + //==>>refresh request, for an example only: + { + int refresh_sent = 0; + + stun_buffer message; + stun_init_request(STUN_METHOD_REFRESH, &message); + uint32_t lt = htonl(600); + stun_attr_add(&message, STUN_ATTRIBUTE_LIFETIME, (const char*) <, + 4); + + if(clnet_info->s_mobile_id[0]) { + stun_attr_add(&message, STUN_ATTRIBUTE_MOBILITY_TICKET, (const char*)clnet_info->s_mobile_id, strlen(clnet_info->s_mobile_id)); + } + + if(add_integrity(clnet_info, &message)<0) return -1; + + stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); + + while (!refresh_sent) { + + int len = send_buffer(clnet_info, &message, 0,0); + + if (len > 0) { + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "refresh sent\n"); + } + refresh_sent = 1; + } else { + perror("send"); + exit(1); + } + } + } + + if(not_rare_event()) return 0; + + ////////refresh response==>> + { + int refresh_received = 0; + stun_buffer message; + while (!refresh_received) { + + int len = recv_buffer(clnet_info, &message, 1, 0); + + if (len > 0) { + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "refresh response received: \n"); + } + message.len = len; + int err_code = 0; + u08bits err_msg[129]; + if (stun_is_success_response(&message)) { + read_mobility_ticket(clnet_info, &message); + refresh_received = 1; + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); + } + } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, + &err_code,err_msg,sizeof(err_msg), + clnet_info->realm,clnet_info->nonce)) { + if(err_code == SHA_TOO_WEAK && (clnet_info->shatype == SHATYPE_SHA1)) { + clnet_info->shatype = SHATYPE_SHA256; + recalculate_restapi_hmac(); + } + goto beg_refresh; + } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { + refresh_received = 1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "error %d (%s)\n", + err_code,(char*)err_msg); + return -1; + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "unknown refresh response\n"); + /* Try again ? */ + } + } else { + perror("recv"); + exit(-1); + break; + } + } + } + } + + return 0; +} + +static int turn_channel_bind(int verbose, uint16_t *chn, + app_ur_conn_info *clnet_info, ioa_addr *peer_addr) { + + beg_bind: + + { + int cb_sent = 0; + + stun_buffer message; + + if(negative_test) { + *chn = stun_set_channel_bind_request(&message, peer_addr, (u16bits)random()); + } else { + *chn = stun_set_channel_bind_request(&message, peer_addr, *chn); + } + + if(add_integrity(clnet_info, &message)<0) return -1; + + stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); + + while (!cb_sent) { + + int len = send_buffer(clnet_info, &message, 0,0); + if (len > 0) { + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "channel bind sent\n"); + } + cb_sent = 1; + } else { + perror("send"); + exit(1); + } + } + } + + ////////////<<==channel bind send + + if(not_rare_event()) return 0; + + ////////channel bind response==>> + + { + int cb_received = 0; + stun_buffer message; + while (!cb_received) { + + int len = recv_buffer(clnet_info, &message, 1, 0); + if (len > 0) { + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "cb response received: \n"); + } + int err_code = 0; + u08bits err_msg[129]; + if (stun_is_success_response(&message)) { + + cb_received = 1; + + if(clnet_info->nonce[0] || use_short_term) { + SHATYPE sht = clnet_info->shatype; + if(stun_check_message_integrity_str(get_turn_credentials_type(), + message.buf, (size_t)(message.len), g_uname, + clnet_info->realm, g_upwd, sht)<1) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in channel bind message received from server\n"); + return -1; + } + } + + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success: 0x%x\n", + (int) (*chn)); + } + } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, + &err_code,err_msg,sizeof(err_msg), + clnet_info->realm,clnet_info->nonce)) { + if(err_code == SHA_TOO_WEAK && (clnet_info->shatype == SHATYPE_SHA1)) { + clnet_info->shatype = SHATYPE_SHA256; + recalculate_restapi_hmac(); + } + goto beg_bind; + } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { + cb_received = 1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "channel bind: error %d (%s)\n", + err_code,(char*)err_msg); + return -1; + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "unknown channel bind response\n"); + /* Try again ? */ + } + } else { + perror("recv"); + exit(-1); + break; + } + } + } + + return 0; +} + +static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, + ioa_addr *peer_addr, int addrnum) +{ + + if(no_permissions || (addrnum<1)) + return 0; + + char saddr[129]="\0"; + if (verbose) { + addr_to_string(peer_addr,(u08bits*)saddr); + } + + beg_cp: + + { + int cp_sent = 0; + + stun_buffer message; + + stun_init_request(STUN_METHOD_CREATE_PERMISSION, &message); + { + int addrindex; + for(addrindex=0;addrindex 0) { + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "create perm sent: %s\n",saddr); + } + cp_sent = 1; + } else { + perror("send"); + exit(1); + } + } + } + + ////////////<<==create permission send + + if(not_rare_event()) return 0; + + ////////create permission response==>> + + { + int cp_received = 0; + stun_buffer message; + while (!cp_received) { + + int len = recv_buffer(clnet_info, &message, 1, 0); + if (len > 0) { + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "cp response received: \n"); + } + int err_code = 0; + u08bits err_msg[129]; + if (stun_is_success_response(&message)) { + + cp_received = 1; + + if(clnet_info->nonce[0] || use_short_term) { + SHATYPE sht = clnet_info->shatype; + if(stun_check_message_integrity_str(get_turn_credentials_type(), + message.buf, (size_t)(message.len), g_uname, + clnet_info->realm, g_upwd, sht)<1) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in create permission message received from server\n"); + return -1; + } + } + + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); + } + } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, + &err_code,err_msg,sizeof(err_msg), + clnet_info->realm,clnet_info->nonce)) { + if(err_code == SHA_TOO_WEAK && (clnet_info->shatype == SHATYPE_SHA1)) { + clnet_info->shatype = SHATYPE_SHA256; + recalculate_restapi_hmac(); + } + goto beg_cp; + } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { + cp_received = 1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "create permission error %d (%s)\n", + err_code,(char*)err_msg); + return -1; + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "unknown create permission response\n"); + /* Try again ? */ + } + } else { + perror("recv"); + exit(-1); + } + } + } + + return 0; +} + +int start_connection(uint16_t clnet_remote_port0, + const char *remote_address0, + const unsigned char* ifname, const char *local_address, + int verbose, + app_ur_conn_info *clnet_info_probe, + app_ur_conn_info *clnet_info, + uint16_t *chn, + app_ur_conn_info *clnet_info_rtcp, + uint16_t *chn_rtcp) { + + ioa_addr relay_addr; + ioa_addr relay_addr_rtcp; + ioa_addr peer_addr_rtcp; + + addr_cpy(&peer_addr_rtcp,&peer_addr); + addr_set_port(&peer_addr_rtcp,addr_get_port(&peer_addr_rtcp)+1); + + /* Probe: */ + + if (clnet_connect(clnet_remote_port0, remote_address0, ifname, local_address, + verbose, clnet_info_probe) < 0) { + exit(-1); + } + + uint16_t clnet_remote_port = clnet_remote_port0; + char remote_address[1025]; + STRCPY(remote_address,remote_address0); + + clnet_allocate(verbose, clnet_info_probe, &relay_addr, default_address_family, remote_address, &clnet_remote_port); + + /* Real: */ + + *chn = 0; + if(chn_rtcp) *chn_rtcp=0; + + if (clnet_connect(clnet_remote_port, remote_address, ifname, local_address, + verbose, clnet_info) < 0) { + exit(-1); + } + + if(!no_rtcp) { + if (clnet_connect(clnet_remote_port, remote_address, ifname, local_address, + verbose, clnet_info_rtcp) < 0) { + exit(-1); + } + } + + int af = default_address_family ? default_address_family : get_allocate_address_family(&peer_addr); + if (clnet_allocate(verbose, clnet_info, &relay_addr, af, NULL,NULL) < 0) { + exit(-1); + } + + if(rare_event()) return 0; + + if(!no_rtcp) { + af = default_address_family ? default_address_family : get_allocate_address_family(&peer_addr_rtcp); + if (clnet_allocate(verbose, clnet_info_rtcp, &relay_addr_rtcp, af,NULL,NULL) < 0) { + exit(-1); + } + if(rare_event()) return 0; + } + + if (!dos) { + if (!do_not_use_channel) { + /* These multiple "channel bind" requests are here only because + * we are playing with the TURN server trying to screw it */ + if (turn_channel_bind(verbose, chn, clnet_info, &peer_addr_rtcp) + < 0) { + exit(-1); + } + if(rare_event()) return 0; + + if (turn_channel_bind(verbose, chn, clnet_info, &peer_addr_rtcp) + < 0) { + exit(-1); + } + if(rare_event()) return 0; + *chn = 0; + if (turn_channel_bind(verbose, chn, clnet_info, &peer_addr) < 0) { + exit(-1); + } + + if(rare_event()) return 0; + if (turn_channel_bind(verbose, chn, clnet_info, &peer_addr) < 0) { + exit(-1); + } + if(rare_event()) return 0; + + if(extra_requests) { + const char *sarbaddr = "164.156.178.190"; + if(random() % 2 == 0) + sarbaddr = "2001::172"; + ioa_addr arbaddr; + make_ioa_addr((const u08bits*)sarbaddr, 333, &arbaddr); + int i; + int maxi = (unsigned short)random() % EXTRA_CREATE_PERMS; + for(i=0;i0) + addr_cpy(&arbaddr[i],&arbaddr[0]); + addr_set_port(&arbaddr[i], (unsigned short)random()); + u08bits *u=(u08bits*)&(arbaddr[i].s4.sin_addr); + u[(unsigned short)random()%4] = u[(unsigned short)random()%4] + 1; + //char sss[128]; + //addr_to_string(&arbaddr[i],(u08bits*)sss); + //printf("%s: 111.111: %s\n",__FUNCTION__,sss); + } + turn_create_permission(verbose, clnet_info, arbaddr, maxi); + } + } else { + + int before=(random()%2 == 0); + + if(before) { + if (turn_create_permission(verbose, clnet_info, &peer_addr, 1) < 0) { + exit(-1); + } + if(rare_event()) return 0; + if (turn_create_permission(verbose, clnet_info, &peer_addr_rtcp, 1) + < 0) { + exit(-1); + } + if(rare_event()) return 0; + } + + if(extra_requests) { + const char *sarbaddr = "64.56.78.90"; + if(random() % 2 == 0) + sarbaddr = "2001::172"; + ioa_addr arbaddr[EXTRA_CREATE_PERMS]; + make_ioa_addr((const u08bits*)sarbaddr, 333, &arbaddr[0]); + int i; + int maxi = (unsigned short)random() % EXTRA_CREATE_PERMS; + for(i=0;i0) + addr_cpy(&arbaddr[i],&arbaddr[0]); + addr_set_port(&arbaddr[i], (unsigned short)random()); + u08bits *u=(u08bits*)&(arbaddr[i].s4.sin_addr); + u[(unsigned short)random()%4] = u[(unsigned short)random()%4] + 1; + //char sss[128]; + //addr_to_string(&arbaddr,(u08bits*)sss); + //printf("%s: 111.111: %s\n",__FUNCTION__,sss); + } + turn_create_permission(verbose, clnet_info, arbaddr, maxi); + } + + if(!before) { + if (turn_create_permission(verbose, clnet_info, &peer_addr, 1) < 0) { + exit(-1); + } + if(rare_event()) return 0; + if (turn_create_permission(verbose, clnet_info, &peer_addr_rtcp, 1) + < 0) { + exit(-1); + } + if(rare_event()) return 0; + } + + if (!no_rtcp) { + if (turn_create_permission(verbose, clnet_info_rtcp, + &peer_addr_rtcp, 1) < 0) { + exit(-1); + } + if(rare_event()) return 0; + if (turn_create_permission(verbose, clnet_info_rtcp, &peer_addr, 1) + < 0) { + exit(-1); + } + if(rare_event()) return 0; + } + } + } + + addr_cpy(&(clnet_info->peer_addr), &peer_addr); + if(!no_rtcp) + addr_cpy(&(clnet_info_rtcp->peer_addr), &peer_addr_rtcp); + + return 0; +} + + +int start_c2c_connection(uint16_t clnet_remote_port0, + const char *remote_address0, const unsigned char* ifname, + const char *local_address, int verbose, + app_ur_conn_info *clnet_info_probe, + app_ur_conn_info *clnet_info1, + uint16_t *chn1, app_ur_conn_info *clnet_info1_rtcp, + uint16_t *chn1_rtcp, + app_ur_conn_info *clnet_info2, uint16_t *chn2, + app_ur_conn_info *clnet_info2_rtcp, + uint16_t *chn2_rtcp) { + + ioa_addr relay_addr1; + ioa_addr relay_addr1_rtcp; + + ioa_addr relay_addr2; + ioa_addr relay_addr2_rtcp; + + *chn1 = 0; + *chn2 = 0; + if(chn1_rtcp) *chn1_rtcp=0; + if(chn2_rtcp) *chn2_rtcp=0; + + /* Probe: */ + + if (clnet_connect(clnet_remote_port0, remote_address0, ifname, local_address, + verbose, clnet_info_probe) < 0) { + exit(-1); + } + + uint16_t clnet_remote_port = clnet_remote_port0; + char remote_address[1025]; + STRCPY(remote_address,remote_address0); + + clnet_allocate(verbose, clnet_info_probe, &relay_addr1, default_address_family, remote_address, &clnet_remote_port); + + if(rare_event()) return 0; + + /* Real: */ + + if (clnet_connect(clnet_remote_port, remote_address, ifname, local_address, + verbose, clnet_info1) < 0) { + exit(-1); + } + + if(!no_rtcp) + if (clnet_connect(clnet_remote_port, remote_address, ifname, local_address, + verbose, clnet_info1_rtcp) < 0) { + exit(-1); + } + + if(passive_tcp) + clnet_info2->is_peer = 1; + + if (clnet_connect(clnet_remote_port, remote_address, ifname, local_address, + verbose, clnet_info2) < 0) { + exit(-1); + } + + if(!no_rtcp) + if (clnet_connect(clnet_remote_port, remote_address, ifname, local_address, + verbose, clnet_info2_rtcp) < 0) { + exit(-1); + } + + if(!no_rtcp) { + + if (clnet_allocate(verbose, clnet_info1, &relay_addr1, default_address_family,NULL,NULL) + < 0) { + exit(-1); + } + + if(rare_event()) return 0; + + if (clnet_allocate(verbose, clnet_info1_rtcp, + &relay_addr1_rtcp, default_address_family,NULL,NULL) < 0) { + exit(-1); + } + + if(rare_event()) return 0; + + if (clnet_allocate(verbose, clnet_info2, &relay_addr2, default_address_family,NULL,NULL) + < 0) { + exit(-1); + } + + if(rare_event()) return 0; + + if (clnet_allocate(verbose, clnet_info2_rtcp, + &relay_addr2_rtcp, default_address_family,NULL,NULL) < 0) { + exit(-1); + } + + if(rare_event()) return 0; + } else { + + if (clnet_allocate(verbose, clnet_info1, &relay_addr1, default_address_family,NULL,NULL) + < 0) { + exit(-1); + } + if(rare_event()) return 0; + if(!(clnet_info2->is_peer)) { + if (clnet_allocate(verbose, clnet_info2, &relay_addr2, default_address_family,NULL,NULL) < 0) { + exit(-1); + } + if(rare_event()) return 0; + } else { + addr_cpy(&(clnet_info2->remote_addr),&relay_addr1); + addr_cpy(&relay_addr2,&(clnet_info2->local_addr)); + } + } + + if (!do_not_use_channel) { + if (turn_channel_bind(verbose, chn1, clnet_info1, &relay_addr2) < 0) { + exit(-1); + } + + if(extra_requests) { + const char *sarbaddr = "164.156.178.190"; + if(random() % 2 == 0) + sarbaddr = "2001::172"; + ioa_addr arbaddr; + make_ioa_addr((const u08bits*)sarbaddr, 333, &arbaddr); + int i; + int maxi = (unsigned short)random() % EXTRA_CREATE_PERMS; + for(i=0;i0) + addr_cpy(&arbaddr[i],&arbaddr[0]); + addr_set_port(&arbaddr[i], (unsigned short)random()); + u08bits *u=(u08bits*)&(arbaddr[i].s4.sin_addr); + u[(unsigned short)random()%4] = u[(unsigned short)random()%4] + 1; + //char sss[128]; + //addr_to_string(&arbaddr[i],(u08bits*)sss); + //printf("%s: 111.111: %s\n",__FUNCTION__,sss); + } + turn_create_permission(verbose, clnet_info1, arbaddr, maxi); + } + + if(!no_rtcp) + if (turn_channel_bind(verbose, chn1_rtcp, clnet_info1_rtcp, + &relay_addr2_rtcp) < 0) { + exit(-1); + } + if(rare_event()) return 0; + if (turn_channel_bind(verbose, chn2, clnet_info2, &relay_addr1) < 0) { + exit(-1); + } + if(rare_event()) return 0; + if(!no_rtcp) + if (turn_channel_bind(verbose, chn2_rtcp, clnet_info2_rtcp, + &relay_addr1_rtcp) < 0) { + exit(-1); + } + if(rare_event()) return 0; + } else { + + if (turn_create_permission(verbose, clnet_info1, &relay_addr2, 1) < 0) { + exit(-1); + } + + if(extra_requests) { + const char *sarbaddr = "64.56.78.90"; + if(random() % 2 == 0) + sarbaddr = "2001::172"; + ioa_addr arbaddr; + make_ioa_addr((const u08bits*)sarbaddr, 333, &arbaddr); + int i; + int maxi = (unsigned short)random() % EXTRA_CREATE_PERMS; + for(i=0;iis_peer)) { + if (turn_create_permission(verbose, clnet_info2, &relay_addr1, 1) < 0) { + exit(-1); + } + if(rare_event()) return 0; + } + if (!no_rtcp) + if (turn_create_permission(verbose, clnet_info2_rtcp, &relay_addr1_rtcp, 1) < 0) { + exit(-1); + } + if(rare_event()) return 0; + } + + addr_cpy(&(clnet_info1->peer_addr), &relay_addr2); + if(!no_rtcp) + addr_cpy(&(clnet_info1_rtcp->peer_addr), &relay_addr2_rtcp); + addr_cpy(&(clnet_info2->peer_addr), &relay_addr1); + if(!no_rtcp) + addr_cpy(&(clnet_info2_rtcp->peer_addr), &relay_addr1_rtcp); + + return 0; +} + +//////////// RFC 6062 /////////////// + +int turn_tcp_connect(int verbose, app_ur_conn_info *clnet_info, ioa_addr *peer_addr) { + + { + int cp_sent = 0; + + stun_buffer message; + + stun_init_request(STUN_METHOD_CONNECT, &message); + stun_attr_add_addr(&message, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, peer_addr); + + if(add_integrity(clnet_info, &message)<0) return -1; + + stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); + + while (!cp_sent) { + + int len = send_buffer(clnet_info, &message, 0,0); + + if (len > 0) { + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "tcp connect sent\n"); + } + cp_sent = 1; + } else { + perror("send"); + exit(1); + } + } + } + + ////////////<<==connect send + + return 0; +} + +static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, app_tcp_conn_info *atc, int errorOK) { + + beg_cb: + + { + int cb_sent = 0; + + stun_buffer message; + u32bits cid = atc->cid; + + stun_init_request(STUN_METHOD_CONNECTION_BIND, &message); + + stun_attr_add(&message, STUN_ATTRIBUTE_CONNECTION_ID, (const s08bits*)&cid,4); + + if(add_integrity(clnet_info, &message)<0) return -1; + + stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); + + while (!cb_sent) { + + int len = send_buffer(clnet_info, &message, 1, atc); + + if (len > 0) { + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "connection bind sent\n"); + } + cb_sent = 1; + } else { + if(errorOK) + return 0; + perror("send"); + exit(1); + } + } + } + + ////////////<<==connection bind send + + if(not_rare_event()) return 0; + + ////////connection bind response==>> + + { + int cb_received = 0; + stun_buffer message; + while (!cb_received) { + + int len = recv_buffer(clnet_info, &message, 1, atc); + if (len > 0) { + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "connect bind response received: \n"); + } + int err_code = 0; + u08bits err_msg[129]; + if (stun_is_success_response(&message)) { + + if(clnet_info->nonce[0] || use_short_term) { + SHATYPE sht = clnet_info->shatype; + if(stun_check_message_integrity_str(get_turn_credentials_type(), + message.buf, (size_t)(message.len), g_uname, + clnet_info->realm, g_upwd, sht)<1) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in connect bind message received from server\n"); + return -1; + } + } + + if(stun_get_method(&message)!=STUN_METHOD_CONNECTION_BIND) + continue; + cb_received = 1; + if (verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); + } + atc->tcp_data_bound = 1; + } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, + &err_code,err_msg,sizeof(err_msg), + clnet_info->realm,clnet_info->nonce)) { + if(err_code == SHA_TOO_WEAK && (clnet_info->shatype == SHATYPE_SHA1)) { + clnet_info->shatype = SHATYPE_SHA256; + recalculate_restapi_hmac(); + } + goto beg_cb; + } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { + cb_received = 1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "connection bind error %d (%s)\n", + err_code,(char*)err_msg); + return -1; + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "unknown connection bind response\n"); + /* Try again ? */ + } + } else { + if(errorOK) + return 0; + perror("recv"); + exit(-1); + } + } + } + + return 0; +} + +void tcp_data_connect(app_ur_session *elem, u32bits cid) +{ + int clnet_fd = socket(elem->pinfo.remote_addr.ss.sa_family, SOCK_STREAM, 0); + if (clnet_fd < 0) { + perror("socket"); + exit(-1); + } + + if (sock_bind_to_device(clnet_fd, client_ifname) < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "Cannot bind client socket to device %s\n", client_ifname); + } + set_sock_buf_size(clnet_fd, (UR_CLIENT_SOCK_BUF_SIZE<<2)); + + ++elem->pinfo.tcp_conn_number; + int i = (int)(elem->pinfo.tcp_conn_number-1); + elem->pinfo.tcp_conn=(app_tcp_conn_info**)realloc(elem->pinfo.tcp_conn,elem->pinfo.tcp_conn_number*sizeof(app_tcp_conn_info*)); + elem->pinfo.tcp_conn[i]=(app_tcp_conn_info*)turn_malloc(sizeof(app_tcp_conn_info)); + ns_bzero(elem->pinfo.tcp_conn[i],sizeof(app_tcp_conn_info)); + + elem->pinfo.tcp_conn[i]->tcp_data_fd = clnet_fd; + elem->pinfo.tcp_conn[i]->cid = cid; + + addr_cpy(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),&(elem->pinfo.local_addr)); + + addr_set_port(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),0); + + addr_bind(clnet_fd, &(elem->pinfo.tcp_conn[i]->tcp_data_local_addr), 1); + + addr_get_from_sock(clnet_fd,&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr)); + + { + int cycle = 0; + while(cycle++<1024) { + int err = 0; + if (addr_connect(clnet_fd, &(elem->pinfo.remote_addr),&err) < 0) { + if(err == EADDRINUSE) { + socket_closesocket(clnet_fd); + clnet_fd = socket(elem->pinfo.remote_addr.ss.sa_family, SOCK_STREAM, 0); + if (clnet_fd < 0) { + perror("socket"); + exit(-1); + } + if (sock_bind_to_device(clnet_fd, client_ifname) < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "Cannot bind client socket to device %s\n", client_ifname); + } + set_sock_buf_size(clnet_fd, UR_CLIENT_SOCK_BUF_SIZE<<2); + + elem->pinfo.tcp_conn[i]->tcp_data_fd = clnet_fd; + + addr_cpy(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),&(elem->pinfo.local_addr)); + + addr_set_port(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),0); + + addr_bind(clnet_fd, &(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),1); + + addr_get_from_sock(clnet_fd,&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr)); + + continue; + + } else { + perror("connect"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: cannot connect to remote addr\n", __FUNCTION__); + exit(-1); + } + } else { + break; + } + } + } + + if(use_secure) { + elem->pinfo.tcp_conn[i]->tcp_data_ssl = tls_connect(elem->pinfo.tcp_conn[i]->tcp_data_fd, &(elem->pinfo.remote_addr)); + if(!(elem->pinfo.tcp_conn[i]->tcp_data_ssl)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: cannot SSL connect to remote addr\n", __FUNCTION__); + exit(-1); + } + } + + if(turn_tcp_connection_bind(clnet_verbose, &(elem->pinfo), elem->pinfo.tcp_conn[i],0)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: cannot BIND to tcp connection\n", __FUNCTION__); + } else { + + socket_set_nonblocking(clnet_fd); + + struct event* ev = event_new(client_event_base,clnet_fd, + EV_READ|EV_PERSIST,client_input_handler, + elem); + + event_add(ev,NULL); + + elem->input_tcp_data_ev = ev; + + addr_debug_print(clnet_verbose, &(elem->pinfo.remote_addr), "TCP data network connected to"); + } +} + +///////////////////////////////////////////////// diff --git a/src/apps/uclient/startuclient.h b/src/apps/uclient/startuclient.h new file mode 100644 index 00000000..fbef34e7 --- /dev/null +++ b/src/apps/uclient/startuclient.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2011, 2012, 2013 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 __STARTCLIENT_TURN__ +#define __STARTCLIENT_TURN__ + +#include "ns_turn_utils.h" +#include "session.h" + +#ifdef __cplusplus +extern "C" { +#endif + +///////////////////////////////////////////////////////// + +int rare_event(void); +int not_rare_event(void); + +int start_c2c_connection(uint16_t clnet_remote_port, + const char *remote_address, + const unsigned char* ifname, const char *local_address, + int verbose, + app_ur_conn_info *clnet_info_probe, + app_ur_conn_info *clnet_info1, + uint16_t *chn1, + app_ur_conn_info *clnet_info1_rtcp, + uint16_t *chn1_rtcp, + app_ur_conn_info *clnet_info2, + uint16_t *chn2, + app_ur_conn_info *clnet_info2_rtcp, + uint16_t *chn2_rtcp); + +int start_connection(uint16_t clnet_remote_port, + const char *remote_address, + const unsigned char* ifname, const char *local_address, + int verbose, + app_ur_conn_info *clnet_info_probe, + app_ur_conn_info *clnet_info, + uint16_t *chn, + app_ur_conn_info *clnet_info_rtcp, + uint16_t *chn_rtcp); + +int turn_tcp_connect(int verbose, app_ur_conn_info *clnet_info, ioa_addr *peer_addr); + +void tcp_data_connect(app_ur_session *elem, u32bits cid); + +int socket_connect(evutil_socket_t clnet_fd, ioa_addr *remote_addr, int *connect_err); + +int read_mobility_ticket(app_ur_conn_info *clnet_info, stun_buffer *message); + +//////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__STARTCLIENT_TURN__ + diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c new file mode 100644 index 00000000..6e23aa60 --- /dev/null +++ b/src/apps/uclient/uclient.c @@ -0,0 +1,1433 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "apputils.h" +#include "uclient.h" +#include "startuclient.h" +#include "ns_turn_utils.h" +#include "session.h" + +#include +#include + +#include + +static int verbose_packets=0; + +static size_t current_clients_number = 0; + +static int start_full_timer=0; +static u32bits tot_messages=0; +static u32bits tot_send_messages=0; +static u64bits tot_send_bytes = 0; +static u32bits tot_recv_messages=0; +static u64bits tot_recv_bytes = 0; +static u64bits tot_send_dropped = 0; + +struct event_base* client_event_base=NULL; + +static int client_write(app_ur_session *elem); +static int client_shutdown(app_ur_session *elem); + +static u64bits current_time = 0; +static u64bits current_mstime = 0; + +static char buffer_to_send[65536]="\0"; + +static int total_clients = 0; + +/* Patch for unlimited number of clients provided by ucudbm@gmail.com */ +static app_ur_session** elems = NULL; + +#define SLEEP_INTERVAL (234) + +int RTP_PACKET_INTERVAL = 20; + +static inline s64bits time_minus(u64bits t1, u64bits t2) { + return ( (s64bits)t1 - (s64bits)t2 ); +} + +static u64bits total_loss = 0; +static u64bits total_jitter = 0; +static u64bits total_latency = 0; + +static u64bits min_latency = 0xFFFFFFFF; +static u64bits max_latency = 0; +static u64bits min_jitter = 0xFFFFFFFF; +static u64bits max_jitter = 0; + + +static int show_statistics = 0; + +/////////////////////////////////////////////////////////////////////////////// + +static void __turn_getMSTime(void) { + static u64bits start_sec = 0; + struct timespec tp={0,0}; +#if defined(CLOCK_REALTIME) + clock_gettime(CLOCK_REALTIME, &tp); +#else + tp.tv_sec = time(NULL); +#endif + if(!start_sec) + start_sec = tp.tv_sec; + if(current_time != (u64bits)((u64bits)(tp.tv_sec)-start_sec)) + show_statistics = 1; + current_time = (u64bits)((u64bits)(tp.tv_sec)-start_sec); + current_mstime = (u64bits)((current_time * 1000) + (tp.tv_nsec/1000000)); +} + +//////////////////////////////////////////////////////////////////// + +static int refresh_channel(app_ur_session* elem, u16bits method, uint32_t lt); + +//////////////////////// SS //////////////////////////////////////// + +static app_ur_session* init_app_session(app_ur_session *ss) { + if(ss) { + ns_bzero(ss,sizeof(app_ur_session)); + ss->pinfo.fd=-1; + ss->pinfo.shatype = shatype; + } + return ss; +} + +static app_ur_session* create_new_ss(void) +{ + ++current_clients_number; + return init_app_session((app_ur_session*) turn_malloc(sizeof(app_ur_session))); +} + +static void uc_delete_session_elem_data(app_ur_session* cdi) { + if(cdi) { + EVENT_DEL(cdi->input_ev); + EVENT_DEL(cdi->input_tcp_data_ev); + if(cdi->pinfo.tcp_conn) { + int i = 0; + for(i=0;i<(int)(cdi->pinfo.tcp_conn_number);++i) { + if(cdi->pinfo.tcp_conn[i]) { + if(cdi->pinfo.tcp_conn[i]->tcp_data_ssl && !(cdi->pinfo.broken)) { + if(!(SSL_get_shutdown(cdi->pinfo.tcp_conn[i]->tcp_data_ssl) & SSL_SENT_SHUTDOWN)) { + SSL_set_shutdown(cdi->pinfo.tcp_conn[i]->tcp_data_ssl, SSL_RECEIVED_SHUTDOWN); + SSL_shutdown(cdi->pinfo.tcp_conn[i]->tcp_data_ssl); + } + if(cdi->pinfo.tcp_conn[i]->tcp_data_ssl) { + SSL_free(cdi->pinfo.tcp_conn[i]->tcp_data_ssl); + cdi->pinfo.tcp_conn[i]->tcp_data_ssl = NULL; + } + if(cdi->pinfo.tcp_conn[i]->tcp_data_fd>=0) { + socket_closesocket(cdi->pinfo.tcp_conn[i]->tcp_data_fd); + cdi->pinfo.tcp_conn[i]->tcp_data_fd=-1; + } + turn_free(cdi->pinfo.tcp_conn[i], 111); + cdi->pinfo.tcp_conn[i]=NULL; + } + } + } + cdi->pinfo.tcp_conn_number=0; + turn_free(cdi->pinfo.tcp_conn, 111); + cdi->pinfo.tcp_conn=NULL; + } + if(cdi->pinfo.ssl && !(cdi->pinfo.broken)) { + if(!(SSL_get_shutdown(cdi->pinfo.ssl) & SSL_SENT_SHUTDOWN)) { + SSL_set_shutdown(cdi->pinfo.ssl, SSL_RECEIVED_SHUTDOWN); + SSL_shutdown(cdi->pinfo.ssl); + } + } + if(cdi->pinfo.ssl) { + SSL_free(cdi->pinfo.ssl); + cdi->pinfo.ssl = NULL; + } + if(cdi->pinfo.fd>=0) { + socket_closesocket(cdi->pinfo.fd); + } + cdi->pinfo.fd=-1; + } +} + +static int remove_all_from_ss(app_ur_session* ss) +{ + if (ss) { + uc_delete_session_elem_data(ss); + + --current_clients_number; + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +int send_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int data_connection, app_tcp_conn_info *atc) +{ + + int rc = 0; + int ret = -1; + + char *buffer = (char*) (message->buf); + + if(negative_protocol_test && (message->len>0)) { + if(random()%10 == 0) { + int np = (int)((unsigned long)random()%10); + while(np-->0) { + int pos = (int)((unsigned long)random()%(unsigned long)message->len); + int val = (int)((unsigned long)random()%256); + message->buf[pos]=(u08bits)val; + } + } + } + + SSL *ssl = clnet_info->ssl; + ioa_socket_raw fd = clnet_info->fd; + + if(data_connection) { + if(atc) { + ssl = atc->tcp_data_ssl; + fd = atc->tcp_data_fd; + } else if(is_TCP_relay()){ + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "trying to send tcp data buffer over unready connection: size=%d\n",(int)(message->len)); + return -1; + } + } + + if (ssl) { + + int message_sent = 0; + while (!message_sent) { + + if (SSL_get_shutdown(ssl)) { + return -1; + } + + int len = 0; + do { + len = SSL_write(ssl, buffer, (int)message->len); + } while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS))); + + if(len == (int)message->len) { + if (clnet_verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "buffer sent: size=%d\n",len); + } + + message_sent = 1; + ret = len; + } else { + switch (SSL_get_error(ssl, len)){ + case SSL_ERROR_NONE: + /* Try again ? */ + break; + case SSL_ERROR_WANT_WRITE: + /* Just try again later */ + break; + case SSL_ERROR_WANT_READ: + /* continue with reading */ + break; + case SSL_ERROR_ZERO_RETURN: + /* Try again */ + break; + case SSL_ERROR_SYSCALL: + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Socket write error 111.666: \n"); + if (handle_socket_error()) + break; + case SSL_ERROR_SSL: + { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SSL write error: \n"); + char buf[1024]; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s (%d)\n", + ERR_error_string(ERR_get_error(),buf), + SSL_get_error(ssl, len)); + } + default: + clnet_info->broken = 1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Unexpected error while writing!\n"); + return -1; + } + } + } + + } else if (fd >= 0) { + + size_t left = (size_t) (message->len); + + while (left > 0) { + do { + rc = send(fd, buffer, left, 0); + } while (rc < 0 && ((errno == EINTR) || (errno == ENOBUFS))); + if (rc > 0) { + left -= (size_t) rc; + buffer += rc; + } else { + tot_send_dropped+=1; + break; + } + } + + if (left > 0) + return -1; + + ret = (int) message->len; + } + + return ret; +} + +int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, + app_tcp_conn_info *atc) { + + int rc = 0; + + ioa_socket_raw fd = clnet_info->fd; + if (atc) + fd = atc->tcp_data_fd; + + SSL* ssl = clnet_info->ssl; + if (atc) + ssl = atc->tcp_data_ssl; + + if (!use_secure && !use_tcp && fd >= 0) { + + /* Plain UDP */ + + do { + rc = recv(fd, message->buf, sizeof(message->buf) - 1, 0); + if (rc < 0 && errno == EAGAIN && sync) + errno = EINTR; + } while (rc < 0 && (errno == EINTR)); + + if (rc < 0) { + return -1; + } + + message->len = rc; + + } else if (use_secure && ssl && !(clnet_info->broken)) { + + /* TLS/DTLS */ + + int message_received = 0; + int cycle = 0; + while (!message_received && cycle++ < 100) { + + if (SSL_get_shutdown(ssl)) + return -1; + + rc = 0; + do { + rc = SSL_read(ssl, message->buf, sizeof(message->buf) - 1); + if (rc < 0 && errno == EAGAIN && sync) + continue; + } while (rc < 0 && (errno == EINTR)); + + if (rc > 0) { + + if (clnet_verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "response received: size=%d\n", rc); + } + message->len = rc; + message_received = 1; + + } else { + + int sslerr = SSL_get_error(ssl, rc); + + switch (sslerr) { + case SSL_ERROR_NONE: + /* Try again ? */ + break; + case SSL_ERROR_WANT_WRITE: + /* Just try again later */ + break; + case SSL_ERROR_WANT_READ: + /* continue with reading */ + break; + case SSL_ERROR_ZERO_RETURN: + /* Try again */ + break; + case SSL_ERROR_SYSCALL: + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "Socket read error 111.999: \n"); + if (handle_socket_error()) + break; + case SSL_ERROR_SSL: { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SSL write error: \n"); + char buf[1024]; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s (%d)\n", + ERR_error_string(ERR_get_error(), buf), + SSL_get_error(ssl, rc)); + } + default: + clnet_info->broken = 1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "Unexpected error while reading: rc=%d, sslerr=%d\n", + rc, sslerr); + return -1; + } + + if (!sync) + break; + } + } + + } else if (!use_secure && use_tcp && fd >= 0) { + + /* Plain TCP */ + + do { + rc = recv(fd, message->buf, sizeof(message->buf) - 1, MSG_PEEK); + if ((rc < 0) && (errno == EAGAIN) && sync) { + errno = EINTR; + } + } while (rc < 0 && (errno == EINTR)); + + if (rc > 0) { + int mlen = rc; + size_t app_msg_len = (size_t) rc; + if (!atc) { + mlen = stun_get_message_len_str(message->buf, rc, 1, + &app_msg_len); + } else { + if (!sync) + mlen = clmessage_length; + + if (mlen > clmessage_length) + mlen = clmessage_length; + + app_msg_len = (size_t) mlen; + } + + if (mlen > 0) { + + int rcr = 0; + int rsf = 0; + int cycle = 0; + while (rsf < mlen && cycle++ < 128) { + do { + rcr = recv(fd, message->buf + rsf, + (size_t) mlen - (size_t) rsf, 0); + if (rcr < 0 && errno == EAGAIN && sync) + errno = EINTR; + } while (rcr < 0 && (errno == EINTR)); + + if (rcr > 0) + rsf += rcr; + + } + + if (rsf < 1) + return -1; + + if (rsf < (int) app_msg_len) { + if ((size_t) (app_msg_len / (size_t) rsf) * ((size_t) (rsf)) + != app_msg_len) { + return -1; + } + } + + message->len = app_msg_len; + + rc = app_msg_len; + + } else { + rc = 0; + } + } + } + + return rc; +} + +static int client_read(app_ur_session *elem, int is_tcp_data, app_tcp_conn_info *atc) { + + if (!elem) + return -1; + + if (elem->state != UR_STATE_READY) + return -1; + + elem->ctime = current_time; + + app_ur_conn_info *clnet_info = &(elem->pinfo); + int err_code = 0; + u08bits err_msg[129]; + int rc = 0; + int applen = 0; + + if (clnet_verbose && verbose_packets) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "before read ...\n"); + } + + rc = recv_buffer(clnet_info, &(elem->in_buffer), 0, atc); + + if (clnet_verbose && verbose_packets) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "read %d bytes\n", (int) rc); + } + + if (rc > 0) { + + elem->in_buffer.len = rc; + + uint16_t chnumber = 0; + + const message_info *mi = NULL; + + size_t buffers = 1; + + if(is_tcp_data) { + if ((int)elem->in_buffer.len == clmessage_length) { + mi = (message_info*)(elem->in_buffer.buf); + } + } else if (stun_is_indication(&(elem->in_buffer))) { + + if(use_short_term) { + SHATYPE sht = elem->pinfo.shatype; + if(stun_check_message_integrity_str(get_turn_credentials_type(), + elem->in_buffer.buf, (size_t)(elem->in_buffer.len), g_uname, + elem->pinfo.realm, g_upwd, sht)<1) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in indication message 0x%x received from server\n",(unsigned int)stun_get_method(&(elem->in_buffer))); + return -1; + } + } + + uint16_t method = stun_get_method(&elem->in_buffer); + + if((method == STUN_METHOD_CONNECTION_ATTEMPT)&& is_TCP_relay()) { + stun_attr_ref sar = stun_attr_get_first(&(elem->in_buffer)); + u32bits cid = 0; + while(sar) { + int attr_type = stun_attr_get_type(sar); + if(attr_type == STUN_ATTRIBUTE_CONNECTION_ID) { + cid = *((const u32bits*)stun_attr_get_value(sar)); + break; + } + sar = stun_attr_get_next_str(elem->in_buffer.buf,elem->in_buffer.len,sar); + } + if(negative_test) { + tcp_data_connect(elem,(u64bits)random()); + } else { + /* positive test */ + tcp_data_connect(elem,cid); + } + return rc; + } else if (method != STUN_METHOD_DATA) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_INFO, + "ERROR: received indication message has wrong method: 0x%x\n", + (int) method); + return rc; + } else { + + stun_attr_ref sar = stun_attr_get_first_by_type(&(elem->in_buffer), STUN_ATTRIBUTE_DATA); + if (!sar) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "ERROR: received DATA message has no data, size=%d\n", rc); + return rc; + } + + int rlen = stun_attr_get_len(sar); + applen = rlen; + if (rlen != clmessage_length) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "ERROR: received DATA message has wrong len: %d, must be %d\n", rlen, clmessage_length); + tot_recv_bytes += applen; + return rc; + } + + const u08bits* data = stun_attr_get_value(sar); + + mi = (const message_info*) data; + } + + } else if (stun_is_success_response(&(elem->in_buffer))) { + + if(elem->pinfo.nonce[0] || use_short_term) { + SHATYPE sht = elem->pinfo.shatype; + if(stun_check_message_integrity_str(get_turn_credentials_type(), + elem->in_buffer.buf, (size_t)(elem->in_buffer.len), g_uname, + elem->pinfo.realm, g_upwd, sht)<1) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in success message 0x%x received from server\n",(unsigned int)stun_get_method(&(elem->in_buffer))); + return -1; + } + } + + if(is_TCP_relay() && (stun_get_method(&(elem->in_buffer)) == STUN_METHOD_CONNECT)) { + stun_attr_ref sar = stun_attr_get_first(&(elem->in_buffer)); + u32bits cid = 0; + while(sar) { + int attr_type = stun_attr_get_type(sar); + if(attr_type == STUN_ATTRIBUTE_CONNECTION_ID) { + cid = *((const u32bits*)stun_attr_get_value(sar)); + break; + } + sar = stun_attr_get_next_str(elem->in_buffer.buf,elem->in_buffer.len,sar); + } + tcp_data_connect(elem,cid); + } + + return rc; + } else if (stun_is_challenge_response_str(elem->in_buffer.buf, (size_t)elem->in_buffer.len, + &err_code,err_msg,sizeof(err_msg), + clnet_info->realm,clnet_info->nonce)) { + if(err_code == SHA_TOO_WEAK && (elem->pinfo.shatype == SHATYPE_SHA1)) { + elem->pinfo.shatype = SHATYPE_SHA256; + recalculate_restapi_hmac(); + } + + if(is_TCP_relay() && (stun_get_method(&(elem->in_buffer)) == STUN_METHOD_CONNECT)) { + turn_tcp_connect(clnet_verbose, &(elem->pinfo), &(elem->pinfo.peer_addr)); + } else if(stun_get_method(&(elem->in_buffer)) == STUN_METHOD_REFRESH) { + refresh_channel(elem, stun_get_method(&elem->in_buffer),600); + } + return rc; + } else if (stun_is_error_response(&(elem->in_buffer), NULL,NULL,0)) { + return rc; + } else if (stun_is_channel_message(&(elem->in_buffer), &chnumber, use_tcp)) { + if (elem->chnum != chnumber) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "ERROR: received message has wrong channel: %d\n", + (int) chnumber); + return rc; + } + + if (elem->in_buffer.len >= 4) { + if (((int)(elem->in_buffer.len-4) < clmessage_length) || + ((int)(elem->in_buffer.len-4) > clmessage_length + 3)) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_INFO, + "ERROR: received buffer have wrong length: %d, must be %d, len=%d\n", + rc, clmessage_length + 4,(int)elem->in_buffer.len); + return rc; + } + + mi = (message_info*)(elem->in_buffer.buf + 4); + applen = elem->in_buffer.len -4; + } + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "ERROR: Unknown message received of size: %d\n",(int)(elem->in_buffer.len)); + return rc; + } + + if(mi) { + /* + printf("%s: 111.111: msgnum=%d, rmsgnum=%d, sent=%lu, recv=%lu\n",__FUNCTION__, + mi->msgnum,elem->recvmsgnum,(unsigned long)mi->mstime,(unsigned long)current_mstime); + */ + if(mi->msgnum != elem->recvmsgnum+1) + ++(elem->loss); + else { + u64bits clatency = (u64bits)time_minus(current_mstime,mi->mstime); + if(clatency>max_latency) + max_latency = clatency; + if(clatencylatency += clatency; + if(elem->rmsgnum>0) { + u64bits cjitter = abs((int)(current_mstime-elem->recvtimems)-RTP_PACKET_INTERVAL); + + if(cjitter>max_jitter) + max_jitter = cjitter; + if(cjitterjitter += cjitter; + } + } + + elem->recvmsgnum = mi->msgnum; + } + + elem->rmsgnum+=buffers; + tot_recv_messages+=buffers; + if(applen > 0) + tot_recv_bytes += applen; + else + tot_recv_bytes += elem->in_buffer.len; + elem->recvtimems=current_mstime; + elem->wait_cycles = 0; + + } else if(rc == 0) { + return 0; + } else { + return -1; + } + + return rc; +} + +static int client_shutdown(app_ur_session *elem) { + + if(!elem) return -1; + + elem->state=UR_STATE_DONE; + + elem->ctime=current_time; + + remove_all_from_ss(elem); + + if (clnet_verbose) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"done, connection 0x%lx closed.\n",(long)elem); + + return 0; +} + +static int client_write(app_ur_session *elem) { + + if(!elem) return -1; + + if(elem->state!=UR_STATE_READY) return -1; + + elem->ctime=current_time; + + message_info *mi = (message_info*)buffer_to_send; + mi->msgnum=elem->wmsgnum; + mi->mstime=current_mstime; + app_tcp_conn_info *atc=NULL; + + if (is_TCP_relay()) { + + memcpy(elem->out_buffer.buf, buffer_to_send, clmessage_length); + elem->out_buffer.len = clmessage_length; + + if(elem->pinfo.is_peer) { + if(send(elem->pinfo.fd, elem->out_buffer.buf, clmessage_length, 0)>=0) { + ++elem->wmsgnum; + elem->to_send_timems += RTP_PACKET_INTERVAL; + tot_send_messages++; + tot_send_bytes += clmessage_length; + } + return 0; + } + + if (!(elem->pinfo.tcp_conn) || !(elem->pinfo.tcp_conn_number)) { + return -1; + } + int i = (unsigned int)(random()) % elem->pinfo.tcp_conn_number; + atc = elem->pinfo.tcp_conn[i]; + if(!atc->tcp_data_bound) { + printf("%s: Uninitialized atc: i=%d, atc=0x%lx\n",__FUNCTION__,i,(long)atc); + return -1; + } + } else if(!do_not_use_channel) { + /* Let's always do padding: */ + stun_init_channel_message(elem->chnum, &(elem->out_buffer), clmessage_length, mandatory_channel_padding || use_tcp); + memcpy(elem->out_buffer.buf+4,buffer_to_send,clmessage_length); + } else { + stun_init_indication(STUN_METHOD_SEND, &(elem->out_buffer)); + stun_attr_add(&(elem->out_buffer), STUN_ATTRIBUTE_DATA, buffer_to_send, clmessage_length); + stun_attr_add_addr(&(elem->out_buffer),STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &(elem->pinfo.peer_addr)); + 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)); + } + + if (elem->out_buffer.len > 0) { + + if (clnet_verbose && verbose_packets) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "before write ...\n"); + } + + int rc=send_buffer(&(elem->pinfo),&(elem->out_buffer),1,atc); + + ++elem->wmsgnum; + elem->to_send_timems += RTP_PACKET_INTERVAL; + + if(rc >= 0) { + if (clnet_verbose && verbose_packets) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "wrote %d bytes\n", (int) rc); + } + tot_send_messages++; + tot_send_bytes += clmessage_length; + } else { + return -1; + } + } + + return 0; +} + +void client_input_handler(evutil_socket_t fd, short what, void* arg) { + + if(!(what&EV_READ)||!arg) return; + + UNUSED_ARG(fd); + + app_ur_session* elem = (app_ur_session*)arg; + if(!elem) { + return; + } + + switch(elem->state) { + case UR_STATE_READY: + do { + app_tcp_conn_info *atc = NULL; + int is_tcp_data = 0; + if(elem->pinfo.tcp_conn) { + int i = 0; + for(i=0;i<(int)(elem->pinfo.tcp_conn_number);++i) { + if(elem->pinfo.tcp_conn[i]) { + if((fd==elem->pinfo.tcp_conn[i]->tcp_data_fd) && (elem->pinfo.tcp_conn[i]->tcp_data_bound)) { + is_tcp_data = 1; + atc = elem->pinfo.tcp_conn[i]; + break; + } + } + } + } + int rc = client_read(elem, is_tcp_data, atc); + if(rc<=0) break; + } while(1); + + break; + default: + ; + } +} + +static void run_events(int short_burst) +{ + struct timeval timeout; + + if(!short_burst) { + timeout.tv_sec = 1; + timeout.tv_usec = 0; + } else { + timeout.tv_sec = 0; + timeout.tv_usec = 100000; + } + + event_base_loopexit(client_event_base, &timeout); + + event_base_dispatch(client_event_base); +} + +////////////////////// main method ///////////////// + +static int start_client(const char *remote_address, int port, + const unsigned char* ifname, const char *local_address, + int messagenumber, + int i) { + + app_ur_session* ss=create_new_ss(); + app_ur_session* ss_rtcp=NULL; + + if(!no_rtcp) + ss_rtcp = create_new_ss(); + + app_ur_conn_info clnet_info_probe; /* for load balancing probe */ + ns_bzero(&clnet_info_probe,sizeof(clnet_info_probe)); + clnet_info_probe.fd = -1; + clnet_info_probe.shatype = shatype; + + app_ur_conn_info *clnet_info=&(ss->pinfo); + app_ur_conn_info *clnet_info_rtcp=NULL; + + if(!no_rtcp) + clnet_info_rtcp = &(ss_rtcp->pinfo); + + uint16_t chnum=0; + uint16_t chnum_rtcp=0; + + start_connection(port, remote_address, + ifname, local_address, + clnet_verbose, + &clnet_info_probe, + clnet_info, &chnum, + clnet_info_rtcp, &chnum_rtcp); + + if(clnet_info_probe.ssl) { + SSL_free(clnet_info_probe.ssl); + clnet_info_probe.ssl = NULL; + clnet_info_probe.fd = -1; + } else if(clnet_info_probe.fd != -1) { + socket_closesocket(clnet_info_probe.fd); + clnet_info_probe.fd = -1; + } + + socket_set_nonblocking(clnet_info->fd); + + if(!no_rtcp) + socket_set_nonblocking(clnet_info_rtcp->fd); + + struct event* ev = event_new(client_event_base,clnet_info->fd, + EV_READ|EV_PERSIST,client_input_handler, + ss); + + event_add(ev,NULL); + + struct event* ev_rtcp = NULL; + + if(!no_rtcp) { + ev_rtcp = event_new(client_event_base,clnet_info_rtcp->fd, + EV_READ|EV_PERSIST,client_input_handler, + ss_rtcp); + + event_add(ev_rtcp,NULL); + } + + ss->state=UR_STATE_READY; + + ss->input_ev=ev; + ss->tot_msgnum=messagenumber; + ss->recvmsgnum=-1; + ss->chnum=chnum; + + if(!no_rtcp) { + + ss_rtcp->state=UR_STATE_READY; + + ss_rtcp->input_ev=ev_rtcp; + ss_rtcp->tot_msgnum=ss->tot_msgnum; + if(ss_rtcp->tot_msgnum<1) ss_rtcp->tot_msgnum=1; + ss_rtcp->recvmsgnum=-1; + ss_rtcp->chnum=chnum_rtcp; + } + + elems[i]=ss; + + refresh_channel(ss, 0, 600); + + if(!no_rtcp) + elems[i+1]=ss_rtcp; + + return 0; +} + +static int start_c2c(const char *remote_address, int port, + const unsigned char* ifname, const char *local_address, + int messagenumber, + int i) { + + app_ur_session* ss1=create_new_ss(); + app_ur_session* ss1_rtcp=NULL; + + if(!no_rtcp) + ss1_rtcp = create_new_ss(); + + app_ur_session* ss2=create_new_ss(); + app_ur_session* ss2_rtcp=NULL; + + if(!no_rtcp) + ss2_rtcp = create_new_ss(); + + app_ur_conn_info clnet_info_probe; /* for load balancing probe */ + ns_bzero(&clnet_info_probe,sizeof(clnet_info_probe)); + clnet_info_probe.fd = -1; + clnet_info_probe.shatype = shatype; + + app_ur_conn_info *clnet_info1=&(ss1->pinfo); + app_ur_conn_info *clnet_info1_rtcp=NULL; + + if(!no_rtcp) + clnet_info1_rtcp = &(ss1_rtcp->pinfo); + + app_ur_conn_info *clnet_info2=&(ss2->pinfo); + app_ur_conn_info *clnet_info2_rtcp=NULL; + + if(!no_rtcp) + clnet_info2_rtcp = &(ss2_rtcp->pinfo); + + uint16_t chnum1=0; + uint16_t chnum1_rtcp=0; + uint16_t chnum2=0; + uint16_t chnum2_rtcp=0; + + start_c2c_connection(port, remote_address, + ifname, local_address, + clnet_verbose, + &clnet_info_probe, + clnet_info1, &chnum1, + clnet_info1_rtcp, &chnum1_rtcp, + clnet_info2, &chnum2, + clnet_info2_rtcp, &chnum2_rtcp); + + if(clnet_info_probe.ssl) { + SSL_free(clnet_info_probe.ssl); + clnet_info_probe.ssl = NULL; + clnet_info_probe.fd = -1; + } else if(clnet_info_probe.fd != -1) { + socket_closesocket(clnet_info_probe.fd); + clnet_info_probe.fd = -1; + } + + socket_set_nonblocking(clnet_info1->fd); + + if(!no_rtcp) + socket_set_nonblocking(clnet_info1_rtcp->fd); + + socket_set_nonblocking(clnet_info2->fd); + + if(!no_rtcp) + socket_set_nonblocking(clnet_info2_rtcp->fd); + + struct event* ev1 = event_new(client_event_base,clnet_info1->fd, + EV_READ|EV_PERSIST,client_input_handler, + ss1); + + event_add(ev1,NULL); + + struct event* ev1_rtcp = NULL; + + if(!no_rtcp) { + ev1_rtcp = event_new(client_event_base,clnet_info1_rtcp->fd, + EV_READ|EV_PERSIST,client_input_handler, + ss1_rtcp); + + event_add(ev1_rtcp,NULL); + } + + struct event* ev2 = event_new(client_event_base,clnet_info2->fd, + EV_READ|EV_PERSIST,client_input_handler, + ss2); + + event_add(ev2,NULL); + + struct event* ev2_rtcp = NULL; + + if(!no_rtcp) { + ev2_rtcp = event_new(client_event_base,clnet_info2_rtcp->fd, + EV_READ|EV_PERSIST,client_input_handler, + ss2_rtcp); + + event_add(ev2_rtcp,NULL); + } + + ss1->state=UR_STATE_READY; + + ss1->input_ev=ev1; + ss1->tot_msgnum=messagenumber; + ss1->recvmsgnum=-1; + ss1->chnum=chnum1; + + if(!no_rtcp) { + + ss1_rtcp->state=UR_STATE_READY; + + ss1_rtcp->input_ev=ev1_rtcp; + ss1_rtcp->tot_msgnum=ss1->tot_msgnum; + if(ss1_rtcp->tot_msgnum<1) ss1_rtcp->tot_msgnum=1; + ss1_rtcp->recvmsgnum=-1; + ss1_rtcp->chnum=chnum1_rtcp; + } + + ss2->state=UR_STATE_READY; + + ss2->input_ev=ev2; + ss2->tot_msgnum=ss1->tot_msgnum; + ss2->recvmsgnum=-1; + ss2->chnum=chnum2; + + if(!no_rtcp) { + ss2_rtcp->state=UR_STATE_READY; + + ss2_rtcp->input_ev=ev2_rtcp; + ss2_rtcp->tot_msgnum=ss1_rtcp->tot_msgnum; + ss2_rtcp->recvmsgnum=-1; + ss2_rtcp->chnum=chnum2_rtcp; + } + + elems[i++]=ss1; + if(!no_rtcp) + elems[i++]=ss1_rtcp; + elems[i++]=ss2; + if(!no_rtcp) + elems[i++]=ss2_rtcp; + + return 0; +} + +static int refresh_channel(app_ur_session* elem, u16bits method, uint32_t lt) +{ + + stun_buffer message; + app_ur_conn_info *clnet_info = &(elem->pinfo); + + if(clnet_info->is_peer) + return 0; + + if (!method || (method == STUN_METHOD_REFRESH)) { + stun_init_request(STUN_METHOD_REFRESH, &message); + lt = htonl(lt); + stun_attr_add(&message, STUN_ATTRIBUTE_LIFETIME, (const char*) <, 4); + if(add_integrity(clnet_info, &message)<0) return -1; + if(use_fingerprints) + stun_attr_add_fingerprint_str(message.buf, (size_t*) &(message.len)); + send_buffer(clnet_info, &message, 0,0); + } + + if (lt && !addr_any(&(elem->pinfo.peer_addr))) { + + if(!no_permissions) { + if (!method || (method == STUN_METHOD_CREATE_PERMISSION)) { + stun_init_request(STUN_METHOD_CREATE_PERMISSION, &message); + stun_attr_add_addr(&message, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &(elem->pinfo.peer_addr)); + if(add_integrity(clnet_info, &message)<0) return -1; + if(use_fingerprints) + stun_attr_add_fingerprint_str(message.buf, (size_t*) &(message.len)); + send_buffer(&(elem->pinfo), &message, 0,0); + } + } + + if (!method || (method == STUN_METHOD_CHANNEL_BIND)) { + if (STUN_VALID_CHANNEL(elem->chnum)) { + stun_set_channel_bind_request(&message, &(elem->pinfo.peer_addr), elem->chnum); + if(add_integrity(clnet_info, &message)<0) return -1; + if(use_fingerprints) + stun_attr_add_fingerprint_str(message.buf, (size_t*) &(message.len)); + send_buffer(&(elem->pinfo), &message,1,0); + } + } + } + + elem->refresh_time = current_mstime + 30*1000; + + return 0; +} + +static inline int client_timer_handler(app_ur_session* elem) +{ + if (elem) { + if (!turn_time_before(current_mstime, elem->refresh_time)) { + refresh_channel(elem, 0, 600); + } + + if(hang_on && elem->completed) + return 0; + + if (!turn_time_before(current_mstime, elem->to_send_timems)) { + if (elem->wmsgnum >= elem->tot_msgnum) { + if (!turn_time_before(current_mstime, elem->finished_time) || + (tot_recv_messages>=tot_messages)) { + /* + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: elem=0x%x: 111.111: c=%d, t=%d, r=%d, w=%d\n",__FUNCTION__,(int)elem,elem->wait_cycles,elem->tot_msgnum,elem->rmsgnum,elem->wmsgnum); + */ + /* + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: 111.222: ly=%llu, ls=%llu, j=%llu\n",__FUNCTION__, + (unsigned long long)elem->latency, + (unsigned long long)elem->loss, + (unsigned long long)elem->jitter); + */ + total_loss += elem->loss; + elem->loss=0; + total_latency += elem->latency; + elem->latency=0; + total_jitter += elem->jitter; + elem->jitter=0; + elem->completed = 1; + if (!hang_on) { + refresh_channel(elem,0,0); + client_shutdown(elem); + return 1; + } else { + return 0; + } + } + } else { + client_write(elem); + elem->finished_time = current_mstime + STOPPING_TIME*1000; + } + } + } + + return 0; +} + +static void timer_handler(evutil_socket_t fd, short event, void *arg) +{ + UNUSED_ARG(fd); + UNUSED_ARG(event); + UNUSED_ARG(arg); + + __turn_getMSTime(); + + if(start_full_timer) { + int i = 0; + for (i = 0; i < total_clients; ++i) { + if (elems[i]) { + int finished = client_timer_handler(elems[i]); + if (finished) { + elems[i] = NULL; + } + } + } + } +} + +void start_mclient(const char *remote_address, int port, + const unsigned char* ifname, const char *local_address, + int messagenumber, int mclient) { + + if (mclient < 1) + mclient = 1; + + total_clients = mclient; + + if(c2c) { + //mclient must be a multiple of 4: + if(!no_rtcp) + mclient += ((4 - (mclient & 0x00000003)) & 0x00000003); + else if(mclient & 0x1) + ++mclient; + } else { + if(!no_rtcp) + if(mclient & 0x1) + ++mclient; + } + + elems = (app_ur_session**)malloc(sizeof(app_ur_session)*((mclient*2)+1)+sizeof(void*)); + + __turn_getMSTime(); + u32bits stime = current_time; + + memset(buffer_to_send, 7, clmessage_length); + + client_event_base = turn_event_base_new(); + + int i = 0; + int tot_clients = 0; + + if(c2c) { + if(!no_rtcp) + for (i = 0; i < (mclient >> 2); i++) { + if(!dos) usleep(SLEEP_INTERVAL); + if (start_c2c(remote_address, port, ifname, local_address, + messagenumber, i << 2) < 0) { + exit(-1); + } + tot_clients+=4; + } + else + for (i = 0; i < (mclient >> 1); i++) { + if(!dos) usleep(SLEEP_INTERVAL); + if (start_c2c(remote_address, port, ifname, local_address, + messagenumber, i << 1) < 0) { + exit(-1); + } + tot_clients+=2; + } + } else { + if(!no_rtcp) + for (i = 0; i < (mclient >> 1); i++) { + if(!dos) usleep(SLEEP_INTERVAL); + if (start_client(remote_address, port, ifname, local_address, + messagenumber, i << 1) < 0) { + exit(-1); + } + tot_clients+=2; + } + else + for (i = 0; i < mclient; i++) { + if(!dos) usleep(SLEEP_INTERVAL); + if (start_client(remote_address, port, ifname, local_address, + messagenumber, i) < 0) { + exit(-1); + } + tot_clients++; + } + } + + if(dos) + _exit(0); + + total_clients = tot_clients; + + __turn_getMSTime(); + + struct event *ev = event_new(client_event_base, -1, EV_TIMEOUT|EV_PERSIST, timer_handler, NULL); + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = 1000; + + evtimer_add(ev,&tv); + + for(i=0;ipinfo.is_peer) { + int connect_err = 0; + socket_connect(elems[i]->pinfo.fd, &(elems[i]->pinfo.remote_addr), &connect_err); + } + } else if((i%2) == 0) { + if (turn_tcp_connect(clnet_verbose, &(elems[i]->pinfo), &(elems[i]->pinfo.peer_addr)) < 0) { + exit(-1); + } + } + } + run_events(1); + } + + __turn_getMSTime(); + + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Total connect time is %u\n", + ((unsigned int) (current_time - stime))); + + stime = current_time; + + if(is_TCP_relay()) { + u64bits connect_wait_start_time = current_time; + while(1) { + int i = 0; + int completed = 0; + if(passive_tcp) { + for(i=0;ipinfo.is_peer) { + completed+=1; + } else if(elems[i]->pinfo.tcp_conn_number>0 && + elems[i]->pinfo.tcp_conn[0]->tcp_data_bound) { + completed += elems[i]->pinfo.tcp_conn_number; + } + } + if(completed >= total_clients) + break; + } else { + for(i=0;ipinfo.tcp_conn_number>0 && + elems[i]->pinfo.tcp_conn[0]->tcp_data_bound) { + completed += elems[i]->pinfo.tcp_conn_number; + } + } + if(completed >= total_clients) + break; + } + run_events(0); + if(current_time > connect_wait_start_time + STARTING_TCP_RELAY_TIME) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: %d connections are not completed\n", + (int)(total_clients - completed)); + break; + } + } + } + + __turn_getMSTime(); + stime = current_time; + + for(i=0;ito_send_timems = current_mstime + 1000 + ((u32bits)random())%5000; + } + + tot_messages = elems[0]->tot_msgnum * total_clients; + + start_full_timer = 1; + + while (1) { + + run_events(1); + + int msz = (int)current_clients_number; + if (msz < 1) { + break; + } + + if(show_statistics) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: msz=%d, tot_send_msgs=%lu, tot_recv_msgs=%lu, tot_send_bytes ~ %llu, tot_recv_bytes ~ %llu\n", + __FUNCTION__, msz, (unsigned long) tot_send_messages, + (unsigned long) tot_recv_messages, + (unsigned long long) tot_send_bytes, + (unsigned long long) tot_recv_bytes); + show_statistics=0; + } + } + + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: tot_send_msgs=%lu, tot_recv_msgs=%lu\n", + __FUNCTION__, + (unsigned long) tot_send_messages, + (unsigned long) tot_recv_messages); + + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: tot_send_bytes ~ %lu, tot_recv_bytes ~ %lu\n", + __FUNCTION__, + (unsigned long) tot_send_bytes, + (unsigned long) tot_recv_bytes); + + if (client_event_base) + event_base_free(client_event_base); + + if(tot_send_messagesbuf, (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(stun_attr_add_integrity_by_user_str(message->buf, (size_t*)&(message->len), g_uname, + clnet_info->realm, g_upwd, clnet_info->nonce, clnet_info->shatype)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot add integrity to the message\n"); + return -1; + } + } + + return 0; +} + +/////////////////////////////////////////// + diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h new file mode 100644 index 00000000..00ffdc07 --- /dev/null +++ b/src/apps/uclient/uclient.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2011, 2012, 2013 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 __UCLIENT_ECHO__ +#define __UCLIENT_ECHO__ + +#include "ns_turn_utils.h" +#include "stun_buffer.h" +#include "session.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////////////////////// + +#define STOPPING_TIME (5) +#define STARTING_TCP_RELAY_TIME (10) + +extern int clmessage_length; +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; +extern int c2c; +extern ioa_addr peer_addr; +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 char g_auth_secret[1025]; +extern int g_use_auth_secret_with_timestamp; +extern int use_fingerprints; +extern SSL_CTX *root_tls_ctx[32]; +extern int root_tls_ctx_num; +extern int RTP_PACKET_INTERVAL; +extern u08bits relay_transport; +extern unsigned char client_ifname[1025]; +extern struct event_base* client_event_base; +extern int passive_tcp; +extern int mandatory_channel_padding; +extern int negative_test; +extern int negative_protocol_test; +extern int dos; +extern SHATYPE shatype; +extern int mobility; +extern int no_permissions; +extern int extra_requests; + +extern char origin[STUN_MAX_ORIGIN_SIZE+1]; + +#define is_TCP_relay() (relay_transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) + +void start_mclient(const char *remote_address, int port, + const unsigned char* ifname, const char *local_address, + int messagenumber, int mclient); + +int send_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int data_connection, app_tcp_conn_info *atc); +int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, app_tcp_conn_info *atc); + +void client_input_handler(evutil_socket_t fd, short what, void* arg); + +turn_credential_type get_turn_credentials_type(void); + +int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message); + +void recalculate_restapi_hmac(void); + +//////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__UCLIENT_ECHO__ + diff --git a/src/client++/TurnMsgLib.h b/src/client++/TurnMsgLib.h new file mode 100644 index 00000000..db97acc6 --- /dev/null +++ b/src/client++/TurnMsgLib.h @@ -0,0 +1,1195 @@ +/* + * Copyright (C) 2011, 2012, 2013 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 __LIB_TURN_MSG_CPP__ +#define __LIB_TURN_MSG_CPP__ + +#include "ns_turn_ioaddr.h" +#include "ns_turn_msg.h" + +#include + +namespace turn { + +class StunAttr; + +/** + * Exception "end of buffer" + */ +class EndOfStunMsgException { +public: + EndOfStunMsgException() {} + virtual ~EndOfStunMsgException() {} +}; + +/** + * Exception "wrong format of StunAttr" + */ +class WrongStunAttrFormatException { +public: + WrongStunAttrFormatException() {} + virtual ~WrongStunAttrFormatException() {} +}; + +/** + * Exception "wrong format of StunBuffer" + */ +class WrongStunBufferFormatException { +public: + WrongStunBufferFormatException() {} + virtual ~WrongStunBufferFormatException() {} +}; + +/** + * Iterator class for attributes + */ +class StunAttrIterator { +public: + /** + * Iterator constructor: creates iterator on raw messagebuffer. + */ + StunAttrIterator(u08bits *buf, size_t sz) throw (WrongStunBufferFormatException) : + _buf(buf), _sz(sz) { + if(!stun_is_command_message_str(_buf, _sz)) { + throw WrongStunBufferFormatException(); + } + _sar = stun_attr_get_first_str(_buf, _sz); + } + + /** + * Iterator constructor: create iterator over message. + */ + template + StunAttrIterator(T &msg) throw (WrongStunBufferFormatException) : + _buf(msg.getRawBuffer()), _sz(msg.getSize()) { + if(!stun_is_command_message_str(_buf, _sz)) { + throw WrongStunBufferFormatException(); + } + _sar = stun_attr_get_first_str(_buf, _sz); + } + + /** + * Iterator constructor: creates iterator over raw buffer, starting from first + * location of an attribute of particular type. + */ + StunAttrIterator(u08bits *buf, size_t sz, u16bits attr_type) throw (WrongStunBufferFormatException) : + _buf(buf), _sz(sz) { + if(!stun_is_command_message_str(_buf, _sz)) { + throw WrongStunBufferFormatException(); + } + _sar = stun_attr_get_first_by_type_str(_buf, _sz, attr_type); + } + + /** + * Iterator constructor: creates iterator over message, starting from first + * location of an attribute of particular type. + */ + template + StunAttrIterator(T &msg, u16bits attr_type) throw (WrongStunBufferFormatException) : + _buf(msg.getRawBuffer()), _sz(msg.getSize()) { + if(!stun_is_command_message_str(_buf, _sz)) { + throw WrongStunBufferFormatException(); + } + _sar = stun_attr_get_first_by_type_str(_buf, _sz, attr_type); + } + + /** + * Moves iterator to next attribute location + */ + void next() throw(EndOfStunMsgException) { + if(!_sar) { + throw EndOfStunMsgException(); + } + _sar = stun_attr_get_next_str(_buf,_sz,_sar); + } + + /** + * Is the iterator finished + */ + bool eof() const { + return (!_sar); + } + + /** + * Is the iterator at an address attribute + */ + bool isAddr() const { + return stun_attr_is_addr(_sar); + } + + /** + * Return address family attribute value (if the iterator at the "address family" attribute. + */ + int getAddressFamily() const { + return stun_get_requested_address_family(_sar); + } + + /** + * Get attribute type + */ + int getType() const { + return stun_attr_get_type(_sar); + } + + /** + * Destructor + */ + virtual ~StunAttrIterator() {} + + /** + * Return raw memroy field of the attribute value. + * If the attribute value length is zero (0), then return NULL. + */ + const u08bits *getRawBuffer(size_t &sz) const throw(WrongStunAttrFormatException) { + int len = stun_attr_get_len(_sar); + if(len<0) + throw WrongStunAttrFormatException(); + sz = (size_t)len; + const u08bits *value = stun_attr_get_value(_sar); + return value; + } + friend class StunAttr; +private: + u08bits *_buf; + size_t _sz; + stun_attr_ref _sar; +}; + +/** + * Root class of all STUN attributes. + * Can be also used for a generic attribute object. + */ +class StunAttr { +public: + /** + * Empty constructor + */ + StunAttr() : _attr_type(0), _value(0), _sz(0) {} + + /** + * Constructs attribute from iterator + */ + StunAttr(const StunAttrIterator &iter) throw(WrongStunAttrFormatException, EndOfStunMsgException) { + if(iter.eof()) { + throw EndOfStunMsgException(); + } + size_t sz = 0; + const u08bits *ptr = iter.getRawBuffer(sz); + if(sz>=0xFFFF) + throw WrongStunAttrFormatException(); + int at = iter.getType(); + if(at<0) + throw WrongStunAttrFormatException(); + _attr_type = (u16bits)at; + _sz = sz; + _value=(u08bits*)turn_malloc(_sz); + if(ptr) + ns_bcopy(ptr,_value,_sz); + } + + /** + * Destructor + */ + virtual ~StunAttr() { + if(_value) + turn_free(_value,_sz); + } + + /** + * Return raw data representation of the attribute + */ + const u08bits *getRawValue(size_t &sz) const { + sz=_sz; + return _value; + } + + /** + * Set raw data value + */ + void setRawValue(u08bits *value, size_t sz) throw(WrongStunAttrFormatException) { + if(sz>0xFFFF) + throw WrongStunAttrFormatException(); + if(_value) + turn_free(_value,_sz); + _sz = sz; + _value=(u08bits*)turn_malloc(_sz); + if(value) + ns_bcopy(value,_value,_sz); + } + + /** + * Get attribute type + */ + u16bits getType() const { + return _attr_type; + } + + /** + * Set attribute type + */ + void setType(u16bits at) { + _attr_type = at; + } + + /** + * Add attribute to a message + */ + template + int addToMsg(T &msg) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) { + if(!_attr_type) + throw WrongStunAttrFormatException(); + u08bits *buffer = msg.getRawBuffer(); + if(buffer) { + size_t sz = msg.getSize(); + if(addToBuffer(buffer, sz)<0) { + throw WrongStunBufferFormatException(); + } + msg.setSize(sz); + return 0; + } + throw WrongStunBufferFormatException(); + } +protected: + + /** + * Virtual function member to add attribute to a raw buffer + */ + virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) { + if(buffer) { + if(!_value) + throw WrongStunAttrFormatException(); + if(stun_attr_add_str(buffer, &sz, _attr_type, _value, _sz)<0) { + throw WrongStunBufferFormatException(); + } + return 0; + } + throw WrongStunBufferFormatException(); + } + + /** + * Get low-level iterator object + */ + static stun_attr_ref getSar(const StunAttrIterator &iter) { + return iter._sar; + } +private: + u16bits _attr_type; + u08bits *_value; + size_t _sz; +}; + +/** + * Channel number attribute class + */ +class StunAttrChannelNumber : public StunAttr { +public: + StunAttrChannelNumber() : _cn(0) { + setType(STUN_ATTRIBUTE_CHANNEL_NUMBER); + } + StunAttrChannelNumber(const StunAttrIterator &iter) + throw(WrongStunAttrFormatException, EndOfStunMsgException) : + StunAttr(iter) { + + if(iter.eof()) + throw EndOfStunMsgException(); + _cn = stun_attr_get_channel_number(getSar(iter)); + if(!_cn) + throw WrongStunAttrFormatException(); + } + virtual ~StunAttrChannelNumber() {} + u16bits getChannelNumber() const { + return _cn; + } + void setChannelNumber(u16bits cn) { + _cn = cn; + } +protected: + virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) { + return stun_attr_add_channel_number_str(buffer,&sz,_cn); + } +private: + u16bits _cn; +}; + +/** + * Even port attribute class + */ +class StunAttrEvenPort : public StunAttr { +public: + StunAttrEvenPort() : _ep(0) { + setType(STUN_ATTRIBUTE_EVEN_PORT); + } + StunAttrEvenPort(const StunAttrIterator &iter) + throw(WrongStunAttrFormatException, EndOfStunMsgException) : + StunAttr(iter) { + + if(iter.eof()) + throw EndOfStunMsgException(); + _ep = stun_attr_get_even_port(getSar(iter)); + } + virtual ~StunAttrEvenPort() {} + u08bits getEvenPort() const { + return _ep; + } + void setEvenPort(u08bits ep) { + _ep = ep; + } +protected: + virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) { + return stun_attr_add_str(buffer, &sz, STUN_ATTRIBUTE_EVEN_PORT, &_ep, 1); + } +private: + u08bits _ep; +}; + +/** + * Reservation token attribute class + */ +class StunAttrReservationToken : public StunAttr { +public: + StunAttrReservationToken() : _rt(0) { + setType(STUN_ATTRIBUTE_RESERVATION_TOKEN); + } + StunAttrReservationToken(const StunAttrIterator &iter) + throw(WrongStunAttrFormatException, EndOfStunMsgException) : + StunAttr(iter) { + + if(iter.eof()) + throw EndOfStunMsgException(); + _rt = stun_attr_get_reservation_token_value(getSar(iter)); + } + virtual ~StunAttrReservationToken() {} + u64bits getReservationToken() const { + return _rt; + } + void setReservationToken(u64bits rt) { + _rt = rt; + } +protected: + virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) { + uint64_t reservation_token = ioa_ntoh64(_rt); + return stun_attr_add_str(buffer, &sz, STUN_ATTRIBUTE_RESERVATION_TOKEN, (u08bits*) (&reservation_token), 8); + } +private: + u64bits _rt; +}; + +/** + * This attribute class is used for all address attributes + */ +class StunAttrAddr : public StunAttr { +public: + StunAttrAddr(u16bits attr_type = 0) { + addr_set_any(&_addr); + setType(attr_type); + } + StunAttrAddr(const StunAttrIterator &iter) + throw(WrongStunAttrFormatException, EndOfStunMsgException) : + StunAttr(iter) { + + if(iter.eof()) + throw EndOfStunMsgException(); + size_t sz = 0; + const u08bits *buf = iter.getRawBuffer(sz); + if(stun_attr_get_addr_str(buf,sz,getSar(iter),&_addr,NULL)<0) { + throw WrongStunAttrFormatException(); + } + } + virtual ~StunAttrAddr() {} + void getAddr(ioa_addr &addr) const { + addr_cpy(&addr,&_addr); + } + void setAddr(ioa_addr &addr) { + addr_cpy(&_addr,&addr); + } +protected: + virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) { + return stun_attr_add_addr_str(buffer, &sz, getType(), &_addr); + } +private: + ioa_addr _addr; +}; + +/** + * Change Request attribute class + */ +class StunAttrChangeRequest : public StunAttr { +public: + StunAttrChangeRequest() : _changeIp(0), _changePort(0) { + setType(STUN_ATTRIBUTE_CHANGE_REQUEST); + } + StunAttrChangeRequest(const StunAttrIterator &iter) + throw(WrongStunAttrFormatException, EndOfStunMsgException) : + StunAttr(iter) { + + if(iter.eof()) + throw EndOfStunMsgException(); + + if(stun_attr_get_change_request_str(getSar(iter), &_changeIp, &_changePort)<0) { + throw WrongStunAttrFormatException(); + } + } + virtual ~StunAttrChangeRequest() {} + bool getChangeIp() const { + return _changeIp; + } + void setChangeIp(bool ci) { + if(ci) + _changeIp = 1; + else + _changeIp = 0; + } + bool getChangePort() const { + return _changePort; + } + void setChangePort(bool cp) { + if(cp) + _changePort = 1; + else + _changePort = 0; + } +protected: + virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) { + return stun_attr_add_change_request_str(buffer, &sz, _changeIp, _changePort); + } +private: + int _changeIp; + int _changePort; +}; + +/** + * Change Request attribute class + */ +class StunAttrResponsePort : public StunAttr { +public: + StunAttrResponsePort() : _rp(0) { + setType(STUN_ATTRIBUTE_RESPONSE_PORT); + } + StunAttrResponsePort(const StunAttrIterator &iter) + throw(WrongStunAttrFormatException, EndOfStunMsgException) : + StunAttr(iter) { + + if(iter.eof()) + throw EndOfStunMsgException(); + + int rp = stun_attr_get_response_port_str(getSar(iter)); + if(rp<0) { + throw WrongStunAttrFormatException(); + } + _rp = (u16bits)rp; + } + virtual ~StunAttrResponsePort() {} + u16bits getResponsePort() const { + return _rp; + } + void setResponsePort(u16bits p) { + _rp = p; + } +protected: + virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) { + return stun_attr_add_response_port_str(buffer, &sz, _rp); + } +private: + u16bits _rp; +}; + +/** + * Padding attribute class + */ +class StunAttrPadding : public StunAttr { +public: + StunAttrPadding() : _p(0) { + setType(STUN_ATTRIBUTE_PADDING); + } + StunAttrPadding(const StunAttrIterator &iter) + throw(WrongStunAttrFormatException, EndOfStunMsgException) : + StunAttr(iter) { + + if(iter.eof()) + throw EndOfStunMsgException(); + + int p = stun_attr_get_padding_len_str(getSar(iter)); + if(p<0) { + throw WrongStunAttrFormatException(); + } + _p = (u16bits)p; + } + virtual ~StunAttrPadding() {} + u16bits getPadding() const { + return _p; + } + /** + * Set length of padding + */ + void setPadding(u16bits p) { + _p = p; + } +protected: + virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) { + return stun_attr_add_padding_str(buffer, &sz, _p); + } +private: + u16bits _p; +}; + +/** + * Generic "STUN Message" class, base class for all messages + */ +class StunMsg { +public: + /** + * Empty constructor + */ + StunMsg() { + _allocated_sz = 0xFFFF; + _buffer = (u08bits*)turn_malloc(_allocated_sz); + _deallocate = true; + _sz = 0; + _constructed = 0; + } + + /** + * Construct message over raw buffer. + * Parameter "construct" is true if the buffer is initialized. + */ + StunMsg(u08bits *buffer, size_t total_sz, size_t sz, bool constructed) : + _buffer(buffer), _deallocate(false), _allocated_sz(total_sz), + _sz(sz), _constructed(constructed) {} + + /** + * Destructor + */ + virtual ~StunMsg() { + if(_deallocate && _buffer) { + turn_free(_buffer, _allocated_sz); + } + } + + /** + * Initialize buffer + */ + void construct() { + constructBuffer(); + } + + /** + * Checks if the message is properly constructed + */ + bool isValid() { + return check(); + } + + /** + * get raw buffer + */ + u08bits *getRawBuffer() { + return _buffer; + } + + /** + * Get message size in the buffer (message can be mnuch smaller than the whole buffer) + */ + size_t getSize() const { + return _sz; + } + + /** + * Set message size + */ + void setSize(size_t sz) throw(WrongStunBufferFormatException) { + if(sz>_allocated_sz) + throw WrongStunBufferFormatException(); + _sz = sz; + } + + /** + * Check if the raw buffer is a TURN "command" (request, response or indication). + */ + static bool isCommand(u08bits *buffer, size_t sz) { + return stun_is_command_message_str(buffer, sz); + } + + /** + * Check if the current message object is a "command" (request, response, or indication). + */ + bool isCommand() const { + return stun_is_command_message_str(_buffer, _sz); + } + + static bool isIndication(u08bits *buffer, size_t sz) { + return stun_is_indication_str(buffer, sz); + } + + static bool isRequest(u08bits *buffer, size_t sz) { + return stun_is_request_str(buffer, sz); + } + + static bool isSuccessResponse(u08bits *buffer, size_t sz) { + return stun_is_success_response_str(buffer, sz); + } + + static bool isErrorResponse(u08bits *buffer, size_t sz, + int &err_code, u08bits *err_msg, size_t err_msg_size) { + return stun_is_error_response_str(buffer, sz, &err_code, err_msg, err_msg_size); + } + + /** + * Check if the raw buffer is a challenge response (the one with 401 error and realm and nonce values). + */ + static bool isChallengeResponse(const u08bits* buf, size_t sz, + int &err_code, u08bits *err_msg, size_t err_msg_size, + u08bits *realm, u08bits *nonce) { + return stun_is_challenge_response_str(buf, sz, &err_code, err_msg, err_msg_size, realm, nonce); + } + + /** + * Check if the message is a channel message + */ + static bool isChannel(u08bits *buffer, size_t sz) { + return is_channel_msg_str(buffer, sz); + } + + /** + * Check if the fingerprint is present. + */ + static bool isFingerprintPresent(u08bits *buffer, size_t sz) { + if(!stun_is_command_message_str(buffer,sz)) + return false; + stun_attr_ref sar = stun_attr_get_first_by_type_str(buffer, sz, STUN_ATTRIBUTE_FINGERPRINT); + if(!sar) + return false; + + return true; + } + + /** + * Check the fingerprint + */ + static bool checkFingerprint(u08bits *buffer, size_t sz) { + return stun_is_command_message_full_check_str(buffer, sz, 1, NULL); + } + + /** + * Add attribute to the message + */ + int addAttr(StunAttr &attr) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) { + return attr.addToMsg(*this); + } + + /** + * Get transaction ID + */ + virtual stun_tid getTid() const throw(WrongStunBufferFormatException) { + if(!_constructed || !isCommand()) + throw WrongStunBufferFormatException(); + stun_tid tid; + stun_tid_from_message_str(_buffer,_sz,&tid); + return tid; + } + + /** + * Set transaction ID + */ + virtual void setTid(stun_tid &tid) throw(WrongStunBufferFormatException) { + if(!_constructed || !isCommand()) + throw WrongStunBufferFormatException(); + stun_tid_message_cpy(_buffer, &tid); + } + + /** + * Add fingerprint to the message + */ + void addFingerprint() throw(WrongStunBufferFormatException) { + if(!_constructed || !isCommand()) + throw WrongStunBufferFormatException(); + stun_attr_add_fingerprint_str(_buffer,&_sz); + } + + /** + * Check message integrity, in secure communications. + */ + bool checkMessageIntegrity(turn_credential_type ct, std::string &uname, std::string &realm, std::string &upwd) const + throw(WrongStunBufferFormatException) { + if(!_constructed || !isCommand()) + throw WrongStunBufferFormatException(); + u08bits *suname=(u08bits*)strdup(uname.c_str()); + u08bits *srealm=(u08bits*)strdup(realm.c_str()); + u08bits *supwd=(u08bits*)strdup(upwd.c_str()); + SHATYPE sht = SHATYPE_SHA1; + bool ret = (0< stun_check_message_integrity_str(ct,_buffer, _sz, suname, srealm, supwd, sht)); + free(suname); + free(srealm); + free(supwd); + return ret; + } + + /** + * Adds long-term message integrity data to the message. + */ + void addLTMessageIntegrity(std::string &uname, std::string &realm, std::string &upwd, std::string &nonce) + throw(WrongStunBufferFormatException) { + + if(!_constructed || !isCommand()) + throw WrongStunBufferFormatException(); + + u08bits *suname=(u08bits*)strdup(uname.c_str()); + u08bits *srealm=(u08bits*)strdup(realm.c_str()); + u08bits *supwd=(u08bits*)strdup(upwd.c_str()); + u08bits *snonce=(u08bits*)strdup(nonce.c_str()); + + stun_attr_add_integrity_by_user_str(_buffer, &_sz, suname, srealm, supwd, snonce, SHATYPE_SHA1); + + free(suname); + free(srealm); + free(supwd); + free(snonce); + } + + /** + * Adds short-term message integrity data to the message. + */ + void addSTMessageIntegrity(std::string &uname, std::string &upwd) + throw(WrongStunBufferFormatException) { + + if(!_constructed || !isCommand()) + throw WrongStunBufferFormatException(); + + u08bits *suname=(u08bits*)strdup(uname.c_str()); + u08bits *supwd=(u08bits*)strdup(upwd.c_str()); + + stun_attr_add_integrity_by_user_short_term_str(_buffer, &_sz, suname, supwd, SHATYPE_SHA1); + + free(suname); + free(supwd); + } + +protected: + virtual void constructBuffer() = 0; + virtual bool check() = 0; +protected: + u08bits *_buffer; + bool _deallocate; + size_t _allocated_sz; + size_t _sz; + bool _constructed; +}; + +/** + * Class that represents the "request" flavor of STUN/TURN messages. + */ +class StunMsgRequest : public StunMsg { +public: + StunMsgRequest(u16bits method) : _method(method) {}; + StunMsgRequest(u08bits *buffer, size_t total_sz, size_t sz, bool constructed) + throw(WrongStunBufferFormatException) : + StunMsg(buffer,total_sz,sz,constructed),_method(0) { + + if(constructed) { + if(!stun_is_request_str(buffer,sz)) { + throw WrongStunBufferFormatException(); + } + _method = stun_get_method_str(buffer,sz); + } + } + virtual ~StunMsgRequest() {} + + /** + * Get request method + */ + u16bits getMethod() const { + return _method; + } + + /** + * Set method + */ + void setMethod(u16bits method) { + _method = method; + } + + /** + * Construct binding request + */ + void constructBindingRequest() { + stun_set_binding_request_str(_buffer, &_sz); + } + + bool isBindingRequest() const { + return stun_is_binding_request_str(_buffer,_sz,0); + } + + /** + * Construct allocate request + */ + void constructAllocateRequest(u32bits lifetime, int address_family, u08bits transport, int mobile) { + stun_set_allocate_request_str(_buffer, &_sz, lifetime, address_family, transport, mobile); + } + + /** + * Construct channel bind request + */ + void constructChannelBindRequest(const ioa_addr &peer_addr, u16bits channel_number) { + stun_set_channel_bind_request_str(_buffer, &_sz, + &peer_addr, channel_number); + } + +protected: + virtual void constructBuffer() { + stun_init_request_str(_method,_buffer,&_sz); + _constructed = true; + } + + virtual bool check() { + if(!_constructed) + return false; + if(!stun_is_request_str(_buffer,_sz)) { + return false; + } + if(_method != stun_get_method_str(_buffer,_sz)) { + return false; + } + return true; + } + +private: + u16bits _method; +}; + +/** + * Class for STUN/TURN responses + */ +class StunMsgResponse : public StunMsg { +public: + StunMsgResponse(u16bits method, stun_tid &tid) : _method(method), _err(0), _reason(""), _tid(tid) {}; + StunMsgResponse(u16bits method, int error_code, std::string reason, stun_tid &tid) : + _method(method), _err(error_code), _reason(reason), _tid(tid) { + + }; + StunMsgResponse(u08bits *buffer, size_t total_sz, size_t sz, bool constructed) + throw(WrongStunBufferFormatException) : + StunMsg(buffer,total_sz,sz,constructed),_method(0),_err(0),_reason("") { + + if(constructed) { + if(!stun_is_success_response_str(buffer,sz)) { + u08bits errtxt[0xFFFF]; + if(!stun_is_error_response_str(buffer,sz,&_err,errtxt,sizeof(errtxt))) { + throw WrongStunBufferFormatException(); + } + _reason = (char*)errtxt; + } + _method = stun_get_method_str(buffer,sz); + stun_tid_from_message_str(_buffer,_sz,&_tid); + } + } + + u16bits getMethod() const { + return _method; + } + + void setMethod(u16bits method) { + _method = method; + } + + /** + * Get error code + */ + int getError() const { + return _err; + } + + /** + * Set error code + */ + void setError(int err) { + _err = err; + } + + /** + * Get error message + */ + std::string getReason() const { + return _reason; + } + + /** + * Set error message + */ + void setReason(std::string reason) { + _reason = reason; + } + + /** + * Set transaction ID + */ + void setTid(stun_tid &tid) throw(WrongStunBufferFormatException) { + _tid = tid; + } + + /** + * Get transaction ID + */ + virtual stun_tid getTid() const throw(WrongStunBufferFormatException) { + return _tid; + } + + /** + * Check if this is a challenge response, and return realm and nonce + */ + bool isChallenge(std::string &realm, std::string &nonce) const { + bool ret = false; + if(_constructed) { + int err_code; + u08bits err_msg[1025]; + size_t err_msg_size=sizeof(err_msg); + u08bits srealm[0xFFFF]; + u08bits snonce[0xFFFF]; + ret = stun_is_challenge_response_str(_buffer, _sz, &err_code, err_msg, err_msg_size, srealm, snonce); + if(ret) { + realm = (char*)srealm; + nonce = (char*)snonce; + } + } + return ret; + } + + bool isChallenge() const { + std::string realm, nonce; + return isChallenge(realm, nonce); + } + + /** + * Check if this is a success response + */ + bool isSuccess() const { + return (_err == 0); + } + + /** + * Construct binding response + */ + void constructBindingResponse(stun_tid &tid, + const ioa_addr &reflexive_addr, int error_code, + const u08bits *reason) { + + stun_set_binding_response_str(_buffer, &_sz, &tid, + &reflexive_addr, error_code, + reason, 0 , 0); + } + + bool isBindingResponse() const { + return stun_is_binding_response_str(_buffer,_sz); + } + + /** + * Construct allocate response + */ + void constructAllocateResponse(stun_tid &tid, + const ioa_addr &relayed_addr, + const ioa_addr &reflexive_addr, + u32bits lifetime, int error_code, const u08bits *reason, + u64bits reservation_token, char *mobile_id) { + + stun_set_allocate_response_str(_buffer, &_sz, &tid, + &relayed_addr, + &reflexive_addr, + lifetime, error_code, reason, + reservation_token, mobile_id); + } + + /** + * Construct channel bind response + */ + void constructChannelBindResponse(stun_tid &tid, int error_code, const u08bits *reason) { + stun_set_channel_bind_response_str(_buffer, &_sz, &tid, error_code, reason); + } + +protected: + virtual void constructBuffer() { + if(_err) { + stun_init_error_response_str(_method, _buffer, &_sz, _err, (const u08bits*)_reason.c_str(), &_tid); + } else { + stun_init_success_response_str(_method, _buffer, &_sz, &_tid); + } + _constructed = true; + } + + virtual bool check() { + if(!_constructed) + return false; + if(!stun_is_success_response_str(_buffer,_sz)) { + u08bits errtxt[0xFFFF]; + int cerr=0; + if(!stun_is_error_response_str(_buffer,_sz,&cerr,errtxt,sizeof(errtxt))) { + throw WrongStunBufferFormatException(); + } + if(cerr != _err) { + throw WrongStunBufferFormatException(); + } + } + if(_method != stun_get_method_str(_buffer,_sz)) { + return false; + } + return true; + } + +private: + u16bits _method; + int _err; + std::string _reason; + stun_tid _tid; +}; + +/** + * Class for STUN/TURN indications + */ +class StunMsgIndication : public StunMsg { +public: + StunMsgIndication(u16bits method) : _method(method) {}; + StunMsgIndication(u08bits *buffer, size_t total_sz, size_t sz, bool constructed) + throw(WrongStunBufferFormatException) : + StunMsg(buffer,total_sz,sz,constructed),_method(0) { + + if(constructed) { + if(!stun_is_indication_str(buffer,sz)) { + throw WrongStunBufferFormatException(); + } + _method = stun_get_method_str(buffer,sz); + } + } + virtual ~StunMsgIndication() {} + + u16bits getMethod() const { + return _method; + } + + void setMethod(u16bits method) { + _method = method; + } + +protected: + virtual void constructBuffer() { + stun_init_indication_str(_method,_buffer,&_sz); + _constructed = true; + } + + virtual bool check() { + if(!_constructed) + return false; + if(!stun_is_indication_str(_buffer,_sz)) { + return false; + } + if(_method != stun_get_method_str(_buffer,_sz)) { + return false; + } + return true; + } + +private: + u16bits _method; +}; + +/** + * Channel message + */ +class StunMsgChannel : public StunMsg { +public: + StunMsgChannel(u16bits cn, int length) : _cn(cn), _len(length) {}; + StunMsgChannel(u08bits *buffer, size_t total_sz, size_t sz, bool constructed) + throw(WrongStunBufferFormatException) : + StunMsg(buffer,total_sz,sz,constructed),_cn(0) { + + if(constructed) { + if(!stun_is_channel_message_str(buffer,&_sz,&_cn,0)) { + throw WrongStunBufferFormatException(); + } + if(_sz>0xFFFF || _sz<4) + throw WrongStunBufferFormatException(); + + _len = _sz-4; + } else { + if(total_sz>0xFFFF || total_sz<4) + throw WrongStunBufferFormatException(); + + _len = 0; + } + } + virtual ~StunMsgChannel() {} + + u16bits getChannelNumber() const { + return _cn; + } + + void setChannelNumber(u16bits cn) { + _cn = cn; + } + + /** + * Get length of message itself (excluding the 4 channel number bytes) + */ + size_t getLength() const { + return _len; + } + + /** + * Set length of message itself (excluding the 4 channel number bytes) + */ + void setLength(size_t len) { + _len = len; + } + +protected: + virtual void constructBuffer() { + stun_init_channel_message_str(_cn,_buffer,&_sz,(int)_len,0); + _constructed = true; + } + + virtual bool check() { + if(!_constructed) + return false; + u16bits cn = 0; + if(!stun_is_channel_message_str(_buffer,&_sz,&cn,0)) { + return false; + } + if(_cn != cn) { + return false; + } + return true; + } + +private: + u16bits _cn; + size_t _len; +}; + +}; +/* namespace */ + +#endif +/* __LIB_TURN_MSG_CPP__ */ diff --git a/src/client/ns_turn_ioaddr.c b/src/client/ns_turn_ioaddr.c new file mode 100644 index 00000000..ef55ab14 --- /dev/null +++ b/src/client/ns_turn_ioaddr.c @@ -0,0 +1,477 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "ns_turn_ioaddr.h" + +////////////////////////////////////////////////////////////// + +u32bits get_ioa_addr_len(const ioa_addr* addr) { + if(addr->ss.sa_family == AF_INET) return sizeof(struct sockaddr_in); + else if(addr->ss.sa_family == AF_INET6) return sizeof(struct sockaddr_in6); + return 0; +} + +/////////////////////////////////////////////////////////////// + +void addr_set_any(ioa_addr *addr) { + if(addr) + ns_bzero(addr,sizeof(ioa_addr)); +} + +int addr_any(const ioa_addr* addr) { + + if(!addr) + return 1; + + if(addr->ss.sa_family == AF_INET) { + return ((addr->s4.sin_addr.s_addr==0)&&(addr->s4.sin_port==0)); + } else if(addr->ss.sa_family == AF_INET6) { + if(addr->s6.sin6_port!=0) return 0; + else { + size_t i; + for(i=0;is6.sin6_addr);i++) + if(((const s08bits*)&(addr->s6.sin6_addr))[i]) return 0; + } + } + + return 1; +} + +int addr_any_no_port(const ioa_addr* addr) { + if(!addr) + return 1; + + if(addr->ss.sa_family == AF_INET) { + return (addr->s4.sin_addr.s_addr==0); + } else if(addr->ss.sa_family == AF_INET6) { + size_t i; + for(i=0;is6.sin6_addr);i++) + if(((const s08bits*)(&(addr->s6.sin6_addr)))[i]) return 0; + } + + return 1; +} + +u32bits hash_int32(u32bits a) +{ + a = a ^ (a>>4); + a = (a^0xdeadbeef) + (a<<5); + a = a ^ (a>>11); + return a; +} + +u64bits hash_int64(u64bits a) +{ + a = a ^ (a>>4); + a = (a^0xdeadbeefdeadbeef) + (a<<5); + a = a ^ (a>>11); + return a; +} + +u32bits addr_hash(const ioa_addr *addr) +{ + if(!addr) + return 0; + + u32bits ret = 0; + if (addr->ss.sa_family == AF_INET) { + ret = hash_int32(addr->s4.sin_addr.s_addr + addr->s4.sin_port); + } else { + const u64bits *a = (const u64bits *) (&(addr->s6.sin6_addr)); + ret = (u32bits)((hash_int64(a[0])<<3) + (hash_int64(a[1] + addr->s6.sin6_port))); + } + return ret; +} + +u32bits addr_hash_no_port(const ioa_addr *addr) +{ + if(!addr) + return 0; + + u32bits ret = 0; + if (addr->ss.sa_family == AF_INET) { + ret = hash_int32(addr->s4.sin_addr.s_addr); + } else { + const u64bits *a = (const u64bits *) (&(addr->s6.sin6_addr)); + ret = (u32bits)((hash_int64(a[0])<<3) + (hash_int64(a[1]))); + } + return ret; +} + +void addr_cpy(ioa_addr* dst, const ioa_addr* src) { + if(dst && src) + ns_bcopy(src,dst,sizeof(ioa_addr)); +} + +void addr_cpy4(ioa_addr* dst, const struct sockaddr_in* src) { + if(src && dst) + ns_bcopy(src,dst,sizeof(struct sockaddr_in)); +} + +void addr_cpy6(ioa_addr* dst, const struct sockaddr_in6* src) { + if(src && dst) + ns_bcopy(src,dst,sizeof(struct sockaddr_in6)); +} + +int addr_eq(const ioa_addr* a1, const ioa_addr *a2) { + + if(!a1) return (!a2); + else if(!a2) return (!a1); + + if(a1->ss.sa_family == a2->ss.sa_family) { + if(a1->ss.sa_family == AF_INET && a1->s4.sin_port == a2->s4.sin_port) { + if((int)a1->s4.sin_addr.s_addr == (int)a2->s4.sin_addr.s_addr) { + return 1; + } + } else if(a1->ss.sa_family == AF_INET6 && a1->s6.sin6_port == a2->s6.sin6_port) { + const u64bits *p1=(const u64bits *)(&(a1->s6.sin6_addr)); + const u64bits *p2=(const u64bits *)(&(a2->s6.sin6_addr)); + if(p1[0]==p2[0] && p1[1]==p2[1]) { + return 1; + } + } + } + + return 0; +} + +int addr_eq_no_port(const ioa_addr* a1, const ioa_addr *a2) { + + if(!a1) return (!a2); + else if(!a2) return (!a1); + + if(a1->ss.sa_family == a2->ss.sa_family) { + if(a1->ss.sa_family == AF_INET) { + if((int)a1->s4.sin_addr.s_addr == (int)a2->s4.sin_addr.s_addr) { + return 1; + } + } else if(a1->ss.sa_family == AF_INET6) { + const u64bits *p1=(const u64bits *)(&(a1->s6.sin6_addr)); + const u64bits *p2=(const u64bits *)(&(a2->s6.sin6_addr)); + if(p1[0]==p2[0] && p1[1]==p2[1]) { + return 1; + } + } + } + return 0; +} + +int make_ioa_addr(const u08bits* saddr, int port, ioa_addr *addr) { + + if(!saddr || !addr) return -1; + + ns_bzero(addr, sizeof(ioa_addr)); + if((strlen((const s08bits*)saddr) == 0)|| + (inet_pton(AF_INET, (const s08bits*)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) { + 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); +#endif + addr->s6.sin6_port = nswap16(port); + } else { + return -1; + } + + return 0; +} + +static char* get_addr_string_and_port(char* s0, int *port) +{ + char *s = s0; + while(*s && (*s==' ')) ++s; + if(*s == '[') { + ++s; + char *tail = strstr(s,"]"); + if(tail) { + *tail=0; + ++tail; + while(*tail && (*tail==' ')) ++tail; + if(*tail==':') { + ++tail; + *port = atoi(tail); + return s; + } else if(*tail == 0) { + *port = 0; + return s; + } + } + } else { + char *tail = strstr(s,":"); + if(tail) { + *tail = 0; + ++tail; + *port = atoi(tail); + return s; + } else { + *port = 0; + return s; + } + } + return NULL; +} + +int make_ioa_addr_from_full_string(const u08bits* saddr, int default_port, ioa_addr *addr) +{ + if(!addr) + return -1; + + int ret = -1; + int port = 0; + char* s = strdup((const char*)saddr); + char *sa = get_addr_string_and_port(s,&port); + if(sa) { + if(port<1) + port = default_port; + ret = make_ioa_addr((u08bits*)sa,port,addr); + } + turn_free(s,strlen(s)+1); + return ret; +} + +int addr_to_string(const ioa_addr* addr, u08bits* saddr) +{ + + if (addr && saddr) { + + s08bits addrtmp[MAX_IOA_ADDR_STRING]; + + if (addr->ss.sa_family == AF_INET) { + inet_ntop(AF_INET, &addr->s4.sin_addr, addrtmp, INET_ADDRSTRLEN); + if(addr_get_port(addr)>0) + snprintf((s08bits*)saddr, MAX_IOA_ADDR_STRING, "%s:%d", addrtmp, addr_get_port(addr)); + else + strncpy((s08bits*)saddr, addrtmp, MAX_IOA_ADDR_STRING); + } else if (addr->ss.sa_family == AF_INET6) { + inet_ntop(AF_INET6, &addr->s6.sin6_addr, addrtmp, INET6_ADDRSTRLEN); + if(addr_get_port(addr)>0) + snprintf((s08bits*)saddr, MAX_IOA_ADDR_STRING, "[%s]:%d", addrtmp, addr_get_port(addr)); + else + strncpy((s08bits*)saddr, addrtmp, MAX_IOA_ADDR_STRING); + } else { + return -1; + } + + return 0; + } + + return -1; +} + +int addr_to_string_no_port(const ioa_addr* addr, u08bits* saddr) +{ + + if (addr && saddr) { + + s08bits addrtmp[MAX_IOA_ADDR_STRING]; + + if (addr->ss.sa_family == AF_INET) { + inet_ntop(AF_INET, &addr->s4.sin_addr, addrtmp, INET_ADDRSTRLEN); + strncpy((s08bits*)saddr, addrtmp, MAX_IOA_ADDR_STRING); + } else if (addr->ss.sa_family == AF_INET6) { + inet_ntop(AF_INET6, &addr->s6.sin6_addr, addrtmp, INET6_ADDRSTRLEN); + strncpy((s08bits*)saddr, addrtmp, MAX_IOA_ADDR_STRING); + } else { + return -1; + } + + return 0; + } + + return -1; +} + +void addr_set_port(ioa_addr* addr, int port) { + if(addr) { + if(addr->s4.sin_family == AF_INET) { + addr->s4.sin_port = nswap16(port); + } else if(addr->s6.sin6_family == AF_INET6) { + addr->s6.sin6_port = nswap16(port); + } + } +} + +int addr_get_port(const ioa_addr* addr) { + if(!addr) + return 0; + + if(addr->s4.sin_family == AF_INET) { + return nswap16(addr->s4.sin_port); + } else if(addr->s6.sin6_family == AF_INET6) { + return nswap16(addr->s6.sin6_port); + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////// + +void ioa_addr_range_set(ioa_addr_range* range, const ioa_addr* addr_min, const ioa_addr* addr_max) { + if(range) { + if(addr_min) addr_cpy(&(range->min),addr_min); + else addr_set_any(&(range->min)); + if(addr_max) addr_cpy(&(range->max),addr_max); + else addr_set_any(&(range->max)); + } +} + +int addr_less_eq(const ioa_addr* addr1, const ioa_addr* addr2) { + + if(!addr1) return 1; + else if(!addr2) return 0; + else { + if(addr1->ss.sa_family != addr2->ss.sa_family) return (addr1->ss.sa_family < addr2->ss.sa_family); + else if(addr1->ss.sa_family == AF_INET) { + return ((u32bits)nswap32(addr1->s4.sin_addr.s_addr) <= (u32bits)nswap32(addr2->s4.sin_addr.s_addr)); + } else if(addr1->ss.sa_family == AF_INET6) { + int i; + for(i=0;i<16;i++) { + if((u08bits)(((const s08bits*)&(addr1->s6.sin6_addr))[i]) > (u08bits)(((const s08bits*)&(addr2->s6.sin6_addr))[i])) + return 0; + } + return 1; + } else return 1; + } +} + +int ioa_addr_in_range(const ioa_addr_range* range, const ioa_addr* addr) { + + if(range && addr) { + if(addr_any(&(range->min)) || addr_less_eq(&(range->min),addr)) { + if(addr_any(&(range->max))) { + return 1; + } else { + return addr_less_eq(addr,&(range->max)); + } + } + } + + return 0; +} + +void ioa_addr_range_cpy(ioa_addr_range* dest, const ioa_addr_range* src) { + if(dest && src) { + addr_cpy(&(dest->min),&(src->min)); + addr_cpy(&(dest->max),&(src->max)); + } +} + +/////// Check whether this is a good address ////////////// + +int ioa_addr_is_multicast(ioa_addr *addr) +{ + if(addr) { + if(addr->ss.sa_family == AF_INET) { + const u08bits *u = ((const u08bits*)&(addr->s4.sin_addr)); + return (u[0] > 223); + } else if(addr->ss.sa_family == AF_INET6) { + u08bits u = ((const u08bits*)&(addr->s6.sin6_addr))[0]; + return (u == 255); + } + } + return 0; +} + +int ioa_addr_is_loopback(ioa_addr *addr) +{ + if(addr) { + if(addr->ss.sa_family == AF_INET) { + const u08bits *u = ((const u08bits*)&(addr->s4.sin_addr)); + return (u[0] == 127); + } else if(addr->ss.sa_family == AF_INET6) { + const u08bits *u = ((const u08bits*)&(addr->s6.sin6_addr)); + if(u[7] == 1) { + int i; + for(i=0;i<7;++i) { + if(u[i]) + return 0; + } + return 1; + } + } + } + return 0; +} + +/////// Map "public" address to "private" address ////////////// + +// Must be called only in a single-threaded context, +// before the program starts spawning threads: + +static ioa_addr **public_addrs = NULL; +static ioa_addr **private_addrs = NULL; +static size_t mcount = 0; +static size_t msz = 0; + +void ioa_addr_add_mapping(ioa_addr *apub, ioa_addr *apriv) +{ + size_t new_size = msz + sizeof(ioa_addr*); + public_addrs = (ioa_addr**)turn_realloc(public_addrs, msz, new_size); + private_addrs = (ioa_addr**)turn_realloc(private_addrs, msz, new_size); + public_addrs[mcount]=(ioa_addr*)turn_malloc(sizeof(ioa_addr)); + private_addrs[mcount]=(ioa_addr*)turn_malloc(sizeof(ioa_addr)); + addr_cpy(public_addrs[mcount],apub); + addr_cpy(private_addrs[mcount],apriv); + ++mcount; + msz += sizeof(ioa_addr*); +} + +void map_addr_from_public_to_private(const ioa_addr *public_addr, ioa_addr *private_addr) +{ + size_t i; + for(i=0;i +#include +#include +#include +#include + +#include + +/////////// + +long turn_random(void) +{ + long ret = 0; + if(!RAND_bytes((unsigned char *)&ret,sizeof(ret))) + ret = random(); + return ret; +} + +void turn_random32_size(u32bits *ar, size_t sz) +{ + if(!RAND_bytes((unsigned char *)ar, sz<<2)<0) { + size_t i; + for(i=0;i>1) | + ((tt & 0x0E00)>>2) | ((tt & 0x3000)>>2); +} + +u16bits stun_get_msg_type_str(const u08bits *buf, size_t len) { + if(!buf || len<2) return (u16bits)-1; + return ((nswap16(((const u16bits*)buf)[0])) & 0x3FFF); +} + +int is_channel_msg_str(const u08bits* buf, size_t blen) { + return (buf && blen>=4 && STUN_VALID_CHANNEL(nswap16(((const u16bits*)buf)[0]))); +} + +/////////////// message types ///////////////////////////////// + +int stun_is_command_message_str(const u08bits* buf, size_t blen) +{ + if (buf && blen >= STUN_HEADER_LENGTH) { + if (!STUN_VALID_CHANNEL(nswap16(((const u16bits*)buf)[0]))) { + if ((((u08bits) buf[0]) & ((u08bits) (0xC0))) == 0) { + if (nswap32(((const u32bits*)(buf))[1]) + == STUN_MAGIC_COOKIE) { + u16bits len = nswap16(((const u16bits*)(buf))[1]); + if ((len & 0x0003) == 0) { + if ((size_t) (len + STUN_HEADER_LENGTH) == blen) { + return 1; + } + } + } + } + } + } + return 0; +} + +int old_stun_is_command_message_str(const u08bits* buf, size_t blen, u32bits *cookie) +{ + if (buf && blen >= STUN_HEADER_LENGTH) { + if (!STUN_VALID_CHANNEL(nswap16(((const u16bits*)buf)[0]))) { + if ((((u08bits) buf[0]) & ((u08bits) (0xC0))) == 0) { + if (nswap32(((const u32bits*)(buf))[1]) + != STUN_MAGIC_COOKIE) { + u16bits len = nswap16(((const u16bits*)(buf))[1]); + if ((len & 0x0003) == 0) { + if ((size_t) (len + STUN_HEADER_LENGTH) == blen) { + *cookie = nswap32(((const u32bits*)(buf))[1]); + return 1; + } + } + } + } + } + } + return 0; +} + +int stun_is_command_message_full_check_str(const u08bits* buf, size_t blen, int must_check_fingerprint, int *fingerprint_present) { + if(!stun_is_command_message_str(buf,blen)) + return 0; + stun_attr_ref sar = stun_attr_get_first_by_type_str(buf, blen, STUN_ATTRIBUTE_FINGERPRINT); + if(!sar) { + if(fingerprint_present) + *fingerprint_present = 0; + if(stun_get_method_str(buf,blen) == STUN_METHOD_BINDING) { + return 1; + } + return !must_check_fingerprint; + } + if(stun_attr_get_len(sar) != 4) + return 0; + const u32bits* fingerprint = (const u32bits*)stun_attr_get_value(sar); + if(!fingerprint) + return !must_check_fingerprint; + u32bits crc32len = (u32bits)((((const u08bits*)fingerprint)-buf)-4); + int ret = (*fingerprint == nswap32(ns_crc32(buf,crc32len) ^ ((u32bits)0x5354554e))); + if(ret && fingerprint_present) + *fingerprint_present = ret; + return ret; +} + +int stun_is_command_message_offset_str(const u08bits* buf, size_t blen, int offset) { + return stun_is_command_message_str(buf + offset, blen); +} + +int stun_is_request_str(const u08bits* buf, size_t len) { + if(is_channel_msg_str(buf,len)) return 0; + return IS_STUN_REQUEST(stun_get_msg_type_str(buf,len)); +} + +int stun_is_success_response_str(const u08bits* buf, size_t len) { + if(is_channel_msg_str(buf,len)) return 0; + return IS_STUN_SUCCESS_RESP(stun_get_msg_type_str(buf,len)); +} + +int stun_is_error_response_str(const u08bits* buf, size_t len, int *err_code, u08bits *err_msg, size_t err_msg_size) { + if(is_channel_msg_str(buf,len)) return 0; + if(IS_STUN_ERR_RESP(stun_get_msg_type_str(buf,len))) { + if(err_code) { + stun_attr_ref sar = stun_attr_get_first_by_type_str(buf, len, STUN_ATTRIBUTE_ERROR_CODE); + if(sar) { + if(stun_attr_get_len(sar)>=4) { + const u08bits* val = (const u08bits*)stun_attr_get_value(sar); + *err_code=(int)(val[2]*100 + val[3]); + if(err_msg && err_msg_size>0) { + err_msg[0]=0; + if(stun_attr_get_len(sar)>4) { + size_t msg_len = stun_attr_get_len(sar) - 4; + if(msg_len>(err_msg_size-1)) + msg_len=err_msg_size - 1; + ns_bcopy(val+4, err_msg, msg_len); + err_msg[msg_len]=0; + } + } + } + } + } + return 1; + } + return 0; +} + +int stun_is_challenge_response_str(const u08bits* buf, size_t len, int *err_code, u08bits *err_msg, size_t err_msg_size, + u08bits *realm, u08bits *nonce) +{ + int ret = stun_is_error_response_str(buf, len, err_code, err_msg, err_msg_size); + + if(ret && (((*err_code) == 401) || ((*err_code) == 438) || ((*err_code) == SHA_TOO_WEAK))) { + + stun_attr_ref sar = stun_attr_get_first_by_type_str(buf,len,STUN_ATTRIBUTE_REALM); + if(sar) { + const u08bits *value = stun_attr_get_value(sar); + if(value) { + size_t vlen = (size_t)stun_attr_get_len(sar); + ns_bcopy(value,realm,vlen); + realm[vlen]=0; + sar = stun_attr_get_first_by_type_str(buf,len,STUN_ATTRIBUTE_NONCE); + if(sar) { + value = stun_attr_get_value(sar); + if(value) { + vlen = (size_t)stun_attr_get_len(sar); + ns_bcopy(value,nonce,vlen); + nonce[vlen]=0; + return 1; + } + } + } + } + } + + return 0; +} + +int stun_is_response_str(const u08bits* buf, size_t len) { + if(is_channel_msg_str(buf,len)) return 0; + if(IS_STUN_SUCCESS_RESP(stun_get_msg_type_str(buf,len))) return 1; + if(IS_STUN_ERR_RESP(stun_get_msg_type_str(buf,len))) return 1; + return 0; +} + +int stun_is_indication_str(const u08bits* buf, size_t len) { + if(is_channel_msg_str(buf,len)) return 0; + return IS_STUN_INDICATION(stun_get_msg_type_str(buf,len)); +} + +u16bits stun_make_request(u16bits method) { + return GET_STUN_REQUEST(stun_make_type(method)); +} + +u16bits stun_make_indication(u16bits method) { + return GET_STUN_INDICATION(stun_make_type(method)); +} + +u16bits stun_make_success_response(u16bits method) { + return GET_STUN_SUCCESS_RESP(stun_make_type(method)); +} + +u16bits stun_make_error_response(u16bits method) { + return GET_STUN_ERR_RESP(stun_make_type(method)); +} + +//////////////// INIT //////////////////////////////////////////// + +void stun_init_buffer_str(u08bits *buf, size_t *len) { + *len=STUN_HEADER_LENGTH; + ns_bzero(buf,*len); +} + +void stun_init_command_str(u16bits message_type, u08bits* buf, size_t *len) { + stun_init_buffer_str(buf,len); + message_type &= (u16bits)(0x3FFF); + ((u16bits*)buf)[0]=nswap16(message_type); + ((u16bits*)buf)[1]=0; + ((u32bits*)buf)[1]=nswap32(STUN_MAGIC_COOKIE); + stun_tid_generate_in_message_str(buf,NULL); +} + +void old_stun_init_command_str(u16bits message_type, u08bits* buf, size_t *len, u32bits cookie) { + stun_init_buffer_str(buf,len); + message_type &= (u16bits)(0x3FFF); + ((u16bits*)buf)[0]=nswap16(message_type); + ((u16bits*)buf)[1]=0; + ((u32bits*)buf)[1]=nswap32(cookie); + stun_tid_generate_in_message_str(buf,NULL); +} + +void stun_init_request_str(u16bits method, u08bits* buf, size_t *len) { + stun_init_command_str(stun_make_request(method), buf, len); +} + +void stun_init_indication_str(u16bits method, u08bits* buf, size_t *len) { + stun_init_command_str(stun_make_indication(method), buf, len); +} + +void stun_init_success_response_str(u16bits method, u08bits* buf, size_t *len, stun_tid* id) { + stun_init_command_str(stun_make_success_response(method), buf, len); + if(id) { + stun_tid_message_cpy(buf, id); + } +} + +void old_stun_init_success_response_str(u16bits method, u08bits* buf, size_t *len, stun_tid* id, u32bits cookie) { + old_stun_init_command_str(stun_make_success_response(method), buf, len, cookie); + if(id) { + stun_tid_message_cpy(buf, id); + } +} + +static void stun_init_error_response_common_str(u08bits* buf, size_t *len, + u16bits error_code, const u08bits *reason, + stun_tid* id) +{ + + if (!reason) { + + switch (error_code){ + case 300: + reason = (const u08bits *) "Try Alternate"; + break; + case 400: + reason = (const u08bits *) "Bad Request"; + break; + case 401: + reason = (const u08bits *) "Unauthorized"; + break; + case 404: + reason = (const u08bits *) "Not Found"; + break; + case 420: + reason = (const u08bits *) "Unknown Attribute"; + break; + case 438: + reason = (const u08bits *) "Stale Nonce"; + break; + case 500: + reason = (const u08bits *) "Server Error"; + break; + default: + reason = (const u08bits *) "Unknown Error"; + break; + }; + } + + u08bits avalue[513]; + avalue[0] = 0; + avalue[1] = 0; + avalue[2] = (u08bits) (error_code / 100); + avalue[3] = (u08bits) (error_code % 100); + strncpy((s08bits*) (avalue + 4), (const s08bits*) reason, sizeof(avalue)-4); + avalue[sizeof(avalue)-1]=0; + int alen = 4 + strlen((const s08bits*) (avalue+4)); + + //"Manual" padding for compatibility with classic old stun: + { + int rem = alen % 4; + if(rem) { + alen +=(4-rem); + } + } + + stun_attr_add_str(buf, len, STUN_ATTRIBUTE_ERROR_CODE, (u08bits*) avalue, alen); + if (id) { + stun_tid_message_cpy(buf, id); + } +} + +void old_stun_init_error_response_str(u16bits method, u08bits* buf, size_t *len, + u16bits error_code, const u08bits *reason, + stun_tid* id, u32bits cookie) +{ + + old_stun_init_command_str(stun_make_error_response(method), buf, len, cookie); + + stun_init_error_response_common_str(buf, len, + error_code, reason, + id); +} + +void stun_init_error_response_str(u16bits method, u08bits* buf, size_t *len, + u16bits error_code, const u08bits *reason, + stun_tid* id) +{ + + stun_init_command_str(stun_make_error_response(method), buf, len); + + stun_init_error_response_common_str(buf, len, + error_code, reason, + id); +} + +/////////// CHANNEL //////////////////////////////////////////////// + +int stun_init_channel_message_str(u16bits chnumber, u08bits* buf, size_t *len, int length, int do_padding) +{ + u16bits rlen = (u16bits)length; + + if(length<0 || (MAX_STUN_MESSAGE_SIZE<(4+length))) return -1; + ((u16bits*)(buf))[0]=nswap16(chnumber); + ((u16bits*)(buf))[1]=nswap16((u16bits)length); + + if(do_padding && (rlen & 0x0003)) + rlen = ((rlen>>2)+1)<<2; + + *len=4+rlen; + + return 0; +} + +int stun_is_channel_message_str(const u08bits *buf, size_t *blen, u16bits* chnumber, int mandatory_padding) +{ + u16bits datalen_header; + u16bits datalen_actual; + + if (!blen || (*blen < 4)) + return 0; + + u16bits chn = nswap16(((const u16bits*)(buf))[0]); + if (!STUN_VALID_CHANNEL(chn)) + return 0; + + if(*blen>(u16bits)-1) + *blen=(u16bits)-1; + + datalen_actual = (u16bits)(*blen) - 4; + datalen_header = ((const u16bits*)buf)[1]; + datalen_header = nswap16(datalen_header); + + if (datalen_header > datalen_actual) + return 0; + + if (datalen_header != datalen_actual) { + + /* maybe there are padding bytes for 32-bit alignment. Mandatory for TCP. Optional for UDP */ + + if(datalen_actual & 0x0003) { + + if(mandatory_padding) { + return 0; + } else if ((datalen_actual < datalen_header) || (datalen_header == 0)) { + return 0; + } else { + u16bits diff = datalen_actual - datalen_header; + if (diff > 3) + return 0; + } + } + } + + *blen = datalen_header + 4; + + if (chnumber) + *chnumber = chn; + + return 1; +} + +////////// STUN message /////////////////////////////// + +static inline int sheadof(const char *head, const char* full) +{ + while(*head) { + if(*head != *full) + return 0; + ++head;++full; + } + return 1; +} + +static inline const char* findstr(const char *hay, size_t slen, const char *needle) +{ + const char *ret = NULL; + + if(hay && slen && needle) { + size_t nlen=strlen(needle); + if(nlen<=slen) { + size_t smax = slen-nlen+1; + size_t i; + const char *sp = hay; + for(i=0;i=12) { + if((s[0]=='G')&&(s[1]=='E')&&(s[2]=='T')&&(s[3]==' ')) { + const char *sp=findstr(s+4,blen-4,"HTTP"); + if(sp) { + sp += 4; + size_t diff_blen = sp-s; + if(diff_blen+4 <= blen) { + sp=findstr(sp,blen-diff_blen,"\r\n\r\n"); + if(sp) { + return (int)(sp-s+4); + } + } + } + + } + } + return 0; +} + +int is_http_get(const char *s, size_t blen) { + return is_http_get_inline(s, blen); +} + +int stun_get_message_len_str(u08bits *buf, size_t blen, int padding, size_t *app_len) { + if (buf && blen) { + /* STUN request/response ? */ + if (buf && blen >= STUN_HEADER_LENGTH) { + if (!STUN_VALID_CHANNEL(nswap16(((const u16bits*)buf)[0]))) { + if ((((u08bits) buf[0]) & ((u08bits) (0xC0))) == 0) { + if (nswap32(((const u32bits*)(buf))[1]) + == STUN_MAGIC_COOKIE) { + u16bits len = nswap16(((const u16bits*)(buf))[1]); + if ((len & 0x0003) == 0) { + len += STUN_HEADER_LENGTH; + if ((size_t) len <= blen) { + *app_len = (size_t)len; + return (int)len; + } + } + } + } + } + } + + //HTTP request ? + { + int http_len = is_http_get_inline(((char*)buf), blen); + if((http_len>0) && ((size_t)http_len<=blen)) { + *app_len = (size_t)http_len; + return http_len; + } + } + + /* STUN channel ? */ + if(blen>=4) { + u16bits chn=nswap16(((const u16bits*)(buf))[0]); + if(STUN_VALID_CHANNEL(chn)) { + + u16bits bret = (4+(nswap16(((const u16bits*)(buf))[1]))); + + *app_len = bret; + + if(padding && (bret & 0x0003)) { + bret = ((bret>>2)+1)<<2; + } + + if(bret<=blen) { + return bret; + } + } + } + + } + + return -1; +} + +////////// ALLOCATE /////////////////////////////////// + +int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int address_family, + u08bits transport, int mobile) { + + stun_init_request_str(STUN_METHOD_ALLOCATE, buf, len); + + //REQUESTED-TRANSPORT + { + u08bits field[4]; + field[0]=transport; + field[1]=0; + field[2]=0; + field[3]=0; + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_TRANSPORT,field,sizeof(field))<0) return -1; + } + + //LIFETIME + { + if(lifetime<1) lifetime=STUN_DEFAULT_ALLOCATE_LIFETIME; + u32bits field=nswap32(lifetime); + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_LIFETIME,(u08bits*)(&field),sizeof(field))<0) return -1; + } + + if(mobile) { + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_MOBILITY_TICKET,(const u08bits*)"",0)<0) return -1; + } + + //ADRESS-FAMILY + switch (address_family) { + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: + { + u08bits field[4]; + field[0] = (u08bits)address_family; + field[1]=0; + field[2]=0; + field[3]=0; + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1; + break; + } + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT: + /* ignore */ + break; + default: + return -1; + }; + + return 0; +} + +int stun_set_allocate_response_str(u08bits* buf, size_t *len, stun_tid* tid, + const ioa_addr *relayed_addr, const ioa_addr *reflexive_addr, + u32bits lifetime, int error_code, const u08bits *reason, + u64bits reservation_token, char* mobile_id) { + + if(!error_code) { + + stun_init_success_response_str(STUN_METHOD_ALLOCATE, buf, len, tid); + + if(relayed_addr) { + if(stun_attr_add_addr_str(buf,len,STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS,relayed_addr)<0) return -1; + } + + if(reflexive_addr) { + if(stun_attr_add_addr_str(buf,len,STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,reflexive_addr)<0) return -1; + } + + if(reservation_token) { + reservation_token=nswap64(reservation_token); + stun_attr_add_str(buf,len,STUN_ATTRIBUTE_RESERVATION_TOKEN,(u08bits*)(&reservation_token),8); + } + + { + if(lifetime<1) lifetime=STUN_DEFAULT_ALLOCATE_LIFETIME; + else if(lifetime>STUN_MAX_ALLOCATE_LIFETIME) lifetime = STUN_MAX_ALLOCATE_LIFETIME; + + u32bits field=nswap32(lifetime); + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_LIFETIME,(u08bits*)(&field),sizeof(field))<0) return -1; + } + + if(mobile_id && *mobile_id) { + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_MOBILITY_TICKET,(u08bits*)mobile_id,strlen(mobile_id))<0) return -1; + } + + } else { + stun_init_error_response_str(STUN_METHOD_ALLOCATE, buf, len, error_code, reason, tid); + } + + return 0; +} + +/////////////// CHANNEL BIND /////////////////////////////////////// + +u16bits stun_set_channel_bind_request_str(u08bits* buf, size_t *len, + const ioa_addr* peer_addr, u16bits channel_number) { + + if(!STUN_VALID_CHANNEL(channel_number)) { + channel_number = 0x4000 + ((u16bits)(((u32bits)turn_random())%(0x7FFF-0x4000+1))); + } + + stun_init_request_str(STUN_METHOD_CHANNEL_BIND, buf, len); + + if(stun_attr_add_channel_number_str(buf, len, channel_number)<0) return 0; + + if(!peer_addr) { + ioa_addr ca; + ns_bzero(&ca,sizeof(ioa_addr)); + + if(stun_attr_add_addr_str(buf,len,STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &ca)<0) return 0; + } else { + if(stun_attr_add_addr_str(buf,len,STUN_ATTRIBUTE_XOR_PEER_ADDRESS, peer_addr)<0) return 0; + } + + return channel_number; +} + +void stun_set_channel_bind_response_str(u08bits* buf, size_t *len, stun_tid* tid, int error_code, const u08bits *reason) { + if(!error_code) { + stun_init_success_response_str(STUN_METHOD_CHANNEL_BIND, buf, len, tid); + } else { + stun_init_error_response_str(STUN_METHOD_CHANNEL_BIND, buf, len, error_code, reason, tid); + } +} + +/////////////// BINDING /////////////////////////////////////// + +void stun_set_binding_request_str(u08bits* buf, size_t *len) { + stun_init_request_str(STUN_METHOD_BINDING, buf, len); +} + +int stun_set_binding_response_str(u08bits* buf, size_t *len, stun_tid* tid, + const ioa_addr *reflexive_addr, int error_code, const u08bits *reason, + u32bits cookie, int old_stun) + +{ + if (!error_code) { + if (!old_stun) { + stun_init_success_response_str(STUN_METHOD_BINDING, buf, len, tid); + } else { + old_stun_init_success_response_str(STUN_METHOD_BINDING, buf, len, tid, cookie); + } + if(!old_stun) { + if (stun_attr_add_addr_str(buf, len, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, reflexive_addr) < 0) + return -1; + } + if (stun_attr_add_addr_str(buf, len, STUN_ATTRIBUTE_MAPPED_ADDRESS, reflexive_addr) < 0) + return -1; + } else if (!old_stun) { + stun_init_error_response_str(STUN_METHOD_BINDING, buf, len, error_code, reason, tid); + } else { + old_stun_init_error_response_str(STUN_METHOD_BINDING, buf, len, error_code, reason, tid, cookie); + } + + return 0; +} + +int stun_is_binding_request_str(const u08bits* buf, size_t len, size_t offset) +{ + if(offset < len) { + buf += offset; + len -= offset; + if (stun_is_command_message_str(buf, len)) { + if (stun_is_request_str(buf, len) && (stun_get_method_str(buf, len) == STUN_METHOD_BINDING)) { + return 1; + } + } + } + return 0; +} + +int stun_is_binding_response_str(const u08bits* buf, size_t len) { + if(stun_is_command_message_str(buf,len) && + (stun_get_method_str(buf,len)==STUN_METHOD_BINDING)) { + if(stun_is_response_str(buf,len)) { + return 1; + } + } + return 0; +} + +/////////////////////////////// TID /////////////////////////////// + + +int stun_tid_equals(const stun_tid *id1, const stun_tid *id2) { + if(id1==id2) return 1; + if(!id1) return 0; + if(!id2) return 0; + { + unsigned int i=0; + for(i=0;itsx_id[i]!=id2->tsx_id[i]) return 0; + } + } + return 1; +} + +void stun_tid_cpy(stun_tid *id1, const stun_tid *id2) { + if(!id1) return; + if(!id2) return; + ns_bcopy((const void*)(id2->tsx_id),(void*)(id1->tsx_id),STUN_TID_SIZE); +} + +static void stun_tid_string_cpy(u08bits* s, const stun_tid* id) { + if(s && id) { + ns_bcopy((const void*)(id->tsx_id),s,STUN_TID_SIZE); + } +} + +static void stun_tid_from_string(const u08bits* s, stun_tid* id) { + if(s && id) { + ns_bcopy(s,(void*)(id->tsx_id),STUN_TID_SIZE); + } +} + +void stun_tid_from_message_str(const u08bits* buf, size_t len, stun_tid* id) { + UNUSED_ARG(len); + stun_tid_from_string(buf+8, id); +} + +void stun_tid_message_cpy(u08bits* buf, const stun_tid* id) { + if(buf && id) { + stun_tid_string_cpy(buf+8, id); + } +} + +void stun_tid_generate(stun_tid* id) { + if(id) { + u32bits *w=(u32bits*)(id->tsx_id); + turn_random32_size(w,3); + } +} + +void stun_tid_generate_in_message_str(u08bits* buf, stun_tid* id) { + stun_tid tmp; + if(!id) id=&tmp; + stun_tid_generate(id); + stun_tid_message_cpy(buf, id); +} + +/////////////////// TIME //////////////////////////////////////////////////////// + +u32bits stun_adjust_allocate_lifetime(u32bits lifetime) { + if(!lifetime) return STUN_DEFAULT_ALLOCATE_LIFETIME; + else if(lifetimeSTUN_MAX_ALLOCATE_LIFETIME) return STUN_MAX_ALLOCATE_LIFETIME; + return lifetime; +} + +////////////// ATTR ///////////////////////////////////////////////////////////// + +int stun_attr_get_type(stun_attr_ref attr) { + if(attr) + return (int)(nswap16(((const u16bits*)attr)[0])); + return -1; +} + +int stun_attr_get_len(stun_attr_ref attr) { + if(attr) + return (int)(nswap16(((const u16bits*)attr)[1])); + return -1; +} + +const u08bits* stun_attr_get_value(stun_attr_ref attr) { + if(attr) { + int len = (int)(nswap16(((const u16bits*)attr)[1])); + if(len<1) return NULL; + return ((const u08bits*)attr)+4; + } + return NULL; +} + +int stun_get_requested_address_family(stun_attr_ref attr) +{ + if (attr) { + int len = (int) (nswap16(((const u16bits*)attr)[1])); + if (len != 4) + return STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_INVALID; + int val = ((const u08bits*) attr)[4]; + switch (val){ + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: + return val; + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: + return val; + default: + return STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_INVALID; + }; + } + return STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT; +} + +u16bits stun_attr_get_channel_number(stun_attr_ref attr) { + if(attr) { + const u08bits* value = stun_attr_get_value(attr); + if(value && (stun_attr_get_len(attr) >= 2)) { + u16bits cn=nswap16(((const u16bits*)value)[0]); + if(STUN_VALID_CHANNEL(cn)) return cn; + } + } + return 0; +} + +u64bits stun_attr_get_reservation_token_value(stun_attr_ref attr) { + if(attr) { + const u08bits* value = stun_attr_get_value(attr); + if(value && (stun_attr_get_len(attr) == 8)) { + return nswap64(((const u64bits*)value)[0]); + } + } + return 0; +} + +int stun_attr_is_addr(stun_attr_ref attr) { + + if(attr) { + switch(stun_attr_get_type(attr)) { + case STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS: + case STUN_ATTRIBUTE_XOR_PEER_ADDRESS: + case STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS: + case STUN_ATTRIBUTE_MAPPED_ADDRESS: + case STUN_ATTRIBUTE_ALTERNATE_SERVER: + case OLD_STUN_ATTRIBUTE_RESPONSE_ADDRESS: + case OLD_STUN_ATTRIBUTE_SOURCE_ADDRESS: + case OLD_STUN_ATTRIBUTE_CHANGED_ADDRESS: + case OLD_STUN_ATTRIBUTE_REFLECTED_FROM: + case STUN_ATTRIBUTE_RESPONSE_ORIGIN: + case STUN_ATTRIBUTE_OTHER_ADDRESS: + return 1; + break; + default: + ; + }; + } + return 0; +} + +u08bits stun_attr_get_even_port(stun_attr_ref attr) { + if(attr) { + const u08bits* value=stun_attr_get_value(attr); + if(value) { + if((u08bits)(value[0]) > 0x7F) return 1; + } + } + return 0; +} + +stun_attr_ref stun_attr_get_first_by_type_str(const u08bits* buf, size_t len, u16bits attr_type) { + + stun_attr_ref attr=stun_attr_get_first_str(buf,len); + while(attr) { + if(stun_attr_get_type(attr) == attr_type) { + return attr; + } + attr=stun_attr_get_next_str(buf,len,attr); + } + + return NULL; +} + +stun_attr_ref stun_attr_get_first_str(const u08bits* buf, size_t len) { + + if(stun_get_command_message_len_str(buf,len)>STUN_HEADER_LENGTH) { + return (stun_attr_ref)(buf+STUN_HEADER_LENGTH); + } + + return NULL; +} + +stun_attr_ref stun_attr_get_next_str(const u08bits* buf, size_t len, stun_attr_ref prev) { + + if(!prev) return stun_attr_get_first_str(buf,len); + else { + const u08bits* end = buf + stun_get_command_message_len_str(buf,len); + int attrlen=stun_attr_get_len(prev); + u16bits rem4 = ((u16bits)attrlen) & 0x0003; + if(rem4) { + attrlen = attrlen+4-(int)rem4; + } + const u08bits* attr_end=(const u08bits*)prev+4+attrlen; + if(attr_end=MAX_STUN_MESSAGE_SIZE) return -1; + else { + u08bits* attr_start=buf+clen; + + u16bits *attr_start_16t=(u16bits*)attr_start; + + stun_set_command_message_len_str(buf,newlen); + *len = newlen; + + attr_start_16t[0]=nswap16(attr); + attr_start_16t[1]=nswap16(alen); + if(alen>0) ns_bcopy(avalue,attr_start+4,alen); + return 0; + } +} + +int stun_attr_add_addr_str(u08bits *buf, size_t *len, u16bits attr_type, const ioa_addr* ca) { + + stun_tid tid; + stun_tid_from_message_str(buf, *len, &tid); + + int xor_ed=0; + switch(attr_type) { + case STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS: + case STUN_ATTRIBUTE_XOR_PEER_ADDRESS: + case STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS: + xor_ed=1; + break; + default: + ; + }; + + ioa_addr public_addr; + map_addr_from_private_to_public(ca,&public_addr); + + u08bits cfield[64]; + int clen=0; + if(stun_addr_encode(&public_addr, cfield, &clen, xor_ed, STUN_MAGIC_COOKIE, tid.tsx_id)<0) { + return -1; + } + + if(stun_attr_add_str(buf,len,attr_type,(u08bits*)(&cfield),clen)<0) return -1; + + return 0; +} + +int stun_attr_get_addr_str(const u08bits *buf, size_t len, stun_attr_ref attr, ioa_addr* ca, const ioa_addr *default_addr) { + + stun_tid tid; + stun_tid_from_message_str(buf, len, &tid); + ioa_addr public_addr; + + ns_bzero(ca,sizeof(ioa_addr)); + + int attr_type = stun_attr_get_type(attr); + if(attr_type<0) return -1; + + int xor_ed=0; + switch(attr_type) { + case STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS: + case STUN_ATTRIBUTE_XOR_PEER_ADDRESS: + case STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS: + xor_ed=1; + break; + default: + ; + }; + + const u08bits *cfield=stun_attr_get_value(attr); + if(!cfield) return -1; + + if(stun_addr_decode(&public_addr, cfield, stun_attr_get_len(attr), xor_ed, STUN_MAGIC_COOKIE, tid.tsx_id)<0) { + return -1; + } + + map_addr_from_public_to_private(&public_addr, ca); + + if(default_addr && addr_any_no_port(ca) && !addr_any_no_port(default_addr)) { + int port = addr_get_port(ca); + addr_cpy(ca,default_addr); + addr_set_port(ca,port); + } + + return 0; +} + +int stun_attr_get_first_addr_str(const u08bits *buf, size_t len, u16bits attr_type, ioa_addr* ca, const ioa_addr *default_addr) { + + stun_attr_ref attr=stun_attr_get_first_str(buf,len); + + while(attr) { + if(stun_attr_is_addr(attr) && (attr_type == stun_attr_get_type(attr))) { + if(stun_attr_get_addr_str(buf,len,attr,ca,default_addr)==0) { + return 0; + } + } + attr=stun_attr_get_next_str(buf,len,attr); + } + + return -1; +} + +int stun_attr_add_channel_number_str(u08bits* buf, size_t *len, u16bits chnumber) { + + u16bits field[2]; + field[0]=nswap16(chnumber); + field[1]=0; + + return stun_attr_add_str(buf,len,STUN_ATTRIBUTE_CHANNEL_NUMBER,(u08bits*)(field),sizeof(field)); +} + +u16bits stun_attr_get_first_channel_number_str(const u08bits *buf, size_t len) { + + stun_attr_ref attr=stun_attr_get_first_str(buf,len); + while(attr) { + if(stun_attr_get_type(attr) == STUN_ATTRIBUTE_CHANNEL_NUMBER) { + u16bits ret = stun_attr_get_channel_number(attr); + if(STUN_VALID_CHANNEL(ret)) { + return ret; + } + } + attr=stun_attr_get_next_str(buf,len,attr); + } + + return 0; +} + +////////////// FINGERPRINT //////////////////////////// + +int stun_attr_add_fingerprint_str(u08bits *buf, size_t *len) +{ + u32bits crc32 = 0; + stun_attr_add_str(buf, len, STUN_ATTRIBUTE_FINGERPRINT, (u08bits*)&crc32, 4); + crc32 = ns_crc32(buf,*len-8); + *((u32bits*)(buf+*len-4)) = nswap32(crc32 ^ ((u32bits)0x5354554e)); + return 0; +} +////////////// CRC /////////////////////////////////////////////// + +#define CRC_MASK 0xFFFFFFFFUL + +#define UPDATE_CRC(crc, c) crc = crctable[(u08bits)crc ^ (u08bits)(c)] ^ (crc >> 8) + +static const u32bits crctable[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, +}; + +/* + +#define CRCPOLY 0xEDB88320UL +reversed 0x04C11DB7 +1110 1101 1001 1000 1000 0011 0010 0000 + +static void make_crctable(void) +{ + uint i, j; + u32bits r; + + for (i = 0; i < 256; ++i) { + r = i; + for (j = 8; j > 0; --j) { + if (r & 1) + r = (r >> 1) ^ CRCPOLY; + else + r >>= 1; + } + crctable[i] = r; + } +} +*/ + +static u32bits ns_crc32(const u08bits *buffer, u32bits len) +{ + u32bits crc = CRC_MASK; + while ( len-- ) UPDATE_CRC( crc, *buffer++ ); + return (~crc); +} + +//////////// SASLprep RFC 4013 ///////////////////////////////////////// + +/* We support only basic ASCII table */ + +int SASLprep(u08bits *s) +{ + if(s) { + u08bits *strin = s; + u08bits *strout = s; + for(;;) { + u08bits c = *strin; + if(!c) { + *strout=0; + break; + } + + switch(c) { + case 0xAD: + ++strin; + break; + case 0xA0: + case 0x20: + *strout=0x20; + ++strout; + ++strin; + break; + case 0x7F: + return -1; + default: + if(c<0x1F) + return -1; + if(c>=0x80 && c<=0x9F) + return -1; + *strout=c; + ++strout; + ++strin; + }; + } + } + + return 0; +} + +//////////////// Message Integrity //////////////////////////// + +size_t get_hmackey_size(SHATYPE shatype) +{ + if(shatype == SHATYPE_SHA256) + return 32; + return 16; +} + +void print_bin_func(const char *name, size_t len, const void *s, const char *func) +{ + printf("<%s>:<%s>:len=%d:[",func,name,(int)len); + size_t i; + for(i=0;i orig_len) + return -1; + + if (stun_set_command_message_len_str(buf, new_len) < 0) + return -1; + + if(ct == TURN_CREDENTIALS_SHORT_TERM) { + res = stun_calculate_hmac(buf, (size_t) new_len - 4 - shasize, pwd, strlen((char*)pwd), new_hmac, &shasize, shatype); + } else { + res = stun_calculate_hmac(buf, (size_t) new_len - 4 - shasize, key, get_hmackey_size(shatype), new_hmac, &shasize, shatype); + } + + stun_set_command_message_len_str(buf, orig_len); + if(res<0) + return -1; + + old_hmac = stun_attr_get_value(sar); + if(!old_hmac) + return -1; + + if(bcmp(old_hmac,new_hmac,shasize)) + return 0; + + return 1; +} + +/* + * Return -1 if failure, 0 if the integrity is not correct, 1 if OK + */ +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; + + if(ct == TURN_CREDENTIALS_SHORT_TERM) + strncpy((char*)pwd,(char*)upwd,sizeof(st_password_t)); + else if (stun_produce_integrity_key_str(uname, realm, upwd, key, shatype) < 0) + return -1; + + return stun_check_message_integrity_by_key_str(ct, buf, len, key, pwd, shatype, NULL); +} + +/* RFC 5780 */ + +int stun_attr_get_change_request_str(stun_attr_ref attr, int *change_ip, int *change_port) +{ + if(stun_attr_get_len(attr) == 4) { + const u08bits* value = stun_attr_get_value(attr); + if(value) { + *change_ip = (value[3] & (u08bits)0x04); + *change_port = (value[3] & (u08bits)0x02); + return 0; + } + } + return -1; +} + +int stun_attr_add_change_request_str(u08bits *buf, size_t *len, int change_ip, int change_port) +{ + u08bits avalue[4]={0,0,0,0}; + + if(change_ip) { + if(change_port) { + avalue[3] = 0x06; + } else { + avalue[3] = 0x04; + } + } else if(change_port) { + avalue[3]=0x02; + } + + return stun_attr_add_str(buf, len, STUN_ATTRIBUTE_CHANGE_REQUEST, avalue, 4); +} + +int stun_attr_get_response_port_str(stun_attr_ref attr) +{ + if(stun_attr_get_len(attr) >= 2) { + const u08bits* value = stun_attr_get_value(attr); + if(value) { + return nswap16(((const u16bits*)value)[0]); + } + } + return -1; +} + +int stun_attr_add_response_port_str(u08bits *buf, size_t *len, u16bits port) +{ + u08bits avalue[4]={0,0,0,0}; + u16bits *port_ptr = (u16bits*)avalue; + + *port_ptr = nswap16(port); + + return stun_attr_add_str(buf, len, STUN_ATTRIBUTE_RESPONSE_PORT, avalue, 4); +} + +int stun_attr_get_padding_len_str(stun_attr_ref attr) { + int len = stun_attr_get_len(attr); + if(len<0) + return -1; + return (u16bits)len; +} + +int stun_attr_add_padding_str(u08bits *buf, size_t *len, u16bits padding_len) +{ + u08bits avalue[0xFFFF]; + ns_bzero(avalue,padding_len); + + return stun_attr_add_str(buf, len, STUN_ATTRIBUTE_PADDING, avalue, padding_len); +} + +/////////////////////////////////////////////////////////////// diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h new file mode 100644 index 00000000..4a684f5d --- /dev/null +++ b/src/client/ns_turn_msg.h @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2011, 2012, 2013 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 __LIB_TURN_MSG__ +#define __LIB_TURN_MSG__ + +#include "ns_turn_ioaddr.h" +#include "ns_turn_msg_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////// + +/** + * Structure holding the STUN message Transaction ID + */ +#define STUN_TID_SIZE (12) +typedef struct { + /** + * Binary array + */ + uint8_t tsx_id[STUN_TID_SIZE]; +} stun_tid; + +typedef enum { + TURN_CREDENTIALS_NONE = 0, + TURN_CREDENTIALS_LONG_TERM, + TURN_CREDENTIALS_SHORT_TERM, + TURN_CREDENTIALS_UNDEFINED +} turn_credential_type; + +/** + * HMAC key + */ +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 const void* stun_attr_ref; + +////////////////////////////////////////////////////////////// + +int stun_tid_equals(const stun_tid *id1, const stun_tid *id2); +void stun_tid_cpy(stun_tid *id_dst, const stun_tid *id_src); +void stun_tid_generate(stun_tid* id); + +/////////////////////////////////////////////////////////////// + +u16bits stun_make_type(u16bits method); +u16bits stun_make_request(u16bits method); +u16bits stun_make_indication(u16bits method); +u16bits stun_make_success_response(u16bits method); +u16bits stun_make_error_response(u16bits method); + +/////////////////////////////////////////////////////////////// + +u32bits stun_adjust_allocate_lifetime(u32bits lifetime); + +///////////// STR //////////////////////////////////////////////// + +int stun_get_message_len_str(u08bits *buf, size_t len, int padding, size_t *app_len); + +void stun_init_buffer_str(u08bits *buf, size_t *len); +void stun_init_command_str(u16bits message_type, u08bits* buf, size_t *len); +void old_stun_init_command_str(u16bits message_type, u08bits* buf, size_t *len, u32bits cookie); +void stun_init_request_str(u16bits method, u08bits* buf, size_t *len); +void stun_init_indication_str(u16bits method, u08bits* buf, size_t *len); +void stun_init_success_response_str(u16bits method, u08bits* buf, size_t *len, stun_tid* id); +void old_stun_init_success_response_str(u16bits method, u08bits* buf, size_t *len, stun_tid* id, u32bits cookie); +void stun_init_error_response_str(u16bits method, u08bits* buf, size_t *len, u16bits error_code, const u08bits *reason, stun_tid* id); +void old_stun_init_error_response_str(u16bits method, u08bits* buf, size_t *len, u16bits error_code, const u08bits *reason, stun_tid* id, u32bits cookie); +int stun_init_channel_message_str(u16bits chnumber, u08bits* buf, size_t *len, int length, int do_padding); + +int stun_is_command_message_str(const u08bits* buf, size_t blen); +int old_stun_is_command_message_str(const u08bits* buf, size_t blen, u32bits *cookie); +int stun_is_command_message_full_check_str(const u08bits* buf, size_t blen, int must_check_fingerprint, int *fingerprint_present); +int stun_is_command_message_offset_str(const u08bits* buf, size_t blen, int offset); +int stun_is_request_str(const u08bits* buf, size_t len); +int stun_is_success_response_str(const u08bits* buf, size_t len); +int stun_is_error_response_str(const u08bits* buf, size_t len, int *err_code, u08bits *err_msg, size_t err_msg_size); +int stun_is_challenge_response_str(const u08bits* buf, size_t len, int *err_code, u08bits *err_msg, size_t err_msg_size, u08bits *realm, u08bits *nonce); +int stun_is_response_str(const u08bits* buf, size_t len); +int stun_is_indication_str(const u08bits* buf, size_t len); +u16bits stun_get_method_str(const u08bits *buf, size_t len); +u16bits stun_get_msg_type_str(const u08bits *buf, size_t len); +int stun_is_channel_message_str(const u08bits *buf, size_t *blen, u16bits* chnumber, int mandatory_padding); +int is_channel_msg_str(const u08bits* buf, size_t blen); + +void stun_set_binding_request_str(u08bits* buf, size_t *len); +int stun_set_binding_response_str(u08bits* buf, size_t *len, stun_tid* tid, + const ioa_addr *reflexive_addr, int error_code, + const u08bits *reason, + u32bits cookie, int old_stun); +int stun_is_binding_request_str(const u08bits* buf, size_t len, size_t offset); +int stun_is_binding_response_str(const u08bits* buf, size_t len); + +void stun_tid_from_message_str(const u08bits* buf, size_t len, stun_tid* id); +void stun_tid_message_cpy(u08bits *buf, const stun_tid* id); +void stun_tid_generate_in_message_str(u08bits* buf, stun_tid* id); + +int stun_get_command_message_len_str(const u08bits* buf, size_t len); + +int stun_attr_is_addr(stun_attr_ref attr); +int stun_attr_get_type(stun_attr_ref attr); +int stun_attr_get_len(stun_attr_ref attr); +const u08bits* stun_attr_get_value(stun_attr_ref attr); +u16bits stun_attr_get_channel_number(stun_attr_ref attr); +u08bits stun_attr_get_even_port(stun_attr_ref attr); +u64bits stun_attr_get_reservation_token_value(stun_attr_ref attr); +stun_attr_ref stun_attr_get_first_by_type_str(const u08bits* buf, size_t len, u16bits attr_type); +stun_attr_ref stun_attr_get_first_str(const u08bits* buf, size_t len); +stun_attr_ref stun_attr_get_next_str(const u08bits* buf, size_t len, stun_attr_ref prev); +int stun_attr_add_str(u08bits* buf, size_t *len, u16bits attr, const u08bits* avalue, int alen); +int stun_attr_add_addr_str(u08bits *buf, size_t *len, u16bits attr_type, const ioa_addr* ca); +int stun_attr_get_addr_str(const u08bits *buf, size_t len, stun_attr_ref attr, ioa_addr* ca, const ioa_addr *default_addr); +int stun_attr_get_first_addr_str(const u08bits *buf, size_t len, u16bits attr_type, ioa_addr* ca, const ioa_addr *default_addr); +int stun_attr_add_channel_number_str(u08bits* buf, size_t *len, u16bits chnumber); +u16bits stun_attr_get_first_channel_number_str(const u08bits *buf, size_t len); + +int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int address_family, u08bits transport, int mobile); +int stun_set_allocate_response_str(u08bits* buf, size_t *len, stun_tid* tid, + const ioa_addr *relayed_addr, + const ioa_addr *reflexive_addr, + u32bits lifetime, int error_code, const u08bits *reason, + u64bits reservation_token, char *mobile_id); + +u16bits stun_set_channel_bind_request_str(u08bits* buf, size_t *len, + const ioa_addr* peer_addr, u16bits channel_number); +void stun_set_channel_bind_response_str(u08bits* buf, size_t *len, stun_tid* tid, int error_code, const u08bits *reason); + +int stun_get_requested_address_family(stun_attr_ref attr); + +int stun_attr_add_fingerprint_str(u08bits *buf, size_t *len); + +int SASLprep(u08bits *s); + +#define print_bin(str, len, field) print_bin_func(str,len,field,__FUNCTION__) +void print_bin_func(const char *name, size_t len, const void *s, const char *func); + +/* + * 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_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_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); +size_t get_hmackey_size(SHATYPE shatype); + +/* + * To be implemented with openssl + */ + +#define TURN_RANDOM_SIZE (sizeof(long)) +long turn_random(void); +void turn_random32_size(u32bits *ar, size_t sz); + +int stun_produce_integrity_key_str(u08bits *uname, u08bits *realm, u08bits *upwd, hmackey_t key, SHATYPE shatype); +int stun_calculate_hmac(const u08bits *buf, size_t len, const u08bits *key, size_t sz, u08bits *hmac, unsigned int *hmac_len, SHATYPE shatype); + +/* RFC 5780 */ +int stun_attr_get_change_request_str(stun_attr_ref attr, int *change_ip, int *change_port); +int stun_attr_add_change_request_str(u08bits *buf, size_t *len, int change_ip, int change_port); +int stun_attr_get_response_port_str(stun_attr_ref attr); +int stun_attr_add_response_port_str(u08bits *buf, size_t *len, u16bits port); +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); + +/////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__LIB_TURN_MSG__ diff --git a/src/client/ns_turn_msg_addr.c b/src/client/ns_turn_msg_addr.c new file mode 100644 index 00000000..d9193ca5 --- /dev/null +++ b/src/client/ns_turn_msg_addr.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "ns_turn_msg_addr.h" + +////////////////////////////////////////////////////////////////////////////// + +int stun_addr_encode(const ioa_addr* ca, u08bits *cfield, int *clen, int xor_ed, u32bits mc, const u08bits *tsx_id) { + + if(!cfield || !clen || !ca || !tsx_id) return -1; + + if (ca->ss.sa_family == AF_INET || ca->ss.sa_family==0) { + + /* IPv4 address */ + + *clen=8; + + cfield[0]=0; + cfield[1]=1; //IPv4 family + + if (xor_ed) { + + /* Port */ + ((u16bits*)cfield)[1] = (ca->s4.sin_port) ^ nswap16(mc >> 16); + + /* Address */ + ((u32bits*)cfield)[1] = (ca->s4.sin_addr.s_addr) ^ nswap32(mc); + + } else { + + /* Port */ + ((u16bits*)cfield)[1]=ca->s4.sin_port; + + /* Address */ + ((u32bits*)cfield)[1]=ca->s4.sin_addr.s_addr; + } + + } else if (ca->ss.sa_family == AF_INET6) { + + /* IPv6 address */ + + *clen=20; + + cfield[0]=0; + cfield[1]=2; //IPv6 family + + if (xor_ed) { + + unsigned int i; + u08bits *dst = ((u08bits*)cfield)+4; + const u08bits *src = (const u08bits*)&(ca->s6.sin6_addr); + u32bits magic = nswap32(mc); + + /* Port */ + ((u16bits*)cfield)[1] = ca->s6.sin6_port ^ nswap16(mc >> 16); + + /* Address */ + + for (i=0; i<4; ++i) { + dst[i] = (u08bits)(src[i] ^ ((const u08bits*)&magic)[i]); + } + for (i=0; i<12; ++i) { + dst[i+4] = (u08bits)(src[i+4] ^ tsx_id[i]); + } + + } else { + + /* Port */ + ((u16bits*)cfield)[1]=ca->s6.sin6_port; + + /* Address */ + ns_bcopy(&ca->s6.sin6_addr, ((u08bits*)cfield)+4, 16); + } + + } else { + return -1; + } + + return 0; +} + +int stun_addr_decode(ioa_addr* ca, const u08bits *cfield, int len, int xor_ed, u32bits mc, const u08bits *tsx_id) { + + if(!cfield || !len || !ca || !tsx_id || (len<8)) return -1; + + if(cfield[0]!=0) { + return -1; + } + + int sa_family; + + if(cfield[1]==1) sa_family=AF_INET; + else if(cfield[1]==2) sa_family=AF_INET6; + else return -1; + + ca->ss.sa_family=sa_family; + + if (sa_family == AF_INET) { + + if(len!=8) return -1; + + /* IPv4 address */ + + /* Port */ + ca->s4.sin_port=((const u16bits*)cfield)[1]; + + /* Address */ + ca->s4.sin_addr.s_addr=((const u32bits*)cfield)[1]; + + if (xor_ed) { + ca->s4.sin_port ^= nswap16(mc >> 16); + ca->s4.sin_addr.s_addr ^= nswap32(mc); + } + + } else if (sa_family == AF_INET6) { + + /* IPv6 address */ + + if(len!=20) return -1; + + /* Port */ + ca->s6.sin6_port = ((const u16bits*)cfield)[1]; + + /* Address */ + ns_bcopy(((const u08bits*)cfield)+4, &ca->s6.sin6_addr, 16); + + if (xor_ed) { + + unsigned int i; + u08bits *dst; + const u08bits *src; + u32bits magic = nswap32(mc); + + /* Port */ + ca->s6.sin6_port ^= nswap16(mc >> 16); + + /* Address */ + src = ((const u08bits*)cfield)+4; + dst = (u08bits*)&ca->s6.sin6_addr; + for (i=0; i<4; ++i) { + dst[i] = (u08bits)(src[i] ^ ((const u08bits*)&magic)[i]); + } + for (i=0; i<12; ++i) { + dst[i+4] = (u08bits)(src[i+4] ^ tsx_id[i]); + } + } + + } else { + return -1; + } + + return 0; +} + +////////////////////////////////////////////////////////////////////////////// + diff --git a/src/client/ns_turn_msg_addr.h b/src/client/ns_turn_msg_addr.h new file mode 100644 index 00000000..6d03c3c7 --- /dev/null +++ b/src/client/ns_turn_msg_addr.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2011, 2012, 2013 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 __LIB_TURN_MSG_ADDR__ +#define __LIB_TURN_MSG_ADDR__ + +#include "ns_turn_ioaddr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////// + +int stun_addr_encode(const ioa_addr* ca, u08bits *cfield, int *clen, int xor_ed, u32bits mc, const u08bits *tsx_id); +int stun_addr_decode(ioa_addr* ca, const u08bits *cfield, int len, int xor_ed, u32bits mc, const u08bits *tsx_id); + +/////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__LIB_TURN_MSG_ADDR__ diff --git a/src/client/ns_turn_msg_defs.h b/src/client/ns_turn_msg_defs.h new file mode 100644 index 00000000..431e1e88 --- /dev/null +++ b/src/client/ns_turn_msg_defs.h @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2011, 2012, 2013 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 __LIB_TURN_MSG_DEFS__ +#define __LIB_TURN_MSG_DEFS__ + +/////////////////////////////////////////// +// http://www.iana.org/assignments/stun-parameters/stun-parameters.xhtml +/////////////////////////////////////////// + +#define STUN_HEADER_LENGTH (20) +#define STUN_CHANNEL_HEADER_LENGTH (4) + +#define STUN_MAX_USERNAME_SIZE (513) +#define STUN_MAX_REALM_SIZE (127) +#define STUN_MAX_ORIGIN_SIZE (127) +#define STUN_MAX_NONCE_SIZE (127) +#define STUN_MAX_PWD_SIZE (127) + +#define STUN_MAGIC_COOKIE (0x2112A442) + +#define IS_STUN_REQUEST(msg_type) (((msg_type) & 0x0110) == 0x0000) +#define IS_STUN_INDICATION(msg_type) (((msg_type) & 0x0110) == 0x0010) +#define IS_STUN_SUCCESS_RESP(msg_type) (((msg_type) & 0x0110) == 0x0100) +#define IS_STUN_ERR_RESP(msg_type) (((msg_type) & 0x0110) == 0x0110) + +#define GET_STUN_REQUEST(msg_type) (msg_type & 0xFEEF) +#define GET_STUN_INDICATION(msg_type) ((msg_type & 0xFEEF)|0x0010) +#define GET_STUN_SUCCESS_RESP(msg_type) ((msg_type & 0xFEEF)|0x0100) +#define GET_STUN_ERR_RESP(msg_type) (msg_type | 0x0110) + +/* Lifetimes: */ +#define STUN_DEFAULT_ALLOCATE_LIFETIME (600) +#define STUN_MIN_ALLOCATE_LIFETIME STUN_DEFAULT_ALLOCATE_LIFETIME +#define STUN_MAX_ALLOCATE_LIFETIME (3600) +#define STUN_CHANNEL_LIFETIME (600) +#define STUN_PERMISSION_LIFETIME (300) +#define STUN_NONCE_EXPIRATION_TIME (600) +/**/ + +#define STUN_METHOD_BINDING (0x0001) +#define STUN_METHOD_ALLOCATE (0x0003) +#define STUN_METHOD_REFRESH (0x0004) +#define STUN_METHOD_SEND (0x0006) +#define STUN_METHOD_DATA (0x0007) +#define STUN_METHOD_CREATE_PERMISSION (0x0008) +#define STUN_METHOD_CHANNEL_BIND (0x0009) + +/* RFC 6062 ==>>*/ +#define STUN_METHOD_CONNECT (0x000a) +#define STUN_METHOD_CONNECTION_BIND (0x000b) +#define STUN_METHOD_CONNECTION_ATTEMPT (0x000c) +/* <<== RFC 6062 */ + +#define STUN_ATTRIBUTE_MAPPED_ADDRESS (0x0001) +#define OLD_STUN_ATTRIBUTE_RESPONSE_ADDRESS (0x0002) +#define STUN_ATTRIBUTE_CHANGE_REQUEST (0x0003) +#define OLD_STUN_ATTRIBUTE_SOURCE_ADDRESS (0x0004) +#define OLD_STUN_ATTRIBUTE_CHANGED_ADDRESS (0x0005) +#define STUN_ATTRIBUTE_USERNAME (0x0006) +#define OLD_STUN_ATTRIBUTE_PASSWORD (0x0007) +#define STUN_ATTRIBUTE_MESSAGE_INTEGRITY (0x0008) +#define STUN_ATTRIBUTE_ERROR_CODE (0x0009) +#define STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES (0x000A) +#define OLD_STUN_ATTRIBUTE_REFLECTED_FROM (0x000B) +#define STUN_ATTRIBUTE_REALM (0x0014) +#define STUN_ATTRIBUTE_NONCE (0x0015) +#define STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY (0x0017) +#define STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS (0x0020) +#define OLD_STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS (0x8020) + +#define STUN_ATTRIBUTE_SOFTWARE (0x8022) +#define OLD_STUN_ATTRIBUTE_SERVER STUN_ATTRIBUTE_SOFTWARE +#define STUN_ATTRIBUTE_ALTERNATE_SERVER (0x8023) +#define STUN_ATTRIBUTE_FINGERPRINT (0x8028) + +#define STUN_ATTRIBUTE_CHANNEL_NUMBER (0x000C) +#define STUN_ATTRIBUTE_LIFETIME (0x000D) +#define STUN_ATTRIBUTE_BANDWIDTH (0x0010) +#define STUN_ATTRIBUTE_XOR_PEER_ADDRESS (0x0012) +#define STUN_ATTRIBUTE_DATA (0x0013) +#define STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS (0x0016) +#define STUN_ATTRIBUTE_EVEN_PORT (0x0018) +#define STUN_ATTRIBUTE_REQUESTED_TRANSPORT (0x0019) +#define STUN_ATTRIBUTE_DONT_FRAGMENT (0x001A) +#define STUN_ATTRIBUTE_TIMER_VAL (0x0021) +#define STUN_ATTRIBUTE_RESERVATION_TOKEN (0x0022) + +/* ICE */ +#define STUN_ATTRIBUTE_PRIORITY (0x0024) +#define STUN_ATTRIBUTE_ICE_CONTROLLED (0x8029) + +/* RFC 5780 */ +#define STUN_ATTRIBUTE_PADDING (0x0026) +#define STUN_ATTRIBUTE_RESPONSE_PORT (0x0027) +#define STUN_ATTRIBUTE_RESPONSE_ORIGIN (0x802b) +#define STUN_ATTRIBUTE_OTHER_ADDRESS (0x802c) + +/* RFC 6062 ==>> */ +#define STUN_ATTRIBUTE_CONNECTION_ID (0x002a) +/* <<== RFC 6062 */ + +#define STUN_VALID_CHANNEL(chn) ((chn)>=0x4000 && (chn)<=0x7FFF) + +///////// values ////////////////// + +/* RFC 6156 ==>> */ +#define STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4 (0x01) +#define STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6 (0x02) +#define STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT (0x00) +#define STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_INVALID (-1) +/* <<== RFC 6156 */ + +/* RFC 6062 ==>> */ +#define STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE (6) +#define STUN_ATTRIBUTE_TRANSPORT_UDP_VALUE (17) +#define STUN_ATTRIBUTE_TRANSPORT_TLS_VALUE (56) +#define STUN_ATTRIBUTE_TRANSPORT_DTLS_VALUE (250) +/* <<== RFC 6062 */ + +/* Mobility ==>> */ +#define STUN_ATTRIBUTE_MOBILITY_TICKET (0x802E) +#define STUN_ATTRIBUTE_MOBILITY_EVENT (0x802) +#define STUN_ATTRIBUTE_MOBILITY_SUPPORT (0x8000) +/* <<== Mobility */ + +/* Origin ==>> */ +#define STUN_ATTRIBUTE_ORIGIN (0x802F) +/* <<== Origin */ + +//////////////////////////////////////////////// + +#endif //__LIB_TURN_MSG_DEFS__ diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h new file mode 100644 index 00000000..bbf364d2 --- /dev/null +++ b/src/ns_turn_defs.h @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2011, 2012, 2013 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 __IOADEFS__ +#define __IOADEFS__ + +#define TURN_SERVER_VERSION "3.3.0.0" +#define TURN_SERVER_VERSION_NAME "Threetrees" +#define TURN_SOFTWARE "Coturn-"TURN_SERVER_VERSION" '"TURN_SERVER_VERSION_NAME"'" + +#if (defined(__unix__) || defined(unix)) && !defined(USG) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////// + +/* NS types: */ + +#define s08bits char +#define s16bits int16_t +#define s32bits int32_t +#define s64bits int64_t + +#define u08bits unsigned char +#define u16bits uint16_t +#define u32bits uint32_t +#define u64bits uint64_t + +#define ns_bcopy(src,dst,sz) bcopy((src),(dst),(sz)) +#define ns_bzero(ptr,sz) bzero((ptr),(sz)) + +#define nswap16(s) ntohs(s) +#define nswap32(ul) ntohl(ul) +#define nswap64(ull) ioa_ntoh64(ull) + +static inline u64bits _ioa_ntoh64(u64bits v) +{ +#if BYTE_ORDER == LITTLE_ENDIAN + u08bits *src = (u08bits*) &v; + u08bits* dst = src + 7; + while (src < dst) { + u08bits vdst = *dst; + *(dst--) = *src; + *(src++) = vdst; + } +#elif BYTE_ORDER == BIG_ENDIAN + /* OK */ +#else +#error WRONG BYTE_ORDER SETTING +#endif + return v; +} + +/* TTL */ +#define TTL_IGNORE ((int)(-1)) +#define TTL_DEFAULT (64) + +/* TOS */ +#define TOS_IGNORE ((int)(-1)) +#define TOS_DEFAULT (0) + +#define ioa_ntoh64 _ioa_ntoh64 +#define ioa_hton64 _ioa_ntoh64 + +#define turn_malloc(sz) malloc(sz) +#define turn_free(ptr,sz) free(ptr) +#define turn_realloc(ptr, old_sz, new_sz) realloc((ptr),(new_sz)) +#define turn_calloc(number, sz) calloc((number),(sz)) + +#define turn_time() ((turn_time_t)time(NULL)) + +typedef int vint; +typedef vint* vintp; + +typedef u32bits turn_time_t; + +#define turn_time_before(t1,t2) ((((s32bits)(t1))-((s32bits)(t2))) < 0) + +#if !defined(UNUSED_ARG) +#define UNUSED_ARG(A) do { A=A; } while(0) +#endif + +#define MAX_STUN_MESSAGE_SIZE (65507) +#define STUN_BUFFER_SIZE (MAX_STUN_MESSAGE_SIZE) +#define UDP_STUN_BUFFER_SIZE (1024<<4) + +#define NONCE_LENGTH_32BITS (4) + +#define DEFAULT_STUN_PORT (3478) +#define DEFAULT_STUN_TLS_PORT (5349) + +#if BYTE_ORDER == LITTLE_ENDIAN +#define DEFAULT_STUN_PORT_NBO (0x960D) +#elif BYTE_ORDER == BIG_ENDIAN +#define DEFAULT_STUN_PORT_NBO (0x0D96) +#else +#error WRONG BYTE_ORDER SETTING +#endif + +#define STRCPY(dst,src) \ + do { if((const char*)(dst) != (const char*)(src)) { \ + if(sizeof(dst)==sizeof(char*))\ + strcpy(((char*)(dst)),(const char*)(src));\ + else {\ + size_t szdst = sizeof((dst));\ + strncpy((char*)(dst),(const char*)(src),szdst);\ + ((char*)(dst))[szdst-1] = 0;\ + }\ + } } while(0) + +////////////////// Security //////////////////////////// + +#define SHA1SIZEBYTES (20) +#define SHA256SIZEBYTES (32) + +#define MAXSHASIZE (128) + +enum _SHATYPE { + SHATYPE_SHA1 = 0, + SHATYPE_SHA256 +}; + +typedef enum _SHATYPE SHATYPE; + +#define shatype_name(sht) ((sht == SHATYPE_SHA1) ? "SHA1" : ((sht == SHATYPE_SHA256) ? "SHA256" : "SHA UNKNOWN")) + +#define SHA_TOO_WEAK (426) + +//////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif +/* __IODEFS__ */ diff --git a/src/server/ns_turn_allocation.c b/src/server/ns_turn_allocation.c new file mode 100644 index 00000000..e337aab1 --- /dev/null +++ b/src/server/ns_turn_allocation.c @@ -0,0 +1,694 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "ns_turn_allocation.h" + +/////////////// Permission forward declarations ///////////////// + +static void init_turn_permission_hashtable(turn_permission_hashtable *map); +static void free_turn_permission_hashtable(turn_permission_hashtable *map); +static turn_permission_info* get_from_turn_permission_hashtable(turn_permission_hashtable *map, const ioa_addr *addr); + +/////////////// ALLOCATION ////////////////////////////////////// + +void init_allocation(void *owner, allocation* a, ur_map *tcp_connections) { + if(a) { + ns_bzero(a,sizeof(allocation)); + a->owner = owner; + a->tcp_connections = tcp_connections; + init_turn_permission_hashtable(&(a->addr_to_perm)); + } +} + +void clear_allocation(allocation *a) +{ + if (a) { + + if(a->is_valid) + turn_report_allocation_delete(a); + + if(a->tcs.elems) { + size_t i; + size_t sz = a->tcs.sz; + for(i=0;itcs.elems[i]; + if(tc) { + delete_tcp_connection(tc); + a->tcs.elems[i] = NULL; + break; + } + } + turn_free(a->tcs.elems,sz*sizeof(tcp_connection*)); + a->tcs.elems = NULL; + } + a->tcs.sz = 0; + + clear_ioa_socket_session_if(a->relay_session.s, a->owner); + clear_ts_ur_session_data(&(a->relay_session)); + + IOA_EVENT_DEL(a->lifetime_ev); + + /* The order is important here: */ + free_turn_permission_hashtable(&(a->addr_to_perm)); + ch_map_clean(&(a->chns)); + + a->is_valid=0; + } +} + +ts_ur_session *get_relay_session(allocation *a) +{ + return &(a->relay_session); +} + +ioa_socket_handle get_relay_socket(allocation *a) +{ + return a->relay_session.s; +} + +void set_allocation_lifetime_ev(allocation *a, turn_time_t exp_time, ioa_timer_handle ev) +{ + if (a) { + IOA_EVENT_DEL(a->lifetime_ev); + a->expiration_time = exp_time; + a->lifetime_ev = ev; + } +} + +int is_allocation_valid(const allocation* a) { + if(a) return a->is_valid; + else return 0; +} + +void set_allocation_valid(allocation* a, int value) { + if(a) a->is_valid=value; +} + +turn_permission_info* allocation_get_permission(allocation* a, const ioa_addr *addr) { + if(a) { + return get_from_turn_permission_hashtable(&(a->addr_to_perm), addr); + } + return NULL; +} + +///////////////////////////// TURN_PERMISSION ///////////////////////////////// + +static int delete_channel_info_from_allocation_map(ur_map_key_type key, ur_map_value_type value); + +void turn_permission_clean(turn_permission_info* tinfo) +{ + if (tinfo && tinfo->allocated) { + + if(!(tinfo->lifetime_ev)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: strange (1) permission to be cleaned\n",__FUNCTION__); + } + + IOA_EVENT_DEL(tinfo->lifetime_ev); + lm_map_foreach(&(tinfo->chns), (foreachcb_type) delete_channel_info_from_allocation_map); + lm_map_clean(&(tinfo->chns)); + ns_bzero(tinfo,sizeof(turn_permission_info)); + } +} + +static void init_turn_permission_hashtable(turn_permission_hashtable *map) +{ + if (map) + ns_bzero(map,sizeof(turn_permission_hashtable)); +} + +static void free_turn_permission_hashtable(turn_permission_hashtable *map) +{ + if(map) { + + size_t i; + for(i=0;itable[i]); + + { + size_t j; + for(j=0;jmain_slots[j]); + if(slot->info.allocated) { + turn_permission_clean(&(slot->info)); + } + } + } + + if(parray->extra_slots) { + size_t j; + for(j=0;jextra_sz;++j) { + turn_permission_slot *slot = parray->extra_slots[j]; + if(slot) { + if(slot->info.allocated) { + turn_permission_clean(&(slot->info)); + } + turn_free(slot,sizeof(turn_permission_slot)); + } + } + turn_free(parray->extra_slots, parray->extra_sz * sizeof(turn_permission_slot*)); + parray->extra_slots = NULL; + } + parray->extra_sz = 0; + } + } +} + +static turn_permission_info* get_from_turn_permission_hashtable(turn_permission_hashtable *map, const ioa_addr *addr) +{ + if (!addr || !map) + return NULL; + + u32bits index = addr_hash_no_port(addr) & (TURN_PERMISSION_HASHTABLE_SIZE-1); + turn_permission_array *parray = &(map->table[index]); + + { + size_t i; + for (i = 0; i < TURN_PERMISSION_ARRAY_SIZE; ++i) { + turn_permission_slot *slot = &(parray->main_slots[i]); + if (slot->info.allocated && addr_eq_no_port(&(slot->info.addr), addr)) { + return &(slot->info); + } + } + } + + if(parray->extra_slots) { + + size_t i; + size_t sz = parray->extra_sz; + for (i = 0; i < sz; ++i) { + turn_permission_slot *slot = parray->extra_slots[i]; + if (slot->info.allocated && addr_eq_no_port(&(slot->info.addr), addr)) { + return &(slot->info); + } + } + } + + return NULL; +} + +static void ch_info_clean(ch_info* c) { + if(c) { + IOA_EVENT_DEL(c->lifetime_ev); + ns_bzero(c,sizeof(ch_info)); + } +} + +static int delete_channel_info_from_allocation_map(ur_map_key_type key, ur_map_value_type value) +{ + UNUSED_ARG(key); + + if(value) { + ch_info* chn = (ch_info*)value; + + if(chn->chnum <1) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: strange (0) channel to be cleaned: chnum<1\n",__FUNCTION__); + } + + ch_info_clean(chn); + } + + return 0; +} + +void turn_channel_delete(ch_info* chn) +{ + if(chn) { + int port = addr_get_port(&(chn->peer_addr)); + if(port<1) { + char s[129]; + addr_to_string(&(chn->peer_addr),(u08bits*)s); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: strange (1) channel to be cleaned: port is empty: %s\n",__FUNCTION__,s); + } + { + turn_permission_info* tinfo = (turn_permission_info*)chn->owner; + if(tinfo) { + lm_map_del(&(tinfo->chns), (ur_map_key_type)port,NULL); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: strange (2) channel to be cleaned: permission is empty\n",__FUNCTION__); + } + } + delete_channel_info_from_allocation_map((ur_map_key_type)port,(ur_map_value_type)chn); + } +} + +ch_info* allocation_get_new_ch_info(allocation* a, u16bits chnum, ioa_addr* peer_addr) +{ + + turn_permission_info* tinfo = get_from_turn_permission_hashtable(&(a->addr_to_perm), peer_addr); + + if (!tinfo) + tinfo = allocation_add_permission(a, peer_addr); + + ch_info* chn = ch_map_get(&(a->chns), chnum, 1); + + chn->allocated = 1; + chn->chnum = chnum; + chn->port = addr_get_port(peer_addr); + addr_cpy(&(chn->peer_addr), peer_addr); + chn->owner = tinfo; + + lm_map_put(&(tinfo->chns), (ur_map_key_type) addr_get_port(peer_addr), (ur_map_value_type) chn); + + return chn; +} + +ch_info* allocation_get_ch_info(allocation* a, u16bits chnum) { + return ch_map_get(&(a->chns), chnum, 0); +} + +ch_info* allocation_get_ch_info_by_peer_addr(allocation* a, ioa_addr* peer_addr) { + turn_permission_info* tinfo = get_from_turn_permission_hashtable(&(a->addr_to_perm), peer_addr); + if(tinfo) { + return get_turn_channel(tinfo,peer_addr); + } + return NULL; +} + +u16bits get_turn_channel_number(turn_permission_info* tinfo, ioa_addr *addr) +{ + if (tinfo) { + ur_map_value_type t = 0; + if (lm_map_get(&(tinfo->chns), (ur_map_key_type)addr_get_port(addr), &t) && t) { + ch_info* chn = (ch_info*) t; + if (STUN_VALID_CHANNEL(chn->chnum)) { + return chn->chnum; + } + } + } + + return 0; +} + +ch_info *get_turn_channel(turn_permission_info* tinfo, ioa_addr *addr) +{ + if (tinfo) { + ur_map_value_type t = 0; + if (lm_map_get(&(tinfo->chns), (ur_map_key_type)addr_get_port(addr), &t) && t) { + ch_info* chn = (ch_info*) t; + if (STUN_VALID_CHANNEL(chn->chnum)) { + return chn; + } + } + } + + return NULL; +} + +turn_permission_hashtable *allocation_get_turn_permission_hashtable(allocation *a) +{ + return &(a->addr_to_perm); +} + +turn_permission_info* allocation_add_permission(allocation *a, const ioa_addr* addr) +{ + if (a && addr) { + + turn_permission_hashtable *map = &(a->addr_to_perm); + u32bits hash = addr_hash_no_port(addr); + size_t fds = (size_t) (hash & (TURN_PERMISSION_HASHTABLE_SIZE-1)); + + turn_permission_array *parray = &(map->table[fds]); + + turn_permission_slot *slot = NULL; + + { + size_t i; + for(i=0;imain_slots[i]); + if(!(slot->info.allocated)) { + break; + } else { + slot=NULL; + } + } + } + + if(!slot) { + + size_t old_sz = parray->extra_sz; + + turn_permission_slot **slots = parray->extra_slots; + + if(slots) { + size_t i; + for(i=0;iinfo.allocated)) { + break; + } else { + slot=NULL; + } + } + } + + if(!slot) { + size_t old_sz_mem = old_sz * sizeof(turn_permission_slot*); + parray->extra_slots = (turn_permission_slot **) turn_realloc(parray->extra_slots, + old_sz_mem, old_sz_mem + sizeof(turn_permission_slot*)); + slots = parray->extra_slots; + parray->extra_sz = old_sz + 1; + slots[old_sz] = (turn_permission_slot *)turn_malloc(sizeof(turn_permission_slot)); + slot = slots[old_sz]; + } + } + + ns_bzero(slot,sizeof(turn_permission_slot)); + slot->info.allocated = 1; + turn_permission_info *elem = &(slot->info); + addr_cpy(&(elem->addr), addr); + elem->owner = a; + + return elem; + } else { + return NULL; + } +} + +ch_info *ch_map_get(ch_map* map, u16bits chnum, int new_chn) +{ + ch_info *ret = NULL; + if(map) { + size_t index = (size_t)(chnum & (CH_MAP_HASH_SIZE-1)); + ch_map_array *a = &(map->table[index]); + + size_t i; + for(i=0;imain_chns[i]); + if(chi->allocated) { + if(!new_chn && (chi->chnum == chnum)) { + return chi; + } + } else if(new_chn) { + return chi; + } + } + + size_t old_sz = a->extra_sz; + if(old_sz && a->extra_chns) { + for(i=0;iextra_chns[i]; + if(chi) { + if(chi->allocated) { + if(!new_chn && (chi->chnum == chnum)) { + return chi; + } + } else if(new_chn) { + return chi; + } + } + } + } + + if(new_chn) { + size_t old_sz_mem = old_sz * sizeof(ch_info*); + a->extra_chns = (ch_info**)turn_realloc(a->extra_chns,old_sz_mem,old_sz_mem + sizeof(ch_info*)); + a->extra_chns[old_sz] = (ch_info*)turn_malloc(sizeof(ch_info)); + ns_bzero(a->extra_chns[old_sz],sizeof(ch_info)); + a->extra_sz += 1; + + return a->extra_chns[old_sz]; + } + } + + return ret; +} + +void ch_map_clean(ch_map* map) +{ + if(map) { + size_t index; + for(index = 0; index < CH_MAP_HASH_SIZE; ++index) { + + ch_map_array *a = &(map->table[index]); + + size_t i; + for(i=0;imain_chns[i]); + if(chi->allocated) { + ch_info_clean(chi); + } + } + + if(a->extra_chns) { + size_t sz = a->extra_sz; + for(i=0;iextra_chns[i]; + if(chi) { + if(chi->allocated) { + ch_info_clean(chi); + } + turn_free(chi,sizeof(ch_info)); + a->extra_chns[i] = NULL; + } + } + turn_free(a->extra_chns, sizeof(ch_info*)*sz); + a->extra_chns = NULL; + } + a->extra_sz = 0; + } + } +} + +////////////////// TCP connections /////////////////////////////// + +static void set_new_tc_id(u08bits server_id, tcp_connection *tc) { + allocation *a = (allocation*)(tc->owner); + ur_map *map = a->tcp_connections; + u32bits newid; + u32bits sid = server_id; + sid = sid<<24; + do { + newid = 0; + while (!newid) { + newid = (u32bits)turn_random(); + if(!newid) { + continue; + } + newid = newid & 0x00FFFFFF; + if(!newid) { + continue; + } + newid = newid | sid; + } + } while(ur_map_get(map, (ur_map_key_type)newid, NULL)); + tc->id = newid; + ur_map_put(map, (ur_map_key_type)newid, (ur_map_value_type)tc); +} + +tcp_connection *create_tcp_connection(u08bits server_id, allocation *a, stun_tid *tid, ioa_addr *peer_addr, int *err_code) +{ + tcp_connection_list *tcl = &(a->tcs); + if(tcl->elems) { + size_t i; + for(i=0;isz;++i) { + tcp_connection *otc = tcl->elems[i]; + if(otc) { + if(addr_eq(&(otc->peer_addr),peer_addr)) { + *err_code = 446; + return NULL; + } + } + } + } + tcp_connection *tc = (tcp_connection*)turn_malloc(sizeof(tcp_connection)); + ns_bzero(tc,sizeof(tcp_connection)); + addr_cpy(&(tc->peer_addr),peer_addr); + if(tid) + ns_bcopy(tid,&(tc->tid),sizeof(stun_tid)); + tc->owner = a; + + int found = 0; + if(a->tcs.elems) { + size_t i; + for(i=0;isz;++i) { + tcp_connection *otc = tcl->elems[i]; + if(!otc) { + tcl->elems[i] = tc; + found = 1; + break; + } + } + } + + if(!found) { + size_t old_sz_mem = a->tcs.sz * sizeof(tcp_connection*); + a->tcs.elems = (tcp_connection**)turn_realloc(a->tcs.elems,old_sz_mem,old_sz_mem+sizeof(tcp_connection*)); + a->tcs.elems[a->tcs.sz] = tc; + a->tcs.sz += 1; + tcl = &(a->tcs); + } + + set_new_tc_id(server_id, tc); + return tc; +} + +void delete_tcp_connection(tcp_connection *tc) +{ + if(tc) { + if(tc->done) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s: check on already closed tcp data connection: 0x%lx\n",__FUNCTION__,(unsigned long)tc); + return; + } + tc->done = 1; + + clear_unsent_buffer(&(tc->ub_to_client)); + + IOA_EVENT_DEL(tc->peer_conn_timeout); + IOA_EVENT_DEL(tc->conn_bind_timeout); + allocation *a = (allocation*)(tc->owner); + if(a) { + ur_map *map = a->tcp_connections; + if(map) { + ur_map_del(map, (ur_map_key_type)(tc->id),NULL); + } + tcp_connection_list *tcl = &(a->tcs); + if(tcl->elems) { + size_t i; + for(i=0;isz;++i) { + if(tcl->elems[i] == tc) { + tcl->elems[i] = NULL; + break; + } + } + } + } + IOA_CLOSE_SOCKET(tc->client_s); + IOA_CLOSE_SOCKET(tc->peer_s); + turn_free(tc,sizeof(tcp_connection)); + } +} + +tcp_connection *get_and_clean_tcp_connection_by_id(ur_map *map, tcp_connection_id id) +{ + if(map) { + ur_map_value_type t = 0; + if (ur_map_get(map, (ur_map_key_type)id, &t) && t) { + ur_map_del(map, (ur_map_key_type)id,NULL); + return (tcp_connection*)t; + } + } + return NULL; +} + +tcp_connection *get_tcp_connection_by_peer(allocation *a, ioa_addr *peer_addr) +{ + if(a && peer_addr) { + tcp_connection_list *tcl = &(a->tcs); + if(tcl->elems) { + size_t i; + size_t sz = tcl->sz; + for(i=0;ielems[i]; + if(tc) { + if(addr_eq(&(tc->peer_addr),peer_addr)) { + return tc; + } + } + } + } + } + return NULL; +} + +int can_accept_tcp_connection_from_peer(allocation *a, ioa_addr *peer_addr, int server_relay) +{ + if(server_relay) + return 1; + + if(a && peer_addr) { + return (get_from_turn_permission_hashtable(&(a->addr_to_perm), peer_addr) != NULL); + } + + return 0; +} + +//////////////// Unsent buffers ////////////////////// + +void clear_unsent_buffer(unsent_buffer *ub) +{ + if(ub) { + if(ub->bufs) { + size_t sz; + for(sz = 0; szsz; sz++) { + ioa_network_buffer_handle nbh = ub->bufs[sz]; + if(nbh) { + ioa_network_buffer_delete(NULL, nbh); + ub->bufs[sz] = NULL; + } + } + turn_free(ub->bufs,sizeof(ioa_network_buffer_handle) * ub->sz); + ub->bufs = NULL; + } + ub->sz = 0; + } +} + +void add_unsent_buffer(unsent_buffer *ub, ioa_network_buffer_handle nbh) +{ + if(!ub || (ub->sz >= MAX_UNSENT_BUFFER_SIZE)) { + ioa_network_buffer_delete(NULL, nbh); + } else { + ub->bufs = (ioa_network_buffer_handle*)turn_realloc(ub->bufs, sizeof(ioa_network_buffer_handle) * ub->sz, sizeof(ioa_network_buffer_handle) * (ub->sz+1)); + ub->bufs[ub->sz] = nbh; + ub->sz +=1; + } +} + +ioa_network_buffer_handle top_unsent_buffer(unsent_buffer *ub) +{ + ioa_network_buffer_handle ret = NULL; + if(ub && ub->bufs && ub->sz) { + size_t sz; + for(sz=0; szsz; ++sz) { + if(ub->bufs[sz]) { + ret = ub->bufs[sz]; + break; + } + } + } + return ret; +} + +void pop_unsent_buffer(unsent_buffer *ub) +{ + if(ub && ub->bufs && ub->sz) { + size_t sz; + for(sz=0; szsz; ++sz) { + if(ub->bufs[sz]) { + ub->bufs[sz] = NULL; + break; + } + } + } +} + +////////////////////////////////////////////////////////////////// + diff --git a/src/server/ns_turn_allocation.h b/src/server/ns_turn_allocation.h new file mode 100644 index 00000000..200db1f1 --- /dev/null +++ b/src/server/ns_turn_allocation.h @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2011, 2012, 2013 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_TURN_A_LIB__ +#define __TURN_TURN_A_LIB__ + +#include "ns_turn_utils.h" +#include "ns_turn_msg.h" +#include "ns_turn_ioalib.h" +#include "ns_turn_maps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +///////// Defines ////////// + +#define TCP_PEER_CONN_TIMEOUT (30) +#define TCP_CONN_BIND_TIMEOUT (30) + +///////// types //////////// + +enum _UR_STATE { + UR_STATE_UNKNOWN=0, + UR_STATE_READY, + UR_STATE_DONE +}; + +typedef enum _UR_STATE UR_STATE; + +////////////// Network session //////////////// + +typedef struct +{ + UR_STATE state; + ioa_socket_handle s; + int known_mtu; +} ts_ur_session; + +static inline void clear_ts_ur_session_data(ts_ur_session* cdi) +{ + if (cdi) + IOA_CLOSE_SOCKET(cdi->s); +} + +////////// RFC 6062 TCP connection //////// + +#define MAX_UNSENT_BUFFER_SIZE (0x10) + +enum _TC_STATE { + TC_STATE_UNKNOWN=0, + TC_STATE_CLIENT_TO_PEER_CONNECTING, + TC_STATE_PEER_CONNECTING, + TC_STATE_PEER_CONNECTED, + TC_STATE_READY, + TC_STATE_FAILED +}; + +typedef enum _TC_STATE TC_STATE; + +typedef u32bits tcp_connection_id; + +typedef struct { + size_t sz; + ioa_network_buffer_handle *bufs; +} unsent_buffer; + +struct _tcp_connection +{ + TC_STATE state; + tcp_connection_id id; + ioa_addr peer_addr; + ioa_socket_handle client_s; + ioa_socket_handle peer_s; + ioa_timer_handle peer_conn_timeout; + ioa_timer_handle conn_bind_timeout; + stun_tid tid; + void *owner; //a + int done; + unsent_buffer ub_to_client; +}; + +typedef struct _tcp_connection_list { + size_t sz; + tcp_connection **elems; +} tcp_connection_list; + +//////////////////////////////// + +#define TURN_PERMISSION_HASHTABLE_SIZE (0x8) +#define TURN_PERMISSION_ARRAY_SIZE (0x3) + +struct _allocation; + +typedef struct _ch_info { + u16bits chnum; + int allocated; + u16bits port; + ioa_addr peer_addr; + turn_time_t expiration_time; + ioa_timer_handle lifetime_ev; + void *owner; //perm +} ch_info; + +///////////// "channel" map ///////////////////// + +#define CH_MAP_HASH_SIZE (0x8) +#define CH_MAP_ARRAY_SIZE (0x3) + +typedef struct _chn_map_array { + ch_info main_chns[CH_MAP_ARRAY_SIZE]; + size_t extra_sz; + ch_info **extra_chns; +} ch_map_array; + +typedef struct _ch_map { + ch_map_array table[CH_MAP_HASH_SIZE]; +} ch_map; + +ch_info *ch_map_get(ch_map* map, u16bits chnum, int new_chn); +void ch_map_clean(ch_map* map); + +//////////////////////////// + +typedef struct _turn_permission_info { + int allocated; + lm_map chns; + ioa_addr addr; + turn_time_t expiration_time; + ioa_timer_handle lifetime_ev; + void* owner; //a +} turn_permission_info; + +typedef struct _turn_permission_slot { + turn_permission_info info; +} turn_permission_slot; + +typedef struct _turn_permission_array { + turn_permission_slot main_slots[TURN_PERMISSION_ARRAY_SIZE]; + size_t extra_sz; + turn_permission_slot **extra_slots; +} turn_permission_array; + +typedef struct _turn_permission_hashtable { + turn_permission_array table[TURN_PERMISSION_HASHTABLE_SIZE]; +} turn_permission_hashtable; + +//////////////// ALLOCATION ////////////////////// + +typedef struct _allocation { + int is_valid; + stun_tid tid; + turn_time_t expiration_time; + ioa_timer_handle lifetime_ev; + turn_permission_hashtable addr_to_perm; + ts_ur_session relay_session; + ch_map chns; /* chnum-to-ch_info* */ + void *owner; //ss + ur_map *tcp_connections; //global (per turn server) reference + tcp_connection_list tcs; //local reference +} allocation; + +//////////// CHANNELS //////////////////// + +u16bits get_turn_channel_number(turn_permission_info* tinfo, ioa_addr *addr); +ch_info *get_turn_channel(turn_permission_info* tinfo, ioa_addr *addr); + +void turn_channel_delete(ch_info* chn); + +/////////// ALLOCATION //////////// + +void init_allocation(void *owner, allocation* a, ur_map *tcp_connections); +void clear_allocation(allocation *a); + +void turn_permission_clean(turn_permission_info* tinfo); + +void set_allocation_lifetime_ev(allocation *a, turn_time_t exp_time, ioa_timer_handle ev); +int is_allocation_valid(const allocation* a); +void set_allocation_valid(allocation* a, int value); +turn_permission_info* allocation_get_permission(allocation* a, const ioa_addr *addr); +turn_permission_hashtable* allocation_get_turn_permission_hashtable(allocation *a); +turn_permission_info* allocation_add_permission(allocation *a, const ioa_addr* addr); + +ch_info* allocation_get_new_ch_info(allocation* a, u16bits chnum, ioa_addr* peer_addr); +ch_info* allocation_get_ch_info(allocation* a, u16bits chnum); +ch_info* allocation_get_ch_info_by_peer_addr(allocation* a, ioa_addr* peer_addr); + +ts_ur_session *get_relay_session(allocation *a); +ioa_socket_handle get_relay_socket(allocation *a); + +tcp_connection *get_and_clean_tcp_connection_by_id(ur_map *map, tcp_connection_id id); +tcp_connection *get_tcp_connection_by_peer(allocation *a, ioa_addr *peer_addr); +int can_accept_tcp_connection_from_peer(allocation *a, ioa_addr *peer_addr, int server_relay); +tcp_connection *create_tcp_connection(u08bits server_id, allocation *a, stun_tid *tid, ioa_addr *peer_addr, int *err_code); +void delete_tcp_connection(tcp_connection *tc); + +void clear_unsent_buffer(unsent_buffer *ub); +void add_unsent_buffer(unsent_buffer *ub, ioa_network_buffer_handle nbh); +ioa_network_buffer_handle top_unsent_buffer(unsent_buffer *ub); +void pop_unsent_buffer(unsent_buffer *ub); + +/////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__TURN_TURN_A_LIB__ diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h new file mode 100644 index 00000000..7b9559aa --- /dev/null +++ b/src/server/ns_turn_ioalib.h @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +/* + * IO Abstraction library + */ + +#ifndef __IOA_LIB__ +#define __IOA_LIB__ + +#include "ns_turn_ioaddr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +////////////// forward declarations //////// + +struct _ts_ur_super_session; +typedef struct _ts_ur_super_session ts_ur_super_session; + +struct _tcp_connection; +typedef struct _tcp_connection tcp_connection; + + +////////////// Mutexes ///////////////////// + +struct _turn_mutex { + u32bits data; + void* mutex; +}; + +typedef struct _turn_mutex turn_mutex; + +int turn_mutex_init(turn_mutex* mutex); +int turn_mutex_init_recursive(turn_mutex* mutex); + +int turn_mutex_lock(const turn_mutex *mutex); +int turn_mutex_unlock(const turn_mutex *mutex); + +int turn_mutex_destroy(turn_mutex* mutex); + +#define TURN_MUTEX_DECLARE(mutex) turn_mutex mutex; +#define TURN_MUTEX_INIT(mutex) turn_mutex_init(mutex) +#define TURN_MUTEX_INIT_RECURSIVE(mutex) turn_mutex_init_recursive(mutex) +#define TURN_MUTEX_LOCK(mutex) turn_mutex_lock(mutex) +#define TURN_MUTEX_UNLOCK(mutex) turn_mutex_unlock(mutex) +#define TURN_MUTEX_DESTROY(mutex) turn_mutex_destroy(mutex) + +/////// Sockets ////////////////////////////// + +#define IOA_EV_TIMEOUT 0x01 +#define IOA_EV_READ 0x02 +#define IOA_EV_WRITE 0x04 +#define IOA_EV_SIGNAL 0x08 +#define IOA_EV_CLOSE 0x10 + +enum _SOCKET_TYPE { + UNKNOWN_SOCKET=0, + TCP_SOCKET=6, + UDP_SOCKET=17, + TLS_SOCKET=56, + DTLS_SOCKET=250, + TENTATIVE_TCP_SOCKET=255 +}; + +typedef enum _SOCKET_TYPE SOCKET_TYPE; + +enum _SOCKET_APP_TYPE { + UNKNOWN_APP_SOCKET, + CLIENT_SOCKET, + RELAY_SOCKET, + RELAY_RTCP_SOCKET, + TCP_CLIENT_DATA_SOCKET, + TCP_RELAY_DATA_SOCKET, + LISTENER_SOCKET +}; + +typedef enum _SOCKET_APP_TYPE SOCKET_APP_TYPE; + +struct _ioa_socket; +typedef struct _ioa_socket ioa_socket; +typedef ioa_socket *ioa_socket_handle; + +struct _ioa_engine; +typedef struct _ioa_engine ioa_engine; +typedef ioa_engine *ioa_engine_handle; + +typedef void *ioa_timer_handle; + +typedef void *ioa_network_buffer_handle; + +/* event data for net event */ +typedef struct _ioa_net_data { + ioa_addr src_addr; + ioa_network_buffer_handle nbh; + int recv_ttl; + int recv_tos; +} ioa_net_data; + +/* Callback on TCP connection completion */ +typedef void (*connect_cb)(int success, void *arg); +/* Callback on accepted socket from TCP relay endpoint */ +typedef void (*accept_cb)(ioa_socket_handle s, void *arg); + +////////// REALM //////////// + +struct _realm_options_t; +typedef struct _realm_options_t realm_options_t; + +//////// IP White/black listing /////////// + +struct _ip_range_list { + char **ranges; + ioa_addr_range **encaddrsranges; + size_t ranges_number; +}; + +typedef struct _ip_range_list ip_range_list_t; + +void ioa_lock_whitelist(ioa_engine_handle e); +void ioa_unlock_whitelist(ioa_engine_handle e); +const ip_range_list_t* ioa_get_whitelist(ioa_engine_handle e); + +void ioa_lock_blacklist(ioa_engine_handle e); +void ioa_unlock_blacklist(ioa_engine_handle e); +const ip_range_list_t* ioa_get_blacklist(ioa_engine_handle e); + +//////////////////////////////////////////// + +/* + * Network buffer functions + */ +ioa_network_buffer_handle ioa_network_buffer_allocate(ioa_engine_handle e); +void ioa_network_buffer_header_init(ioa_network_buffer_handle nbh); +u08bits *ioa_network_buffer_data(ioa_network_buffer_handle nbh); +size_t ioa_network_buffer_get_size(ioa_network_buffer_handle nbh); +size_t ioa_network_buffer_get_capacity(ioa_network_buffer_handle nbh); +size_t ioa_network_buffer_get_capacity_udp(void); +void ioa_network_buffer_set_size(ioa_network_buffer_handle nbh, size_t len); +void ioa_network_buffer_add_offset_size(ioa_network_buffer_handle nbh, u16bits offset, u08bits coffset, size_t len); +u16bits ioa_network_buffer_get_offset(ioa_network_buffer_handle nbh); +u08bits ioa_network_buffer_get_coffset(ioa_network_buffer_handle nbh); +void ioa_network_buffer_delete(ioa_engine_handle e, ioa_network_buffer_handle nbh); + +/* + * Status reporting functions + */ +void turn_report_allocation_set(void *a, turn_time_t lifetime, int refresh); +void turn_report_allocation_delete(void *a); +void turn_report_session_usage(void *session); + +/* + * Network event handler callback + * chnum parameter is just an optimisation hint - + * the function must work correctly when chnum=0 + * (when no hint information is available). + */ +typedef void (*ioa_net_event_handler)(ioa_socket_handle s, int event_type, ioa_net_data *data, void *ctx); + +/* + * Timer callback + */ +typedef void (*ioa_timer_event_handler)(ioa_engine_handle e, void *ctx); + +/* timers */ + +ioa_timer_handle set_ioa_timer(ioa_engine_handle e, int secs, int ms, ioa_timer_event_handler cb, void *ctx, int persist, const s08bits *txt); +void stop_ioa_timer(ioa_timer_handle th); +void delete_ioa_timer(ioa_timer_handle th); +#define IOA_EVENT_DEL(E) do { if(E) { delete_ioa_timer(E); E = NULL; } } while(0) + +ioa_socket_handle create_unbound_ioa_socket(ioa_engine_handle e, ioa_socket_handle parent_s, int family, SOCKET_TYPE st, SOCKET_APP_TYPE sat); + +void inc_ioa_socket_ref_counter(ioa_socket_handle s); + +/* Relay socket handling */ +/* + * event_port == -1: no rtcp; + * event_port == 0: reserve rtcp; + * even_port == +1: reserve and bind rtcp. + */ +int create_relay_ioa_sockets(ioa_engine_handle e, ioa_socket_handle client_s, + int address_family, u08bits transport, + int even_port, ioa_socket_handle *rtp_s, ioa_socket_handle *rtcp_s, + u64bits *out_reservation_token, int *err_code, const u08bits **reason, + accept_cb acb, void *acbarg); + +ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, ioa_addr *peer_addr, connect_cb cb, void *arg); + +int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_token, ioa_socket_handle *s); + +int get_ioa_socket_address_family(ioa_socket_handle s); +SOCKET_TYPE get_ioa_socket_type(ioa_socket_handle s); +SOCKET_APP_TYPE get_ioa_socket_app_type(ioa_socket_handle s); +const char* get_ioa_socket_tls_method(ioa_socket_handle s); +const char* get_ioa_socket_tls_cipher(ioa_socket_handle s); +void set_ioa_socket_app_type(ioa_socket_handle s, SOCKET_APP_TYPE sat); +ioa_addr* get_local_addr_from_ioa_socket(ioa_socket_handle s); +ioa_addr* get_remote_addr_from_ioa_socket(ioa_socket_handle s); +int get_local_mtu_ioa_socket(ioa_socket_handle s); +ts_ur_super_session *get_ioa_socket_session(ioa_socket_handle s); +void set_ioa_socket_session(ioa_socket_handle s, ts_ur_super_session *ss); +void clear_ioa_socket_session_if(ioa_socket_handle s, void *ss); +tcp_connection *get_ioa_socket_sub_session(ioa_socket_handle s); +void set_ioa_socket_sub_session(ioa_socket_handle s, tcp_connection *tc); +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); +int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, ioa_network_buffer_handle nbh, int ttl, int tos); +void close_ioa_socket(ioa_socket_handle s); +#define IOA_CLOSE_SOCKET(S) do { if(S) { close_ioa_socket(S); S = NULL; } } while(0) +ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach); +void detach_socket_net_data(ioa_socket_handle s); +int set_df_on_ioa_socket(ioa_socket_handle s, int value); +void set_do_not_use_df(ioa_socket_handle s); +int ioa_socket_tobeclosed(ioa_socket_handle s); +void set_ioa_socket_tobeclosed(ioa_socket_handle s); +void close_ioa_socket_after_processing_if_necessary(ioa_socket_handle s); +int check_username_hash(ioa_socket_handle s, u08bits *username, u08bits *realm); +void set_username_hash(ioa_socket_handle s, u08bits *username, u08bits *realm); + +////////////////// Base64 ///////////////////////////// + +char *base64_encode(const unsigned char *data, + size_t input_length, + size_t *output_length); + +void build_base64_decoding_table(void); + +unsigned char *base64_decode(const char *data, + size_t input_length, + size_t *output_length); + +///////////// Realm /////////////////// + +void get_default_realm_options(realm_options_t* ro); +void get_realm_options_by_origin(char *origin, realm_options_t* ro); +void get_realm_options_by_name(char *realm, realm_options_t* ro); +int get_canonic_origin(const char* o, char *co, int sz); +int get_default_protocol_port(const char* scheme, size_t slen); + +/////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* __IOA_LIB__ */ diff --git a/src/server/ns_turn_khash.h b/src/server/ns_turn_khash.h new file mode 100644 index 00000000..813bc0ca --- /dev/null +++ b/src/server/ns_turn_khash.h @@ -0,0 +1,391 @@ +/* The MIT License + + Copyright (c) 2008, by Attractive Chaos + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + */ + +/* Changes, 2011-2012: + proprietary header added, with proprietary memory management functions. +*/ + +/* + An example: + +#include "khash.h" +KHASH_MAP_INIT_INT(32, s08bits) +int main() { + int ret, is_missing; + khiter_t k; + khash_t(32) *h = kh_init(32); + k = kh_put(32, h, 5, &ret); + if (!ret) kh_del(32, h, k); + kh_value(h, k) = 10; + k = kh_get(32, h, 10); + is_missing = (k == kh_end(h)); + k = kh_get(32, h, 5); + kh_del(32, h, k); + for (k = kh_begin(h); k != kh_end(h); ++k) + if (kh_exist(h, k)) kh_value(h, k) = 1; + kh_destroy(32, h); + return 0; +} +*/ + +/* + 2008-09-19 (0.2.3): + + * Corrected the example + * Improved interfaces + + 2008-09-11 (0.2.2): + + * Improved speed a little in kh_put() + + 2008-09-10 (0.2.1): + + * Added kh_clear() + * Fixed a compiling error + + 2008-09-02 (0.2.0): + + * Changed to token concatenation which increases flexibility. + + 2008-08-31 (0.1.2): + + * Fixed a bug in kh_get(), which has not been tested previously. + + 2008-08-31 (0.1.1): + + * Added destructor +*/ + + +#ifndef __AC_KHASH_H +#define __AC_KHASH_H + +#define AC_VERSION_KHASH_H "0.2.2" + +#include "ns_turn_defs.h" + +typedef u32bits khint_t; +typedef khint_t khiter_t; + +typedef struct _str_chunk_t { + const s08bits *str; + size_t len; +} str_chunk_t; + +#define __ac_HASH_PRIME_SIZE 32 +static const u32bits __ac_prime_list[__ac_HASH_PRIME_SIZE] = +{ + 0ul, 3ul, 11ul, 23ul, 53ul, + 97ul, 193ul, 389ul, 769ul, 1543ul, + 3079ul, 6151ul, 12289ul, 24593ul, 49157ul, + 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul, + 3145739ul, 6291469ul, 12582917ul, 25165843ul, 50331653ul, + 100663319ul, 201326611ul, 402653189ul, 805306457ul, 1610612741ul, + 3221225473ul, 4294967291ul +}; + +#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2) +#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1) +#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3) +#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1))) +#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1))) +#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1))) +#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1)) + +static const double __ac_HASH_UPPER = 0.77; + +#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ + typedef struct { \ + khint_t n_buckets, size, n_occupied, upper_bound; \ + u32bits *flags; u32bits flags_size; \ + khkey_t *keys; u32bits keys_size; \ + khval_t *vals; u32bits vals_size; \ + } kh_##name##_t; \ + static inline kh_##name##_t *kh_init_##name(void) { \ + return (kh_##name##_t*)turn_calloc(1, sizeof(kh_##name##_t)); \ + } \ + static inline void kh_destroy_##name(kh_##name##_t *h) \ + { \ + if (h) { \ + turn_free(h->keys,h->keys_size); turn_free(h->flags,h->flags_size); \ + turn_free(h->vals, h->vals_size); \ + turn_free(h, sizeof(kh_##name##_t)); \ + } \ + } \ + static inline void kh_clear_##name(kh_##name##_t *h) \ + { \ + if (h && h->flags) { \ + memset(h->flags, 0xaa, ((h->n_buckets>>4) + 1) * sizeof(u32bits)); \ + h->size = h->n_occupied = 0; \ + } \ + } \ + static inline khint_t kh_get_##name(kh_##name##_t *h, khkey_t key) \ + { \ + if (h->n_buckets) { \ + khint_t inc, k, i, last; \ + k = __hash_func(key); i = k % h->n_buckets; \ + inc = 1 + k % (h->n_buckets - 1); last = i; \ + while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ + if (i + inc >= h->n_buckets) i = i + inc - h->n_buckets; \ + else i += inc; \ + if (i == last) return h->n_buckets; \ + } \ + return __ac_iseither(h->flags, i)? h->n_buckets : i; \ + } else return 0; \ + } \ + static inline void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \ + { \ + u32bits *new_flags = 0; \ + u32bits new_flags_size = 0; \ + khint_t j = 1; \ + { \ + khint_t t = __ac_HASH_PRIME_SIZE - 1; \ + while (__ac_prime_list[t] > new_n_buckets) --t; \ + new_n_buckets = __ac_prime_list[t+1]; \ + if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; \ + else { \ + new_flags_size = ((new_n_buckets>>4) + 1) * sizeof(u32bits); \ + new_flags = (u32bits*)turn_malloc(new_flags_size); \ + memset(new_flags, 0xaa, new_flags_size); \ + if (h->n_buckets < new_n_buckets) { \ + h->keys = (khkey_t*)turn_realloc(h->keys, h->keys_size, new_n_buckets * sizeof(khkey_t)); \ + h->keys_size = new_n_buckets * sizeof(khkey_t); \ + if (kh_is_map) { \ + h->vals = (khval_t*)turn_realloc(h->vals, h->vals_size, new_n_buckets * sizeof(khval_t)); \ + h->vals_size = new_n_buckets * sizeof(khval_t); \ + } \ + } \ + } \ + } \ + if (j) { \ + for (j = 0; j != h->n_buckets; ++j) { \ + if (__ac_iseither(h->flags, j) == 0) { \ + khkey_t key = h->keys[j]; \ + khval_t val; \ + if (kh_is_map) val = h->vals[j]; \ + __ac_set_isdel_true(h->flags, j); \ + while (1) { \ + khint_t inc, k, i; \ + k = __hash_func(key); \ + i = k % new_n_buckets; \ + inc = 1 + k % (new_n_buckets - 1); \ + while (!__ac_isempty(new_flags, i)) { \ + if (i + inc >= new_n_buckets) i = i + inc - new_n_buckets; \ + else i += inc; \ + } \ + __ac_set_isempty_false(new_flags, i); \ + if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { \ + { khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \ + if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \ + __ac_set_isdel_true(h->flags, i); \ + } else { \ + h->keys[i] = key; \ + if (kh_is_map) h->vals[i] = val; \ + break; \ + } \ + } \ + } \ + } \ + if (h->n_buckets > new_n_buckets) { \ + h->keys = (khkey_t*)turn_realloc(h->keys, h->keys_size, new_n_buckets * sizeof(khkey_t)); \ + h->keys_size = new_n_buckets * sizeof(khkey_t); \ + if (kh_is_map) { \ + h->vals = (khval_t*)turn_realloc(h->vals, h->vals_size, new_n_buckets * sizeof(khval_t)); \ + h->vals_size = new_n_buckets * sizeof(khval_t); \ + } \ + } \ + turn_free(h->flags, h->flags_size); \ + h->flags = new_flags; \ + h->flags_size = new_flags_size; \ + h->n_buckets = new_n_buckets; \ + h->n_occupied = h->size; \ + h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \ + } \ + } \ + static inline khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \ + { \ + khint_t x; \ + if (h->n_occupied >= h->upper_bound) { \ + if (h->n_buckets > (h->size<<1)) kh_resize_##name(h, h->n_buckets - 1); \ + else kh_resize_##name(h, h->n_buckets + 1); \ + } \ + { \ + khint_t inc, k, i, site, last; \ + x = site = h->n_buckets; k = __hash_func(key); i = k % h->n_buckets; \ + if (__ac_isempty(h->flags, i)) x = i; \ + else { \ + inc = 1 + k % (h->n_buckets - 1); last = i; \ + while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ + if (__ac_isdel(h->flags, i)) site = i; \ + if (i + inc >= h->n_buckets) i = i + inc - h->n_buckets; \ + else i += inc; \ + if (i == last) { x = site; break; } \ + } \ + if (x == h->n_buckets) { \ + if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \ + else x = i; \ + } \ + } \ + } \ + if (__ac_isempty(h->flags, x)) { \ + h->keys[x] = key; \ + __ac_set_isboth_false(h->flags, x); \ + ++h->size; ++h->n_occupied; \ + *ret = 1; \ + } else if (__ac_isdel(h->flags, x)) { \ + h->keys[x] = key; \ + __ac_set_isboth_false(h->flags, x); \ + ++h->size; \ + *ret = 2; \ + } else *ret = 0; \ + return x; \ + } \ + static inline void kh_del_##name(kh_##name##_t *h, khint_t x) \ + { \ + if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \ + __ac_set_isdel_true(h->flags, x); \ + --h->size; \ + } \ + } + +/* --- BEGIN OF HASH FUNCTIONS --- */ + +#define kh_int_hash_func(key) (u32bits)((key<<3) + nswap32(key>>7)) +#define kh_int_hash_equal(a, b) (a == b) +#define kh_int64_hash_func(key) (u32bits)((key)>>33^(key)^(key)<<11) +#define kh_int64_hash_equal(a, b) (a == b) + +static inline khint_t __ac_X31_hash_string(const s08bits *s) +{ + khint_t h = *s; + if (h) + for (++s; *s; ++s) + h = (h << 5) - h + *s; + return h; +} +static inline khint_t __ac_X31_hash_cstring(const s08bits *s) +{ + khint_t h = tolower((int)*s); + if (h) + for (++s; *s; ++s) + h = (h << 5) - h + tolower((int)*s); + return h; +} +static inline khint_t __ac_X31_hash_nstring(const str_chunk_t *s) +{ + khint_t h = *(s->str); + if (h) { + size_t i; + for (i = 0; i < s->len; i++) + h = (h << 5) - h + s->str[i]; + } + return h; +} +static inline khint_t __ac_X31_hash_ncstring(const str_chunk_t *s) +{ + khint_t h = tolower((int)(*(s->str))); + if (h) { + size_t i; + for (i = 0; i < s->len; i++) + h = (h << 5) - h + tolower((int)(s->str[i])); + } + return h; +} +#define kh_str_hash_func(key) __ac_X31_hash_string(key) +#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0) +#define kh_cstr_hash_func(key) __ac_X31_hash_cstring(key) +#define kh_cstr_hash_equal(a, b) (strcasecmp(a, b) == 0) +#define kh_nstr_hash_func(key) __ac_X31_hash_nstring(key) +#define kh_nstr_hash_equal(a, b) (a->len == b->len && (strncmp(a->str, b->str, a->len) == 0)) +#define kh_ncstr_hash_func(key) __ac_X31_hash_ncstring(key) +#define kh_ncstr_hash_equal(a, b) (a->len == b->len && (strncasecmp(a->str, b->str, a->len) == 0)) + +/* --- END OF HASH FUNCTIONS --- */ + +/* Other necessary macros... */ + +#define khash_t(name) kh_##name##_t + +#define kh_init(name) kh_init_##name() +#define kh_destroy(name, h) kh_destroy_##name(h) +#define kh_clear(name, h) kh_clear_##name(h) +#define kh_resize(name, h, s) kh_resize_##name(h, s) +#define kh_put(name, h, k, r) kh_put_##name(h, k, r) +#define kh_get(name, h, k) kh_get_##name(h, k) +#define kh_del(name, h, k) kh_del_##name(h, k) + +#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x))) +#define kh_key(h, x) ((h)->keys[x]) +#define kh_val(h, x) ((h)->vals[x]) +#define kh_value(h, x) ((h)->vals[x]) +#define kh_begin(h) (khint_t)(0) +#define kh_end(h) ((h)->n_buckets) +#define kh_size(h) ((h)->size) +#define kh_n_buckets(h) ((h)->n_buckets) + +/* More convenient interfaces */ + +#define KHASH_SET_INIT_INT(name) \ + KHASH_INIT(name, u32bits, s08bits, 0, kh_int_hash_func, kh_int_hash_equal) + +#define KHASH_MAP_INIT_INT(name, khval_t) \ + KHASH_INIT(name, u32bits, khval_t, 1, kh_int_hash_func, kh_int_hash_equal) + +#define KHASH_SET_INIT_INT64(name) \ + KHASH_INIT(name, u64bits, s08bits, 0, kh_int64_hash_func, kh_int64_hash_equal) + +#define KHASH_MAP_INIT_INT64(name, khval_t) \ + KHASH_INIT(name, u64bits, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal) + +typedef const s08bits *kh_cstr_t; +typedef const str_chunk_t *kh_ncstr_t; +#define KHASH_SET_INIT_STR(name) \ + KHASH_INIT(name, kh_cstr_t, s08bits, 0, kh_str_hash_func, kh_str_hash_equal) + +#define KHASH_MAP_INIT_STR(name, khval_t) \ + KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal) + +#define KHASH_SET_INIT_CSTR(name) \ + KHASH_INIT(name, kh_cstr_t, s08bits, 0, kh_cstr_hash_func, kh_cstr_hash_equal) + +#define KHASH_MAP_INIT_CSTR(name, khval_t) \ + KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_cstr_hash_func, kh_cstr_hash_equal) + +#define KHASH_SET_INIT_NSTR(name) \ + KHASH_INIT(name, kh_ncstr_t, s08bits, 0, kh_nstr_hash_func, kh_nstr_hash_equal) + +#define KHASH_MAP_INIT_NSTR(name, khval_t) \ + KHASH_INIT(name, kh_ncstr_t, khval_t, 1, kh_nstr_hash_func, kh_nstr_hash_equal) + +#define KHASH_SET_INIT_NCSTR(name) \ + KHASH_INIT(name, kh_ncstr_t, s08bits, 0, kh_ncstr_hash_func, kh_ncstr_hash_equal) + +#define KHASH_MAP_INIT_NCSTR(name, khval_t) \ + KHASH_INIT(name, kh_ncstr_t, khval_t, 1, kh_ncstr_hash_func, kh_ncstr_hash_equal) + +////////////////////////////////////////////// + +#endif /* __AC_KHASH_H */ diff --git a/src/server/ns_turn_maps.c b/src/server/ns_turn_maps.c new file mode 100644 index 00000000..d5d3504b --- /dev/null +++ b/src/server/ns_turn_maps.c @@ -0,0 +1,1122 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "ns_turn_maps.h" + +#include "ns_turn_ioalib.h" + +#include "ns_turn_khash.h" + +KHASH_MAP_INIT_INT64(3, ur_map_value_type) + +#define MAGIC_HASH ((u64bits)(0x90ABCDEFL)) + +struct _ur_map { + khash_t(3) *h; + u64bits magic; + TURN_MUTEX_DECLARE(mutex) +}; + +static int ur_map_init(ur_map* map) { + if(map) { + map->h=kh_init(3); + if(map->h) { + map->magic=MAGIC_HASH; + TURN_MUTEX_INIT_RECURSIVE(&(map->mutex)); + return 0; + } + } + return -1; +} + +#define ur_map_valid(map) ((map) && ((map)->h) && ((map)->magic==MAGIC_HASH)) + +ur_map* ur_map_create() { + ur_map *map=(ur_map*)turn_malloc(sizeof(ur_map)); + if(ur_map_init(map)<0) { + turn_free(map,sizeof(ur_map)); + return NULL; + } + return map; +} + +/** + * @ret: + * 0 - success + * -1 - error + */ +int ur_map_put(ur_map* map, ur_map_key_type key, ur_map_value_type value) { + if(!ur_map_valid(map)) return -1; + else { + + int ret=0; + khiter_t k; + + k = kh_get(3, map->h, key); + if(k != kh_end(map->h)) { + kh_del(3, map->h, k); + } + + k = kh_put(3,map->h,key,&ret); + + if (!ret) { + kh_del(3, map->h, k); + return -1; + } + + kh_value(map->h, k) = value; + + return 0; + } +} + +/** + * @ret: + * 1 - success + * 0 - not found + */ +int ur_map_get(const ur_map* map, ur_map_key_type key, ur_map_value_type *value) { + if(!ur_map_valid(map)) return 0; + else { + + khiter_t k; + + k = kh_get(3, map->h, key); + if((k != kh_end(map->h)) && kh_exist(map->h,k)) { + if(value) *value=kh_value(map->h,k); + return 1; + } + + return 0; + } +} + +/** + * @ret: + * 1 - success + * 0 - not found + */ +int ur_map_del(ur_map* map, ur_map_key_type key,ur_map_del_func delfunc) { + if(!ur_map_valid(map)) return 0; + else { + + khiter_t k; + + k = kh_get(3, map->h, key); + if((k != kh_end(map->h)) && kh_exist(map->h,k)) { + if(delfunc) { + delfunc(kh_value(map->h,k)); + } + kh_del(3,map->h,k); + return 1; + } + + return 0; + } +} + +/** + * @ret: + * 1 - success + * 0 - not found + */ +int ur_map_exist(const ur_map* map, ur_map_key_type key) { + if(!ur_map_valid(map)) return 0; + else { + + khiter_t k; + + k = kh_get(3, map->h, key); + if((k != kh_end(map->h)) && kh_exist(map->h,k)) { + return 1; + } + + return 0; + } +} + +void ur_map_free(ur_map** map) { + if(map && ur_map_valid(*map)) { + kh_destroy(3,(*map)->h); + (*map)->h=NULL; + (*map)->magic=0; + TURN_MUTEX_DESTROY(&((*map)->mutex)); + turn_free(*map,sizeof(ur_map)); + *map=NULL; + } +} + +size_t ur_map_size(const ur_map* map) { + if(ur_map_valid(map)) { + return kh_size(map->h); + } else { + return 0; + } +} + +int ur_map_foreach(ur_map* map, foreachcb_type func) { + if(map && func && ur_map_valid(map)) { + khiter_t k; + for (k = kh_begin((*map)->h); k != kh_end(map->h); ++k) { + if (kh_exist(map->h, k)) { + if(func((ur_map_key_type)(kh_key(map->h, k)), + (ur_map_value_type)(kh_value(map->h, k)))) { + return 1; + } + } + } + } + return 0; +} + +int ur_map_foreach_arg(ur_map* map, foreachcb_arg_type func, void* arg) { + if(map && func && ur_map_valid(map)) { + khiter_t k; + for (k = kh_begin((*map)->h); k != kh_end(map->h); ++k) { + if (kh_exist(map->h, k)) { + if(func((ur_map_key_type)(kh_key(map->h, k)), + (ur_map_value_type)(kh_value(map->h, k)), + arg) + ) { + return 1; + } + } + } + } + return 0; +} + +int ur_map_lock(const ur_map* map) { + if(ur_map_valid(map)) { + TURN_MUTEX_LOCK((const turn_mutex*)&(map->mutex)); + return 0; + } + return -1; +} + +int ur_map_unlock(const ur_map* map) { + if(ur_map_valid(map)) { + TURN_MUTEX_UNLOCK((const turn_mutex*)&(map->mutex)); + return 0; + } + return -1; +} + +//////////////////// LOCAL MAPS //////////////////////////////////// + +void lm_map_init(lm_map *map) +{ + if(map) { + ns_bzero(map,sizeof(lm_map)); + } +} + +/** + * @ret: + * 0 - success + * -1 - error + */ + +int lm_map_put(lm_map* map, ur_map_key_type key, ur_map_value_type value) +{ + int ret = -1; + if(map && key && value) { + + size_t index = (size_t)(key & (LM_MAP_HASH_SIZE - 1)); + lm_map_array *a = &(map->table[index]); + + size_t i; + + for(i=0;imain_keys[i]; + ur_map_value_type value0 = a->main_values[i]; + + if(key0 == key) { + if(value0 == value) { + return 0; + } else { + return -1; + } + } + + if(!key0 || !value0) { + a->main_keys[i] = key; + a->main_values[i] = value; + return 0; + } + } + + size_t esz = a->extra_sz; + if(esz && a->extra_keys && a->extra_values) { + for(i=0;iextra_keys[i]; + ur_map_value_type *valuep = a->extra_values[i]; + if(keyp && valuep) { + if(!(*keyp) || !(*valuep)) { + *keyp = key; + *valuep = value; + return 0; + } + } else { + if(!(*keyp)) { + a->extra_keys[i] = (ur_map_key_type*)turn_malloc(sizeof(ur_map_key_type)); + keyp = a->extra_keys[i]; + } + if(!(*valuep)) { + a->extra_values[i] = (ur_map_value_type*)turn_malloc(sizeof(ur_map_value_type)); + valuep = a->extra_values[i]; + } + *keyp = key; + *valuep = value; + return 0; + } + } + } + + size_t old_sz = esz; + size_t old_sz_mem = esz * sizeof(ur_map_key_type*); + a->extra_keys = (ur_map_key_type**)turn_realloc(a->extra_keys,old_sz_mem,old_sz_mem + sizeof(ur_map_key_type*)); + a->extra_keys[old_sz] = (ur_map_key_type*)turn_malloc(sizeof(ur_map_key_type)); + *(a->extra_keys[old_sz]) = key; + + old_sz_mem = esz * sizeof(ur_map_value_type*); + a->extra_values = (ur_map_value_type**)turn_realloc(a->extra_values,old_sz_mem,old_sz_mem + sizeof(ur_map_value_type*)); + a->extra_values[old_sz] = (ur_map_value_type*)turn_malloc(sizeof(ur_map_value_type)); + *(a->extra_values[old_sz]) = value; + + a->extra_sz += 1; + + return 0; + } + return ret; +} + +/** + * @ret: + * 1 - success + * 0 - not found + */ + +int lm_map_get(const lm_map* map, ur_map_key_type key, ur_map_value_type *value) +{ + int ret = 0; + if(map && key) { + size_t index = (size_t)(key & (LM_MAP_HASH_SIZE - 1)); + const lm_map_array *a = &(map->table[index]); + + size_t i; + + for(i=0;imain_keys[i]; + if((key0 == key) && a->main_values[i]) { + if(value) { + *value = a->main_values[i]; + } + return 1; + } + } + + size_t esz = a->extra_sz; + if(esz && a->extra_keys && a->extra_values) { + for(i=0;iextra_keys[i]; + ur_map_value_type *valuep = a->extra_values[i]; + if(keyp && valuep) { + if(*keyp == key) { + if(value) + *value = *valuep; + return 1; + } + } + } + } + } + + return ret; +} +/** + * @ret: + * 1 - success + * 0 - not found + */ + +int lm_map_del(lm_map* map, ur_map_key_type key,ur_map_del_func delfunc) +{ + int ret = 0; + + if(map && key) { + size_t index = (size_t)(key & (LM_MAP_HASH_SIZE - 1)); + lm_map_array *a = &(map->table[index]); + + size_t i; + + for(i=0;imain_keys[i]; + + if((key0 == key) && a->main_values[i]) { + if(delfunc) { + delfunc(a->main_values[i]); + } + a->main_keys[i] = 0; + a->main_values[i] = 0; + return 1; + } + } + + size_t esz = a->extra_sz; + if(esz && a->extra_keys && a->extra_values) { + for(i=0;iextra_keys[i]; + ur_map_value_type *valuep = a->extra_values[i]; + if(keyp && valuep) { + if(*keyp == key) { + if(delfunc) + delfunc(*valuep); + *keyp = 0; + *valuep = 0; + return 1; + } + } + } + } + } + + return ret; +} +/** + * @ret: + * 1 - success + * 0 - not found + */ + +int lm_map_exist(const lm_map* map, ur_map_key_type key) +{ + return lm_map_get(map, key, NULL); +} + +void lm_map_clean(lm_map* map) +{ + size_t j; + for(j=0;jtable[j]); + + size_t esz = a->extra_sz; + if(esz) { + size_t i; + if(a->extra_keys) { + for(i=0;iextra_keys[i]; + if(keyp) { + *keyp = 0; + turn_free(keyp,sizeof(ur_map_key_type)); + } + } + turn_free(a->extra_keys,esz * sizeof(ur_map_key_type)); + a->extra_keys = NULL; + } + if(a->extra_values) { + for(i=0;iextra_values[i]; + if(valuep) { + *valuep = 0; + turn_free(valuep,sizeof(ur_map_value_type)); + } + } + turn_free(a->extra_values,esz * sizeof(ur_map_value_type)); + a->extra_values = NULL; + } + } + } + + lm_map_init(map); +} + +size_t lm_map_size(const lm_map* map) +{ + size_t ret = 0; + + if(map) { + + size_t i; + + for(i=0;itable[i]); + + size_t j; + + for(j=0;jmain_keys[j] && a->main_values[j]) { + ++ret; + } + } + + size_t esz = a->extra_sz; + if(esz && a->extra_values && a->extra_keys) { + for(j=0;jextra_keys[j]) && *(a->extra_values[j])) { + ++ret; + } + } + } + } + } + + return ret; +} + +int lm_map_foreach(lm_map* map, foreachcb_type func) +{ + size_t ret = 0; + + if(map) { + + size_t i; + + for(i=0;itable[i]); + + size_t j; + + for(j=0;jmain_keys[j] && a->main_values[j]) { + if(func((ur_map_key_type)a->main_keys[j], + (ur_map_value_type)a->main_values[j])) { + return 1; + } + } + } + + size_t esz = a->extra_sz; + if(esz && a->extra_values && a->extra_keys) { + for(j=0;jextra_keys[j]) && *(a->extra_values[j])) { + if(func((ur_map_key_type)*(a->extra_keys[j]), + (ur_map_value_type)*(a->extra_values[j]))) { + return 1; + } + } + } + } + } + } + + return ret; +} + +int lm_map_foreach_arg(lm_map* map, foreachcb_arg_type func, void* arg) +{ + size_t ret = 0; + + if(map) { + + size_t i; + + for(i=0;itable[i]); + + size_t j; + + for(j=0;jmain_keys[j] && a->main_values[j]) { + if(func((ur_map_key_type)a->main_keys[j], + (ur_map_value_type)a->main_values[j], + arg)) { + return 1; + } + } + } + + size_t esz = a->extra_sz; + if(esz && a->extra_values && a->extra_keys) { + for(j=0;jextra_keys[j]) && *(a->extra_values[j])) { + if(func((ur_map_key_type)*(a->extra_keys[j]), + (ur_map_value_type)*(a->extra_values[j]), + arg)) { + return 1; + } + } + } + } + } + } + + return ret; +} + +//////////////////// ADDR LISTS /////////////////////////////////// + +static void addr_list_free(addr_list_header* slh) { + if(slh) { + if(slh->extra_list) { + turn_free(slh->extra_list,sizeof(addr_elem)*(slh->extra_sz)); + } + ns_bzero(slh,sizeof(addr_list_header)); + } +} + +static void addr_list_add(addr_list_header* slh, const ioa_addr* key, ur_addr_map_value_type value) { + + if(!key || !value) return; + + addr_elem *elem = NULL; + size_t i; + + for(i=0;imain_list[i].value)) { + elem = &(slh->main_list[i]); + break; + } + } + + if(!elem && slh->extra_list) { + for(i=0;iextra_sz;++i) { + if(!(slh->extra_list[i].value)) { + elem = &(slh->extra_list[i]); + break; + } + } + } + + if(!elem) { + size_t old_sz = slh->extra_sz; + size_t old_sz_mem = old_sz * sizeof(addr_elem); + slh->extra_list = (addr_elem*)turn_realloc(slh->extra_list, old_sz_mem, old_sz_mem + sizeof(addr_elem)); + elem = &(slh->extra_list[old_sz]); + slh->extra_sz += 1; + } + + addr_cpy(&(elem->key),key); + elem->value=value; +} + +static void addr_list_remove(addr_list_header* slh, const ioa_addr* key, + ur_addr_map_func delfunc, int *counter) { + if(!slh || !key) return; + + if(counter) + *counter = 0; + + size_t i; + + for(i=0;imain_list[i]); + if(elem->value) { + if(addr_eq(&(elem->key),key)) { + if(delfunc && elem->value) + delfunc(elem->value); + elem->value = 0; + if(counter) { + *counter += 1; + } + } + } + } + + if(slh->extra_list) { + for(i=0;iextra_sz;++i) { + addr_elem *elem=&(slh->extra_list[i]); + if(elem->value) { + if(addr_eq(&(elem->key),key)) { + if(delfunc && elem->value) + delfunc(elem->value); + elem->value = 0; + if(counter) { + *counter += 1; + } + } + } + } + } +} + +static void addr_list_foreach(addr_list_header* slh, ur_addr_map_func func) { + if(slh && func) { + + size_t i; + + for(i=0;imain_list[i]); + if(elem->value) { + func(elem->value); + } + } + + if(slh->extra_list) { + for(i=0;iextra_sz;++i) { + addr_elem *elem=&(slh->extra_list[i]); + if(elem->value) { + func(elem->value); + } + } + } + } +} + +static addr_elem* addr_list_get(addr_list_header* slh, const ioa_addr* key) { + + if(!slh || !key) return NULL; + + size_t i; + + for(i=0;imain_list[i]); + if(elem->value) { + if(addr_eq(&(elem->key),key)) { + return elem; + } + } + } + + if(slh->extra_list) { + for(i=0;iextra_sz;++i) { + addr_elem *elem=&(slh->extra_list[i]); + if(elem->value) { + if(addr_eq(&(elem->key),key)) { + return elem; + } + } + } + } + + return NULL; +} + +static const addr_elem* addr_list_get_const(const addr_list_header* slh, const ioa_addr* key) { + + if(!slh || !key) return NULL; + + size_t i; + + for(i=0;imain_list[i]); + if(elem->value) { + if(addr_eq(&(elem->key),key)) { + return elem; + } + } + } + + if(slh->extra_list) { + for(i=0;iextra_sz;++i) { + const addr_elem *elem=&(slh->extra_list[i]); + if(elem->value) { + if(addr_eq(&(elem->key),key)) { + return elem; + } + } + } + } + + return NULL; +} + +////////// ADDR MAPS //////////////////////////////////////////// + +#define addr_map_index(key) (addr_hash((key)) & (ADDR_MAP_SIZE - 1)) + +#define get_addr_list_header(map, key) (&((map)->lists[addr_map_index((key))])) + +#define ur_addr_map_valid(map) ((map) && ((map)->magic==MAGIC_HASH)) + +void ur_addr_map_init(ur_addr_map* map) { + if(map) { + ns_bzero(map,sizeof(ur_addr_map)); + map->magic=MAGIC_HASH; + } +} + +void ur_addr_map_clean(ur_addr_map* map) { + if(map && ur_addr_map_valid(map)) { + u32bits i=0; + for(i=0;ilists[i])); + } + ns_bzero(map,sizeof(ur_addr_map)); + } +} + +/** + * @ret: + * 0 - success + * -1 - error + * if the addr key exists, the value is updated. + */ +int ur_addr_map_put(ur_addr_map* map, ioa_addr* key, ur_addr_map_value_type value) { + + if(!ur_addr_map_valid(map)) return -1; + + else { + + addr_list_header* slh = get_addr_list_header(map, key); + + addr_elem* elem = addr_list_get(slh, key); + if(elem) { + elem->value=value; + } else { + addr_list_add(slh,key,value); + } + + return 0; + } +} + +/** + * @ret: + * 1 - success + * 0 - not found + */ +int ur_addr_map_get(const ur_addr_map* map, ioa_addr* key, ur_addr_map_value_type *value) { + + if(!ur_addr_map_valid(map)) return 0; + + else { + + const addr_list_header* slh = get_addr_list_header(map, key); + + const addr_elem *elem = addr_list_get_const(slh, key); + if(elem) { + if(value) *value=elem->value; + return 1; + } + + return 0; + } +} + +/** + * @ret: + * 1 - success + * 0 - not found + */ +int ur_addr_map_del(ur_addr_map* map, ioa_addr* key,ur_addr_map_func delfunc) { + + if(!ur_addr_map_valid(map)) return 0; + + else { + + addr_list_header* slh = get_addr_list_header(map, key); + + int counter=0; + + addr_list_remove(slh, key, delfunc, &counter); + + return (counter>0); + } +} + +/** + * @ret: + * 1 - success + * 0 - not found + */ +void ur_addr_map_foreach(ur_addr_map* map, ur_addr_map_func func) { + + if(ur_addr_map_valid(map)) { + + u32bits i=0; + for(i=0;ilists[i]); + + addr_list_foreach(slh, func); + } + } +} + +//////////////////// STRING LISTS /////////////////////////////////// + +typedef struct _string_list { + struct _string_list* next; +} string_list; + +typedef struct _string_elem { + string_list list; + ur_string_map_key_type key; + u32bits key_size; + ur_string_map_value_type value; +} string_elem; + +typedef struct _string_list_header { + string_list *list; +} string_list_header; + +static size_t string_list_size(const string_list *sl) { + if(!sl) return 0; + return 1+string_list_size(sl->next); +} + +static void string_list_free(string_list_header* slh, ur_string_map_func del_value_func) { + if(slh) { + string_list* list=slh->list; + while(list) { + string_elem *elem=(string_elem*)list; + string_list* tail=elem->list.next; + if(elem->key) turn_free(elem->key,elem->key_size); + if(del_value_func && elem->value) + del_value_func(elem->value); + turn_free(elem,sizeof(string_elem)); + list=tail; + } + slh->list=NULL; + } +} + +static string_list* string_list_add(string_list* sl, const ur_string_map_key_type key, ur_string_map_value_type value) { + if(!key) return sl; + string_elem *elem=(string_elem*)turn_malloc(sizeof(string_elem)); + elem->list.next=sl; + elem->key_size = strlen(key)+1; + elem->key=(s08bits*)turn_malloc(elem->key_size); + ns_bcopy(key,elem->key,elem->key_size); + elem->value=value; + return &(elem->list); +} + +static string_list* string_list_remove(string_list* sl, const ur_string_map_key_type key, + ur_string_map_func del_value_func, int *counter) { + if(!sl || !key) return sl; + string_elem *elem=(string_elem*)sl; + string_list* tail=elem->list.next; + if(strcmp(elem->key,key)==0) { + turn_free(elem->key,elem->key_size); + if(del_value_func) + del_value_func(elem->value); + turn_free(elem,sizeof(string_elem)); + if(counter) *counter+=1; + sl=string_list_remove(tail, key, del_value_func, counter); + } else { + elem->list.next=string_list_remove(tail,key,del_value_func,counter); + } + return sl; +} + +static string_elem* string_list_get(string_list* sl, const ur_string_map_key_type key) { + + if(!sl || !key) return NULL; + + string_elem *elem=(string_elem*)sl; + if(strcmp(elem->key,key)==0) { + return elem; + } else { + return string_list_get(elem->list.next, key); + } +} + +////////// STRING MAPS //////////////////////////////////////////// + +#define STRING_MAP_SIZE (1024) + +struct _ur_string_map { + string_list_header lists[STRING_MAP_SIZE]; + u64bits magic; + ur_string_map_func del_value_func; + TURN_MUTEX_DECLARE(mutex) +}; + +static unsigned long string_hash(const ur_string_map_key_type key) { + + u08bits *str=(u08bits*)key; + + unsigned long hash = 0; + int c = 0; + + while ((c = *str++)) + hash = c + (hash << 6) + (hash << 16) - hash; + + return hash; +} + +static int string_map_index(const ur_string_map_key_type key) { + return (int)(string_hash(key) % STRING_MAP_SIZE); +} + +static string_list_header* get_string_list_header(ur_string_map *map, const ur_string_map_key_type key) { + return &(map->lists[string_map_index(key)]); +} + +static int ur_string_map_init(ur_string_map* map) { + if(map) { + ns_bzero(map,sizeof(ur_string_map)); + map->magic=MAGIC_HASH; + + TURN_MUTEX_INIT_RECURSIVE(&(map->mutex)); + + return 0; + } + return -1; +} + +static int ur_string_map_valid(const ur_string_map *map) { + return (map && map->magic==MAGIC_HASH); +} + +ur_string_map* ur_string_map_create(ur_string_map_func del_value_func) { + ur_string_map *map=(ur_string_map*)turn_malloc(sizeof(ur_string_map)); + if(ur_string_map_init(map)<0) { + turn_free(map,sizeof(ur_string_map)); + return NULL; + } + map->del_value_func = del_value_func; + return map; +} + +/** + * @ret: + * 0 - success + * -1 - error + * if the string key exists, and the value is different, return error. + */ +int ur_string_map_put(ur_string_map* map, const ur_string_map_key_type key, ur_string_map_value_type value) { + + if(!ur_string_map_valid(map)) return -1; + + else { + + string_list_header* slh = get_string_list_header(map, key); + + string_elem *elem = string_list_get(slh->list, key); + if(elem) { + if(elem->value != value) { + if(map->del_value_func) + map->del_value_func(elem->value); + elem->value = value; + } + return 0; + } + + slh->list=string_list_add(slh->list,key,value); + + return 0; + } +} + +/** + * @ret: + * 1 - success + * 0 - not found + */ +int ur_string_map_get(ur_string_map* map, const ur_string_map_key_type key, ur_string_map_value_type *value) { + + if(!ur_string_map_valid(map)) return 0; + + else { + + string_list_header* slh = get_string_list_header(map, key); + string_elem *elem = string_list_get(slh->list, key); + if(elem) { + if(value) *value=elem->value; + return 1; + } else { + return 0; + } + } +} + +/** + * @ret: + * 1 - success + * 0 - not found + */ +int ur_string_map_del(ur_string_map* map, const ur_string_map_key_type key) { + + if(!ur_string_map_valid(map)) return 0; + + else { + + string_list_header* slh = get_string_list_header(map, key); + + int counter=0; + + slh->list=string_list_remove(slh->list, key, map->del_value_func, &counter); + + return (counter>0); + } +} + +void ur_string_map_clean(ur_string_map* map) { + if (ur_string_map_valid(map)) { + int i = 0; + for (i = 0; i < STRING_MAP_SIZE; i++) { + string_list_free(&(map->lists[i]), map->del_value_func); + } + } +} + +void ur_string_map_free(ur_string_map** map) { + if(map && ur_string_map_valid(*map)) { + int i=0; + for(i=0;ilists[i]),(*map)->del_value_func); + } + (*map)->magic=0; + TURN_MUTEX_DESTROY(&((*map)->mutex)); + turn_free(*map,sizeof(ur_string_map)); + *map=NULL; + } +} + +size_t ur_string_map_size(const ur_string_map* map) { + if(ur_string_map_valid(map)) { + size_t ret=0; + int i=0; + for(i=0;ilists[i].list); + } + return ret; + } else { + return 0; + } +} + +int ur_string_map_lock(const ur_string_map* map) { + if(ur_string_map_valid(map)) { + TURN_MUTEX_LOCK((const turn_mutex*)&(map->mutex)); + return 0; + } + return -1; +} + +int ur_string_map_unlock(const ur_string_map* map) { + if(ur_string_map_valid(map)) { + TURN_MUTEX_UNLOCK((const turn_mutex*)&(map->mutex)); + return 0; + } + return -1; +} + +//////////////////////////////////////////////////////////////// diff --git a/src/server/ns_turn_maps.h b/src/server/ns_turn_maps.h new file mode 100644 index 00000000..3a873aa6 --- /dev/null +++ b/src/server/ns_turn_maps.h @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2011, 2012, 2013 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_MAPS__ +#define __TURN_MAPS__ + +#include "ns_turn_ioaddr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////// UR MAP ////////////////// + +struct _ur_map; +typedef struct _ur_map ur_map; + +//////////////// Common Definitions ////// + +typedef u64bits ur_map_key_type; +typedef unsigned long ur_map_value_type; + +typedef void (*ur_map_del_func)(ur_map_value_type); + +typedef int (*foreachcb_type)(ur_map_key_type key, ur_map_value_type value); +typedef int (*foreachcb_arg_type)(ur_map_key_type key, + ur_map_value_type value, + void *arg); + +///////////// non-local map ///////////////////// + +ur_map* ur_map_create(void); + +/** + * @ret: + * 0 - success + * -1 - error + */ + +int ur_map_put(ur_map* map, ur_map_key_type key, ur_map_value_type value); + +/** + * @ret: + * 1 - success + * 0 - not found + */ + +int ur_map_get(const ur_map* map, ur_map_key_type key, ur_map_value_type *value); +/** + * @ret: + * 1 - success + * 0 - not found + */ + +int ur_map_del(ur_map* map, ur_map_key_type key,ur_map_del_func delfunc); +/** + * @ret: + * 1 - success + * 0 - not found + */ + +int ur_map_exist(const ur_map* map, ur_map_key_type key); + +void ur_map_free(ur_map** map); + +size_t ur_map_size(const ur_map* map); + +int ur_map_foreach(ur_map* map, foreachcb_type func); + +int ur_map_foreach_arg(ur_map* map, foreachcb_arg_type func, void* arg); + +int ur_map_lock(const ur_map* map); +int ur_map_unlock(const ur_map* map); + +///////////// "local" map ///////////////////// + +#define LM_MAP_HASH_SIZE (8) +#define LM_MAP_ARRAY_SIZE (3) + +typedef struct _lm_map_array { + ur_map_key_type main_keys[LM_MAP_ARRAY_SIZE]; + ur_map_value_type main_values[LM_MAP_ARRAY_SIZE]; + size_t extra_sz; + ur_map_key_type **extra_keys; + ur_map_value_type **extra_values; +} lm_map_array; + +typedef struct _lm_map { + lm_map_array table[LM_MAP_HASH_SIZE]; +} lm_map; + +void lm_map_init(lm_map *map); + +/** + * @ret: + * 0 - success + * -1 - error + */ + +int lm_map_put(lm_map* map, ur_map_key_type key, ur_map_value_type value); + +/** + * @ret: + * 1 - success + * 0 - not found + */ + +int lm_map_get(const lm_map* map, ur_map_key_type key, ur_map_value_type *value); +/** + * @ret: + * 1 - success + * 0 - not found + */ + +int lm_map_del(lm_map* map, ur_map_key_type key,ur_map_del_func delfunc); +/** + * @ret: + * 1 - success + * 0 - not found + */ + +int lm_map_exist(const lm_map* map, ur_map_key_type key); + +void lm_map_clean(lm_map* map); + +size_t lm_map_size(const lm_map* map); + +int lm_map_foreach(lm_map* map, foreachcb_type func); + +int lm_map_foreach_arg(lm_map* map, foreachcb_arg_type func, void* arg); + +//////////////// UR ADDR MAP ////////////////// + +typedef unsigned long ur_addr_map_value_type; + +#define ADDR_MAP_SIZE (1024) +#define ADDR_ARRAY_SIZE (4) + +typedef struct _addr_elem { + ioa_addr key; + ur_addr_map_value_type value; +} addr_elem; + +typedef struct _addr_list_header { + addr_elem main_list[ADDR_ARRAY_SIZE]; + addr_elem *extra_list; + size_t extra_sz; +} addr_list_header; + +struct _ur_addr_map { + addr_list_header lists[ADDR_MAP_SIZE]; + u64bits magic; +}; + +struct _ur_addr_map; +typedef struct _ur_addr_map ur_addr_map; + +typedef void (*ur_addr_map_func)(ur_addr_map_value_type); + +void ur_addr_map_init(ur_addr_map* map); +void ur_addr_map_clean(ur_addr_map* map); + +/** + * @ret: + * 0 - success + * -1 - error + * if the addr key exists, the value is updated. + */ +int ur_addr_map_put(ur_addr_map* map, ioa_addr* key, ur_addr_map_value_type value); + +/** + * @ret: + * 1 - success + * 0 - not found + */ +int ur_addr_map_get(const ur_addr_map* map, ioa_addr* key, ur_addr_map_value_type *value); + +/** + * @ret: + * 1 - success + * 0 - not found + */ +int ur_addr_map_del(ur_addr_map* map, ioa_addr* key,ur_addr_map_func func); + +/** + * @ret: + * 1 - success + * 0 - not found + */ +void ur_addr_map_foreach(ur_addr_map* map, ur_addr_map_func func); + +size_t ur_addr_map_size(const ur_addr_map* map); + +//////////////// UR STRING MAP ////////////////// + +typedef s08bits* ur_string_map_key_type; +typedef void* ur_string_map_value_type; +struct _ur_string_map; +typedef struct _ur_string_map ur_string_map; + +typedef void (*ur_string_map_func)(ur_string_map_value_type); + +ur_string_map* ur_string_map_create(ur_string_map_func del_value_func); + +/** + * @ret: + * 0 - success + * -1 - error + * if the string key exists, and the value is different, return error. + */ +int ur_string_map_put(ur_string_map* map, const ur_string_map_key_type key, ur_string_map_value_type value); + +/** + * @ret: + * 1 - success + * 0 - not found + */ +int ur_string_map_get(ur_string_map* map, const ur_string_map_key_type key, ur_string_map_value_type *value); + +/** + * @ret: + * 1 - success + * 0 - not found + */ +int ur_string_map_del(ur_string_map* map, const ur_string_map_key_type key); + +void ur_string_map_clean(ur_string_map* map); +void ur_string_map_free(ur_string_map** map); + +size_t ur_string_map_size(const ur_string_map* map); + +int ur_string_map_lock(const ur_string_map* map); +int ur_string_map_unlock(const ur_string_map* map); + +//////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__TURN_MAPS__ diff --git a/src/server/ns_turn_maps_rtcp.c b/src/server/ns_turn_maps_rtcp.c new file mode 100644 index 00000000..704d3b18 --- /dev/null +++ b/src/server/ns_turn_maps_rtcp.c @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "ns_turn_maps_rtcp.h" + +#include "ns_turn_utils.h" +#include "ns_turn_ioaddr.h" + +//////////////////////////////////////////// + +#define MAGIC_RTCP_MAP (0x76859403) +#define RTCP_TIMEOUT (300) +#define MAX_TOKEN_DEL (1024) + +//////////////////////////////////////////// + +struct _rtcp_map { + u32bits magic; + ur_map *map; + ioa_timer_handle timer_ev; + TURN_MUTEX_DECLARE(mutex) +}; + + +typedef struct { + ioa_socket_handle s; + turn_time_t t; + rtcp_token_type token; +} rtcp_alloc_type; + +//////////////////////////////////////////// + +static int rtcp_map_valid(const rtcp_map *map) { + return (map && (map->magic==MAGIC_RTCP_MAP) && map->map); +} + +typedef struct { + rtcp_token_type tokens[MAX_TOKEN_DEL]; + int tn; + turn_time_t t; +} timeout_check_arg_type; + +static int timeout_check(ur_map_key_type key, + ur_map_value_type value, + void *arg) { + + if(value && arg) { + + timeout_check_arg_type *tcat=(timeout_check_arg_type*)arg; + + rtcp_alloc_type* rat=(rtcp_alloc_type*)value; + + if(turn_time_before(rat->t, tcat->t) && (tcat->tntokens[(tcat->tn)++]=key; + } + } + + return 0; +} + +static void rtcp_map_timeout_handler(ioa_engine_handle e, void* arg) { + + UNUSED_ARG(e); + + if(!arg) return; + + rtcp_map* map=(rtcp_map*)arg; + + if(rtcp_map_valid(map)) { + + TURN_MUTEX_LOCK(&map->mutex); + + timeout_check_arg_type tcat; + tcat.tn=0; + tcat.t=turn_time(); + + ur_map_foreach_arg(map->map, timeout_check, &tcat); + + TURN_MUTEX_UNLOCK(&map->mutex); + + int i=0; + for(i=0;imagic != MAGIC_RTCP_MAP) { + map->magic = MAGIC_RTCP_MAP; + map->map = ur_map_create(); + if (e) + map->timer_ev = set_ioa_timer(e, 3, 0, rtcp_map_timeout_handler, + map, 1, "rtcp_map_timeout_handler"); + TURN_MUTEX_INIT(&map->mutex); + if (rtcp_map_valid(map)) + return 0; + } + } + return -1; +} + +rtcp_map* rtcp_map_create(ioa_engine_handle e) { + rtcp_map *map=(rtcp_map*)turn_malloc(sizeof(rtcp_map)); + ns_bzero(map,sizeof(rtcp_map)); + if(rtcp_map_init(map,e)<0) { + turn_free(map,sizeof(rtcp_map)); + return NULL; + } + return map; +} + +/** + * @ret: + * 0 - success + * -1 - error + */ +int rtcp_map_put(rtcp_map* map, rtcp_token_type token, ioa_socket_handle s) { + if(!rtcp_map_valid(map)) return -1; + else { + rtcp_alloc_type *value=(rtcp_alloc_type*)turn_malloc(sizeof(rtcp_alloc_type)); + if(!value) return -1; + ns_bzero(value,sizeof(rtcp_alloc_type)); + value->s=s; + value->t=turn_time() + RTCP_TIMEOUT; + value->token=token; + TURN_MUTEX_LOCK(&map->mutex); + int ret = ur_map_put(map->map,token,(ur_map_value_type)value); + //TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: 111.111: ret=%d, token=%llu\n",__FUNCTION__,ret,token); + TURN_MUTEX_UNLOCK(&map->mutex); + if(ret<0) turn_free(value,sizeof(rtcp_alloc_type)); + return ret; + } +} + +/** + * @ret: + * >=0 - success + * <0 - not found + */ +ioa_socket_handle rtcp_map_get(const rtcp_map* map, rtcp_token_type token) { + if(!rtcp_map_valid(map)) return NULL; + else { + ur_map_value_type value; + TURN_MUTEX_LOCK(&map->mutex); + int ret = ur_map_get(map->map,token,&value); + //TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: 111.111: ret=%d, value=%llu, token=%llu\n",__FUNCTION__,ret,(unsigned long)value,token); + TURN_MUTEX_UNLOCK(&map->mutex); + if(!ret) return NULL; + rtcp_alloc_type* rval=(rtcp_alloc_type*)value; + if(!rval) return NULL; + //TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: 111.222: ret=%d, token=%llu\n",__FUNCTION__,ret,token); + return rval->s; + } +} + +static void rtcp_alloc_free(ur_map_value_type value) +{ + rtcp_alloc_type *at = (rtcp_alloc_type *)value; + if (at) { + IOA_CLOSE_SOCKET(at->s); + turn_free(at,sizeof(rtcp_alloc_type)); + } +} + +static void rtcp_alloc_free_savefd(ur_map_value_type value) +{ + rtcp_alloc_type *at = (rtcp_alloc_type *) value; + if (at) { + turn_free(at,sizeof(rtcp_alloc_type)); + } +} + +static int foreachcb_free(ur_map_key_type key, ur_map_value_type value) { + UNUSED_ARG(key); + if(value) { + rtcp_alloc_free(value); + } + return 0; +} + +/** + * @ret: + * 1 - success + * 0 - not found + */ +int rtcp_map_del(rtcp_map* map, rtcp_token_type token) { + if(!rtcp_map_valid(map)) return 0; + else { + TURN_MUTEX_LOCK(&map->mutex); + int ret = ur_map_del(map->map,token,rtcp_alloc_free); + TURN_MUTEX_UNLOCK(&map->mutex); + return ret; + } +} +int rtcp_map_del_savefd(rtcp_map* map, rtcp_token_type token) { + if(!rtcp_map_valid(map)) return 0; + else { + TURN_MUTEX_LOCK(&map->mutex); + int ret = ur_map_del(map->map,token,rtcp_alloc_free_savefd); + TURN_MUTEX_UNLOCK(&map->mutex); + return ret; + } +} + +void rtcp_map_free(rtcp_map** map) { + if(map && rtcp_map_valid(*map)) { + TURN_MUTEX_LOCK(&((*map)->mutex)); + IOA_EVENT_DEL((*map)->timer_ev); + ur_map_foreach((*map)->map, foreachcb_free); + ur_map_free(&((*map)->map)); + (*map)->magic=0; + TURN_MUTEX_UNLOCK(&((*map)->mutex)); + TURN_MUTEX_DESTROY(&((*map)->mutex)); + turn_free(*map,sizeof(rtcp_map)); + *map=NULL; + } +} + +size_t rtcp_map_size(const rtcp_map* map) { + if(rtcp_map_valid(map)) { + TURN_MUTEX_LOCK(&map->mutex); + size_t ret = ur_map_size(map->map); + TURN_MUTEX_UNLOCK(&map->mutex); + return ret; + } else { + return 0; + } +} + +//////////////////////////////////////////////////////////////// diff --git a/src/server/ns_turn_maps_rtcp.h b/src/server/ns_turn_maps_rtcp.h new file mode 100644 index 00000000..19ce3cb0 --- /dev/null +++ b/src/server/ns_turn_maps_rtcp.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2011, 2012, 2013 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_RTCP_MAP__ +#define __TURN_RTCP_MAP__ + +#include "ns_turn_maps.h" +#include "ns_turn_ioalib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////// RTCP MAP ////////////////// + +typedef ur_map_key_type rtcp_token_type; + +struct _rtcp_map; +typedef struct _rtcp_map rtcp_map; + +//////////////////////////////////////////////// + +rtcp_map* rtcp_map_create(ioa_engine_handle e); + +/** + * @ret: + * 0 - success + * -1 - error + */ +int rtcp_map_put(rtcp_map* map, rtcp_token_type key, ioa_socket_handle s); + +/** + * @ret: + * >=0 - success + * <0 - not found + */ +ioa_socket_handle rtcp_map_get(const rtcp_map* map, rtcp_token_type token); + +/** + * @ret: + * 1 - success + * 0 - not found + */ +int rtcp_map_del(rtcp_map* map, rtcp_token_type token); +int rtcp_map_del_savefd(rtcp_map* map, rtcp_token_type token); + +/** + * @ret: + * 1 - success + * 0 - not found + */ +void rtcp_map_free(rtcp_map** map); + +size_t rtcp_map_size(const rtcp_map* map); + +//////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__TURN_RTCP_MAP__ diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c new file mode 100644 index 00000000..5161d85e --- /dev/null +++ b/src/server/ns_turn_server.c @@ -0,0 +1,4407 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "ns_turn_server.h" + +#include "ns_turn_utils.h" +#include "ns_turn_allocation.h" +#include "ns_turn_msg_addr.h" +#include "ns_turn_ioalib.h" + +/////////////////////////////////////////// + +#define FUNCSTART if(server && eve(server->verbose)) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s:%d:start\n",__FUNCTION__,__LINE__) +#define FUNCEND if(server && eve(server->verbose)) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s:%d:end\n",__FUNCTION__,__LINE__) + +//////////////////////////////////////////////// + +#define MAX_NUMBER_OF_UNKNOWN_ATTRS (128) + +int TURN_MAX_ALLOCATE_TIMEOUT = 60; +int TURN_MAX_ALLOCATE_TIMEOUT_STUN_ONLY = 3; + +/////////////////////////////////////////// + +static int attach_socket_to_session(turn_turnserver* server, ioa_socket_handle s, ts_ur_super_session* ss); + +static int check_stun_auth(turn_turnserver *server, + ts_ur_super_session *ss, stun_tid *tid, int *resp_constructed, + int *err_code, const u08bits **reason, + ioa_net_data *in_buffer, ioa_network_buffer_handle nbh, + u16bits method, int *message_integrity, + int *postpone_reply, + int can_resume); + +static int create_relay_connection(turn_turnserver* server, + ts_ur_super_session *ss, u32bits lifetime, + int address_family, u08bits transport, + int even_port, u64bits in_reservation_token, u64bits *out_reservation_token, + int *err_code, const u08bits **reason, accept_cb acb); + +static int refresh_relay_connection(turn_turnserver* server, + ts_ur_super_session *ss, u32bits lifetime, int even_port, + u64bits in_reservation_token, u64bits *out_reservation_token, + int *err_code); + +static int write_client_connection(turn_turnserver *server, ts_ur_super_session* ss, ioa_network_buffer_handle nbh, int ttl, int tos); + +static void tcp_peer_accept_connection(ioa_socket_handle s, void *arg); + +static int read_client_connection(turn_turnserver *server, ts_ur_session *elem, + ts_ur_super_session *ss, ioa_net_data *in_buffer, + int can_resume, int count_usage); + +static int need_stun_authentication(turn_turnserver *server, ts_ur_super_session *ss); + +/////////////////// timer ////////////////////////// + +static void timer_timeout_handler(ioa_engine_handle e, void *arg) +{ + UNUSED_ARG(e); + if(arg) { + turn_turnserver *server=(turn_turnserver*)arg; + server->ctime = turn_time(); + } +} + +turn_time_t get_turn_server_time(turn_turnserver *server) +{ + if(server) { + return server->ctime; + } + return turn_time(); +} + +/////////////////// quota ////////////////////// + +static int inc_quota(ts_ur_super_session* ss, u08bits *username) +{ + if(ss && !(ss->quota_used) && ss->server && ((turn_turnserver*)ss->server)->chquotacb && username) { + + if(((turn_turnserver*)ss->server)->ct == TURN_CREDENTIALS_LONG_TERM) { + if(!(ss->realm_set)) { + return -1; + } + } + + if((((turn_turnserver*)ss->server)->chquotacb)(username, (u08bits*)ss->realm_options.name)<0) { + + return -1; + + } else { + + STRCPY(ss->username,username); + + ss->quota_used = 1; + } + } + + return 0; +} + +static void dec_quota(ts_ur_super_session* ss) +{ + if(ss && ss->quota_used && ss->server && ((turn_turnserver*)ss->server)->raqcb) { + + ss->quota_used = 0; + + (((turn_turnserver*)ss->server)->raqcb)(ss->username, (u08bits*)ss->realm_options.name); + } +} + +/////////////////// server lists /////////////////// + +void init_turn_server_addrs_list(turn_server_addrs_list_t *l) +{ + if(l) { + l->addrs = NULL; + l->size = 0; + turn_mutex_init(&(l->m)); + } +} + +/////////////////// RFC 5780 /////////////////////// + +void set_rfc5780(turn_turnserver *server, get_alt_addr_cb cb, send_message_cb smcb) +{ + if(server) { + if(!cb || !smcb) { + server->rfc5780 = 0; + server->alt_addr_cb = NULL; + server->sm_cb = NULL; + } else { + server->rfc5780 = 1; + server->alt_addr_cb = cb; + server->sm_cb = smcb; + } + } +} + +static int is_rfc5780(turn_turnserver *server) +{ + if(!server) + return 0; + + return ((server->rfc5780) && (server->alt_addr_cb)); +} + +static int get_other_address(turn_turnserver *server, ts_ur_super_session *ss, ioa_addr *alt_addr) +{ + if(is_rfc5780(server) && ss && ss->client_session.s) { + int ret = server->alt_addr_cb(get_local_addr_from_ioa_socket(ss->client_session.s), alt_addr); + return ret; + } + + return -1; +} + +static int send_turn_message_to(turn_turnserver *server, ioa_network_buffer_handle nbh, ioa_addr *response_origin, ioa_addr *response_destination) +{ + if(is_rfc5780(server) && nbh && response_origin && response_destination) { + return server->sm_cb(server->e, nbh, response_origin, response_destination); + } + + return -1; +} + +/////////////////// Peer addr check ///////////////////////////// + +static int good_peer_addr(turn_turnserver *server, ioa_addr *peer_addr) +{ + if(server && peer_addr) { + if(*(server->no_multicast_peers) && ioa_addr_is_multicast(peer_addr)) + return 0; + if(*(server->no_loopback_peers) && ioa_addr_is_loopback(peer_addr)) + return 0; + + { + int i; + + if(server->ip_whitelist) { + // White listing of addr ranges + for (i = server->ip_whitelist->ranges_number - 1; i >= 0; --i) { + if (ioa_addr_in_range(server->ip_whitelist->encaddrsranges[i], peer_addr)) + return 1; + } + } + + { + ioa_lock_whitelist(server->e); + + const ip_range_list_t* wl = ioa_get_whitelist(server->e); + if(wl) { + // White listing of addr ranges + for (i = wl->ranges_number - 1; i >= 0; --i) { + if (ioa_addr_in_range(wl->encaddrsranges[i], peer_addr)) { + ioa_unlock_whitelist(server->e); + return 1; + } + } + } + + ioa_unlock_whitelist(server->e); + } + + if(server->ip_blacklist) { + // Black listing of addr ranges + for (i = server->ip_blacklist->ranges_number - 1; i >= 0; --i) { + if (ioa_addr_in_range(server->ip_blacklist->encaddrsranges[i], peer_addr)) { + char saddr[129]; + addr_to_string_no_port(peer_addr,(u08bits*)saddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "A peer IP %s denied in the range: %s\n",saddr,server->ip_blacklist->ranges[i]); + return 0; + } + } + } + + { + ioa_lock_blacklist(server->e); + + const ip_range_list_t* bl = ioa_get_blacklist(server->e); + if(bl) { + // Black listing of addr ranges + for (i = bl->ranges_number - 1; i >= 0; --i) { + if (ioa_addr_in_range(bl->encaddrsranges[i], peer_addr)) { + ioa_unlock_blacklist(server->e); + char saddr[129]; + addr_to_string_no_port(peer_addr,(u08bits*)saddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "A peer IP %s denied in the range: %s\n",saddr,bl->ranges[i]); + return 0; + } + } + } + + ioa_unlock_blacklist(server->e); + } + } + } + + return 1; +} + +/////////////////// Allocation ////////////////////////////////// + +allocation* get_allocation_ss(ts_ur_super_session *ss) { + return &(ss->alloc); +} + +static inline ts_ur_session *get_relay_session_ss(ts_ur_super_session *ss) +{ + return &(ss->alloc.relay_session); +} + +static inline ioa_socket_handle get_relay_socket_ss(ts_ur_super_session *ss) +{ + return ss->alloc.relay_session.s; +} + +/////////// Session info /////// + +void turn_session_info_init(struct turn_session_info* tsi) { + if(tsi) { + ns_bzero(tsi,sizeof(struct turn_session_info)); + } +} + +void turn_session_info_clean(struct turn_session_info* tsi) { + if(tsi) { + if(tsi->extra_peers_data) { + turn_free(tsi->extra_peers_data, sizeof(addr_data)*(tsi->extra_peers_size)); + } + turn_session_info_init(tsi); + } +} + +void turn_session_info_add_peer(struct turn_session_info* tsi, ioa_addr *peer) +{ + if(tsi && peer) { + { + size_t i; + for(i=0;imain_peers_size;++i) { + if(addr_eq(peer, &(tsi->main_peers_data[i].addr))) { + return; + } + } + + if(tsi->main_peers_size < TURN_MAIN_PEERS_ARRAY_SIZE) { + addr_cpy(&(tsi->main_peers_data[tsi->main_peers_size].addr),peer); + addr_to_string(&(tsi->main_peers_data[tsi->main_peers_size].addr), + (u08bits*)tsi->main_peers_data[tsi->main_peers_size].saddr); + tsi->main_peers_size += 1; + return; + } + } + + if(tsi->extra_peers_data) { + size_t sz; + for(sz=0;szextra_peers_size;++sz) { + if(addr_eq(peer, &(tsi->extra_peers_data[sz].addr))) { + return; + } + } + } + tsi->extra_peers_data = (addr_data*)turn_realloc(tsi->extra_peers_data,tsi->extra_peers_size*sizeof(addr_data),(tsi->extra_peers_size+1)*sizeof(addr_data)); + addr_cpy(&(tsi->extra_peers_data[tsi->extra_peers_size].addr),peer); + addr_to_string(&(tsi->extra_peers_data[tsi->extra_peers_size].addr), + (u08bits*)tsi->extra_peers_data[tsi->extra_peers_size].saddr); + tsi->extra_peers_size += 1; + } +} + +struct tsi_arg { + struct turn_session_info* tsi; + ioa_addr *addr; +}; + +static int turn_session_info_foreachcb(ur_map_key_type key, ur_map_value_type value, void *arg) +{ + UNUSED_ARG(value); + + int port = (int)key; + struct tsi_arg *ta = (struct tsi_arg *)arg; + if(port && ta && ta->tsi && ta->addr) { + ioa_addr a; + addr_cpy(&a,ta->addr); + addr_set_port(&a,port); + turn_session_info_add_peer(ta->tsi,&a); + } + return 0; +} + +int turn_session_info_copy_from(struct turn_session_info* tsi, ts_ur_super_session *ss) +{ + int ret = -1; + + if(tsi && ss) { + tsi->id = ss->id; + tsi->start_time = ss->start_time; + tsi->valid = is_allocation_valid(&(ss->alloc)) && !(ss->to_be_closed) && (ss->quota_used); + if(tsi->valid) { + tsi->expiration_time = ss->alloc.expiration_time; + if(ss->client_session.s) { + tsi->client_protocol = get_ioa_socket_type(ss->client_session.s); + addr_cpy(&(tsi->local_addr_data.addr),get_local_addr_from_ioa_socket(ss->client_session.s)); + addr_to_string(&(tsi->local_addr_data.addr),(u08bits*)tsi->local_addr_data.saddr); + addr_cpy(&(tsi->remote_addr_data.addr),get_remote_addr_from_ioa_socket(ss->client_session.s)); + addr_to_string(&(tsi->remote_addr_data.addr),(u08bits*)tsi->remote_addr_data.saddr); + } + if(ss->alloc.relay_session.s) { + tsi->peer_protocol = get_ioa_socket_type(ss->alloc.relay_session.s); + addr_cpy(&(tsi->relay_addr_data.addr),get_local_addr_from_ioa_socket(ss->alloc.relay_session.s)); + addr_to_string(&(tsi->relay_addr_data.addr),(u08bits*)tsi->relay_addr_data.saddr); + } + STRCPY(tsi->username,ss->username); + tsi->enforce_fingerprints = ss->enforce_fingerprints; + STRCPY(tsi->tls_method, get_ioa_socket_tls_method(ss->client_session.s)); + STRCPY(tsi->tls_cipher, get_ioa_socket_tls_cipher(ss->client_session.s)); + STRCPY(tsi->realm, ss->realm_options.name); + STRCPY(tsi->origin, ss->origin); + + if(ss->t_received_packets > ss->received_packets) + tsi->received_packets = ss->t_received_packets; + else + tsi->received_packets = ss->received_packets; + + if(ss->t_sent_packets > ss->sent_packets) + tsi->sent_packets = ss->t_sent_packets; + else + tsi->sent_packets = ss->sent_packets; + + if(ss->t_received_bytes > ss->received_bytes) + tsi->received_bytes = ss->t_received_bytes; + else + tsi->received_bytes = ss->received_bytes; + + if(ss->t_sent_bytes > ss->sent_bytes) + tsi->sent_bytes = ss->t_sent_bytes; + else + tsi->sent_bytes = ss->sent_bytes; + + { + tsi->received_rate = ss->received_rate; + tsi->sent_rate = ss->sent_rate; + tsi->total_rate = tsi->received_rate + tsi->sent_rate; + } + + tsi->is_mobile = ss->is_mobile; + + { + size_t i; + for(i=0;ialloc.addr_to_perm.table[i]); + + { + size_t j; + for(j=0;jmain_slots[j]); + if(slot->info.allocated) { + turn_session_info_add_peer(tsi,&(slot->info.addr)); + struct tsi_arg arg = { + tsi, + &(slot->info.addr) + }; + lm_map_foreach_arg(&(slot->info.chns), turn_session_info_foreachcb, &arg); + } + } + } + + { + turn_permission_slot **slots = parray->extra_slots; + if(slots) { + size_t sz = parray->extra_sz; + size_t j; + for(j=0;jinfo.allocated) { + turn_session_info_add_peer(tsi,&(slot->info.addr)); + struct tsi_arg arg = { + tsi, + &(slot->info.addr) + }; + lm_map_foreach_arg(&(slot->info.chns), turn_session_info_foreachcb, &arg); + } + } + } + } + } + } + + { + tcp_connection_list *tcl = &(ss->alloc.tcs); + if(tcl->elems) { + size_t i; + size_t sz = tcl->sz; + for(i=0;ielems[i]) { + tcp_connection *tc = tcl->elems[i]; + if(tc) { + turn_session_info_add_peer(tsi,&(tc->peer_addr)); + } + } + } + } + } + } + + ret = 0; + } + + return ret; +} + +int report_turn_session_info(turn_turnserver *server, ts_ur_super_session *ss, int force_invalid) +{ + if(server && ss && server->send_turn_session_info) { + struct turn_session_info tsi; + turn_session_info_init(&tsi); + if(turn_session_info_copy_from(&tsi,ss)<0) { + turn_session_info_clean(&tsi); + } else { + if(force_invalid) + tsi.valid = 0; + if(server->send_turn_session_info(&tsi)<0) { + turn_session_info_clean(&tsi); + } else { + return 0; + } + } + } + + return -1; +} + +/////////// SS ///////////////// + +static int mobile_id_to_string(mobile_id_t mid, char *dst, size_t dst_sz) +{ + size_t output_length = 0; + + if(!dst) + return -1; + + char *s = base64_encode((const unsigned char *)&mid, + sizeof(mid), + &output_length); + + if(!s) + return -1; + + if(!output_length || (output_length+1 > dst_sz)) { + turn_free(s, output_length); + return -1; + } + + ns_bcopy(s, dst, output_length); + + turn_free(s, output_length); + + dst[output_length] = 0; + + return (int)output_length; +} + +static mobile_id_t string_to_mobile_id(char* src) +{ + mobile_id_t mid = 0; + + if(src) { + + size_t output_length = 0; + + unsigned char *out = base64_decode(src, strlen(src), &output_length); + + if(out) { + + if(output_length == sizeof(mid)) { + mid = *((mobile_id_t*)out); + } + + turn_free(out, output_length); + } + } + + return mid; +} + +static mobile_id_t get_new_mobile_id(turn_turnserver* server) +{ + mobile_id_t newid = 0; + + if(server && server->mobile_connections_map) { + ur_map *map = server->mobile_connections_map; + u64bits sid = server->id; + sid = sid<<56; + do { + while (!newid) { + if(TURN_RANDOM_SIZE == sizeof(mobile_id_t)) + newid = (mobile_id_t)turn_random(); + else { + newid = (mobile_id_t)turn_random(); + newid = (newid<<32) + (mobile_id_t)turn_random(); + } + if(!newid) { + continue; + } + newid = newid & 0x00FFFFFFFFFFFFFFLL; + if(!newid) { + continue; + } + newid = newid | sid; + } + } while(ur_map_get(map, (ur_map_key_type)newid, NULL)); + } + return newid; +} + +static void put_session_into_mobile_map(ts_ur_super_session *ss) +{ + if(ss && ss->server) { + turn_turnserver* server = (turn_turnserver*)(ss->server); + if(*(server->mobility) && server->mobile_connections_map) { + if(!(ss->mobile_id)) { + ss->mobile_id = get_new_mobile_id(server); + mobile_id_to_string(ss->mobile_id, ss->s_mobile_id, sizeof(ss->s_mobile_id)); + } + ur_map_put(server->mobile_connections_map, (ur_map_key_type)(ss->mobile_id), (ur_map_value_type)ss); + } + } + +} + +static void put_session_into_map(ts_ur_super_session *ss) +{ + if(ss && ss->server) { + turn_turnserver* server = (turn_turnserver*)(ss->server); + if(!(ss->id)) { + ss->id = (turnsession_id)((turnsession_id)server->id * 1000000000000000LL); + ss->id += ++(server->session_id_counter); + ss->start_time = server->ctime; + } + ur_map_put(server->sessions_map, (ur_map_key_type)(ss->id), (ur_map_value_type)ss); + put_session_into_mobile_map(ss); + } + +} + +static void delete_session_from_mobile_map(ts_ur_super_session *ss) +{ + if(ss && ss->server && ss->mobile_id) { + turn_turnserver* server = (turn_turnserver*)(ss->server); + if(server->mobile_connections_map) { + ur_map_del(server->mobile_connections_map, (ur_map_key_type)(ss->mobile_id), NULL); + } + ss->mobile_id = 0; + ss->s_mobile_id[0] = 0; + } +} + +static void delete_session_from_map(ts_ur_super_session *ss) +{ + if(ss && ss->server) { + turn_turnserver* server = (turn_turnserver*)(ss->server); + ur_map_del(server->sessions_map, (ur_map_key_type)(ss->id), NULL); + delete_session_from_mobile_map(ss); + } +} + +static ts_ur_super_session* get_session_from_map(turn_turnserver* server, turnsession_id sid) +{ + ts_ur_super_session *ss = NULL; + if(server) { + ur_map_value_type value = 0; + if(ur_map_get(server->sessions_map, (ur_map_key_type)sid, &value) && value) { + ss = (ts_ur_super_session*)value; + } + } + return ss; +} + +static ts_ur_super_session* get_session_from_mobile_map(turn_turnserver* server, mobile_id_t mid) +{ + ts_ur_super_session *ss = NULL; + if(server && *(server->mobility) && server->mobile_connections_map && mid) { + ur_map_value_type value = 0; + if(ur_map_get(server->mobile_connections_map, (ur_map_key_type)mid, &value) && value) { + ss = (ts_ur_super_session*)value; + } + } + return ss; +} + +static ts_ur_super_session* create_new_ss(turn_turnserver* server) { + // + //printf("%s: 111.111: session size=%lu\n",__FUNCTION__,(unsigned long)sizeof(ts_ur_super_session)); + // + ts_ur_super_session *ss = (ts_ur_super_session*)turn_malloc(sizeof(ts_ur_super_session)); + ns_bzero(ss,sizeof(ts_ur_super_session)); + ss->server = server; + get_default_realm_options(&(ss->realm_options)); + put_session_into_map(ss); + init_allocation(ss,&(ss->alloc), server->tcp_relay_connections); + return ss; +} + +static void delete_ur_map_ss(void *p) { + if (p) { + ts_ur_super_session* ss = (ts_ur_super_session*) p; + delete_session_from_map(ss); + clear_ts_ur_session_data(&(ss->client_session)); + clear_allocation(get_allocation_ss(ss)); + IOA_EVENT_DEL(ss->to_be_allocated_timeout_ev); + turn_free(p,sizeof(ts_ur_super_session)); + } +} + +/////////// clean all ///////////////////// + +static int turn_server_remove_all_from_ur_map_ss(ts_ur_super_session* ss) { + if (!ss) + return 0; + else { + int ret = 0; + if (ss->client_session.s) { + clear_ioa_socket_session_if(ss->client_session.s, ss); + } + if (get_relay_socket_ss(ss)) { + clear_ioa_socket_session_if(get_relay_socket_ss(ss), ss); + } + delete_ur_map_ss(ss); + return ret; + } +} + +///////////////////////////////////////////////////////////////// + +static void client_ss_channel_timeout_handler(ioa_engine_handle e, void* arg) { + + UNUSED_ARG(e); + + if (!arg) + return; + + ch_info* chn = (ch_info*) arg; + + turn_channel_delete(chn); +} + +static void client_ss_perm_timeout_handler(ioa_engine_handle e, void* arg) { + + UNUSED_ARG(e); + + if (!arg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: empty permission to be cleaned\n",__FUNCTION__); + return; + } + + turn_permission_info* tinfo = (turn_permission_info*) arg; + + if(!(tinfo->allocated)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: unallocated permission to be cleaned\n",__FUNCTION__); + return; + } + + if(!(tinfo->lifetime_ev)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: strange (1) permission to be cleaned\n",__FUNCTION__); + } + + if(!(tinfo->owner)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: strange (2) permission to be cleaned\n",__FUNCTION__); + } + + turn_permission_clean(tinfo); +} + +/////////////////////////////////////////////////////////////////// + +static int update_turn_permission_lifetime(ts_ur_super_session *ss, turn_permission_info *tinfo, turn_time_t time_delta) { + + if (ss && tinfo && tinfo->owner) { + + turn_turnserver *server = (turn_turnserver *) (ss->server); + + if (server) { + + if(!time_delta) time_delta = STUN_PERMISSION_LIFETIME; + tinfo->expiration_time = server->ctime + time_delta; + + IOA_EVENT_DEL(tinfo->lifetime_ev); + tinfo->lifetime_ev = set_ioa_timer(server->e, time_delta, 0, + client_ss_perm_timeout_handler, tinfo, 0, + "client_ss_channel_timeout_handler"); + + return 0; + } + } + return -1; +} + +static int update_channel_lifetime(ts_ur_super_session *ss, ch_info* chn) +{ + + if (chn) { + + turn_permission_info* tinfo = (turn_permission_info*) (chn->owner); + + if (tinfo && tinfo->owner) { + + turn_turnserver *server = (turn_turnserver *) (ss->server); + + if (server) { + + if (update_turn_permission_lifetime(ss, tinfo, STUN_CHANNEL_LIFETIME) < 0) + return -1; + + chn->expiration_time = server->ctime + STUN_CHANNEL_LIFETIME; + + IOA_EVENT_DEL(chn->lifetime_ev); + chn->lifetime_ev = set_ioa_timer(server->e, STUN_CHANNEL_LIFETIME, 0, + client_ss_channel_timeout_handler, + chn, 0, + "client_ss_channel_timeout_handler"); + + return 0; + } + } + } + return -1; +} + +/////////////// TURN /////////////////////////// + +#define SKIP_ATTRIBUTES case STUN_ATTRIBUTE_PRIORITY: case STUN_ATTRIBUTE_FINGERPRINT: case STUN_ATTRIBUTE_MESSAGE_INTEGRITY: break; \ + case STUN_ATTRIBUTE_USERNAME: case STUN_ATTRIBUTE_REALM: case STUN_ATTRIBUTE_NONCE: case STUN_ATTRIBUTE_ORIGIN: \ + sar = stun_attr_get_next_str(ioa_network_buffer_data(in_buffer->nbh),\ + ioa_network_buffer_get_size(in_buffer->nbh), sar); \ + continue + +static u08bits get_transport_value(const u08bits *value) { + if((value[0] == STUN_ATTRIBUTE_TRANSPORT_UDP_VALUE)|| + (value[0] == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE)) { + return value[0]; + } + return 0; +} + +static int handle_turn_allocate(turn_turnserver *server, + ts_ur_super_session *ss, stun_tid *tid, int *resp_constructed, + int *err_code, const u08bits **reason, u16bits *unknown_attrs, u16bits *ua_num, + ioa_net_data *in_buffer, ioa_network_buffer_handle nbh) { + + allocation* a = get_allocation_ss(ss); + + ts_ur_session* elem = &(ss->client_session); + + if (is_allocation_valid(a)) { + + if (!stun_tid_equals(tid, &(a->tid))) { + *err_code = 437; + *reason = (const u08bits *)"Wrong TID"; + } else { + size_t len = ioa_network_buffer_get_size(nbh); + ioa_addr xor_relayed_addr; + ioa_addr *relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss)); + if(relayed_addr) { + if(server->external_ip_set) { + addr_cpy(&xor_relayed_addr, &(server->external_ip)); + addr_set_port(&xor_relayed_addr,addr_get_port(relayed_addr)); + } else { + addr_cpy(&xor_relayed_addr, relayed_addr); + } + stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, + tid, + &xor_relayed_addr, + get_remote_addr_from_ioa_socket(elem->s), + (a->expiration_time - server->ctime), 0, NULL, 0, + ss->s_mobile_id); + ioa_network_buffer_set_size(nbh,len); + *resp_constructed = 1; + } + } + + } else { + + a = NULL; + + u08bits transport = 0; + u32bits lifetime = 0; + int even_port = -1; + int dont_fragment = 0; + u64bits in_reservation_token = 0; + int af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT; + u08bits username[STUN_MAX_USERNAME_SIZE+1]="\0"; + size_t ulen = 0; + + stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh)); + while (sar && (!(*err_code)) && (*ua_num < MAX_NUMBER_OF_UNKNOWN_ATTRS)) { + + int attr_type = stun_attr_get_type(sar); + + if(attr_type == STUN_ATTRIBUTE_USERNAME) { + const u08bits* value = stun_attr_get_value(sar); + if (value) { + ulen = stun_attr_get_len(sar); + if(ulen>=sizeof(username)) { + *err_code = 400; + *reason = (const u08bits *)"User name is too long"; + break; + } + ns_bcopy(value,username,ulen); + username[ulen]=0; + } + } + + switch (attr_type) { + SKIP_ATTRIBUTES; + case STUN_ATTRIBUTE_MOBILITY_TICKET: + if(!(*(server->mobility))) { + *err_code = 501; + *reason = (const u08bits *)"Mobility Forbidden"; + } else if (stun_attr_get_len(sar) != 0) { + *err_code = 400; + *reason = (const u08bits *)"Wrong Mobility Field"; + } else { + ss->is_mobile = 1; + } + break; + case STUN_ATTRIBUTE_REQUESTED_TRANSPORT: { + if (stun_attr_get_len(sar) != 4) { + *err_code = 400; + *reason = (const u08bits *)"Wrong Transport Field"; + } else if(transport) { + *err_code = 400; + *reason = (const u08bits *)"Duplicate Transport Fields"; + } else { + const u08bits* value = stun_attr_get_value(sar); + if (value) { + transport = get_transport_value(value); + if (!transport || value[1] || value[2] || value[3]) { + *err_code = 442; + *reason = (const u08bits *)"Unsupported Transport Protocol"; + } + if((transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) && *(server->no_tcp_relay)) { + *err_code = 403; + *reason = (const u08bits *)"TCP Transport is not allowed by the TURN Server configuration"; + } else if((transport == STUN_ATTRIBUTE_TRANSPORT_UDP_VALUE) && *(server->no_udp_relay)) { + *err_code = 403; + *reason = (const u08bits *)"UDP Transport is not allowed by the TURN Server configuration"; + } else if(ss->client_session.s) { + SOCKET_TYPE cst = get_ioa_socket_type(ss->client_session.s); + if((transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) && + (cst!=TCP_SOCKET) && (cst!=TLS_SOCKET)) { + *err_code = 400; + *reason = (const u08bits *)"Wrong Transport Data"; + } else { + ss->is_tcp_relay = (transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE); + } + } + } else { + *err_code = 400; + *reason = (const u08bits *)"Wrong Transport Data"; + } + } + } + break; + case STUN_ATTRIBUTE_DONT_FRAGMENT: + dont_fragment = 1; + if(!(server->dont_fragment)) + unknown_attrs[(*ua_num)++] = nswap16(attr_type); + break; + case STUN_ATTRIBUTE_LIFETIME: { + if (stun_attr_get_len(sar) != 4) { + *err_code = 400; + *reason = (const u08bits *)"Wrong Lifetime Field"; + } else { + const u08bits* value = stun_attr_get_value(sar); + if (!value) { + *err_code = 400; + *reason = (const u08bits *)"Wrong Lifetime Data"; + } else { + lifetime = nswap32(*((const u32bits*)value)); + } + } + } + break; + case STUN_ATTRIBUTE_EVEN_PORT: { + if (in_reservation_token) { + *err_code = 400; + *reason = (const u08bits *)"Even Port and Reservation Token cannot be used together"; + } else if (even_port >= 0) { + *err_code = 400; + *reason = (const u08bits *)"Even Port cannot be used in this request"; + } else { + even_port = stun_attr_get_even_port(sar); + } + } + break; + case STUN_ATTRIBUTE_RESERVATION_TOKEN: { + int len = stun_attr_get_len(sar); + if (len != 8) { + *err_code = 400; + *reason = (const u08bits *)"Wrong Format of Reservation Token"; + } else if(af != STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT) { + *err_code = 400; + *reason = (const u08bits *)"Address family attribute can not be used with reservation token request"; + } else { + if (even_port >= 0) { + *err_code = 400; + *reason = (const u08bits *)"Reservation Token cannot be used in this request with even port"; + } else if (in_reservation_token) { + *err_code = 400; + *reason = (const u08bits *)"Reservation Token cannot be used in this request"; + } else { + in_reservation_token = stun_attr_get_reservation_token_value(sar); + } + } + } + break; + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY: { + if(in_reservation_token) { + *err_code = 400; + *reason = (const u08bits *)"Address family attribute can not be used with reservation token request"; + } else { + int af_req = stun_get_requested_address_family(sar); + if(af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT) { + switch (af_req) { + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: + af = af_req; + break; + default: + *err_code = 440; + *reason = (const u08bits *)"Unsupported address family requested"; + } + } else { + *err_code = 400; + *reason = (const u08bits *)"Only one address family attribute can be used in a request"; + } + } + } + break; + default: + if(attr_type>=0x0000 && attr_type<=0x7FFF) + unknown_attrs[(*ua_num)++] = nswap16(attr_type); + }; + sar = stun_attr_get_next_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + sar); + } + + if (!transport) { + + *err_code = 400; + if(!(*reason)) + *reason = (const u08bits *)"Transport field missed or wrong"; + + } else if (*ua_num > 0) { + + *err_code = 420; + if(!(*reason)) + *reason = (const u08bits *)"Unknown attribute"; + + } else if (*err_code) { + + ; + + } else if((transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) && (dont_fragment || in_reservation_token || (even_port!=-1))) { + + *err_code = 400; + if(!(*reason)) + *reason = (const u08bits *)"Request parameters are incompatible with TCP transport"; + + } else { + + if(*(server->mobility)) { + if(!(ss->is_mobile)) { + delete_session_from_mobile_map(ss); + } + } + + lifetime = stun_adjust_allocate_lifetime(lifetime); + u64bits out_reservation_token = 0; + + if(inc_quota(ss, username)<0) { + + *err_code = 486; + *reason = (const u08bits *)"Allocation Quota Reached"; + + } else { + + if (create_relay_connection(server, ss, lifetime, + af, transport, + even_port, in_reservation_token, &out_reservation_token, + err_code, reason, + tcp_peer_accept_connection) < 0) { + + dec_quota(ss); + + if (!*err_code) { + *err_code = 437; + if(!(*reason)) + *reason = (const u08bits *)"Cannot create relay endpoint"; + } + + } else { + + a = get_allocation_ss(ss); + + set_allocation_valid(a,1); + + stun_tid_cpy(&(a->tid), tid); + + size_t len = ioa_network_buffer_get_size(nbh); + + ioa_addr xor_relayed_addr; + ioa_addr *relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss)); + if(relayed_addr) { + if(server->external_ip_set) { + addr_cpy(&xor_relayed_addr, &(server->external_ip)); + addr_set_port(&xor_relayed_addr,addr_get_port(relayed_addr)); + } else { + addr_cpy(&xor_relayed_addr, relayed_addr); + } + + stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid, + &xor_relayed_addr, + get_remote_addr_from_ioa_socket(elem->s), lifetime, + 0,NULL, + out_reservation_token, + ss->s_mobile_id); + ioa_network_buffer_set_size(nbh,len); + *resp_constructed = 1; + + turn_report_allocation_set(&(ss->alloc), lifetime, 0); + } + } + } + } + } + + if (!(*resp_constructed)) { + + if (!(*err_code)) { + *err_code = 437; + } + + size_t len = ioa_network_buffer_get_size(nbh); + stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid, NULL, NULL, 0, *err_code, *reason, 0, ss->s_mobile_id); + ioa_network_buffer_set_size(nbh,len); + *resp_constructed = 1; + } + + return 0; +} + +static int handle_turn_refresh(turn_turnserver *server, + ts_ur_super_session *ss, stun_tid *tid, int *resp_constructed, + int *err_code, const u08bits **reason, u16bits *unknown_attrs, u16bits *ua_num, + ioa_net_data *in_buffer, ioa_network_buffer_handle nbh, + int message_integrity, int *no_response, int can_resume) { + + allocation* a = get_allocation_ss(ss); + + if (!is_allocation_valid(a) && !(*(server->mobility))) { + + *err_code = 437; + *reason = (const u08bits *)"Invalid allocation"; + + } else { + + u32bits lifetime = 0; + int to_delete = 0; + mobile_id_t mid = 0; + char smid[sizeof(ss->s_mobile_id)] = "\0"; + + stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh)); + while (sar && (!(*err_code)) && (*ua_num < MAX_NUMBER_OF_UNKNOWN_ATTRS)) { + int attr_type = stun_attr_get_type(sar); + switch (attr_type) { + SKIP_ATTRIBUTES; + case STUN_ATTRIBUTE_MOBILITY_TICKET: { + if(!(*(server->mobility))) { + *err_code = 501; + *reason = (const u08bits *)"Mobility forbidden"; + } if(is_allocation_valid(a)) { + *err_code = 400; + *reason = (const u08bits *)"Mobility ticket cannot be used for a stable, already established allocation"; + } else { + int smid_len = stun_attr_get_len(sar); + if(smid_len>0 && (((size_t)smid_len)relay_session.s); + if(addr) { + int is_err = 0; + switch (af_req) { + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: + if(addr->ss.sa_family != AF_INET) { + is_err = 1; + } + break; + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: + if(addr->ss.sa_family != AF_INET6) { + is_err = 1; + } + break; + default: + is_err = 1; + } + + if(is_err) { + *err_code = 443; + *reason = (const u08bits *)"Peer Address Family Mismatch"; + } + } + } + break; + default: + if(attr_type>=0x0000 && attr_type<=0x7FFF) + unknown_attrs[(*ua_num)++] = nswap16(attr_type); + }; + sar = stun_attr_get_next_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), sar); + } + + if (*ua_num > 0) { + + *err_code = 420; + *reason = (const u08bits *)"Unknown attribute"; + + } else if (*err_code) { + + ; + + } else if(!is_allocation_valid(a)) { + + if(mid && smid[0]) { + + turnserver_id tsid = ((0xFF00000000000000LL) & mid)>>56; + + if(tsid != server->id) { + + if(server->send_socket_to_relay) { + ioa_socket_handle new_s = detach_ioa_socket(ss->client_session.s, 1); + if(new_s) { + if(server->send_socket_to_relay(tsid, mid, tid, new_s, message_integrity, + RMT_MOBILE_SOCKET, in_buffer)<0) { + *err_code = 400; + *reason = (const u08bits *)"Wrong mobile ticket"; + } else { + *no_response = 1; + } + } else { + *err_code = 500; + *reason = (const u08bits *)"Cannot create new socket"; + return -1; + } + } else { + *err_code = 500; + *reason = (const u08bits *)"Server send socket procedure is not set"; + } + + ss->to_be_closed = 1; + + } else { + + ts_ur_super_session *orig_ss = get_session_from_mobile_map(server, mid); + if(!orig_ss) { + *err_code = 404; + *reason = (const u08bits *)"Allocation not found"; + } else if(orig_ss == ss) { + *err_code = 437; + *reason = (const u08bits *)"Invalid allocation"; + } else if(!(orig_ss->is_mobile)) { + *err_code = 500; + *reason = (const u08bits *)"Software error: invalid mobile allocation"; + } else if(orig_ss->client_session.s == ss->client_session.s) { + *err_code = 500; + *reason = (const u08bits *)"Software error: invalid mobile client socket (orig)"; + } else if(!(ss->client_session.s)) { + *err_code = 500; + *reason = (const u08bits *)"Software error: invalid mobile client socket (new)"; + } else { + + get_realm_options_by_name(orig_ss->realm_options.name, &(ss->realm_options)); + + //Check security: + int postpone_reply = 0; + check_stun_auth(server, orig_ss, tid, resp_constructed, err_code, reason, in_buffer, nbh, + STUN_METHOD_REFRESH, &message_integrity, &postpone_reply, can_resume); + + if(postpone_reply) { + + *no_response = 1; + + } else if(!(*err_code)) { + + //Session transfer: + + if (to_delete) + lifetime = 0; + else + lifetime = stun_adjust_allocate_lifetime(lifetime); + + if (refresh_relay_connection(server, orig_ss, lifetime, 0, 0, 0, + err_code) < 0) { + + if (!(*err_code)) { + *err_code = 437; + *reason = (const u08bits *)"Cannot refresh relay connection (internal error)"; + } + + } else if(!to_delete && orig_ss && (inc_quota(orig_ss, orig_ss->username)<0)) { + + *err_code = 486; + *reason = (const u08bits *)"Allocation Quota Reached"; + + } else { + + //Transfer socket: + + ioa_socket_handle s = detach_ioa_socket(ss->client_session.s, 0); + + ss->to_be_closed = 1; + + if(!s) { + dec_quota(orig_ss); + *err_code = 500; + } else { + + if(attach_socket_to_session(server, s, orig_ss) < 0) { + IOA_CLOSE_SOCKET(s); + *err_code = 500; + dec_quota(orig_ss); + } else { + + delete_session_from_mobile_map(ss); + delete_session_from_mobile_map(orig_ss); + put_session_into_mobile_map(orig_ss); + + //Use new buffer and redefine ss: + nbh = ioa_network_buffer_allocate(server->e); + ss = orig_ss; + size_t len = ioa_network_buffer_get_size(nbh); + + turn_report_allocation_set(&(ss->alloc), lifetime, 1); + + stun_init_success_response_str(STUN_METHOD_REFRESH, ioa_network_buffer_data(nbh), &len, tid); + u32bits lt = nswap32(lifetime); + + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_LIFETIME, + (const u08bits*) <, 4); + ioa_network_buffer_set_size(nbh,len); + + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, + STUN_ATTRIBUTE_MOBILITY_TICKET, + (u08bits*)ss->s_mobile_id,strlen(ss->s_mobile_id)); + ioa_network_buffer_set_size(nbh,len); + + { + static const u08bits *field = (const u08bits *) TURN_SOFTWARE; + static const size_t fsz = sizeof(TURN_SOFTWARE)-1; + size_t len = ioa_network_buffer_get_size(nbh); + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz); + ioa_network_buffer_set_size(nbh, len); + } + + if(message_integrity) { + 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) { + if (stun_attr_add_fingerprint_str(ioa_network_buffer_data(nbh), &len) < 0) { + dec_quota(ss); + *err_code = 500; + ioa_network_buffer_delete(server->e, nbh); + return -1; + } + ioa_network_buffer_set_size(nbh, len); + } + + *no_response = 1; + + return write_client_connection(server, ss, nbh, TTL_IGNORE, TOS_IGNORE); + } + } + } + } + + report_turn_session_info(server,orig_ss,0); + } + } + } else { + *err_code = 437; + *reason = (const u08bits *)"Invalid allocation"; + } + + } else { + + if (to_delete) + lifetime = 0; + else + lifetime = stun_adjust_allocate_lifetime(lifetime); + + if (refresh_relay_connection(server, ss, lifetime, 0, 0, 0, + err_code) < 0) { + + if (!(*err_code)) { + *err_code = 437; + *reason = (const u08bits *)"Cannot refresh relay connection (internal error)"; + } + + } else { + + turn_report_allocation_set(&(ss->alloc), lifetime, 1); + + size_t len = ioa_network_buffer_get_size(nbh); + stun_init_success_response_str(STUN_METHOD_REFRESH, ioa_network_buffer_data(nbh), &len, tid); + u32bits lt = nswap32(lifetime); + + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_LIFETIME, + (const u08bits*) <, 4); + ioa_network_buffer_set_size(nbh,len); + + *resp_constructed = 1; + } + } + } + + if(!no_response) { + if (!(*resp_constructed)) { + + if (!(*err_code)) { + *err_code = 437; + } + + size_t len = ioa_network_buffer_get_size(nbh); + stun_init_error_response_str(STUN_METHOD_REFRESH, ioa_network_buffer_data(nbh), &len, *err_code, *reason, tid); + ioa_network_buffer_set_size(nbh,len); + + *resp_constructed = 1; + } + } + + return 0; +} + +/* RFC 6062 ==>> */ + +static void tcp_deliver_delayed_buffer(unsent_buffer *ub, ioa_socket_handle s, ts_ur_super_session *ss) +{ + if(ub && s && ub->bufs && ub->sz && ss) { + size_t i = 0; + do { + ioa_network_buffer_handle nbh = top_unsent_buffer(ub); + if(!nbh) + break; + + u32bits bytes = (u32bits)ioa_network_buffer_get_size(nbh); + + int ret = send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE); + if (ret < 0) { + set_ioa_socket_tobeclosed(s); + } else { + ++(ss->sent_packets); + ss->sent_bytes += bytes; + turn_report_session_usage(ss); + } + pop_unsent_buffer(ub); + } while(!ioa_socket_tobeclosed(s) && ((i++)owner; + if(a) { + ss=(ts_ur_super_session*)a->owner; + } + + if((tc->state != TC_STATE_READY) || !(tc->client_s)) { + add_unsent_buffer(&(tc->ub_to_client), in_buffer->nbh); + in_buffer->nbh = NULL; + return; + } + + ioa_network_buffer_handle nbh = in_buffer->nbh; + in_buffer->nbh = NULL; + + u32bits bytes = (u32bits)ioa_network_buffer_get_size(nbh); + + int ret = send_data_from_ioa_socket_nbh(tc->client_s, NULL, nbh, TTL_IGNORE, TOS_IGNORE); + if (ret < 0) { + set_ioa_socket_tobeclosed(s); + } else if(ss) { + ++(ss->sent_packets); + ss->sent_bytes += bytes; + turn_report_session_usage(ss); + } +} + +static void tcp_client_input_handler_rfc6062data(ioa_socket_handle s, int event_type, ioa_net_data *in_buffer, void *arg) +{ + if (!(event_type & IOA_EV_READ) || !arg) + return; + + UNUSED_ARG(s); + + tcp_connection *tc = (tcp_connection*)arg; + ts_ur_super_session *ss=NULL; + allocation *a=(allocation*)tc->owner; + if(a) { + ss=(ts_ur_super_session*)a->owner; + } + + if(tc->state != TC_STATE_READY) + return; + + if(!(tc->peer_s)) + return; + + ioa_network_buffer_handle nbh = in_buffer->nbh; + in_buffer->nbh = NULL; + + if(ss) { + u32bits bytes = (u32bits)ioa_network_buffer_get_size(nbh); + ++(ss->received_packets); + ss->received_bytes += bytes; + } + + int ret = send_data_from_ioa_socket_nbh(tc->peer_s, NULL, nbh, TTL_IGNORE, TOS_IGNORE); + if (ret < 0) { + set_ioa_socket_tobeclosed(s); + } + + turn_report_session_usage(ss); +} + +static void tcp_conn_bind_timeout_handler(ioa_engine_handle e, void *arg) +{ + UNUSED_ARG(e); + if(arg) { + tcp_connection *tc = (tcp_connection *)arg; + delete_tcp_connection(tc); + } +} + +static void tcp_peer_connection_completed_callback(int success, void *arg) +{ + if(arg) { + tcp_connection *tc = (tcp_connection *)arg; + allocation *a = (allocation*)(tc->owner); + ts_ur_super_session *ss = (ts_ur_super_session*)(a->owner); + turn_turnserver *server=(turn_turnserver*)(ss->server); + int err_code = 0; + + IOA_EVENT_DEL(tc->peer_conn_timeout); + + ioa_network_buffer_handle nbh = ioa_network_buffer_allocate(server->e); + size_t len = ioa_network_buffer_get_size(nbh); + + if(success) { + if(register_callback_on_ioa_socket(server->e, tc->peer_s, IOA_EV_READ, tcp_peer_input_handler, tc, 1)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: cannot set TCP peer data input callback\n", __FUNCTION__); + success=0; + err_code = 500; + } + } + + if(success) { + tc->state = TC_STATE_PEER_CONNECTED; + stun_init_success_response_str(STUN_METHOD_CONNECT, ioa_network_buffer_data(nbh), &len, &(tc->tid)); + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_CONNECTION_ID, + (const u08bits*)&(tc->id), 4); + + IOA_EVENT_DEL(tc->conn_bind_timeout); + tc->conn_bind_timeout = set_ioa_timer(server->e, TCP_CONN_BIND_TIMEOUT, 0, + tcp_conn_bind_timeout_handler, tc, 0, + "tcp_conn_bind_timeout_handler"); + + } else { + tc->state = TC_STATE_FAILED; + if(!err_code) + err_code = 447; + const u08bits *reason = (const u08bits *)"Connection Timeout or Failure"; + stun_init_error_response_str(STUN_METHOD_CONNECT, ioa_network_buffer_data(nbh), &len, err_code, reason, &(tc->tid)); + } + + ioa_network_buffer_set_size(nbh,len); + + if(need_stun_authentication(server, ss)) { + 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); + } + + write_client_connection(server, ss, nbh, TTL_IGNORE, TOS_IGNORE); + + if(!success) { + delete_tcp_connection(tc); + } + /* test */ + else if(0) + { + int i = 0; + for(i=0;i<22;i++) { + ioa_network_buffer_handle nbh_test = ioa_network_buffer_allocate(server->e); + size_t len_test = ioa_network_buffer_get_size(nbh_test); + u08bits *data = ioa_network_buffer_data(nbh_test); + const char* data_test="111.111.111.111.111"; + len_test = strlen(data_test); + ns_bcopy(data_test,data,len_test); + ioa_network_buffer_set_size(nbh_test,len_test); + send_data_from_ioa_socket_nbh(tc->peer_s, NULL, nbh_test, TTL_IGNORE, TOS_IGNORE); + } + } + } +} + +static void tcp_peer_conn_timeout_handler(ioa_engine_handle e, void *arg) +{ + UNUSED_ARG(e); + + tcp_peer_connection_completed_callback(0,arg); +} + +static int tcp_start_connection_to_peer(turn_turnserver *server, ts_ur_super_session *ss, stun_tid *tid, + allocation *a, ioa_addr *peer_addr, + int *err_code, const u08bits **reason) +{ + FUNCSTART; + + if(!ss) { + *err_code = 500; + *reason = (const u08bits *)"Server error: empty session"; + FUNCEND; + return -1; + } + + if(!(a->relay_session.s)) { + *err_code = 500; + *reason = (const u08bits *)"Server error: no relay connection created"; + FUNCEND; + return -1; + } + + tcp_connection *tc = get_tcp_connection_by_peer(a, peer_addr); + if(tc) { + *err_code = 446; + *reason = (const u08bits *)"Connection Already Exists"; + FUNCEND; + return -1; + } + + tc = create_tcp_connection(server->id, a, tid, peer_addr, err_code); + if(!tc) { + if(!(*err_code)) { + *err_code = 500; + *reason = (const u08bits *)"Server error: TCP connection object creation failed"; + } + FUNCEND; + return -1; + } else if(*err_code) { + delete_tcp_connection(tc); + FUNCEND; + return -1; + } + + IOA_EVENT_DEL(tc->peer_conn_timeout); + tc->peer_conn_timeout = set_ioa_timer(server->e, TCP_PEER_CONN_TIMEOUT, 0, + tcp_peer_conn_timeout_handler, tc, 0, + "tcp_peer_conn_timeout_handler"); + + ioa_socket_handle tcs = ioa_create_connecting_tcp_relay_socket(a->relay_session.s, peer_addr, tcp_peer_connection_completed_callback, tc); + if(!tcs) { + delete_tcp_connection(tc); + *err_code = 500; + *reason = (const u08bits *)"Server error: TCP relay socket for connection cannot be created"; + FUNCEND; + return -1; + } + + tc->state = TC_STATE_CLIENT_TO_PEER_CONNECTING; + IOA_CLOSE_SOCKET(tc->peer_s); + tc->peer_s = tcs; + set_ioa_socket_sub_session(tc->peer_s,tc); + + FUNCEND; + return 0; +} + +static void tcp_peer_accept_connection(ioa_socket_handle s, void *arg) +{ + if(s) { + + if(!arg) { + close_ioa_socket(s); + return; + } + + ts_ur_super_session *ss = (ts_ur_super_session*)arg; + turn_turnserver *server=(turn_turnserver*)(ss->server); + + FUNCSTART; + + allocation *a = &(ss->alloc); + ioa_addr *peer_addr = get_remote_addr_from_ioa_socket(s); + + tcp_connection *tc = get_tcp_connection_by_peer(a, peer_addr); + if(tc) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: peer data socket with this address already exist\n", __FUNCTION__); + if(tc->peer_s != s) + close_ioa_socket(s); + FUNCEND; + return; + } + + if(!good_peer_addr(server, peer_addr)) { + u08bits saddr[256]; + addr_to_string(peer_addr, saddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: an attempt to connect from a peer with forbidden address: %s\n", __FUNCTION__,saddr); + close_ioa_socket(s); + FUNCEND; + return; + } + + if(!can_accept_tcp_connection_from_peer(a,peer_addr,server->server_relay)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: peer has no permission to connect\n", __FUNCTION__); + close_ioa_socket(s); + FUNCEND; + return; + } + + stun_tid tid; + ns_bzero(&tid,sizeof(stun_tid)); + int err_code=0; + tc = create_tcp_connection(server->id, a, &tid, peer_addr, &err_code); + if(!tc) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: cannot create TCP connection\n", __FUNCTION__); + close_ioa_socket(s); + FUNCEND; + return; + } + + tc->state = TC_STATE_PEER_CONNECTED; + tc->peer_s = s; + + set_ioa_socket_session(s,ss); + set_ioa_socket_sub_session(s,tc); + + if(register_callback_on_ioa_socket(server->e, s, IOA_EV_READ, tcp_peer_input_handler, tc, 1)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: cannot set TCP peer data input callback\n", __FUNCTION__); + close_ioa_socket(s); + tc->peer_s = NULL; + tc->state = TC_STATE_UNKNOWN; + FUNCEND; + return; + } + + IOA_EVENT_DEL(tc->conn_bind_timeout); + tc->conn_bind_timeout = set_ioa_timer(server->e, TCP_CONN_BIND_TIMEOUT, 0, + tcp_conn_bind_timeout_handler, tc, 0, + "tcp_conn_bind_timeout_handler"); + + ioa_network_buffer_handle nbh = ioa_network_buffer_allocate(server->e); + size_t len = ioa_network_buffer_get_size(nbh); + + stun_init_indication_str(STUN_METHOD_CONNECTION_ATTEMPT, ioa_network_buffer_data(nbh), &len); + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_CONNECTION_ID, + (const u08bits*)&(tc->id), 4); + stun_attr_add_addr_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, peer_addr); + + ioa_network_buffer_set_size(nbh,len); + + { + static const u08bits *field = (const u08bits *) TURN_SOFTWARE; + static const size_t fsz = sizeof(TURN_SOFTWARE)-1; + size_t len = ioa_network_buffer_get_size(nbh); + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz); + 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); + ioa_network_buffer_set_size(nbh, len); + } + + write_client_connection(server, ss, nbh, TTL_IGNORE, TOS_IGNORE); + + FUNCEND; + } +} + +static int handle_turn_connect(turn_turnserver *server, + ts_ur_super_session *ss, stun_tid *tid, + int *err_code, const u08bits **reason, u16bits *unknown_attrs, u16bits *ua_num, + ioa_net_data *in_buffer) { + + FUNCSTART; + ioa_addr peer_addr; + int peer_found = 0; + addr_set_any(&peer_addr); + allocation* a = get_allocation_ss(ss); + + if(!(ss->is_tcp_relay)) { + *err_code = 403; + *reason = (const u08bits *)"Connect cannot be used with UDP relay"; + } else if (!is_allocation_valid(a)) { + *err_code = 437; + *reason = (const u08bits *)"Allocation mismatch"; + } else { + + stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh)); + while (sar && (!(*err_code)) && (*ua_num < MAX_NUMBER_OF_UNKNOWN_ATTRS)) { + int attr_type = stun_attr_get_type(sar); + switch (attr_type) { + SKIP_ATTRIBUTES; + case STUN_ATTRIBUTE_XOR_PEER_ADDRESS: + { + if(stun_attr_get_addr_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + sar, &peer_addr, + &(ss->default_peer_addr)) == -1) { + *err_code = 400; + *reason = (const u08bits *)"Bad Peer Address"; + } else { + ioa_addr *relay_addr = get_local_addr_from_ioa_socket(a->relay_session.s); + + if(relay_addr && (relay_addr->ss.sa_family != peer_addr.ss.sa_family)) { + *err_code = 443; + *reason = (const u08bits *)"Peer Address Family Mismatch"; + } + + peer_found = 1; + } + break; + } + default: + if(attr_type>=0x0000 && attr_type<=0x7FFF) + unknown_attrs[(*ua_num)++] = nswap16(attr_type); + }; + sar = stun_attr_get_next_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + sar); + } + + if (*ua_num > 0) { + + *err_code = 420; + *reason = (const u08bits *)"Unknown attribute"; + + } else if (*err_code) { + + ; + + } else if (!peer_found) { + + *err_code = 400; + *reason = (const u08bits *)"Where is Peer Address ?"; + + } else { + if(!good_peer_addr(server,&peer_addr)) { + *err_code = 403; + *reason = (const u08bits *) "Forbidden IP"; + } else { + tcp_start_connection_to_peer(server, ss, tid, a, &peer_addr, err_code, reason); + } + } + } + + FUNCEND; + return 0; +} + +static int handle_turn_connection_bind(turn_turnserver *server, + ts_ur_super_session *ss, stun_tid *tid, int *resp_constructed, + int *err_code, const u08bits **reason, u16bits *unknown_attrs, u16bits *ua_num, + ioa_net_data *in_buffer, ioa_network_buffer_handle nbh, int message_integrity) { + + allocation* a = get_allocation_ss(ss); + + u16bits method = STUN_METHOD_CONNECTION_BIND; + + if (is_allocation_valid(a)) { + + *err_code = 400; + *reason = (const u08bits *)"Bad request: CONNECTION_BIND cannot be issued after allocation"; + + } else if((get_ioa_socket_type(ss->client_session.s)!=TCP_SOCKET) && (get_ioa_socket_type(ss->client_session.s)!=TLS_SOCKET)) { + + *err_code = 400; + *reason = (const u08bits *)"Bad request: CONNECTION_BIND only possible with TCP/TLS"; + + } else { + tcp_connection_id id = 0; + + stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh)); + while (sar && (!(*err_code)) && (*ua_num < MAX_NUMBER_OF_UNKNOWN_ATTRS)) { + int attr_type = stun_attr_get_type(sar); + switch (attr_type) { + SKIP_ATTRIBUTES; + case STUN_ATTRIBUTE_CONNECTION_ID: { + if (stun_attr_get_len(sar) != 4) { + *err_code = 400; + *reason = (const u08bits *)"Wrong Connection ID field format"; + } else { + const u08bits* value = stun_attr_get_value(sar); + if (!value) { + *err_code = 400; + *reason = (const u08bits *)"Wrong Connection ID field data"; + } else { + id = *((const u32bits*)value); //AS-IS encoding, no conversion to/from network byte order + } + } + } + break; + default: + if(attr_type>=0x0000 && attr_type<=0x7FFF) + unknown_attrs[(*ua_num)++] = nswap16(attr_type); + }; + sar = stun_attr_get_next_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), sar); + } + + if (*ua_num > 0) { + + *err_code = 420; + *reason = (const u08bits *)"Unknown attribute"; + + } else if (*err_code) { + + ; + + } else { + if(server->send_socket_to_relay) { + turnserver_id sid = (id & 0xFF000000)>>24; + ioa_socket_handle s = ss->client_session.s; + if(s) { + ioa_socket_handle new_s = detach_ioa_socket(s, 1); + if(new_s) { + if(server->send_socket_to_relay(sid, id, tid, new_s, message_integrity, RMT_CB_SOCKET, NULL)<0) { + *err_code = 400; + *reason = (const u08bits *)"Wrong connection id"; + } + } else { + *err_code = 500; + } + } else { + *err_code = 500; + } + } else { + *err_code = 500; + } + ss->to_be_closed = 1; + } + } + + if (!(*resp_constructed) && ss->client_session.s && !ioa_socket_tobeclosed(ss->client_session.s)) { + + if (!(*err_code)) { + *err_code = 437; + } + + size_t len = ioa_network_buffer_get_size(nbh); + stun_init_error_response_str(method, ioa_network_buffer_data(nbh), &len, *err_code, *reason, tid); + ioa_network_buffer_set_size(nbh,len); + + *resp_constructed = 1; + } + + return 0; +} + +int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_connection_id tcid, stun_tid *tid, ioa_socket_handle s, int message_integrity) +{ + if(!server) + return -1; + + FUNCSTART; + + tcp_connection *tc = NULL; + ts_ur_super_session *ss = NULL; + + int err_code = 0; + + if(tcid && tid && s) { + + tc = get_and_clean_tcp_connection_by_id(server->tcp_relay_connections, tcid); + if(!tc || (tc->state == TC_STATE_READY) || (tc->client_s)) { + err_code = 400; + } else { + allocation *a = (allocation*)(tc->owner); + if(!a || !(a->owner)) { + err_code = 500; + } else { + ss = (ts_ur_super_session*)(a->owner); + if(!check_username_hash(s,ss->username,(u08bits*)ss->realm_options.name)) { + err_code = 401; + } else { + tc->state = TC_STATE_READY; + tc->client_s = s; + set_ioa_socket_session(s,ss); + set_ioa_socket_sub_session(s,tc); + set_ioa_socket_app_type(s,TCP_CLIENT_DATA_SOCKET); + if(register_callback_on_ioa_socket(server->e, s, IOA_EV_READ, tcp_client_input_handler_rfc6062data, tc, 1)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: cannot set TCP client data input callback\n", __FUNCTION__); + err_code = 500; + } else { + IOA_EVENT_DEL(tc->conn_bind_timeout); + } + } + } + } + + ioa_network_buffer_handle nbh = ioa_network_buffer_allocate(server->e); + + if(!err_code) { + size_t len = ioa_network_buffer_get_size(nbh); + stun_init_success_response_str(STUN_METHOD_CONNECTION_BIND, ioa_network_buffer_data(nbh), &len, tid); + ioa_network_buffer_set_size(nbh,len); + } else { + size_t len = ioa_network_buffer_get_size(nbh); + stun_init_error_response_str(STUN_METHOD_CONNECTION_BIND, ioa_network_buffer_data(nbh), &len, err_code, NULL, tid); + ioa_network_buffer_set_size(nbh,len); + } + + { + static const u08bits *field = (const u08bits *) TURN_SOFTWARE; + static const size_t fsz = sizeof(TURN_SOFTWARE)-1; + size_t len = ioa_network_buffer_get_size(nbh); + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz); + ioa_network_buffer_set_size(nbh, len); + } + + if(message_integrity && ss) { + size_t len = ioa_network_buffer_get_size(nbh); + 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 &&(ss->enforce_fingerprints))) { + size_t len = ioa_network_buffer_get_size(nbh); + stun_attr_add_fingerprint_str(ioa_network_buffer_data(nbh), &len); + ioa_network_buffer_set_size(nbh, len); + } + + if(ss && !err_code) { + send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE); + tcp_deliver_delayed_buffer(&(tc->ub_to_client),s,ss); + FUNCEND; + return 0; + } else { + /* Just to set the necessary structures for the packet sending: */ + if(register_callback_on_ioa_socket(server->e, s, IOA_EV_READ, NULL, NULL, 1)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: cannot set TCP tmp client data input callback\n", __FUNCTION__); + ioa_network_buffer_delete(server->e, nbh); + } else { + send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE); + } + } + } + + if(s) { + if(tc && (s==tc->client_s)) { + ; + } else { + close_ioa_socket(s); + } + } + + FUNCEND; + return -1; +} + +/* <<== RFC 6062 */ + +static int handle_turn_channel_bind(turn_turnserver *server, + ts_ur_super_session *ss, stun_tid *tid, int *resp_constructed, + int *err_code, const u08bits **reason, u16bits *unknown_attrs, u16bits *ua_num, + ioa_net_data *in_buffer, ioa_network_buffer_handle nbh) { + + FUNCSTART; + u16bits chnum = 0; + ioa_addr peer_addr; + addr_set_any(&peer_addr); + allocation* a = get_allocation_ss(ss); + int addr_found = 0; + + if(ss->is_tcp_relay) { + *err_code = 403; + *reason = (const u08bits *)"Channel bind cannot be used with TCP relay"; + } else if (is_allocation_valid(a)) { + + stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh)); + while (sar && (!(*err_code)) && (*ua_num < MAX_NUMBER_OF_UNKNOWN_ATTRS)) { + int attr_type = stun_attr_get_type(sar); + switch (attr_type) { + SKIP_ATTRIBUTES; + case STUN_ATTRIBUTE_CHANNEL_NUMBER: { + if (chnum) { + chnum = 0; + *err_code = 400; + *reason = (const u08bits *)"Channel number cannot be duplicated in this request"; + break; + } + chnum = stun_attr_get_channel_number(sar); + if (!chnum) { + *err_code = 400; + *reason = (const u08bits *)"Channel number cannot be zero in this request"; + break; + } + } + break; + case STUN_ATTRIBUTE_XOR_PEER_ADDRESS: + { + stun_attr_get_addr_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + sar, &peer_addr, + &(ss->default_peer_addr)); + + ioa_addr *relay_addr = get_local_addr_from_ioa_socket(a->relay_session.s); + + if(relay_addr && relay_addr->ss.sa_family != peer_addr.ss.sa_family) { + *err_code = 443; + *reason = (const u08bits *)"Peer Address Family Mismatch"; + } + + if(addr_get_port(&peer_addr) < 1) { + *err_code = 400; + *reason = (const u08bits *)"Empty port number in channel bind request"; + } else { + addr_found = 1; + } + + break; + } + default: + if(attr_type>=0x0000 && attr_type<=0x7FFF) + unknown_attrs[(*ua_num)++] = nswap16(attr_type); + }; + sar = stun_attr_get_next_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + sar); + } + + if (*ua_num > 0) { + + *err_code = 420; + *reason = (const u08bits *)"Unknown attribute"; + + } else if (*err_code) { + + ; + + } else if (!chnum || addr_any(&peer_addr) || !addr_found) { + + *err_code = 400; + *reason = (const u08bits *)"Bad channel bind request"; + + } else if(!STUN_VALID_CHANNEL(chnum)) { + + *err_code = 400; + *reason = (const u08bits *)"Bad channel number"; + + } else { + + ch_info* chn = allocation_get_ch_info(a, chnum); + turn_permission_info* tinfo = NULL; + + if (chn) { + if (!addr_eq(&peer_addr, &(chn->peer_addr))) { + *err_code = 400; + *reason = (const u08bits *)"You cannot use the same channel number with different peer"; + } else { + tinfo = (turn_permission_info*) (chn->owner); + if (!tinfo) { + *err_code = 500; + *reason = (const u08bits *)"Wrong permission info"; + } else { + if (!addr_eq_no_port(&peer_addr, &(tinfo->addr))) { + *err_code = 500; + *reason = (const u08bits *)"Wrong permission info and peer addr conbination"; + } else if (chn->port != addr_get_port(&peer_addr)) { + *err_code = 500; + *reason = (const u08bits *)"Wrong port number"; + } + } + } + + } else { + + chn = allocation_get_ch_info_by_peer_addr(a, &peer_addr); + if(chn) { + *err_code = 400; + *reason = (const u08bits *)"You cannot use the same peer with different channel number"; + } else { + if(!good_peer_addr(server,&peer_addr)) { + *err_code = 403; + *reason = (const u08bits *) "Forbidden IP"; + } else { + chn = allocation_get_new_ch_info(a, chnum, &peer_addr); + if (!chn) { + *err_code = 500; + *reason = (const u08bits *) "Cannot find channel data"; + } else { + tinfo = (turn_permission_info*) (chn->owner); + if (!tinfo) { + *err_code = 500; + *reason + = (const u08bits *) "Wrong turn permission info"; + } + } + } + } + } + + if (!(*err_code) && chn && tinfo) { + + if (update_channel_lifetime(ss,chn) < 0) { + *err_code = 500; + *reason = (const u08bits *)"Cannot update channel lifetime (internal error)"; + } else { + size_t len = ioa_network_buffer_get_size(nbh); + stun_set_channel_bind_response_str(ioa_network_buffer_data(nbh), &len, tid, 0, NULL); + ioa_network_buffer_set_size(nbh,len); + *resp_constructed = 1; + } + } + } + } + + FUNCEND; + return 0; +} + +static int handle_turn_binding(turn_turnserver *server, + ts_ur_super_session *ss, stun_tid *tid, int *resp_constructed, + int *err_code, const u08bits **reason, u16bits *unknown_attrs, u16bits *ua_num, + ioa_net_data *in_buffer, ioa_network_buffer_handle nbh, + int *origin_changed, ioa_addr *response_origin, + int *dest_changed, ioa_addr *response_destination, + u32bits cookie, int old_stun) { + + FUNCSTART; + ts_ur_session* elem = &(ss->client_session); + int change_ip = 0; + int change_port = 0; + int padding = 0; + int response_port_present = 0; + u16bits response_port = 0; + SOCKET_TYPE st = get_ioa_socket_type(ss->client_session.s); + int use_reflected_from = 0; + + if(!(ss->client_session.s)) + return -1; + + *origin_changed = 0; + *dest_changed = 0; + + stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh)); + while (sar && (!(*err_code)) && (*ua_num < MAX_NUMBER_OF_UNKNOWN_ATTRS)) { + int attr_type = stun_attr_get_type(sar); + switch (attr_type) { + case OLD_STUN_ATTRIBUTE_PASSWORD: + SKIP_ATTRIBUTES; + case STUN_ATTRIBUTE_CHANGE_REQUEST: +/* + * This fix allows the client program from the Stuntman source to make STUN binding requests + * to this server. + * + * It was provided by John Selbie, from STUNTMAN project: + * + * "Here's the gist of the change. Stuntman comes with a STUN client library + * and client program. The client program displays the mapped IP address and + * port if it gets back a successful binding response. + * It also interops with JSTUN, a Java implementation of STUN. + * However, the JSTUN server refuses to respond to any binding request that + * doesn't have a CHANGE-REQUEST attribute in it. + * ... workaround is for the client to make a request with an empty CHANGE-REQUEST + * attribute (neither the ip or port bit are set)." + * + */ + stun_attr_get_change_request_str(sar, &change_ip, &change_port); + if( (!is_rfc5780(server)) && (change_ip || change_port)) { + *err_code = 420; + *reason = (const u08bits *)"Unknown attribute: TURN server was configured without RFC 5780 support"; + break; + } + if(change_ip || change_port) { + if(st != UDP_SOCKET) { + *err_code = 400; + *reason = (const u08bits *)"Wrong request: applicable only to UDP protocol"; + } + } + break; + case STUN_ATTRIBUTE_PADDING: + if(response_port_present) { + *err_code = 400; + *reason = (const u08bits *)"Wrong request format: you cannot use PADDING and RESPONSE_PORT together"; + } else if((st != UDP_SOCKET) && (st != DTLS_SOCKET)) { + *err_code = 400; + *reason = (const u08bits *)"Wrong request: padding applicable only to UDP and DTLS protocols"; + } else { + padding = 1; + } + break; + case STUN_ATTRIBUTE_RESPONSE_PORT: + if(padding) { + *err_code = 400; + *reason = (const u08bits *)"Wrong request format: you cannot use PADDING and RESPONSE_PORT together"; + } else if(st != UDP_SOCKET) { + *err_code = 400; + *reason = (const u08bits *)"Wrong request: applicable only to UDP protocol"; + } else { + int rp = stun_attr_get_response_port_str(sar); + if(rp>=0) { + response_port_present = 1; + response_port = (u16bits)rp; + } else { + *err_code = 400; + *reason = (const u08bits *)"Wrong response port format"; + } + } + break; + case OLD_STUN_ATTRIBUTE_RESPONSE_ADDRESS: + if(old_stun) { + use_reflected_from = 1; + stun_attr_get_addr_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + sar, response_destination, response_destination); + break; + } + default: + if(attr_type>=0x0000 && attr_type<=0x7FFF) + unknown_attrs[(*ua_num)++] = nswap16(attr_type); + }; + sar = stun_attr_get_next_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + sar); + } + + if (*ua_num > 0) { + + *err_code = 420; + *reason = (const u08bits *)"Unknown attribute"; + + } else if (*err_code) { + + ; + + } else if(ss->client_session.s) { + + size_t len = ioa_network_buffer_get_size(nbh); + if (stun_set_binding_response_str(ioa_network_buffer_data(nbh), &len, tid, + get_remote_addr_from_ioa_socket(elem->s), 0, NULL, cookie, old_stun) >= 0) { + + addr_cpy(response_origin, get_local_addr_from_ioa_socket(ss->client_session.s)); + + *resp_constructed = 1; + + if(old_stun && use_reflected_from) { + stun_attr_add_addr_str(ioa_network_buffer_data(nbh), &len, + OLD_STUN_ATTRIBUTE_REFLECTED_FROM, + get_remote_addr_from_ioa_socket(ss->client_session.s)); + } + + if(!is_rfc5780(server)) { + + if(old_stun) { + stun_attr_add_addr_str(ioa_network_buffer_data(nbh), &len, + OLD_STUN_ATTRIBUTE_SOURCE_ADDRESS, response_origin); + stun_attr_add_addr_str(ioa_network_buffer_data(nbh), &len, + OLD_STUN_ATTRIBUTE_CHANGED_ADDRESS, response_origin); + } else { + stun_attr_add_addr_str(ioa_network_buffer_data(nbh), &len, + STUN_ATTRIBUTE_RESPONSE_ORIGIN, response_origin); + } + + } else if(ss->client_session.s) { + + ioa_addr other_address; + + if(get_other_address(server,ss,&other_address) == 0) { + + addr_cpy(response_destination, get_remote_addr_from_ioa_socket(ss->client_session.s)); + + if(change_ip) { + *origin_changed = 1; + if(change_port) { + addr_cpy(response_origin,&other_address); + } else { + int old_port = addr_get_port(response_origin); + addr_cpy(response_origin,&other_address); + addr_set_port(response_origin,old_port); + } + } else if(change_port) { + *origin_changed = 1; + addr_set_port(response_origin,addr_get_port(&other_address)); + } + + if(old_stun) { + stun_attr_add_addr_str(ioa_network_buffer_data(nbh), &len, + OLD_STUN_ATTRIBUTE_SOURCE_ADDRESS, response_origin); + stun_attr_add_addr_str(ioa_network_buffer_data(nbh), &len, + OLD_STUN_ATTRIBUTE_CHANGED_ADDRESS, &other_address); + } else { + stun_attr_add_addr_str(ioa_network_buffer_data(nbh), &len, + STUN_ATTRIBUTE_RESPONSE_ORIGIN, response_origin); + stun_attr_add_addr_str(ioa_network_buffer_data(nbh), &len, + STUN_ATTRIBUTE_OTHER_ADDRESS, &other_address); + } + + if(response_port_present) { + *dest_changed = 1; + addr_set_port(response_destination, (int)response_port); + } + + if(padding) { + int mtu = get_local_mtu_ioa_socket(ss->client_session.s); + if(mtu<68) + mtu=1500; + + mtu = (mtu >> 2) << 2; + stun_attr_add_padding_str(ioa_network_buffer_data(nbh), &len, (u16bits)mtu); + } + } + } + } + ioa_network_buffer_set_size(nbh, len); + } + + FUNCEND; + return 0; +} + +static int handle_turn_send(turn_turnserver *server, ts_ur_super_session *ss, + int *err_code, const u08bits **reason, u16bits *unknown_attrs, u16bits *ua_num, + ioa_net_data *in_buffer) { + + FUNCSTART; + + ioa_addr peer_addr; + const u08bits* value = NULL; + int len = -1; + int addr_found = 0; + int set_df = 0; + + addr_set_any(&peer_addr); + allocation* a = get_allocation_ss(ss); + + if(ss->is_tcp_relay) { + *err_code = 403; + *reason = (const u08bits *)"Send cannot be used with TCP relay"; + } else if (is_allocation_valid(a) && (in_buffer->recv_ttl != 0)) { + + stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh)); + while (sar && (!(*err_code)) && (*ua_num < MAX_NUMBER_OF_UNKNOWN_ATTRS)) { + int attr_type = stun_attr_get_type(sar); + switch (attr_type) { + SKIP_ATTRIBUTES; + case STUN_ATTRIBUTE_DONT_FRAGMENT: + if(!(server->dont_fragment)) + unknown_attrs[(*ua_num)++] = nswap16(attr_type); + else + set_df = 1; + break; + case STUN_ATTRIBUTE_XOR_PEER_ADDRESS: { + if (addr_found) { + *err_code = 400; + *reason = (const u08bits *)"Address duplication"; + } else { + stun_attr_get_addr_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + sar, &peer_addr, + &(ss->default_peer_addr)); + } + } + break; + case STUN_ATTRIBUTE_DATA: { + if (len >= 0) { + *err_code = 400; + *reason = (const u08bits *)"Data duplication"; + } else { + len = stun_attr_get_len(sar); + value = stun_attr_get_value(sar); + } + } + break; + default: + if(attr_type>=0x0000 && attr_type<=0x7FFF) + unknown_attrs[(*ua_num)++] = nswap16(attr_type); + }; + sar = stun_attr_get_next_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + sar); + } + + if (*err_code) { + ; + } else if (*ua_num > 0) { + + *err_code = 420; + + } else if (!addr_any(&peer_addr) && len >= 0) { + + turn_permission_info* tinfo = NULL; + + if(!(server->server_relay)) + tinfo = allocation_get_permission(a, &peer_addr); + + if (tinfo || (server->server_relay)) { + + set_df_on_ioa_socket(get_relay_socket_ss(ss), set_df); + + ioa_network_buffer_handle nbh = in_buffer->nbh; + if(value && len>0) { + u16bits offset = (u16bits)(value - ioa_network_buffer_data(nbh)); + ioa_network_buffer_add_offset_size(nbh,offset,0,len); + } else { + len = 0; + ioa_network_buffer_set_size(nbh,len); + } + ioa_network_buffer_header_init(nbh); + send_data_from_ioa_socket_nbh(get_relay_socket_ss(ss), &peer_addr, nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos); + in_buffer->nbh = NULL; + } + + } else { + *err_code = 400; + *reason = (const u08bits *)"No address found"; + } + } + + FUNCEND; + return 0; +} + +static int update_permission(ts_ur_super_session *ss, ioa_addr *peer_addr) { + + if (!ss || !peer_addr) + return -1; + + allocation* a = get_allocation_ss(ss); + + turn_permission_info* tinfo = allocation_get_permission(a, peer_addr); + + if (!tinfo) { + tinfo = allocation_add_permission(a, peer_addr); + } + + if (!tinfo) + return -1; + + if (update_turn_permission_lifetime(ss, tinfo, 0) < 0) + return -1; + + ch_info *chn = get_turn_channel(tinfo, peer_addr); + if(chn) { + if (update_channel_lifetime(ss, chn) < 0) + return -1; + } + + return 0; +} + +static int handle_turn_create_permission(turn_turnserver *server, + ts_ur_super_session *ss, stun_tid *tid, int *resp_constructed, + int *err_code, const u08bits **reason, u16bits *unknown_attrs, u16bits *ua_num, + ioa_net_data *in_buffer, ioa_network_buffer_handle nbh) { + + int ret = -1; + + int addr_found = 0; + + UNUSED_ARG(server); + + allocation* a = get_allocation_ss(ss); + + if (is_allocation_valid(a)) { + + { + stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh)); + + while (sar && (!(*err_code)) && (*ua_num < MAX_NUMBER_OF_UNKNOWN_ATTRS)) { + + int attr_type = stun_attr_get_type(sar); + + switch (attr_type) { + + SKIP_ATTRIBUTES; + + case STUN_ATTRIBUTE_XOR_PEER_ADDRESS: { + + ioa_addr peer_addr; + addr_set_any(&peer_addr); + + stun_attr_get_addr_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + sar, &peer_addr, + &(ss->default_peer_addr)); + + ioa_addr *relay_addr = get_local_addr_from_ioa_socket(a->relay_session.s); + + if(relay_addr && (relay_addr->ss.sa_family != peer_addr.ss.sa_family)) { + *err_code = 443; + *reason = (const u08bits *)"Peer Address Family Mismatch"; + } else if(!good_peer_addr(server, &peer_addr)) { + *err_code = 403; + *reason = (const u08bits *) "Forbidden IP"; + } else { + addr_found++; + } + } + break; + default: + if(attr_type>=0x0000 && attr_type<=0x7FFF) + unknown_attrs[(*ua_num)++] = nswap16(attr_type); + }; + sar = stun_attr_get_next_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + sar); + } + } + + if (*ua_num > 0) { + + *err_code = 420; + + } else if (*err_code) { + + ; + + } else if (!addr_found) { + + *err_code = 400; + *reason = (const u08bits *)"No address found"; + + } else { + + stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh)); + + while (sar) { + + int attr_type = stun_attr_get_type(sar); + + switch (attr_type) { + + SKIP_ATTRIBUTES; + + case STUN_ATTRIBUTE_XOR_PEER_ADDRESS: { + + ioa_addr peer_addr; + addr_set_any(&peer_addr); + + stun_attr_get_addr_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + sar, &peer_addr, + &(ss->default_peer_addr)); + + addr_set_port(&peer_addr, 0); + if (update_permission(ss, &peer_addr) < 0) { + *err_code = 500; + *reason = (const u08bits *)"Cannot update some permissions (critical server software error)"; + } + } + break; + default: + ; + } + + sar = stun_attr_get_next_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + sar); + } + + if(*err_code == 0) { + size_t len = ioa_network_buffer_get_size(nbh); + stun_init_success_response_str(STUN_METHOD_CREATE_PERMISSION, + ioa_network_buffer_data(nbh), &len, tid); + ioa_network_buffer_set_size(nbh,len); + + ret = 0; + *resp_constructed = 1; + } + } + } + + return ret; +} + +// AUTH ==>> + +static int need_stun_authentication(turn_turnserver *server, ts_ur_super_session *ss) +{ + UNUSED_ARG(ss); + + if(server) { + switch(server->ct) { + case TURN_CREDENTIALS_LONG_TERM: + return 1; + case TURN_CREDENTIALS_SHORT_TERM: + return 1; + default: + ; + }; + } + + return 0; +} + +static int create_challenge_response(ts_ur_super_session *ss, stun_tid *tid, int *resp_constructed, + int *err_code, const u08bits **reason, + ioa_network_buffer_handle nbh, + u16bits method) +{ + size_t len = ioa_network_buffer_get_size(nbh); + stun_init_error_response_str(method, ioa_network_buffer_data(nbh), &len, *err_code, *reason, tid); + *resp_constructed = 1; + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_NONCE, + ss->nonce, (int)(NONCE_MAX_SIZE-1)); + char *realm = ss->realm_options.name; + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_REALM, + (u08bits*)realm, (int)(strlen((s08bits*)(realm)))); + ioa_network_buffer_set_size(nbh,len); + return 0; +} + +#if !defined(min) +#define min(a,b) ((a)<=(b) ? (a) : (b)) +#endif + +static void resume_processing_after_username_check(int success, hmackey_t hmackey, st_password_t pwd, turn_turnserver *server, u64bits ctxkey, ioa_net_data *in_buffer) +{ + + if(server && in_buffer && in_buffer->nbh) { + + ts_ur_super_session *ss = get_session_from_map(server,(turnsession_id)ctxkey); + if(ss && ss->client_session.s) { + turn_turnserver *server = (turn_turnserver *)ss->server; + ts_ur_session *elem = &(ss->client_session); + + if(success) { + ns_bcopy(hmackey,ss->hmackey,sizeof(hmackey_t)); + ss->hmackey_set = 1; + ns_bcopy(pwd,ss->pwd,sizeof(st_password_t)); + } + + read_client_connection(server,elem,ss,in_buffer,0,0); + + close_ioa_socket_after_processing_if_necessary(ss->client_session.s); + + ioa_network_buffer_delete(server->e, in_buffer->nbh); + in_buffer->nbh=NULL; + } + } +} + +static int check_stun_auth(turn_turnserver *server, + ts_ur_super_session *ss, stun_tid *tid, int *resp_constructed, + int *err_code, const u08bits **reason, + ioa_net_data *in_buffer, ioa_network_buffer_handle nbh, + u16bits method, int *message_integrity, + int *postpone_reply, + int can_resume) +{ + u08bits usname[STUN_MAX_USERNAME_SIZE+1]; + u08bits nonce[STUN_MAX_NONCE_SIZE+1]; + u08bits realm[STUN_MAX_REALM_SIZE+1]; + size_t alen = 0; + + if(!need_stun_authentication(server, ss)) + return 0; + + int new_nonce = 0; + + { + int generate_new_nonce = 0; + if(ss->nonce[0]==0) { + generate_new_nonce = 1; + new_nonce = 1; + } + + if(*(server->stale_nonce)) { + if(turn_time_before(ss->nonce_expiration_time,server->ctime)) { + generate_new_nonce = 1; + } + } + + if(generate_new_nonce) { + + int i = 0; + + if(TURN_RANDOM_SIZE == 8) { + for(i=0;i<(NONCE_LENGTH_32BITS>>1);i++) { + u08bits *s = ss->nonce + 8*i; + u64bits rand=(u64bits)turn_random(); + snprintf((s08bits*)s, NONCE_MAX_SIZE-8*i, "%08lx",(unsigned long)rand); + } + } else { + for(i=0;inonce + 4*i; + u32bits rand=(u32bits)turn_random(); + snprintf((s08bits*)s, NONCE_MAX_SIZE-4*i, "%04x",(unsigned int)rand); + } + } + ss->nonce_expiration_time = server->ctime + STUN_NONCE_EXPIRATION_TIME; + } + } + + /* MESSAGE_INTEGRITY ATTR: */ + + stun_attr_ref sar = stun_attr_get_first_by_type_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + STUN_ATTRIBUTE_MESSAGE_INTEGRITY); + + 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; + } + } + + { + int sarlen = stun_attr_get_len(sar); + switch(sarlen) { + case SHA1SIZEBYTES: + if(server->shatype != SHATYPE_SHA1) { + *err_code = SHA_TOO_WEAK; + return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); + return -1; + } + break; + case SHA256SIZEBYTES: + if(server->shatype != SHATYPE_SHA256) { + *err_code = 401; + return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); + return -1; + } + break; + default: + *err_code = 401; + return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); + return -1; + }; + } + + if(server->ct != TURN_CREDENTIALS_SHORT_TERM) { + + /* REALM ATTR: */ + + sar = stun_attr_get_first_by_type_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + STUN_ATTRIBUTE_REALM); + + if(!sar) { + *err_code = 400; + *reason = (const u08bits*)"Bad request"; + return -1; + } + + alen = min((size_t)stun_attr_get_len(sar),sizeof(realm)-1); + ns_bcopy(stun_attr_get_value(sar),realm,alen); + realm[alen]=0; + + if(method == STUN_METHOD_CONNECTION_BIND) { + + get_realm_options_by_name((char *)realm, &(ss->realm_options)); + + } else if(strcmp((char*)realm, (char*)(ss->realm_options.name))) { + *err_code = 400; + *reason = (const u08bits*)"Bad request: the realm value incorrect"; + return -1; + } + } + + /* USERNAME ATTR: */ + + sar = stun_attr_get_first_by_type_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + STUN_ATTRIBUTE_USERNAME); + + if(!sar) { + *err_code = 400; + *reason = (const u08bits*)"Bad request"; + return -1; + } + + alen = min((size_t)stun_attr_get_len(sar),sizeof(usname)-1); + ns_bcopy(stun_attr_get_value(sar),usname,alen); + usname[alen]=0; + + if(ss->username[0]) { + if(strcmp((char*)ss->username,(char*)usname)) { + *err_code = 401; + *reason = (const u08bits*)"Wrong username"; + return -1; + } + } else { + STRCPY(ss->username,usname); + set_username_hash(ss->client_session.s,ss->username,(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), + ioa_network_buffer_get_size(in_buffer->nbh), + STUN_ATTRIBUTE_NONCE); + + if(!sar) { + *err_code = 400; + *reason = (const u08bits*)"Bad request"; + return -1; + } + + alen = min((size_t)stun_attr_get_len(sar),sizeof(nonce)-1); + ns_bcopy(stun_attr_get_value(sar),nonce,alen); + nonce[alen]=0; + + /* Stale Nonce check: */ + + if(new_nonce) { + *err_code = 438; + *reason = (const u08bits*)"Wrong nonce"; + return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); + } + + if(strcmp((s08bits*)ss->nonce,(s08bits*)nonce)) { + *err_code = 438; + *reason = (const u08bits*)"Stale nonce"; + return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); + } + } + + /* Password */ + if(!(ss->hmackey_set) && (ss->pwd[0] == 0)) { + ur_string_map_value_type ukey = NULL; + if(can_resume) { + ukey = (server->userkeycb)(server->id, server->ct, usname, realm, resume_processing_after_username_check, in_buffer, ss->id, postpone_reply); + if(*postpone_reply) { + return 0; + } + } + /* we always return NULL for short-term credentials here */ + if(!ukey) { + /* 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; + } + } + ns_bcopy(ukey,ss->hmackey,16); + ss->hmackey_set = 1; + } + + /* Check integrity */ + int too_weak = 0; + if(stun_check_message_integrity_by_key_str(server->ct,ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + ss->hmackey, + ss->pwd, + server->shatype, + &too_weak)<1) { + + if(too_weak) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: user %s credentials are incorrect: SHA function is too weak\n", + __FUNCTION__, (char*)usname); + *err_code = SHA_TOO_WEAK; + *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; + } + } + + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: user %s credentials are incorrect\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; + } + } + + *message_integrity = 1; + + return 0; +} + +//<<== AUTH + +static void set_alternate_server(turn_server_addrs_list_t *asl, const ioa_addr *local_addr, size_t *counter, u16bits method, stun_tid *tid, int *resp_constructed, int *err_code, const u08bits **reason, ioa_network_buffer_handle nbh) +{ + if(asl && asl->size && local_addr) { + + size_t i; + + /* to prevent indefinite cycle: */ + + for(i=0;isize;++i) { + ioa_addr *addr = &(asl->addrs[i]); + if(addr_eq(addr,local_addr)) + return; + } + + for(i=0;isize;++i) { + if(*counter>=asl->size) + *counter = 0; + ioa_addr *addr = &(asl->addrs[*counter]); + *counter +=1; + if(addr->ss.sa_family == local_addr->ss.sa_family) { + + *err_code = 300; + *reason = (const u08bits *)"Redirect"; + + size_t len = ioa_network_buffer_get_size(nbh); + stun_init_error_response_str(method, ioa_network_buffer_data(nbh), &len, *err_code, *reason, tid); + *resp_constructed = 1; + stun_attr_add_addr_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_ALTERNATE_SERVER, addr); + ioa_network_buffer_set_size(nbh,len); + + return; + } + } + } +} + +#define log_method(ss, method, err_code, reason) \ +{\ + if(!(err_code)) {\ + if(ss->origin[0]) {\ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ + "session %018llu: origin <%s> realm <%s> user <%s>: incoming packet " method " processed, success\n",\ + (unsigned long long)(ss->id), (const char*)(ss->origin),(const char*)(ss->realm_options.name),(const char*)(ss->username));\ + } else {\ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ + "session %018llu: realm <%s> user <%s>: incoming packet " method " processed, success\n",\ + (unsigned long long)(ss->id), (const char*)(ss->realm_options.name),(const char*)(ss->username));\ + }\ + } else {\ + if(ss->origin[0]) {\ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ + "session %018llu: origin <%s> realm <%s> user <%s>: incoming packet " method " processed, error %d: %s\n",\ + (unsigned long long)(ss->id), (const char*)(ss->origin),(const char*)(ss->realm_options.name),(const char*)(ss->username), (err_code), (reason));\ + } else {\ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ + "session %018llu: realm <%s> user <%s>: incoming packet " method " processed, error %d: %s\n",\ + (unsigned long long)(ss->id), (const char*)(ss->realm_options.name),(const char*)(ss->username), (err_code), (reason));\ + }\ + }\ +} + +static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, ioa_net_data *in_buffer, ioa_network_buffer_handle nbh, int *resp_constructed, int can_resume) +{ + + stun_tid tid; + int err_code = 0; + const u08bits *reason = NULL; + int no_response = 0; + int message_integrity = 0; + + if(!(ss->client_session.s)) + return -1; + + u16bits unknown_attrs[MAX_NUMBER_OF_UNKNOWN_ATTRS]; + u16bits ua_num = 0; + u16bits method = stun_get_method_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh)); + + *resp_constructed = 0; + + stun_tid_from_message_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + &tid); + + if (stun_is_request_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh))) { + + if((method == STUN_METHOD_BINDING) && (*(server->no_stun))) { + + no_response = 1; + if(server->verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: STUN method 0x%x ignored\n", + __FUNCTION__, (unsigned int)method); + } + + } else if((method != STUN_METHOD_BINDING) && (*(server->stun_only))) { + + no_response = 1; + if(server->verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: STUN method 0x%x ignored\n", + __FUNCTION__, (unsigned int)method); + } + + } else if((method != STUN_METHOD_BINDING) || (*(server->secure_stun))) { + + if(method == STUN_METHOD_ALLOCATE) { + + SOCKET_TYPE cst = get_ioa_socket_type(ss->client_session.s); + turn_server_addrs_list_t *asl = server->alternate_servers_list; + + if(((cst == UDP_SOCKET)||(cst == DTLS_SOCKET)) && server->self_udp_balance && + server->aux_servers_list && server->aux_servers_list->size) { + asl = server->aux_servers_list; + } else if(((cst == TLS_SOCKET) || (cst == DTLS_SOCKET)) && + server->tls_alternate_servers_list && server->tls_alternate_servers_list->size) { + asl = server->tls_alternate_servers_list; + } + + if(asl && asl->size) { + turn_mutex_lock(&(asl->m)); + set_alternate_server(asl,get_local_addr_from_ioa_socket(ss->client_session.s),&(server->as_counter),method,&tid,resp_constructed,&err_code,&reason,nbh); + turn_mutex_unlock(&(asl->m)); + } + } + + if(!(ss->realm_set) && (method == STUN_METHOD_ALLOCATE)) { + stun_attr_ref sar = stun_attr_get_first_by_type_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + STUN_ATTRIBUTE_ORIGIN); + + if(sar) { + int sarlen = stun_attr_get_len(sar); + if(sarlen>0) { + char *o = (char*)turn_malloc(sarlen+1); + ns_bcopy(stun_attr_get_value(sar),o,sarlen); + o[sarlen]=0; + char *corigin = (char*)turn_malloc(STUN_MAX_ORIGIN_SIZE+1); + corigin[0]=0; + if(get_canonic_origin(o,corigin,STUN_MAX_ORIGIN_SIZE)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: Wrong origin format: %s\n", + __FUNCTION__, o); + } + strncpy(ss->origin,corigin,STUN_MAX_ORIGIN_SIZE); + turn_free(corigin,sarlen+1); + turn_free(o,sarlen+1); + get_realm_options_by_origin(ss->origin,&(ss->realm_options)); + } + } + ss->realm_set = 1; + } + + if(!err_code && !(*resp_constructed) && !no_response) { + if(!(*(server->mobility)) || (method != STUN_METHOD_REFRESH) || is_allocation_valid(get_allocation_ss(ss))) { + int postpone_reply = 0; + check_stun_auth(server, ss, &tid, resp_constructed, &err_code, &reason, in_buffer, nbh, method, &message_integrity, &postpone_reply, can_resume); + if(postpone_reply) + no_response = 1; + } + } + } + + if (!err_code && !(*resp_constructed) && !no_response) { + + switch (method){ + + case STUN_METHOD_ALLOCATE: + + { + handle_turn_allocate(server, ss, &tid, resp_constructed, &err_code, &reason, + unknown_attrs, &ua_num, in_buffer, nbh); + + if(server->verbose) { + log_method(ss, "ALLOCATE", err_code, reason); + } + + break; + } + + case STUN_METHOD_CONNECT: + + handle_turn_connect(server, ss, &tid, &err_code, &reason, + unknown_attrs, &ua_num, in_buffer); + + if(server->verbose) { + log_method(ss, "CONNECT", err_code, reason); + } + + if(!err_code) + no_response = 1; + + break; + + case STUN_METHOD_CONNECTION_BIND: + + handle_turn_connection_bind(server, ss, &tid, resp_constructed, &err_code, &reason, + unknown_attrs, &ua_num, in_buffer, nbh, message_integrity); + + if(server->verbose) { + log_method(ss, "CONNECTION_BIND", err_code, reason); + } + + break; + + case STUN_METHOD_REFRESH: + + handle_turn_refresh(server, ss, &tid, resp_constructed, &err_code, &reason, + unknown_attrs, &ua_num, in_buffer, nbh, message_integrity, + &no_response, can_resume); + + if(server->verbose) { + log_method(ss, "REFRESH", err_code, reason); + } + break; + + case STUN_METHOD_CHANNEL_BIND: + + handle_turn_channel_bind(server, ss, &tid, resp_constructed, &err_code, &reason, + unknown_attrs, &ua_num, in_buffer, nbh); + + if(server->verbose) { + log_method(ss, "CHANNEL_BIND", err_code, reason); + } + break; + + case STUN_METHOD_CREATE_PERMISSION: + + handle_turn_create_permission(server, ss, &tid, resp_constructed, &err_code, &reason, + unknown_attrs, &ua_num, in_buffer, nbh); + + if(server->verbose) { + log_method(ss, "CREATE_PERMISSION", err_code, reason); + } + break; + + case STUN_METHOD_BINDING: + + { + int origin_changed=0; + ioa_addr response_origin; + int dest_changed=0; + ioa_addr response_destination; + + handle_turn_binding(server, ss, &tid, resp_constructed, &err_code, &reason, + unknown_attrs, &ua_num, in_buffer, nbh, + &origin_changed, &response_origin, + &dest_changed, &response_destination, + 0, 0); + + if(server->verbose) { + log_method(ss, "BINDING", err_code, reason); + } + + if(*resp_constructed && !err_code && (origin_changed || dest_changed)) { + + if (server->verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "RFC 5780 request successfully processed\n"); + } + + { + static const u08bits *field = (const u08bits *) TURN_SOFTWARE; + static const size_t fsz = sizeof(TURN_SOFTWARE)-1; + size_t len = ioa_network_buffer_get_size(nbh); + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz); + ioa_network_buffer_set_size(nbh, len); + } + + send_turn_message_to(server, nbh, &response_origin, &response_destination); + + no_response = 1; + } + + break; + } + default: + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unsupported STUN request received, method 0x%x\n",(unsigned int)method); + }; + } + + } else if (stun_is_indication_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh))) { + + 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){ + + case STUN_METHOD_BINDING: + //ICE ? + break; + + case STUN_METHOD_SEND: + + handle_turn_send(server, ss, &err_code, &reason, unknown_attrs, &ua_num, in_buffer); + + if(eve(server->verbose)) { + log_method(ss, "SEND", err_code, reason); + } + + break; + + case STUN_METHOD_DATA: + + err_code = 403; + + if(eve(server->verbose)) { + log_method(ss, "DATA", err_code, reason); + } + + break; + + default: + if (server->verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Unsupported STUN indication received: method 0x%x\n",(unsigned int)method); + } + } + }; + + } else { + + no_response = 1; + + if (server->verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Wrong STUN message received\n"); + } + } + + if(ss->to_be_closed || !(ss->client_session.s) || ioa_socket_tobeclosed(ss->client_session.s)) + return 0; + + if (ua_num > 0) { + + err_code = 420; + + size_t len = ioa_network_buffer_get_size(nbh); + stun_init_error_response_str(method, ioa_network_buffer_data(nbh), &len, err_code, NULL, &tid); + + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES, (const u08bits*) unknown_attrs, (ua_num + * 2)); + + ioa_network_buffer_set_size(nbh,len); + + *resp_constructed = 1; + } + + if (!no_response) { + + if (!(*resp_constructed)) { + + if (!err_code) + err_code = 400; + + size_t len = ioa_network_buffer_get_size(nbh); + stun_init_error_response_str(method, ioa_network_buffer_data(nbh), &len, err_code, reason, &tid); + ioa_network_buffer_set_size(nbh,len); + *resp_constructed = 1; + } + + { + static const u08bits *field = (const u08bits *) TURN_SOFTWARE; + static const size_t fsz = sizeof(TURN_SOFTWARE)-1; + size_t len = ioa_network_buffer_get_size(nbh); + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz); + ioa_network_buffer_set_size(nbh, len); + } + + if(message_integrity) { + size_t len = ioa_network_buffer_get_size(nbh); + 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(err_code) { + if(server->verbose) { + log_method(ss, "message", err_code, reason); + } + } + + } else { + *resp_constructed = 0; + } + + return 0; +} + +static int handle_old_stun_command(turn_turnserver *server, ts_ur_super_session *ss, ioa_net_data *in_buffer, ioa_network_buffer_handle nbh, int *resp_constructed, u32bits cookie) +{ + + stun_tid tid; + int err_code = 0; + const u08bits *reason = NULL; + int no_response = 0; + + u16bits unknown_attrs[MAX_NUMBER_OF_UNKNOWN_ATTRS]; + u16bits ua_num = 0; + u16bits method = stun_get_method_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh)); + + *resp_constructed = 0; + + stun_tid_from_message_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), + &tid); + + if (stun_is_request_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh))) { + + if(method != STUN_METHOD_BINDING) { + no_response = 1; + if(server->verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: OLD STUN method 0x%x ignored\n", + __FUNCTION__, (unsigned int)method); + } + } + + if (!err_code && !(*resp_constructed) && !no_response) { + + int origin_changed=0; + ioa_addr response_origin; + int dest_changed=0; + ioa_addr response_destination; + + handle_turn_binding(server, ss, &tid, resp_constructed, &err_code, &reason, + unknown_attrs, &ua_num, in_buffer, nbh, + &origin_changed, &response_origin, + &dest_changed, &response_destination, + cookie,1); + + if(server->verbose) { + log_method(ss, "OLD BINDING", err_code, reason); + } + + if(*resp_constructed && !err_code && (origin_changed || dest_changed)) { + + if (server->verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "RFC3489 CHANGE request successfully processed\n"); + } + + { + size_t newsz = (((sizeof(TURN_SOFTWARE))>>2) + 1)<<2; + u08bits software[120]; + if(newsz>sizeof(software)) + newsz = sizeof(software); + ns_bcopy(TURN_SOFTWARE,software,newsz); + size_t len = ioa_network_buffer_get_size(nbh); + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, OLD_STUN_ATTRIBUTE_SERVER, software, newsz); + ioa_network_buffer_set_size(nbh, len); + } + + send_turn_message_to(server, nbh, &response_origin, &response_destination); + + no_response = 1; + } + } + } else { + + no_response = 1; + + if (server->verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Wrong OLD STUN message received\n"); + } + } + + if (ua_num > 0) { + + err_code = 420; + + size_t len = ioa_network_buffer_get_size(nbh); + old_stun_init_error_response_str(method, ioa_network_buffer_data(nbh), &len, err_code, NULL, &tid, cookie); + + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES, (const u08bits*) unknown_attrs, (ua_num * 2)); + + ioa_network_buffer_set_size(nbh,len); + + *resp_constructed = 1; + } + + if (!no_response) { + + if (!(*resp_constructed)) { + + if (!err_code) + err_code = 400; + + size_t len = ioa_network_buffer_get_size(nbh); + old_stun_init_error_response_str(method, ioa_network_buffer_data(nbh), &len, err_code, reason, &tid, cookie); + ioa_network_buffer_set_size(nbh,len); + *resp_constructed = 1; + } + + { + size_t newsz = (((sizeof(TURN_SOFTWARE))>>2) + 1)<<2; + u08bits software[120]; + if(newsz>sizeof(software)) + newsz = sizeof(software); + ns_bcopy(TURN_SOFTWARE,software,newsz); + size_t len = ioa_network_buffer_get_size(nbh); + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, OLD_STUN_ATTRIBUTE_SERVER, software, newsz); + ioa_network_buffer_set_size(nbh, len); + } + + if(err_code) { + if(server->verbose) { + log_method(ss, "OLD STUN message", err_code, reason); + } + } + + } else { + *resp_constructed = 0; + } + + return 0; +} + +////////////////////////////////////////////////////////////////// + +static int write_to_peerchannel(ts_ur_super_session* ss, u16bits chnum, ioa_net_data *in_buffer) { + + int rc = 0; + + if (ss && get_relay_socket_ss(ss) && (in_buffer->recv_ttl!=0)) { + + allocation* a = get_allocation_ss(ss); + + if (is_allocation_valid(a)) { + + ch_info* chn = allocation_get_ch_info(a, chnum); + + if (!chn) + return -1; + + /* Channel packets are always sent with DF=0: */ + set_df_on_ioa_socket(get_relay_socket_ss(ss), 0); + + ioa_network_buffer_handle nbh = in_buffer->nbh; + + ioa_network_buffer_add_offset_size(in_buffer->nbh, STUN_CHANNEL_HEADER_LENGTH, 0, ioa_network_buffer_get_size(in_buffer->nbh)-STUN_CHANNEL_HEADER_LENGTH); + + ioa_network_buffer_header_init(nbh); + + rc = send_data_from_ioa_socket_nbh(get_relay_socket_ss(ss), &(chn->peer_addr), nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos); + in_buffer->nbh = NULL; + } + } + + return rc; +} + +static void client_input_handler(ioa_socket_handle s, int event_type, + ioa_net_data *data, void *arg); +static void peer_input_handler(ioa_socket_handle s, int event_type, + ioa_net_data *data, void *arg); + +/////////////// Client actions ///////////////// + +int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, int force, const char* reason) { + + FUNCSTART; + + if (!ss) + return -1; + + ts_ur_session* elem = &(ss->client_session); + + report_turn_session_info(server,ss,1); + dec_quota(ss); + + if(!force) { + + if (elem->s && server->verbose) { + + char sraddr[129]="\0"; + char sladdr[129]="\0"; + addr_to_string(get_remote_addr_from_ioa_socket(elem->s),(u08bits*)sraddr); + addr_to_string(get_local_addr_from_ioa_socket(elem->s),(u08bits*)sladdr); + + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: closed (1st stage), user <%s> realm <%s> origin <%s>, local %s, remote %s, reason: %s\n",(unsigned long long)(ss->id),(char*)ss->username,(char*)ss->realm_options.name,(char*)ss->origin, sladdr,sraddr,reason); + } + + IOA_CLOSE_SOCKET(elem->s); + + FUNCEND; + + return 0; + } + + if (eve(server->verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "closing session 0x%lx, client socket 0x%lx in state %ld (socket session=0x%lx)\n", + (long) ss, + (long) elem->s, + (long) (elem->state), + (long)get_ioa_socket_session(elem->s)); + } + + if (elem->state == UR_STATE_DONE) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "!!! closing session 0x%lx, client session 0x%lx in DONE state\n", + (long)ss, (long) elem); + return -1; + } + + elem->state = UR_STATE_DONE; + + if (ss->alloc.relay_session.state == UR_STATE_DONE) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "!!! closing session 0x%lx, relay session 0x%lx in DONE state\n", + (long)ss, (long)&(ss->alloc.relay_session)); + return -1; + } + ss->alloc.relay_session.state = UR_STATE_DONE; + + if (server->disconnect) + server->disconnect(ss); + + IOA_CLOSE_SOCKET(elem->s); + IOA_CLOSE_SOCKET(ss->alloc.relay_session.s); + + if (server->verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: closed (2nd stage), user <%s> realm <%s> origin <%s>, reason: %s\n", + (unsigned long long)(ss->id), (char*)ss->username,(char*)ss->realm_options.name,(char*)ss->origin, reason); + } + + turn_server_remove_all_from_ur_map_ss(ss); + + FUNCEND; + + return 0; +} + +static void client_to_be_allocated_timeout_handler(ioa_engine_handle e, + void *arg) { + + if (!arg) + return; + + UNUSED_ARG(e); + + ts_ur_super_session* ss = (ts_ur_super_session*) arg; + + turn_turnserver* server = (turn_turnserver*) (ss->server); + + if (!server) + return; + + FUNCSTART; + + int to_close = 0; + + ioa_socket_handle s = ss->client_session.s; + if(!s || ioa_socket_tobeclosed(s)) { + to_close = 1; + } else { + ioa_socket_handle rs = ss->alloc.relay_session.s; + if(!rs || ioa_socket_tobeclosed(rs)) { + to_close = 1; + } else if(ss->alloc.relay_session.state == UR_STATE_DONE) { + to_close = 1; + } else if(ss->client_session.state == UR_STATE_DONE) { + to_close = 1; + } else if(!(ss->alloc.lifetime_ev)) { + to_close = 1; + } else if(!(ss->to_be_allocated_timeout_ev)) { + to_close = 1; + } + } + + if(to_close) { + IOA_EVENT_DEL(ss->to_be_allocated_timeout_ev); + shutdown_client_connection(server, ss, 1, "allocation watchdog determined stale session state"); + } + + FUNCEND; +} + +static int write_client_connection(turn_turnserver *server, ts_ur_super_session* ss, ioa_network_buffer_handle nbh, int ttl, int tos) { + + FUNCSTART; + + ts_ur_session* elem = &(ss->client_session); + + if (elem->state != UR_STATE_READY) { + ioa_network_buffer_delete(server->e, nbh); + FUNCEND; + return -1; + } else { + + ++(ss->sent_packets); + ss->sent_bytes += (u32bits)ioa_network_buffer_get_size(nbh); + turn_report_session_usage(ss); + + if (eve(server->verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: prepare to write to s 0x%lx\n", __FUNCTION__, + (long) (elem->s)); + } + + int ret = send_data_from_ioa_socket_nbh(elem->s, NULL, nbh, ttl, tos); + + FUNCEND; + return ret; + } +} + +static void client_ss_allocation_timeout_handler(ioa_engine_handle e, void *arg) { + + UNUSED_ARG(e); + + if (!arg) + return; + + ts_ur_super_session* ss = (ts_ur_super_session*)arg; + + if (!ss) + return; + + allocation* a = get_allocation_ss(ss); + + turn_turnserver* server = (turn_turnserver*) (ss->server); + + if (!server) { + clear_allocation(a); + return; + } + + FUNCSTART; + + shutdown_client_connection(server, ss, 0, "allocation timeout"); + + FUNCEND; +} + +static int create_relay_connection(turn_turnserver* server, + ts_ur_super_session *ss, u32bits lifetime, + int address_family, u08bits transport, + int even_port, u64bits in_reservation_token, u64bits *out_reservation_token, + int *err_code, const u08bits **reason, + accept_cb acb) { + + if (server && ss && ss->client_session.s) { + + allocation* a = get_allocation_ss(ss); + ts_ur_session* newelem = get_relay_session_ss(ss); + + IOA_CLOSE_SOCKET(newelem->s); + + ns_bzero(newelem, sizeof(ts_ur_session)); + newelem->s = NULL; + + ioa_socket_handle rtcp_s = NULL; + + if (in_reservation_token) { + + if (get_ioa_socket_from_reservation(server->e, in_reservation_token, + &newelem->s) < 0) { + IOA_CLOSE_SOCKET(newelem->s); + *err_code = 508; + *reason = (const u08bits *)"Cannot find reserved socket"; + return -1; + } + + if(!check_username_hash(newelem->s,ss->username,(u08bits*)ss->realm_options.name)) { + IOA_CLOSE_SOCKET(newelem->s); + *err_code = 508; + *reason = (const u08bits *)"Cannot find a valid reserved socket for this username"; + return -1; + } + + addr_debug_print(server->verbose, get_local_addr_from_ioa_socket(newelem->s), "Local relay addr (RTCP)"); + + } else { + + int res = create_relay_ioa_sockets(server->e, + ss->client_session.s, + address_family, transport, + even_port, &(newelem->s), &rtcp_s, out_reservation_token, + err_code, reason, acb, ss); + if (res < 0) { + if(!(*err_code)) + *err_code = 508; + if(!(*reason)) + *reason = (const u08bits *)"Cannot create socket"; + IOA_CLOSE_SOCKET(newelem->s); + IOA_CLOSE_SOCKET(rtcp_s); + return -1; + } + } + + if (newelem->s == NULL) { + IOA_CLOSE_SOCKET(rtcp_s); + *err_code = 508; + *reason = (const u08bits *)"Cannot create relay socket"; + return -1; + } + + set_username_hash(newelem->s,ss->username,(u08bits*)ss->realm_options.name); + + if (rtcp_s) { + if (out_reservation_token && *out_reservation_token) { + set_username_hash(rtcp_s,ss->username,(u08bits*)ss->realm_options.name); + /* OK */ + } else { + IOA_CLOSE_SOCKET(newelem->s); + IOA_CLOSE_SOCKET(rtcp_s); + *err_code = 508; + *reason = (const u08bits *)"Wrong reservation tokens (internal error)"; + return -1; + } + } + + newelem->state = UR_STATE_READY; + + /* RFC6156: do not use DF when IPv6 is involved: */ + if((get_local_addr_from_ioa_socket(newelem->s)->ss.sa_family == AF_INET6) || + (get_local_addr_from_ioa_socket(ss->client_session.s)->ss.sa_family == AF_INET6)) + 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 (lifetime<1) + lifetime = STUN_DEFAULT_ALLOCATE_LIFETIME; + else if(lifetime>STUN_MAX_ALLOCATE_LIFETIME) + lifetime = STUN_MAX_ALLOCATE_LIFETIME; + + ioa_timer_handle ev = set_ioa_timer(server->e, lifetime, 0, + client_ss_allocation_timeout_handler, ss, 0, + "client_ss_allocation_timeout_handler"); + set_allocation_lifetime_ev(a, server->ctime + lifetime, ev); + + set_ioa_socket_session(newelem->s, ss); + } + + return 0; +} + +static int refresh_relay_connection(turn_turnserver* server, + ts_ur_super_session *ss, u32bits lifetime, int even_port, + u64bits in_reservation_token, u64bits *out_reservation_token, + int *err_code) { + + UNUSED_ARG(even_port); + UNUSED_ARG(in_reservation_token); + UNUSED_ARG(out_reservation_token); + UNUSED_ARG(err_code); + + allocation* a = get_allocation_ss(ss); + + if (server && ss && is_allocation_valid(a)) { + + if (lifetime < 1) { + set_allocation_valid(&(ss->alloc),0); + lifetime = 1; + } + + ioa_timer_handle ev = set_ioa_timer(server->e, lifetime, 0, + client_ss_allocation_timeout_handler, ss, 0, + "refresh_client_ss_allocation_timeout_handler"); + + set_allocation_lifetime_ev(a, server->ctime + lifetime, ev); + + return 0; + + } else { + return -1; + } +} + +static void write_http_echo(turn_turnserver *server, ts_ur_super_session *ss) +{ + if(server && ss && ss->client_session.s && !(ss->to_be_closed)) { + ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(server->e); + size_t len_http = ioa_network_buffer_get_size(nbh_http); + u08bits *data = ioa_network_buffer_data(nbh_http); + char data_http[1025]; + char content_http[1025]; + const char* title = "TURN Server"; + snprintf(content_http,sizeof(content_http)-1,"\r\n\r\n \r\n %s\r\n \r\n \r\n %s\r\n \r\n\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); + len_http = strlen(data_http); + ns_bcopy(data_http,data,len_http); + ioa_network_buffer_set_size(nbh_http,len_http); + send_data_from_ioa_socket_nbh(ss->client_session.s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE); + } +} + +static int read_client_connection(turn_turnserver *server, ts_ur_session *elem, + ts_ur_super_session *ss, ioa_net_data *in_buffer, + int can_resume, int count_usage) { + + FUNCSTART; + + if (!server || !elem || !ss || !in_buffer) { + FUNCEND; + return -1; + } + + if (elem->state != UR_STATE_READY) { + FUNCEND; + return -1; + } + + int ret = (int)ioa_network_buffer_get_size(in_buffer->nbh); + if (ret < 0) { + FUNCEND; + return -1; + } + + if(count_usage) { + ++(ss->received_packets); + ss->received_bytes += (u32bits)ioa_network_buffer_get_size(in_buffer->nbh); + turn_report_session_usage(ss); + } + + if (eve(server->verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: data.buffer=0x%lx, data.len=%ld\n", __FUNCTION__, + (long)ioa_network_buffer_data(in_buffer->nbh), + (long)ioa_network_buffer_get_size(in_buffer->nbh)); + } + + u16bits chnum = 0; + u32bits old_stun_cookie = 0; + + size_t blen = ioa_network_buffer_get_size(in_buffer->nbh); + size_t orig_blen = blen; + SOCKET_TYPE st = get_ioa_socket_type(ss->client_session.s); + int is_padding_mandatory = ((st == TCP_SOCKET)||(st==TLS_SOCKET)||(st==TENTATIVE_TCP_SOCKET)); + + if (stun_is_channel_message_str(ioa_network_buffer_data(in_buffer->nbh), + &blen, + &chnum, + is_padding_mandatory)) { + + if(ss->is_tcp_relay) { + //Forbidden + FUNCEND; + return -1; + } + + int rc = 0; + + if(blen<=orig_blen) { + ioa_network_buffer_set_size(in_buffer->nbh,blen); + rc = write_to_peerchannel(ss, chnum, in_buffer); + } + + if (eve(server->verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: wrote to peer %d bytes\n", + __FUNCTION__, (int) rc); + } + + FUNCEND; + return 0; + + } else if (stun_is_command_message_full_check_str(ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh), 0, &(ss->enforce_fingerprints))) { + + ioa_network_buffer_handle nbh = ioa_network_buffer_allocate(server->e); + int resp_constructed = 0; + + u16bits method = stun_get_method_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh)); + + handle_turn_command(server, ss, in_buffer, nbh, &resp_constructed, can_resume); + + if((method != STUN_METHOD_BINDING) && (method != STUN_METHOD_SEND)) + report_turn_session_info(server,ss,0); + + if(ss->to_be_closed || ioa_socket_tobeclosed(ss->client_session.s)) { + FUNCEND; + ioa_network_buffer_delete(server->e, nbh); + return 0; + } + + if (resp_constructed) { + + if ((server->fingerprint) || ss->enforce_fingerprints) { + size_t len = ioa_network_buffer_get_size(nbh); + if (stun_attr_add_fingerprint_str(ioa_network_buffer_data(nbh), &len) < 0) { + FUNCEND ; + ioa_network_buffer_delete(server->e, nbh); + return -1; + } + ioa_network_buffer_set_size(nbh, len); + } + + int ret = write_client_connection(server, ss, nbh, TTL_IGNORE, TOS_IGNORE); + + FUNCEND ; + return ret; + } else { + ioa_network_buffer_delete(server->e, nbh); + return 0; + } + + } else if (old_stun_is_command_message_str(ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh), &old_stun_cookie) && !(*(server->no_stun))) { + + ioa_network_buffer_handle nbh = ioa_network_buffer_allocate(server->e); + int resp_constructed = 0; + + handle_old_stun_command(server, ss, in_buffer, nbh, &resp_constructed, old_stun_cookie); + + if (resp_constructed) { + + int ret = write_client_connection(server, ss, nbh, TTL_IGNORE, TOS_IGNORE); + + FUNCEND ; + return ret; + } else { + ioa_network_buffer_delete(server->e, nbh); + return 0; + } + + } else { + SOCKET_TYPE st = get_ioa_socket_type(ss->client_session.s); + 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))) + write_http_echo(server,ss); + } + } + + //Unrecognized message received, ignore it + + FUNCEND; + return -1; +} + +static int attach_socket_to_session(turn_turnserver* server, ioa_socket_handle s, ts_ur_super_session* ss) { + + int ret = -1; + FUNCSTART; + + if(s && server && ss) { + + if(ss->client_session.s != s) { + + ts_ur_session *newelem = &(ss->client_session); + + if(newelem->s) { + IOA_CLOSE_SOCKET(newelem->s); + } + + newelem->s = s; + + register_callback_on_ioa_socket(server->e, newelem->s, IOA_EV_READ, + client_input_handler, ss, 0); + + set_ioa_socket_session(newelem->s, ss); + + newelem->state = UR_STATE_READY; + } + + ret = 0; + } + + FUNCEND; + return ret; +} + +int open_client_connection_session(turn_turnserver* server, + struct socket_message *sm) { + + FUNCSTART; + if (!server) + return -1; + + if (!(sm->s)) + return -1; + + ts_ur_super_session* ss = create_new_ss(server); + + ts_ur_session *newelem = &(ss->client_session); + + newelem->s = sm->s; + + register_callback_on_ioa_socket(server->e, newelem->s, IOA_EV_READ, + client_input_handler, ss, 0); + + set_ioa_socket_session(newelem->s, ss); + + newelem->state = UR_STATE_READY; + + int at = TURN_MAX_ALLOCATE_TIMEOUT; + if(*(server->stun_only)) + at = TURN_MAX_ALLOCATE_TIMEOUT_STUN_ONLY; + + IOA_EVENT_DEL(ss->to_be_allocated_timeout_ev); + ss->to_be_allocated_timeout_ev = set_ioa_timer(server->e, + at, 0, + client_to_be_allocated_timeout_handler, ss, 1, + "client_to_be_allocated_timeout_handler"); + + if(sm->nd.nbh) { + client_input_handler(newelem->s,IOA_EV_READ,&(sm->nd),ss); + ioa_network_buffer_delete(server->e, sm->nd.nbh); + sm->nd.nbh = NULL; + } + + FUNCEND; + + return 0; +} + +/////////////// io handlers /////////////////// + +static void peer_input_handler(ioa_socket_handle s, int event_type, + ioa_net_data *in_buffer, void *arg) { + + if (!(event_type & IOA_EV_READ) || !arg) + return; + + if(in_buffer->recv_ttl==0) + return; + + UNUSED_ARG(s); + + ts_ur_super_session* ss = (ts_ur_super_session*) arg; + + if(!ss) return; + + turn_turnserver *server = (turn_turnserver*) (ss->server); + + if (!server) { + return; + } + + ts_ur_session* elem = get_relay_session_ss(ss); + if (elem->s == NULL) { + return; + } + + int offset = STUN_CHANNEL_HEADER_LENGTH; + + int ilen = min((int)ioa_network_buffer_get_size(in_buffer->nbh), + (int)(ioa_network_buffer_get_capacity_udp() - offset)); + + if (ilen >= 0) { + + size_t len = (size_t)(ilen); + + allocation* a = get_allocation_ss(ss); + if (is_allocation_valid(a)) { + + u16bits chnum = 0; + + ioa_network_buffer_handle nbh = NULL; + + turn_permission_info* tinfo = allocation_get_permission(a, + &(in_buffer->src_addr)); + if (tinfo) { + chnum = get_turn_channel_number(tinfo, &(in_buffer->src_addr)); + } else if(!(server->server_relay)) { + return; + } + + if (chnum) { + nbh = in_buffer->nbh; + + ioa_network_buffer_add_offset_size(nbh, + 0, + STUN_CHANNEL_HEADER_LENGTH, + ioa_network_buffer_get_size(nbh)+STUN_CHANNEL_HEADER_LENGTH); + + ioa_network_buffer_header_init(nbh); + + SOCKET_TYPE st = get_ioa_socket_type(ss->client_session.s); + int do_padding = ((st == TCP_SOCKET)||(st==TLS_SOCKET)||(st==TENTATIVE_TCP_SOCKET)); + + stun_init_channel_message_str(chnum, ioa_network_buffer_data(nbh), &len, len, do_padding); + ioa_network_buffer_set_size(nbh,len); + in_buffer->nbh = NULL; + if (eve(server->verbose)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: send channel 0x%x\n", __FUNCTION__, + (int) (chnum)); + } + } else { + nbh = ioa_network_buffer_allocate(server->e); + stun_init_indication_str(STUN_METHOD_DATA, ioa_network_buffer_data(nbh), &len); + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_DATA, + ioa_network_buffer_data(in_buffer->nbh), (size_t)ilen); + stun_attr_add_addr_str(ioa_network_buffer_data(nbh), &len, + STUN_ATTRIBUTE_XOR_PEER_ADDRESS, + &(in_buffer->src_addr)); + ioa_network_buffer_set_size(nbh,len); + + { + static const u08bits *field = (const u08bits *) TURN_SOFTWARE; + static const size_t fsz = sizeof(TURN_SOFTWARE)-1; + size_t len = ioa_network_buffer_get_size(nbh); + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz); + 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); + ioa_network_buffer_set_size(nbh, len); + } + } + if (eve(server->verbose)) { + u16bits* t = (u16bits*) ioa_network_buffer_data(nbh); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Send data: 0x%x\n", + (int) (nswap16(t[0]))); + } + + int ret = write_client_connection(server, ss, nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos); + if (ret < 0) { + if(server->verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "session %018llu: client socket to be closed from peer handler: ss=0x%lx\n", (unsigned long long)(ss->id), (long)ss); + } + set_ioa_socket_tobeclosed(s); + } + } + } +} + +static void client_input_handler(ioa_socket_handle s, int event_type, + ioa_net_data *data, void *arg) { + + if (!arg) + return; + + UNUSED_ARG(s); + UNUSED_ARG(event_type); + + ts_ur_super_session* ss = (ts_ur_super_session*)arg; + + turn_turnserver *server = (turn_turnserver*)ss->server; + + if (!server) { + return; + } + + ts_ur_session* elem = &(ss->client_session); + + if (elem->s == NULL) { + return; + } + + int ret = 0; + + switch (elem->state) { + case UR_STATE_READY: + read_client_connection(server, elem, ss, data, 1, 1); + break; + case UR_STATE_DONE: + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "!!! %s: Trying to read from closed socket: s=0x%lx\n", + __FUNCTION__, (long) (elem->s)); + break; + default: + ret = -1; + } + + if (ret < 0) { + if(server->verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "session %018llu: client socket error in client handler: s=0x%lx\n", (unsigned long long)(ss->id), (long) (elem->s)); + } + set_ioa_socket_tobeclosed(s); + } else if (ss->to_be_closed) { + if(server->verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "session %018llu: client socket to be closed in client handler: ss=0x%lx\n", (unsigned long long)(ss->id), (long)ss); + } + set_ioa_socket_tobeclosed(s); + } +} + +/////////////////////////////////////////////////////////// + +void init_turn_server(turn_turnserver* server, + turnserver_id id, int verbose, ioa_engine_handle e, turn_credential_type ct, + int stun_port, int fingerprint, dont_fragment_option_t dont_fragment, + get_user_key_cb userkeycb, + check_new_allocation_quota_cb chquotacb, + release_allocation_quota_cb raqcb, + ioa_addr *external_ip, + vintp no_tcp_relay, + vintp no_udp_relay, + vintp stale_nonce, + vintp stun_only, + vintp no_stun, + turn_server_addrs_list_t *alternate_servers_list, + turn_server_addrs_list_t *tls_alternate_servers_list, + turn_server_addrs_list_t *aux_servers_list, + int self_udp_balance, + vintp no_multicast_peers, vintp no_loopback_peers, + ip_range_list_t* ip_whitelist, ip_range_list_t* ip_blacklist, + 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) { + + if (!server) + return; + + ns_bzero(server,sizeof(turn_turnserver)); + + server->e = e; + server->id = id; + server->ctime = turn_time(); + server->session_id_counter = 0; + server->sessions_map = ur_map_create(); + server->tcp_relay_connections = ur_map_create(); + server->ct = ct; + server->userkeycb = userkeycb; + server->chquotacb = chquotacb; + server->raqcb = raqcb; + server->no_multicast_peers = no_multicast_peers; + server->no_loopback_peers = no_loopback_peers; + server->secure_stun = secure_stun; + server->shatype = shatype; + server->mobility = mobility; + server->server_relay = server_relay; + server->send_turn_session_info = send_turn_session_info; + if(mobility) + server->mobile_connections_map = ur_map_create(); + + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"turn server id=%d created\n",(int)id); + + server->no_tcp_relay = no_tcp_relay; + server->no_udp_relay = no_udp_relay; + + server->alternate_servers_list = alternate_servers_list; + server->tls_alternate_servers_list = tls_alternate_servers_list; + server->aux_servers_list = aux_servers_list; + server->self_udp_balance = self_udp_balance; + + server->stale_nonce = stale_nonce; + server->stun_only = stun_only; + server->no_stun = no_stun; + + server->dont_fragment = dont_fragment; + server->fingerprint = fingerprint; + if(external_ip) { + addr_cpy(&(server->external_ip), external_ip); + server->external_ip_set = 1; + } + if (stun_port < 1) + stun_port = DEFAULT_STUN_PORT; + + server->verbose = verbose; + + server->ip_whitelist = ip_whitelist; + server->ip_blacklist = ip_blacklist; + + server->send_socket_to_relay = send_socket_to_relay; + + set_ioa_timer(server->e, 1, 0, timer_timeout_handler, server, 1, "timer_timeout_handler"); +} + +ioa_engine_handle turn_server_get_engine(turn_turnserver *s) { + if(s) + return s->e; + return NULL; +} + +void set_disconnect_cb(turn_turnserver* server, int(*disconnect)( + ts_ur_super_session*)) { + server->disconnect = disconnect; +} + +////////////////////////////////////////////////////////////////// diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h new file mode 100644 index 00000000..ea740e68 --- /dev/null +++ b/src/server/ns_turn_server.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2011, 2012, 2013 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_SERVER__ +#define __TURN_SERVER__ + +#include "ns_turn_utils.h" +#include "ns_turn_session.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +//////////// ALTERNATE-SERVER ///////////// + +struct _turn_server_addrs_list { + ioa_addr *addrs; + volatile size_t size; + turn_mutex m; +}; + +typedef struct _turn_server_addrs_list turn_server_addrs_list_t; + +void init_turn_server_addrs_list(turn_server_addrs_list_t *l); + +////////// RFC 5780 /////////////////////// + +typedef int (*get_alt_addr_cb)(ioa_addr *addr, ioa_addr *alt_addr); +typedef int (*send_message_cb)(ioa_engine_handle e, ioa_network_buffer_handle nbh, ioa_addr *origin, ioa_addr *destination); + +////////////////////////////////////////// + +extern int TURN_MAX_ALLOCATE_TIMEOUT; +extern int TURN_MAX_ALLOCATE_TIMEOUT_STUN_ONLY; + +typedef u08bits turnserver_id; + +enum _MESSAGE_TO_RELAY_TYPE { + RMT_UNKNOWN = 0, + RMT_SOCKET, + RMT_CB_SOCKET, + RMT_MOBILE_SOCKET +}; +typedef enum _MESSAGE_TO_RELAY_TYPE MESSAGE_TO_RELAY_TYPE; + +struct socket_message { + ioa_socket_handle s; + ioa_net_data nd; +}; + +typedef enum { + DONT_FRAGMENT_UNSUPPORTED=0, + DONT_FRAGMENT_SUPPORTED, + DONT_FRAGMENT_SUPPORT_EMULATED +} dont_fragment_option_t; + +struct _turn_turnserver; +typedef struct _turn_turnserver turn_turnserver; + +typedef void (*get_username_resume_cb)(int success, hmackey_t hmackey, st_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, 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, u08bits *realm); +typedef void (*release_allocation_quota_cb)(u08bits *username, 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); +typedef int (*send_turn_session_info_cb)(struct turn_session_info *tsi); + +struct _turn_turnserver { + + turnserver_id id; + + turnsession_id session_id_counter; + ur_map *sessions_map; + + turn_time_t ctime; + + ioa_engine_handle e; + int verbose; + int fingerprint; + int rfc5780; + vintp stale_nonce; + vintp stun_only; + vintp no_stun; + vintp secure_stun; + SHATYPE shatype; + turn_credential_type ct; + get_alt_addr_cb alt_addr_cb; + send_message_cb sm_cb; + dont_fragment_option_t dont_fragment; + int (*disconnect)(ts_ur_super_session*); + get_user_key_cb userkeycb; + check_new_allocation_quota_cb chquotacb; + release_allocation_quota_cb raqcb; + int external_ip_set; + ioa_addr external_ip; + vintp no_loopback_peers; + vintp no_multicast_peers; + send_turn_session_info_cb send_turn_session_info; + + /* RFC 6062 ==>> */ + vintp no_udp_relay; + vintp no_tcp_relay; + ur_map *tcp_relay_connections; + send_socket_to_relay_cb send_socket_to_relay; + /* <<== RFC 6062 */ + + /* Alternate servers ==>> */ + turn_server_addrs_list_t *alternate_servers_list; + size_t as_counter; + turn_server_addrs_list_t *tls_alternate_servers_list; + size_t tls_as_counter; + turn_server_addrs_list_t *aux_servers_list; + int self_udp_balance; + + /* White/black listing of address ranges */ + ip_range_list_t* ip_whitelist; + ip_range_list_t* ip_blacklist; + + /* Mobility */ + vintp mobility; + ur_map *mobile_connections_map; + + /* Server relay */ + int server_relay; +}; + +/////////////////////////////////////////// + +void init_turn_server(turn_turnserver* server, + turnserver_id id, int verbose, + ioa_engine_handle e, + turn_credential_type ct, + int stun_port, + int fingerprint, + dont_fragment_option_t dont_fragment, + get_user_key_cb userkeycb, + check_new_allocation_quota_cb chquotacb, + release_allocation_quota_cb raqcb, + ioa_addr *external_addr, + vintp no_tcp_relay, + vintp no_udp_relay, + vintp stale_nonce, + vintp stun_only, + vintp no_stun, + turn_server_addrs_list_t *alternate_servers_list, + turn_server_addrs_list_t *tls_alternate_servers_list, + turn_server_addrs_list_t *aux_servers_list, + int self_udp_balance, + vintp no_multicast_peers, + vintp no_loopback_peers, + ip_range_list_t* ip_whitelist, + ip_range_list_t* ip_blacklist, + 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); + +ioa_engine_handle turn_server_get_engine(turn_turnserver *s); + +////////// RFC 5780 /////////////////////// + +void set_rfc5780(turn_turnserver *server, get_alt_addr_cb cb, send_message_cb smcb); + +/////////////////////////////////////////// + +int open_client_connection_session(turn_turnserver* server, struct socket_message *sm); +int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, int force, const char* reason); +void set_disconnect_cb(turn_turnserver* server, int (*disconnect)(ts_ur_super_session*)); + +int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_connection_id tcid, stun_tid *tid, ioa_socket_handle s, int message_integrity); + +int report_turn_session_info(turn_turnserver *server, ts_ur_super_session *ss, int force_invalid); + +turn_time_t get_turn_server_time(turn_turnserver *server); + +/////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__TURN_SERVER__ diff --git a/src/server/ns_turn_session.h b/src/server/ns_turn_session.h new file mode 100644 index 00000000..86c6010e --- /dev/null +++ b/src/server/ns_turn_session.h @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2011, 2012, 2013 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_SESSION__ +#define __TURN_SESSION__ + +#include "ns_turn_utils.h" +#include "ns_turn_maps.h" +#include "ns_turn_ioalib.h" +#include "ns_turn_allocation.h" + +#ifdef __cplusplus +extern "C" { +#endif + +////////// REALM //////////// + +typedef struct _perf_options_t { + + vint max_bps; + vint total_quota; + vint user_quota; + +} perf_options_t; + +struct _realm_options_t { + + s08bits name[STUN_MAX_REALM_SIZE + 1]; + + perf_options_t perf_options; +}; + +//////////////// session info ////////////////////// + +typedef u64bits turnsession_id; + +#define NONCE_MAX_SIZE (NONCE_LENGTH_32BITS*4+1) + +typedef u64bits mobile_id_t; + +struct _ts_ur_super_session { + void* server; + turnsession_id id; + turn_time_t start_time; + ts_ur_session client_session; + ioa_addr default_peer_addr; + allocation alloc; + ioa_timer_handle to_be_allocated_timeout_ev; + u08bits nonce[NONCE_MAX_SIZE]; + turn_time_t nonce_expiration_time; + u08bits username[STUN_MAX_USERNAME_SIZE+1]; + hmackey_t hmackey; + int hmackey_set; + st_password_t pwd; + int enforce_fingerprints; + int is_tcp_relay; + int to_be_closed; + int quota_used; + /* Stats */ + u32bits received_packets; + u32bits sent_packets; + u32bits received_bytes; + u32bits sent_bytes; + u64bits t_received_packets; + u64bits t_sent_packets; + u64bits t_received_bytes; + u64bits t_sent_bytes; + u64bits received_rate; + size_t sent_rate; + size_t total_rate; + /* Mobile */ + int is_mobile; + mobile_id_t mobile_id; + char s_mobile_id[33]; + /* Realm */ + realm_options_t realm_options; + int realm_set; + s08bits origin[STUN_MAX_ORIGIN_SIZE + 1]; +}; + +////// Session info for statistics ////// + +#define TURN_ADDR_STR_SIZE (65) +#define TURN_MAIN_PEERS_ARRAY_SIZE (5) + +typedef struct _addr_data { + ioa_addr addr; + char saddr[TURN_ADDR_STR_SIZE]; +} addr_data; + +struct turn_session_info { + turnsession_id id; + int valid; + turn_time_t start_time; + turn_time_t expiration_time; + SOCKET_TYPE client_protocol; + SOCKET_TYPE peer_protocol; + char tls_method[17]; + char tls_cipher[65]; + addr_data local_addr_data; + addr_data remote_addr_data; + addr_data relay_addr_data; + u08bits username[STUN_MAX_USERNAME_SIZE+1]; + int enforce_fingerprints; +/* Stats */ + u64bits received_packets; + u64bits sent_packets; + u64bits received_bytes; + u64bits sent_bytes; + u32bits received_rate; + u32bits sent_rate; + u32bits total_rate; +/* Mobile */ + int is_mobile; +/* Peers */ + addr_data main_peers_data[TURN_MAIN_PEERS_ARRAY_SIZE]; + size_t main_peers_size; + addr_data *extra_peers_data; + size_t extra_peers_size; +/* Realm */ + char realm[STUN_MAX_REALM_SIZE+1]; + char origin[STUN_MAX_ORIGIN_SIZE + 1]; +}; + +void turn_session_info_init(struct turn_session_info* tsi); +void turn_session_info_clean(struct turn_session_info* tsi); +void turn_session_info_add_peer(struct turn_session_info* tsi, ioa_addr *peer); + +int turn_session_info_copy_from(struct turn_session_info* tsi, ts_ur_super_session *ss); + +////////////// ss ///////////////////// + +allocation* get_allocation_ss(ts_ur_super_session *ss); + +/////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif //__TURN_SESSION__ diff --git a/turndb/schema.sql b/turndb/schema.sql new file mode 100644 index 00000000..e4d84aca --- /dev/null +++ b/turndb/schema.sql @@ -0,0 +1,41 @@ + +CREATE TABLE turnusers_lt ( + realm varchar(512), + 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), + value varchar(512), + primary key (realm,value) +); + +CREATE TABLE allowed_peer_ip ( + ip_range varchar(256), + primary key (ip_range) +); + +CREATE TABLE denied_peer_ip ( + ip_range varchar(256), + primary key (ip_range) +); + +CREATE TABLE turn_origin_to_realm ( + origin varchar(512), + realm varchar(512), + primary key (origin,realm) +); + +CREATE TABLE turn_realm_option ( + realm varchar(512), + opt varchar(32), + value varchar(128), + primary key (realm,opt) +); diff --git a/turndb/schema.stats.redis b/turndb/schema.stats.redis new file mode 100644 index 00000000..c35fd0e0 --- /dev/null +++ b/turndb/schema.stats.redis @@ -0,0 +1,38 @@ +Redis database for allocation statuses and for event notifications +has the following schema: + +1) The allocation status is stored as keys "turn/user//allocation//status", +and the values may be "new lifetime=..." or "refreshed lifetime=...". There may be multiple +allocations under the same user name. + +2) Additionally, the same information is reported through the "publish" mechanism. +The same keys are used and the same status is reported, with the addition of status "deleted". +The user session that is interested in those statuses, must subscribe to the events as: + + psubscribe turn/realm/*/user/*/allocation/*/status + +3) Allocation traffic information is reported through the "publish" mechanism. +The keys are "turn/user//allocation//traffic". The application that is interested +in the traffic information must subscribe to the events as: + + psubscribe turn/realm/*/user/*/allocation/*/traffic + +Or, to receive all allocation events: + + psubscribe turn/realm/*/user/*/allocation/* + +4) Redis database configuration parameters + +TURN Server connects to the Redis and keeps the same connection during the +TURN server lifetime. That means that we have to take care about that +connection - it must NOT expire. + +You have to take care about Redis connection parameters, the timeout and the +keepalive. The following settings must be in your Redis config file +(/etc/redis.conf or /usr/local/etc/redis.conf): + +.......... +timeout 0 +.......... +tcp-keepalive 60 +.......... diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis new file mode 100644 index 00000000..69b5f2ef --- /dev/null +++ b/turndb/schema.userdb.redis @@ -0,0 +1,132 @@ + +I. The database + +Redis database for user authentication and peer permissions +has the following schema: + +1) For the long-term credentials there must be keys +"turn/realm//user//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". + +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 +may be used (same as in SQL schema). The key will be +"turn/realm//secret/" and the value will be +"". For example, if we have secrets "hero1", "hero2" and "hero3", +then we will have keys "turn/realm/north.gov/secret/123", +"turn/realm/north.gov/secret/234", "turn/realm/north.gov/secret/345" +and their values will be "hero1", "hero2", "hero3". The turnserver will +issue command "keys turn/realm/north.gov/secret/*" it it will try to use the +obtained keys in arbitrary order. + +4) The "white" and "black" peer IP ranges are stored as keys of the +following form: "turn/allowed-peer-ip/" or +"turn/denied-peer-ip/" + +The meaning of the keys is the same as the meaning of allowed-peer-ip and +denied-peer-ip turnserver command-line option. The only difference is that +the option values are "static" (they remain the same for the lifetime of +the turnserver process) but the database records can be dynamically changed +and they will be almost immediately "seen" by the turnserver process. + +II. Extra realms data in the database + +We can use more than one realm with the same instance of the TURN server. +This is done through the ORIGIN mechanism - users with different ORIGINS +are placed into different realms. The database includes information about the +relationships between the ORIGIN and realms, and about the extra realms +database numbers. + The relationship between ORIGIN and realm is set as keys of form: +"turn/origin/" with the realm-names as the value. Many different +ORIGIN keys may have the same realm. If the ORIGIN value is not found in +the database or the ORIGIN field is missed in the initial allocate +request, then the default realm is assumed. + +III) Example of a Redis default user database setup. + +This example sets user database for: + + * long-term credentials with hashed passwords and + with default realm "north.gov"; + * long-term credentials with open passwords and + with default realm "north.gov"; + * TURN REST API with shared secret "logen"; + * 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 + or the ORIGIN field is absent in the ALLOCATE request then the default + realm is used. + * The realm performance parameters: "max_bps", + "total_quota" and "user_quota" (same names as the turnserver + configuration options, with the same meanings). + +The shell command would be: + +$ redis-cli < Date: Mon, 21 Apr 2014 05:19:53 +0000 Subject: [PATCH 002/805] minor text fix --- src/apps/uclient/mainuclient.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index f7e8fb66..a050e590 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -121,7 +121,7 @@ static char Usage[] = " Without this option, by default, SHA1 is used.\n" " -M ICE Mobility engaged.\n" " -I Do not set permissions on TURN relay endpoints\n" - " (for testing the non-standard server relay functionality).\n" + " (for testing the non-standard server relay functionality).\n" " -G Generate extra requests (create permissions, channel bind).\n" "Options:\n" " -l Message length (Default: 100 Bytes).\n" From ed527c53b9697dd4ee6fb400a64a44339eeadbb5 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 21 Apr 2014 05:27:06 +0000 Subject: [PATCH 003/805] minor text fix --- src/apps/uclient/mainuclient.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index a050e590..01a37856 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -121,7 +121,7 @@ static char Usage[] = " Without this option, by default, SHA1 is used.\n" " -M ICE Mobility engaged.\n" " -I Do not set permissions on TURN relay endpoints\n" - " (for testing the non-standard server relay functionality).\n" + " (for testing the non-standard server relay functionality).\n" " -G Generate extra requests (create permissions, channel bind).\n" "Options:\n" " -l Message length (Default: 100 Bytes).\n" @@ -142,6 +142,7 @@ static char Usage[] = " -w STUN/TURN user password.\n" " -W TURN REST API authentication secret. Is not compatible with -A option.\n" " -C TURN REST API timestamp/username separator symbol (character). The default value is ':'.\n" + " -F Cipher suite for TLS/DTLS. Default value is DEFAULT.\n" " -o - the ORIGIN STUN attribute value.\n"; ////////////////////////////////////////////////// From 6bad096e4ba0e3948029e4e547d5d1cab489c118 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 21 Apr 2014 06:14:29 +0000 Subject: [PATCH 004/805] docs fixed --- README.turnserver | 13 ++++++++++--- man/man1/turnserver.1 | 11 +++++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/README.turnserver b/README.turnserver index d0ccff7d..a62f008a 100644 --- a/README.turnserver +++ b/README.turnserver @@ -613,11 +613,14 @@ Once the temporary username and password are obtained by the client (browser) application, then the rest is just 'classic" long-term credentials mechanism. For developers, we are going to describe it step-by-step below: - - a new TURN client sends a request command to the TURN server. + - a new TURN client sends a request command to the TURN server. Optionally, + it adds the ORIGIN field to it. - TURN server sees that this is a new client and the message is not authenticated. - the TURN server generates a random nonce string, and return the - error 401 to the client, with nonce and realm included. + error 401 to the client, with nonce and realm included. If the ORIGIN + field was present in the client request, it may affect the realm value + that the server chooses for the client. - the client sees the 401 error and it extracts two values from the error response: the nonce and the realm. - the client uses username, realm and password to produce a key: @@ -703,7 +706,11 @@ the "open password" option is less secure but more convenient for low-security e For short-term credentials, you will use open passwords only. See the file turndb/testredisdbsetup.sh as an example. -6) Of course, the turnserver can be used in non-secure mode, when users are allowed to establish +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 +performance options (max-bps, user-quota, total-quota). + +7) Of course, the turnserver can be used in non-secure mode, when users are allowed to establish sessions anonymously. But in most cases (like WebRTC) that will not work. For the status and statistics database, there are two choices: diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index ac25cd56..238ba797 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -843,13 +843,16 @@ application, then the rest is just 'classic" long\-term credentials mechanism. For developers, we are going to describe it step\-by\-step below: .RS .IP \(bu 3 -a new TURN client sends a request command to the TURN server. +a new TURN client sends a request command to the TURN server. Optionally, +it adds the ORIGIN field to it. .IP \(bu 3 TURN server sees that this is a new client and the message is not authenticated. .IP \(bu 3 the TURN server generates a random nonce string, and return the -error 401 to the client, with nonce and realm included. +error 401 to the client, with nonce and realm included. If the ORIGIN +field was present in the client request, it may affect the realm value +that the server chooses for the client. .IP \(bu 3 the client sees the 401 error and it extracts two values from the error response: the nonce and the realm. @@ -947,6 +950,10 @@ the "open password" option is less secure but more convenient for low\-security For short\-term credentials, you will use open passwords only. 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 +performance \fIoptions\fP (max\-bps, user\-quota, total\-quota). +.IP 7) 4 Of course, the \fIturnserver\fP can be used in non\-secure mode, when users are allowed to establish sessions anonymously. But in most cases (like WebRTC) that will not work. .PP From e9945332575a9abc211f5234eccc3f071a0fdb3a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 21 Apr 2014 21:44:34 +0000 Subject: [PATCH 005/805] Issue 123 fix merged from parent project --- src/apps/relay/ns_ioalib_engine_impl.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 5afe397f..02da6b0b 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -3243,17 +3243,19 @@ int ioa_socket_tobeclosed(ioa_socket_handle s) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s); return 1; } - if(s->broken) { + if(s->tobeclosed) { + return 1; + } else if(s->broken) { + s->tobeclosed = 1; log_socket_event(s, "socket broken", 0); return 1; - } else if(s->tobeclosed) { - log_socket_event(s, "socket to be closed", 0); - return 1; } else if(s->fd < 0) { + s->tobeclosed = 1; log_socket_event(s, "socket fd<0", 0); return 1; } else if(s->ssl) { if(SSL_get_shutdown(s->ssl)) { + s->tobeclosed = 1; log_socket_event(s, "socket SSL shutdown", 0); return 1; } From 9c412e2f4e76151f295831215dfb625be68af1d0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Apr 2014 00:10:03 +0000 Subject: [PATCH 006/805] more fixes for Issue 123 --- src/server/ns_turn_server.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 5161d85e..c1af3492 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3598,7 +3598,7 @@ int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, report_turn_session_info(server,ss,1); dec_quota(ss); - if(!force) { + if(!force && ss->is_mobile) { if (elem->s && server->verbose) { @@ -3650,8 +3650,14 @@ int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, IOA_CLOSE_SOCKET(ss->alloc.relay_session.s); if (server->verbose) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: closed (2nd stage), user <%s> realm <%s> origin <%s>, reason: %s\n", - (unsigned long long)(ss->id), (char*)ss->username,(char*)ss->realm_options.name,(char*)ss->origin, reason); + + char sraddr[129]="\0"; + char sladdr[129]="\0"; + addr_to_string(get_remote_addr_from_ioa_socket(elem->s),(u08bits*)sraddr); + addr_to_string(get_local_addr_from_ioa_socket(elem->s),(u08bits*)sladdr); + + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: closed (2nd stage), user <%s> realm <%s> origin <%s>, local %s, remote %s, reason: %s\n", + (unsigned long long)(ss->id), (char*)ss->username,(char*)ss->realm_options.name,(char*)ss->origin, sladdr,sraddr, reason); } turn_server_remove_all_from_ur_map_ss(ss); From c9ceff404b3a9c30667350792aad9104b80a1680 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Apr 2014 00:16:53 +0000 Subject: [PATCH 007/805] more fixes for Issue 123 --- src/server/ns_turn_server.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index c1af3492..fa94532e 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3646,9 +3646,6 @@ int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, if (server->disconnect) server->disconnect(ss); - IOA_CLOSE_SOCKET(elem->s); - IOA_CLOSE_SOCKET(ss->alloc.relay_session.s); - if (server->verbose) { char sraddr[129]="\0"; @@ -3660,6 +3657,9 @@ int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, (unsigned long long)(ss->id), (char*)ss->username,(char*)ss->realm_options.name,(char*)ss->origin, sladdr,sraddr, reason); } + IOA_CLOSE_SOCKET(elem->s); + IOA_CLOSE_SOCKET(ss->alloc.relay_session.s); + turn_server_remove_all_from_ur_map_ss(ss); FUNCEND; From 9174961875c24e615fcc0996dbfca06837f2dbe8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Apr 2014 00:51:34 +0000 Subject: [PATCH 008/805] more fixes for Issue 123 --- src/apps/relay/ns_ioalib_engine_impl.c | 33 ++++++-------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 02da6b0b..5d99cdac 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -2654,9 +2654,12 @@ static void socket_input_handler_bev(struct bufferevent *bev, void* arg) return; } - while (!ioa_socket_tobeclosed(s)) { - if (socket_input_worker(s) <= 0) - break; + { + size_t cycle = 0; + while (!ioa_socket_tobeclosed(s) && (cycle++<1024)) { + if (socket_input_worker(s) <= 0) + break; + } } if((s->magic != SOCKET_MAGIC)||(s->done)) { @@ -2665,29 +2668,7 @@ static void socket_input_handler_bev(struct bufferevent *bev, void* arg) return; } - if (ioa_socket_tobeclosed(s)) { - switch(s->sat) { - case TCP_CLIENT_DATA_SOCKET: - case TCP_RELAY_DATA_SOCKET: - { - tcp_connection *tc = s->sub_session; - if(tc) { - delete_tcp_connection(tc); - } - } - break; - default: - { - ts_ur_super_session *ss = s->session; - if (ss) { - turn_turnserver *server = (turn_turnserver *)ss->server; - if (server) { - shutdown_client_connection(server, ss, 0, "TCP socket buffer operation error (input handler)"); - } - } - } - } - } + close_ioa_socket_after_processing_if_necessary(s); } } From ff0e692c5b88344e3fdce5c1813eb5d01bf621ce Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Apr 2014 05:57:23 +0000 Subject: [PATCH 009/805] code cleaning --- src/apps/common/hiredis_libevent2.h | 10 +++++----- src/apps/relay/mainrelay.c | 8 +------- src/apps/relay/mainrelay.h | 6 ------ src/apps/relay/userdb.c | 8 +------- src/apps/relay/userdb.h | 9 +-------- 5 files changed, 8 insertions(+), 33 deletions(-) diff --git a/src/apps/common/hiredis_libevent2.h b/src/apps/common/hiredis_libevent2.h index 54d8864f..94948b76 100644 --- a/src/apps/common/hiredis_libevent2.h +++ b/src/apps/common/hiredis_libevent2.h @@ -32,8 +32,6 @@ #define __HIREDIS_LIBEVENT_H__ -#if !defined(TURN_NO_HIREDIS) - #include #ifdef __cplusplus @@ -48,6 +46,8 @@ typedef void* redis_context_handle; ////////////////////////////////////// +#if !defined(TURN_NO_HIREDIS) + void redis_async_init(void); redis_context_handle redisLibeventAttach(struct event_base *base, char *ip, int port, char *pwd, int db); @@ -56,12 +56,12 @@ void send_message_to_redis(redis_context_handle rch, const char *command, const int is_redis_asyncconn_good(redis_context_handle rch); +#endif +/* TURN_NO_HIREDIS */ + #ifdef __cplusplus } #endif -#endif -/* TURN_NO_HIREDIS */ - #endif /*__HIREDIS_LIBEVENT_H__*/ diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 9c6bc2c0..d36526a2 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -73,9 +73,7 @@ TURN_VERBOSE_NONE,0,0, DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,1, 0,0,0,0, "", -#if !defined(TURN_NO_HIREDIS) "",0, -#endif { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,NULL,NULL,NULL }, @@ -86,11 +84,7 @@ NEV_UNKNOWN, LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,"", 0,NULL,0,NULL,DEFAULT_GENERAL_RELAY_SERVERS_NUMBER,0, ////////////// Auth server ///////////////////////////////////// -{NULL,NULL,NULL,0 -#if !defined(TURN_NO_HIREDIS) -,NULL -#endif -}, +{NULL,NULL,NULL,0,NULL}, /////////////// AUX SERVERS //////////////// {NULL,0,{0,NULL}},0, /////////////// ALTERNATE SERVERS //////////////// diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index a76c1b32..c5433dc0 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -83,9 +83,7 @@ #include "ns_ioalib_impl.h" -#if !defined(TURN_NO_HIREDIS) #include "hiredis_libevent2.h" -#endif #ifdef __cplusplus extern "C" { @@ -172,9 +170,7 @@ struct auth_server { struct bufferevent *in_buf; struct bufferevent *out_buf; pthread_t thr; -#if !defined(TURN_NO_HIREDIS) redis_context_handle rch; -#endif }; /////////// PARAMS ////////////////////////////////// @@ -240,10 +236,8 @@ typedef struct _turn_params_ { char listener_ifname[1025]; -#if !defined(TURN_NO_HIREDIS) char redis_statsdb[1025]; int use_redis_statsdb; -#endif struct listener_server listener; diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index a45b5c0e..c6a5503a 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -2893,13 +2893,7 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b /////////// PING ////////////// -void auth_ping( -#if !defined(TURN_NO_HIREDIS) - redis_context_handle rch -#else - void -#endif -) +void auth_ping(redis_context_handle rch) { donot_print_connection_success = 1; diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index 758166c2..a2847ae2 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -191,13 +191,7 @@ void release_allocation_quota(u08bits *username, u08bits *realm); /////////// Handle user DB ///////////////// void read_userdb_file(int to_print); -void auth_ping( -#if !defined(TURN_NO_HIREDIS) - redis_context_handle rch -#else - void -#endif -); +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); @@ -207,7 +201,6 @@ int add_ip_list_range(char* range, ip_range_list_t * list); ///////////// Redis ////////////////////// #if !defined(TURN_NO_HIREDIS) -#include "hiredis_libevent2.h" redis_context_handle get_redis_async_connection(struct event_base *base, const char* connection_string, int delete_keys); #endif From 4ea930c8443c8ee5e866bb55e4e64e724224c95e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Apr 2014 22:10:19 +0000 Subject: [PATCH 010/805] Issue 123 --- src/apps/relay/ns_ioalib_engine_impl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 5d99cdac..1b5712e0 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -2656,7 +2656,7 @@ static void socket_input_handler_bev(struct bufferevent *bev, void* arg) { size_t cycle = 0; - while (!ioa_socket_tobeclosed(s) && (cycle++<1024)) { + while (!ioa_socket_tobeclosed(s) && (cycle++<64)) { if (socket_input_worker(s) <= 0) break; } @@ -3220,7 +3220,7 @@ int ioa_socket_tobeclosed(ioa_socket_handle s) } if(s->done) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s: ceck on already closed socket: 0x%lx, st=%d, sat=%d\n",__FUNCTION__,(long)s,s->st,s->sat); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s: check on already closed socket: 0x%lx, st=%d, sat=%d\n",__FUNCTION__,(long)s,s->st,s->sat); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s); return 1; } From af741582c294d282112ed2626743fc83028d9228 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Apr 2014 23:03:59 +0000 Subject: [PATCH 011/805] Issue 123 --- src/apps/uclient/uclient.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 6e23aa60..615488a3 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1118,7 +1118,7 @@ static int refresh_channel(app_ur_session* elem, u16bits method, uint32_t lt) return 0; } -static inline int client_timer_handler(app_ur_session* elem) +static inline int client_timer_handler(app_ur_session* elem, int *done) { if (elem) { if (!turn_time_before(current_mstime, elem->refresh_time)) { @@ -1157,6 +1157,7 @@ static inline int client_timer_handler(app_ur_session* elem) } } } else { + *done += 1; client_write(elem); elem->finished_time = current_mstime + STOPPING_TIME*1000; } @@ -1176,14 +1177,23 @@ static void timer_handler(evutil_socket_t fd, short event, void *arg) if(start_full_timer) { int i = 0; + int done = 0; for (i = 0; i < total_clients; ++i) { if (elems[i]) { - int finished = client_timer_handler(elems[i]); + int finished = client_timer_handler(elems[i],&done); if (finished) { elems[i] = NULL; } } } + if(done>5 && dos) { + for (i = 0; i < total_clients; ++i) { + if (elems[i]) { + close(elems[i]->pinfo.fd); + elems[i]->pinfo.fd = -1; + } + } + } } } From f088108139f1e7c11b0388112d2b27625851d63a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 23 Apr 2014 06:30:23 +0000 Subject: [PATCH 012/805] issue 123 --- src/apps/relay/ns_ioalib_engine_impl.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 1b5712e0..07f86afa 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -100,7 +100,6 @@ static void close_socket_net_data(ioa_socket_handle s); /************** Utils **************************/ static const int tcp_congestion_control = 1; -static const int udp_congestion_control = 1; static int bufferevent_enabled(struct bufferevent *bufev, short flags) { @@ -2597,7 +2596,17 @@ static void socket_output_handler_bev(struct bufferevent *bev, void* arg) ioa_socket_handle s = (ioa_socket_handle) arg; - if ((s->magic != SOCKET_MAGIC)||(s->done)||ioa_socket_tobeclosed(s)||(bev != s->bev)) { + if ((s->magic != SOCKET_MAGIC)||(s->done)||(bev != s->bev)) { + return; + } + + if (s->tobeclosed) { + if (bufferevent_enabled(bev,EV_READ)) { + bufferevent_disable(bev,EV_READ); + } + if (bufferevent_enabled(bev,EV_WRITE)) { + bufferevent_disable(bev,EV_WRITE); + } return; } @@ -3031,7 +3040,7 @@ int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, ret = (int) ioa_network_buffer_get_size(nbh); - if(!udp_congestion_control || is_socket_writeable(s,(size_t)ret,__FUNCTION__,2)) { + if(!tcp_congestion_control || is_socket_writeable(s,(size_t)ret,__FUNCTION__,2)) { if (bufferevent_write( s->bev, ioa_network_buffer_data(nbh), From 114257e872eaac404cdf1b5332eacd9264fc76d4 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 23 Apr 2014 21:34:16 +0000 Subject: [PATCH 013/805] more fixes for issue 123 --- src/apps/relay/ns_ioalib_engine_impl.c | 32 ++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 07f86afa..b96d283f 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -2530,8 +2530,10 @@ static void socket_input_handler(evutil_socket_t fd, short what, void* arg) ioa_socket_handle s = (ioa_socket_handle)arg; - if(!s) + if(!s) { + read_spare_buffer(fd); return; + } if((s->magic != SOCKET_MAGIC)||(s->done)) { read_spare_buffer(fd); @@ -2547,6 +2549,8 @@ static void socket_input_handler(evutil_socket_t fd, short what, void* arg) if (!ioa_socket_tobeclosed(s)) socket_input_worker(s); + else + read_spare_buffer(fd); if((s->magic != SOCKET_MAGIC)||(s->done)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!!%s (1) on socket, ev=%d: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(int)what,(long)s, s->st, s->sat); @@ -2645,30 +2649,50 @@ static void socket_output_handler_bev(struct bufferevent *bev, void* arg) } } +static int read_spare_buffer_bev(struct bufferevent *bev) +{ + if(bev) { + char some_buffer[8192]; + bufferevent_read(bev, some_buffer, sizeof(some_buffer)); + } + return 0; +} + static void socket_input_handler_bev(struct bufferevent *bev, void* arg) { - if (bev && arg) { + if (bev) { + + if(!arg) { + read_spare_buffer_bev(bev); + return; + } ioa_socket_handle s = (ioa_socket_handle) arg; if(bev != s->bev) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx: wrong bev\n", __FUNCTION__,(long)s); + read_spare_buffer_bev(bev); return; } if((s->magic != SOCKET_MAGIC)||(s->done)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!!%s on socket: 0x%lx, st=%d, sat=%d\n", __FUNCTION__, (long) s, s->st, s->sat); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s); + read_spare_buffer_bev(bev); return; } { size_t cycle = 0; - while (!ioa_socket_tobeclosed(s) && (cycle++<64)) { + do { + if(ioa_socket_tobeclosed(s)) { + read_spare_buffer_bev(bev); + break; + } if (socket_input_worker(s) <= 0) break; - } + } while(cycle++<128); } if((s->magic != SOCKET_MAGIC)||(s->done)) { From 454396e5cc7918ab871d40304e538b31320b6732 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 24 Apr 2014 01:36:13 +0000 Subject: [PATCH 014/805] a better fix for problem 123 --- src/apps/relay/ns_ioalib_engine_impl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index b96d283f..40b1e8c8 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -2687,12 +2687,12 @@ static void socket_input_handler_bev(struct bufferevent *bev, void* arg) size_t cycle = 0; do { if(ioa_socket_tobeclosed(s)) { - read_spare_buffer_bev(bev); + read_spare_buffer_bev(s->bev); break; } if (socket_input_worker(s) <= 0) break; - } while(cycle++<128); + } while((cycle++<128) && (s->bev)); } if((s->magic != SOCKET_MAGIC)||(s->done)) { From 03ea4937ace7d59e62e25a46b99e758dd1924024 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 24 Apr 2014 06:02:45 +0000 Subject: [PATCH 015/805] more fixes for 123 issue --- README.turnutils | 2 + .../selfloadbalance/secure_dos_attack.sh | 46 ++++++++++++++++++- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 2 +- man/man1/turnutils.1 | 6 ++- src/apps/uclient/mainuclient.c | 7 ++- src/apps/uclient/uclient.c | 4 +- src/apps/uclient/uclient.h | 1 + src/server/ns_turn_server.c | 2 +- 9 files changed, 64 insertions(+), 8 deletions(-) diff --git a/README.turnutils b/README.turnutils index e0c7c8c8..17550fb4 100644 --- a/README.turnutils +++ b/README.turnutils @@ -113,6 +113,8 @@ Flags: -G Generate extra requests (create permissions, channel bind). +-B Random disconnect after a few initial packets. + Options with required values: -l Message length (Default: 100 Bytes). diff --git a/examples/scripts/selfloadbalance/secure_dos_attack.sh b/examples/scripts/selfloadbalance/secure_dos_attack.sh index 75189d66..4601348b 100755 --- a/examples/scripts/selfloadbalance/secure_dos_attack.sh +++ b/examples/scripts/selfloadbalance/secure_dos_attack.sh @@ -11,7 +11,7 @@ fi export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/ -export SLEEP_TIME=9 +export SLEEP_TIME=11 while [ 0 ] ; do @@ -63,6 +63,50 @@ PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -G -t -S -k turn_cli ########################### +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -B -N -R -G -n 30 -m 10 -l 170 -g -u ninefingers -w youhavetoberealistic -y $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -B -N -R -G -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u ninefingers -w youhavetoberealistic $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -B -N -R -G -S -k turn_client_pkey.pem -n 10 -m 10 -l 170 -e ::1 -x -g -u ninefingers -w youhavetoberealistic -s $@ 127.0.0.1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -B -N -R -G -t -n 50 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -B -N -R -G -T -n 30 -m 10 -l 170 -y -g -u gorst -w hero $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -B -N -R -G -T -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -y -g -u gorst -w hero $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -B -N -R -G -t -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -B -N -R -G -n 30 -m 10 -l 170 -g -u ninefingers -w youhavetoberealistic -y -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -B -N -R -G -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u ninefingers -w youhavetoberealistic -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -B -N -R -G -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -e ::1 -x -g -u ninefingers -w youhavetoberealistic -s -p 12345 $@ 127.0.0.1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -B -N -R -G -t -n 50 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -B -N -R -G -T -n 30 -m 10 -l 170 -y -g -u gorst -w hero -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -B -N -R -G -T -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -y -g -u gorst -w hero -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -B -N -R -G -t -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero -p 12345 $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -B -N -R -G -n 30 -m 10 -l 170 -g -u ninefingers -w youhavetoberealistic -y -p 12346 $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -B -N -R -G -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u ninefingers -w youhavetoberealistic -p 12346 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -B -N -R -G -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -e ::1 -x -g -u ninefingers -w youhavetoberealistic -s -p 12346 $@ 127.0.0.1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -B -N -R -G -t -n 50 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero -p 12346 $@ ::1 & + +PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -B -N -R -G -T -n 30 -m 10 -l 170 -y -g -u gorst -w hero -p 12346 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -B -N -R -G -T -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -y -g -u gorst -w hero -p 12346 $@ ::1 & + +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -B -N -R -G -t -S -k turn_client_pkey.pem -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero -p 12346 $@ ::1 & + +########################### + PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -O -N -R -G -n 30 -m 10 -l 170 -g -u ninefingers -w youhavetoberealistic -y $@ ::1 & PATH=examples/bin/:../bin/:./bin/:${PATH} turnutils_uclient -O -N -R -G -n 30 -m 10 -l 170 -e 127.0.0.1 -X -g -u ninefingers -w youhavetoberealistic $@ ::1 & diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 7537c852..fbdac452 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "20 April 2014" "" "" +.TH TURN 1 "23 April 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 238ba797..14008819 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "20 April 2014" "" "" +.TH TURN 1 "23 April 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 1e2c93d9..f72b9e68 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "20 April 2014" "" "" +.TH TURN 1 "23 April 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -169,6 +169,10 @@ Do not set permissions on TURN relay endpoints Generate extra requests (create permissions, channel bind). .TP .B +\fB\-B\fP +Random disconnect after a few initial packets. +.TP +.B Options with required values: .TP .B diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 01a37856..8d7e77bb 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -81,6 +81,7 @@ int mandatory_channel_padding = 0; int negative_test = 0; int negative_protocol_test = 0; int dos = 0; +int random_disconnect = 0; SHATYPE shatype = SHATYPE_SHA1; @@ -123,6 +124,7 @@ static char Usage[] = " -I Do not set permissions on TURN relay endpoints\n" " (for testing the non-standard server relay functionality).\n" " -G Generate extra requests (create permissions, channel bind).\n" + " -B Random disconnect after a few initial packets.\n" "Options:\n" " -l Message length (Default: 100 Bytes).\n" " -i Certificate file (for secure connections only, optional).\n" @@ -196,11 +198,14 @@ int main(int argc, char **argv) ns_bzero(local_addr, sizeof(local_addr)); - while ((c = getopt(argc, argv, "d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:vsyhcxXgtTSAPDNOUHMRIG")) != -1) { + while ((c = getopt(argc, argv, "d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:vsyhcxXgtTSAPDNOUHMRIGB")) != -1) { switch (c){ case 'o': STRCPY(origin,optarg); break; + case 'B': + random_disconnect = 1; + break; case 'G': extra_requests = 1; break; diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 615488a3..bc27d38e 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1180,13 +1180,13 @@ static void timer_handler(evutil_socket_t fd, short event, void *arg) int done = 0; for (i = 0; i < total_clients; ++i) { if (elems[i]) { - int finished = client_timer_handler(elems[i],&done); + int finished = client_timer_handler(elems[i], &done); if (finished) { elems[i] = NULL; } } } - if(done>5 && dos) { + if(done>5 && (dos || random_disconnect)) { for (i = 0; i < total_clients; ++i) { if (elems[i]) { close(elems[i]->pinfo.fd); diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index 00ffdc07..93e595b6 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -76,6 +76,7 @@ extern int mandatory_channel_padding; extern int negative_test; extern int negative_protocol_test; extern int dos; +extern int random_disconnect; extern SHATYPE shatype; extern int mobility; extern int no_permissions; diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index fa94532e..0fce1f8c 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4258,7 +4258,7 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: client socket to be closed from peer handler: ss=0x%lx\n", (unsigned long long)(ss->id), (long)ss); } - set_ioa_socket_tobeclosed(s); + set_ioa_socket_tobeclosed(ss->client_session.s); } } } From 10c0951db37e814d497a4f5f4da3f2608d7dc3bb Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 24 Apr 2014 06:46:29 +0000 Subject: [PATCH 016/805] issue 123 fixes --- src/server/ns_turn_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 0fce1f8c..3a8674f8 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3598,7 +3598,7 @@ int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, report_turn_session_info(server,ss,1); dec_quota(ss); - if(!force && ss->is_mobile) { + if(!force) { if (elem->s && server->verbose) { From 2e60266b6d4401e5bdb0b5c0f1b0b8e61bc1b5c7 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 24 Apr 2014 07:19:51 +0000 Subject: [PATCH 017/805] more 123 fixes --- src/server/ns_turn_server.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 3a8674f8..4eb52d8a 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4252,14 +4252,7 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, (int) (nswap16(t[0]))); } - int ret = write_client_connection(server, ss, nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos); - if (ret < 0) { - if(server->verbose) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, - "session %018llu: client socket to be closed from peer handler: ss=0x%lx\n", (unsigned long long)(ss->id), (long)ss); - } - set_ioa_socket_tobeclosed(ss->client_session.s); - } + write_client_connection(server, ss, nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos); } } } From 4caebe3639526d0c34b722299002f00558a80bbb Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 24 Apr 2014 07:22:05 +0000 Subject: [PATCH 018/805] 123 fixes --- src/apps/relay/netengine.c | 6 +----- src/apps/relay/ns_ioalib_impl.h | 2 -- src/apps/relay/userdb.h | 2 -- src/server/ns_turn_server.c | 3 --- 4 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 326adaca..64cab84c 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1478,11 +1478,7 @@ static void* run_auth_server_thread(void *arg) run_events(eb,NULL); read_userdb_file(0); update_white_and_black_lists(); - auth_ping( -#if !defined(TURN_NO_HIREDIS) - authserver->rch -#endif - ); + auth_ping(authserver->rch); } return arg; diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 3fe3529f..3628c831 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -157,9 +157,7 @@ struct _ioa_engine size_t relays_number; size_t relay_addr_counter; ioa_addr *relay_addrs; -#if !defined(TURN_NO_HIREDIS) redis_context_handle rch; -#endif }; #define SOCKET_MAGIC (0xABACADEF) diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index a2847ae2..ae4cf4a5 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -34,9 +34,7 @@ #include #include -#if !defined(TURN_NO_HIREDIS) #include "hiredis_libevent2.h" -#endif #include "ns_turn_utils.h" #include "ns_turn_maps.h" diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 4eb52d8a..e3875bb3 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -2849,20 +2849,17 @@ static int check_stun_auth(turn_turnserver *server, if(server->shatype != SHATYPE_SHA1) { *err_code = SHA_TOO_WEAK; return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); - return -1; } break; case SHA256SIZEBYTES: if(server->shatype != SHATYPE_SHA256) { *err_code = 401; return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); - return -1; } break; default: *err_code = 401; return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); - return -1; }; } From de1fe9835dff3443dc15ff589424e1a6a476a5cf Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 24 Apr 2014 08:17:49 +0000 Subject: [PATCH 019/805] fixes for 123 --- src/server/ns_turn_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index e3875bb3..709976ee 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3595,7 +3595,7 @@ int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, report_turn_session_info(server,ss,1); dec_quota(ss); - if(!force) { + if(!force && ss->is_mobile) { if (elem->s && server->verbose) { From 869c06d5858ea8bb9e7f09bb4e57ef979aa14452 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 25 Apr 2014 05:51:06 +0000 Subject: [PATCH 020/805] compile-time OpenSSL version --- src/apps/relay/mainrelay.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index d36526a2..7a5ba894 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1539,9 +1539,9 @@ static void print_features(unsigned long mfn) #endif #if OPENSSL_VERSION_NUMBER >= 0x10000000L - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL version: fresh enough\n"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL compile-time version 0x%llx: fresh enough\n",(unsigned long long)OPENSSL_VERSION_NUMBER); #else - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL version: antique\n"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL compile-time version 0x%llx version: antique\n",(unsigned long long)OPENSSL_VERSION_NUMBER); #endif TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Default Net Engine version: %d (%s)\n\n=====================================================\n\n", (int)turn_params.net_engine_version, turn_params.net_engine_version_txt[(int)turn_params.net_engine_version]); From 4614f7c23a1cf644394f3eb1210bcd945276244d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 25 Apr 2014 19:09:30 +0000 Subject: [PATCH 021/805] cleaning --- src/apps/relay/turncli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index ce1185bf..8712493c 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -1115,7 +1115,7 @@ static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd clisession->bev = bufferevent_socket_new(cliserver.event_base, fd, - BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); bufferevent_setcb(clisession->bev, cli_socket_input_handler_bev, NULL, cli_eventcb_bev, clisession); bufferevent_setwatermark(clisession->bev, EV_READ|EV_WRITE, 0, BUFFEREVENT_HIGH_WATERMARK); From c5afa961a01e507e6bcfe931e5219400916b9a88 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 27 Apr 2014 03:46:08 +0000 Subject: [PATCH 022/805] issue 123 --- src/apps/relay/ns_ioalib_engine_impl.c | 36 ++++++++++++++------------ src/apps/relay/ns_ioalib_impl.h | 1 + 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 40b1e8c8..2deaecc0 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -2600,6 +2600,9 @@ static void socket_output_handler_bev(struct bufferevent *bev, void* arg) ioa_socket_handle s = (ioa_socket_handle) arg; + if(s->in_write) + return; + if ((s->magic != SOCKET_MAGIC)||(s->done)||(bev != s->bev)) { return; } @@ -2608,9 +2611,6 @@ static void socket_output_handler_bev(struct bufferevent *bev, void* arg) if (bufferevent_enabled(bev,EV_READ)) { bufferevent_disable(bev,EV_READ); } - if (bufferevent_enabled(bev,EV_WRITE)) { - bufferevent_disable(bev,EV_WRITE); - } return; } @@ -3064,21 +3064,25 @@ int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, ret = (int) ioa_network_buffer_get_size(nbh); - if(!tcp_congestion_control || is_socket_writeable(s,(size_t)ret,__FUNCTION__,2)) { - if (bufferevent_write( - s->bev, + if (!tcp_congestion_control || is_socket_writeable( + s, (size_t) ret, __FUNCTION__, 2)) { + s->in_write = 1; + if (bufferevent_write(s->bev, ioa_network_buffer_data(nbh), - ioa_network_buffer_get_size(nbh)) - < 0) { - ret = -1; - perror("bufev send"); - log_socket_event(s, "socket write failed, to be closed",1); - s->tobeclosed = 1; - s->broken = 1; - } + ioa_network_buffer_get_size(nbh)) < 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; } else { - //drop the packet - ; + //drop the packet + ; } } } else if (s->ssl) { diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 3628c831..2dee9341 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -175,6 +175,7 @@ struct _ioa_socket SOCKET_TYPE st; SOCKET_APP_TYPE sat; SSL* ssl; + int in_write; char orig_ctx_type[16]; int bound; int local_addr_known; From 8553e9f46a1523b12defc3cca77b6b60ebfa1d8d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 27 Apr 2014 09:38:19 +0000 Subject: [PATCH 023/805] issue 123 --- src/apps/relay/ns_ioalib_engine_impl.c | 88 +++++++++++++------------- src/server/ns_turn_ioalib.h | 4 +- src/server/ns_turn_server.c | 14 ++-- 3 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 2deaecc0..989074f3 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -998,33 +998,31 @@ int set_socket_options(ioa_socket_handle s) /* <<== Socket options helpers */ -ioa_socket_handle create_unbound_ioa_socket(ioa_engine_handle e, ioa_socket_handle parent_s, int family, SOCKET_TYPE st, SOCKET_APP_TYPE sat) +ioa_socket_handle create_unbound_ioa_socket(ioa_engine_handle e, int family, SOCKET_TYPE st, SOCKET_APP_TYPE sat) { evutil_socket_t fd = -1; ioa_socket_handle ret = NULL; - if(!parent_s) { - switch (st){ - case UDP_SOCKET: - fd = socket(family, SOCK_DGRAM, 0); - if (fd < 0) { - perror("UDP socket"); - return NULL; - } - set_sock_buf_size(fd, UR_CLIENT_SOCK_BUF_SIZE); - break; - case TCP_SOCKET: - fd = socket(family, SOCK_STREAM, 0); - if (fd < 0) { - perror("TCP socket"); - return NULL; - } - set_sock_buf_size(fd, UR_CLIENT_SOCK_BUF_SIZE); - break; - default: - /* we do not support other sockets in the relay position */ + switch (st){ + case UDP_SOCKET: + fd = socket(family, SOCK_DGRAM, 0); + if (fd < 0) { + perror("UDP socket"); return NULL; } + set_sock_buf_size(fd, UR_CLIENT_SOCK_BUF_SIZE); + break; + case TCP_SOCKET: + fd = socket(family, SOCK_STREAM, 0); + if (fd < 0) { + perror("TCP socket"); + return NULL; + } + set_sock_buf_size(fd, UR_CLIENT_SOCK_BUF_SIZE); + break; + default: + /* we do not support other sockets in the relay position */ + return NULL; } ret = (ioa_socket*)turn_malloc(sizeof(ioa_socket)); @@ -1038,11 +1036,7 @@ ioa_socket_handle create_unbound_ioa_socket(ioa_engine_handle e, ioa_socket_hand ret->sat = sat; ret->e = e; - if(parent_s) { - add_socket_to_parent(parent_s, ret); - } else { - set_socket_options(ret); - } + set_socket_options(ret); return ret; } @@ -1128,7 +1122,7 @@ int create_relay_ioa_sockets(ioa_engine_handle e, if (port >= 0 && even_port > 0) { IOA_CLOSE_SOCKET(*rtcp_s); - *rtcp_s = create_unbound_ioa_socket(e, NULL, relay_addr.ss.sa_family, UDP_SOCKET, RELAY_RTCP_SOCKET); + *rtcp_s = create_unbound_ioa_socket(e, relay_addr.ss.sa_family, UDP_SOCKET, RELAY_RTCP_SOCKET); if (*rtcp_s == NULL) { perror("socket"); IOA_CLOSE_SOCKET(*rtp_s); @@ -1164,7 +1158,7 @@ int create_relay_ioa_sockets(ioa_engine_handle e, IOA_CLOSE_SOCKET(*rtp_s); - *rtp_s = create_unbound_ioa_socket(e, NULL, relay_addr.ss.sa_family, + *rtp_s = create_unbound_ioa_socket(e, relay_addr.ss.sa_family, (transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) ? TCP_SOCKET : UDP_SOCKET, RELAY_SOCKET); if (*rtp_s == NULL) { @@ -1334,7 +1328,7 @@ static void connect_eventcb(struct bufferevent *bev, short events, void *ptr) ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, ioa_addr *peer_addr, connect_cb cb, void *arg) { - ioa_socket_handle ret = create_unbound_ioa_socket(s->e, NULL, s->family, s->st, TCP_RELAY_DATA_SOCKET); + ioa_socket_handle ret = create_unbound_ioa_socket(s->e, s->family, s->st, TCP_RELAY_DATA_SOCKET); if(!ret) { return NULL; @@ -1509,6 +1503,9 @@ ioa_socket_handle create_ioa_socket_from_fd(ioa_engine_handle e, /* Only must be called for DTLS_SOCKET */ ioa_socket_handle create_ioa_socket_from_ssl(ioa_engine_handle e, ioa_socket_handle parent_s, SSL* ssl, SOCKET_TYPE st, SOCKET_APP_TYPE sat, const ioa_addr *remote_addr, const ioa_addr *local_addr) { + if(!parent_s) + return NULL; + ioa_socket_handle ret = create_ioa_socket_from_fd(e, parent_s->fd, parent_s, st, sat, remote_addr, local_addr); if(ret) { @@ -1637,7 +1634,7 @@ void close_ioa_socket(ioa_socket_handle s) } } -ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach) +ioa_socket_handle detach_ioa_socket(ioa_socket_handle s) { ioa_socket_handle ret = NULL; @@ -1669,14 +1666,15 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach) evutil_socket_t udp_fd = -1; - if(full_detach && s->parent_s) { - + if(s->parent_s) { +#if defined(SO_REUSEPORT) udp_fd = socket(s->local_addr.ss.sa_family, SOCK_DGRAM, 0); if (udp_fd < 0) { perror("socket"); TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"%s: Cannot allocate new socket\n",__FUNCTION__); return ret; } +#endif } detach_socket_net_data(s); @@ -1711,15 +1709,20 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach) ret->local_addr_known = s->local_addr_known; addr_cpy(&(ret->local_addr),&(s->local_addr)); ret->connected = s->connected; - ioa_socket_handle parent_s = s->parent_s; addr_cpy(&(ret->remote_addr),&(s->remote_addr)); + ioa_socket_handle parent_s = s->parent_s; ur_addr_map *sockets_container = s->sockets_container; - + delete_socket_from_map(s); delete_socket_from_parent(s); - if(full_detach && parent_s) { + if(udp_fd<0) { + + add_socket_to_parent(parent_s, ret); + add_socket_to_map(ret,sockets_container); + + } else { ret->fd = udp_fd; @@ -1741,10 +1744,6 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach) } set_socket_options(ret); - - } else { - add_socket_to_parent(parent_s, ret); - add_socket_to_map(ret,sockets_container); } ret->current_ttl = s->current_ttl; @@ -1825,7 +1824,7 @@ void set_ioa_socket_app_type(ioa_socket_handle s, SOCKET_APP_TYPE sat) { ioa_addr* get_local_addr_from_ioa_socket(ioa_socket_handle s) { - if (s) { + if (s && (s->magic == SOCKET_MAGIC) && !(s->done)) { if(s->parent_s) { return get_local_addr_from_ioa_socket(s->parent_s); @@ -1859,7 +1858,7 @@ ioa_addr* get_local_addr_from_ioa_socket(ioa_socket_handle s) ioa_addr* get_remote_addr_from_ioa_socket(ioa_socket_handle s) { - if (s) { + if (s && (s->magic == SOCKET_MAGIC) && !(s->done)) { if (s->connected) { return &(s->remote_addr); @@ -2325,24 +2324,23 @@ static int socket_input_worker(ioa_socket_handle s) if(s->e->tls_ctx_v1_2) { s->ssl = SSL_new(s->e->tls_ctx_v1_2); STRCPY(s->orig_ctx_type,"TLSv1.2"); - break; } + break; #endif #if defined(SSL_TXT_TLSV1_1) case TURN_TLS_v1_1: if(s->e->tls_ctx_v1_1) { s->ssl = SSL_new(s->e->tls_ctx_v1_1); STRCPY(s->orig_ctx_type,"TLSv1.1"); - break; } - + break; #endif case TURN_TLS_v1_0: if(s->e->tls_ctx_v1_0) { s->ssl = SSL_new(s->e->tls_ctx_v1_0); STRCPY(s->orig_ctx_type,"TLSv1.0"); - break; } + break; default: if(s->e->tls_ctx_ssl23) { s->ssl = SSL_new(s->e->tls_ctx_ssl23); diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 7b9559aa..46711e32 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -197,7 +197,7 @@ void stop_ioa_timer(ioa_timer_handle th); void delete_ioa_timer(ioa_timer_handle th); #define IOA_EVENT_DEL(E) do { if(E) { delete_ioa_timer(E); E = NULL; } } while(0) -ioa_socket_handle create_unbound_ioa_socket(ioa_engine_handle e, ioa_socket_handle parent_s, int family, SOCKET_TYPE st, SOCKET_APP_TYPE sat); +ioa_socket_handle create_unbound_ioa_socket(ioa_engine_handle e, int family, SOCKET_TYPE st, SOCKET_APP_TYPE sat); void inc_ioa_socket_ref_counter(ioa_socket_handle s); @@ -235,7 +235,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, ioa_network_buffer_handle nbh, int ttl, int tos); void close_ioa_socket(ioa_socket_handle s); #define IOA_CLOSE_SOCKET(S) do { if(S) { close_ioa_socket(S); S = NULL; } } while(0) -ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach); +ioa_socket_handle detach_ioa_socket(ioa_socket_handle s); void detach_socket_net_data(ioa_socket_handle s); int set_df_on_ioa_socket(ioa_socket_handle s, int value); void set_do_not_use_df(ioa_socket_handle s); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 709976ee..01955cef 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -374,8 +374,10 @@ int turn_session_info_copy_from(struct turn_session_info* tsi, ts_ur_super_sessi } if(ss->alloc.relay_session.s) { tsi->peer_protocol = get_ioa_socket_type(ss->alloc.relay_session.s); - addr_cpy(&(tsi->relay_addr_data.addr),get_local_addr_from_ioa_socket(ss->alloc.relay_session.s)); - addr_to_string(&(tsi->relay_addr_data.addr),(u08bits*)tsi->relay_addr_data.saddr); + if(ss->alloc.is_valid) { + addr_cpy(&(tsi->relay_addr_data.addr),get_local_addr_from_ioa_socket(ss->alloc.relay_session.s)); + addr_to_string(&(tsi->relay_addr_data.addr),(u08bits*)tsi->relay_addr_data.saddr); + } } STRCPY(tsi->username,ss->username); tsi->enforce_fingerprints = ss->enforce_fingerprints; @@ -1238,7 +1240,7 @@ static int handle_turn_refresh(turn_turnserver *server, if(tsid != server->id) { if(server->send_socket_to_relay) { - ioa_socket_handle new_s = detach_ioa_socket(ss->client_session.s, 1); + ioa_socket_handle new_s = detach_ioa_socket(ss->client_session.s); if(new_s) { if(server->send_socket_to_relay(tsid, mid, tid, new_s, message_integrity, RMT_MOBILE_SOCKET, in_buffer)<0) { @@ -1316,7 +1318,7 @@ static int handle_turn_refresh(turn_turnserver *server, //Transfer socket: - ioa_socket_handle s = detach_ioa_socket(ss->client_session.s, 0); + ioa_socket_handle s = detach_ioa_socket(ss->client_session.s); ss->to_be_closed = 1; @@ -1950,7 +1952,7 @@ static int handle_turn_connection_bind(turn_turnserver *server, turnserver_id sid = (id & 0xFF000000)>>24; ioa_socket_handle s = ss->client_session.s; if(s) { - ioa_socket_handle new_s = detach_ioa_socket(s, 1); + ioa_socket_handle new_s = detach_ioa_socket(s); if(new_s) { if(server->send_socket_to_relay(sid, id, tid, new_s, message_integrity, RMT_CB_SOCKET, NULL)<0) { *err_code = 400; @@ -2344,8 +2346,8 @@ static int handle_turn_binding(turn_turnserver *server, stun_attr_get_addr_str(ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh), sar, response_destination, response_destination); - break; } + break; default: if(attr_type>=0x0000 && attr_type<=0x7FFF) unknown_attrs[(*ua_num)++] = nswap16(attr_type); From 6a15715bb29802874fd20e27a1d05bbe0a5388f4 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 27 Apr 2014 17:10:28 +0000 Subject: [PATCH 024/805] minor fix --- src/apps/relay/ns_ioalib_engine_impl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 989074f3..1a12dbb3 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1826,9 +1826,10 @@ ioa_addr* get_local_addr_from_ioa_socket(ioa_socket_handle s) { if (s && (s->magic == SOCKET_MAGIC) && !(s->done)) { - if(s->parent_s) { - return get_local_addr_from_ioa_socket(s->parent_s); - } else if (s->local_addr_known) { + if(s->parent_s) + s = s->parent_s; + + if (s->local_addr_known) { return &(s->local_addr); } else if (s->bound && (addr_get_port(&(s->local_addr)) > 0)) { s->local_addr_known = 1; @@ -1871,7 +1872,7 @@ int get_local_mtu_ioa_socket(ioa_socket_handle s) { if(s) { if(s->parent_s) - return get_local_mtu_ioa_socket(s->parent_s); + s = s->parent_s; return get_socket_mtu(s->fd, s->family, (s->e && eve(s->e->verbose))); } From c1d067d9577f80a86a9779f7e21129e35a7d611e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 27 Apr 2014 18:22:07 +0000 Subject: [PATCH 025/805] compilation warning fixed --- src/server/ns_turn_maps.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/server/ns_turn_maps.c b/src/server/ns_turn_maps.c index d5d3504b..7fc1bc76 100644 --- a/src/server/ns_turn_maps.c +++ b/src/server/ns_turn_maps.c @@ -164,6 +164,11 @@ int ur_map_exist(const ur_map* map, ur_map_key_type key) { void ur_map_free(ur_map** map) { if(map && ur_map_valid(*map)) { + { + static int khctest=0; + if(khctest) + kh_clear(3,(*map)->h); + } kh_destroy(3,(*map)->h); (*map)->h=NULL; (*map)->magic=0; From 94a676b816108882266a6cd3b821dca19b9a245e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 28 Apr 2014 00:09:00 +0000 Subject: [PATCH 026/805] dtls mobile fix --- src/apps/relay/ns_ioalib_engine_impl.c | 9 ++++----- src/server/ns_turn_ioalib.h | 2 +- src/server/ns_turn_server.c | 6 +++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 1a12dbb3..7f2b896d 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1634,7 +1634,7 @@ void close_ioa_socket(ioa_socket_handle s) } } -ioa_socket_handle detach_ioa_socket(ioa_socket_handle s) +ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach) { ioa_socket_handle ret = NULL; @@ -1666,15 +1666,13 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s) evutil_socket_t udp_fd = -1; - if(s->parent_s) { -#if defined(SO_REUSEPORT) + if(s->parent_s && full_detach) { udp_fd = socket(s->local_addr.ss.sa_family, SOCK_DGRAM, 0); if (udp_fd < 0) { perror("socket"); TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"%s: Cannot allocate new socket\n",__FUNCTION__); return ret; } -#endif } detach_socket_net_data(s); @@ -1826,8 +1824,9 @@ ioa_addr* get_local_addr_from_ioa_socket(ioa_socket_handle s) { if (s && (s->magic == SOCKET_MAGIC) && !(s->done)) { - if(s->parent_s) + if(s->parent_s) { s = s->parent_s; + } if (s->local_addr_known) { return &(s->local_addr); diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 46711e32..896f797c 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -235,7 +235,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, ioa_network_buffer_handle nbh, int ttl, int tos); void close_ioa_socket(ioa_socket_handle s); #define IOA_CLOSE_SOCKET(S) do { if(S) { close_ioa_socket(S); S = NULL; } } while(0) -ioa_socket_handle detach_ioa_socket(ioa_socket_handle s); +ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach); void detach_socket_net_data(ioa_socket_handle s); int set_df_on_ioa_socket(ioa_socket_handle s, int value); void set_do_not_use_df(ioa_socket_handle s); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 01955cef..e5738f87 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1240,7 +1240,7 @@ static int handle_turn_refresh(turn_turnserver *server, if(tsid != server->id) { if(server->send_socket_to_relay) { - ioa_socket_handle new_s = detach_ioa_socket(ss->client_session.s); + ioa_socket_handle new_s = detach_ioa_socket(ss->client_session.s,1); if(new_s) { if(server->send_socket_to_relay(tsid, mid, tid, new_s, message_integrity, RMT_MOBILE_SOCKET, in_buffer)<0) { @@ -1318,7 +1318,7 @@ static int handle_turn_refresh(turn_turnserver *server, //Transfer socket: - ioa_socket_handle s = detach_ioa_socket(ss->client_session.s); + ioa_socket_handle s = detach_ioa_socket(ss->client_session.s,0); ss->to_be_closed = 1; @@ -1952,7 +1952,7 @@ static int handle_turn_connection_bind(turn_turnserver *server, turnserver_id sid = (id & 0xFF000000)>>24; ioa_socket_handle s = ss->client_session.s; if(s) { - ioa_socket_handle new_s = detach_ioa_socket(s); + ioa_socket_handle new_s = detach_ioa_socket(s,1); if(new_s) { if(server->send_socket_to_relay(sid, id, tid, new_s, message_integrity, RMT_CB_SOCKET, NULL)<0) { *err_code = 400; From 48534765fd7e1ec6581b48a4a4a432ca79a7121e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 30 Apr 2014 05:42:48 +0000 Subject: [PATCH 027/805] version up to 4.0.0.0 --- ChangeLog | 4 ++-- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 6 +++--- src/ns_turn_defs.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index fc896c1e..67ff849b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ -04/20/2014 Oleg Moskalenko -Version 3.3.0.0 'Threetrees': +04/30/2014 Oleg Moskalenko +Version 4.0.0.0 'Threetrees': - multi-tenant server. 04/13/2014 Oleg Moskalenko diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 1e610702..098b0ed5 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=3.3.0.0 +TURNVERSION=4.0.0.0 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index b566e097..37dfbe8d 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 3.3.0.0 +Version: 4.0.0.0 Release: 0%{dist} Summary: Coturn TURN Server @@ -288,8 +288,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Sun Feb 09 2014 Oleg Moskalenko - - Sync to 3.3.0.0 +* Wed Apr 30 2014 Oleg Moskalenko + - Sync to 4.0.0.0 * Tue Feb 04 2014 Oleg Moskalenko - Sync to 3.2.2.6 * Sat Jan 25 2014 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index bbf364d2..274e1f7b 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "3.3.0.0" +#define TURN_SERVER_VERSION "4.0.0.0" #define TURN_SERVER_VERSION_NAME "Threetrees" #define TURN_SOFTWARE "Coturn-"TURN_SERVER_VERSION" '"TURN_SERVER_VERSION_NAME"'" From 4843e4bbda9126106b3ef0c494cd5972ecac38bb Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 30 Apr 2014 06:37:51 +0000 Subject: [PATCH 028/805] compilation warnings fixed --- src/apps/relay/userdb.c | 2 ++ src/client/ns_turn_ioaddr.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index c6a5503a..03a7ed0a 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -2895,6 +2895,8 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b void auth_ping(redis_context_handle rch) { + UNUSED_ARG(rch); + donot_print_connection_success = 1; #if !defined(TURN_NO_PQ) diff --git a/src/client/ns_turn_ioaddr.c b/src/client/ns_turn_ioaddr.c index ef55ab14..26925f36 100644 --- a/src/client/ns_turn_ioaddr.c +++ b/src/client/ns_turn_ioaddr.c @@ -90,7 +90,7 @@ u32bits hash_int32(u32bits a) u64bits hash_int64(u64bits a) { a = a ^ (a>>4); - a = (a^0xdeadbeefdeadbeef) + (a<<5); + a = (a^0xdeadbeefdeadbeefLL) + (a<<5); a = a ^ (a>>11); return a; } From bbf085a3dc839bcf5901a6fb05bef3147a657bb8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 30 Apr 2014 07:06:17 +0000 Subject: [PATCH 029/805] tls message fixed --- src/apps/relay/ns_ioalib_engine_impl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 7f2b896d..e1228c8f 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1709,6 +1709,8 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach) ret->connected = s->connected; addr_cpy(&(ret->remote_addr),&(s->remote_addr)); + STRCPY(ret->orig_ctx_type, s->orig_ctx_type); + ioa_socket_handle parent_s = s->parent_s; ur_addr_map *sockets_container = s->sockets_container; From bb3930bfa52f9e24bbc6c3bc5b4277cd0e79b398 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 30 Apr 2014 07:27:29 +0000 Subject: [PATCH 030/805] lation warning fixed --- src/apps/relay/userdb.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 03a7ed0a..95af55fd 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -908,6 +908,8 @@ static redisContext *get_redis_connection(void) static int get_auth_secrets(secrets_list_t *sl, u08bits *realm) { + UNUSED_ARG(realm); + int ret = -1; clean_secrets_list(sl); @@ -1652,6 +1654,8 @@ int add_user_account(char *user, int dynamic) static int list_users(int is_st, u08bits *realm) { + UNUSED_ARG(realm); + donot_print_connection_success = 1; if(is_pqsql_userdb()){ @@ -2209,6 +2213,8 @@ static int del_origin(u08bits *origin0) static int list_origins(u08bits *realm) { + UNUSED_ARG(realm); + donot_print_connection_success = 1; if(is_pqsql_userdb()){ @@ -2422,6 +2428,8 @@ static int set_realm_option(u08bits *realm, perf_options_t *po) static int list_realm_options(u08bits *realm) { + UNUSED_ARG(realm); + donot_print_connection_success = 1; if(is_pqsql_userdb()){ From 93c0f6d8ff87d6a943bf1d637d6183c2f8ce5fa5 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 30 Apr 2014 08:00:29 +0000 Subject: [PATCH 031/805] dtls fixes --- src/apps/relay/dtls_listener.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index 7d38778f..fa36f715 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -569,6 +569,9 @@ static int create_new_connected_udp_socket( ioa_network_buffer_delete(server->e, server->sm.m.sm.nd.nbh); server->sm.m.sm.nd.nbh = NULL; + + ret->st = DTLS_SOCKET; + STRCPY(ret->orig_ctx_type,"DTLSv1.0"); } #endif From 39e855373b1372c89bf6582dd4d02c2d340b5317 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 1 May 2014 06:18:42 +0000 Subject: [PATCH 032/805] compilation warning fixed --- src/apps/common/ns_turn_utils.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/apps/common/ns_turn_utils.c b/src/apps/common/ns_turn_utils.c index 652d2006..3a04f994 100644 --- a/src/apps/common/ns_turn_utils.c +++ b/src/apps/common/ns_turn_utils.c @@ -598,9 +598,9 @@ int get_canonic_origin(const char* o, char *co, int sz) otmp[schlen]=0; { - char *s = otmp; + unsigned char *s = (unsigned char*)otmp; while(*s) { - *s = (char)tolower(*s); + *s = (unsigned char)tolower((int)*s); ++s; } } @@ -615,9 +615,9 @@ int get_canonic_origin(const char* o, char *co, int sz) snprintf(otmp+schlen,sizeof(otmp)-schlen-1,"://%s",host); { - char *s = otmp + schlen + 3; + unsigned char *s = (unsigned char*)otmp + schlen + 3; while(*s) { - *s = (char)tolower(*s); + *s = (unsigned char)tolower((int)*s); ++s; } } From 151666d349efb891b45e431a73b50a73d3faff9a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 1 May 2014 16:36:38 +0000 Subject: [PATCH 033/805] compilation warning fixed --- src/apps/common/ns_turn_utils.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/apps/common/ns_turn_utils.c b/src/apps/common/ns_turn_utils.c index 3a04f994..ca0a5777 100644 --- a/src/apps/common/ns_turn_utils.c +++ b/src/apps/common/ns_turn_utils.c @@ -281,11 +281,13 @@ void reset_rtpprintf(void) log_unlock(); } -static void set_log_file_name(char *base, char *f) +#define set_log_file_name(base, f) set_log_file_name_func(base, f, sizeof(f)) + +static void set_log_file_name_func(char *base, char *f, size_t fsz) { if(simple_log) { - STRCPY(f,base); - return; + strncpy(f,base,fsz); + return; } char logdate[125]; From f41deb4317d55d4ead567a9f95681c15ab66b674 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 2 May 2014 06:16:04 +0000 Subject: [PATCH 034/805] uclient fix --- src/apps/uclient/uclient.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index bc27d38e..75827a38 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1128,7 +1128,12 @@ static inline int client_timer_handler(app_ur_session* elem, int *done) if(hang_on && elem->completed) return 0; - if (!turn_time_before(current_mstime, elem->to_send_timems)) { + int max_num = 50; + int cur_num = 0; + + while (!turn_time_before(current_mstime, elem->to_send_timems)) { + if(cur_num++>=max_num) + break; if (elem->wmsgnum >= elem->tot_msgnum) { if (!turn_time_before(current_mstime, elem->finished_time) || (tot_recv_messages>=tot_messages)) { From b746c689e1ffb339b38bf404f7b8abb2cbb7e039 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 2 May 2014 06:38:36 +0000 Subject: [PATCH 035/805] changelog updated --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 67ff849b..e2e8d779 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -04/30/2014 Oleg Moskalenko +05/02/2014 Oleg Moskalenko Version 4.0.0.0 'Threetrees': - multi-tenant server. From 08376156ecb30d641a141b7bd2543ed5cdb060f6 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 2 May 2014 07:31:50 +0000 Subject: [PATCH 036/805] changelog updated --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e2e8d779..4390fbf9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ 05/02/2014 Oleg Moskalenko Version 4.0.0.0 'Threetrees': - - multi-tenant server. + - Multi-tenant server. 04/13/2014 Oleg Moskalenko Version 3.2.3.6 'Marshal West': From ce1fcd3263fb9c91164a449093f126bb87c8d15c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 3 May 2014 06:30:11 +0000 Subject: [PATCH 037/805] uninstall fixed in rpm --- rpm/uninstall.turnserver.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rpm/uninstall.turnserver.sh b/rpm/uninstall.turnserver.sh index 01cd3643..bc444ab7 100755 --- a/rpm/uninstall.turnserver.sh +++ b/rpm/uninstall.turnserver.sh @@ -1,18 +1,18 @@ #!/bin/sh -for i in `rpm -q -a | grep turnserver-utils-3` +for i in `rpm -q -a | grep turnserver-utils-` do echo $i sudo rpm -e $i done -for i in `rpm -q -a | grep turnserver-client-libs-3` +for i in `rpm -q -a | grep turnserver-client-libs-` do echo $i sudo rpm -e $i done -for i in `rpm -q -a | grep turnserver.*-3` +for i in `rpm -q -a | grep turnserver.*-` do echo $i sudo rpm -e $i From e663e34c8ec5e2a4cc22b2cf4b6396a81639f67f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 5 May 2014 03:06:42 +0000 Subject: [PATCH 038/805] file executable attribute removed --- turndb/testsqldbsetup.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/turndb/testsqldbsetup.sql b/turndb/testsqldbsetup.sql index 4b7d8383..32b390ed 100755 --- a/turndb/testsqldbsetup.sql +++ b/turndb/testsqldbsetup.sql @@ -26,4 +26,3 @@ insert into allowed_peer_ip (ip_range) values('172.17.13.200'); insert into denied_peer_ip (ip_range) values('172.17.13.133-172.17.14.56'); insert into denied_peer_ip (ip_range) values('123::45'); - From 36d491dfe81b8006908c79bb2a2e16c0e614d9a9 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 5 May 2014 03:11:49 +0000 Subject: [PATCH 039/805] exec property deleted --- turndb/testsqldbsetup.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 turndb/testsqldbsetup.sql diff --git a/turndb/testsqldbsetup.sql b/turndb/testsqldbsetup.sql old mode 100755 new mode 100644 From 3540c854415012291580168dc8655c51d5da68cb Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 7 May 2014 07:26:17 +0000 Subject: [PATCH 040/805] kernel channels definitions --- ChangeLog | 4 ++++ rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/ns_turn_defs.h | 16 +++++++++++++++- src/server/ns_turn_allocation.c | 12 ++++++++---- src/server/ns_turn_allocation.h | 1 + src/server/ns_turn_server.c | 13 +++++++++++++ 7 files changed, 45 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4390fbf9..78d391e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +05/07/2014 Oleg Moskalenko +Version 4.0.0.1 'Threetrees': + - Kernel channel placeholder definitions. + 05/02/2014 Oleg Moskalenko Version 4.0.0.0 'Threetrees': - Multi-tenant server. diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 098b0ed5..a85378fa 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.0.0.0 +TURNVERSION=4.0.0.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 37dfbe8d..2b63720b 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.0.0.0 +Version: 4.0.0.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -288,6 +288,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Wed May 07 2014 Oleg Moskalenko + - Sync to 4.0.0.1 * Wed Apr 30 2014 Oleg Moskalenko - Sync to 4.0.0.0 * Tue Feb 04 2014 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 274e1f7b..05f602da 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.0.0.0" +#define TURN_SERVER_VERSION "4.0.0.1" #define TURN_SERVER_VERSION_NAME "Threetrees" #define TURN_SOFTWARE "Coturn-"TURN_SERVER_VERSION" '"TURN_SERVER_VERSION_NAME"'" @@ -174,6 +174,20 @@ typedef enum _SHATYPE SHATYPE; #define SHA_TOO_WEAK (426) +//////////////// KERNEL-LEVEL CHANNEL HANDLERS ///////// + +#if !defined(TURN_CHANNEL_HANDLER_KERNEL) +#define TURN_CHANNEL_HANDLER_KERNEL void* +#endif + +#if !defined(CREATE_TURN_CHANNEL_KERNEL) +#define CREATE_TURN_CHANNEL_KERNEL(channel_number, address_family_client, address_family_peer, protocol_client, client_addr, local_addr, local_relay_addr, peer_addr) ((TURN_CHANNEL_HANDLER_KERNEL)(1)) +#endif + +#if !defined(DELETE_TURN_CHANNEL_KERNEL) +#define DELETE_TURN_CHANNEL_KERNEL(handler) +#endif + //////////////////////////////////////////////////////// #ifdef __cplusplus diff --git a/src/server/ns_turn_allocation.c b/src/server/ns_turn_allocation.c index e337aab1..f53be24f 100644 --- a/src/server/ns_turn_allocation.c +++ b/src/server/ns_turn_allocation.c @@ -215,10 +215,14 @@ static turn_permission_info* get_from_turn_permission_hashtable(turn_permission_ } static void ch_info_clean(ch_info* c) { - if(c) { - IOA_EVENT_DEL(c->lifetime_ev); - ns_bzero(c,sizeof(ch_info)); - } + if (c) { + if (c->kernel_channel) { + DELETE_TURN_CHANNEL_KERNEL(c->kernel_channel); + c->kernel_channel = 0; + } + IOA_EVENT_DEL(c->lifetime_ev); + ns_bzero(c,sizeof(ch_info)); + } } static int delete_channel_info_from_allocation_map(ur_map_key_type key, ur_map_value_type value) diff --git a/src/server/ns_turn_allocation.h b/src/server/ns_turn_allocation.h index 200db1f1..f0da2a00 100644 --- a/src/server/ns_turn_allocation.h +++ b/src/server/ns_turn_allocation.h @@ -127,6 +127,7 @@ typedef struct _ch_info { turn_time_t expiration_time; ioa_timer_handle lifetime_ev; void *owner; //perm + TURN_CHANNEL_HANDLER_KERNEL kernel_channel; } ch_info; ///////////// "channel" map ///////////////////// diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index e5738f87..c80520e1 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -2241,6 +2241,19 @@ static int handle_turn_channel_bind(turn_turnserver *server, stun_set_channel_bind_response_str(ioa_network_buffer_data(nbh), &len, tid, 0, NULL); ioa_network_buffer_set_size(nbh,len); *resp_constructed = 1; + + if(get_ioa_socket_type(ss->client_session.s) == UDP_SOCKET || + get_ioa_socket_type(ss->client_session.s) == TCP_SOCKET) { + chn->kernel_channel = CREATE_TURN_CHANNEL_KERNEL(chn->chnum, + get_ioa_socket_address_family(ss->client_session.s), + get_ioa_socket_address_family(ss->alloc.relay_session.s), + get_ioa_socket_type(ss->client_session.s)==UDP_SOCKET ? IPPROTO_UDP : IPPROTO_TCP, + &(get_remote_addr_from_ioa_socket(ss->client_session.s)->ss), + &(get_local_addr_from_ioa_socket(ss->client_session.s)->ss), + &(get_local_addr_from_ioa_socket(ss->alloc.relay_session.s)), + &(get_remote_addr_from_ioa_socket(ss->alloc.relay_session.s)) + ); + } } } } From 25c68ead315a70ef14a5880ed026fb6eeeb447f5 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 9 May 2014 07:51:47 +0000 Subject: [PATCH 041/805] kernel channel condition improved --- src/server/ns_turn_server.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index c80520e1..42b35180 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -2242,17 +2242,21 @@ static int handle_turn_channel_bind(turn_turnserver *server, ioa_network_buffer_set_size(nbh,len); *resp_constructed = 1; - if(get_ioa_socket_type(ss->client_session.s) == UDP_SOCKET || - get_ioa_socket_type(ss->client_session.s) == TCP_SOCKET) { - chn->kernel_channel = CREATE_TURN_CHANNEL_KERNEL(chn->chnum, - get_ioa_socket_address_family(ss->client_session.s), - get_ioa_socket_address_family(ss->alloc.relay_session.s), - get_ioa_socket_type(ss->client_session.s)==UDP_SOCKET ? IPPROTO_UDP : IPPROTO_TCP, - &(get_remote_addr_from_ioa_socket(ss->client_session.s)->ss), - &(get_local_addr_from_ioa_socket(ss->client_session.s)->ss), - &(get_local_addr_from_ioa_socket(ss->alloc.relay_session.s)), - &(get_remote_addr_from_ioa_socket(ss->alloc.relay_session.s)) - ); + if(!(ss->is_mobile)) { + if(get_ioa_socket_type(ss->client_session.s) == UDP_SOCKET || + get_ioa_socket_type(ss->client_session.s) == TCP_SOCKET) { + if(get_ioa_socket_type(ss->alloc.relay_session.s) == UDP_SOCKET) { + chn->kernel_channel = CREATE_TURN_CHANNEL_KERNEL(chn->chnum, + get_ioa_socket_address_family(ss->client_session.s), + get_ioa_socket_address_family(ss->alloc.relay_session.s), + (get_ioa_socket_type(ss->client_session.s)==UDP_SOCKET ? IPPROTO_UDP : IPPROTO_TCP), + &(get_remote_addr_from_ioa_socket(ss->client_session.s)->ss), + &(get_local_addr_from_ioa_socket(ss->client_session.s)->ss), + &(get_local_addr_from_ioa_socket(ss->alloc.relay_session.s)), + &(get_remote_addr_from_ioa_socket(ss->alloc.relay_session.s)) + ); + } + } } } } From 60e3477a03f63ae0c2192c7fb284badf419169ca Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 11 May 2014 21:55:10 +0000 Subject: [PATCH 042/805] platform fixes --- INSTALL | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/INSTALL b/INSTALL index 18581344..47bf5f87 100644 --- a/INSTALL +++ b/INSTALL @@ -208,15 +208,16 @@ The following platforms have been used in the development: - Linux CentOS / Red Hat Enterprise Edition 6.4, x86_32 (i386) - Linux Debian 'Squeeze', i386 - Linux Mint 14.1 'Nadia', i386 + - Linux Mint 16 'Petra', i386 - Linux Debian 'Wheezy', x86_64 - Cygwin 1.7.20 - - NetBSD 6.0.1 - - OpenBSD 5.3 - - Amazon Linux + - NetBSD 6.0.1, i386 + - OpenBSD 5.3, i386 + - Amazon Linux, x86_64 - Mac OS X Mountain Lion - - ArchLinux - - Fedora 19 - - OpenSUSE 12.3 x86_64 + - ArchLinux, x86_64 + - Fedora 19 and 20, x86_64 + - OpenSUSE 12.3, x86_64 It must work on many other *NIXes, as well. The configure script and/or Makefile may need adjustments for other *NIXes not mentioned above. From e1630467d608ff753183fcf4a349d8ce91b77352 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 16 May 2014 05:35:24 +0000 Subject: [PATCH 043/805] TODO updated --- TODO | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/TODO b/TODO index fa334dea..f7c5af84 100644 --- a/TODO +++ b/TODO @@ -27,7 +27,7 @@ ================================================================== -1) Exclusive IP addresses for relay +1) Kernel module for data channels. ================================================================== @@ -41,20 +41,6 @@ the slave servers, currently it is only just a dumb round-robin load distributor. -2) For a large enterprise, a user-space stack to be integrated. - - An another socket abstraction to be implemented, - the one that uses the user-space TCP/IP stack with - zero memory copy. This is an ambitious goal that would - increase the system scaleability, significantly. - The stock TCP/IP stack in UNIX and in MS Windows do not - scale gracefully. We are trying to suppress those issues - in the TURN Server, by using an advanced synchronous - I/O technique, but still the underlying stock TCP/IP stack - is a limitation. - -3) Multiple authentication threads. - ================================================================== ### V. SECURITY ### @@ -63,15 +49,13 @@ 1) RADIUS integration ? -2) Watch new TURN security draft. oAuth integration. - ================================================================== ### VI. STANDARDS SUPPORT ### ================================================================== -1) Follow the draft ICE endpoint mobility standard and add changes +1) Follow the draft ICE endpoint mobility standard and apply changes when necessary: https://ietf.org/doc/draft-wing-mmusic-ice-mobility/ @@ -82,10 +66,14 @@ when necessary: 4) Bandwidth draft. -5) ALPN with TLS and DTLS. +5) ALPN with TLS and DTLS (when OpenSSL 1.0.2 is available). 6) Redirect draft. +7) Dual allocation draft. + +8) New security oAuth draft. + ================================================================== ### VII. MISC FEATURES ### From 062b59fdf091fdd85f828eddb4abfaaa3e198069 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 19 May 2014 02:00:42 +0000 Subject: [PATCH 044/805] Code cleaning --- ChangeLog | 4 ++ Makefile.in | 2 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 5 ++- src/apps/uclient/startuclient.c | 12 +++--- src/apps/uclient/uclient.c | 2 +- src/client/ns_turn_msg.c | 2 +- src/client/ns_turn_msg_defs.h | 9 ++--- src/client/ns_turn_msg_defs_new.h | 61 +++++++++++++++++++++++++++++++ src/ns_turn_defs.h | 20 +--------- src/server/ns_turn_server.c | 4 +- 11 files changed, 85 insertions(+), 38 deletions(-) create mode 100644 src/client/ns_turn_msg_defs_new.h diff --git a/ChangeLog b/ChangeLog index 78d391e5..478ab561 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +05/18/2014 Oleg Moskalenko +Version 4.0.0.2 'Threetrees': + - Code cleaning. + 05/07/2014 Oleg Moskalenko Version 4.0.0.1 'Threetrees': - Kernel channel placeholder definitions. diff --git a/Makefile.in b/Makefile.in index 785d738e..cea66b34 100755 --- a/Makefile.in +++ b/Makefile.in @@ -7,7 +7,7 @@ CFLAGS += ${INCFLAGS} MAKE_DEPS = Makefile -LIBCLIENTTURN_HEADERS = src/ns_turn_defs.h src/client++/TurnMsgLib.h src/client/ns_turn_ioaddr.h src/client/ns_turn_msg.h src/client/ns_turn_msg_defs.h src/client/ns_turn_msg_addr.h +LIBCLIENTTURN_HEADERS = src/ns_turn_defs.h src/client++/TurnMsgLib.h src/client/ns_turn_ioaddr.h src/client/ns_turn_msg.h src/client/ns_turn_msg_defs.h src/client/ns_turn_msg_defs_new.h src/client/ns_turn_msg_addr.h LIBCLIENTTURN_MODS = src/client/ns_turn_ioaddr.c src/client/ns_turn_msg_addr.c src/client/ns_turn_msg.c LIBCLIENTTURN_DEPS = ${LIBCLIENTTURN_HEADERS} ${MAKE_DEPS} LIBCLIENTTURN_OBJS = build/obj/ns_turn_ioaddr.o build/obj/ns_turn_msg_addr.o build/obj/ns_turn_msg.o diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index a85378fa..c75808eb 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.0.0.1 +TURNVERSION=4.0.0.2 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 2b63720b..fe0d9fb0 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.0.0.1 +Version: 4.0.0.2 Release: 0%{dist} Summary: Coturn TURN Server @@ -284,10 +284,13 @@ fi %{_includedir}/turn/client/ns_turn_ioaddr.h %{_includedir}/turn/client/ns_turn_msg_addr.h %{_includedir}/turn/client/ns_turn_msg_defs.h +%{_includedir}/turn/client/ns_turn_msg_defs_new.h %{_includedir}/turn/client/ns_turn_msg.h %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Sun May 18 2014 Oleg Moskalenko + - Sync to 4.0.0.2 * Wed May 07 2014 Oleg Moskalenko - Sync to 4.0.0.1 * Wed Apr 30 2014 Oleg Moskalenko diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 35016c8a..825478e0 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -439,14 +439,14 @@ static int clnet_allocate(int verbose, } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce)) { - if(err_code == SHA_TOO_WEAK && (clnet_info->shatype == SHATYPE_SHA1)) { + if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { clnet_info->shatype = SHATYPE_SHA256; recalculate_restapi_hmac(); } goto beg_allocate; } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { - if(err_code == SHA_TOO_WEAK && (clnet_info->shatype == SHATYPE_SHA1) && use_short_term) { + if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1) && use_short_term) { clnet_info->shatype = SHATYPE_SHA256; goto beg_allocate; } @@ -627,7 +627,7 @@ static int clnet_allocate(int verbose, } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce)) { - if(err_code == SHA_TOO_WEAK && (clnet_info->shatype == SHATYPE_SHA1)) { + if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { clnet_info->shatype = SHATYPE_SHA256; recalculate_restapi_hmac(); } @@ -728,7 +728,7 @@ static int turn_channel_bind(int verbose, uint16_t *chn, } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce)) { - if(err_code == SHA_TOO_WEAK && (clnet_info->shatype == SHATYPE_SHA1)) { + if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { clnet_info->shatype = SHATYPE_SHA256; recalculate_restapi_hmac(); } @@ -839,7 +839,7 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce)) { - if(err_code == SHA_TOO_WEAK && (clnet_info->shatype == SHATYPE_SHA1)) { + if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { clnet_info->shatype = SHATYPE_SHA256; recalculate_restapi_hmac(); } @@ -1418,7 +1418,7 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce)) { - if(err_code == SHA_TOO_WEAK && (clnet_info->shatype == SHATYPE_SHA1)) { + if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { clnet_info->shatype = SHATYPE_SHA256; recalculate_restapi_hmac(); } diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 75827a38..4180eb36 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -596,7 +596,7 @@ static int client_read(app_ur_session *elem, int is_tcp_data, app_tcp_conn_info } else if (stun_is_challenge_response_str(elem->in_buffer.buf, (size_t)elem->in_buffer.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce)) { - if(err_code == SHA_TOO_WEAK && (elem->pinfo.shatype == SHATYPE_SHA1)) { + if(err_code == SHA_TOO_WEAK_ERROR_CODE && (elem->pinfo.shatype == SHATYPE_SHA1)) { elem->pinfo.shatype = SHATYPE_SHA256; recalculate_restapi_hmac(); } diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index ceeada67..955a240b 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -281,7 +281,7 @@ int stun_is_challenge_response_str(const u08bits* buf, size_t len, int *err_code { int ret = stun_is_error_response_str(buf, len, err_code, err_msg, err_msg_size); - if(ret && (((*err_code) == 401) || ((*err_code) == 438) || ((*err_code) == SHA_TOO_WEAK))) { + if(ret && (((*err_code) == 401) || ((*err_code) == 438) || ((*err_code) == SHA_TOO_WEAK_ERROR_CODE))) { stun_attr_ref sar = stun_attr_get_first_by_type_str(buf,len,STUN_ATTRIBUTE_REALM); if(sar) { diff --git a/src/client/ns_turn_msg_defs.h b/src/client/ns_turn_msg_defs.h index 431e1e88..11548456 100644 --- a/src/client/ns_turn_msg_defs.h +++ b/src/client/ns_turn_msg_defs.h @@ -31,6 +31,8 @@ #ifndef __LIB_TURN_MSG_DEFS__ #define __LIB_TURN_MSG_DEFS__ +#include "ns_turn_msg_defs_new.h" + /////////////////////////////////////////// // http://www.iana.org/assignments/stun-parameters/stun-parameters.xhtml /////////////////////////////////////////// @@ -40,7 +42,6 @@ #define STUN_MAX_USERNAME_SIZE (513) #define STUN_MAX_REALM_SIZE (127) -#define STUN_MAX_ORIGIN_SIZE (127) #define STUN_MAX_NONCE_SIZE (127) #define STUN_MAX_PWD_SIZE (127) @@ -129,7 +130,7 @@ #define STUN_VALID_CHANNEL(chn) ((chn)>=0x4000 && (chn)<=0x7FFF) -///////// values ////////////////// +///////// extra values ////////////////// /* RFC 6156 ==>> */ #define STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4 (0x01) @@ -151,10 +152,6 @@ #define STUN_ATTRIBUTE_MOBILITY_SUPPORT (0x8000) /* <<== Mobility */ -/* Origin ==>> */ -#define STUN_ATTRIBUTE_ORIGIN (0x802F) -/* <<== Origin */ - //////////////////////////////////////////////// #endif //__LIB_TURN_MSG_DEFS__ diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h new file mode 100644 index 00000000..4ec2a16c --- /dev/null +++ b/src/client/ns_turn_msg_defs_new.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011, 2012, 2013 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 __LIB_TURN_MSG_DEFS_NEW__ +#define __LIB_TURN_MSG_DEFS_NEW__ + +/***** POST-RFC5766 FRESH SPECS ***********/ + +/* Origin ==>> */ +#define STUN_MAX_ORIGIN_SIZE (127) +#define STUN_ATTRIBUTE_ORIGIN (0x802F) +/* <<== Origin */ + +/* SHA AGILITY ==>> */ + +#define SHA1SIZEBYTES (20) +#define SHA256SIZEBYTES (32) + +#define MAXSHASIZE (128) + +enum _SHATYPE { + SHATYPE_SHA1 = 0, + SHATYPE_SHA256 +}; + +typedef enum _SHATYPE SHATYPE; + +#define shatype_name(sht) ((sht == SHATYPE_SHA1) ? "SHA1" : ((sht == SHATYPE_SHA256) ? "SHA256" : "SHA UNKNOWN")) + +#define SHA_TOO_WEAK_ERROR_CODE (426) + +/* <<== SHA AGILITY */ + +#endif //__LIB_TURN_MSG_DEFS_NEW__ diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 05f602da..363c91b2 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.0.0.1" +#define TURN_SERVER_VERSION "4.0.0.2" #define TURN_SERVER_VERSION_NAME "Threetrees" #define TURN_SOFTWARE "Coturn-"TURN_SERVER_VERSION" '"TURN_SERVER_VERSION_NAME"'" @@ -156,24 +156,6 @@ typedef u32bits turn_time_t; }\ } } while(0) -////////////////// Security //////////////////////////// - -#define SHA1SIZEBYTES (20) -#define SHA256SIZEBYTES (32) - -#define MAXSHASIZE (128) - -enum _SHATYPE { - SHATYPE_SHA1 = 0, - SHATYPE_SHA256 -}; - -typedef enum _SHATYPE SHATYPE; - -#define shatype_name(sht) ((sht == SHATYPE_SHA1) ? "SHA1" : ((sht == SHATYPE_SHA256) ? "SHA256" : "SHA UNKNOWN")) - -#define SHA_TOO_WEAK (426) - //////////////// KERNEL-LEVEL CHANNEL HANDLERS ///////// #if !defined(TURN_CHANNEL_HANDLER_KERNEL) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 42b35180..041a3935 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -2866,7 +2866,7 @@ static int check_stun_auth(turn_turnserver *server, switch(sarlen) { case SHA1SIZEBYTES: if(server->shatype != SHATYPE_SHA1) { - *err_code = SHA_TOO_WEAK; + *err_code = SHA_TOO_WEAK_ERROR_CODE; return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); } break; @@ -3010,7 +3010,7 @@ static int check_stun_auth(turn_turnserver *server, TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: user %s credentials are incorrect: SHA function is too weak\n", __FUNCTION__, (char*)usname); - *err_code = SHA_TOO_WEAK; + *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); From 0cd2b66e5519e1d5d2b3e9cf0918d428ba5183b8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 21 May 2014 07:35:40 +0000 Subject: [PATCH 045/805] Debian isntall info updated --- INSTALL | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/INSTALL b/INSTALL index 47bf5f87..5c4235d9 100644 --- a/INSTALL +++ b/INSTALL @@ -22,6 +22,33 @@ In the new Debian "jessie", and in the related Ubuntu and Mint, you will be able to just select rfc5766-turn-server from the packages list and install it through Synaptic or through the package manager. +If you are using the Debian package from the project download site, then follow these instructions: + +Unpack the archive: + + $ tar xvfz turnserver-<...>.tar.gz + +Read the INSTALl file: + + $ cat INSTALL + +Install the *.deb file: + + $ sudo apt-get install gdebi-core + $ sudo gdebi coturn*.deb + +(to install the bare package without any dependencies, type: + + $ sudo dpkg -i coturn_*_*.deb) + +After the install, read the documentation in /usr/share/doc/coturn directory. + +All binaries will be installed in /usr/bin/ directory. +The turn*.conf config files are in /etc directory. + +The service start-up control scripts will be in /etc/init.d/coturn and +in /etc/defaults/coturn files. + 3) ArchLinux has alse the predecessor of the TURN server package: https://aur.archlinux.org/packages/rfc5766-turn-server/ From 5a339c60dff18226eff5917c55cf7ec2d9aeff5f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 26 May 2014 07:37:16 +0000 Subject: [PATCH 046/805] working on bandwidth draft --- ChangeLog | 4 ++++ README.turnserver | 5 +++++ examples/etc/turnserver.conf | 7 +++++++ man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 9 ++++++++- man/man1/turnutils.1 | 2 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/apps/relay/mainrelay.c | 14 +++++++++++--- src/apps/relay/mainrelay.h | 1 + src/apps/relay/turncli.c | 1 + src/ns_turn_defs.h | 2 +- 12 files changed, 44 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 478ab561..e5b87590 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +05/25/2014 Oleg Moskalenko +Version 4.0.1.1 'Threetrees': + - Bandwidth draft implemented. + 05/18/2014 Oleg Moskalenko Version 4.0.0.2 'Threetrees': - Code cleaning. diff --git a/README.turnserver b/README.turnserver index a62f008a..fbc0efe7 100644 --- a/README.turnserver +++ b/README.turnserver @@ -377,6 +377,11 @@ Options with required values: that limit will be dropped or temporary suppressed (within the available buffer limits). This option can also be set through the database, for a particular realm. + +-B, --bps-capacity Maximum server capacity. + Total bytes-per-second bandwidth the TURN server is allowed to allocate + for the sessions, combined (input and output network streams are treated + separately). --static-auth-secret Static authentication secret value (a string) for TURN REST API only. If not set, then the turn server will try to use the dynamic value diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 07fdfb32..5cf7f7c1 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -312,6 +312,13 @@ # #max-bps=0 +# +# Maximum server capacity. +# Total bytes-per-second bandwidth the TURN server is allowed to allocate +# for the sessions, combined (input and output network streams are treated separately). +# +# bps-capacity=0 + # Uncomment if no UDP client listener is desired. # By default UDP client listener is always started. # diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index fbdac452..4151f845 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "23 April 2014" "" "" +.TH TURN 1 "26 May 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 14008819..ba47a972 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "23 April 2014" "" "" +.TH TURN 1 "26 May 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -559,6 +559,13 @@ available buffer limits). This option can also be set through the database, for a particular realm. .TP .B +\fB\-B\fP, \fB\-\-bps\-capacity\fP +Maximum server capacity. +Total bytes\-per\-second bandwidth the TURN server is allowed to allocate +for the sessions, combined (input and output network streams are treated +separately). +.TP +.B \fB\-\-static\-auth\-secret\fP Static authentication secret value (a string) for TURN REST API only. If not set, then the turn server will try to use the dynamic value diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index f72b9e68..20a72357 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "23 April 2014" "" "" +.TH TURN 1 "26 May 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index c75808eb..11e7ee82 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.0.0.2 +TURNVERSION=4.0.1.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index fe0d9fb0..c9e0d5f9 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.0.0.2 +Version: 4.0.1.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -289,6 +289,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Sun May 25 2014 Oleg Moskalenko + - Sync to 4.0.1.1 * Sun May 18 2014 Oleg Moskalenko - Sync to 4.0.0.2 * Wed May 07 2014 Oleg Moskalenko diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 7a5ba894..2cc79011 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -92,7 +92,7 @@ LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,"", /////////////// stop server //////////////// 0, /////////////// MISC PARAMS //////////////// -0,0,0,0,0,SHATYPE_SHA1,':',0,0,TURN_CREDENTIALS_NONE,0,0,0,0, +0,0,0,0,0,SHATYPE_SHA1,':',0,0,TURN_CREDENTIALS_NONE,0,0,0,0,0, ///////////// Users DB ////////////// { TURN_USERDB_TYPE_FILE, {"\0",NULL}, {0,NULL,NULL, {NULL,0}} } @@ -400,11 +400,14 @@ static char Usage[] = "Usage: turnserver [options]\n" " This option can also be set through the database, for a particular realm.\n" " -Q, --total-quota Total allocations quota: global limit on concurrent allocations.\n" " This option can also be set through the database, for a particular realm.\n" -" -s, --max-bps Max bytes-per-second bandwidth a TURN session is allowed to handle\n" +" -s, --max-bps Default max bytes-per-second bandwidth a TURN session is allowed to handle\n" " (input and output network streams are treated separately). Anything above\n" " that limit will be dropped or temporary suppressed\n" " (within the available buffer limits).\n" " This option can also be set through the database, for a particular realm.\n" +" -B, --bps-capacity Maximum server capacity.\n" +" Total bytes-per-second bandwidth the TURN server is allowed to allocate\n" +" for the sessions, combined (input and output network streams are treated separately).\n" " -c Configuration file name (default - turnserver.conf).\n" " -b, --userdb User database file name (default - turnuserdb.conf) for long-term credentials only.\n" #if !defined(TURN_NO_PQ) @@ -592,7 +595,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" " Setting to zero value means removal of the option.\n" " -h, --help Help\n"; -#define OPTIONS "c:d:p:L:E:X:i:m:l:r:u:b:e:M:N:O:q:Q:s:C:vVofhznaAS" +#define OPTIONS "c:d:p:L:E:X:i:m:l:r:u:b:B:e:M:N:O:q:Q:s:C:vVofhznaAS" #define ADMIN_OPTIONS "gGORIHlLkaADSdb:e:M:N:u:r:p:s:X:o:h" @@ -694,6 +697,7 @@ static struct option long_options[] = { { "user-quota", required_argument, NULL, 'q' }, { "total-quota", required_argument, NULL, 'Q' }, { "max-bps", required_argument, NULL, 's' }, + { "bps-capacity", required_argument, NULL, 'B' }, { "verbose", optional_argument, NULL, 'v' }, { "Verbose", optional_argument, NULL, 'V' }, { "daemon", optional_argument, NULL, 'o' }, @@ -1103,6 +1107,10 @@ static void set_option(int c, char *value) get_realm(NULL)->options.perf_options.max_bps = atoi(value); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%lu bytes per second allowed per session\n",(unsigned long)turn_params.max_bps); break; + case 'B': + turn_params.bps_capacity = (band_limit_t)atoi(value); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%lu bytes per second allowed, combined server capacity\n",(unsigned long)turn_params.bps_capacity); + break; case NO_UDP_OPT: turn_params.no_udp = get_bool_value(value); break; diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index c5433dc0..2f56ad3c 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -299,6 +299,7 @@ typedef struct _turn_params_ { turn_credential_type ct; int use_auth_secret_with_timestamp; band_limit_t max_bps; + band_limit_t bps_capacity; vint total_quota; vint user_quota; diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index 8712493c..17dcc24b 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -714,6 +714,7 @@ static void cli_print_configuration(struct cli_session* cs) cli_print_uint(cs,(unsigned long)turn_params.min_port,"min-port",0); cli_print_uint(cs,(unsigned long)turn_params.max_port,"max-port",0); + cli_print_uint(cs,(unsigned long)turn_params.bps_capacity,"bps_capacity",0); cli_print_ip_range_list(cs,&turn_params.ip_whitelist,"Whitelist IP",0); cli_print_ip_range_list(cs,&turn_params.ip_blacklist,"Blacklist IP",0); diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 363c91b2..b39538ce 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.0.0.2" +#define TURN_SERVER_VERSION "4.0.1.1" #define TURN_SERVER_VERSION_NAME "Threetrees" #define TURN_SOFTWARE "Coturn-"TURN_SERVER_VERSION" '"TURN_SERVER_VERSION_NAME"'" From ec38153d81ef86e0cddddf368ca4e541a1a010df Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 27 May 2014 01:47:45 +0000 Subject: [PATCH 047/805] working on bandwidth draft --- src/apps/relay/mainrelay.c | 7 ++++++- src/apps/relay/mainrelay.h | 1 + src/apps/relay/netengine.c | 3 ++- src/apps/relay/ns_ioalib_impl.h | 2 -- src/apps/relay/turncli.c | 7 ++++++- src/server/ns_turn_server.c | 5 ++++- src/server/ns_turn_server.h | 8 +++++++- 7 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 2cc79011..c08b09bd 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -92,7 +92,7 @@ LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,"", /////////////// stop server //////////////// 0, /////////////// MISC PARAMS //////////////// -0,0,0,0,0,SHATYPE_SHA1,':',0,0,TURN_CREDENTIALS_NONE,0,0,0,0,0, +0,0,0,0,0,SHATYPE_SHA1,':',0,0,TURN_CREDENTIALS_NONE,0,0,0,0,0,0, ///////////// Users DB ////////////// { TURN_USERDB_TYPE_FILE, {"\0",NULL}, {0,NULL,NULL, {NULL,0}} } @@ -1715,6 +1715,11 @@ int main(int argc, char **argv) } } + if(turn_params.bps_capacity && !(turn_params.max_bps)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nCONFIG ERROR: If you set the --bps-capacity option, then you must set --max-bps options, too.\n"); + exit(-1); + } + if(turn_params.no_udp_relay && turn_params.no_tcp_relay) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nCONFIG ERROR: --no-udp-relay and --no-tcp-relay options cannot be used together.\n"); exit(-1); diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index 2f56ad3c..2dc22307 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -300,6 +300,7 @@ typedef struct _turn_params_ { int use_auth_secret_with_timestamp; band_limit_t max_bps; band_limit_t bps_capacity; + band_limit_t bps_capacity_allocated; vint total_quota; vint user_quota; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 64cab84c..64be86de 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1381,7 +1381,8 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int send_socket_to_relay, &turn_params.secure_stun, turn_params.shatype, &turn_params.mobility, turn_params.server_relay, - send_turn_session_info); + send_turn_session_info, + turn_params.max_bps); if(to_set_rfc5780) { set_rfc5780(&(rs->server), get_alt_addr, send_message_from_listener_to_client); diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 2dee9341..08f22351 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -80,8 +80,6 @@ typedef struct _stun_buffer_list { size_t tsz; } stun_buffer_list; -typedef vint band_limit_t; - /* * New connection callback */ diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index 17dcc24b..ed003d8f 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -361,6 +361,10 @@ static void change_cli_param(struct cli_session* cs, const char* pn) cli_max_output_sessions = atoi(pn+strlen("cli-max-output-sessions")); cli_print_uint(cs,(unsigned long)cli_max_output_sessions,"cli-max-output-sessions",2); return; + } else if(strstr(pn,"bps-capacity")==pn) { + turn_params.bps_capacity = atoi(pn+strlen("bps-capacity")); + cli_print_uint(cs,(unsigned long)turn_params.bps_capacity,"bps-capacity",2); + return; } myprintf(cs, "\n"); @@ -714,7 +718,8 @@ static void cli_print_configuration(struct cli_session* cs) cli_print_uint(cs,(unsigned long)turn_params.min_port,"min-port",0); cli_print_uint(cs,(unsigned long)turn_params.max_port,"max-port",0); - cli_print_uint(cs,(unsigned long)turn_params.bps_capacity,"bps_capacity",0); + cli_print_uint(cs,(unsigned long)turn_params.bps_capacity,"bps-capacity",2); + cli_print_uint(cs,(unsigned long)turn_params.bps_capacity_allocated,"Allocated bps-capacity",0); cli_print_ip_range_list(cs,&turn_params.ip_whitelist,"Whitelist IP",0); cli_print_ip_range_list(cs,&turn_params.ip_blacklist,"Blacklist IP",0); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 041a3935..362c34fe 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4348,7 +4348,8 @@ void init_turn_server(turn_turnserver* server, ip_range_list_t* ip_whitelist, ip_range_list_t* ip_blacklist, 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_turn_session_info_cb send_turn_session_info, + band_limit_t max_bps) { if (!server) return; @@ -4405,6 +4406,8 @@ void init_turn_server(turn_turnserver* server, server->send_socket_to_relay = send_socket_to_relay; + server->max_bps = max_bps; + set_ioa_timer(server->e, 1, 0, timer_timeout_handler, server, 1, "timer_timeout_handler"); } diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index ea740e68..f55470fc 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -92,6 +92,8 @@ typedef void (*release_allocation_quota_cb)(u08bits *username, 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); typedef int (*send_turn_session_info_cb)(struct turn_session_info *tsi); +typedef vint band_limit_t; + struct _turn_turnserver { turnserver_id id; @@ -149,6 +151,9 @@ struct _turn_turnserver { /* Server relay */ int server_relay; + + /* Bandwidth draft: */ + band_limit_t max_bps; }; /////////////////////////////////////////// @@ -182,7 +187,8 @@ void init_turn_server(turn_turnserver* server, SHATYPE shatype, vintp mobility, int server_relay, - send_turn_session_info_cb send_turn_session_info); + send_turn_session_info_cb send_turn_session_info, + band_limit_t max_bps); ioa_engine_handle turn_server_get_engine(turn_turnserver *s); From 9218a1fc4315ca4f91d29156904a8a7c3174f783 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 27 May 2014 04:20:23 +0000 Subject: [PATCH 048/805] working on bandwidth draft --- src/apps/relay/turncli.c | 28 ++++++++++++++++++++-------- src/apps/relay/userdb.c | 9 +++++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index ed003d8f..57050041 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -350,12 +350,16 @@ static void change_cli_param(struct cli_session* cs, const char* pn) if(cs && cs->ts && pn) { if(strstr(pn,"total-quota")==pn) { - int new_quota = change_total_quota(cs->realm, atoi(pn+strlen("total-quota"))); - cli_print_uint(cs,(unsigned long)new_quota,"total-quota",2); + turn_params.total_quota = atoi(pn+strlen("total-quota")); + cli_print_uint(cs,(unsigned long)turn_params.total_quota,"total-quota",2); return; } else if(strstr(pn,"user-quota")==pn) { - int new_quota = change_user_quota(cs->realm, atoi(pn+strlen("user-quota"))); - cli_print_uint(cs,(unsigned long)new_quota,"user-quota",2); + turn_params.user_quota = atoi(pn+strlen("user-quota")); + cli_print_uint(cs,(unsigned long)turn_params.user_quota,"user-quota",2); + return; + } else if(strstr(pn,"max-bps")==pn) { + turn_params.max_bps = atoi(pn+strlen("max-bps")); + cli_print_uint(cs,(unsigned long)turn_params.max_bps,"max-bps",2); return; } else if(strstr(pn,"cli-max-output-sessions")==pn) { cli_max_output_sessions = atoi(pn+strlen("cli-max-output-sessions")); @@ -718,7 +722,6 @@ static void cli_print_configuration(struct cli_session* cs) cli_print_uint(cs,(unsigned long)turn_params.min_port,"min-port",0); cli_print_uint(cs,(unsigned long)turn_params.max_port,"max-port",0); - cli_print_uint(cs,(unsigned long)turn_params.bps_capacity,"bps-capacity",2); cli_print_uint(cs,(unsigned long)turn_params.bps_capacity_allocated,"Allocated bps-capacity",0); cli_print_ip_range_list(cs,&turn_params.ip_whitelist,"Whitelist IP",0); @@ -791,9 +794,18 @@ static void cli_print_configuration(struct cli_session* cs) cli_print_uint(cs,(unsigned long)cs->rp->status.total_current_allocs,"total-current-allocs",0); - cli_print_uint(cs,(unsigned long)cs->rp->options.perf_options.total_quota,"total-quota",2); - cli_print_uint(cs,(unsigned long)cs->rp->options.perf_options.user_quota,"user-quota",2); - cli_print_uint(cs,(unsigned long)cs->rp->options.perf_options.max_bps,"max-bps",0); + myprintf(cs,"\n"); + + cli_print_uint(cs,(unsigned long)turn_params.total_quota,"total-quota",2); + cli_print_uint(cs,(unsigned long)turn_params.user_quota,"user-quota",2); + cli_print_uint(cs,(unsigned long)turn_params.bps_capacity,"bps-capacity",2); + cli_print_uint(cs,(unsigned long)turn_params.max_bps,"max-bps",2); + + myprintf(cs,"\n"); + + cli_print_uint(cs,(unsigned long)cs->rp->options.perf_options.total_quota,"current realm total-quota",0); + cli_print_uint(cs,(unsigned long)cs->rp->options.perf_options.user_quota,"current realm user-quota",0); + cli_print_uint(cs,(unsigned long)cs->rp->options.perf_options.max_bps,"current realm max-bps",0); myprintf(cs,"\n"); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 95af55fd..12b16d1f 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -3282,6 +3282,15 @@ static int set_redis_realm_opt(char *realm, const char* key, vint *value) void reread_realms(void) { + { + realm_params_t* defrp = get_realm(NULL); + ur_string_map_lock(realms); + defrp->options.perf_options.max_bps = turn_params.max_bps; + defrp->options.perf_options.total_quota = turn_params.total_quota; + defrp->options.perf_options.user_quota = turn_params.user_quota; + ur_string_map_unlock(realms); + } + #if !defined(TURN_NO_PQ) PGconn * pqc = get_pqdb_connection(); if(pqc) { From f9608553fb600db22b00b61da2d38d4e819a6b8e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 27 May 2014 07:48:11 +0000 Subject: [PATCH 049/805] working on bandwidth draft --- src/apps/relay/netengine.c | 30 +++++++++++++++++++++++++++++- src/server/ns_turn_server.c | 3 ++- src/server/ns_turn_server.h | 6 ++++-- src/server/ns_turn_session.h | 3 +++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 64be86de..24d981a2 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -77,6 +77,32 @@ static void barrier_wait_func(const char* func, int line) #define barrier_wait() barrier_wait_func(__FUNCTION__,__LINE__) +/////////////// Bandwidth ////////////////// + +static pthread_mutex_t mutex_bps; + +static band_limit_t allocate_bps(band_limit_t bps) +{ + band_limit_t ret = 0; + if(bps>0) { + pthread_mutex_lock(&mutex_bps); + + if(turn_params.bps_capacity_allocated < turn_params.bps_capacity) { + band_limit_t reserve = turn_params.bps_capacity - turn_params.bps_capacity_allocated; + if(reserve <= bps) { + ret = reserve; + turn_params.bps_capacity_allocated = turn_params.bps_capacity; + } else { + ret = bps; + turn_params.bps_capacity_allocated -= ret; + } + } + + pthread_mutex_unlock(&mutex_bps); + } + return ret; +} + /////////////// AUX SERVERS //////////////// static void add_aux_server_list(const char *saddr, turn_server_addrs_list_t *list) @@ -1382,7 +1408,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, - turn_params.max_bps); + turn_params.max_bps, allocate_bps); if(to_set_rfc5780) { set_rfc5780(&(rs->server), get_alt_addr, send_message_from_listener_to_client); @@ -1527,6 +1553,8 @@ void setup_server(void) { evthread_use_pthreads(); + pthread_mutex_init(&mutex_bps, NULL); + #if !defined(TURN_NO_THREAD_BARRIERS) /* relay threads plus auth thread plus main listener thread */ diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 362c34fe..40398cd0 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4349,7 +4349,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, - band_limit_t max_bps) { + band_limit_t max_bps, allocate_bps_cb allocate_bps_func) { if (!server) return; @@ -4407,6 +4407,7 @@ void init_turn_server(turn_turnserver* server, server->send_socket_to_relay = send_socket_to_relay; server->max_bps = max_bps; + server->allocate_bps_func = allocate_bps_func; set_ioa_timer(server->e, 1, 0, timer_timeout_handler, server, 1, "timer_timeout_handler"); } diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index f55470fc..3a76ca39 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -92,7 +92,7 @@ typedef void (*release_allocation_quota_cb)(u08bits *username, 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); typedef int (*send_turn_session_info_cb)(struct turn_session_info *tsi); -typedef vint band_limit_t; +typedef band_limit_t (*allocate_bps_cb)(band_limit_t bps); struct _turn_turnserver { @@ -154,6 +154,7 @@ struct _turn_turnserver { /* Bandwidth draft: */ band_limit_t max_bps; + allocate_bps_cb allocate_bps_func; }; /////////////////////////////////////////// @@ -188,7 +189,8 @@ void init_turn_server(turn_turnserver* server, vintp mobility, int server_relay, send_turn_session_info_cb send_turn_session_info, - band_limit_t max_bps); + band_limit_t max_bps, + allocate_bps_cb allocate_bps_func); ioa_engine_handle turn_server_get_engine(turn_turnserver *s); diff --git a/src/server/ns_turn_session.h b/src/server/ns_turn_session.h index 86c6010e..cd9a8fcd 100644 --- a/src/server/ns_turn_session.h +++ b/src/server/ns_turn_session.h @@ -60,6 +60,7 @@ struct _realm_options_t { //////////////// session info ////////////////////// typedef u64bits turnsession_id; +typedef unsigned int band_limit_t; #define NONCE_MAX_SIZE (NONCE_LENGTH_32BITS*4+1) @@ -103,6 +104,8 @@ struct _ts_ur_super_session { realm_options_t realm_options; int realm_set; s08bits origin[STUN_MAX_ORIGIN_SIZE + 1]; + /* Bandwidth */ + band_limit_t bps; }; ////// Session info for statistics ////// From 3871a2387cafff7977f5cde21ee133ae67c9cdca Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 28 May 2014 01:28:31 +0000 Subject: [PATCH 050/805] debian install procedure fixed --- INSTALL | 1 + 1 file changed, 1 insertion(+) diff --git a/INSTALL b/INSTALL index 5c4235d9..82a0e72d 100644 --- a/INSTALL +++ b/INSTALL @@ -34,6 +34,7 @@ Read the INSTALl file: Install the *.deb file: + $ sudo apt-get update $ sudo apt-get install gdebi-core $ sudo gdebi coturn*.deb From aa0bcabb871b8fc133d8961a481d01348cfe2a89 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 28 May 2014 06:13:07 +0000 Subject: [PATCH 051/805] working on bandwidth draft --- src/apps/relay/mainrelay.h | 8 +++ src/apps/relay/netengine.c | 76 ++++++++++++++++++++++---- src/apps/relay/ns_ioalib_engine_impl.c | 8 +-- src/apps/relay/ns_ioalib_impl.h | 3 +- src/apps/relay/turncli.c | 22 ++++---- src/server/ns_turn_server.c | 3 +- src/server/ns_turn_server.h | 4 +- 7 files changed, 88 insertions(+), 36 deletions(-) diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index 2dc22307..e0ffb118 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -348,6 +348,14 @@ void init_listener(void); void setup_server(void); void run_listener_server(struct listener_server *ls); +////////// BPS //////////////// + +band_limit_t get_bps_capacity_allocated(void); +band_limit_t get_bps_capacity(void); +void set_bps_capacity(band_limit_t value); +band_limit_t get_max_bps(void); +void set_max_bps(band_limit_t value); + /////////////////////////////// #ifdef __cplusplus diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 24d981a2..502a89dc 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -81,20 +81,31 @@ static void barrier_wait_func(const char* func, int line) static pthread_mutex_t mutex_bps; -static band_limit_t allocate_bps(band_limit_t bps) +static band_limit_t allocate_bps(band_limit_t bps, int negative) { band_limit_t ret = 0; if(bps>0) { pthread_mutex_lock(&mutex_bps); - if(turn_params.bps_capacity_allocated < turn_params.bps_capacity) { - band_limit_t reserve = turn_params.bps_capacity - turn_params.bps_capacity_allocated; - if(reserve <= bps) { - ret = reserve; - turn_params.bps_capacity_allocated = turn_params.bps_capacity; + if(!negative) { + + if(turn_params.bps_capacity_allocated < turn_params.bps_capacity) { + band_limit_t reserve = turn_params.bps_capacity - turn_params.bps_capacity_allocated; + if(reserve <= bps) { + ret = reserve; + turn_params.bps_capacity_allocated = turn_params.bps_capacity; + } else { + ret = bps; + turn_params.bps_capacity_allocated -= ret; + } + } + + } else { + if(turn_params.bps_capacity_allocated >= bps) { + turn_params.bps_capacity_allocated -= bps; + ret = turn_params.bps_capacity_allocated; } else { - ret = bps; - turn_params.bps_capacity_allocated -= ret; + turn_params.bps_capacity_allocated = 0; } } @@ -103,6 +114,47 @@ static band_limit_t allocate_bps(band_limit_t bps) return ret; } +band_limit_t get_bps_capacity_allocated(void) +{ + band_limit_t ret = 0; + pthread_mutex_lock(&mutex_bps); + ret = turn_params.bps_capacity_allocated; + pthread_mutex_unlock(&mutex_bps); + return ret; +} + +band_limit_t get_bps_capacity(void) +{ + band_limit_t ret = 0; + pthread_mutex_lock(&mutex_bps); + ret = turn_params.bps_capacity; + pthread_mutex_unlock(&mutex_bps); + return ret; +} + +void set_bps_capacity(band_limit_t value) +{ + pthread_mutex_lock(&mutex_bps); + turn_params.bps_capacity = value; + pthread_mutex_unlock(&mutex_bps); +} + +band_limit_t get_max_bps(void) +{ + band_limit_t ret = 0; + pthread_mutex_lock(&mutex_bps); + ret = turn_params.max_bps; + pthread_mutex_unlock(&mutex_bps); + return ret; +} + +void set_max_bps(band_limit_t value) +{ + pthread_mutex_lock(&mutex_bps); + turn_params.max_bps = value; + pthread_mutex_unlock(&mutex_bps); +} + /////////////// AUX SERVERS //////////////// static void add_aux_server_list(const char *saddr, turn_server_addrs_list_t *list) @@ -735,7 +787,7 @@ static ioa_engine_handle create_new_listener_engine(void) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (udp listener/relay thread): %s\n",event_base_get_method(eb)); super_memory_t* sm = new_super_memory_region(); ioa_engine_handle e = create_ioa_engine(sm, eb, turn_params.listener.tp, turn_params.relay_ifname, turn_params.relays_number, turn_params.relay_addrs, - turn_params.default_relays, turn_params.verbose, turn_params.max_bps + turn_params.default_relays, turn_params.verbose #if !defined(TURN_NO_HIREDIS) ,turn_params.redis_statsdb #endif @@ -781,7 +833,7 @@ static void setup_listener(void) turn_params.listener.ioa_eng = create_ioa_engine(sm, turn_params.listener.event_base, turn_params.listener.tp, turn_params.relay_ifname, turn_params.relays_number, turn_params.relay_addrs, - turn_params.default_relays, turn_params.verbose, turn_params.max_bps + turn_params.default_relays, turn_params.verbose #if !defined(TURN_NO_HIREDIS) ,turn_params.redis_statsdb #endif @@ -1355,7 +1407,7 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int rs->event_base = turn_event_base_new(); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (general relay thread): %s\n",event_base_get_method(rs->event_base)); rs->ioa_eng = create_ioa_engine(rs->sm, rs->event_base, turn_params.listener.tp, turn_params.relay_ifname, - turn_params.relays_number, turn_params.relay_addrs, turn_params.default_relays, turn_params.verbose, turn_params.max_bps + turn_params.relays_number, turn_params.relay_addrs, turn_params.default_relays, turn_params.verbose #if !defined(TURN_NO_HIREDIS) ,turn_params.redis_statsdb #endif @@ -1408,7 +1460,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, - turn_params.max_bps, allocate_bps); + allocate_bps); if(to_set_rfc5780) { set_rfc5780(&(rs->server), get_alt_addr, send_message_from_listener_to_client); diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index e1228c8f..a797b06c 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -335,7 +335,7 @@ static void timer_handler(ioa_engine_handle e, void* arg) { ioa_engine_handle create_ioa_engine(super_memory_t *sm, struct event_base *eb, turnipports *tp, const s08bits* relay_ifname, size_t relays_number, s08bits **relay_addrs, int default_relays, - int verbose, band_limit_t max_bps + int verbose #if !defined(TURN_NO_HIREDIS) ,const char* redis_report_connection_string #endif @@ -370,7 +370,6 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm, e->sm = sm; e->default_relays = default_relays; - e->max_bpj = max_bps; e->verbose = verbose; e->tp = tp; if (eb) { @@ -627,10 +626,7 @@ static int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read) { if(s && (s->e) && sz && (s->sat == CLIENT_SOCKET) && (s->session)) { - band_limit_t max_bps = s->e->max_bpj; - band_limit_t s_max_bps = s->session->realm_options.perf_options.max_bps; - if(s_max_bps>0) - max_bps = s_max_bps; + band_limit_t max_bps = s->session->realm_options.perf_options.max_bps; if(max_bps<1) return 1; diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 08f22351..51356691 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -144,7 +144,6 @@ struct _ioa_engine #endif SSL_CTX *dtls_ctx; turn_time_t jiffie; /* bandwidth check interval */ - band_limit_t max_bpj; ioa_timer_handle timer_ev; s08bits cmsg[TURN_CMSG_SZ+1]; int predef_timer_intervals[PREDEF_TIMERS_NUM]; @@ -238,7 +237,7 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm, struct event_base *eb, turnipports* tp, const s08bits* relay_if, size_t relays_number, s08bits **relay_addrs, int default_relays, - int verbose, band_limit_t max_bps + int verbose #if !defined(TURN_NO_HIREDIS) ,const char* redis_report_connection_string #endif diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index 57050041..785f54d0 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -358,17 +358,17 @@ static void change_cli_param(struct cli_session* cs, const char* pn) cli_print_uint(cs,(unsigned long)turn_params.user_quota,"user-quota",2); return; } else if(strstr(pn,"max-bps")==pn) { - turn_params.max_bps = atoi(pn+strlen("max-bps")); - cli_print_uint(cs,(unsigned long)turn_params.max_bps,"max-bps",2); + set_max_bps((band_limit_t)atol(pn+strlen("max-bps"))); + cli_print_uint(cs,(unsigned long)get_max_bps(),"max-bps",2); + return; + } else if(strstr(pn,"bps-capacity")==pn) { + set_bps_capacity((band_limit_t)atol(pn+strlen("bps-capacity"))); + cli_print_uint(cs,(unsigned long)get_bps_capacity(),"bps-capacity",2); return; } else if(strstr(pn,"cli-max-output-sessions")==pn) { cli_max_output_sessions = atoi(pn+strlen("cli-max-output-sessions")); cli_print_uint(cs,(unsigned long)cli_max_output_sessions,"cli-max-output-sessions",2); return; - } else if(strstr(pn,"bps-capacity")==pn) { - turn_params.bps_capacity = atoi(pn+strlen("bps-capacity")); - cli_print_uint(cs,(unsigned long)turn_params.bps_capacity,"bps-capacity",2); - return; } myprintf(cs, "\n"); @@ -722,7 +722,6 @@ static void cli_print_configuration(struct cli_session* cs) cli_print_uint(cs,(unsigned long)turn_params.min_port,"min-port",0); cli_print_uint(cs,(unsigned long)turn_params.max_port,"max-port",0); - cli_print_uint(cs,(unsigned long)turn_params.bps_capacity_allocated,"Allocated bps-capacity",0); cli_print_ip_range_list(cs,&turn_params.ip_whitelist,"Whitelist IP",0); cli_print_ip_range_list(cs,&turn_params.ip_blacklist,"Blacklist IP",0); @@ -796,10 +795,11 @@ static void cli_print_configuration(struct cli_session* cs) myprintf(cs,"\n"); - cli_print_uint(cs,(unsigned long)turn_params.total_quota,"total-quota",2); - cli_print_uint(cs,(unsigned long)turn_params.user_quota,"user-quota",2); - cli_print_uint(cs,(unsigned long)turn_params.bps_capacity,"bps-capacity",2); - cli_print_uint(cs,(unsigned long)turn_params.max_bps,"max-bps",2); + cli_print_uint(cs,(unsigned long)turn_params.total_quota,"Default total-quota",2); + cli_print_uint(cs,(unsigned long)turn_params.user_quota,"Default user-quota",2); + cli_print_uint(cs,(unsigned long)get_bps_capacity(),"Total server bps-capacity",2); + cli_print_uint(cs,(unsigned long)get_bps_capacity_allocated(),"Allocated bps-capacity",0); + cli_print_uint(cs,(unsigned long)get_max_bps(),"Default max-bps",2); myprintf(cs,"\n"); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 40398cd0..0b345add 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4349,7 +4349,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, - band_limit_t max_bps, allocate_bps_cb allocate_bps_func) { + allocate_bps_cb allocate_bps_func) { if (!server) return; @@ -4406,7 +4406,6 @@ void init_turn_server(turn_turnserver* server, server->send_socket_to_relay = send_socket_to_relay; - server->max_bps = max_bps; server->allocate_bps_func = allocate_bps_func; set_ioa_timer(server->e, 1, 0, timer_timeout_handler, server, 1, "timer_timeout_handler"); diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index 3a76ca39..20fc9dec 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -92,7 +92,7 @@ typedef void (*release_allocation_quota_cb)(u08bits *username, 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); typedef int (*send_turn_session_info_cb)(struct turn_session_info *tsi); -typedef band_limit_t (*allocate_bps_cb)(band_limit_t bps); +typedef band_limit_t (*allocate_bps_cb)(band_limit_t bps, int negative); struct _turn_turnserver { @@ -153,7 +153,6 @@ struct _turn_turnserver { int server_relay; /* Bandwidth draft: */ - band_limit_t max_bps; allocate_bps_cb allocate_bps_func; }; @@ -189,7 +188,6 @@ void init_turn_server(turn_turnserver* server, vintp mobility, int server_relay, send_turn_session_info_cb send_turn_session_info, - band_limit_t max_bps, allocate_bps_cb allocate_bps_func); ioa_engine_handle turn_server_get_engine(turn_turnserver *s); From 8e459aa44e27e17ca1d62be4e59a6befcf300c36 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 29 May 2014 06:49:49 +0000 Subject: [PATCH 052/805] working on bandwidth draft --- src/apps/relay/mainrelay.c | 2 +- src/apps/relay/netengine.c | 7 ++--- src/apps/relay/ns_ioalib_engine_impl.c | 6 +++-- src/apps/relay/turncli.c | 2 ++ src/apps/relay/userdb.c | 36 ++++++++++++++------------ src/client/ns_turn_msg_defs_new.h | 6 +++++ src/server/ns_turn_server.c | 13 ++++++++++ src/server/ns_turn_server.h | 2 +- src/server/ns_turn_session.h | 7 +++-- 9 files changed, 56 insertions(+), 25 deletions(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index c08b09bd..c0c07240 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1338,7 +1338,7 @@ static int adminmain(int argc, char **argv) u08bits pwd[STUN_MAX_PWD_SIZE+1]=""; u08bits secret[AUTH_SECRET_SIZE+1]=""; u08bits origin[STUN_MAX_ORIGIN_SIZE+1]=""; - perf_options_t po = {-1,-1,-1}; + perf_options_t po = {(band_limit_t)-1,-1,-1}; while (((c = getopt_long(argc, argv, ADMIN_OPTIONS, admin_long_options, NULL)) != -1)) { switch (c){ diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 502a89dc..94208111 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -81,13 +81,13 @@ static void barrier_wait_func(const char* func, int line) static pthread_mutex_t mutex_bps; -static band_limit_t allocate_bps(band_limit_t bps, int negative) +static band_limit_t allocate_bps(band_limit_t bps, int positive) { band_limit_t ret = 0; if(bps>0) { pthread_mutex_lock(&mutex_bps); - if(!negative) { + if(positive) { if(turn_params.bps_capacity_allocated < turn_params.bps_capacity) { band_limit_t reserve = turn_params.bps_capacity - turn_params.bps_capacity_allocated; @@ -96,11 +96,12 @@ static band_limit_t allocate_bps(band_limit_t bps, int negative) turn_params.bps_capacity_allocated = turn_params.bps_capacity; } else { ret = bps; - turn_params.bps_capacity_allocated -= ret; + turn_params.bps_capacity_allocated += ret; } } } else { + if(turn_params.bps_capacity_allocated >= bps) { turn_params.bps_capacity_allocated -= bps; ret = turn_params.bps_capacity_allocated; diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index a797b06c..7373adad 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -624,9 +624,11 @@ void delete_ioa_timer(ioa_timer_handle th) static int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read) { - if(s && (s->e) && sz && (s->sat == CLIENT_SOCKET) && (s->session)) { + if(s && (s->e) && sz && + ((s->sat == CLIENT_SOCKET) || (s->sat == RELAY_SOCKET) || (s->sat == RELAY_RTCP_SOCKET)) && + (s->session)) { - band_limit_t max_bps = s->session->realm_options.perf_options.max_bps; + band_limit_t max_bps = s->session->bps; if(max_bps<1) return 1; diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index 785f54d0..6645add5 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -506,6 +506,8 @@ static int print_session(ur_map_key_type key, ur_map_value_type value, void *arg myprintf(cs," TLS method: %s\n",tsi->tls_method); myprintf(cs," TLS cipher: %s\n",tsi->tls_cipher); } + if(tsi->bps) + myprintf(cs," Max throughput: %lu bytes per second\n",(unsigned long)tsi->bps); myprintf(cs," usage: rp=%lu, rb=%lu, sp=%lu, sb=%lu\n",(unsigned long)(tsi->received_packets), (unsigned long)(tsi->received_bytes),(unsigned long)(tsi->sent_packets),(unsigned long)(tsi->sent_bytes)); myprintf(cs," rate: r=%lu, s=%lu, total=%lu (bytes per sec)\n",(unsigned long)(tsi->received_rate), (unsigned long)(tsi->sent_rate),(unsigned long)(tsi->total_rate)); if(tsi->main_peers_size) { diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 12b16d1f..73251133 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -2343,12 +2343,12 @@ static int list_origins(u08bits *realm) return 0; } -static int set_realm_option_one(u08bits *realm, vint value, const char* opt) +static int set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) { UNUSED_ARG(realm); UNUSED_ARG(value); UNUSED_ARG(opt); - if(value<0) + if(value == (unsigned long)-1) return 0; #if !defined(TURN_NO_PQ) if(is_pqsql_userdb()) { @@ -2363,7 +2363,7 @@ static int set_realm_option_one(u08bits *realm, vint value, const char* opt) } } if(value>0) { - snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%d')",realm,opt,(int)value); + snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%lu')",realm,opt,(unsigned long)value); PGresult *res = PQexec(pqc, statement); if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting realm option information: %s\n",PQerrorMessage(pqc)); @@ -2386,7 +2386,7 @@ static int set_realm_option_one(u08bits *realm, vint value, const char* opt) mysql_query(myc, statement); } if(value>0) { - snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%d')",realm,opt,(int)value); + snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%lu')",realm,opt,(unsigned long)value); int res = mysql_query(myc, statement); if (res) { TURN_LOG_FUNC( @@ -2406,7 +2406,7 @@ static int set_realm_option_one(u08bits *realm, vint value, const char* opt) char s[LONG_STRING_SIZE]; if(value>0) - snprintf(s,sizeof(s),"set turn/realm/%s/%s %d", (char*)realm, opt, (int)value); + snprintf(s,sizeof(s),"set turn/realm/%s/%s %lu", (char*)realm, opt, (unsigned long)value); else snprintf(s,sizeof(s),"del turn/realm/%s/%s", (char*)realm, opt); @@ -2420,9 +2420,9 @@ static int set_realm_option_one(u08bits *realm, vint value, const char* opt) static int set_realm_option(u08bits *realm, perf_options_t *po) { - set_realm_option_one(realm,po->max_bps,"max-bps"); - set_realm_option_one(realm,po->user_quota,"user-quota"); - set_realm_option_one(realm,po->total_quota,"total-quota"); + set_realm_option_one(realm,(unsigned long)po->max_bps,"max-bps"); + set_realm_option_one(realm,(unsigned long)po->user_quota,"user-quota"); + set_realm_option_one(realm,(unsigned long)po->total_quota,"total-quota"); return 0; } @@ -2612,7 +2612,7 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b if(ct == TA_SET_REALM_OPTION) { must_set_admin_realm(realm); - if(!(po && (po->max_bps>=0 || po->total_quota>=0 || po->user_quota>=0))) { + if(!(po && (po->max_bps!=((band_limit_t)-1) || po->total_quota>=0 || po->user_quota>=0))) { fprintf(stderr, "The operation cannot be completed: a realm option must be set.\n"); exit(-1); } @@ -3246,7 +3246,7 @@ int add_ip_list_range(char* range, ip_range_list_t * list) /////////// REALM ////////////// #if !defined(TURN_NO_HIREDIS) -static int set_redis_realm_opt(char *realm, const char* key, vint *value) +static int set_redis_realm_opt(char *realm, const char* key, unsigned long *value) { int found = 0; @@ -3268,7 +3268,7 @@ static int set_redis_realm_opt(char *realm, const char* key, vint *value) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type); } else { ur_string_map_lock(realms); - *value = atoi(rget->str); + *value = (unsigned long)atol(rget->str); ur_string_map_unlock(realms); found = 1; } @@ -3371,7 +3371,7 @@ void reread_realms(void) if(rval && oval && vval) { realm_params_t* rp = get_realm(rval); if(!strcmp(oval,"max-bps")) - rp->options.perf_options.max_bps = (vint)atoi(vval); + rp->options.perf_options.max_bps = (band_limit_t)atol(vval); else if(!strcmp(oval,"total-quota")) rp->options.perf_options.total_quota = (vint)atoi(vval); else if(!strcmp(oval,"user-quota")) @@ -3491,7 +3491,7 @@ void reread_realms(void) vval[sz]=0; realm_params_t* rp = get_realm(rval); if(!strcmp(oval,"max-bps")) - rp->options.perf_options.max_bps = (vint)atoi(vval); + rp->options.perf_options.max_bps = (band_limit_t)atol(vval); else if(!strcmp(oval,"total-quota")) rp->options.perf_options.total_quota = (vint)atoi(vval); else if(!strcmp(oval,"user-quota")) @@ -3583,21 +3583,25 @@ void reread_realms(void) for (i = 0; ioptions.perf_options.max_bps))) { + unsigned long value = 0; + if(!set_redis_realm_opt(realm,"max-bps",&value)) { ur_string_map_lock(realms); rp->options.perf_options.max_bps = turn_params.max_bps; ur_string_map_unlock(realms); } - if(!set_redis_realm_opt(realm,"total-quota",&(rp->options.perf_options.total_quota))) { + rp->options.perf_options.max_bps = (band_limit_t)value; + if(!set_redis_realm_opt(realm,"total-quota",&value)) { ur_string_map_lock(realms); rp->options.perf_options.total_quota = turn_params.total_quota; ur_string_map_unlock(realms); } - if(!set_redis_realm_opt(realm,"user-quota",&(rp->options.perf_options.user_quota))) { + rp->options.perf_options.total_quota = (vint)value; + if(!set_redis_realm_opt(realm,"user-quota",&value)) { ur_string_map_lock(realms); rp->options.perf_options.user_quota = turn_params.user_quota; ur_string_map_unlock(realms); } + rp->options.perf_options.user_quota = (vint)value; } } } diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 4ec2a16c..57b64c2a 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -58,4 +58,10 @@ typedef enum _SHATYPE SHATYPE; /* <<== SHA AGILITY */ +/* Bandwidth */ + +#define STUN_ATTRIBUTE_NEW_BANDWIDTH (0x8000 + STUN_ATTRIBUTE_BANDWIDTH) + +/* <<== Bandwidth */ + #endif //__LIB_TURN_MSG_DEFS_NEW__ diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 0b345add..53d996db 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -132,6 +132,13 @@ static void dec_quota(ts_ur_super_session* ss) ss->quota_used = 0; + if(ss->bps) { + if(((turn_turnserver*)ss->server)->allocate_bps_func) { + ((turn_turnserver*)ss->server)->allocate_bps_func(ss->bps,0); + } + ss->bps = 0; + } + (((turn_turnserver*)ss->server)->raqcb)(ss->username, (u08bits*)ss->realm_options.name); } } @@ -361,6 +368,7 @@ int turn_session_info_copy_from(struct turn_session_info* tsi, ts_ur_super_sessi if(tsi && ss) { tsi->id = ss->id; + tsi->bps = ss->bps; tsi->start_time = ss->start_time; tsi->valid = is_allocation_valid(&(ss->alloc)) && !(ss->to_be_closed) && (ss->quota_used); if(tsi->valid) { @@ -1057,6 +1065,11 @@ static int handle_turn_allocate(turn_turnserver *server, } else { + band_limit_t max_bps = ss->realm_options.perf_options.max_bps; + if(max_bps && server->allocate_bps_func) { + ss->bps = server->allocate_bps_func(max_bps,1); + } + if (create_relay_connection(server, ss, lifetime, af, transport, even_port, in_reservation_token, &out_reservation_token, diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index 20fc9dec..da24b329 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -92,7 +92,7 @@ typedef void (*release_allocation_quota_cb)(u08bits *username, 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); typedef int (*send_turn_session_info_cb)(struct turn_session_info *tsi); -typedef band_limit_t (*allocate_bps_cb)(band_limit_t bps, int negative); +typedef band_limit_t (*allocate_bps_cb)(band_limit_t bps, int positive); struct _turn_turnserver { diff --git a/src/server/ns_turn_session.h b/src/server/ns_turn_session.h index cd9a8fcd..b5e42071 100644 --- a/src/server/ns_turn_session.h +++ b/src/server/ns_turn_session.h @@ -42,9 +42,11 @@ extern "C" { ////////// REALM //////////// +typedef unsigned int band_limit_t; + typedef struct _perf_options_t { - vint max_bps; + band_limit_t max_bps; vint total_quota; vint user_quota; @@ -60,7 +62,6 @@ struct _realm_options_t { //////////////// session info ////////////////////// typedef u64bits turnsession_id; -typedef unsigned int band_limit_t; #define NONCE_MAX_SIZE (NONCE_LENGTH_32BITS*4+1) @@ -150,6 +151,8 @@ struct turn_session_info { /* Realm */ char realm[STUN_MAX_REALM_SIZE+1]; char origin[STUN_MAX_ORIGIN_SIZE + 1]; +/* Bandwidth */ + band_limit_t bps; }; void turn_session_info_init(struct turn_session_info* tsi); From fdbd91e4d5d5456f593ddedd943e9bdf1cd95b97 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 29 May 2014 07:18:43 +0000 Subject: [PATCH 053/805] working on bandwidth --- src/apps/relay/netengine.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 94208111..be02bfaf 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -89,7 +89,10 @@ static band_limit_t allocate_bps(band_limit_t bps, int positive) if(positive) { - if(turn_params.bps_capacity_allocated < turn_params.bps_capacity) { + if(!(turn_params.bps_capacity)) { + ret = bps; + turn_params.bps_capacity_allocated += ret; + } else if(turn_params.bps_capacity_allocated < turn_params.bps_capacity) { band_limit_t reserve = turn_params.bps_capacity - turn_params.bps_capacity_allocated; if(reserve <= bps) { ret = reserve; From 16f2f22dd332b4c77bd9833790b15a3bfa199b0d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 30 May 2014 06:32:03 +0000 Subject: [PATCH 054/805] working on bandwidth --- README.turnutils | 2 ++ man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 2 +- man/man1/turnutils.1 | 6 +++++- src/apps/relay/ns_ioalib_engine_impl.c | 2 +- src/apps/uclient/mainuclient.c | 8 +++++++- src/apps/uclient/startuclient.c | 4 ++++ src/apps/uclient/uclient.h | 1 + src/client/ns_turn_msg.c | 20 +++++++++++++++++++ src/client/ns_turn_msg.h | 3 +++ src/server/ns_turn_server.c | 27 ++++++++++++++++++++++---- src/server/ns_turn_session.h | 2 -- 12 files changed, 68 insertions(+), 11 deletions(-) diff --git a/README.turnutils b/README.turnutils index 17550fb4..89b592ae 100644 --- a/README.turnutils +++ b/README.turnutils @@ -153,6 +153,8 @@ Options with required values: -F Cipher suite for TLS/DTLS. Default value is DEFAULT. +-a Bandwidth for the bandwidth request in ALLOCATE. The default value is zero. + See the examples in the "examples/scripts" directory. ====================================== diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 4151f845..029151f9 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "26 May 2014" "" "" +.TH TURN 1 "29 May 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index ba47a972..395b2dfc 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "26 May 2014" "" "" +.TH TURN 1 "29 May 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 20a72357..5e4f324f 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "26 May 2014" "" "" +.TH TURN 1 "29 May 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -244,6 +244,10 @@ TURN REST API. The default value is :. .B \fB\-F\fP Cipher suite for TLS/DTLS. Default value is DEFAULT. +.TP +.B +\fB\-a\fP +Bandwidth for the bandwidth request in ALLOCATE. The default value is zero. .PP See the examples in the "examples/scripts" directory. .PP diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 7373adad..ebed6464 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -624,7 +624,7 @@ void delete_ioa_timer(ioa_timer_handle th) static int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read) { - if(s && (s->e) && sz && + if(read && s && (s->e) && sz && ((s->sat == CLIENT_SOCKET) || (s->sat == RELAY_SOCKET) || (s->sat == RELAY_RTCP_SOCKET)) && (s->session)) { diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 8d7e77bb..9afa477d 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -93,6 +93,8 @@ int extra_requests = 0; char origin[STUN_MAX_ORIGIN_SIZE+1] = "\0"; +band_limit_t bps = 0; + //////////////// local definitions ///////////////// static char Usage[] = @@ -145,6 +147,7 @@ static char Usage[] = " -W TURN REST API authentication secret. Is not compatible with -A option.\n" " -C TURN REST API timestamp/username separator symbol (character). The default value is ':'.\n" " -F Cipher suite for TLS/DTLS. Default value is DEFAULT.\n" + " -a Bandwidth for the bandwidth request in ALLOCATE. The default value is zero.\n" " -o - the ORIGIN STUN attribute value.\n"; ////////////////////////////////////////////////// @@ -198,8 +201,11 @@ int main(int argc, char **argv) ns_bzero(local_addr, sizeof(local_addr)); - while ((c = getopt(argc, argv, "d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:vsyhcxXgtTSAPDNOUHMRIGB")) != -1) { + while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:vsyhcxXgtTSAPDNOUHMRIGB")) != -1) { switch (c){ + case 'a': + bps = (band_limit_t)atol(optarg); + break; case 'o': STRCPY(origin,optarg); break; diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 825478e0..171ad97b 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -339,6 +339,10 @@ static int clnet_allocate(int verbose, stun_set_allocate_request(&message, 800, af, relay_transport, mobility); else stun_set_allocate_request(&message, 300, af, relay_transport, mobility); + + if(bps) + stun_attr_add_bandwidth_str(message.buf, (size_t*)(&(message.len)), bps); + if(dont_fragment) stun_attr_add(&message, STUN_ATTRIBUTE_DONT_FRAGMENT, NULL, 0); if(!no_rtcp) { diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index 93e595b6..6c3bad3d 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -81,6 +81,7 @@ extern SHATYPE shatype; extern int mobility; extern int no_permissions; extern int extra_requests; +extern band_limit_t bps; extern char origin[STUN_MAX_ORIGIN_SIZE+1]; diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 955a240b..b5d69d91 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -944,6 +944,17 @@ u16bits stun_attr_get_channel_number(stun_attr_ref attr) { return 0; } +band_limit_t stun_attr_get_bandwidth(stun_attr_ref attr) { + if(attr) { + const u08bits* value = stun_attr_get_value(attr); + if(value && (stun_attr_get_len(attr) >= 4)) { + u32bits bps=nswap32(((const u32bits*)value)[0]); + return (band_limit_t)(bps << 7); + } + } + return 0; +} + u64bits stun_attr_get_reservation_token_value(stun_attr_ref attr) { if(attr) { const u08bits* value = stun_attr_get_value(attr); @@ -1150,6 +1161,15 @@ int stun_attr_add_channel_number_str(u08bits* buf, size_t *len, u16bits chnumber return stun_attr_add_str(buf,len,STUN_ATTRIBUTE_CHANNEL_NUMBER,(u08bits*)(field),sizeof(field)); } +int stun_attr_add_bandwidth_str(u08bits* buf, size_t *len, band_limit_t bps0) { + + u32bits bps = (band_limit_t)(bps0 >> 7); + + u32bits field=nswap32(bps); + + return stun_attr_add_str(buf,len,STUN_ATTRIBUTE_NEW_BANDWIDTH,(u08bits*)(&field),sizeof(field)); +} + u16bits stun_attr_get_first_channel_number_str(const u08bits *buf, size_t len) { stun_attr_ref attr=stun_attr_get_first_str(buf,len); diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 4a684f5d..33cb9561 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -68,6 +68,7 @@ typedef u08bits hmackey_t[64]; */ #define SHORT_TERM_PASSWORD_SIZE (512) typedef u08bits st_password_t[SHORT_TERM_PASSWORD_SIZE+1]; +typedef unsigned int band_limit_t; /////////////////////////////////// @@ -140,6 +141,7 @@ int stun_attr_get_type(stun_attr_ref attr); int stun_attr_get_len(stun_attr_ref attr); const u08bits* stun_attr_get_value(stun_attr_ref attr); u16bits stun_attr_get_channel_number(stun_attr_ref attr); +band_limit_t stun_attr_get_bandwidth(stun_attr_ref attr); u08bits stun_attr_get_even_port(stun_attr_ref attr); u64bits stun_attr_get_reservation_token_value(stun_attr_ref attr); stun_attr_ref stun_attr_get_first_by_type_str(const u08bits* buf, size_t len, u16bits attr_type); @@ -150,6 +152,7 @@ int stun_attr_add_addr_str(u08bits *buf, size_t *len, u16bits attr_type, const i int stun_attr_get_addr_str(const u08bits *buf, size_t len, stun_attr_ref attr, ioa_addr* ca, const ioa_addr *default_addr); int stun_attr_get_first_addr_str(const u08bits *buf, size_t len, u16bits attr_type, ioa_addr* ca, const ioa_addr *default_addr); int stun_attr_add_channel_number_str(u08bits* buf, size_t *len, u16bits chnumber); +int stun_attr_add_bandwidth_str(u08bits* buf, size_t *len, band_limit_t bps); u16bits stun_attr_get_first_channel_number_str(const u08bits *buf, size_t len); int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int address_family, u08bits transport, int mobile); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 53d996db..a3cf0273 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -868,6 +868,8 @@ static int handle_turn_allocate(turn_turnserver *server, int af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT; u08bits username[STUN_MAX_USERNAME_SIZE+1]="\0"; size_t ulen = 0; + band_limit_t bps = 0; + band_limit_t max_bps = 0; stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh)); @@ -891,6 +893,9 @@ static int handle_turn_allocate(turn_turnserver *server, switch (attr_type) { SKIP_ATTRIBUTES; + case STUN_ATTRIBUTE_NEW_BANDWIDTH: + bps = stun_attr_get_bandwidth(sar); + break; case STUN_ATTRIBUTE_MOBILITY_TICKET: if(!(*(server->mobility))) { *err_code = 501; @@ -1065,12 +1070,21 @@ static int handle_turn_allocate(turn_turnserver *server, } else { - band_limit_t max_bps = ss->realm_options.perf_options.max_bps; - if(max_bps && server->allocate_bps_func) { - ss->bps = server->allocate_bps_func(max_bps,1); + if(server->allocate_bps_func) { + max_bps = ss->realm_options.perf_options.max_bps; + if(max_bps && (!bps || (bps && (bps>max_bps)))) { + bps = max_bps; + } + if(bps) { + ss->bps = server->allocate_bps_func(bps,1); + if(!(ss->bps)) { + *err_code = 486; + *reason = (const u08bits *)"Allocation Bandwidth Quota Reached"; + } + } } - if (create_relay_connection(server, ss, lifetime, + if (*err_code || create_relay_connection(server, ss, lifetime, af, transport, even_port, in_reservation_token, &out_reservation_token, err_code, reason, @@ -1110,6 +1124,11 @@ static int handle_turn_allocate(turn_turnserver *server, 0,NULL, out_reservation_token, ss->s_mobile_id); + + if(ss->bps) { + stun_attr_add_bandwidth_str(ioa_network_buffer_data(nbh), &len, ss->bps); + } + ioa_network_buffer_set_size(nbh,len); *resp_constructed = 1; diff --git a/src/server/ns_turn_session.h b/src/server/ns_turn_session.h index b5e42071..60366f42 100644 --- a/src/server/ns_turn_session.h +++ b/src/server/ns_turn_session.h @@ -42,8 +42,6 @@ extern "C" { ////////// REALM //////////// -typedef unsigned int band_limit_t; - typedef struct _perf_options_t { band_limit_t max_bps; From 7e7ee8b868b0020d7a6bee410b1933d34843792c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 30 May 2014 06:37:08 +0000 Subject: [PATCH 055/805] docs cleaning --- README.turnutils | 6 ++++-- man/man1/turnutils.1 | 4 ++++ src/apps/uclient/mainuclient.c | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/README.turnutils b/README.turnutils index 89b592ae..1c2f5990 100644 --- a/README.turnutils +++ b/README.turnutils @@ -113,7 +113,7 @@ Flags: -G Generate extra requests (create permissions, channel bind). --B Random disconnect after a few initial packets. +-B Random disconnect after a few initial packets. Options with required values: @@ -148,11 +148,13 @@ Options with required values: -W TURN REST API authentication secret. Is not compatible with -A flag. --C This is the timestamp/username separator symbol (character) in +-C This is the timestamp/username separator symbol (character) in TURN REST API. The default value is :. -F Cipher suite for TLS/DTLS. Default value is DEFAULT. +-o the ORIGIN STUN attribute value. + -a Bandwidth for the bandwidth request in ALLOCATE. The default value is zero. See the examples in the "examples/scripts" directory. diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 5e4f324f..9601c90a 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -246,6 +246,10 @@ TURN REST API. The default value is :. Cipher suite for TLS/DTLS. Default value is DEFAULT. .TP .B +\fB\-o\fP +the ORIGIN STUN attribute value. +.TP +.B \fB\-a\fP Bandwidth for the bandwidth request in ALLOCATE. The default value is zero. .PP diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 9afa477d..437c69cb 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -147,8 +147,8 @@ static char Usage[] = " -W TURN REST API authentication secret. Is not compatible with -A option.\n" " -C TURN REST API timestamp/username separator symbol (character). The default value is ':'.\n" " -F Cipher suite for TLS/DTLS. Default value is DEFAULT.\n" - " -a Bandwidth for the bandwidth request in ALLOCATE. The default value is zero.\n" - " -o - the ORIGIN STUN attribute value.\n"; + " -o - the ORIGIN STUN attribute value.\n" + " -a Bandwidth for the bandwidth request in ALLOCATE. The default value is zero.\n"; ////////////////////////////////////////////////// From a138db3ae9c6452a1f67ef9f603c17a6ffdf049e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 31 May 2014 08:19:47 +0000 Subject: [PATCH 056/805] merge bug fixes 126, 137 from rfc5766-turn-server --- src/apps/relay/netengine.c | 27 +++++++-- src/apps/relay/ns_ioalib_impl.h | 1 + src/server/ns_turn_server.c | 102 +++++++++++++++++++------------- src/server/ns_turn_server.h | 2 +- 4 files changed, 83 insertions(+), 49 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index be02bfaf..90996acd 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -508,11 +508,20 @@ static int send_socket_to_relay(turnserver_id id, u64bits cid, stun_tid *tid, io switch (rmt) { case(RMT_CB_SOCKET): { - sm.m.cb_sm.id = id; - sm.m.cb_sm.connection_id = (tcp_connection_id)cid; - stun_tid_cpy(&(sm.m.cb_sm.tid),tid); - sm.m.cb_sm.s = s; - sm.m.cb_sm.message_integrity = message_integrity; + if(nd && nd->nbh) { + sm.m.cb_sm.id = id; + sm.m.cb_sm.connection_id = (tcp_connection_id)cid; + stun_tid_cpy(&(sm.m.cb_sm.tid),tid); + sm.m.cb_sm.s = s; + sm.m.cb_sm.message_integrity = message_integrity; + + addr_cpy(&(sm.m.cb_sm.nd.src_addr),&(nd->src_addr)); + sm.m.cb_sm.nd.recv_tos = nd->recv_tos; + sm.m.cb_sm.nd.recv_ttl = nd->recv_ttl; + sm.m.cb_sm.nd.nbh = nd->nbh; + + nd->nbh = NULL; + } break; } @@ -562,6 +571,9 @@ static int send_socket_to_relay(turnserver_id id, u64bits cid, stun_tid *tid, io if(rmt == RMT_MOBILE_SOCKET) { ioa_network_buffer_delete(NULL, sm.m.sm.nd.nbh); sm.m.sm.nd.nbh = NULL; + } else if(rmt == RMT_CB_SOCKET) { + ioa_network_buffer_delete(NULL, sm.m.cb_sm.nd.nbh); + sm.m.cb_sm.nd.nbh = NULL; } } @@ -608,7 +620,10 @@ static int handle_relay_message(relay_server_handle rs, struct message_to_relay case RMT_CB_SOCKET: turnserver_accept_tcp_client_data_connection(&(rs->server), sm->m.cb_sm.connection_id, - &(sm->m.cb_sm.tid), sm->m.cb_sm.s, sm->m.cb_sm.message_integrity); + &(sm->m.cb_sm.tid), sm->m.cb_sm.s, sm->m.cb_sm.message_integrity, &(sm->m.cb_sm.nd)); + + ioa_network_buffer_delete(rs->ioa_eng, sm->m.cb_sm.nd.nbh); + sm->m.cb_sm.nd.nbh = NULL; break; case RMT_MOBILE_SOCKET: { diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 51356691..4b4936f2 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -90,6 +90,7 @@ struct cb_socket_message { stun_tid tid; ioa_socket_handle s; int message_integrity; + ioa_net_data nd; }; struct relay_server { diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index a3cf0273..da9109ef 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -47,6 +47,31 @@ int TURN_MAX_ALLOCATE_TIMEOUT = 60; int TURN_MAX_ALLOCATE_TIMEOUT_STUN_ONLY = 3; +#define log_method(ss, method, err_code, reason) \ +{\ + if(!(err_code)) {\ + if(ss->origin[0]) {\ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ + "session %018llu: origin <%s> realm <%s> user <%s>: incoming packet " method " processed, success\n",\ + (unsigned long long)(ss->id), (const char*)(ss->origin),(const char*)(ss->realm_options.name),(const char*)(ss->username));\ + } else {\ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ + "session %018llu: realm <%s> user <%s>: incoming packet " method " processed, success\n",\ + (unsigned long long)(ss->id), (const char*)(ss->realm_options.name),(const char*)(ss->username));\ + }\ + } else {\ + if(ss->origin[0]) {\ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ + "session %018llu: origin <%s> realm <%s> user <%s>: incoming packet " method " processed, error %d: %s\n",\ + (unsigned long long)(ss->id), (const char*)(ss->origin),(const char*)(ss->realm_options.name),(const char*)(ss->username), (err_code), (reason));\ + } else {\ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ + "session %018llu: realm <%s> user <%s>: incoming packet " method " processed, error %d: %s\n",\ + (unsigned long long)(ss->id), (const char*)(ss->realm_options.name),(const char*)(ss->username), (err_code), (reason));\ + }\ + }\ +} + /////////////////////////////////////////// static int attach_socket_to_session(turn_turnserver* server, ioa_socket_handle s, ts_ur_super_session* ss); @@ -1986,7 +2011,7 @@ static int handle_turn_connection_bind(turn_turnserver *server, if(s) { ioa_socket_handle new_s = detach_ioa_socket(s,1); if(new_s) { - if(server->send_socket_to_relay(sid, id, tid, new_s, message_integrity, RMT_CB_SOCKET, NULL)<0) { + if(server->send_socket_to_relay(sid, id, tid, new_s, message_integrity, RMT_CB_SOCKET, in_buffer)<0) { *err_code = 400; *reason = (const u08bits *)"Wrong connection id"; } @@ -2019,7 +2044,7 @@ static int handle_turn_connection_bind(turn_turnserver *server, return 0; } -int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_connection_id tcid, stun_tid *tid, ioa_socket_handle s, int message_integrity) +int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_connection_id tcid, stun_tid *tid, ioa_socket_handle s, int message_integrity, ioa_net_data *in_buffer) { if(!server) return -1; @@ -2030,10 +2055,13 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co ts_ur_super_session *ss = NULL; int err_code = 0; + const u08bits *reason = NULL; if(tcid && tid && s) { tc = get_and_clean_tcp_connection_by_id(server->tcp_relay_connections, tcid); + ioa_network_buffer_handle nbh = ioa_network_buffer_allocate(server->e); + int resp_constructed = 0; if(!tc || (tc->state == TC_STATE_READY) || (tc->client_s)) { err_code = 400; } else { @@ -2042,9 +2070,18 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co err_code = 500; } else { ss = (ts_ur_super_session*)(a->owner); - if(!check_username_hash(s,ss->username,(u08bits*)ss->realm_options.name)) { - err_code = 401; - } else { + + //Check security: + int postpone_reply = 0; + check_stun_auth(server, ss, tid, &resp_constructed, &err_code, &reason, in_buffer, nbh, + STUN_METHOD_CONNECTION_BIND, &message_integrity, &postpone_reply, 0); + + if(postpone_reply) { + + ioa_network_buffer_delete(server->e, nbh); + return 0; + + } else if(!err_code) { tc->state = TC_STATE_READY; tc->client_s = s; set_ioa_socket_session(s,ss); @@ -2060,16 +2097,16 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co } } - ioa_network_buffer_handle nbh = ioa_network_buffer_allocate(server->e); - - if(!err_code) { - size_t len = ioa_network_buffer_get_size(nbh); - stun_init_success_response_str(STUN_METHOD_CONNECTION_BIND, ioa_network_buffer_data(nbh), &len, tid); - ioa_network_buffer_set_size(nbh,len); - } else { - size_t len = ioa_network_buffer_get_size(nbh); - stun_init_error_response_str(STUN_METHOD_CONNECTION_BIND, ioa_network_buffer_data(nbh), &len, err_code, NULL, tid); - ioa_network_buffer_set_size(nbh,len); + if(!resp_constructed) { + if(!err_code) { + size_t len = ioa_network_buffer_get_size(nbh); + stun_init_success_response_str(STUN_METHOD_CONNECTION_BIND, ioa_network_buffer_data(nbh), &len, tid); + ioa_network_buffer_set_size(nbh,len); + } else { + size_t len = ioa_network_buffer_get_size(nbh); + stun_init_error_response_str(STUN_METHOD_CONNECTION_BIND, ioa_network_buffer_data(nbh), &len, err_code, NULL, tid); + ioa_network_buffer_set_size(nbh,len); + } } { @@ -2092,6 +2129,10 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co ioa_network_buffer_set_size(nbh, len); } + if(server->verbose) { + log_method(ss, "CONNECTION_BIND", err_code, reason); + } + if(ss && !err_code) { send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE); tcp_deliver_delayed_buffer(&(tc->ub_to_client),s,ss); @@ -3106,31 +3147,6 @@ static void set_alternate_server(turn_server_addrs_list_t *asl, const ioa_addr * } } -#define log_method(ss, method, err_code, reason) \ -{\ - if(!(err_code)) {\ - if(ss->origin[0]) {\ - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ - "session %018llu: origin <%s> realm <%s> user <%s>: incoming packet " method " processed, success\n",\ - (unsigned long long)(ss->id), (const char*)(ss->origin),(const char*)(ss->realm_options.name),(const char*)(ss->username));\ - } else {\ - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ - "session %018llu: realm <%s> user <%s>: incoming packet " method " processed, success\n",\ - (unsigned long long)(ss->id), (const char*)(ss->realm_options.name),(const char*)(ss->username));\ - }\ - } else {\ - if(ss->origin[0]) {\ - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ - "session %018llu: origin <%s> realm <%s> user <%s>: incoming packet " method " processed, error %d: %s\n",\ - (unsigned long long)(ss->id), (const char*)(ss->origin),(const char*)(ss->realm_options.name),(const char*)(ss->username), (err_code), (reason));\ - } else {\ - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ - "session %018llu: realm <%s> user <%s>: incoming packet " method " processed, error %d: %s\n",\ - (unsigned long long)(ss->id), (const char*)(ss->realm_options.name),(const char*)(ss->username), (err_code), (reason));\ - }\ - }\ -} - static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, ioa_net_data *in_buffer, ioa_network_buffer_handle nbh, int *resp_constructed, int can_resume) { @@ -3225,7 +3241,9 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, } if(!err_code && !(*resp_constructed) && !no_response) { - if(!(*(server->mobility)) || (method != STUN_METHOD_REFRESH) || is_allocation_valid(get_allocation_ss(ss))) { + if(method == STUN_METHOD_CONNECTION_BIND) { + ; + } else if(!(*(server->mobility)) || (method != STUN_METHOD_REFRESH) || is_allocation_valid(get_allocation_ss(ss))) { int postpone_reply = 0; check_stun_auth(server, ss, &tid, resp_constructed, &err_code, &reason, in_buffer, nbh, method, &message_integrity, &postpone_reply, can_resume); if(postpone_reply) @@ -3270,7 +3288,7 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, handle_turn_connection_bind(server, ss, &tid, resp_constructed, &err_code, &reason, unknown_attrs, &ua_num, in_buffer, nbh, message_integrity); - if(server->verbose) { + if(server->verbose && err_code) { log_method(ss, "CONNECTION_BIND", err_code, reason); } diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index da24b329..c8855748 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -202,7 +202,7 @@ int open_client_connection_session(turn_turnserver* server, struct socket_messag int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, int force, const char* reason); void set_disconnect_cb(turn_turnserver* server, int (*disconnect)(ts_ur_super_session*)); -int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_connection_id tcid, stun_tid *tid, ioa_socket_handle s, int message_integrity); +int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_connection_id tcid, stun_tid *tid, ioa_socket_handle s, int message_integrity, ioa_net_data *nd); int report_turn_session_info(turn_turnserver *server, ts_ur_super_session *ss, int force_invalid); From baa2199c728ea6ba538b44e42d453145f6a61f83 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 31 May 2014 17:12:01 +0000 Subject: [PATCH 057/805] auth reliability --- src/apps/relay/dtls_listener.c | 2 +- src/apps/relay/netengine.c | 9 ++++++-- src/apps/relay/ns_ioalib_engine_impl.c | 2 +- src/apps/relay/ns_ioalib_impl.h | 1 + src/server/ns_turn_ioalib.h | 2 +- src/server/ns_turn_server.c | 32 +++++++++++++++----------- src/server/ns_turn_server.h | 5 ++-- 7 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index fa36f715..623877ea 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -348,7 +348,7 @@ static int handle_udp_packet(dtls_listener_relay_server_type *server, if (s && s->read_cb && sm->m.sm.nd.nbh) { s->e = ioa_eng; - s->read_cb(s, IOA_EV_READ, &(sm->m.sm.nd), s->read_ctx); + s->read_cb(s, IOA_EV_READ, &(sm->m.sm.nd), s->read_ctx, 1); ioa_network_buffer_delete(ioa_eng, sm->m.sm.nd.nbh); sm->m.sm.nd.nbh = NULL; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 90996acd..95daee8c 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -436,6 +436,7 @@ static int send_socket_to_general_relay(ioa_engine_handle e, struct message_to_r struct message_to_relay *smptr = sm; smptr->t = RMT_SOCKET; + smptr->m.sm.can_resume = 1; { struct evbuffer *output = NULL; @@ -472,7 +473,8 @@ static int send_socket_to_general_relay(ioa_engine_handle e, struct message_to_r } static int send_socket_to_relay(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 message_integrity, MESSAGE_TO_RELAY_TYPE rmt, ioa_net_data *nd, + int can_resume) { int ret = 0; @@ -519,6 +521,7 @@ static int send_socket_to_relay(turnserver_id id, u64bits cid, stun_tid *tid, io sm.m.cb_sm.nd.recv_tos = nd->recv_tos; sm.m.cb_sm.nd.recv_ttl = nd->recv_ttl; sm.m.cb_sm.nd.nbh = nd->nbh; + sm.m.cb_sm.can_resume = can_resume; nd->nbh = NULL; } @@ -533,6 +536,7 @@ static int send_socket_to_relay(turnserver_id id, u64bits cid, stun_tid *tid, io sm.m.sm.nd.recv_tos = nd->recv_tos; sm.m.sm.nd.recv_ttl = nd->recv_ttl; sm.m.sm.nd.nbh = nd->nbh; + sm.m.sm.can_resume = can_resume; nd->nbh = NULL; } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Empty buffer with mobile socket\n",__FUNCTION__); @@ -620,7 +624,8 @@ static int handle_relay_message(relay_server_handle rs, struct message_to_relay case RMT_CB_SOCKET: turnserver_accept_tcp_client_data_connection(&(rs->server), sm->m.cb_sm.connection_id, - &(sm->m.cb_sm.tid), sm->m.cb_sm.s, sm->m.cb_sm.message_integrity, &(sm->m.cb_sm.nd)); + &(sm->m.cb_sm.tid), sm->m.cb_sm.s, sm->m.cb_sm.message_integrity, &(sm->m.cb_sm.nd), + sm->m.cb_sm.can_resume); ioa_network_buffer_delete(rs->ioa_eng, sm->m.cb_sm.nd.nbh); sm->m.cb_sm.nd.nbh = NULL; diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index ebed6464..d339339e 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -2484,7 +2484,7 @@ static int socket_input_worker(ioa_socket_handle s) nd.recv_ttl = ttl; nd.recv_tos = tos; - s->read_cb(s, IOA_EV_READ, &nd, s->read_ctx); + s->read_cb(s, IOA_EV_READ, &nd, s->read_ctx, 1); if(nd.nbh) free_blist_elem(s->e,buf_elem); diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 4b4936f2..dd161c9c 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -91,6 +91,7 @@ struct cb_socket_message { ioa_socket_handle s; int message_integrity; ioa_net_data nd; + int can_resume; }; struct relay_server { diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 896f797c..41ea6d9e 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -183,7 +183,7 @@ void turn_report_session_usage(void *session); * the function must work correctly when chnum=0 * (when no hint information is available). */ -typedef void (*ioa_net_event_handler)(ioa_socket_handle s, int event_type, ioa_net_data *data, void *ctx); +typedef void (*ioa_net_event_handler)(ioa_socket_handle s, int event_type, ioa_net_data *data, void *ctx, int can_resume); /* * Timer callback diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index da9109ef..f2377499 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1300,7 +1300,7 @@ static int handle_turn_refresh(turn_turnserver *server, ioa_socket_handle new_s = detach_ioa_socket(ss->client_session.s,1); if(new_s) { if(server->send_socket_to_relay(tsid, mid, tid, new_s, message_integrity, - RMT_MOBILE_SOCKET, in_buffer)<0) { + RMT_MOBILE_SOCKET, in_buffer, can_resume)<0) { *err_code = 400; *reason = (const u08bits *)"Wrong mobile ticket"; } else { @@ -1528,12 +1528,13 @@ static void tcp_deliver_delayed_buffer(unsent_buffer *ub, ioa_socket_handle s, t } } -static void tcp_peer_input_handler(ioa_socket_handle s, int event_type, ioa_net_data *in_buffer, void *arg) +static void tcp_peer_input_handler(ioa_socket_handle s, int event_type, ioa_net_data *in_buffer, void *arg, int can_resume) { if (!(event_type & IOA_EV_READ) || !arg) return; UNUSED_ARG(s); + UNUSED_ARG(can_resume); tcp_connection *tc = (tcp_connection*)arg; ts_ur_super_session *ss=NULL; @@ -1563,12 +1564,13 @@ static void tcp_peer_input_handler(ioa_socket_handle s, int event_type, ioa_net_ } } -static void tcp_client_input_handler_rfc6062data(ioa_socket_handle s, int event_type, ioa_net_data *in_buffer, void *arg) +static void tcp_client_input_handler_rfc6062data(ioa_socket_handle s, int event_type, ioa_net_data *in_buffer, void *arg, int can_resume) { if (!(event_type & IOA_EV_READ) || !arg) return; UNUSED_ARG(s); + UNUSED_ARG(can_resume); tcp_connection *tc = (tcp_connection*)arg; ts_ur_super_session *ss=NULL; @@ -1947,7 +1949,8 @@ static int handle_turn_connect(turn_turnserver *server, static int handle_turn_connection_bind(turn_turnserver *server, ts_ur_super_session *ss, stun_tid *tid, int *resp_constructed, int *err_code, const u08bits **reason, u16bits *unknown_attrs, u16bits *ua_num, - ioa_net_data *in_buffer, ioa_network_buffer_handle nbh, int message_integrity) { + ioa_net_data *in_buffer, ioa_network_buffer_handle nbh, int message_integrity, + int can_resume) { allocation* a = get_allocation_ss(ss); @@ -2011,7 +2014,7 @@ static int handle_turn_connection_bind(turn_turnserver *server, if(s) { ioa_socket_handle new_s = detach_ioa_socket(s,1); if(new_s) { - if(server->send_socket_to_relay(sid, id, tid, new_s, message_integrity, RMT_CB_SOCKET, in_buffer)<0) { + if(server->send_socket_to_relay(sid, id, tid, new_s, message_integrity, RMT_CB_SOCKET, in_buffer, can_resume)<0) { *err_code = 400; *reason = (const u08bits *)"Wrong connection id"; } @@ -2044,7 +2047,7 @@ static int handle_turn_connection_bind(turn_turnserver *server, return 0; } -int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_connection_id tcid, stun_tid *tid, ioa_socket_handle s, int message_integrity, ioa_net_data *in_buffer) +int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_connection_id tcid, stun_tid *tid, ioa_socket_handle s, int message_integrity, ioa_net_data *in_buffer, int can_resume) { if(!server) return -1; @@ -2074,7 +2077,7 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co //Check security: int postpone_reply = 0; check_stun_auth(server, ss, tid, &resp_constructed, &err_code, &reason, in_buffer, nbh, - STUN_METHOD_CONNECTION_BIND, &message_integrity, &postpone_reply, 0); + STUN_METHOD_CONNECTION_BIND, &message_integrity, &postpone_reply, can_resume); if(postpone_reply) { @@ -3286,7 +3289,7 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, case STUN_METHOD_CONNECTION_BIND: handle_turn_connection_bind(server, ss, &tid, resp_constructed, &err_code, &reason, - unknown_attrs, &ua_num, in_buffer, nbh, message_integrity); + unknown_attrs, &ua_num, in_buffer, nbh, message_integrity, can_resume); if(server->verbose && err_code) { log_method(ss, "CONNECTION_BIND", err_code, reason); @@ -3646,9 +3649,9 @@ static int write_to_peerchannel(ts_ur_super_session* ss, u16bits chnum, ioa_net_ } static void client_input_handler(ioa_socket_handle s, int event_type, - ioa_net_data *data, void *arg); + ioa_net_data *data, void *arg, int can_resume); static void peer_input_handler(ioa_socket_handle s, int event_type, - ioa_net_data *data, void *arg); + ioa_net_data *data, void *arg, int can_resume); /////////////// Client actions ///////////////// @@ -4198,7 +4201,7 @@ int open_client_connection_session(turn_turnserver* server, "client_to_be_allocated_timeout_handler"); if(sm->nd.nbh) { - client_input_handler(newelem->s,IOA_EV_READ,&(sm->nd),ss); + client_input_handler(newelem->s,IOA_EV_READ,&(sm->nd),ss,sm->can_resume); ioa_network_buffer_delete(server->e, sm->nd.nbh); sm->nd.nbh = NULL; } @@ -4211,7 +4214,7 @@ int open_client_connection_session(turn_turnserver* server, /////////////// io handlers /////////////////// static void peer_input_handler(ioa_socket_handle s, int event_type, - ioa_net_data *in_buffer, void *arg) { + ioa_net_data *in_buffer, void *arg, int can_resume) { if (!(event_type & IOA_EV_READ) || !arg) return; @@ -4220,6 +4223,7 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, return; UNUSED_ARG(s); + UNUSED_ARG(can_resume); ts_ur_super_session* ss = (ts_ur_super_session*) arg; @@ -4324,7 +4328,7 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, } static void client_input_handler(ioa_socket_handle s, int event_type, - ioa_net_data *data, void *arg) { + ioa_net_data *data, void *arg, int can_resume) { if (!arg) return; @@ -4350,7 +4354,7 @@ static void client_input_handler(ioa_socket_handle s, int event_type, switch (elem->state) { case UR_STATE_READY: - read_client_connection(server, elem, ss, data, 1, 1); + read_client_connection(server, elem, ss, data, can_resume, 1); break; case UR_STATE_DONE: TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index c8855748..88134652 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -74,6 +74,7 @@ typedef enum _MESSAGE_TO_RELAY_TYPE MESSAGE_TO_RELAY_TYPE; struct socket_message { ioa_socket_handle s; ioa_net_data nd; + int can_resume; }; typedef enum { @@ -89,7 +90,7 @@ typedef void (*get_username_resume_cb)(int success, hmackey_t hmackey, st_passwo typedef u08bits *(*get_user_key_cb)(turnserver_id id, turn_credential_type ct, 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, u08bits *realm); typedef void (*release_allocation_quota_cb)(u08bits *username, 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); +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 band_limit_t (*allocate_bps_cb)(band_limit_t bps, int positive); @@ -202,7 +203,7 @@ int open_client_connection_session(turn_turnserver* server, struct socket_messag int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, int force, const char* reason); void set_disconnect_cb(turn_turnserver* server, int (*disconnect)(ts_ur_super_session*)); -int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_connection_id tcid, stun_tid *tid, ioa_socket_handle s, int message_integrity, ioa_net_data *nd); +int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_connection_id tcid, stun_tid *tid, ioa_socket_handle s, int message_integrity, ioa_net_data *nd, int can_resume); int report_turn_session_info(turn_turnserver *server, ts_ur_super_session *ss, int force_invalid); From 4b7a0a56c9be59f63e02800b0fd12a438477b01e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 31 May 2014 17:29:16 +0000 Subject: [PATCH 058/805] a minor fix --- src/apps/relay/dtls_listener.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index 623877ea..e763f496 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -604,6 +604,7 @@ static void udp_server_input_handler(evutil_socket_t fd, short what, void* arg) server->sm.m.sm.nd.nbh = elem; server->sm.m.sm.nd.recv_ttl = TTL_IGNORE; server->sm.m.sm.nd.recv_tos = TOS_IGNORE; + server->sm.m.sm.can_resume = 1; addr_set_any(&(server->sm.m.sm.nd.src_addr)); From d016f2a2c083f1b1aff43386fcdf5256d88e6863 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 31 May 2014 18:36:13 +0000 Subject: [PATCH 059/805] password change in the database for an active session is supported --- src/server/ns_turn_server.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index f2377499..882bc54a 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3095,6 +3095,13 @@ static int check_stun_auth(turn_turnserver *server, } } + if(can_resume) { + (server->userkeycb)(server->id, server->ct, usname, realm, resume_processing_after_username_check, in_buffer, ss->id, postpone_reply); + if(*postpone_reply) { + return 0; + } + } + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: user %s credentials are incorrect\n", __FUNCTION__, (char*)usname); From 4292a63573c5b9c0fd5f9eb451ca12afc08a5152 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 1 Jun 2014 01:40:36 +0000 Subject: [PATCH 060/805] auth cleaning --- src/apps/relay/netengine.c | 1 - src/apps/relay/tls_listener.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 95daee8c..f0f7d420 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -436,7 +436,6 @@ static int send_socket_to_general_relay(ioa_engine_handle e, struct message_to_r struct message_to_relay *smptr = sm; smptr->t = RMT_SOCKET; - smptr->m.sm.can_resume = 1; { struct evbuffer *output = NULL; diff --git a/src/apps/relay/tls_listener.c b/src/apps/relay/tls_listener.c index f887f166..53a605e8 100644 --- a/src/apps/relay/tls_listener.c +++ b/src/apps/relay/tls_listener.c @@ -104,6 +104,7 @@ static void server_input_handler(struct evconnlistener *l, evutil_socket_t fd, server->sm.m.sm.nd.recv_tos = TOS_IGNORE; server->sm.m.sm.nd.nbh = NULL; server->sm.m.sm.s = ioas; + server->sm.m.sm.can_resume = 1; server->sm.relay_server = server->relay_server; int rc = server->connect_cb(server->e, &(server->sm)); From 0d65000ff0f9fc26556cd682576c343e482cfbba Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 2 Jun 2014 19:53:51 +0000 Subject: [PATCH 061/805] Issue 128 merged from rfc5766-turn-server --- ChangeLog | 1 + src/apps/relay/ns_ioalib_engine_impl.c | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index e5b87590..70bc86c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 05/25/2014 Oleg Moskalenko Version 4.0.1.1 'Threetrees': - Bandwidth draft implemented. + - Issues 126, 127 and 128 fixes merged from rfc5766-turn-server. 05/18/2014 Oleg Moskalenko Version 4.0.0.2 'Threetrees': diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index d339339e..6398cf67 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -108,11 +108,13 @@ static int bufferevent_enabled(struct bufferevent *bufev, short flags) static int is_socket_writeable(ioa_socket_handle s, size_t sz, const char *msg, int option) { - UNUSED_ARG(s); UNUSED_ARG(sz); UNUSED_ARG(msg); UNUSED_ARG(option); + if(!s) + return 0; + if(!(s->done) && !(s->broken) && !(s->tobeclosed)) { switch(s->st) { @@ -2273,13 +2275,13 @@ static int socket_input_worker(ioa_socket_handle s) addr_cpy(&remote_addr,&(s->remote_addr)); if(tcp_congestion_control && s->sub_session && s->bev) { - if(s == s->sub_session->client_s) { + if(s == s->sub_session->client_s && (s->sub_session->peer_s)) { if(!is_socket_writeable(s->sub_session->peer_s, STUN_BUFFER_SIZE,__FUNCTION__,0)) { if(bufferevent_enabled(s->bev,EV_READ)) { bufferevent_disable(s->bev,EV_READ); } } - } else if(s == s->sub_session->peer_s) { + } else if(s == s->sub_session->peer_s && (s->sub_session->client_s)) { if(!is_socket_writeable(s->sub_session->client_s, STUN_BUFFER_SIZE,__FUNCTION__,1)) { if(bufferevent_enabled(s->bev,EV_READ)) { bufferevent_disable(s->bev,EV_READ); @@ -3430,7 +3432,7 @@ void turn_report_allocation_set(void *a, turn_time_t lifetime, int refresh) turn_turnserver *server = (turn_turnserver*)ss->server; if(server) { ioa_engine_handle e = turn_server_get_engine(server); - if(e && e->verbose) { + if(e && e->verbose && ss->client_session.s) { if(ss->client_session.s->ssl) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: %s, realm=<%s>, username=<%s>, lifetime=%lu, cipher=%s, method=%s (%s)\n", (unsigned long long)ss->id, status, (char*)ss->realm_options.name, (char*)ss->username, (unsigned long)lifetime, SSL_get_cipher(ss->client_session.s->ssl), turn_get_ssl_method(ss->client_session.s->ssl, ss->client_session.s->orig_ctx_type),ss->client_session.s->orig_ctx_type); From 51776875cf66366bc6ee885ca2c47ac2719ee328 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 3 Jun 2014 22:40:34 +0000 Subject: [PATCH 062/805] minor fix --- src/server/ns_turn_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 882bc54a..e546e64c 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -48,7 +48,7 @@ int TURN_MAX_ALLOCATE_TIMEOUT = 60; int TURN_MAX_ALLOCATE_TIMEOUT_STUN_ONLY = 3; #define log_method(ss, method, err_code, reason) \ -{\ +if (ss) {\ if(!(err_code)) {\ if(ss->origin[0]) {\ TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ From f4e49c5dbb717c7345bacb85cfaa34946713ac43 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 3 Jun 2014 22:55:24 +0000 Subject: [PATCH 063/805] working on rfc6062 crash --- src/server/ns_turn_allocation.c | 11 +++++++++++ src/server/ns_turn_allocation.h | 1 + src/server/ns_turn_server.c | 5 ++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/server/ns_turn_allocation.c b/src/server/ns_turn_allocation.c index f53be24f..4c2fc239 100644 --- a/src/server/ns_turn_allocation.c +++ b/src/server/ns_turn_allocation.c @@ -602,6 +602,17 @@ tcp_connection *get_and_clean_tcp_connection_by_id(ur_map *map, tcp_connection_i return NULL; } +tcp_connection *get_tcp_connection_by_id(ur_map *map, tcp_connection_id id) +{ + if(map) { + ur_map_value_type t = 0; + if (ur_map_get(map, (ur_map_key_type)id, &t) && t) { + return (tcp_connection*)t; + } + } + return NULL; +} + tcp_connection *get_tcp_connection_by_peer(allocation *a, ioa_addr *peer_addr) { if(a && peer_addr) { diff --git a/src/server/ns_turn_allocation.h b/src/server/ns_turn_allocation.h index f0da2a00..e67ba5d3 100644 --- a/src/server/ns_turn_allocation.h +++ b/src/server/ns_turn_allocation.h @@ -217,6 +217,7 @@ ts_ur_session *get_relay_session(allocation *a); ioa_socket_handle get_relay_socket(allocation *a); tcp_connection *get_and_clean_tcp_connection_by_id(ur_map *map, tcp_connection_id id); +tcp_connection *get_tcp_connection_by_id(ur_map *map, tcp_connection_id id); tcp_connection *get_tcp_connection_by_peer(allocation *a, ioa_addr *peer_addr); int can_accept_tcp_connection_from_peer(allocation *a, ioa_addr *peer_addr, int server_relay); tcp_connection *create_tcp_connection(u08bits server_id, allocation *a, stun_tid *tid, ioa_addr *peer_addr, int *err_code); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index e546e64c..830754ef 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -2062,7 +2062,7 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co if(tcid && tid && s) { - tc = get_and_clean_tcp_connection_by_id(server->tcp_relay_connections, tcid); + tc = get_tcp_connection_by_id(server->tcp_relay_connections, tcid); ioa_network_buffer_handle nbh = ioa_network_buffer_allocate(server->e); int resp_constructed = 0; if(!tc || (tc->state == TC_STATE_READY) || (tc->client_s)) { @@ -2100,6 +2100,9 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co } } + if(tc) + get_and_clean_tcp_connection_by_id(server->tcp_relay_connections, tcid); + if(!resp_constructed) { if(!err_code) { size_t len = ioa_network_buffer_get_size(nbh); From 769f2eaf1407f5e9e9fece1365d978ddc8c6b689 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 4 Jun 2014 17:06:44 +0000 Subject: [PATCH 064/805] cleaning --- src/server/ns_turn_server.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 830754ef..62ee04b6 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -47,27 +47,31 @@ int TURN_MAX_ALLOCATE_TIMEOUT = 60; int TURN_MAX_ALLOCATE_TIMEOUT_STUN_ONLY = 3; -#define log_method(ss, method, err_code, reason) \ -if (ss) {\ - if(!(err_code)) {\ - if(ss->origin[0]) {\ +#define log_method(ss0, method, err_code0, reason0) \ +if (ss0) {\ + ts_ur_super_session* _ss = (ss0); \ + int _err_code = (err_code0); \ + if(!_err_code) {\ + if(_ss->origin[0]) {\ TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ "session %018llu: origin <%s> realm <%s> user <%s>: incoming packet " method " processed, success\n",\ - (unsigned long long)(ss->id), (const char*)(ss->origin),(const char*)(ss->realm_options.name),(const char*)(ss->username));\ + (unsigned long long)(_ss->id), (const char*)(_ss->origin),(const char*)(_ss->realm_options.name),(const char*)(_ss->username));\ } else {\ TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ "session %018llu: realm <%s> user <%s>: incoming packet " method " processed, success\n",\ - (unsigned long long)(ss->id), (const char*)(ss->realm_options.name),(const char*)(ss->username));\ + (unsigned long long)(_ss->id), (const char*)(_ss->realm_options.name),(const char*)(_ss->username));\ }\ } else {\ - if(ss->origin[0]) {\ + const char *_reason = (const char*)(reason0); \ + if(!_reason) _reason="Unknown error"; \ + if(_ss->origin[0]) {\ TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ "session %018llu: origin <%s> realm <%s> user <%s>: incoming packet " method " processed, error %d: %s\n",\ - (unsigned long long)(ss->id), (const char*)(ss->origin),(const char*)(ss->realm_options.name),(const char*)(ss->username), (err_code), (reason));\ + (unsigned long long)(_ss->id), (const char*)(_ss->origin),(const char*)(_ss->realm_options.name),(const char*)(_ss->username), _err_code, _reason);\ } else {\ TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ "session %018llu: realm <%s> user <%s>: incoming packet " method " processed, error %d: %s\n",\ - (unsigned long long)(ss->id), (const char*)(ss->realm_options.name),(const char*)(ss->username), (err_code), (reason));\ + (unsigned long long)(_ss->id), (const char*)(_ss->realm_options.name),(const char*)(_ss->username), _err_code, _reason);\ }\ }\ } From 2bedd6d1fd2dd7a4f1ce131e1c77743a3b34510c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 5 Jun 2014 06:07:39 +0000 Subject: [PATCH 065/805] cleaning --- src/server/ns_turn_server.c | 54 ++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 62ee04b6..0e1e4912 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -47,33 +47,33 @@ int TURN_MAX_ALLOCATE_TIMEOUT = 60; int TURN_MAX_ALLOCATE_TIMEOUT_STUN_ONLY = 3; -#define log_method(ss0, method, err_code0, reason0) \ -if (ss0) {\ - ts_ur_super_session* _ss = (ss0); \ - int _err_code = (err_code0); \ - if(!_err_code) {\ - if(_ss->origin[0]) {\ - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ - "session %018llu: origin <%s> realm <%s> user <%s>: incoming packet " method " processed, success\n",\ - (unsigned long long)(_ss->id), (const char*)(_ss->origin),(const char*)(_ss->realm_options.name),(const char*)(_ss->username));\ - } else {\ - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ - "session %018llu: realm <%s> user <%s>: incoming packet " method " processed, success\n",\ - (unsigned long long)(_ss->id), (const char*)(_ss->realm_options.name),(const char*)(_ss->username));\ - }\ - } else {\ - const char *_reason = (const char*)(reason0); \ - if(!_reason) _reason="Unknown error"; \ - if(_ss->origin[0]) {\ - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ - "session %018llu: origin <%s> realm <%s> user <%s>: incoming packet " method " processed, error %d: %s\n",\ - (unsigned long long)(_ss->id), (const char*)(_ss->origin),(const char*)(_ss->realm_options.name),(const char*)(_ss->username), _err_code, _reason);\ - } else {\ - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,\ - "session %018llu: realm <%s> user <%s>: incoming packet " method " processed, error %d: %s\n",\ - (unsigned long long)(_ss->id), (const char*)(_ss->realm_options.name),(const char*)(_ss->username), _err_code, _reason);\ - }\ - }\ +static inline void log_method(ts_ur_super_session* ss, const char *method, int err_code, const u08bits *reason) +{ + if(ss) { + if(!method) method = "unknown"; + if(!err_code) { + if(ss->origin[0]) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "session %018llu: origin <%s> realm <%s> user <%s>: incoming packet %s processed, success\n", + (unsigned long long)(ss->id), (const char*)(ss->origin),(const char*)(ss->realm_options.name),(const char*)(ss->username),method); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "session %018llu: realm <%s> user <%s>: incoming packet %s processed, success\n", + (unsigned long long)(ss->id), (const char*)(ss->realm_options.name),(const char*)(ss->username),method); + } + } else { + if(!reason) reason=(const u08bits*)"Unknown error"; + if(ss->origin[0]) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "session %018llu: origin <%s> realm <%s> user <%s>: incoming packet %s processed, error %d: %s\n", + (unsigned long long)(ss->id), (const char*)(ss->origin),(const char*)(ss->realm_options.name),(const char*)(ss->username), method, err_code, reason); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "session %018llu: realm <%s> user <%s>: incoming packet %s processed, error %d: %s\n", + (unsigned long long)(ss->id), (const char*)(ss->realm_options.name),(const char*)(ss->username), method, err_code, reason); + } + } + } } /////////////////////////////////////////// From dde7b015d8d208637ecb2714bb9d445a98223f02 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 5 Jun 2014 15:09:02 +0000 Subject: [PATCH 066/805] TODO updated --- TODO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO b/TODO index f7c5af84..d06abbbc 100644 --- a/TODO +++ b/TODO @@ -64,7 +64,7 @@ when necessary: 3) MS TURN, MS STUN extensions. -4) Bandwidth draft. +4) Multiple origins. 5) ALPN with TLS and DTLS (when OpenSSL 1.0.2 is available). From 3b5021c3a0b5b52f9c40218741a4c55a504ee149 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 5 Jun 2014 19:46:11 +0000 Subject: [PATCH 067/805] schema fixed --- turndb/schema.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/turndb/schema.sql b/turndb/schema.sql index e4d84aca..36dee3cc 100644 --- a/turndb/schema.sql +++ b/turndb/schema.sql @@ -30,7 +30,7 @@ CREATE TABLE denied_peer_ip ( CREATE TABLE turn_origin_to_realm ( origin varchar(512), realm varchar(512), - primary key (origin,realm) + primary key (origin) ); CREATE TABLE turn_realm_option ( From 4ec76705083606e6b58e463c4d4a31bb218f5431 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 7 Jun 2014 06:31:08 +0000 Subject: [PATCH 068/805] version bump --- ChangeLog | 4 ++-- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 6 +++--- src/ns_turn_defs.h | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 70bc86c5..adfd5cec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ -05/25/2014 Oleg Moskalenko -Version 4.0.1.1 'Threetrees': +06/06/2014 Oleg Moskalenko +Version 4.0.1.2 'Severard': - Bandwidth draft implemented. - Issues 126, 127 and 128 fixes merged from rfc5766-turn-server. diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 11e7ee82..403e5409 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.0.1.1 +TURNVERSION=4.0.1.2 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index c9e0d5f9..ab9e5f55 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.0.1.1 +Version: 4.0.1.2 Release: 0%{dist} Summary: Coturn TURN Server @@ -289,8 +289,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Sun May 25 2014 Oleg Moskalenko - - Sync to 4.0.1.1 +* Fri Jun 06 2014 Oleg Moskalenko + - Sync to 4.0.1.2 * Sun May 18 2014 Oleg Moskalenko - Sync to 4.0.0.2 * Wed May 07 2014 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index b39538ce..8cedec21 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,8 +31,8 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.0.1.1" -#define TURN_SERVER_VERSION_NAME "Threetrees" +#define TURN_SERVER_VERSION "4.0.1.2" +#define TURN_SERVER_VERSION_NAME "Severard" #define TURN_SOFTWARE "Coturn-"TURN_SERVER_VERSION" '"TURN_SERVER_VERSION_NAME"'" #if (defined(__unix__) || defined(unix)) && !defined(USG) From 1c285660871b64f05915a96fc3f7f1480cd628e3 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 14 Jun 2014 06:05:04 +0000 Subject: [PATCH 069/805] log file reset on SIGHUP --- ChangeLog | 5 +++++ rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/apps/common/ns_turn_utils.c | 11 +++++++++++ src/ns_turn_defs.h | 2 +- 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index adfd5cec..0db7302f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +06/13/2014 Oleg Moskalenko +Version 4.0.1.3 'Severard': + - Logfile reset on SIGHUP + (Gustavo Garcia suggestion). + 06/06/2014 Oleg Moskalenko Version 4.0.1.2 'Severard': - Bandwidth draft implemented. diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 403e5409..a2d19a54 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.0.1.2 +TURNVERSION=4.0.1.3 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index ab9e5f55..5da21c4d 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.0.1.2 +Version: 4.0.1.3 Release: 0%{dist} Summary: Coturn TURN Server @@ -289,6 +289,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Fri Jun 13 2014 Oleg Moskalenko + - Sync to 4.0.1.3 * Fri Jun 06 2014 Oleg Moskalenko - Sync to 4.0.1.2 * Sun May 18 2014 Oleg Moskalenko diff --git a/src/apps/common/ns_turn_utils.c b/src/apps/common/ns_turn_utils.c index ca0a5777..211d9f8f 100644 --- a/src/apps/common/ns_turn_utils.c +++ b/src/apps/common/ns_turn_utils.c @@ -42,6 +42,8 @@ #include #include +#include + ////////// LOG TIME OPTIMIZATION /////////// static volatile turn_time_t log_start_time = 0; @@ -337,11 +339,20 @@ static void set_log_file_name_func(char *base, char *f, size_t fsz) turn_free(tail,strlen(tail)+1); } +static void sighup_callback_handler(int signum) +{ + if(signum == SIGHUP) { + printf("%s: resetting the log file\n",__FUNCTION__); + reset_rtpprintf(); + } +} + static void set_rtpfile(void) { if(to_syslog) { return; } else if (!_rtpfile) { + signal(SIGHUP, sighup_callback_handler); if(log_fn_base[0]) { if(!strcmp(log_fn_base,"syslog")) { _rtpfile = stdout; diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 8cedec21..261bcf5e 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.0.1.2" +#define TURN_SERVER_VERSION "4.0.1.3" #define TURN_SERVER_VERSION_NAME "Severard" #define TURN_SOFTWARE "Coturn-"TURN_SERVER_VERSION" '"TURN_SERVER_VERSION_NAME"'" From a70f1f9e23c89b27b35d3a12b26e19974493990b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 15 Jun 2014 03:49:05 +0000 Subject: [PATCH 070/805] log reset CLI command --- ChangeLog | 1 + src/apps/relay/turncli.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/ChangeLog b/ChangeLog index 0db7302f..e82ab455 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,7 @@ Version 4.0.1.3 'Severard': - Logfile reset on SIGHUP (Gustavo Garcia suggestion). + - Log reset CLi command. 06/06/2014 Oleg Moskalenko Version 4.0.1.2 'Severard': diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index 6645add5..d04f2a44 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -132,6 +132,8 @@ static const char *CLI_HELP_STR[] = "", " pu [udp|tcp|dtls|tls]- print current users", "", + " lr - log reset", + "", " aas ip[:port} - add an alternate server reference", " das ip[:port] - delete an alternate server reference", " atas ip[:port] - add a TLS alternate server reference", @@ -191,6 +193,14 @@ static void myprintf(struct cli_session *cs, const char *format, ...) } } +static void log_reset(struct cli_session* cs) +{ + if(cs) { + reset_rtpprintf(); + myprintf(cs," log reset done\n"); + } +} + static void print_str_array(struct cli_session* cs, const char** sa) { if(cs && sa) { @@ -1012,6 +1022,9 @@ static int run_cli_input(struct cli_session* cs, const char *buf0, unsigned int } else if(strstr(cmd,"ps") == cmd) { print_sessions(cs,cmd+2,1,0); type_cli_cursor(cs); + } else if(strstr(cmd,"lr") == cmd) { + log_reset(cs); + type_cli_cursor(cs); } else if(strstr(cmd,"cc ") == cmd) { change_cli_param(cs,cmd+3); type_cli_cursor(cs); From aab8215a4d8615966cfc8e0406cdcaec0f72846f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 16 Jun 2014 06:32:32 +0000 Subject: [PATCH 071/805] error codes fixed --- ChangeLog | 3 +++ src/server/ns_turn_server.c | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index e82ab455..e977ce7d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,9 @@ Version 4.0.1.3 'Severard': - Logfile reset on SIGHUP (Gustavo Garcia suggestion). - Log reset CLi command. + - Some error code corrections: + * "Mobility forbidden" error changed, to value 405. + * "Wrong credentials" situation is now treated as error 441. 06/06/2014 Oleg Moskalenko Version 4.0.1.2 'Severard': diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 0e1e4912..657d02fe 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -927,7 +927,7 @@ static int handle_turn_allocate(turn_turnserver *server, break; case STUN_ATTRIBUTE_MOBILITY_TICKET: if(!(*(server->mobility))) { - *err_code = 501; + *err_code = 405; *reason = (const u08bits *)"Mobility Forbidden"; } else if (stun_attr_get_len(sar) != 0) { *err_code = 400; @@ -1211,7 +1211,7 @@ static int handle_turn_refresh(turn_turnserver *server, SKIP_ATTRIBUTES; case STUN_ATTRIBUTE_MOBILITY_TICKET: { if(!(*(server->mobility))) { - *err_code = 501; + *err_code = 405; *reason = (const u08bits *)"Mobility forbidden"; } if(is_allocation_valid(a)) { *err_code = 400; @@ -3012,8 +3012,8 @@ static int check_stun_auth(turn_turnserver *server, if(ss->username[0]) { if(strcmp((char*)ss->username,(char*)usname)) { - *err_code = 401; - *reason = (const u08bits*)"Wrong username"; + *err_code = 441; + *reason = (const u08bits*)"Wrong credentials"; return -1; } } else { From 495d7940b6edccb30e292834a78f5cc2e8d5cf77 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 16 Jun 2014 06:40:25 +0000 Subject: [PATCH 072/805] an error code fixed --- src/server/ns_turn_server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 657d02fe..1eefd940 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -2988,8 +2988,8 @@ static int check_stun_auth(turn_turnserver *server, get_realm_options_by_name((char *)realm, &(ss->realm_options)); } else if(strcmp((char*)realm, (char*)(ss->realm_options.name))) { - *err_code = 400; - *reason = (const u08bits*)"Bad request: the realm value incorrect"; + *err_code = 441; + *reason = (const u08bits*)"Wrong credentials: the realm value incorrect"; return -1; } } From 14ef08b18294ccd796741fcfa863e0ba6935a482 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 18 Jun 2014 17:47:39 +0000 Subject: [PATCH 073/805] Issue 129 fixed merged from the sister project --- ChangeLog | 1 + src/apps/relay/userdb.c | 48 +++++++++++++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index e977ce7d..2cfcf256 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 06/13/2014 Oleg Moskalenko Version 4.0.1.3 'Severard': + - Redis DB connection status fixed (Issue 129). - Logfile reset on SIGHUP (Gustavo Garcia suggestion). - Log reset CLi command. diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 73251133..5801232a 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -879,19 +879,45 @@ static redisContext *get_redis_connection(void) redisconnection = redisConnect(ip, port); } - if (!redisconnection) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB connection\n"); - } else { - if (co->password) { - turnFreeRedisReply(redisCommand(redisconnection, "AUTH %s", co->password)); - } - if (co->dbname) { - turnFreeRedisReply(redisCommand(redisconnection, "select %s", co->dbname)); - } - if (!donot_print_connection_success) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis DB sync connection success: %s\n", pud->userdb); + if (redisconnection) { + if(redisconnection->err) { + if(redisconnection->errstr[0]) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis: %s\n",redisconnection->errstr); + } + redisFree(redisconnection); + redisconnection = NULL; + } else if (co->password) { + void *reply = redisCommand(redisconnection, "AUTH %s", co->password); + if(!reply) { + if(redisconnection->err && redisconnection->errstr[0]) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis: %s\n",redisconnection->errstr); + } + redisFree(redisconnection); + redisconnection = NULL; + } else { + turnFreeRedisReply(reply); + if (co->dbname) { + reply = redisCommand(redisconnection, "select %s", co->dbname); + if(!reply) { + if(redisconnection->err && redisconnection->errstr[0]) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis: %s\n",redisconnection->errstr); + } + redisFree(redisconnection); + redisconnection = NULL; + } else { + turnFreeRedisReply(reply); + } + } + } } } + + if (!redisconnection) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB connection\n"); + } else if (!donot_print_connection_success) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis DB sync connection success: %s\n", pud->userdb); + } + RyconninfoFree(co); } pud->connection = redisconnection; From 76e358d47702bbcdf6f97fe32aa2d3e2a1a2c7a5 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 22 Jun 2014 07:39:03 +0000 Subject: [PATCH 074/805] update for c++11 --- src/ns_turn_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 261bcf5e..e025d140 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -33,7 +33,7 @@ #define TURN_SERVER_VERSION "4.0.1.3" #define TURN_SERVER_VERSION_NAME "Severard" -#define TURN_SOFTWARE "Coturn-"TURN_SERVER_VERSION" '"TURN_SERVER_VERSION_NAME"'" +#define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" #if (defined(__unix__) || defined(unix)) && !defined(USG) #include From d5121987ba0d9bef694173e7e2cc8f8cd365229f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 26 Jun 2014 06:03:00 +0000 Subject: [PATCH 075/805] version bump --- ChangeLog | 4 ++++ README.turnserver | 4 +++- examples/etc/turnserver.conf | 4 +++- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 6 ++++-- man/man1/turnutils.1 | 2 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/ns_turn_defs.h | 2 +- 9 files changed, 21 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2cfcf256..37ea073b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +06/25/2014 Oleg Moskalenko +Version 4.0.1.4 'Severard': + - c++11 compilation warnings fixed. + 06/13/2014 Oleg Moskalenko Version 4.0.1.3 'Severard': - Redis DB connection status fixed (Issue 129). diff --git a/README.turnserver b/README.turnserver index fbc0efe7..888a7e0b 100644 --- a/README.turnserver +++ b/README.turnserver @@ -425,7 +425,9 @@ Options with required values: definite log file name. The special names are "stdout" and "-" - they will force everything to the stdout. Also, "syslog" name will redirect everything into - the system log (syslog), as if the option "--syslog" was set. + the system log (syslog), as if the option "--syslog" was set. + In the runtime, the logfile can be reset with the SIGHUP signal + to the turnserver process. --alternate-server Option to set the "redirection" mode. The value of this option will be the address of the alternate server for UDP & TCP service in form of diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 5cf7f7c1..f5dc5f8a 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -421,7 +421,9 @@ # With this option you can set the definite log file name. # The special names are "stdout" and "-" - they will force everything # to the stdout. Also, the "syslog" name will force everything to -# the system log (syslog). +# the system log (syslog). +# In the runtime, the logfile can be reset with the SIGHUP signal +# to the turnserver process. # #log-file=/var/tmp/turn.log diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 029151f9..70b13659 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "29 May 2014" "" "" +.TH TURN 1 "25 June 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 395b2dfc..a4546fa2 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "29 May 2014" "" "" +.TH TURN 1 "25 June 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -625,7 +625,9 @@ first that file will be used). With this option you can set the definite log file name. The special names are "stdout" and "\-" \- they will force everything to the stdout. Also, "syslog" name will redirect everything into -the system log (syslog), as if the option "\fB\-\-syslog\fP" was set. +the system log (syslog), as if the option "\fB\-\-syslog\fP" was set. +In the runtime, the logfile can be reset with the SIGHUP signal +to the \fIturnserver\fP process. .TP .B \fB\-\-alternate\-server\fP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 9601c90a..facf3c58 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "29 May 2014" "" "" +.TH TURN 1 "25 June 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index a2d19a54..85abba6d 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.0.1.3 +TURNVERSION=4.0.1.4 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 5da21c4d..abb36815 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.0.1.3 +Version: 4.0.1.4 Release: 0%{dist} Summary: Coturn TURN Server @@ -289,6 +289,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Wed Jun 25 2014 Oleg Moskalenko + - Sync to 4.0.1.4 * Fri Jun 13 2014 Oleg Moskalenko - Sync to 4.0.1.3 * Fri Jun 06 2014 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index e025d140..636adde1 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.0.1.3" +#define TURN_SERVER_VERSION "4.0.1.4" #define TURN_SERVER_VERSION_NAME "Severard" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 3be4918558e72d4f060e970ed5d6e05fca8166ef Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 27 Jun 2014 06:00:01 +0000 Subject: [PATCH 076/805] extra warnings --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index c09a3b64..9b584d6c 100755 --- a/configure +++ b/configure @@ -714,7 +714,7 @@ fi GNUOSCFLAGS="-g ${GNUOSCFLAGS}" GNUOSCFLAGS="${GNUOSCFLAGS} -Wall -Wno-deprecated-declarations -Wextra -Wformat-security -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wcast-qual" -GNUOSCFLAGS="${GNUOSCFLAGS} -Wno-write-strings" +GNUOSCFLAGS="${GNUOSCFLAGS}" ${CC} -Werror ${GNUOSCFLAGS} ${TMPCPROGC} ${OSCFLAGS} -o ${TMPCPROGB} 2>>/dev/null ER=$? @@ -726,7 +726,7 @@ if ! [ ${ER} -eq 0 ] ; then ${ECHO_CMD} "Not an ordinary GNU or Clang compiler" else ${ECHO_CMD} "g++ or something..." - GNUOSCFLAGS="-g -Wall -Wno-deprecated-declarations -Wextra -Wformat-security -Wpointer-arith -Wcast-qual -Wno-write-strings" + GNUOSCFLAGS="-g -Wall -Wno-deprecated-declarations -Wextra -Wformat-security -Wpointer-arith -Wcast-qual" ${CC} -Werror ${GNUOSCFLAGS} ${TMPCPROGC} ${OSCFLAGS} -o ${TMPCPROGB} 2>>/dev/null ER=$? if ! [ ${ER} -eq 0 ] ; then From 65993999629ef686557b9bc94370fa2bdb25efb8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 27 Jun 2014 06:04:07 +0000 Subject: [PATCH 077/805] extra warnings --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 9b584d6c..2e156038 100755 --- a/configure +++ b/configure @@ -731,7 +731,7 @@ if ! [ ${ER} -eq 0 ] ; then ER=$? if ! [ ${ER} -eq 0 ] ; then ${ECHO_CMD} "Not an ordinary g++ compiler" - GNUOSCFLAGS="-x c++ -g -Wall -Wno-deprecated-declarations -Wextra -Wformat-security -Wpointer-arith -Wcast-qual -Wno-write-strings" + GNUOSCFLAGS="-x c++ -g -Wall -Wno-deprecated-declarations -Wextra -Wformat-security -Wpointer-arith -Wcast-qual" ${CC} -Werror ${GNUOSCFLAGS} ${TMPCPROGC} ${OSCFLAGS} -o ${TMPCPROGB} 2>>/dev/null ER=$? if ! [ ${ER} -eq 0 ] ; then From c45284801f489cbb91dd1137677157e140788b3c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 27 Jun 2014 06:50:26 +0000 Subject: [PATCH 078/805] working on warnings --- src/apps/relay/mainrelay.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index c0c07240..a0e3d4f1 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -661,7 +661,15 @@ enum EXTRA_OPTS { ADMIN_USER_QUOTA_OPT }; -static struct option long_options[] = { +struct myoption { + const char *name; /* name of long option */ + int has_arg; /* whether option takes an argument */ + int *flag; /* if not NULL, set *flag to val when option found */ + int val; /* if flag is not NULL, value to set *flag to. */ + /* if flag is NULL, return value */ +}; + +static const struct myoption long_options[] = { { "listening-device", required_argument, NULL, 'd' }, { "listening-port", required_argument, NULL, 'p' }, { "tls-listening-port", required_argument, NULL, TLS_PORT_OPT }, @@ -755,7 +763,7 @@ static struct option long_options[] = { { NULL, no_argument, NULL, 0 } }; -static struct option admin_long_options[] = { +static const struct myoption admin_long_options[] = { { "key", no_argument, NULL, 'k' }, { "add", no_argument, NULL, 'a' }, { "delete", no_argument, NULL, 'd' }, @@ -1340,7 +1348,7 @@ static int adminmain(int argc, char **argv) u08bits origin[STUN_MAX_ORIGIN_SIZE+1]=""; perf_options_t po = {(band_limit_t)-1,-1,-1}; - while (((c = getopt_long(argc, argv, ADMIN_OPTIONS, admin_long_options, NULL)) != -1)) { + while (((c = getopt_long(argc, argv, ADMIN_OPTIONS, (const struct option*)admin_long_options, NULL)) != -1)) { switch (c){ case 'g': ct = TA_SET_REALM_OPTION; @@ -1640,7 +1648,7 @@ int main(int argc, char **argv) init_dynamic_ip_lists(); if (!strstr(argv[0], "turnadmin")) { - while (((c = getopt_long(argc, argv, OPTIONS, long_options, NULL)) != -1)) { + while (((c = getopt_long(argc, argv, OPTIONS, (const struct option*)long_options, NULL)) != -1)) { switch (c){ case 'l': set_logfile(optarg); @@ -1700,7 +1708,7 @@ int main(int argc, char **argv) read_config_file(argc,argv,0); - while (((c = getopt_long(argc, argv, OPTIONS, long_options, NULL)) != -1)) { + while (((c = getopt_long(argc, argv, OPTIONS, (const struct option*)long_options, NULL)) != -1)) { if(c != 'u') set_option(c,optarg); } @@ -1709,7 +1717,7 @@ int main(int argc, char **argv) optind = 0; - while (((c = getopt_long(argc, argv, OPTIONS, long_options, NULL)) != -1)) { + while (((c = getopt_long(argc, argv, OPTIONS, (const struct option*)long_options, NULL)) != -1)) { if(c == 'u') { set_option(c,optarg); } From 0657709ec1aaa71d1f042fb74c26787e3cd92aaf Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 27 Jun 2014 07:10:31 +0000 Subject: [PATCH 079/805] changelog updated --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 37ea073b..cca9aa71 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ 06/25/2014 Oleg Moskalenko Version 4.0.1.4 'Severard': - - c++11 compilation warnings fixed. + - working on compilation warnings. 06/13/2014 Oleg Moskalenko Version 4.0.1.3 'Severard': From 6477fcdceeabd44398ef9c47a4a1bdcfa4e12a37 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 29 Jun 2014 05:33:13 +0000 Subject: [PATCH 080/805] multiple origins supported --- ChangeLog | 1 + src/apps/relay/userdb.c | 4 +++- src/server/ns_turn_ioalib.h | 2 +- src/server/ns_turn_server.c | 41 ++++++++++++++++++++++--------------- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index cca9aa71..db1f63ca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 06/25/2014 Oleg Moskalenko Version 4.0.1.4 'Severard': + - multiple origins supported. - working on compilation warnings. 06/13/2014 Oleg Moskalenko diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 5801232a..953acd9b 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -186,7 +186,7 @@ int get_realm_data(char* name, realm_params_t* rp) return 0; } -void get_realm_options_by_origin(char *origin, realm_options_t* ro) +int get_realm_options_by_origin(char *origin, realm_options_t* ro) { ur_string_map_value_type value = 0; TURN_MUTEX_LOCK(&o_to_realm_mutex); @@ -197,9 +197,11 @@ void get_realm_options_by_origin(char *origin, realm_options_t* ro) get_realm_data(realm, &rp); ns_bcopy(&(rp.options),ro,sizeof(realm_options_t)); free(realm); + return 1; } else { TURN_MUTEX_UNLOCK(&o_to_realm_mutex); get_default_realm_options(ro); + return 0; } } diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 41ea6d9e..73ddf09b 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -260,7 +260,7 @@ unsigned char *base64_decode(const char *data, ///////////// Realm /////////////////// void get_default_realm_options(realm_options_t* ro); -void get_realm_options_by_origin(char *origin, realm_options_t* ro); +int get_realm_options_by_origin(char *origin, realm_options_t* ro); void get_realm_options_by_name(char *realm, realm_options_t* ro); int get_canonic_origin(const char* o, char *co, int sz); int get_default_protocol_port(const char* scheme, size_t slen); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 1eefd940..2e65ae11 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3231,29 +3231,36 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, } if(!(ss->realm_set) && (method == STUN_METHOD_ALLOCATE)) { - stun_attr_ref sar = stun_attr_get_first_by_type_str(ioa_network_buffer_data(in_buffer->nbh), - ioa_network_buffer_get_size(in_buffer->nbh), - STUN_ATTRIBUTE_ORIGIN); - if(sar) { - int sarlen = stun_attr_get_len(sar); - if(sarlen>0) { - char *o = (char*)turn_malloc(sarlen+1); - ns_bcopy(stun_attr_get_value(sar),o,sarlen); - o[sarlen]=0; - char *corigin = (char*)turn_malloc(STUN_MAX_ORIGIN_SIZE+1); - corigin[0]=0; - if(get_canonic_origin(o,corigin,STUN_MAX_ORIGIN_SIZE)<0) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh)); + + int origin_found = 0; + + while(sar && !origin_found) { + if(stun_attr_get_type(sar) == STUN_ATTRIBUTE_ORIGIN) { + int sarlen = stun_attr_get_len(sar); + if(sarlen>0) { + char *o = (char*)turn_malloc(sarlen+1); + ns_bcopy(stun_attr_get_value(sar),o,sarlen); + o[sarlen]=0; + char *corigin = (char*)turn_malloc(STUN_MAX_ORIGIN_SIZE+1); + corigin[0]=0; + if(get_canonic_origin(o,corigin,STUN_MAX_ORIGIN_SIZE)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Wrong origin format: %s\n", __FUNCTION__, o); + } + strncpy(ss->origin,corigin,STUN_MAX_ORIGIN_SIZE); + turn_free(corigin,sarlen+1); + turn_free(o,sarlen+1); + origin_found = get_realm_options_by_origin(ss->origin,&(ss->realm_options)); } - strncpy(ss->origin,corigin,STUN_MAX_ORIGIN_SIZE); - turn_free(corigin,sarlen+1); - turn_free(o,sarlen+1); - get_realm_options_by_origin(ss->origin,&(ss->realm_options)); } + sar = stun_attr_get_next_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), sar); } + ss->realm_set = 1; } From 9ff68fff25ec2ccafdecf7ed9a146c6e512cd477 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 29 Jun 2014 06:32:57 +0000 Subject: [PATCH 081/805] compilation warnings fixed --- src/apps/relay/mainrelay.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index a0e3d4f1..94f953ac 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -669,6 +669,13 @@ struct myoption { /* if flag is NULL, return value */ }; +struct uoptions { + union { + const struct myoption *m; + const struct option *o; + } u; +}; + static const struct myoption long_options[] = { { "listening-device", required_argument, NULL, 'd' }, { "listening-port", required_argument, NULL, 'p' }, @@ -1348,7 +1355,10 @@ static int adminmain(int argc, char **argv) u08bits origin[STUN_MAX_ORIGIN_SIZE+1]=""; perf_options_t po = {(band_limit_t)-1,-1,-1}; - while (((c = getopt_long(argc, argv, ADMIN_OPTIONS, (const struct option*)admin_long_options, NULL)) != -1)) { + struct uoptions uo; + uo.u.m = admin_long_options; + + while (((c = getopt_long(argc, argv, ADMIN_OPTIONS, uo.u.o, NULL)) != -1)) { switch (c){ case 'g': ct = TA_SET_REALM_OPTION; @@ -1648,7 +1658,11 @@ int main(int argc, char **argv) init_dynamic_ip_lists(); if (!strstr(argv[0], "turnadmin")) { - while (((c = getopt_long(argc, argv, OPTIONS, (const struct option*)long_options, NULL)) != -1)) { + + struct uoptions uo; + uo.u.m = long_options; + + while (((c = getopt_long(argc, argv, OPTIONS, uo.u.o, NULL)) != -1)) { switch (c){ case 'l': set_logfile(optarg); @@ -1708,7 +1722,10 @@ int main(int argc, char **argv) read_config_file(argc,argv,0); - while (((c = getopt_long(argc, argv, OPTIONS, (const struct option*)long_options, NULL)) != -1)) { + struct uoptions uo; + uo.u.m = long_options; + + while (((c = getopt_long(argc, argv, OPTIONS, uo.u.o, NULL)) != -1)) { if(c != 'u') set_option(c,optarg); } @@ -1717,7 +1734,7 @@ int main(int argc, char **argv) optind = 0; - while (((c = getopt_long(argc, argv, OPTIONS, (const struct option*)long_options, NULL)) != -1)) { + while (((c = getopt_long(argc, argv, OPTIONS, uo.u.o, NULL)) != -1)) { if(c == 'u') { set_option(c,optarg); } From 7f367a7330c14ce1b0a80c12f1c6875a650adf22 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 29 Jun 2014 07:22:16 +0000 Subject: [PATCH 082/805] typo fixed --- INSTALL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL b/INSTALL index 82a0e72d..8a923382 100644 --- a/INSTALL +++ b/INSTALL @@ -50,7 +50,7 @@ The turn*.conf config files are in /etc directory. The service start-up control scripts will be in /etc/init.d/coturn and in /etc/defaults/coturn files. -3) ArchLinux has alse the predecessor of the TURN server package: +3) ArchLinux has also the predecessor of the TURN server package: https://aur.archlinux.org/packages/rfc5766-turn-server/ From eaf84cf18b81779248ab2b8c87e9f8c62d809709 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 29 Jun 2014 07:25:30 +0000 Subject: [PATCH 083/805] archlinux info updated --- INSTALL | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/INSTALL b/INSTALL index 8a923382..ff60b585 100644 --- a/INSTALL +++ b/INSTALL @@ -50,11 +50,11 @@ The turn*.conf config files are in /etc directory. The service start-up control scripts will be in /etc/init.d/coturn and in /etc/defaults/coturn files. -3) ArchLinux has also the predecessor of the TURN server package: +3) ArchLinux has this TURN server package: -https://aur.archlinux.org/packages/rfc5766-turn-server/ +https://aur.archlinux.org/packages/coturn/ -4) OpenSUSE has a package, too: +4) OpenSUSE has an older package, too: https://build.opensuse.org/package/show/home:ehauenstein/rfc5766-turn-server From 77805876e5380348660b95faef4eaa5117692508 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 30 Jun 2014 04:34:21 +0000 Subject: [PATCH 084/805] multiple origins "emitted" by uclient --- src/apps/uclient/startuclient.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 171ad97b..1593d28a 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -355,8 +355,13 @@ static int clnet_allocate(int verbose, } } - if(origin[0]) + if(origin[0]) { + const char* some_origin = "https://carleon.gov:443"; + stun_attr_add(&message, STUN_ATTRIBUTE_ORIGIN, some_origin, strlen(some_origin)); stun_attr_add(&message, STUN_ATTRIBUTE_ORIGIN, origin, strlen(origin)); + some_origin = "ftp://uffrith.net"; + stun_attr_add(&message, STUN_ATTRIBUTE_ORIGIN, some_origin, strlen(some_origin)); + } if(add_integrity(clnet_info, &message)<0) return -1; From dbd1b97e57b2d493422d39206e992046b81a5f26 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 30 Jun 2014 05:02:37 +0000 Subject: [PATCH 085/805] some proprietary code removed --- src/server/ns_turn_server.c | 10 +++++----- src/server/ns_turn_session.h | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 2e65ae11..0367535f 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1898,7 +1898,7 @@ static int handle_turn_connect(turn_turnserver *server, if(stun_attr_get_addr_str(ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh), sar, &peer_addr, - &(ss->default_peer_addr)) == -1) { + NULL) == -1) { *err_code = 400; *reason = (const u08bits *)"Bad Peer Address"; } else { @@ -2216,7 +2216,7 @@ static int handle_turn_channel_bind(turn_turnserver *server, stun_attr_get_addr_str(ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh), sar, &peer_addr, - &(ss->default_peer_addr)); + NULL); ioa_addr *relay_addr = get_local_addr_from_ioa_socket(a->relay_session.s); @@ -2591,7 +2591,7 @@ static int handle_turn_send(turn_turnserver *server, ts_ur_super_session *ss, stun_attr_get_addr_str(ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh), sar, &peer_addr, - &(ss->default_peer_addr)); + NULL); } } break; @@ -2717,7 +2717,7 @@ static int handle_turn_create_permission(turn_turnserver *server, stun_attr_get_addr_str(ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh), sar, &peer_addr, - &(ss->default_peer_addr)); + NULL); ioa_addr *relay_addr = get_local_addr_from_ioa_socket(a->relay_session.s); @@ -2776,7 +2776,7 @@ static int handle_turn_create_permission(turn_turnserver *server, stun_attr_get_addr_str(ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh), sar, &peer_addr, - &(ss->default_peer_addr)); + NULL); addr_set_port(&peer_addr, 0); if (update_permission(ss, &peer_addr) < 0) { diff --git a/src/server/ns_turn_session.h b/src/server/ns_turn_session.h index 60366f42..db247898 100644 --- a/src/server/ns_turn_session.h +++ b/src/server/ns_turn_session.h @@ -70,7 +70,6 @@ struct _ts_ur_super_session { turnsession_id id; turn_time_t start_time; ts_ur_session client_session; - ioa_addr default_peer_addr; allocation alloc; ioa_timer_handle to_be_allocated_timeout_ev; u08bits nonce[NONCE_MAX_SIZE]; From b8c87ea5e8c68aa79ec5ffcba771fad70c451e2e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 7 Jul 2014 06:35:32 +0000 Subject: [PATCH 086/805] working on double allocs --- src/apps/relay/ns_ioalib_engine_impl.c | 10 +- src/apps/uclient/session.h | 1 - src/server/ns_turn_allocation.c | 12 +- src/server/ns_turn_allocation.h | 24 +-- src/server/ns_turn_server.c | 248 +++++++++---------------- src/server/ns_turn_session.h | 2 +- 6 files changed, 110 insertions(+), 187 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 6398cf67..065ba659 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -2761,7 +2761,7 @@ static void eventcb_bev(struct bufferevent *bev, short events, void *arg) if (events & BEV_EVENT_EOF) { if(server->verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: TCP socket closed remotely %s\n",(unsigned long long)(ss->id),sraddr); - if(s == ss->client_session.s) { + if(s == ss->client_socket) { shutdown_client_connection(server, ss, 0, "TCP connection closed by client (callback)"); } else if(s == ss->alloc.relay_session.s) { shutdown_client_connection(server, ss, 0, "TCP connection closed by peer (callback)"); @@ -3432,10 +3432,10 @@ void turn_report_allocation_set(void *a, turn_time_t lifetime, int refresh) turn_turnserver *server = (turn_turnserver*)ss->server; if(server) { ioa_engine_handle e = turn_server_get_engine(server); - if(e && e->verbose && ss->client_session.s) { - if(ss->client_session.s->ssl) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: %s, realm=<%s>, username=<%s>, lifetime=%lu, cipher=%s, method=%s (%s)\n", (unsigned long long)ss->id, status, (char*)ss->realm_options.name, (char*)ss->username, (unsigned long)lifetime, SSL_get_cipher(ss->client_session.s->ssl), - turn_get_ssl_method(ss->client_session.s->ssl, ss->client_session.s->orig_ctx_type),ss->client_session.s->orig_ctx_type); + if(e && e->verbose && ss->client_socket) { + if(ss->client_socket->ssl) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: %s, realm=<%s>, username=<%s>, lifetime=%lu, cipher=%s, method=%s (%s)\n", (unsigned long long)ss->id, status, (char*)ss->realm_options.name, (char*)ss->username, (unsigned long)lifetime, SSL_get_cipher(ss->client_socket->ssl), + turn_get_ssl_method(ss->client_socket->ssl, ss->client_socket->orig_ctx_type),ss->client_socket->orig_ctx_type); } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: %s, realm=<%s>, username=<%s>, lifetime=%lu\n", (unsigned long long)ss->id, status, (char*)ss->realm_options.name, (char*)ss->username, (unsigned long)lifetime); } diff --git a/src/apps/uclient/session.h b/src/apps/uclient/session.h index 39e2fbca..5635c529 100644 --- a/src/apps/uclient/session.h +++ b/src/apps/uclient/session.h @@ -95,7 +95,6 @@ typedef struct { uint16_t chnum; int wait_cycles; int timer_cycle; - int known_mtu; int completed; struct event *input_ev; struct event *input_tcp_data_ev; diff --git a/src/server/ns_turn_allocation.c b/src/server/ns_turn_allocation.c index 4c2fc239..dff6c5c4 100644 --- a/src/server/ns_turn_allocation.c +++ b/src/server/ns_turn_allocation.c @@ -71,9 +71,9 @@ void clear_allocation(allocation *a) a->tcs.sz = 0; clear_ioa_socket_session_if(a->relay_session.s, a->owner); - clear_ts_ur_session_data(&(a->relay_session)); + clear_relay_endpoint_session_data(&(a->relay_session)); - IOA_EVENT_DEL(a->lifetime_ev); + IOA_EVENT_DEL(a->relay_session.lifetime_ev); /* The order is important here: */ free_turn_permission_hashtable(&(a->addr_to_perm)); @@ -83,7 +83,7 @@ void clear_allocation(allocation *a) } } -ts_ur_session *get_relay_session(allocation *a) +relay_endpoint_session *get_relay_session(allocation *a) { return &(a->relay_session); } @@ -96,9 +96,9 @@ ioa_socket_handle get_relay_socket(allocation *a) void set_allocation_lifetime_ev(allocation *a, turn_time_t exp_time, ioa_timer_handle ev) { if (a) { - IOA_EVENT_DEL(a->lifetime_ev); - a->expiration_time = exp_time; - a->lifetime_ev = ev; + IOA_EVENT_DEL(a->relay_session.lifetime_ev); + a->relay_session.expiration_time = exp_time; + a->relay_session.lifetime_ev = ev; } } diff --git a/src/server/ns_turn_allocation.h b/src/server/ns_turn_allocation.h index e67ba5d3..c99440de 100644 --- a/src/server/ns_turn_allocation.h +++ b/src/server/ns_turn_allocation.h @@ -45,26 +45,16 @@ extern "C" { #define TCP_PEER_CONN_TIMEOUT (30) #define TCP_CONN_BIND_TIMEOUT (30) -///////// types //////////// - -enum _UR_STATE { - UR_STATE_UNKNOWN=0, - UR_STATE_READY, - UR_STATE_DONE -}; - -typedef enum _UR_STATE UR_STATE; - ////////////// Network session //////////////// typedef struct { - UR_STATE state; ioa_socket_handle s; - int known_mtu; -} ts_ur_session; + turn_time_t expiration_time; + ioa_timer_handle lifetime_ev; +} relay_endpoint_session; -static inline void clear_ts_ur_session_data(ts_ur_session* cdi) +static inline void clear_relay_endpoint_session_data(relay_endpoint_session* cdi) { if (cdi) IOA_CLOSE_SOCKET(cdi->s); @@ -178,10 +168,8 @@ typedef struct _turn_permission_hashtable { typedef struct _allocation { int is_valid; stun_tid tid; - turn_time_t expiration_time; - ioa_timer_handle lifetime_ev; turn_permission_hashtable addr_to_perm; - ts_ur_session relay_session; + relay_endpoint_session relay_session; ch_map chns; /* chnum-to-ch_info* */ void *owner; //ss ur_map *tcp_connections; //global (per turn server) reference @@ -213,7 +201,7 @@ ch_info* allocation_get_new_ch_info(allocation* a, u16bits chnum, ioa_addr* peer ch_info* allocation_get_ch_info(allocation* a, u16bits chnum); ch_info* allocation_get_ch_info_by_peer_addr(allocation* a, ioa_addr* peer_addr); -ts_ur_session *get_relay_session(allocation *a); +relay_endpoint_session *get_relay_session(allocation *a); ioa_socket_handle get_relay_socket(allocation *a); tcp_connection *get_and_clean_tcp_connection_by_id(ur_map *map, tcp_connection_id id); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 0367535f..b6539d51 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -103,7 +103,7 @@ static int write_client_connection(turn_turnserver *server, ts_ur_super_session* static void tcp_peer_accept_connection(ioa_socket_handle s, void *arg); -static int read_client_connection(turn_turnserver *server, ts_ur_session *elem, +static int read_client_connection(turn_turnserver *server, ts_ur_super_session *ss, ioa_net_data *in_buffer, int can_resume, int count_usage); @@ -210,8 +210,8 @@ static int is_rfc5780(turn_turnserver *server) static int get_other_address(turn_turnserver *server, ts_ur_super_session *ss, ioa_addr *alt_addr) { - if(is_rfc5780(server) && ss && ss->client_session.s) { - int ret = server->alt_addr_cb(get_local_addr_from_ioa_socket(ss->client_session.s), alt_addr); + if(is_rfc5780(server) && ss && ss->client_socket) { + int ret = server->alt_addr_cb(get_local_addr_from_ioa_socket(ss->client_socket), alt_addr); return ret; } @@ -308,7 +308,7 @@ allocation* get_allocation_ss(ts_ur_super_session *ss) { return &(ss->alloc); } -static inline ts_ur_session *get_relay_session_ss(ts_ur_super_session *ss) +static inline relay_endpoint_session *get_relay_session_ss(ts_ur_super_session *ss) { return &(ss->alloc.relay_session); } @@ -401,12 +401,12 @@ int turn_session_info_copy_from(struct turn_session_info* tsi, ts_ur_super_sessi tsi->start_time = ss->start_time; tsi->valid = is_allocation_valid(&(ss->alloc)) && !(ss->to_be_closed) && (ss->quota_used); if(tsi->valid) { - tsi->expiration_time = ss->alloc.expiration_time; - if(ss->client_session.s) { - tsi->client_protocol = get_ioa_socket_type(ss->client_session.s); - addr_cpy(&(tsi->local_addr_data.addr),get_local_addr_from_ioa_socket(ss->client_session.s)); + tsi->expiration_time = ss->alloc.relay_session.expiration_time; + if(ss->client_socket) { + tsi->client_protocol = get_ioa_socket_type(ss->client_socket); + addr_cpy(&(tsi->local_addr_data.addr),get_local_addr_from_ioa_socket(ss->client_socket)); addr_to_string(&(tsi->local_addr_data.addr),(u08bits*)tsi->local_addr_data.saddr); - addr_cpy(&(tsi->remote_addr_data.addr),get_remote_addr_from_ioa_socket(ss->client_session.s)); + addr_cpy(&(tsi->remote_addr_data.addr),get_remote_addr_from_ioa_socket(ss->client_socket)); addr_to_string(&(tsi->remote_addr_data.addr),(u08bits*)tsi->remote_addr_data.saddr); } if(ss->alloc.relay_session.s) { @@ -418,8 +418,8 @@ int turn_session_info_copy_from(struct turn_session_info* tsi, ts_ur_super_sessi } STRCPY(tsi->username,ss->username); tsi->enforce_fingerprints = ss->enforce_fingerprints; - STRCPY(tsi->tls_method, get_ioa_socket_tls_method(ss->client_session.s)); - STRCPY(tsi->tls_cipher, get_ioa_socket_tls_cipher(ss->client_session.s)); + STRCPY(tsi->tls_method, get_ioa_socket_tls_method(ss->client_socket)); + STRCPY(tsi->tls_cipher, get_ioa_socket_tls_cipher(ss->client_socket)); STRCPY(tsi->realm, ss->realm_options.name); STRCPY(tsi->origin, ss->origin); @@ -712,7 +712,7 @@ static void delete_ur_map_ss(void *p) { if (p) { ts_ur_super_session* ss = (ts_ur_super_session*) p; delete_session_from_map(ss); - clear_ts_ur_session_data(&(ss->client_session)); + IOA_CLOSE_SOCKET(ss->client_socket); clear_allocation(get_allocation_ss(ss)); IOA_EVENT_DEL(ss->to_be_allocated_timeout_ev); turn_free(p,sizeof(ts_ur_super_session)); @@ -726,8 +726,8 @@ static int turn_server_remove_all_from_ur_map_ss(ts_ur_super_session* ss) { return 0; else { int ret = 0; - if (ss->client_session.s) { - clear_ioa_socket_session_if(ss->client_session.s, ss); + if (ss->client_socket) { + clear_ioa_socket_session_if(ss->client_socket, ss); } if (get_relay_socket_ss(ss)) { clear_ioa_socket_session_if(get_relay_socket_ss(ss), ss); @@ -856,8 +856,6 @@ static int handle_turn_allocate(turn_turnserver *server, allocation* a = get_allocation_ss(ss); - ts_ur_session* elem = &(ss->client_session); - if (is_allocation_valid(a)) { if (!stun_tid_equals(tid, &(a->tid))) { @@ -877,8 +875,8 @@ static int handle_turn_allocate(turn_turnserver *server, stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid, &xor_relayed_addr, - get_remote_addr_from_ioa_socket(elem->s), - (a->expiration_time - server->ctime), 0, NULL, 0, + get_remote_addr_from_ioa_socket(ss->client_socket), + (a->relay_session.expiration_time - server->ctime), 0, NULL, 0, ss->s_mobile_id); ioa_network_buffer_set_size(nbh,len); *resp_constructed = 1; @@ -957,8 +955,8 @@ static int handle_turn_allocate(turn_turnserver *server, } else if((transport == STUN_ATTRIBUTE_TRANSPORT_UDP_VALUE) && *(server->no_udp_relay)) { *err_code = 403; *reason = (const u08bits *)"UDP Transport is not allowed by the TURN Server configuration"; - } else if(ss->client_session.s) { - SOCKET_TYPE cst = get_ioa_socket_type(ss->client_session.s); + } else if(ss->client_socket) { + SOCKET_TYPE cst = get_ioa_socket_type(ss->client_socket); if((transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) && (cst!=TCP_SOCKET) && (cst!=TLS_SOCKET)) { *err_code = 400; @@ -1149,7 +1147,7 @@ static int handle_turn_allocate(turn_turnserver *server, stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid, &xor_relayed_addr, - get_remote_addr_from_ioa_socket(elem->s), lifetime, + get_remote_addr_from_ioa_socket(ss->client_socket), lifetime, 0,NULL, out_reservation_token, ss->s_mobile_id); @@ -1301,7 +1299,7 @@ static int handle_turn_refresh(turn_turnserver *server, if(tsid != server->id) { if(server->send_socket_to_relay) { - ioa_socket_handle new_s = detach_ioa_socket(ss->client_session.s,1); + ioa_socket_handle new_s = detach_ioa_socket(ss->client_socket,1); if(new_s) { if(server->send_socket_to_relay(tsid, mid, tid, new_s, message_integrity, RMT_MOBILE_SOCKET, in_buffer, can_resume)<0) { @@ -1334,10 +1332,10 @@ static int handle_turn_refresh(turn_turnserver *server, } else if(!(orig_ss->is_mobile)) { *err_code = 500; *reason = (const u08bits *)"Software error: invalid mobile allocation"; - } else if(orig_ss->client_session.s == ss->client_session.s) { + } else if(orig_ss->client_socket == ss->client_socket) { *err_code = 500; *reason = (const u08bits *)"Software error: invalid mobile client socket (orig)"; - } else if(!(ss->client_session.s)) { + } else if(!(ss->client_socket)) { *err_code = 500; *reason = (const u08bits *)"Software error: invalid mobile client socket (new)"; } else { @@ -1379,7 +1377,7 @@ static int handle_turn_refresh(turn_turnserver *server, //Transfer socket: - ioa_socket_handle s = detach_ioa_socket(ss->client_session.s,0); + ioa_socket_handle s = detach_ioa_socket(ss->client_socket,0); ss->to_be_closed = 1; @@ -1965,7 +1963,7 @@ static int handle_turn_connection_bind(turn_turnserver *server, *err_code = 400; *reason = (const u08bits *)"Bad request: CONNECTION_BIND cannot be issued after allocation"; - } else if((get_ioa_socket_type(ss->client_session.s)!=TCP_SOCKET) && (get_ioa_socket_type(ss->client_session.s)!=TLS_SOCKET)) { + } else if((get_ioa_socket_type(ss->client_socket)!=TCP_SOCKET) && (get_ioa_socket_type(ss->client_socket)!=TLS_SOCKET)) { *err_code = 400; *reason = (const u08bits *)"Bad request: CONNECTION_BIND only possible with TCP/TLS"; @@ -2014,7 +2012,7 @@ static int handle_turn_connection_bind(turn_turnserver *server, } else { if(server->send_socket_to_relay) { turnserver_id sid = (id & 0xFF000000)>>24; - ioa_socket_handle s = ss->client_session.s; + ioa_socket_handle s = ss->client_socket; if(s) { ioa_socket_handle new_s = detach_ioa_socket(s,1); if(new_s) { @@ -2035,7 +2033,7 @@ static int handle_turn_connection_bind(turn_turnserver *server, } } - if (!(*resp_constructed) && ss->client_session.s && !ioa_socket_tobeclosed(ss->client_session.s)) { + if (!(*resp_constructed) && ss->client_socket && !ioa_socket_tobeclosed(ss->client_socket)) { if (!(*err_code)) { *err_code = 437; @@ -2326,15 +2324,15 @@ static int handle_turn_channel_bind(turn_turnserver *server, *resp_constructed = 1; if(!(ss->is_mobile)) { - if(get_ioa_socket_type(ss->client_session.s) == UDP_SOCKET || - get_ioa_socket_type(ss->client_session.s) == TCP_SOCKET) { + if(get_ioa_socket_type(ss->client_socket) == UDP_SOCKET || + get_ioa_socket_type(ss->client_socket) == TCP_SOCKET) { if(get_ioa_socket_type(ss->alloc.relay_session.s) == UDP_SOCKET) { chn->kernel_channel = CREATE_TURN_CHANNEL_KERNEL(chn->chnum, - get_ioa_socket_address_family(ss->client_session.s), + get_ioa_socket_address_family(ss->client_socket), get_ioa_socket_address_family(ss->alloc.relay_session.s), - (get_ioa_socket_type(ss->client_session.s)==UDP_SOCKET ? IPPROTO_UDP : IPPROTO_TCP), - &(get_remote_addr_from_ioa_socket(ss->client_session.s)->ss), - &(get_local_addr_from_ioa_socket(ss->client_session.s)->ss), + (get_ioa_socket_type(ss->client_socket)==UDP_SOCKET ? IPPROTO_UDP : IPPROTO_TCP), + &(get_remote_addr_from_ioa_socket(ss->client_socket)->ss), + &(get_local_addr_from_ioa_socket(ss->client_socket)->ss), &(get_local_addr_from_ioa_socket(ss->alloc.relay_session.s)), &(get_remote_addr_from_ioa_socket(ss->alloc.relay_session.s)) ); @@ -2359,16 +2357,15 @@ static int handle_turn_binding(turn_turnserver *server, u32bits cookie, int old_stun) { FUNCSTART; - ts_ur_session* elem = &(ss->client_session); int change_ip = 0; int change_port = 0; int padding = 0; int response_port_present = 0; u16bits response_port = 0; - SOCKET_TYPE st = get_ioa_socket_type(ss->client_session.s); + SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket); int use_reflected_from = 0; - if(!(ss->client_session.s)) + if(!(ss->client_socket)) return -1; *origin_changed = 0; @@ -2466,20 +2463,20 @@ static int handle_turn_binding(turn_turnserver *server, ; - } else if(ss->client_session.s) { + } else if(ss->client_socket) { size_t len = ioa_network_buffer_get_size(nbh); if (stun_set_binding_response_str(ioa_network_buffer_data(nbh), &len, tid, - get_remote_addr_from_ioa_socket(elem->s), 0, NULL, cookie, old_stun) >= 0) { + get_remote_addr_from_ioa_socket(ss->client_socket), 0, NULL, cookie, old_stun) >= 0) { - addr_cpy(response_origin, get_local_addr_from_ioa_socket(ss->client_session.s)); + addr_cpy(response_origin, get_local_addr_from_ioa_socket(ss->client_socket)); *resp_constructed = 1; if(old_stun && use_reflected_from) { stun_attr_add_addr_str(ioa_network_buffer_data(nbh), &len, OLD_STUN_ATTRIBUTE_REFLECTED_FROM, - get_remote_addr_from_ioa_socket(ss->client_session.s)); + get_remote_addr_from_ioa_socket(ss->client_socket)); } if(!is_rfc5780(server)) { @@ -2494,13 +2491,13 @@ static int handle_turn_binding(turn_turnserver *server, STUN_ATTRIBUTE_RESPONSE_ORIGIN, response_origin); } - } else if(ss->client_session.s) { + } else if(ss->client_socket) { ioa_addr other_address; if(get_other_address(server,ss,&other_address) == 0) { - addr_cpy(response_destination, get_remote_addr_from_ioa_socket(ss->client_session.s)); + addr_cpy(response_destination, get_remote_addr_from_ioa_socket(ss->client_socket)); if(change_ip) { *origin_changed = 1; @@ -2534,7 +2531,7 @@ static int handle_turn_binding(turn_turnserver *server, } if(padding) { - int mtu = get_local_mtu_ioa_socket(ss->client_session.s); + int mtu = get_local_mtu_ioa_socket(ss->client_socket); if(mtu<68) mtu=1500; @@ -2856,9 +2853,8 @@ static void resume_processing_after_username_check(int success, hmackey_t hmack if(server && in_buffer && in_buffer->nbh) { ts_ur_super_session *ss = get_session_from_map(server,(turnsession_id)ctxkey); - if(ss && ss->client_session.s) { + if(ss && ss->client_socket) { turn_turnserver *server = (turn_turnserver *)ss->server; - ts_ur_session *elem = &(ss->client_session); if(success) { ns_bcopy(hmackey,ss->hmackey,sizeof(hmackey_t)); @@ -2866,9 +2862,9 @@ static void resume_processing_after_username_check(int success, hmackey_t hmack ns_bcopy(pwd,ss->pwd,sizeof(st_password_t)); } - read_client_connection(server,elem,ss,in_buffer,0,0); + read_client_connection(server,ss,in_buffer,0,0); - close_ioa_socket_after_processing_if_necessary(ss->client_session.s); + close_ioa_socket_after_processing_if_necessary(ss->client_socket); ioa_network_buffer_delete(server->e, in_buffer->nbh); in_buffer->nbh=NULL; @@ -3018,7 +3014,7 @@ static int check_stun_auth(turn_turnserver *server, } } else { STRCPY(ss->username,usname); - set_username_hash(ss->client_session.s,ss->username,(u08bits*)ss->realm_options.name); + set_username_hash(ss->client_socket,ss->username,(u08bits*)ss->realm_options.name); } if(server->ct != TURN_CREDENTIALS_SHORT_TERM) { @@ -3173,7 +3169,7 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, int no_response = 0; int message_integrity = 0; - if(!(ss->client_session.s)) + if(!(ss->client_socket)) return -1; u16bits unknown_attrs[MAX_NUMBER_OF_UNKNOWN_ATTRS]; @@ -3212,7 +3208,7 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, if(method == STUN_METHOD_ALLOCATE) { - SOCKET_TYPE cst = get_ioa_socket_type(ss->client_session.s); + SOCKET_TYPE cst = get_ioa_socket_type(ss->client_socket); turn_server_addrs_list_t *asl = server->alternate_servers_list; if(((cst == UDP_SOCKET)||(cst == DTLS_SOCKET)) && server->self_udp_balance && @@ -3225,7 +3221,7 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, if(asl && asl->size) { turn_mutex_lock(&(asl->m)); - set_alternate_server(asl,get_local_addr_from_ioa_socket(ss->client_session.s),&(server->as_counter),method,&tid,resp_constructed,&err_code,&reason,nbh); + set_alternate_server(asl,get_local_addr_from_ioa_socket(ss->client_socket),&(server->as_counter),method,&tid,resp_constructed,&err_code,&reason,nbh); turn_mutex_unlock(&(asl->m)); } } @@ -3447,7 +3443,7 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, } } - if(ss->to_be_closed || !(ss->client_session.s) || ioa_socket_tobeclosed(ss->client_session.s)) + if(ss->to_be_closed || !(ss->client_socket) || ioa_socket_tobeclosed(ss->client_socket)) return 0; if (ua_num > 0) { @@ -3683,24 +3679,22 @@ int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, if (!ss) return -1; - ts_ur_session* elem = &(ss->client_session); - report_turn_session_info(server,ss,1); dec_quota(ss); if(!force && ss->is_mobile) { - if (elem->s && server->verbose) { + if (ss->client_socket && server->verbose) { char sraddr[129]="\0"; char sladdr[129]="\0"; - addr_to_string(get_remote_addr_from_ioa_socket(elem->s),(u08bits*)sraddr); - addr_to_string(get_local_addr_from_ioa_socket(elem->s),(u08bits*)sladdr); + addr_to_string(get_remote_addr_from_ioa_socket(ss->client_socket),(u08bits*)sraddr); + addr_to_string(get_local_addr_from_ioa_socket(ss->client_socket),(u08bits*)sladdr); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: closed (1st stage), user <%s> realm <%s> origin <%s>, local %s, remote %s, reason: %s\n",(unsigned long long)(ss->id),(char*)ss->username,(char*)ss->realm_options.name,(char*)ss->origin, sladdr,sraddr,reason); } - IOA_CLOSE_SOCKET(elem->s); + IOA_CLOSE_SOCKET(ss->client_socket); FUNCEND; @@ -3709,30 +3703,12 @@ int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, if (eve(server->verbose)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, - "closing session 0x%lx, client socket 0x%lx in state %ld (socket session=0x%lx)\n", + "closing session 0x%lx, client socket 0x%lx (socket session=0x%lx)\n", (long) ss, - (long) elem->s, - (long) (elem->state), - (long)get_ioa_socket_session(elem->s)); + (long) ss->client_socket, + (long)get_ioa_socket_session(ss->client_socket)); } - if (elem->state == UR_STATE_DONE) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, - "!!! closing session 0x%lx, client session 0x%lx in DONE state\n", - (long)ss, (long) elem); - return -1; - } - - elem->state = UR_STATE_DONE; - - if (ss->alloc.relay_session.state == UR_STATE_DONE) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, - "!!! closing session 0x%lx, relay session 0x%lx in DONE state\n", - (long)ss, (long)&(ss->alloc.relay_session)); - return -1; - } - ss->alloc.relay_session.state = UR_STATE_DONE; - if (server->disconnect) server->disconnect(ss); @@ -3740,14 +3716,14 @@ int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, char sraddr[129]="\0"; char sladdr[129]="\0"; - addr_to_string(get_remote_addr_from_ioa_socket(elem->s),(u08bits*)sraddr); - addr_to_string(get_local_addr_from_ioa_socket(elem->s),(u08bits*)sladdr); + addr_to_string(get_remote_addr_from_ioa_socket(ss->client_socket),(u08bits*)sraddr); + addr_to_string(get_local_addr_from_ioa_socket(ss->client_socket),(u08bits*)sladdr); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: closed (2nd stage), user <%s> realm <%s> origin <%s>, local %s, remote %s, reason: %s\n", (unsigned long long)(ss->id), (char*)ss->username,(char*)ss->realm_options.name,(char*)ss->origin, sladdr,sraddr, reason); } - IOA_CLOSE_SOCKET(elem->s); + IOA_CLOSE_SOCKET(ss->client_socket); IOA_CLOSE_SOCKET(ss->alloc.relay_session.s); turn_server_remove_all_from_ur_map_ss(ss); @@ -3776,18 +3752,18 @@ static void client_to_be_allocated_timeout_handler(ioa_engine_handle e, int to_close = 0; - ioa_socket_handle s = ss->client_session.s; + ioa_socket_handle s = ss->client_socket; if(!s || ioa_socket_tobeclosed(s)) { to_close = 1; } else { ioa_socket_handle rs = ss->alloc.relay_session.s; if(!rs || ioa_socket_tobeclosed(rs)) { to_close = 1; - } else if(ss->alloc.relay_session.state == UR_STATE_DONE) { + } else if(ss->alloc.relay_session.s == NULL) { to_close = 1; - } else if(ss->client_session.state == UR_STATE_DONE) { + } else if(ss->client_socket == NULL) { to_close = 1; - } else if(!(ss->alloc.lifetime_ev)) { + } else if(!(ss->alloc.relay_session.lifetime_ev)) { to_close = 1; } else if(!(ss->to_be_allocated_timeout_ev)) { to_close = 1; @@ -3806,9 +3782,7 @@ static int write_client_connection(turn_turnserver *server, ts_ur_super_session* FUNCSTART; - ts_ur_session* elem = &(ss->client_session); - - if (elem->state != UR_STATE_READY) { + if (!(ss->client_socket)) { ioa_network_buffer_delete(server->e, nbh); FUNCEND; return -1; @@ -3821,10 +3795,10 @@ static int write_client_connection(turn_turnserver *server, ts_ur_super_session* if (eve(server->verbose)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: prepare to write to s 0x%lx\n", __FUNCTION__, - (long) (elem->s)); + (long) (ss->client_socket)); } - int ret = send_data_from_ioa_socket_nbh(elem->s, NULL, nbh, ttl, tos); + int ret = send_data_from_ioa_socket_nbh(ss->client_socket, NULL, nbh, ttl, tos); FUNCEND; return ret; @@ -3866,14 +3840,14 @@ static int create_relay_connection(turn_turnserver* server, int *err_code, const u08bits **reason, accept_cb acb) { - if (server && ss && ss->client_session.s) { + if (server && ss && ss->client_socket) { allocation* a = get_allocation_ss(ss); - ts_ur_session* newelem = get_relay_session_ss(ss); + relay_endpoint_session* newelem = get_relay_session_ss(ss); IOA_CLOSE_SOCKET(newelem->s); - ns_bzero(newelem, sizeof(ts_ur_session)); + ns_bzero(newelem, sizeof(relay_endpoint_session)); newelem->s = NULL; ioa_socket_handle rtcp_s = NULL; @@ -3900,7 +3874,7 @@ static int create_relay_connection(turn_turnserver* server, } else { int res = create_relay_ioa_sockets(server->e, - ss->client_session.s, + ss->client_socket, address_family, transport, even_port, &(newelem->s), &rtcp_s, out_reservation_token, err_code, reason, acb, ss); @@ -3937,11 +3911,9 @@ static int create_relay_connection(turn_turnserver* server, } } - newelem->state = UR_STATE_READY; - /* RFC6156: do not use DF when IPv6 is involved: */ if((get_local_addr_from_ioa_socket(newelem->s)->ss.sa_family == AF_INET6) || - (get_local_addr_from_ioa_socket(ss->client_session.s)->ss.sa_family == AF_INET6)) + (get_local_addr_from_ioa_socket(ss->client_socket)->ss.sa_family == AF_INET6)) set_do_not_use_df(newelem->s); if(get_ioa_socket_type(newelem->s) != TCP_SOCKET) { @@ -3999,7 +3971,7 @@ static int refresh_relay_connection(turn_turnserver* server, static void write_http_echo(turn_turnserver *server, ts_ur_super_session *ss) { - if(server && ss && ss->client_session.s && !(ss->to_be_closed)) { + if(server && ss && ss->client_socket && !(ss->to_be_closed)) { ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(server->e); size_t len_http = ioa_network_buffer_get_size(nbh_http); u08bits *data = ioa_network_buffer_data(nbh_http); @@ -4011,22 +3983,17 @@ static void write_http_echo(turn_turnserver *server, ts_ur_super_session *ss) len_http = strlen(data_http); ns_bcopy(data_http,data,len_http); ioa_network_buffer_set_size(nbh_http,len_http); - send_data_from_ioa_socket_nbh(ss->client_session.s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE); + send_data_from_ioa_socket_nbh(ss->client_socket, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE); } } -static int read_client_connection(turn_turnserver *server, ts_ur_session *elem, +static int read_client_connection(turn_turnserver *server, ts_ur_super_session *ss, ioa_net_data *in_buffer, int can_resume, int count_usage) { FUNCSTART; - if (!server || !elem || !ss || !in_buffer) { - FUNCEND; - return -1; - } - - if (elem->state != UR_STATE_READY) { + if (!server || !ss || !in_buffer || !(ss->client_socket)) { FUNCEND; return -1; } @@ -4055,7 +4022,7 @@ static int read_client_connection(turn_turnserver *server, ts_ur_session *elem, size_t blen = ioa_network_buffer_get_size(in_buffer->nbh); size_t orig_blen = blen; - SOCKET_TYPE st = get_ioa_socket_type(ss->client_session.s); + SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket); int is_padding_mandatory = ((st == TCP_SOCKET)||(st==TLS_SOCKET)||(st==TENTATIVE_TCP_SOCKET)); if (stun_is_channel_message_str(ioa_network_buffer_data(in_buffer->nbh), @@ -4097,7 +4064,7 @@ static int read_client_connection(turn_turnserver *server, ts_ur_session *elem, if((method != STUN_METHOD_BINDING) && (method != STUN_METHOD_SEND)) report_turn_session_info(server,ss,0); - if(ss->to_be_closed || ioa_socket_tobeclosed(ss->client_session.s)) { + if(ss->to_be_closed || ioa_socket_tobeclosed(ss->client_socket)) { FUNCEND; ioa_network_buffer_delete(server->e, nbh); return 0; @@ -4143,7 +4110,7 @@ static int read_client_connection(turn_turnserver *server, ts_ur_session *elem, } } else { - SOCKET_TYPE st = get_ioa_socket_type(ss->client_session.s); + 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))) write_http_echo(server,ss); @@ -4163,22 +4130,16 @@ static int attach_socket_to_session(turn_turnserver* server, ioa_socket_handle s if(s && server && ss) { - if(ss->client_session.s != s) { + if(ss->client_socket != s) { - ts_ur_session *newelem = &(ss->client_session); + IOA_CLOSE_SOCKET(ss->client_socket); - if(newelem->s) { - IOA_CLOSE_SOCKET(newelem->s); - } + ss->client_socket = s; - newelem->s = s; - - register_callback_on_ioa_socket(server->e, newelem->s, IOA_EV_READ, + register_callback_on_ioa_socket(server->e, s, IOA_EV_READ, client_input_handler, ss, 0); - set_ioa_socket_session(newelem->s, ss); - - newelem->state = UR_STATE_READY; + set_ioa_socket_session(s, ss); } ret = 0; @@ -4200,16 +4161,12 @@ int open_client_connection_session(turn_turnserver* server, ts_ur_super_session* ss = create_new_ss(server); - ts_ur_session *newelem = &(ss->client_session); + ss->client_socket = sm->s; - newelem->s = sm->s; - - register_callback_on_ioa_socket(server->e, newelem->s, IOA_EV_READ, + register_callback_on_ioa_socket(server->e, ss->client_socket, IOA_EV_READ, client_input_handler, ss, 0); - set_ioa_socket_session(newelem->s, ss); - - newelem->state = UR_STATE_READY; + set_ioa_socket_session(ss->client_socket, ss); int at = TURN_MAX_ALLOCATE_TIMEOUT; if(*(server->stun_only)) @@ -4222,7 +4179,7 @@ int open_client_connection_session(turn_turnserver* server, "client_to_be_allocated_timeout_handler"); if(sm->nd.nbh) { - client_input_handler(newelem->s,IOA_EV_READ,&(sm->nd),ss,sm->can_resume); + client_input_handler(ss->client_socket,IOA_EV_READ,&(sm->nd),ss,sm->can_resume); ioa_network_buffer_delete(server->e, sm->nd.nbh); sm->nd.nbh = NULL; } @@ -4256,7 +4213,7 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, return; } - ts_ur_session* elem = get_relay_session_ss(ss); + relay_endpoint_session* elem = get_relay_session_ss(ss); if (elem->s == NULL) { return; } @@ -4295,7 +4252,7 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, ioa_network_buffer_header_init(nbh); - SOCKET_TYPE st = get_ioa_socket_type(ss->client_session.s); + SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket); int do_padding = ((st == TCP_SOCKET)||(st==TLS_SOCKET)||(st==TENTATIVE_TCP_SOCKET)); stun_init_channel_message_str(chnum, ioa_network_buffer_data(nbh), &len, len, do_padding); @@ -4365,34 +4322,13 @@ static void client_input_handler(ioa_socket_handle s, int event_type, return; } - ts_ur_session* elem = &(ss->client_session); - - if (elem->s == NULL) { + if (ss->client_socket != s) { return; } - int ret = 0; + read_client_connection(server, ss, data, can_resume, 1); - switch (elem->state) { - case UR_STATE_READY: - read_client_connection(server, elem, ss, data, can_resume, 1); - break; - case UR_STATE_DONE: - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, - "!!! %s: Trying to read from closed socket: s=0x%lx\n", - __FUNCTION__, (long) (elem->s)); - break; - default: - ret = -1; - } - - if (ret < 0) { - if(server->verbose) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, - "session %018llu: client socket error in client handler: s=0x%lx\n", (unsigned long long)(ss->id), (long) (elem->s)); - } - set_ioa_socket_tobeclosed(s); - } else if (ss->to_be_closed) { + if (ss->to_be_closed) { if(server->verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: client socket to be closed in client handler: ss=0x%lx\n", (unsigned long long)(ss->id), (long)ss); diff --git a/src/server/ns_turn_session.h b/src/server/ns_turn_session.h index db247898..b8986389 100644 --- a/src/server/ns_turn_session.h +++ b/src/server/ns_turn_session.h @@ -69,7 +69,7 @@ struct _ts_ur_super_session { void* server; turnsession_id id; turn_time_t start_time; - ts_ur_session client_session; + ioa_socket_handle client_socket; allocation alloc; ioa_timer_handle to_be_allocated_timeout_ev; u08bits nonce[NONCE_MAX_SIZE]; From b44795b02157a0f08aef8aac3dec7756040d7f91 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 8 Jul 2014 07:45:05 +0000 Subject: [PATCH 087/805] working on double allocations --- src/apps/relay/ns_ioalib_engine_impl.c | 6 +- src/server/ns_turn_allocation.c | 28 +++-- src/server/ns_turn_allocation.h | 14 ++- src/server/ns_turn_server.c | 161 ++++++++++++++++--------- 4 files changed, 137 insertions(+), 72 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 065ba659..8e71ad36 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -2763,8 +2763,10 @@ static void eventcb_bev(struct bufferevent *bev, short events, void *arg) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: TCP socket closed remotely %s\n",(unsigned long long)(ss->id),sraddr); if(s == ss->client_socket) { shutdown_client_connection(server, ss, 0, "TCP connection closed by client (callback)"); - } else if(s == ss->alloc.relay_session.s) { - shutdown_client_connection(server, ss, 0, "TCP connection closed by peer (callback)"); + } else if(s == ss->alloc.relay_sessions[ALLOC_IPV4_INDEX].s) { + shutdown_client_connection(server, ss, 0, "TCP connection closed by peer (ipv4 callback)"); + } else if(s == ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].s) { + shutdown_client_connection(server, ss, 0, "TCP connection closed by peer (ipv6 callback)"); } else { shutdown_client_connection(server, ss, 0, "TCP connection closed by remote party (callback)"); } diff --git a/src/server/ns_turn_allocation.c b/src/server/ns_turn_allocation.c index dff6c5c4..b39e6bad 100644 --- a/src/server/ns_turn_allocation.c +++ b/src/server/ns_turn_allocation.c @@ -70,10 +70,14 @@ void clear_allocation(allocation *a) } a->tcs.sz = 0; - clear_ioa_socket_session_if(a->relay_session.s, a->owner); - clear_relay_endpoint_session_data(&(a->relay_session)); - - IOA_EVENT_DEL(a->relay_session.lifetime_ev); + { + int i; + for(i = 0;irelay_sessions[i].s, a->owner); + clear_relay_endpoint_session_data(&(a->relay_sessions[i])); + IOA_EVENT_DEL(a->relay_sessions[i].lifetime_ev); + } + } /* The order is important here: */ free_turn_permission_hashtable(&(a->addr_to_perm)); @@ -83,22 +87,22 @@ void clear_allocation(allocation *a) } } -relay_endpoint_session *get_relay_session(allocation *a) +relay_endpoint_session *get_relay_session(allocation *a, int family) { - return &(a->relay_session); + return &(a->relay_sessions[ALLOC_INDEX(family)]); } -ioa_socket_handle get_relay_socket(allocation *a) +ioa_socket_handle get_relay_socket(allocation *a, int family) { - return a->relay_session.s; + return a->relay_sessions[ALLOC_INDEX(family)].s; } -void set_allocation_lifetime_ev(allocation *a, turn_time_t exp_time, ioa_timer_handle ev) +void set_allocation_lifetime_ev(allocation *a, turn_time_t exp_time, ioa_timer_handle ev, int family) { if (a) { - IOA_EVENT_DEL(a->relay_session.lifetime_ev); - a->relay_session.expiration_time = exp_time; - a->relay_session.lifetime_ev = ev; + IOA_EVENT_DEL(a->relay_sessions[ALLOC_INDEX(family)].lifetime_ev); + a->relay_sessions[ALLOC_INDEX(family)].expiration_time = exp_time; + a->relay_sessions[ALLOC_INDEX(family)].lifetime_ev = ev; } } diff --git a/src/server/ns_turn_allocation.h b/src/server/ns_turn_allocation.h index c99440de..40b068a4 100644 --- a/src/server/ns_turn_allocation.h +++ b/src/server/ns_turn_allocation.h @@ -165,11 +165,17 @@ typedef struct _turn_permission_hashtable { //////////////// ALLOCATION ////////////////////// +#define ALLOC_IPV4_INDEX (0) +#define ALLOC_IPV6_INDEX (1) +#define ALLOC_PROTOCOLS_NUMBER (2) +#define ALLOC_INDEX(family) ((((family)==AF_INET6)) ? ALLOC_IPV6_INDEX : ALLOC_IPV4_INDEX ) +#define ALLOC_INDEX_ADDR(addr) ALLOC_INDEX(((addr)->ss).sa_family) + typedef struct _allocation { int is_valid; stun_tid tid; turn_permission_hashtable addr_to_perm; - relay_endpoint_session relay_session; + relay_endpoint_session relay_sessions[ALLOC_PROTOCOLS_NUMBER]; ch_map chns; /* chnum-to-ch_info* */ void *owner; //ss ur_map *tcp_connections; //global (per turn server) reference @@ -190,7 +196,7 @@ void clear_allocation(allocation *a); void turn_permission_clean(turn_permission_info* tinfo); -void set_allocation_lifetime_ev(allocation *a, turn_time_t exp_time, ioa_timer_handle ev); +void set_allocation_lifetime_ev(allocation *a, turn_time_t exp_time, ioa_timer_handle ev, int family); int is_allocation_valid(const allocation* a); void set_allocation_valid(allocation* a, int value); turn_permission_info* allocation_get_permission(allocation* a, const ioa_addr *addr); @@ -201,8 +207,8 @@ ch_info* allocation_get_new_ch_info(allocation* a, u16bits chnum, ioa_addr* peer ch_info* allocation_get_ch_info(allocation* a, u16bits chnum); ch_info* allocation_get_ch_info_by_peer_addr(allocation* a, ioa_addr* peer_addr); -relay_endpoint_session *get_relay_session(allocation *a); -ioa_socket_handle get_relay_socket(allocation *a); +relay_endpoint_session *get_relay_session(allocation *a, int family); +ioa_socket_handle get_relay_socket(allocation *a, int family); tcp_connection *get_and_clean_tcp_connection_by_id(ur_map *map, tcp_connection_id id); tcp_connection *get_tcp_connection_by_id(ur_map *map, tcp_connection_id id); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index b6539d51..e2d6c095 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -42,6 +42,21 @@ //////////////////////////////////////////////// +static inline int get_family(int stun_family) { + switch(stun_family) { + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: + return AF_INET; + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: + return AF_INET6; + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT: + return AF_INET; + default: + return AF_INET; + }; +} + +//////////////////////////////////////////////// + #define MAX_NUMBER_OF_UNKNOWN_ATTRS (128) int TURN_MAX_ALLOCATE_TIMEOUT = 60; @@ -97,7 +112,7 @@ static int create_relay_connection(turn_turnserver* server, static int refresh_relay_connection(turn_turnserver* server, ts_ur_super_session *ss, u32bits lifetime, int even_port, u64bits in_reservation_token, u64bits *out_reservation_token, - int *err_code); + int *err_code, int family); static int write_client_connection(turn_turnserver *server, ts_ur_super_session* ss, ioa_network_buffer_handle nbh, int ttl, int tos); @@ -308,14 +323,14 @@ allocation* get_allocation_ss(ts_ur_super_session *ss) { return &(ss->alloc); } -static inline relay_endpoint_session *get_relay_session_ss(ts_ur_super_session *ss) +static inline relay_endpoint_session *get_relay_session_ss(ts_ur_super_session *ss, int family) { - return &(ss->alloc.relay_session); + return get_relay_session(&(ss->alloc),family); } -static inline ioa_socket_handle get_relay_socket_ss(ts_ur_super_session *ss) +static inline ioa_socket_handle get_relay_socket_ss(ts_ur_super_session *ss, int family) { - return ss->alloc.relay_session.s; + return get_relay_socket(&(ss->alloc),family); } /////////// Session info /////// @@ -401,7 +416,16 @@ int turn_session_info_copy_from(struct turn_session_info* tsi, ts_ur_super_sessi tsi->start_time = ss->start_time; tsi->valid = is_allocation_valid(&(ss->alloc)) && !(ss->to_be_closed) && (ss->quota_used); if(tsi->valid) { - tsi->expiration_time = ss->alloc.relay_session.expiration_time; + if(ss->alloc.relay_sessions[ALLOC_IPV4_INDEX].s) { + tsi->expiration_time = ss->alloc.relay_sessions[ALLOC_IPV4_INDEX].expiration_time; + if(ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].s) { + if(turn_time_before(tsi->expiration_time,ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].expiration_time)) { + tsi->expiration_time = ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].expiration_time; + } + } + } else if(ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].s) { + tsi->expiration_time = ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].expiration_time; + } if(ss->client_socket) { tsi->client_protocol = get_ioa_socket_type(ss->client_socket); addr_cpy(&(tsi->local_addr_data.addr),get_local_addr_from_ioa_socket(ss->client_socket)); @@ -409,11 +433,17 @@ int turn_session_info_copy_from(struct turn_session_info* tsi, ts_ur_super_sessi addr_cpy(&(tsi->remote_addr_data.addr),get_remote_addr_from_ioa_socket(ss->client_socket)); addr_to_string(&(tsi->remote_addr_data.addr),(u08bits*)tsi->remote_addr_data.saddr); } - if(ss->alloc.relay_session.s) { - tsi->peer_protocol = get_ioa_socket_type(ss->alloc.relay_session.s); - if(ss->alloc.is_valid) { - addr_cpy(&(tsi->relay_addr_data.addr),get_local_addr_from_ioa_socket(ss->alloc.relay_session.s)); - addr_to_string(&(tsi->relay_addr_data.addr),(u08bits*)tsi->relay_addr_data.saddr); + { + int i; + for(i=0;ialloc.relay_sessions[i].s) { + tsi->peer_protocol = get_ioa_socket_type(ss->alloc.relay_sessions[i].s); + if(ss->alloc.is_valid) { + addr_cpy(&(tsi->relay_addr_data.addr),get_local_addr_from_ioa_socket(ss->alloc.relay_sessions[i].s)); + addr_to_string(&(tsi->relay_addr_data.addr),(u08bits*)tsi->relay_addr_data.saddr); + } + break; + } } } STRCPY(tsi->username,ss->username); @@ -729,8 +759,11 @@ static int turn_server_remove_all_from_ur_map_ss(ts_ur_super_session* ss) { if (ss->client_socket) { clear_ioa_socket_session_if(ss->client_socket, ss); } - if (get_relay_socket_ss(ss)) { - clear_ioa_socket_session_if(get_relay_socket_ss(ss), ss); + if (get_relay_socket_ss(ss,AF_INET)) { + clear_ioa_socket_session_if(get_relay_socket_ss(ss,AF_INET), ss); + } + if (get_relay_socket_ss(ss,AF_INET6)) { + clear_ioa_socket_session_if(get_relay_socket_ss(ss,AF_INET6), ss); } delete_ur_map_ss(ss); return ret; @@ -864,7 +897,9 @@ static int handle_turn_allocate(turn_turnserver *server, } else { size_t len = ioa_network_buffer_get_size(nbh); ioa_addr xor_relayed_addr; - ioa_addr *relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss)); + ioa_addr *relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET)); + if(!relayed_addr) + relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET6)); if(relayed_addr) { if(server->external_ip_set) { addr_cpy(&xor_relayed_addr, &(server->external_ip)); @@ -876,7 +911,7 @@ static int handle_turn_allocate(turn_turnserver *server, tid, &xor_relayed_addr, get_remote_addr_from_ioa_socket(ss->client_socket), - (a->relay_session.expiration_time - server->ctime), 0, NULL, 0, + (get_relay_session(a,relayed_addr->ss.sa_family)->expiration_time - server->ctime), 0, NULL, 0, ss->s_mobile_id); ioa_network_buffer_set_size(nbh,len); *resp_constructed = 1; @@ -1136,7 +1171,9 @@ static int handle_turn_allocate(turn_turnserver *server, size_t len = ioa_network_buffer_get_size(nbh); ioa_addr xor_relayed_addr; - ioa_addr *relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss)); + ioa_addr *relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET)); + if(!relayed_addr) + relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET6)); if(relayed_addr) { if(server->external_ip_set) { addr_cpy(&xor_relayed_addr, &(server->external_ip)); @@ -1188,6 +1225,16 @@ static int handle_turn_refresh(turn_turnserver *server, int message_integrity, int *no_response, int can_resume) { allocation* a = get_allocation_ss(ss); + int family = AF_INET; + { + int i; + for(i = 0;irelay_sessions[i].s) { + family = get_local_addr_from_ioa_socket(a->relay_sessions[i].s)->ss.sa_family; + break; + } + } + } if (!is_allocation_valid(a) && !(*(server->mobility))) { @@ -1248,17 +1295,16 @@ static int handle_turn_refresh(turn_turnserver *server, break; case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY: { int af_req = stun_get_requested_address_family(sar); - ioa_addr *addr = get_local_addr_from_ioa_socket(a->relay_session.s); - if(addr) { + { int is_err = 0; switch (af_req) { case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: - if(addr->ss.sa_family != AF_INET) { + if(family != AF_INET) { is_err = 1; } break; case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: - if(addr->ss.sa_family != AF_INET6) { + if(family != AF_INET6) { is_err = 1; } break; @@ -1361,7 +1407,7 @@ static int handle_turn_refresh(turn_turnserver *server, lifetime = stun_adjust_allocate_lifetime(lifetime); if (refresh_relay_connection(server, orig_ss, lifetime, 0, 0, 0, - err_code) < 0) { + err_code, family) < 0) { if (!(*err_code)) { *err_code = 437; @@ -1462,7 +1508,7 @@ static int handle_turn_refresh(turn_turnserver *server, lifetime = stun_adjust_allocate_lifetime(lifetime); if (refresh_relay_connection(server, ss, lifetime, 0, 0, 0, - err_code) < 0) { + err_code, family) < 0) { if (!(*err_code)) { *err_code = 437; @@ -1704,7 +1750,14 @@ static int tcp_start_connection_to_peer(turn_turnserver *server, ts_ur_super_ses return -1; } - if(!(a->relay_session.s)) { + if(!peer_addr) { + *err_code = 500; + *reason = (const u08bits *)"Server error: empty peer addr"; + FUNCEND; + return -1; + } + + if(!get_relay_socket(a,peer_addr->ss.sa_family)) { *err_code = 500; *reason = (const u08bits *)"Server error: no relay connection created"; FUNCEND; @@ -1738,7 +1791,8 @@ static int tcp_start_connection_to_peer(turn_turnserver *server, ts_ur_super_ses tcp_peer_conn_timeout_handler, tc, 0, "tcp_peer_conn_timeout_handler"); - ioa_socket_handle tcs = ioa_create_connecting_tcp_relay_socket(a->relay_session.s, peer_addr, tcp_peer_connection_completed_callback, tc); + ioa_socket_handle tcs = ioa_create_connecting_tcp_relay_socket(get_relay_socket(a,peer_addr->ss.sa_family), + peer_addr, tcp_peer_connection_completed_callback, tc); if(!tcs) { delete_tcp_connection(tc); *err_code = 500; @@ -1900,9 +1954,7 @@ static int handle_turn_connect(turn_turnserver *server, *err_code = 400; *reason = (const u08bits *)"Bad Peer Address"; } else { - ioa_addr *relay_addr = get_local_addr_from_ioa_socket(a->relay_session.s); - - if(relay_addr && (relay_addr->ss.sa_family != peer_addr.ss.sa_family)) { + if(!get_relay_socket(a,peer_addr.ss.sa_family)) { *err_code = 443; *reason = (const u08bits *)"Peer Address Family Mismatch"; } @@ -2216,9 +2268,7 @@ static int handle_turn_channel_bind(turn_turnserver *server, sar, &peer_addr, NULL); - ioa_addr *relay_addr = get_local_addr_from_ioa_socket(a->relay_session.s); - - if(relay_addr && relay_addr->ss.sa_family != peer_addr.ss.sa_family) { + if(!get_relay_socket(a,peer_addr.ss.sa_family)) { *err_code = 443; *reason = (const u08bits *)"Peer Address Family Mismatch"; } @@ -2326,15 +2376,15 @@ static int handle_turn_channel_bind(turn_turnserver *server, if(!(ss->is_mobile)) { if(get_ioa_socket_type(ss->client_socket) == UDP_SOCKET || get_ioa_socket_type(ss->client_socket) == TCP_SOCKET) { - if(get_ioa_socket_type(ss->alloc.relay_session.s) == UDP_SOCKET) { + if(get_ioa_socket_type(get_relay_socket(&(ss->alloc),peer_addr.ss.sa_family)) == UDP_SOCKET) { chn->kernel_channel = CREATE_TURN_CHANNEL_KERNEL(chn->chnum, get_ioa_socket_address_family(ss->client_socket), - get_ioa_socket_address_family(ss->alloc.relay_session.s), + peer_addr.ss.sa_family, (get_ioa_socket_type(ss->client_socket)==UDP_SOCKET ? IPPROTO_UDP : IPPROTO_TCP), &(get_remote_addr_from_ioa_socket(ss->client_socket)->ss), &(get_local_addr_from_ioa_socket(ss->client_socket)->ss), - &(get_local_addr_from_ioa_socket(ss->alloc.relay_session.s)), - &(get_remote_addr_from_ioa_socket(ss->alloc.relay_session.s)) + &(get_local_addr_from_ioa_socket(get_relay_socket(&(ss->alloc),peer_addr.ss.sa_family))), + &(get_remote_addr_from_ioa_socket(get_relay_socket(&(ss->alloc),peer_addr.ss.sa_family))) ); } } @@ -2626,7 +2676,7 @@ static int handle_turn_send(turn_turnserver *server, ts_ur_super_session *ss, if (tinfo || (server->server_relay)) { - set_df_on_ioa_socket(get_relay_socket_ss(ss), set_df); + set_df_on_ioa_socket(get_relay_socket_ss(ss,peer_addr.ss.sa_family), set_df); ioa_network_buffer_handle nbh = in_buffer->nbh; if(value && len>0) { @@ -2637,7 +2687,7 @@ static int handle_turn_send(turn_turnserver *server, ts_ur_super_session *ss, ioa_network_buffer_set_size(nbh,len); } ioa_network_buffer_header_init(nbh); - send_data_from_ioa_socket_nbh(get_relay_socket_ss(ss), &peer_addr, nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos); + send_data_from_ioa_socket_nbh(get_relay_socket_ss(ss,peer_addr.ss.sa_family), &peer_addr, nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos); in_buffer->nbh = NULL; } @@ -2716,9 +2766,7 @@ static int handle_turn_create_permission(turn_turnserver *server, sar, &peer_addr, NULL); - ioa_addr *relay_addr = get_local_addr_from_ioa_socket(a->relay_session.s); - - if(relay_addr && (relay_addr->ss.sa_family != peer_addr.ss.sa_family)) { + if(!get_relay_socket(a,peer_addr.ss.sa_family)) { *err_code = 443; *reason = (const u08bits *)"Peer Address Family Mismatch"; } else if(!good_peer_addr(server, &peer_addr)) { @@ -3637,7 +3685,7 @@ static int write_to_peerchannel(ts_ur_super_session* ss, u16bits chnum, ioa_net_ int rc = 0; - if (ss && get_relay_socket_ss(ss) && (in_buffer->recv_ttl!=0)) { + if (ss && (in_buffer->recv_ttl!=0)) { allocation* a = get_allocation_ss(ss); @@ -3649,7 +3697,7 @@ static int write_to_peerchannel(ts_ur_super_session* ss, u16bits chnum, ioa_net_ return -1; /* Channel packets are always sent with DF=0: */ - set_df_on_ioa_socket(get_relay_socket_ss(ss), 0); + set_df_on_ioa_socket(get_relay_socket_ss(ss, chn->peer_addr.ss.sa_family), 0); ioa_network_buffer_handle nbh = in_buffer->nbh; @@ -3657,7 +3705,7 @@ static int write_to_peerchannel(ts_ur_super_session* ss, u16bits chnum, ioa_net_ ioa_network_buffer_header_init(nbh); - rc = send_data_from_ioa_socket_nbh(get_relay_socket_ss(ss), &(chn->peer_addr), nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos); + rc = send_data_from_ioa_socket_nbh(get_relay_socket_ss(ss, chn->peer_addr.ss.sa_family), &(chn->peer_addr), nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos); in_buffer->nbh = NULL; } } @@ -3724,7 +3772,12 @@ int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, } IOA_CLOSE_SOCKET(ss->client_socket); - IOA_CLOSE_SOCKET(ss->alloc.relay_session.s); + { + int i; + for(i=0;ialloc.relay_sessions[i].s); + } + } turn_server_remove_all_from_ur_map_ss(ss); @@ -3756,14 +3809,14 @@ static void client_to_be_allocated_timeout_handler(ioa_engine_handle e, if(!s || ioa_socket_tobeclosed(s)) { to_close = 1; } else { - ioa_socket_handle rs = ss->alloc.relay_session.s; - if(!rs || ioa_socket_tobeclosed(rs)) { - to_close = 1; - } else if(ss->alloc.relay_session.s == NULL) { + ioa_socket_handle rs4 = ss->alloc.relay_sessions[ALLOC_IPV4_INDEX].s; + ioa_socket_handle rs6 = ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].s; + if((!rs4 || ioa_socket_tobeclosed(rs4)) && (!rs6 || ioa_socket_tobeclosed(rs6))) { to_close = 1; } else if(ss->client_socket == NULL) { to_close = 1; - } else if(!(ss->alloc.relay_session.lifetime_ev)) { + } else if(!(ss->alloc.relay_sessions[ALLOC_IPV4_INDEX].lifetime_ev) && + !(ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].lifetime_ev)) { to_close = 1; } else if(!(ss->to_be_allocated_timeout_ev)) { to_close = 1; @@ -3843,7 +3896,7 @@ static int create_relay_connection(turn_turnserver* server, if (server && ss && ss->client_socket) { allocation* a = get_allocation_ss(ss); - relay_endpoint_session* newelem = get_relay_session_ss(ss); + relay_endpoint_session* newelem = get_relay_session_ss(ss,get_family(address_family)); IOA_CLOSE_SOCKET(newelem->s); @@ -3929,7 +3982,7 @@ static int create_relay_connection(turn_turnserver* server, ioa_timer_handle ev = set_ioa_timer(server->e, lifetime, 0, client_ss_allocation_timeout_handler, ss, 0, "client_ss_allocation_timeout_handler"); - set_allocation_lifetime_ev(a, server->ctime + lifetime, ev); + set_allocation_lifetime_ev(a, server->ctime + lifetime, ev, get_local_addr_from_ioa_socket(newelem->s)->ss.sa_family); set_ioa_socket_session(newelem->s, ss); } @@ -3940,7 +3993,7 @@ static int create_relay_connection(turn_turnserver* server, static int refresh_relay_connection(turn_turnserver* server, ts_ur_super_session *ss, u32bits lifetime, int even_port, u64bits in_reservation_token, u64bits *out_reservation_token, - int *err_code) { + int *err_code, int family) { UNUSED_ARG(even_port); UNUSED_ARG(in_reservation_token); @@ -3960,7 +4013,7 @@ static int refresh_relay_connection(turn_turnserver* server, client_ss_allocation_timeout_handler, ss, 0, "refresh_client_ss_allocation_timeout_handler"); - set_allocation_lifetime_ev(a, server->ctime + lifetime, ev); + set_allocation_lifetime_ev(a, server->ctime + lifetime, ev, family); return 0; @@ -4205,7 +4258,7 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, ts_ur_super_session* ss = (ts_ur_super_session*) arg; - if(!ss) return; + if(!ss || !s) return; turn_turnserver *server = (turn_turnserver*) (ss->server); @@ -4213,7 +4266,7 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, return; } - relay_endpoint_session* elem = get_relay_session_ss(ss); + relay_endpoint_session* elem = get_relay_session_ss(ss, get_ioa_socket_address_family(s)); if (elem->s == NULL) { return; } From 62301f57ac37f8387a898d0bcb004a84e3cc928b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 9 Jul 2014 07:12:54 +0000 Subject: [PATCH 088/805] working on double allocations --- src/apps/relay/turncli.c | 14 +++++++--- src/server/ns_turn_server.c | 51 +++++++++++++++++++++++------------- src/server/ns_turn_session.h | 5 ++-- 3 files changed, 46 insertions(+), 24 deletions(-) diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index d04f2a44..e6dd2e9e 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -502,13 +502,19 @@ static int print_session(ur_map_key_type key, ur_map_value_type value, void *arg addr_to_string(&(tsi->local_addr_data.addr),(u08bits*)tsi->local_addr_data.saddr); if(!tsi->remote_addr_data.saddr[0]) addr_to_string(&(tsi->remote_addr_data.addr),(u08bits*)tsi->remote_addr_data.saddr); - if(!tsi->relay_addr_data.saddr[0]) - addr_to_string(&(tsi->relay_addr_data.addr),(u08bits*)tsi->relay_addr_data.saddr); + if(!tsi->relay_addr_data_ipv4.saddr[0]) + addr_to_string(&(tsi->relay_addr_data_ipv4.addr),(u08bits*)tsi->relay_addr_data_ipv4.saddr); + if(!tsi->relay_addr_data_ipv6.saddr[0]) + addr_to_string(&(tsi->relay_addr_data_ipv6.addr),(u08bits*)tsi->relay_addr_data_ipv6.saddr); myprintf(cs," client addr %s, server addr %s\n", tsi->remote_addr_data.saddr, tsi->local_addr_data.saddr); - myprintf(cs," relay addr %s\n", - tsi->relay_addr_data.saddr); + if(tsi->relay_addr_data_ipv4.saddr[0]) { + myprintf(cs," relay addr %s\n", tsi->relay_addr_data_ipv4.saddr); + } + if(tsi->relay_addr_data_ipv6.saddr[0]) { + myprintf(cs," relay addr %s\n", tsi->relay_addr_data_ipv6.saddr); + } } myprintf(cs," fingerprints enforced: %s\n",get_flag(tsi->enforce_fingerprints)); myprintf(cs," mobile: %s\n",get_flag(tsi->is_mobile)); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index e2d6c095..c25d7296 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -434,15 +434,18 @@ int turn_session_info_copy_from(struct turn_session_info* tsi, ts_ur_super_sessi addr_to_string(&(tsi->remote_addr_data.addr),(u08bits*)tsi->remote_addr_data.saddr); } { - int i; - for(i=0;ialloc.relay_sessions[i].s) { - tsi->peer_protocol = get_ioa_socket_type(ss->alloc.relay_sessions[i].s); - if(ss->alloc.is_valid) { - addr_cpy(&(tsi->relay_addr_data.addr),get_local_addr_from_ioa_socket(ss->alloc.relay_sessions[i].s)); - addr_to_string(&(tsi->relay_addr_data.addr),(u08bits*)tsi->relay_addr_data.saddr); - } - break; + if(ss->alloc.relay_sessions[ALLOC_IPV4_INDEX].s) { + tsi->peer_protocol = get_ioa_socket_type(ss->alloc.relay_sessions[ALLOC_IPV4_INDEX].s); + if(ss->alloc.is_valid) { + addr_cpy(&(tsi->relay_addr_data_ipv4.addr),get_local_addr_from_ioa_socket(ss->alloc.relay_sessions[ALLOC_IPV4_INDEX].s)); + addr_to_string(&(tsi->relay_addr_data_ipv4.addr),(u08bits*)tsi->relay_addr_data_ipv4.saddr); + } + } + if(ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].s) { + tsi->peer_protocol = get_ioa_socket_type(ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].s); + if(ss->alloc.is_valid) { + addr_cpy(&(tsi->relay_addr_data_ipv6.addr),get_local_addr_from_ioa_socket(ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].s)); + addr_to_string(&(tsi->relay_addr_data_ipv6.addr),(u08bits*)tsi->relay_addr_data_ipv6.saddr); } } } @@ -3896,25 +3899,30 @@ static int create_relay_connection(turn_turnserver* server, if (server && ss && ss->client_socket) { allocation* a = get_allocation_ss(ss); - relay_endpoint_session* newelem = get_relay_session_ss(ss,get_family(address_family)); - - IOA_CLOSE_SOCKET(newelem->s); - - ns_bzero(newelem, sizeof(relay_endpoint_session)); - newelem->s = NULL; - + relay_endpoint_session* newelem = NULL; ioa_socket_handle rtcp_s = NULL; if (in_reservation_token) { + ioa_socket_handle s = NULL; + if (get_ioa_socket_from_reservation(server->e, in_reservation_token, - &newelem->s) < 0) { - IOA_CLOSE_SOCKET(newelem->s); + &s) < 0) { + IOA_CLOSE_SOCKET(s); *err_code = 508; *reason = (const u08bits *)"Cannot find reserved socket"; return -1; } + int family = get_ioa_socket_address_family(s); + + newelem = get_relay_session_ss(ss,family); + + IOA_CLOSE_SOCKET(newelem->s); + + ns_bzero(newelem, sizeof(relay_endpoint_session)); + newelem->s = s; + if(!check_username_hash(newelem->s,ss->username,(u08bits*)ss->realm_options.name)) { IOA_CLOSE_SOCKET(newelem->s); *err_code = 508; @@ -3926,6 +3934,13 @@ static int create_relay_connection(turn_turnserver* server, } else { + newelem = get_relay_session_ss(ss,get_family(address_family)); + + IOA_CLOSE_SOCKET(newelem->s); + + ns_bzero(newelem, sizeof(relay_endpoint_session)); + newelem->s = NULL; + int res = create_relay_ioa_sockets(server->e, ss->client_socket, address_family, transport, diff --git a/src/server/ns_turn_session.h b/src/server/ns_turn_session.h index b8986389..cfb469ab 100644 --- a/src/server/ns_turn_session.h +++ b/src/server/ns_turn_session.h @@ -127,7 +127,8 @@ struct turn_session_info { char tls_cipher[65]; addr_data local_addr_data; addr_data remote_addr_data; - addr_data relay_addr_data; + addr_data relay_addr_data_ipv4; + addr_data relay_addr_data_ipv6; u08bits username[STUN_MAX_USERNAME_SIZE+1]; int enforce_fingerprints; /* Stats */ @@ -146,7 +147,7 @@ struct turn_session_info { addr_data *extra_peers_data; size_t extra_peers_size; /* Realm */ - char realm[STUN_MAX_REALM_SIZE+1]; + char realm[STUN_MAX_REALM_SIZE + 1]; char origin[STUN_MAX_ORIGIN_SIZE + 1]; /* Bandwidth */ band_limit_t bps; From 48537e96249f50fa38e4977b67655cd57686429d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 11 Jul 2014 06:21:02 +0000 Subject: [PATCH 089/805] allocation mismatch fix merged from rfc5766-turn-server --- ChangeLog | 1 + src/apps/uclient/startuclient.c | 48 ++++++++++++++++++++--------- src/server/ns_turn_server.c | 54 ++++++++++++++++++++++----------- 3 files changed, 72 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index db1f63ca..caadd49e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,7 @@ Version 4.0.1.4 'Severard': - multiple origins supported. - working on compilation warnings. + - "allocation mismatch" condition fixed (merged from rfc5766-turn-server). 06/13/2014 Oleg Moskalenko Version 4.0.1.3 'Severard': diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 1593d28a..d4c35229 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -306,7 +306,9 @@ static int clnet_allocate(int verbose, app_ur_conn_info *clnet_info, ioa_addr *relay_addr, int af, - char *turn_addr, u16bits *turn_port) { + char *turn_addr, u16bits *turn_port, + stun_tid *in_tid, + stun_tid *out_tid) { int af_cycle = 0; int reopen_socket = 0; @@ -332,8 +334,9 @@ static int clnet_allocate(int verbose, } stun_buffer message; - if(current_reservation_token) + if(!in_tid && current_reservation_token) { af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT; + } if(!dos) stun_set_allocate_request(&message, 800, af, relay_transport, mobility); @@ -343,9 +346,13 @@ static int clnet_allocate(int verbose, if(bps) stun_attr_add_bandwidth_str(message.buf, (size_t*)(&(message.len)), bps); + if(in_tid) { + stun_tid_message_cpy(message.buf, in_tid); + } + if(dont_fragment) stun_attr_add(&message, STUN_ATTRIBUTE_DONT_FRAGMENT, NULL, 0); - if(!no_rtcp) { + if(!no_rtcp && !in_tid) { if (!never_allocate_rtcp && allocate_rtcp) { uint64_t reservation_token = ioa_ntoh64(current_reservation_token); stun_attr_add(&message, STUN_ATTRIBUTE_RESERVATION_TOKEN, @@ -367,6 +374,10 @@ static int clnet_allocate(int verbose, stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); + if(out_tid) { + stun_tid_from_message_str(message.buf, (size_t)message.len, out_tid); + } + while (!allocate_sent) { int len = send_buffer(clnet_info, &message,0,0); @@ -519,7 +530,9 @@ static int clnet_allocate(int verbose, exit(-1); } - allocate_rtcp = !allocate_rtcp; + if(!in_tid) { + allocate_rtcp = !allocate_rtcp; + } if (1) { @@ -900,7 +913,9 @@ int start_connection(uint16_t clnet_remote_port0, char remote_address[1025]; STRCPY(remote_address,remote_address0); - clnet_allocate(verbose, clnet_info_probe, &relay_addr, default_address_family, remote_address, &clnet_remote_port); + stun_tid tid; + + clnet_allocate(verbose, clnet_info_probe, &relay_addr, default_address_family, remote_address, &clnet_remote_port,NULL,NULL); /* Real: */ @@ -920,15 +935,20 @@ int start_connection(uint16_t clnet_remote_port0, } int af = default_address_family ? default_address_family : get_allocate_address_family(&peer_addr); - if (clnet_allocate(verbose, clnet_info, &relay_addr, af, NULL,NULL) < 0) { + if (clnet_allocate(verbose, clnet_info, &relay_addr, af, NULL,NULL,NULL,&tid) < 0) { exit(-1); } + //strcpy((char*)g_uname,"qqq"); + //if (clnet_allocate(verbose, clnet_info, &relay_addr, af, NULL,NULL,&tid,NULL) < 0) { + // exit(-1); + //} + if(rare_event()) return 0; if(!no_rtcp) { af = default_address_family ? default_address_family : get_allocate_address_family(&peer_addr_rtcp); - if (clnet_allocate(verbose, clnet_info_rtcp, &relay_addr_rtcp, af,NULL,NULL) < 0) { + if (clnet_allocate(verbose, clnet_info_rtcp, &relay_addr_rtcp, af,NULL,NULL,NULL,NULL) < 0) { exit(-1); } if(rare_event()) return 0; @@ -1115,7 +1135,7 @@ int start_c2c_connection(uint16_t clnet_remote_port0, char remote_address[1025]; STRCPY(remote_address,remote_address0); - clnet_allocate(verbose, clnet_info_probe, &relay_addr1, default_address_family, remote_address, &clnet_remote_port); + clnet_allocate(verbose, clnet_info_probe, &relay_addr1, default_address_family, remote_address, &clnet_remote_port,NULL,NULL); if(rare_event()) return 0; @@ -1148,7 +1168,7 @@ int start_c2c_connection(uint16_t clnet_remote_port0, if(!no_rtcp) { - if (clnet_allocate(verbose, clnet_info1, &relay_addr1, default_address_family,NULL,NULL) + if (clnet_allocate(verbose, clnet_info1, &relay_addr1, default_address_family,NULL,NULL,NULL,NULL) < 0) { exit(-1); } @@ -1156,13 +1176,13 @@ int start_c2c_connection(uint16_t clnet_remote_port0, if(rare_event()) return 0; if (clnet_allocate(verbose, clnet_info1_rtcp, - &relay_addr1_rtcp, default_address_family,NULL,NULL) < 0) { + &relay_addr1_rtcp, default_address_family,NULL,NULL,NULL,NULL) < 0) { exit(-1); } if(rare_event()) return 0; - if (clnet_allocate(verbose, clnet_info2, &relay_addr2, default_address_family,NULL,NULL) + if (clnet_allocate(verbose, clnet_info2, &relay_addr2, default_address_family,NULL,NULL,NULL,NULL) < 0) { exit(-1); } @@ -1170,20 +1190,20 @@ int start_c2c_connection(uint16_t clnet_remote_port0, if(rare_event()) return 0; if (clnet_allocate(verbose, clnet_info2_rtcp, - &relay_addr2_rtcp, default_address_family,NULL,NULL) < 0) { + &relay_addr2_rtcp, default_address_family,NULL,NULL,NULL,NULL) < 0) { exit(-1); } if(rare_event()) return 0; } else { - if (clnet_allocate(verbose, clnet_info1, &relay_addr1, default_address_family,NULL,NULL) + if (clnet_allocate(verbose, clnet_info1, &relay_addr1, default_address_family,NULL,NULL,NULL,NULL) < 0) { exit(-1); } if(rare_event()) return 0; if(!(clnet_info2->is_peer)) { - if (clnet_allocate(verbose, clnet_info2, &relay_addr2, default_address_family,NULL,NULL) < 0) { + if (clnet_allocate(verbose, clnet_info2, &relay_addr2, default_address_family,NULL,NULL,NULL,NULL) < 0) { exit(-1); } if(rare_event()) return 0; diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index c25d7296..fb31db19 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3035,8 +3035,13 @@ static int check_stun_auth(turn_turnserver *server, get_realm_options_by_name((char *)realm, &(ss->realm_options)); } else if(strcmp((char*)realm, (char*)(ss->realm_options.name))) { - *err_code = 441; - *reason = (const u08bits*)"Wrong credentials: the realm value incorrect"; + if(method == STUN_METHOD_ALLOCATE) { + *err_code = 437; + *reason = (const u08bits*)"Allocation mismatch: wrong credentials: the realm value is incorrect"; + } else { + *err_code = 441; + *reason = (const u08bits*)"Wrong credentials: the realm value is incorrect"; + } return -1; } } @@ -3059,8 +3064,13 @@ static int check_stun_auth(turn_turnserver *server, if(ss->username[0]) { if(strcmp((char*)ss->username,(char*)usname)) { - *err_code = 441; - *reason = (const u08bits*)"Wrong credentials"; + if(method == STUN_METHOD_ALLOCATE) { + *err_code = 437; + *reason = (const u08bits*)"Allocation mismatch: wrong credentials"; + } else { + *err_code = 441; + *reason = (const u08bits*)"Wrong credentials"; + } return -1; } } else { @@ -3259,21 +3269,31 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, if(method == STUN_METHOD_ALLOCATE) { - SOCKET_TYPE cst = get_ioa_socket_type(ss->client_socket); - turn_server_addrs_list_t *asl = server->alternate_servers_list; - - if(((cst == UDP_SOCKET)||(cst == DTLS_SOCKET)) && server->self_udp_balance && - server->aux_servers_list && server->aux_servers_list->size) { - asl = server->aux_servers_list; - } else if(((cst == TLS_SOCKET) || (cst == DTLS_SOCKET)) && - server->tls_alternate_servers_list && server->tls_alternate_servers_list->size) { - asl = server->tls_alternate_servers_list; + allocation *a = get_allocation_ss(ss); + if(is_allocation_valid(a)) { + if(!stun_tid_equals(&(a->tid), &tid)) { + err_code = 437; + reason = (const u08bits *)"Mismatched allocation: wrong transaction ID"; + } } - if(asl && asl->size) { - turn_mutex_lock(&(asl->m)); - set_alternate_server(asl,get_local_addr_from_ioa_socket(ss->client_socket),&(server->as_counter),method,&tid,resp_constructed,&err_code,&reason,nbh); - turn_mutex_unlock(&(asl->m)); + if(!err_code) { + SOCKET_TYPE cst = get_ioa_socket_type(ss->client_socket); + turn_server_addrs_list_t *asl = server->alternate_servers_list; + + if(((cst == UDP_SOCKET)||(cst == DTLS_SOCKET)) && server->self_udp_balance && + server->aux_servers_list && server->aux_servers_list->size) { + asl = server->aux_servers_list; + } else if(((cst == TLS_SOCKET) || (cst == DTLS_SOCKET)) && + server->tls_alternate_servers_list && server->tls_alternate_servers_list->size) { + asl = server->tls_alternate_servers_list; + } + + if(asl && asl->size) { + turn_mutex_lock(&(asl->m)); + set_alternate_server(asl,get_local_addr_from_ioa_socket(ss->client_socket),&(server->as_counter),method,&tid,resp_constructed,&err_code,&reason,nbh); + turn_mutex_unlock(&(asl->m)); + } } } From 5c3b773d9c0038abda6fb968b481d6a6e75c113f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 11 Jul 2014 07:06:05 +0000 Subject: [PATCH 090/805] MongoDB support: initial checkin --- INSTALL | 67 +- Makefile.in | 7 +- README.turnadmin | 2 + README.turnserver | 25 +- configure | 56 + examples/etc/turnserver.conf | 14 +- postinstall.txt | 2 +- src/apps/relay/dbdrivers/dbd_mongo.c | 916 ++++++++++ src/apps/relay/dbdrivers/dbd_mongo.h | 49 + src/apps/relay/dbdrivers/dbd_mysql.c | 870 +++++++++ src/apps/relay/dbdrivers/dbd_mysql.h | 49 + src/apps/relay/dbdrivers/dbd_pgsql.c | 668 +++++++ src/apps/relay/dbdrivers/dbd_pgsql.h | 49 + src/apps/relay/dbdrivers/dbd_redis.c | 1150 ++++++++++++ src/apps/relay/dbdrivers/dbd_redis.h | 49 + src/apps/relay/dbdrivers/dbdriver.c | 90 + src/apps/relay/dbdrivers/dbdriver.h | 78 + src/apps/relay/mainrelay.c | 48 +- src/apps/relay/mainrelay.h | 2 - src/apps/relay/turncli.c | 5 + src/apps/relay/userdb.c | 2529 +------------------------- src/apps/relay/userdb.h | 9 +- 22 files changed, 4262 insertions(+), 2472 deletions(-) create mode 100644 src/apps/relay/dbdrivers/dbd_mongo.c create mode 100644 src/apps/relay/dbdrivers/dbd_mongo.h create mode 100644 src/apps/relay/dbdrivers/dbd_mysql.c create mode 100644 src/apps/relay/dbdrivers/dbd_mysql.h create mode 100644 src/apps/relay/dbdrivers/dbd_pgsql.c create mode 100644 src/apps/relay/dbdrivers/dbd_pgsql.h create mode 100644 src/apps/relay/dbdrivers/dbd_redis.c create mode 100644 src/apps/relay/dbdrivers/dbd_redis.h create mode 100644 src/apps/relay/dbdrivers/dbdriver.c create mode 100644 src/apps/relay/dbdrivers/dbdriver.h diff --git a/INSTALL b/INSTALL index ff60b585..21d41c0a 100644 --- a/INSTALL +++ b/INSTALL @@ -212,13 +212,13 @@ do not allows that, then after the installation, you may have to adjust the system-wide shared library search path by using "ldconfig -n " (Linux), "ldconfig -m " (BSD) or "crle -u -l " (Solaris). Your system must be able to find the libevent2, openssl and -(optionally) PostgreSQL and/or MySQL (MariaDB) and/or Redis shared libraries, -either with the help of the system-wide library search configuration or by -using LD_LIBRARY_PATH. "make install" will make a non-garantied effort to add -automatically PREFIX/lib and /usr/local/lib to the libraries search path, -but if you have some libraries in different non-default directories -you will have to add them manually to the search path, or you -will have to adjust LD_LIBRARY_PATH. +(optionally) PostgreSQL and/or MySQL (MariaDB) and/or MongoDB and/or Redis +shared libraries, either with the help of the system-wide library search +configuration or by using LD_LIBRARY_PATH. "make install" will make a +non-garantied effort to add automatically PREFIX/lib and /usr/local/lib to +the libraries search path, but if you have some libraries in different +non-default directories you will have to add them manually to the search +path, or you will have to adjust LD_LIBRARY_PATH. V. PLATFORMS @@ -277,8 +277,8 @@ VII. WHICH EXTRA LIBRARIES AND UTILITIES YOU NEED In addition to common *NIX OS services and libraries, to compile this code, OpenSSL (version 1.0.0a or better recommended) and libevent2 (version 2.0.5 or better) are required, the PostgreSQL C client development setup is -optional, the MySQL (MariaDB) C client development setup is optional, and the -Hiredis development files for Redis database access are optional. +optional, the MySQL (MariaDB) C client development setup is optional, the MongoDB +C Driver and the Hiredis development files for Redis database access are optional. For fully functional build, the extra set of libraries must be installed in full version (the development headers and the libraries to link with). For runtime, only runtime setup is required. If the build is modified for @@ -290,6 +290,7 @@ libraries can be downloaded from their web sites: - http://www.libevent.org (required); - http://www.postgresql.org (optional); - http://www.mysql.org (or http://mariadb.org) (optional); + - https://github.com/mongodb/mongo-c-driver (optional); - http://redis.io (optional). The installations are pretty straightforward - the usual @@ -352,6 +353,11 @@ installation: - you have to install gcc first: $ sudo yum install gcc + - mongo-c-driver packages are not available. MongoDB support + will not be compiled, unless you install it "manually" before + the TURN server compilation. Refer to https://github.com/mongodb/mongo-c-driver + for installation instructions of the driver. + - hiredis packages are not available, so do not issue the hiredis installation commands. Redis support will not be compiled, unless you install it "manually" before the TURN @@ -381,7 +387,7 @@ like this: Dynamic library paths: You may also have to adjust the turn server start script, add PostgreSQL -and/or MySQL and/or Redis runtime library path to LD_LIBRARY_PATH. +and/or MySQL and/or MongoDB and/or Redis runtime library path to LD_LIBRARY_PATH. Or you may find that it would be more convenient to adjust the system-wide shared library search path by using commands: @@ -412,17 +418,17 @@ absolute paths or @rpath/... . See also the next section. -NOTE: See "PostgreSQL setup" and "MySQL setup" and "Redis setup" sections -below for more database setup information. +NOTE: See "PostgreSQL setup" and "MySQL setup" and "MongoDB setup" and +"Redis setup" sections below for more database setup information. -NOTE: If you do not install PostgreSQL or MySQL or Redis then you will +NOTE: If you do not install PostgreSQL or MySQL or MongoDB or Redis then you will be limited to flat files for user database. It will work great for smaller user databases (like 100 users) but for larger systems you -will need PostgreSQL or MySQL or Redis. +will need PostgreSQL or MySQL or MongoDB or Redis. -NOTE: To run PostgreSQL or MySQL or Redis server on the same system, +NOTE: To run PostgreSQL or MySQL or MongoDB or Redis server on the same system, you will also have to install a corresponding PostgreSQL or MySQL or -Redis server package. The DB C development packages only provide +MongoDB or Redis server package. The DB C development packages only provide development libraries, and client libraries only provide client access utilities and runtime libraries. The server packages may include everything - client, C development and server runtime. @@ -892,7 +898,28 @@ Or in the turnserver.conf file: mysql-userdb="host=localhost dbname=turn user=turn password=turn connect_timeout=30" -XVI. Redis setup +XVI. MongoDB setup + +The MongoDB setup is well documented on their site http://docs.mongodb.org/manual/. + +If the TURN server was compiled with MongoDB support (mongo-c-driver is the C client +library for MongoDB), then we can use the TURN server database parameter +--mongo-userdb. The value of this parameter is a connection string +for the MongoDB database. The format of the connection string is described at +http://hergert.me/docs/mongo-c-driver/mongoc_uri.html: + +"mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]" + +So, an example of the MongoDB database parameter in the TURN server command +line would be: + +--mongo-userdb="mongodb://localhost:27017/turndb" + +Or in the turnserver.conf file: + +mongo-userdb="mongodb://localhost:27017/turndb" + +XVII. Redis setup The Redis setup is well documented on their site http://redis.io. The TURN Server Redis database schema description can be found @@ -961,20 +988,20 @@ Redis TURN admin commands: $ bin/turnadmin -A -N "host=localhost dbname=0 user=turn password=turn" -u gorst -r north.gov -p hero $ bin/turnadmin -A -N "host=localhost dbname=0 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic -XV. Performance tuning +XVIII. Performance tuning This topic is covered in the wiki page: http://code.google.com/p/coturn/wiki/turn_performance_and_load_balance -XVI. TURN Server setup +XIX. TURN Server setup 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. -XVI. Management interface +XX. 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 diff --git a/Makefile.in b/Makefile.in index cea66b34..171164d3 100755 --- a/Makefile.in +++ b/Makefile.in @@ -27,8 +27,11 @@ IMPL_DEPS = ${COMMON_DEPS} ${IMPL_HEADERS} ${IMPL_MODS} HIREDIS_HEADERS = src/apps/common/hiredis_libevent2.h HIREDIS_MODS = src/apps/common/hiredis_libevent2.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} -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_HEADERS = src/apps/relay/dbdrivers/dbdriver.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_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_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 diff --git a/README.turnadmin b/README.turnadmin index fb5f176d..ab0233f3 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -92,6 +92,8 @@ Options with required values: See the --psql-userdb option in the turnserver section. -M, --mysql-userdb MySQL user database connection string. See the --mysql-userdb option in the turnserver section. +-J, --mongo-userdb MongoDB user database connection string. + See the --mysql-mongo option in the turnserver section. -N, --redis-userdb Redis user database connection string. See the --redis-userdb option in the turnserver section. -u, --user User name. diff --git a/README.turnserver b/README.turnserver index 888a7e0b..555a72f0 100644 --- a/README.turnserver +++ b/README.turnserver @@ -57,7 +57,7 @@ turnserver - a TURN relay server implementation. SYNOPSIS -$ turnserver [-n | -c ] [flags] [ --userdb= | --psql-userdb= | --mysql-userdb= | --redis-userdb= ] [-z | --no-auth | -a | --lt-cred-mech ] [options] +$ turnserver [-n | -c ] [flags] [ --userdb= | --psql-userdb= | --mysql-userdb= | --mongo-userdb= | --redis-userdb= ] [-z | --no-auth | -a | --lt-cred-mech ] [options] $ turnserver -h DESCRIPTION @@ -113,6 +113,17 @@ User database settings: Also, see http://www.mysql.org or http://mariadb.org for full MySQL documentation. +-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 for secret-based timed authentication in TURN RESP API. + The connection string format is like that: + + "mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]" + See the INSTALL file for more explanations and examples. + + Also, see http://docs.mongodb.org/manual/ + 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 value for secret-based timed authentication in TURN RESP API. @@ -138,9 +149,9 @@ Flags: -a, --lt-cred-mech Use long-term credentials mechanism (this one you need for WebRTC usage). This option can be used with either flat file user database or - PostgreSQL DB or MySQL DB or Redis for user keys storage. + PostgreSQL DB or MySQL DB or MongoDB or Redis for user keys storage. -A, --st-cred-mech Use the short-term credentials mechanism. This option requires - a PostgreSQL or MySQL or Redis DB for short term passwords storage. + a PostgreSQL or MySQL or MongoDB or Redis DB for short term passwords storage. -z, --no-auth Do not use any credentials mechanism, allow anonymous access. Opposite to -a and -A options. This is default option when no @@ -461,7 +472,7 @@ Options with required values: no Redis stats DB used). This database keeps allocations status information, and it can be also used for publishing and delivering traffic and allocation event notifications. This database option can be used independently of --redis-userdb option, - and actually Redis can be used for status/statistics and MySQL or PostgreSQL can + and actually Redis can be used for status/statistics and MySQL or MongoDB or PostgreSQL can be used for the user database. The connection string has the same parameters as redis-userdb connection string. @@ -533,7 +544,7 @@ for that you have a number of options: b) userdb config file. - c) a database table (PostgreSQL or MySQL). You will have to set keys with + c) a database table (PostgreSQL or MySQL or MongoDB). You will have to set keys with turnadmin utility (see docs and wiki for turnadmin). You cannot use open passwords in the database. @@ -717,7 +728,9 @@ turndb/testredisdbsetup.sh as an example. can be administered separately, and each realm can have its own set of users and its own performance options (max-bps, user-quota, total-quota). -7) Of course, the turnserver can be used in non-secure mode, when users are allowed to establish +7) If you use MongoDB, the database will be setup for you automatically. + +8) Of course, the turnserver can be used in non-secure mode, when users are allowed to establish sessions anonymously. But in most cases (like WebRTC) that will not work. For the status and statistics database, there are two choices: diff --git a/configure b/configure index 2e156038..0ad77694 100755 --- a/configure +++ b/configure @@ -13,6 +13,8 @@ cleanup() { rm -rf ${PQ_TMPCPROGB} rm -rf ${MYSQL_TMPCPROGC} rm -rf ${MYSQL_TMPCPROGB} + rm -rf ${MONGO_TMPCPROGC} + rm -rf ${MONGO_TMPCPROGB} rm -rf ${D_TMPCPROGC} rm -rf ${D_TMPCPROGB} rm -rf ${E_TMPCPROGC} @@ -124,6 +126,30 @@ testlibmysql() { fi } +testlibmongoc() { + for inc in ${PREFIX}/libmongoc-1.0 ${PREFIX}/libbson-1.0 /usr/local/include/libmongoc-1.0 /usr/local/include/libbson-1.0 /usr/libmongoc-1.0 -I/usr/libbson-1.0 + do + if [ -d ${inc} ] ; then + MONGO_CFLAGS="${MONGO_CFLAGS} -I${inc}" + fi + done + MONGO_LIBS="-lmongoc-1.0 -lbson-1.0" + ${CC} ${MONGO_TMPCPROGC} -o ${MONGO_TMPCPROGB} ${OSCFLAGS} ${DBCFLAGS} ${DBLIBS} ${MONGO_CFLAGS} ${MONGO_LIBS} ${OSLIBS} 2>>/dev/null + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} + ${ECHO_CMD} "MONGODB DEVELOPMENT LIBRARIES (libmongoc-1.0 and libbson-1.0) AND/OR HEADER (mongoc.h)" + ${ECHO_CMD} " ARE NOT INSTALLED PROPERLY ON THIS SYSTEM." + ${ECHO_CMD} " THAT'S OK BUT THE TURN SERVER IS BUILDING WITHOUT MONGODB SUPPORT." + ${ECHO_CMD} + return 0 + else + DBCFLAGS="${DBCFLAGS} ${MONGO_CFLAGS}" + DBLIBS="${DBLIBS} ${MONGO_LIBS}" + return 1 + fi +} + testlib() { testlibraw l${1} } @@ -666,6 +692,19 @@ int main(int argc, char** argv) { } ! +MONGO_TMPCPROG=__test__ccomp__libmongoc__$$ +MONGO_TMPCPROGC=${TMPDIR}/${MONGO_TMPCPROG}.c +MONGO_TMPCPROGB=${TMPDIR}/${MONGO_TMPCPROG} + +cat > ${MONGO_TMPCPROGC} < +int main(int argc, char** argv) { + return (argc+ + (int)(mongoc_client_new("mongodb://localhost:27017")!=0)+ + (int)(argv[0][0])); +} +! + ########################## # What is our compiler ? ########################## @@ -940,6 +979,23 @@ else TURN_NO_MYSQL="-DTURN_NO_MYSQL" fi +########################### +# Test MongoDB +########################### + +if [ -z "${TURN_NO_MONGO}" ] ; then + + testlibmongoc + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "MongoDB found." + else + TURN_NO_MYSQL="-DTURN_NO_MONGO" + fi +else + TURN_NO_MYSQL="-DTURN_NO_MONGO" +fi + ########################### # Test Redis ########################### diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index f5dc5f8a..b389b79b 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -161,14 +161,14 @@ # Uncomment to use long-term credential mechanism. # By default no credentials mechanism is used (any user allowed). # This option can be used with either flat file user database or -# PostgreSQL DB or MySQL DB or Redis DB for user keys storage. +# PostgreSQL DB or MySQL DB or MongoDB or Redis DB for user keys storage. # #lt-cred-mech # Uncomment to use short-term credential mechanism. # By default no credentials mechanism is used (any user allowed). # For short-term credential mechanism you have to use PostgreSQL or -# MySQL or Redis database for user password storage. +# MySQL or MongoDB or Redis database for user password storage. # #st-cred-mech @@ -241,7 +241,7 @@ # 'Dynamic' user accounts database file name. # Only users for long-term mechanism can be stored in a flat file, # short-term mechanism will not work with option, the short-term -# mechanism required PostgreSQL or MySQL or Redis database. +# mechanism required PostgreSQL or MySQL or MongoDB or Redis database. # 'Dynamic' long-term user accounts are dynamically checked by the turnserver process, # so that they can be changed while the turnserver is running. # @@ -268,6 +268,14 @@ # #mysql-userdb="host= dbname= user= password= port= connect_timeout=" +# 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 +# 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 +# +#mongo-userdb="mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]" + # 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 diff --git a/postinstall.txt b/postinstall.txt index c05efceb..b6546c1a 100644 --- a/postinstall.txt +++ b/postinstall.txt @@ -10,7 +10,7 @@ service, you have to: b) For user accounts settings, if using the turnserver with authentication: create and edit /etc/turnuserdb.conf - file, or set up PostgreSQL or MySQL or Redis database for user accounts. + file, or set up PostgreSQL or MySQL or MongoDB or Redis database for user accounts. Use /usr/local/etc/turnuserdb.conf.default as example for flat file DB, or use /usr/local/share/turnserver/schema.sql as SQL database schema, or use /usr/local/share/turnserver/schema.userdb.redis as Redis diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c new file mode 100644 index 00000000..75dbec42 --- /dev/null +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -0,0 +1,916 @@ +/* + * Copyright (C) 2011, 2012, 2013 Citrix Systems + * Copyright (C) 2014 Vivocha S.p.A. + * + * 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. + */ + +#include "../mainrelay.h" +#include "dbd_mongo.h" + +#if !defined(TURN_NO_MONGO) +#include +#include + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +const char * MONGO_DEFAULT_DB = "turn"; + +struct _MONGO { + mongoc_uri_t * uri; + mongoc_client_t * client; + const char * database; +}; + +typedef struct _MONGO MONGO; + +static void mongo_logger(mongoc_log_level_t log_level, const char * log_domain, const char * message, void * user_data) { + UNUSED_ARG(log_domain); + UNUSED_ARG(user_data); + + TURN_LOG_LEVEL l; + + switch(log_level) { + case MONGOC_LOG_LEVEL_ERROR: + l = TURN_LOG_LEVEL_ERROR; + break; + case MONGOC_LOG_LEVEL_WARNING: + l = TURN_LOG_LEVEL_WARNING; + break; + default: + l = TURN_LOG_LEVEL_INFO; + break; + } + TURN_LOG_FUNC(l, "%s\n", message); +} + +static void MongoFree(MONGO * info) { + if(info) { + if(info->uri) mongoc_uri_destroy(info->uri); + if(info->client) mongoc_client_destroy(info->client); + turn_free(info, sizeof(MONGO)); + } +} + +static MONGO * get_mydb_connection(const char *realm) { + UNUSED_ARG(realm); + + persistent_users_db_t * pud = get_persistent_users_db(); + + MONGO * mydbconnection = (MONGO *)(pud->connection); + + if(!mydbconnection) { + mongoc_init(); + mongoc_log_set_handler(&mongo_logger, NULL); + + mydbconnection = (MONGO *)turn_malloc(sizeof(MONGO)); + mydbconnection->uri = mongoc_uri_new(pud->userdb); + + if (!mydbconnection->uri) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open parse MongoDB URI <%s>, connection string format error\n", pud->userdb); + MongoFree(mydbconnection); + mydbconnection = NULL; + } else { + mydbconnection->client = mongoc_client_new_from_uri(mydbconnection->uri); + if (!mydbconnection->client) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize MongoDB connection\n"); + MongoFree(mydbconnection); + mydbconnection = NULL; + } else { + mydbconnection->database = mongoc_uri_get_database(mydbconnection->uri); + if (!mydbconnection->database) mydbconnection->database = MONGO_DEFAULT_DB; + pud->connection = mydbconnection; + } + } + } + return mydbconnection; +} + +static mongoc_collection_t * mongo_get_collection(const char * name) { + MONGO * mc = get_mydb_connection(NULL); + + if(!mc) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error gettting a connection to MongoDB\n"); + return NULL; + } + + mongoc_collection_t * collection; + collection = mongoc_client_get_collection(mc->client, mc->database, name); + + if (!collection) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MongoDB collection '%s'\n", name); + } + + return collection; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static int mongo_get_auth_secrets(secrets_list_t *sl, u08bits *realm) { + mongoc_collection_t * collection = mongo_get_collection("turn_secret"); + + if(!collection) + return -1; + + bson_t query; + bson_init(&query); + BSON_APPEND_UTF8(&query, "realm", (const char *)realm); + + bson_t fields; + bson_init(&fields); + BSON_APPEND_INT32(&fields, "value", 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 '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); + add_to_secrets_list(sl, value); + } + } + mongoc_cursor_destroy(cursor); + ret = 0; + } + + mongoc_collection_destroy(collection); + bson_destroy(&query); + bson_destroy(&fields); + return ret; +} + +static int mongo_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) { + mongoc_collection_t * collection = mongo_get_collection("turnusers_lt"); + + if(!collection) + return -1; + + bson_t query; + bson_init(&query); + BSON_APPEND_UTF8(&query, "name", (const char *)usname); + BSON_APPEND_UTF8(&query, "realm", (const char *)realm); + + bson_t fields; + bson_init(&fields); + BSON_APPEND_INT32(&fields, "hmackey", 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_lt'\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, "hmackey") && BSON_ITER_HOLDS_UTF8(&iter)) { + value = bson_iter_utf8(&iter, &length); + size_t sz = get_hmackey_size(turn_params.shatype) * 2; + if(length < sz) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key format: string length=%d (must be %d): user %s\n", (int)length, (int)sz, usname); + } else { + char kval[sizeof(hmackey_t) + sizeof(hmackey_t) + 1]; + ns_bcopy(value, kval, sz); + kval[sz] = 0; + if(convert_string_key_to_binary(kval, key, sz / 2) < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key: %s, user %s\n", kval, usname); + } else { + ret = 0; + } + } + } + } + mongoc_cursor_destroy(cursor); + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + bson_destroy(&fields); + 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"); + + if(!collection) + return -1; + + bson_t query; + bson_init(&query); + BSON_APPEND_UTF8(&query, "name", (const char *)usname); + BSON_APPEND_UTF8(&query, "realm", (const char *)realm); + + 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, "hmackey", (const char *)key); + + 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_set_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 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); + } + + int ret = -1; + + if (!mongoc_collection_delete(collection, MONGOC_DELETE_SINGLE_REMOVE, &query, NULL, NULL)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting user key information\n"); + } else { + ret = 0; + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + 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); + + 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); + if (!is_st && 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, "name", 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; + const char * value; + 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) { + printf("%s\n", value); + } + } + } + mongoc_cursor_destroy(cursor); + ret = 0; + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + bson_destroy(&fields); + return ret; +} + +static int mongo_show_secret(u08bits *realm) { + mongoc_collection_t * collection = mongo_get_collection("turn_secret"); + + if(!collection) + return -1; + + bson_t query; + bson_init(&query); + BSON_APPEND_UTF8(&query, "realm", (const char *)realm); + + bson_t fields; + bson_init(&fields); + BSON_APPEND_INT32(&fields, "value", 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 '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; +} + +static int mongo_del_secret(u08bits *secret, u08bits *realm) { + mongoc_collection_t * collection = mongo_get_collection("turn_secret"); + + if(!collection) + return -1; + + bson_t query; + bson_init(&query); + 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, 0, &query, NULL, NULL); + mongoc_collection_destroy(collection); + bson_destroy(&query); + return 0; +} + +static int mongo_set_secret(u08bits *secret, u08bits *realm) { + mongoc_collection_t * collection = mongo_get_collection("turn_secret"); + + if(!collection) + return -1; + + bson_t query; + bson_init(&query); + BSON_APPEND_UTF8(&query, "realm", (const char *)realm); + BSON_APPEND_UTF8(&query, "value", (const char *)secret); + + int res = mongoc_collection_insert(collection, MONGOC_INSERT_NONE, &query, NULL, NULL); + mongoc_collection_destroy(collection); + bson_destroy(&query); + + if (!res) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating secret key information\n"); + return -1; + } else { + return 0; + } +} + +static int mongo_add_origin(u08bits *origin, u08bits *realm) { + 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); + + 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; + + bson_t query, doc, child; + bson_init(&query); + bson_init(&doc); + bson_append_document_begin(&doc, "$pull", -1, &child); + BSON_APPEND_UTF8(&child, "origin", (const char *)origin); + bson_append_document_end(&doc, &child); + + if (!mongoc_collection_update(collection, MONGOC_UPDATE_MULTI_UPDATE, &query, &doc, NULL, NULL)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting origin information\n"); + } else { + ret = 0; + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + bson_destroy(&doc); + return ret; +} + +static int mongo_list_origins(u08bits *realm) { + mongoc_collection_t * collection = mongo_get_collection("realm"); + + 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); + 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); + + int ret = -1; + + 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; + + 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; + + 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; +} + +static int mongo_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) { + mongoc_collection_t * collection = mongo_get_collection("realm"); + + if(!collection) + return -1; + + bson_t query, doc, child; + bson_init(&query); + BSON_APPEND_UTF8(&query, "realm", (const char *)realm); + bson_init(&doc); + + char * _k = (char *)turn_malloc(9 + strlen(opt)); + strcpy(_k, "options."); + strcat(_k, opt); + + if (value > 0) { + bson_append_document_begin(&doc, "$set", -1, &child); + BSON_APPEND_INT32(&child, _k, (int32_t)value); + bson_append_document_end(&doc, &child); + } else { + bson_append_document_begin(&doc, "$unset", -1, &child); + BSON_APPEND_INT32(&child, _k, 1); + bson_append_document_end(&doc, &child); + } + free(_k); + + int ret = -1; + + if (!mongoc_collection_update(collection, MONGOC_UPDATE_MULTI_UPDATE, &query, &doc, NULL, NULL)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting origin information\n"); + } else { + ret = 0; + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + bson_destroy(&doc); + return ret; +} + +static int mongo_list_realm_options(u08bits *realm) { + mongoc_collection_t * collection = mongo_get_collection("realm"); + + 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); + 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, "options", 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 'realm'\n"); + } 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); + + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "options") && BSON_ITER_HOLDS_DOCUMENT(&iter)) { + const uint8_t *docbuf = NULL; + uint32_t doclen = 0; + bson_t options; + bson_iter_t options_iter; + + bson_iter_document(&iter, &doclen, &docbuf); + bson_init_static(&options, docbuf, doclen); + + if (bson_iter_init(&options_iter, &options)) { + while(bson_iter_next(&options_iter)) { + const char * _k = bson_iter_key(&options_iter); + printf("key %s, type %d\n", _k, bson_iter_type(&options_iter)); + if (BSON_ITER_HOLDS_DOUBLE(&options_iter)) { + int32_t _v = (int32_t)bson_iter_double(&options_iter); + printf("%s[%s]=%d\n", _k, _realm, _v); + } else if (BSON_ITER_HOLDS_INT32(&options_iter)) { + int32_t _v = bson_iter_int32(&options_iter); + printf("%s[%s]=%d\n", _k, _realm, _v); + } else if (BSON_ITER_HOLDS_INT64(&options_iter)) { + int32_t _v = (int32_t)bson_iter_int64(&options_iter); + printf("%s[%s]=%d\n", _k, _realm, _v); + } + } + } + } + } + } + mongoc_cursor_destroy(cursor); + ret = 0; + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + bson_destroy(&fields); + return ret; +} + +static void mongo_auth_ping(void * rch) { + UNUSED_ARG(rch); + // NOOP +} + +static int mongo_get_ip_list(const char *kind, ip_range_list_t * list) { + char * collection_name = (char *)turn_malloc(strlen(kind) + 9); + sprintf(collection_name, "%s_peer_ip", kind); + mongoc_collection_t * collection = mongo_get_collection(collection_name); + turn_free(collection_name, strlen(kind) + 9); + + if(!collection) + return -1; + + bson_t query; + bson_init(&query); + + bson_t fields; + bson_init(&fields); + BSON_APPEND_INT32(&fields, "ip_range", 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; + 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); + add_ip_list_range(value, list); + } + } + mongoc_cursor_destroy(cursor); + ret = 0; + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + bson_destroy(&fields); + return ret; +} + +static void mongo_reread_realms(secrets_list_t * realms_list) { + UNUSED_ARG(realms_list); + + mongoc_collection_t * collection = mongo_get_collection("realm"); + + if(!collection) + return; + + bson_t query; + bson_init(&query); + + bson_t fields; + bson_init(&fields); + BSON_APPEND_INT32(&fields, "realm", 1); + BSON_APPEND_INT32(&fields, "origin", 1); + BSON_APPEND_INT32(&fields, "options", 1); + + mongoc_cursor_t * cursor; + cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL); + + if (!cursor) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection 'realm'\n"); + } else { + ur_string_map *o_to_realm_new = ur_string_map_create(free); + + 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)) { + char * _realm = strdup(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; + + 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); + ur_string_map_value_type value = strdup(_origin); + ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type)_realm, value); + } + } + } + } + + realm_params_t* rp = get_realm(_realm); + lock_realms(); + rp->options.perf_options.max_bps = turn_params.max_bps; + rp->options.perf_options.total_quota = turn_params.total_quota; + rp->options.perf_options.user_quota = turn_params.user_quota; + unlock_realms(); + + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "options") && BSON_ITER_HOLDS_DOCUMENT(&iter)) { + const uint8_t *docbuf = NULL; + uint32_t doclen = 0; + bson_t options; + bson_iter_t options_iter; + + bson_iter_document(&iter, &doclen, &docbuf); + bson_init_static(&options, docbuf, doclen); + + if (bson_iter_init(&options_iter, &options)) { + while(bson_iter_next(&options_iter)) { + const char * _k = bson_iter_key(&options_iter); + int32_t _v; + if (BSON_ITER_HOLDS_DOUBLE(&options_iter)) { + _v = (int32_t)bson_iter_double(&options_iter); + } else if (BSON_ITER_HOLDS_INT32(&options_iter)) { + _v = bson_iter_int32(&options_iter); + } else if (BSON_ITER_HOLDS_INT64(&options_iter)) { + _v = (int32_t)bson_iter_int64(&options_iter); + } + if (_v) { + if(!strcmp(_k,"max-bps")) + rp->options.perf_options.max_bps = (band_limit_t)_v; + else if(!strcmp(_k,"total-quota")) + rp->options.perf_options.total_quota = (vint)_v; + else if(!strcmp(_k,"user-quota")) + rp->options.perf_options.user_quota = (vint)_v; + else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", _k); + } + } + } + } + } + free(_realm); + } + } + update_o_to_realm(o_to_realm_new); + mongoc_cursor_destroy(cursor); + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + bson_destroy(&fields); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static 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_del_secret, + &mongo_set_secret, + &mongo_add_origin, + &mongo_del_origin, + &mongo_list_origins, + &mongo_set_realm_option_one, + &mongo_list_realm_options, + &mongo_auth_ping, + &mongo_get_ip_list, + &mongo_reread_realms +}; + +turn_dbdriver_t * get_mongo_dbdriver(void) { + return &driver; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#else + +turn_dbdriver_t * get_mongo_dbdriver(void) { + return NULL; +} + +#endif diff --git a/src/apps/relay/dbdrivers/dbd_mongo.h b/src/apps/relay/dbdrivers/dbd_mongo.h new file mode 100644 index 00000000..66ed0a07 --- /dev/null +++ b/src/apps/relay/dbdrivers/dbd_mongo.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011, 2012, 2013 Citrix Systems + * Copyright (C) 2014 Vivocha S.p.A. + * + * 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 __DBD_MONGODB__ +#define __DBD_MONGODB__ + +#include "dbdriver.h" + +#ifdef __cplusplus +extern "C" { +#endif + +turn_dbdriver_t * get_mongo_dbdriver(void); + +#ifdef __cplusplus +} +#endif + +#endif +/// __DBD_MONGODB__/// + diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c new file mode 100644 index 00000000..6027ffd7 --- /dev/null +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -0,0 +1,870 @@ +/* + * Copyright (C) 2011, 2012, 2013 Citrix Systems + * Copyright (C) 2014 Vivocha S.p.A. + * + * 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. + */ + +#include "../mainrelay.h" +#include "dbd_mysql.h" + +#if !defined(TURN_NO_MYSQL) +#include + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static int donot_print_connection_success = 0; + +struct _Myconninfo { + char *host; + char *dbname; + char *user; + char *password; + unsigned int port; + unsigned int connect_timeout; +}; + +typedef struct _Myconninfo Myconninfo; + +static void MyconninfoFree(Myconninfo *co) { + if(co) { + if(co->host) turn_free(co->host,strlen(co->host)+1); + if(co->dbname) turn_free(co->dbname, strlen(co->dbname)+1); + if(co->user) turn_free(co->user, strlen(co->user)+1); + if(co->password) turn_free(co->password, strlen(co->password)+1); + ns_bzero(co,sizeof(Myconninfo)); + } +} + +static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) { + Myconninfo *co = (Myconninfo*)turn_malloc(sizeof(Myconninfo)); + ns_bzero(co,sizeof(Myconninfo)); + if(userdb) { + char *s0=strdup(userdb); + char *s = s0; + + while(s && *s) { + + while(*s && (*s==' ')) ++s; + char *snext = strstr(s," "); + if(snext) { + *snext = 0; + ++snext; + } + + char* seq = strstr(s,"="); + if(!seq) { + MyconninfoFree(co); + co = NULL; + if(errmsg) { + *errmsg = strdup(s); + } + break; + } + + *seq = 0; + if(!strcmp(s,"host")) + co->host = strdup(seq+1); + else if(!strcmp(s,"ip")) + co->host = strdup(seq+1); + else if(!strcmp(s,"addr")) + co->host = strdup(seq+1); + else if(!strcmp(s,"ipaddr")) + co->host = strdup(seq+1); + else if(!strcmp(s,"hostaddr")) + co->host = strdup(seq+1); + else if(!strcmp(s,"dbname")) + co->dbname = strdup(seq+1); + else if(!strcmp(s,"db")) + co->dbname = strdup(seq+1); + else if(!strcmp(s,"database")) + co->dbname = strdup(seq+1); + else if(!strcmp(s,"user")) + co->user = strdup(seq+1); + else if(!strcmp(s,"uname")) + co->user = strdup(seq+1); + else if(!strcmp(s,"name")) + co->user = strdup(seq+1); + else if(!strcmp(s,"username")) + co->user = strdup(seq+1); + else if(!strcmp(s,"password")) + co->password = strdup(seq+1); + else if(!strcmp(s,"pwd")) + co->password = strdup(seq+1); + else if(!strcmp(s,"passwd")) + co->password = strdup(seq+1); + else if(!strcmp(s,"secret")) + co->password = strdup(seq+1); + else if(!strcmp(s,"port")) + co->port = (unsigned int)atoi(seq+1); + else if(!strcmp(s,"p")) + co->port = (unsigned int)atoi(seq+1); + else if(!strcmp(s,"connect_timeout")) + co->connect_timeout = (unsigned int)atoi(seq+1); + else if(!strcmp(s,"timeout")) + co->connect_timeout = (unsigned int)atoi(seq+1); + else { + MyconninfoFree(co); + co = NULL; + if(errmsg) { + *errmsg = strdup(s); + } + break; + } + + s = snext; + } + + turn_free(s0, strlen(s0)+1); + } + + if(!(co->dbname)) + co->dbname=strdup("0"); + if(!(co->host)) + co->host=strdup("127.0.0.1"); + if(!(co->user)) + co->user=strdup(""); + if(!(co->password)) + co->password=strdup(""); + + return co; +} + +static MYSQL *get_mydb_connection(void) { + persistent_users_db_t *pud = get_persistent_users_db(); + + MYSQL *mydbconnection = (MYSQL*)(pud->connection); + + if(mydbconnection) { + if(mysql_ping(mydbconnection)) { + mysql_close(mydbconnection); + mydbconnection=NULL; + } + } + + if(!mydbconnection) { + char *errmsg=NULL; + Myconninfo *co=MyconninfoParse(pud->userdb, &errmsg); + if(!co) { + if(errmsg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg); + turn_free(errmsg,strlen(errmsg)+1); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection <%s>, connection string format error\n",pud->userdb); + } + } else if(errmsg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg); + turn_free(errmsg,strlen(errmsg)+1); + MyconninfoFree(co); + } else if(!(co->dbname)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "MySQL Database name is not provided: <%s>\n",pud->userdb); + MyconninfoFree(co); + } else { + mydbconnection = mysql_init(NULL); + if(!mydbconnection) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize MySQL DB connection\n"); + } else { + if(co->connect_timeout) + mysql_options(mydbconnection,MYSQL_OPT_CONNECT_TIMEOUT,&(co->connect_timeout)); + MYSQL *conn = mysql_real_connect(mydbconnection, co->host, co->user, co->password, co->dbname, co->port, NULL, CLIENT_IGNORE_SIGPIPE); + if(!conn) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection: <%s>, runtime error\n",pud->userdb); + mysql_close(mydbconnection); + mydbconnection=NULL; + } else if(mysql_select_db(mydbconnection, co->dbname)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot connect to MySQL DB: %s\n",co->dbname); + mysql_close(mydbconnection); + mydbconnection=NULL; + } else if(!donot_print_connection_success) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MySQL DB connection success: %s\n",pud->userdb); + } + } + MyconninfoFree(co); + } + pud->connection = mydbconnection; + } + return mydbconnection; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static int mysql_get_auth_secrets(secrets_list_t *sl, u08bits *realm) { + int ret = -1; + MYSQL * myc = get_mydb_connection(); + if(myc) { + char statement[TURN_LONG_STRING_SIZE]; + snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm); + 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) { + for(;;) { + MYSQL_ROW row = mysql_fetch_row(mres); + if(!row) { + break; + } else { + if(row[0]) { + unsigned long *lengths = mysql_fetch_lengths(mres); + if(lengths) { + size_t sz = lengths[0]; + char auth_secret[TURN_LONG_STRING_SIZE]; + ns_bcopy(row[0],auth_secret,sz); + auth_secret[sz]=0; + add_to_secrets_list(sl,auth_secret); + } + } + } + } + ret = 0; + } + + if(mres) + mysql_free_result(mres); + } + } + return ret; +} + +static int mysql_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) { + int ret = -1; + MYSQL * myc = get_mydb_connection(); + if(myc) { + char statement[TURN_LONG_STRING_SIZE]; + snprintf(statement,sizeof(statement),"select hmackey 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 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) { + size_t sz = get_hmackey_size(turn_params.shatype)*2; + if(lengths[0]> %s\n",row[0],row[1]); + } + } + } + ret = 0; + } + + if(mres) + mysql_free_result(mres); + } + } + return ret; +} + +static int mysql_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) { + int ret = 1; + char statement[TURN_LONG_STRING_SIZE]; + MYSQL * myc = get_mydb_connection(); + if (myc) { + { + snprintf(statement,sizeof(statement),"delete from turn_realm_option where realm='%s' and opt='%s'",realm,opt); + mysql_query(myc, statement); + } + if(value>0) { + snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%lu')",realm,opt,(unsigned long)value); + int res = mysql_query(myc, statement); + if (res) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "Error inserting realm option information: %s\n", + mysql_error(myc)); + } else { + ret = 0; + } + } + } + return ret; +} + +static int mysql_list_realm_options(u08bits *realm) { + int ret = 1; + donot_print_connection_success = 1; + char statement[TURN_LONG_STRING_SIZE]; + MYSQL * myc = get_mydb_connection(); + if(myc) { + if(realm && realm[0]) { + snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option where realm='%s' order by realm,opt",realm); + } else { + snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option order by realm,opt"); + } + 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)!=3) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement); + } else { + for(;;) { + MYSQL_ROW row = mysql_fetch_row(mres); + if(!row) { + break; + } else { + if(row[0] && row[1] && row[2]) { + printf("%s[%s]=%s\n",row[1],row[0],row[2]); + } + } + } + ret = 0; + } + + if(mres) + mysql_free_result(mres); + } + } + return ret; +} + +static void mysql_auth_ping(void * rch) { + UNUSED_ARG(rch); + donot_print_connection_success = 1; + MYSQL * myc = get_mydb_connection(); + if(myc) { + char statement[TURN_LONG_STRING_SIZE]; + STRCPY(statement,"select value from turn_secret"); + 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 { + mysql_free_result(mres); + } + } + } +} + +static int mysql_get_ip_list(const char *kind, ip_range_list_t * list) { + int ret = 1; + MYSQL * myc = get_mydb_connection(); + if(myc) { + char statement[TURN_LONG_STRING_SIZE]; + snprintf(statement,sizeof(statement),"select ip_range from %s_peer_ip",kind); + int res = mysql_query(myc, statement); + if(res == 0) { + MYSQL_RES *mres = mysql_store_result(myc); + if(mres && mysql_field_count(myc)==1) { + for(;;) { + MYSQL_ROW row = mysql_fetch_row(mres); + if(!row) { + break; + } else { + if(row[0]) { + unsigned long *lengths = mysql_fetch_lengths(mres); + if(lengths) { + size_t sz = lengths[0]; + char kval[TURN_LONG_STRING_SIZE]; + ns_bcopy(row[0],kval,sz); + kval[sz]=0; + add_ip_list_range(kval,list); + } + } + } + } + ret = 0; + } + + if(mres) + mysql_free_result(mres); + } + } + return ret; +} + +static void mysql_reread_realms(secrets_list_t * realms_list) { + MYSQL * myc = get_mydb_connection(); + if(myc) { + char statement[TURN_LONG_STRING_SIZE]; + { + snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm"); + int res = mysql_query(myc, statement); + if(res == 0) { + MYSQL_RES *mres = mysql_store_result(myc); + if(mres && mysql_field_count(myc)==2) { + + ur_string_map *o_to_realm_new = ur_string_map_create(free); + + for(;;) { + MYSQL_ROW row = mysql_fetch_row(mres); + if(!row) { + break; + } else { + if(row[0] && row[1]) { + unsigned long *lengths = mysql_fetch_lengths(mres); + if(lengths) { + size_t sz = lengths[0]; + char oval[513]; + ns_bcopy(row[0],oval,sz); + oval[sz]=0; + char *rval=strdup(row[1]); + get_realm(rval); + ur_string_map_value_type value = strdup(rval); + ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) oval, value); + } + } + } + } + + update_o_to_realm(o_to_realm_new); + } + + if(mres) + mysql_free_result(mres); + } + } + { + size_t i = 0; + size_t rlsz = 0; + + lock_realms(); + rlsz = realms_list->sz; + unlock_realms(); + + for (i = 0; isecrets[i]; + + realm_params_t* rp = get_realm(realm); + + lock_realms(); + rp->options.perf_options.max_bps = turn_params.max_bps; + unlock_realms(); + + lock_realms(); + rp->options.perf_options.total_quota = turn_params.total_quota; + unlock_realms(); + + lock_realms(); + rp->options.perf_options.user_quota = turn_params.user_quota; + unlock_realms(); + + } + } + + snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option"); + int res = mysql_query(myc, statement); + if(res == 0) { + MYSQL_RES *mres = mysql_store_result(myc); + if(mres && mysql_field_count(myc)==3) { + + for(;;) { + MYSQL_ROW row = mysql_fetch_row(mres); + if(!row) { + break; + } else { + if(row[0] && row[1] && row[2]) { + unsigned long *lengths = mysql_fetch_lengths(mres); + if(lengths) { + char rval[513]; + size_t sz = lengths[0]; + ns_bcopy(row[0],rval,sz); + rval[sz]=0; + char oval[513]; + sz = lengths[1]; + ns_bcopy(row[1],oval,sz); + oval[sz]=0; + char vval[513]; + sz = lengths[2]; + ns_bcopy(row[2],vval,sz); + vval[sz]=0; + realm_params_t* rp = get_realm(rval); + if(!strcmp(oval,"max-bps")) + rp->options.perf_options.max_bps = (band_limit_t)atol(vval); + else if(!strcmp(oval,"total-quota")) + rp->options.perf_options.total_quota = (vint)atoi(vval); + else if(!strcmp(oval,"user-quota")) + rp->options.perf_options.user_quota = (vint)atoi(vval); + else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", oval); + } + } + } + } + } + } + + if(mres) + mysql_free_result(mres); + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static 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_del_secret, + &mysql_set_secret, + &mysql_add_origin, + &mysql_del_origin, + &mysql_list_origins, + &mysql_set_realm_option_one, + &mysql_list_realm_options, + &mysql_auth_ping, + &mysql_get_ip_list, + &mysql_reread_realms +}; + +turn_dbdriver_t * get_mysql_dbdriver(void) { + return &driver; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#else + +turn_dbdriver_t * get_mysql_dbdriver(void) { + return NULL; +} + +#endif diff --git a/src/apps/relay/dbdrivers/dbd_mysql.h b/src/apps/relay/dbdrivers/dbd_mysql.h new file mode 100644 index 00000000..91b15906 --- /dev/null +++ b/src/apps/relay/dbdrivers/dbd_mysql.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011, 2012, 2013 Citrix Systems + * Copyright (C) 2014 Vivocha S.p.A. + * + * 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 __DBD_MYSQL__ +#define __DBD_MYSQL__ + +#include "dbdriver.h" + +#ifdef __cplusplus +extern "C" { +#endif + +turn_dbdriver_t * get_mysql_dbdriver(void); + +#ifdef __cplusplus +} +#endif + +#endif +/// __DBD_MYSQL__/// + diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c new file mode 100644 index 00000000..d688e1c7 --- /dev/null +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -0,0 +1,668 @@ +/* + * Copyright (C) 2011, 2012, 2013 Citrix Systems + * Copyright (C) 2014 Vivocha S.p.A. + * + * 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. + */ + +#include "../mainrelay.h" +#include "dbd_pgsql.h" + +#if !defined(TURN_NO_PQ) +#include + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static int donot_print_connection_success = 0; + +static PGconn *get_pqdb_connection(void) { + persistent_users_db_t *pud = get_persistent_users_db(); + + PGconn *pqdbconnection = (PGconn*)(pud->connection); + if(pqdbconnection) { + ConnStatusType status = PQstatus(pqdbconnection); + if(status != CONNECTION_OK) { + PQfinish(pqdbconnection); + pqdbconnection = NULL; + } + } + if(!pqdbconnection) { + char *errmsg=NULL; + PQconninfoOption *co = PQconninfoParse(pud->userdb, &errmsg); + if(!co) { + if(errmsg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg); + turn_free(errmsg,strlen(errmsg)+1); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, unknown connection string format error\n",pud->userdb); + } + } else { + PQconninfoFree(co); + if(errmsg) + turn_free(errmsg,strlen(errmsg)+1); + pqdbconnection = PQconnectdb(pud->userdb); + if(!pqdbconnection) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb); + } else { + ConnStatusType status = PQstatus(pqdbconnection); + if(status != CONNECTION_OK) { + PQfinish(pqdbconnection); + pqdbconnection = NULL; + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb); + } else if(!donot_print_connection_success){ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "PostgreSQL DB connection success: %s\n",pud->userdb); + } + } + } + pud->connection = pqdbconnection; + } + return pqdbconnection; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static int pgsql_get_auth_secrets(secrets_list_t *sl, u08bits *realm) { + int ret = 1; + PGconn * pqc = get_pqdb_connection(); + if(pqc) { + char statement[TURN_LONG_STRING_SIZE]; + snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm); + 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; + for(i=0;i> %s\n",oval,rval); + } + } + } + ret = 0; + } + if(res) { + PQclear(res); + } + } + return ret; +} + +static int pgsql_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) { + int ret = 1; + char statement[TURN_LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if(pqc) { + { + snprintf(statement,sizeof(statement),"delete from turn_realm_option where realm='%s' and opt='%s'",realm,opt); + PGresult *res = PQexec(pqc, statement); + if(res) { + PQclear(res); + } + } + if(value>0) { + snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%lu')",realm,opt,(unsigned long)value); + PGresult *res = PQexec(pqc, statement); + if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting realm option information: %s\n",PQerrorMessage(pqc)); + } else { + ret = 0; + } + if(res) { + PQclear(res); + } + } + } + return ret; +} + +static int pgsql_list_realm_options(u08bits *realm) { + int ret = 1; + donot_print_connection_success = 1; + char statement[TURN_LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if(pqc) { + if(realm && realm[0]) { + snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option where realm='%s' order by realm,opt",realm); + } else { + snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option order by realm,opt"); + } + 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; + for(i=0;isz; + unlock_realms(); + + for (i = 0; isecrets[i]; + + realm_params_t* rp = get_realm(realm); + + lock_realms(); + rp->options.perf_options.max_bps = turn_params.max_bps; + unlock_realms(); + + lock_realms(); + rp->options.perf_options.total_quota = turn_params.total_quota; + unlock_realms(); + + lock_realms(); + rp->options.perf_options.user_quota = turn_params.user_quota; + unlock_realms(); + + } + } + + snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option"); + PGresult *res = PQexec(pqc, statement); + + if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) { + + int i = 0; + for(i=0;ioptions.perf_options.max_bps = (band_limit_t)atol(vval); + else if(!strcmp(oval,"total-quota")) + rp->options.perf_options.total_quota = (vint)atoi(vval); + else if(!strcmp(oval,"user-quota")) + rp->options.perf_options.user_quota = (vint)atoi(vval); + else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", oval); + } + } + } + } + + if(res) { + PQclear(res); + } + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static 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_del_secret, + &pgsql_set_secret, + &pgsql_add_origin, + &pgsql_del_origin, + &pgsql_list_origins, + &pgsql_set_realm_option_one, + &pgsql_list_realm_options, + &pgsql_auth_ping, + &pgsql_get_ip_list, + &pgsql_reread_realms +}; + +turn_dbdriver_t * get_pgsql_dbdriver(void) { + return &driver; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#else + +turn_dbdriver_t * get_pgsql_dbdriver(void) { + return NULL; +} + +#endif diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.h b/src/apps/relay/dbdrivers/dbd_pgsql.h new file mode 100644 index 00000000..7c36e66e --- /dev/null +++ b/src/apps/relay/dbdrivers/dbd_pgsql.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011, 2012, 2013 Citrix Systems + * Copyright (C) 2014 Vivocha S.p.A. + * + * 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 __DBD_POSTGRESQL__ +#define __DBD_POSTGRESQL__ + +#include "dbdriver.h" + +#ifdef __cplusplus +extern "C" { +#endif + +turn_dbdriver_t * get_pgsql_dbdriver(void); + +#ifdef __cplusplus +} +#endif + +#endif +/// __DBD_POSTGRESQL__/// + diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c new file mode 100644 index 00000000..4a8e900a --- /dev/null +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -0,0 +1,1150 @@ +/* + * Copyright (C) 2011, 2012, 2013 Citrix Systems + * Copyright (C) 2014 Vivocha S.p.A. + * + * 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. + */ + +#include "../mainrelay.h" +#include "dbd_redis.h" + +#if !defined(TURN_NO_HIREDIS) +#include "hiredis_libevent2.h" +#include + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static int donot_print_connection_success = 0; + +static void turnFreeRedisReply(void *reply) { + if(reply) { + freeReplyObject(reply); + } +} + +struct _Ryconninfo { + char *host; + char *dbname; + char *password; + unsigned int connect_timeout; + unsigned int port; +}; + +typedef struct _Ryconninfo Ryconninfo; + +static void RyconninfoFree(Ryconninfo *co) { + if(co) { + if(co->host) turn_free(co->host, strlen(co->host)+1); + if(co->dbname) turn_free(co->dbname, strlen(co->username)+1); + if(co->password) turn_free(co->password, strlen(co->password)+1); + ns_bzero(co,sizeof(Ryconninfo)); + } +} + +static Ryconninfo *RyconninfoParse(const char *userdb, char **errmsg) { + Ryconninfo *co = (Ryconninfo*) turn_malloc(sizeof(Ryconninfo)); + ns_bzero(co,sizeof(Ryconninfo)); + if (userdb) { + char *s0 = strdup(userdb); + char *s = s0; + + while (s && *s) { + + while (*s && (*s == ' ')) + ++s; + char *snext = strstr(s, " "); + if (snext) { + *snext = 0; + ++snext; + } + + char* seq = strstr(s, "="); + if (!seq) { + RyconninfoFree(co); + co = NULL; + if (errmsg) { + *errmsg = strdup(s); + } + break; + } + + *seq = 0; + if (!strcmp(s, "host")) + co->host = strdup(seq + 1); + else if (!strcmp(s, "ip")) + co->host = strdup(seq + 1); + else if (!strcmp(s, "addr")) + co->host = strdup(seq + 1); + else if (!strcmp(s, "ipaddr")) + co->host = strdup(seq + 1); + else if (!strcmp(s, "hostaddr")) + co->host = strdup(seq + 1); + else if (!strcmp(s, "dbname")) + co->dbname = strdup(seq + 1); + else if (!strcmp(s, "db")) + co->dbname = strdup(seq + 1); + else if (!strcmp(s, "database")) + co->dbname = strdup(seq + 1); + else if (!strcmp(s, "user")) + ; + else if (!strcmp(s, "uname")) + ; + else if (!strcmp(s, "name")) + ; + else if (!strcmp(s, "username")) + ; + else if (!strcmp(s, "password")) + co->password = strdup(seq + 1); + else if (!strcmp(s, "pwd")) + co->password = strdup(seq + 1); + else if (!strcmp(s, "passwd")) + co->password = strdup(seq + 1); + else if (!strcmp(s, "secret")) + co->password = strdup(seq + 1); + else if (!strcmp(s, "port")) + co->port = (unsigned int) atoi(seq + 1); + else if (!strcmp(s, "p")) + co->port = (unsigned int) atoi(seq + 1); + else if (!strcmp(s, "connect_timeout")) + co->connect_timeout = (unsigned int) atoi(seq + 1); + else if (!strcmp(s, "timeout")) + co->connect_timeout = (unsigned int) atoi(seq + 1); + else { + RyconninfoFree(co); + co = NULL; + if (errmsg) { + *errmsg = strdup(s); + } + break; + } + + s = snext; + } + + turn_free(s0, strlen(s0)+1); + } + + if(!(co->dbname)) + co->dbname=strdup("0"); + if(!(co->host)) + co->host=strdup("127.0.0.1"); + if(!(co->password)) + co->password=strdup(""); + + return co; +} + +redis_context_handle get_redis_async_connection(struct event_base *base, const char* connection_string, int delete_keys) { + redis_context_handle ret = NULL; + + char *errmsg = NULL; + if(base && connection_string && connection_string[0]) { + Ryconninfo *co = RyconninfoParse(connection_string, &errmsg); + if (!co) { + if (errmsg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", connection_string, errmsg); + turn_free(errmsg,strlen(errmsg)+1); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error\n", connection_string); + } + } else if (errmsg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", connection_string, errmsg); + turn_free(errmsg,strlen(errmsg)+1); + RyconninfoFree(co); + } else { + + if(delete_keys) { + + redisContext *rc = NULL; + + char ip[256] = "\0"; + int port = DEFAULT_REDIS_PORT; + if (co->host) + STRCPY(ip,co->host); + if (!ip[0]) + STRCPY(ip,"127.0.0.1"); + + if (co->port) + port = (int) (co->port); + + if (co->connect_timeout) { + struct timeval tv; + tv.tv_usec = 0; + tv.tv_sec = (time_t) (co->connect_timeout); + rc = redisConnectWithTimeout(ip, port, tv); + } else { + rc = redisConnect(ip, port); + } + + if (!rc) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB async connection\n"); + } else { + if (co->password) { + turnFreeRedisReply(redisCommand(rc, "AUTH %s", co->password)); + } + if (co->dbname) { + turnFreeRedisReply(redisCommand(rc, "select %s", co->dbname)); + } + { + redisReply *reply = (redisReply*)redisCommand(rc, "keys turn/*/allocation/*/status"); + if(reply) { + secrets_list_t keys; + size_t isz = 0; + char s[513]; + + init_secrets_list(&keys); + + 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); + } + } + + for(isz=0;iszhost, co->port, co->password, atoi(co->dbname)); + + if (!ret) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB connection\n"); + } else if (is_redis_asyncconn_good(ret) && !donot_print_connection_success) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis DB async connection to be used: %s\n", connection_string); + } + RyconninfoFree(co); + } + } + + return ret; +} + +static redisContext *get_redis_connection(void) { + persistent_users_db_t *pud = get_persistent_users_db(); + + redisContext *redisconnection = (redisContext*)(pud->connection); + + if(redisconnection) { + if(redisconnection->err) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot connect to redis, err=%d, flags=0x%x\n", __FUNCTION__,(int)redisconnection->err,(unsigned long)redisconnection->flags); + redisFree(redisconnection); + pud->connection = NULL; + redisconnection = NULL; + } + } + + if (!redisconnection) { + + char *errmsg = NULL; + Ryconninfo *co = RyconninfoParse(pud->userdb, &errmsg); + if (!co) { + if (errmsg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", pud->userdb, errmsg); + turn_free(errmsg,strlen(errmsg)+1); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error\n", pud->userdb); + } + } else if (errmsg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", pud->userdb, errmsg); + turn_free(errmsg,strlen(errmsg)+1); + RyconninfoFree(co); + } else { + char ip[256] = "\0"; + int port = DEFAULT_REDIS_PORT; + if (co->host) + STRCPY(ip,co->host); + if (!ip[0]) + STRCPY(ip,"127.0.0.1"); + + if (co->port) + port = (int) (co->port); + + if (co->connect_timeout) { + struct timeval tv; + tv.tv_usec = 0; + tv.tv_sec = (time_t) (co->connect_timeout); + redisconnection = redisConnectWithTimeout(ip, port, tv); + } else { + redisconnection = redisConnect(ip, port); + } + + if (redisconnection) { + if(redisconnection->err) { + if(redisconnection->errstr[0]) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis: %s\n",redisconnection->errstr); + } + redisFree(redisconnection); + redisconnection = NULL; + } else if (co->password) { + void *reply = redisCommand(redisconnection, "AUTH %s", co->password); + if(!reply) { + if(redisconnection->err && redisconnection->errstr[0]) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis: %s\n",redisconnection->errstr); + } + redisFree(redisconnection); + redisconnection = NULL; + } else { + turnFreeRedisReply(reply); + if (co->dbname) { + reply = redisCommand(redisconnection, "select %s", co->dbname); + if(!reply) { + if(redisconnection->err && redisconnection->errstr[0]) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis: %s\n",redisconnection->errstr); + } + redisFree(redisconnection); + redisconnection = NULL; + } else { + turnFreeRedisReply(reply); + } + } + } + } + } + + if (!redisconnection) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB connection\n"); + } else if (!donot_print_connection_success) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis DB sync connection success: %s\n", pud->userdb); + } + + RyconninfoFree(co); + } + pud->connection = redisconnection; + + pud = get_persistent_users_db(); + + redisconnection = (redisContext*)(pud->connection); + } + + return redisconnection; +} + +static int set_redis_realm_opt(char *realm, const char* key, unsigned long *value) +{ + int found = 0; + + redisContext *rc = get_redis_connection(); + + if(rc) { + redisReply *rget = NULL; + + char s[1025]; + + snprintf(s, sizeof(s), "get turn/realm/%s/%s", realm, key); + + 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 { + lock_realms(); + *value = (unsigned long)atol(rget->str); + unlock_realms(); + found = 1; + } + turnFreeRedisReply(rget); + } + } + + return found; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static int redis_get_auth_secrets(secrets_list_t *sl, u08bits *realm) { + int ret = 1; + redisContext *rc = get_redis_connection(); + if(rc) { + redisReply *reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/secret/*", (char*)realm); + if(reply) { + + secrets_list_t keys; + size_t isz = 0; + char s[257]; + + init_secrets_list(&keys); + + 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); + } + } + + for(isz=0;isztype == 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 { + add_to_secrets_list(sl,rget->str); + } + turnFreeRedisReply(rget); + } + } + + clean_secrets_list(&keys); + + ret = 0; + + turnFreeRedisReply(reply); + } + } + return ret; +} + +static int redis_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) { + int ret = 1; + redisContext * rc = get_redis_connection(); + if(rc) { + char s[TURN_LONG_STRING_SIZE]; + snprintf(s,sizeof(s),"get turn/realm/%s/user/%s/key", (char*)realm, 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 { + size_t sz = get_hmackey_size(turn_params.shatype); + if(strlen(rget->str)str,usname); + } else if(convert_string_key_to_binary(rget->str, key, sz)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key: %s, user %s\n",rget->str,usname); + } else { + ret = 0; + } + } + 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; +} + +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)); + turnFreeRedisReply(redisCommand(rc, "save")); + ret = 0; + } + return ret; +} + +static int redis_set_user_pwd(u08bits *usname, st_password_t pwd) { + 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")); + ret = 0; + } + return ret; +} + +static int redis_list_users(int is_st, u08bits *realm) { + int ret = 1; + redisContext *rc = get_redis_connection(); + if(rc) { + secrets_list_t keys; + size_t isz = 0; + + init_secrets_list(&keys); + + 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) + 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); + } + + 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); + } + } + + for(isz=0;isztype == 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); + } + } + + for(isz=0;isztype == 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 { + printf("%s\n",rget->str); + } + } + turnFreeRedisReply(rget); + } + + clean_secrets_list(&keys); + + turnFreeRedisReply(reply); + ret = 0; + } + } + return ret; +} + +static int redis_del_secret(u08bits *secret, u08bits *realm) { + int ret = 1; + donot_print_connection_success = 1; + redisContext *rc = get_redis_connection(); + if(rc) { + redisReply *reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/secret/*", (char*)realm); + if(reply) { + secrets_list_t keys; + size_t isz = 0; + char s[TURN_LONG_STRING_SIZE]; + + init_secrets_list(&keys); + + 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); + } + } + + for(isz=0;isztype == 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(!strcmp((char*)secret,rget->str)) { + snprintf(s,sizeof(s),"del %s", keys.secrets[isz]); + turnFreeRedisReply(redisCommand(rc, s)); + } + } + turnFreeRedisReply(rget); + } + } + } + + turnFreeRedisReply(redisCommand(rc, "save")); + + clean_secrets_list(&keys); + + turnFreeRedisReply(reply); + ret = 0; + } + } + return ret; +} + +static int redis_set_secret(u08bits *secret, u08bits *realm) { + int ret = 1; + donot_print_connection_success = 1; + redisContext *rc = get_redis_connection(); + if(rc) { + char s[TURN_LONG_STRING_SIZE]; + + redis_del_secret(secret, realm); + + snprintf(s,sizeof(s),"set turn/realm/%s/secret/%lu %s", (char*)realm, (unsigned long)turn_time(), secret); + + turnFreeRedisReply(redisCommand(rc, s)); + turnFreeRedisReply(redisCommand(rc, "save")); + ret = 0; + } + return ret; +} + +static int redis_add_origin(u08bits *origin, u08bits *realm) { + int ret = 1; + redisContext *rc = get_redis_connection(); + if(rc) { + char s[TURN_LONG_STRING_SIZE]; + + snprintf(s,sizeof(s),"set turn/origin/%s %s", (char*)origin, (char*)realm); + + turnFreeRedisReply(redisCommand(rc, s)); + turnFreeRedisReply(redisCommand(rc, "save")); + ret = 0; + } + return ret; +} + +static int redis_del_origin(u08bits *origin) { + int ret = 1; + redisContext *rc = get_redis_connection(); + if(rc) { + char s[TURN_LONG_STRING_SIZE]; + + snprintf(s,sizeof(s),"del turn/origin/%s", (char*)origin); + + turnFreeRedisReply(redisCommand(rc, s)); + turnFreeRedisReply(redisCommand(rc, "save")); + ret = 0; + } + return ret; +} + +static int redis_list_origins(u08bits *realm) { + int ret = 1; + donot_print_connection_success = 1; + redisContext *rc = get_redis_connection(); + if(rc) { + secrets_list_t keys; + size_t isz = 0; + + init_secrets_list(&keys); + + redisReply *reply = NULL; + + { + reply = (redisReply*)redisCommand(rc, "keys turn/origin/*"); + 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; + size_t offset = strlen("turn/origin/"); + for (i = 0; i < reply->elements; ++i) { + add_to_secrets_list(&keys,reply->element[i]->str+offset); + } + } + turnFreeRedisReply(reply); + } + } + + for(isz=0;isztype == REDIS_REPLY_ERROR) + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str); + else if (reply->type != REDIS_REPLY_STRING) { + if (reply->type != REDIS_REPLY_NIL) + 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); + } + } + turnFreeRedisReply(reply); + } + } + + clean_secrets_list(&keys); + ret = 0; + } + return ret; +} + +static int redis_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) { + int ret = 1; + redisContext *rc = get_redis_connection(); + if(rc) { + char s[TURN_LONG_STRING_SIZE]; + + if(value>0) + snprintf(s,sizeof(s),"set turn/realm/%s/%s %lu", (char*)realm, opt, (unsigned long)value); + else + snprintf(s,sizeof(s),"del turn/realm/%s/%s", (char*)realm, opt); + + turnFreeRedisReply(redisCommand(rc, s)); + turnFreeRedisReply(redisCommand(rc, "save")); + ret = 0; + } + return ret; +} + +static int redis_list_realm_options(u08bits *realm) { + int ret = 1; + donot_print_connection_success = 1; + redisContext *rc = get_redis_connection(); + if(rc) { + secrets_list_t keys; + size_t isz = 0; + + init_secrets_list(&keys); + + redisReply *reply = NULL; + + { + if(realm && realm[0]) { + reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/*",realm); + } else { + reply = (redisReply*)redisCommand(rc, "keys turn/realm/*"); + } + 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) { + if(strstr(reply->element[i]->str,"/max-bps")|| + strstr(reply->element[i]->str,"/total-quota")|| + strstr(reply->element[i]->str,"/user-quota")) { + add_to_secrets_list(&keys,reply->element[i]->str); + } + } + } + turnFreeRedisReply(reply); + } + } + + size_t offset = strlen("turn/realm/"); + + for(isz=0;isztype == REDIS_REPLY_ERROR) + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str); + else if (reply->type != REDIS_REPLY_STRING) { + if (reply->type != REDIS_REPLY_NIL) + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type); + } else { + printf("%s = %s\n",o+offset,reply->str); + } + turnFreeRedisReply(reply); + } + } + + clean_secrets_list(&keys); + ret = 0; + } + return ret; +} + +static void redis_auth_ping(void * rch) { + donot_print_connection_success = 1; + redisContext *rc = get_redis_connection(); + if(rc) { + turnFreeRedisReply(redisCommand(rc, "keys turn/origin/*")); + } + if(rch) + send_message_to_redis((redis_context_handle)rch, "publish", "__XXX__", "__YYY__"); +} + +static int redis_get_ip_list(const char *kind, ip_range_list_t * list) { + int ret = 1; + redisContext *rc = get_redis_connection(); + if(rc) { + char statement[TURN_LONG_STRING_SIZE]; + snprintf(statement,sizeof(statement),"keys turn/%s-peer-ip/*", kind); + redisReply *reply = (redisReply*)redisCommand(rc, statement); + if(reply) { + secrets_list_t keys; + size_t isz = 0; + char s[257]; + + init_secrets_list(&keys); + + 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); + } + } + + for(isz=0;isztype == 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 { + add_ip_list_range(rget->str,list); + } + turnFreeRedisReply(rget); + } + } + + clean_secrets_list(&keys); + + turnFreeRedisReply(reply); + ret = 0; + } + } + return ret; +} + +static void redis_reread_realms(secrets_list_t * realms_list) { + redisContext *rc = get_redis_connection(); + if (rc) { + + redisReply *reply = (redisReply*) redisCommand(rc, "keys turn/origin/*"); + if (reply) { + + ur_string_map *o_to_realm_new = ur_string_map_create(free); + + secrets_list_t keys; + + init_secrets_list(&keys); + + size_t isz = 0; + + char s[1025]; + + 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); + } + } + + size_t offset = strlen("turn/origin/"); + + for (isz = 0; isz < keys.sz; ++isz) { + char *origin = keys.secrets[isz] + offset; + snprintf(s, sizeof(s), "get %s", keys.secrets[isz]); + 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 { + get_realm(rget->str); + ur_string_map_value_type value = strdup(rget->str); + ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) origin, value); + } + turnFreeRedisReply(rget); + } + } + + clean_secrets_list(&keys); + + update_o_to_realm(o_to_realm_new); + + turnFreeRedisReply(reply); + } + + { + size_t i = 0; + size_t rlsz = 0; + + lock_realms(); + rlsz = realms_list->sz; + unlock_realms(); + + for (i = 0; isecrets[i]; + realm_params_t* rp = get_realm(realm); + unsigned long value = 0; + if(!set_redis_realm_opt(realm,"max-bps",&value)) { + lock_realms(); + rp->options.perf_options.max_bps = turn_params.max_bps; + unlock_realms(); + } + rp->options.perf_options.max_bps = (band_limit_t)value; + if(!set_redis_realm_opt(realm,"total-quota",&value)) { + lock_realms(); + rp->options.perf_options.total_quota = turn_params.total_quota; + unlock_realms(); + } + rp->options.perf_options.total_quota = (vint)value; + if(!set_redis_realm_opt(realm,"user-quota",&value)) { + lock_realms(); + rp->options.perf_options.user_quota = turn_params.user_quota; + unlock_realms(); + } + rp->options.perf_options.user_quota = (vint)value; + } + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static 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_del_secret, + &redis_set_secret, + &redis_add_origin, + &redis_del_origin, + &redis_list_origins, + &redis_set_realm_option_one, + &redis_list_realm_options, + &redis_auth_ping, + &redis_get_ip_list, + &redis_reread_realms +}; + +turn_dbdriver_t * get_redis_dbdriver(void) { + return &driver; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#else + +turn_dbdriver_t * get_redis_dbdriver(void) { + return NULL; +} + +#endif diff --git a/src/apps/relay/dbdrivers/dbd_redis.h b/src/apps/relay/dbdrivers/dbd_redis.h new file mode 100644 index 00000000..6ba27b9f --- /dev/null +++ b/src/apps/relay/dbdrivers/dbd_redis.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011, 2012, 2013 Citrix Systems + * Copyright (C) 2014 Vivocha S.p.A. + * + * 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 __DBD_REDIS__ +#define __DBD_REDIS__ + +#include "dbdriver.h" + +#ifdef __cplusplus +extern "C" { +#endif + +turn_dbdriver_t * get_redis_dbdriver(void); + +#ifdef __cplusplus +} +#endif + +#endif +/// __DBD_REDIS__/// + diff --git a/src/apps/relay/dbdrivers/dbdriver.c b/src/apps/relay/dbdrivers/dbdriver.c new file mode 100644 index 00000000..807ad715 --- /dev/null +++ b/src/apps/relay/dbdrivers/dbdriver.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2011, 2012, 2013 Citrix Systems + * Copyright (C) 2014 Vivocha S.p.A. + * + * 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. + */ + +#include "../mainrelay.h" +#include "dbdriver.h" +#include "dbd_pgsql.h" +#include "dbd_mysql.h" +#include "dbd_mongo.h" +#include "dbd_redis.h" + +static turn_dbdriver_t * _driver; + +int convert_string_key_to_binary(char* keysource, hmackey_t key, size_t sz) { + char is[3]; + size_t i; + unsigned int v; + is[2]=0; + for(i=0;i dbname= user= \\\n password= port= connect_timeout=\".\n" " All parameters are optional.\n" #endif +#if !defined(TURN_NO_MONGO) +" -J, --mongo-userdb 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" +" 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 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" @@ -557,7 +562,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" " -D, --delete-st delete a short-term mechanism user\n" " -l, --list list all long-term mechanism users\n" " -L, --list-st list all short-term mechanism users\n" -#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_HIREDIS) +#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS) " -s, --set-secret= Add shared secret for TURN RESP API\n" " -S, --show-secret Show stored shared secrets for TURN REST API\n" " -X, --delete-secret= Delete a shared secret\n" @@ -576,13 +581,16 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" #if !defined(TURN_NO_MYSQL) " -M, --mysql-userdb MySQL user database connection string, if MySQL DB is used.\n" #endif +#if !defined(TURN_NO_MONGO) + " -J, --mongo-userdb MongoDB user database connection string, if MongoDB is used.\n" +#endif #if !defined(TURN_NO_HIREDIS) " -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" " -p, --password Password\n" -#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_HIREDIS) +#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS) " -o, --origin Origin\n" #endif " -H, --sha256 Use SHA256 digest function to be used for the message integrity.\n" @@ -595,9 +603,9 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" " Setting to zero value means removal of the option.\n" " -h, --help Help\n"; -#define OPTIONS "c:d:p:L:E:X:i:m:l:r:u:b:B:e:M:N:O:q:Q:s:C:vVofhznaAS" - -#define ADMIN_OPTIONS "gGORIHlLkaADSdb:e:M:N:u:r:p:s:X:o:h" +#define OPTIONS "c:d:p:L:E:X:i:m:l:r:u:b:B:e:M:J:N:O:q:Q:s:C:vVofhznaAS" + +#define ADMIN_OPTIONS "gGORIHlLkaADSdb:e:M:J:N:u:r:p:s:X:o:h" enum EXTRA_OPTS { NO_UDP_OPT=256, @@ -701,6 +709,9 @@ static const struct myoption long_options[] = { #if !defined(TURN_NO_MYSQL) { "mysql-userdb", required_argument, NULL, 'M' }, #endif +#if !defined(TURN_NO_MONGO) + { "mongo-userdb", required_argument, NULL, 'J' }, +#endif #if !defined(TURN_NO_HIREDIS) { "redis-userdb", required_argument, NULL, 'N' }, { "redis-statsdb", required_argument, NULL, 'O' }, @@ -776,7 +787,7 @@ static const struct myoption admin_long_options[] = { { "delete", no_argument, NULL, 'd' }, { "list", no_argument, NULL, 'l' }, { "list-st", no_argument, NULL, 'L' }, -#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_HIREDIS) +#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS) { "set-secret", required_argument, NULL, 's' }, { "show-secret", no_argument, NULL, 'S' }, { "delete-secret", required_argument, NULL, 'X' }, @@ -792,6 +803,9 @@ static const struct myoption admin_long_options[] = { #if !defined(TURN_NO_MYSQL) { "mysql-userdb", required_argument, NULL, 'M' }, #endif +#if !defined(TURN_NO_MONGO) + { "mongo-userdb", required_argument, NULL, 'J' }, +#endif #if !defined(TURN_NO_HIREDIS) { "redis-userdb", required_argument, NULL, 'N' }, #endif @@ -799,7 +813,7 @@ static const struct myoption admin_long_options[] = { { "realm", required_argument, NULL, 'r' }, { "password", required_argument, NULL, 'p' }, { "sha256", no_argument, NULL, 'H' }, -#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_HIREDIS) +#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS) { "add-origin", no_argument, NULL, 'O' }, { "del-origin", no_argument, NULL, 'R' }, { "list-origins", required_argument, NULL, 'I' }, @@ -1086,6 +1100,12 @@ static void set_option(int c, char *value) turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MYSQL; break; #endif +#if !defined(TURN_NO_MONGO) + case 'J': + STRCPY(turn_params.default_users_db.persistent_users_db.userdb, value); + turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MONGO; + break; +#endif #if !defined(TURN_NO_HIREDIS) case 'N': STRCPY(turn_params.default_users_db.persistent_users_db.userdb, value); @@ -1411,7 +1431,7 @@ static int adminmain(int argc, char **argv) ct = TA_LIST_USERS; is_st = 1; break; -#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_HIREDIS) +#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS) case 's': ct = TA_SET_SECRET; STRCPY(secret,optarg); @@ -1444,6 +1464,12 @@ static int adminmain(int argc, char **argv) turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MYSQL; break; #endif +#if !defined(TURN_NO_MONGO) + case 'J': + STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg); + turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MONGO; + break; +#endif #if !defined(TURN_NO_HIREDIS) case 'N': STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg); @@ -1558,6 +1584,12 @@ static void print_features(unsigned long mfn) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MySQL is not supported\n"); #endif +#if !defined(TURN_NO_MONGO) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MongoDB supported\n"); +#else + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MongoDB is not supported\n"); +#endif + #if defined(OPENSSL_THREADS) //TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL multithreading supported\n"); #else diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index e0ffb118..22b16902 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -83,8 +83,6 @@ #include "ns_ioalib_impl.h" -#include "hiredis_libevent2.h" - #ifdef __cplusplus extern "C" { #endif diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index e6dd2e9e..b25ce026 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -764,6 +764,11 @@ static void cli_print_configuration(struct cli_session* cs) cli_print_str(cs,"MySQL/MariaDB","DB type",0); break; #endif +#if !defined(TURN_NO_MONGO) + case TURN_USERDB_TYPE_MONGO: + cli_print_str(cs,"MongoDB","DB type",0); + break; +#endif #if !defined(TURN_NO_HIREDIS) case TURN_USERDB_TYPE_REDIS: cli_print_str(cs,"redis","DB type",0); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 953acd9b..59f75df6 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -39,19 +39,6 @@ #include #include -#if !defined(TURN_NO_PQ) -#include -#endif - -#if !defined(TURN_NO_MYSQL) -#include -#endif - -#if !defined(TURN_NO_HIREDIS) -#include "hiredis_libevent2.h" -#include -#endif - #include #include @@ -65,6 +52,7 @@ #include #include "userdb.h" +#include "dbdrivers/dbdriver.h" #include "mainrelay.h" #include "ns_turn_utils.h" @@ -74,12 +62,6 @@ #include "apputils.h" -//////////// USER DB ////////////////////////////// - -#define LONG_STRING_SIZE (TURN_LONG_STRING_SIZE) - -static int donot_print_connection_success=0; - //////////// REALM ////////////// static realm_params_t *default_realm_params_ptr = NULL; @@ -98,6 +80,21 @@ static turn_mutex o_to_realm_mutex; static ur_string_map *o_to_realm = NULL; static secrets_list_t realms_list; +void lock_realms(void) { + ur_string_map_lock(realms); +} + +void unlock_realms(void) { + ur_string_map_unlock(realms); +} + +void update_o_to_realm(ur_string_map * o_to_realm_new) { + TURN_MUTEX_LOCK(&o_to_realm_mutex); + ur_string_map_free(&o_to_realm); + o_to_realm = o_to_realm_new; + TURN_MUTEX_UNLOCK(&o_to_realm_mutex); +} + void create_new_realm(char* name) { realm_params_t *ret = NULL; @@ -319,626 +316,12 @@ void add_to_secrets_list(secrets_list_t *sl, const char* elem) } } -/////////// USER DB CHECK ////////////////// - -static persistent_users_db_t* get_persistent_users_db(void) -{ - return &(turn_params.default_users_db.persistent_users_db); -} - -static int convert_string_key_to_binary(char* keysource, hmackey_t key, size_t sz) { - { - char is[3]; - size_t i; - unsigned int v; - is[2]=0; - for(i=0;iconnection); - if(pqdbconnection) { - ConnStatusType status = PQstatus(pqdbconnection); - if(status != CONNECTION_OK) { - PQfinish(pqdbconnection); - pqdbconnection = NULL; - } - } - if(!pqdbconnection) { - char *errmsg=NULL; - PQconninfoOption *co = PQconninfoParse(pud->userdb, &errmsg); - if(!co) { - if(errmsg) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg); - turn_free(errmsg,strlen(errmsg)+1); - } else { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, unknown connection string format error\n",pud->userdb); - } - } else { - PQconninfoFree(co); - if(errmsg) - turn_free(errmsg,strlen(errmsg)+1); - pqdbconnection = PQconnectdb(pud->userdb); - if(!pqdbconnection) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb); - } else { - ConnStatusType status = PQstatus(pqdbconnection); - if(status != CONNECTION_OK) { - PQfinish(pqdbconnection); - pqdbconnection = NULL; - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb); - } else if(!donot_print_connection_success){ - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "PostgreSQL DB connection success: %s\n",pud->userdb); - } - } - } - pud->connection = pqdbconnection; - } - return pqdbconnection; -} - -#endif - -#if !defined(TURN_NO_MYSQL) - -struct _Myconninfo { - char *host; - char *dbname; - char *user; - char *password; - unsigned int port; - unsigned int connect_timeout; -}; - -typedef struct _Myconninfo Myconninfo; - -static void MyconninfoFree(Myconninfo *co) { - if(co) { - if(co->host) turn_free(co->host,strlen(co->host)+1); - if(co->dbname) turn_free(co->dbname, strlen(co->dbname)+1); - if(co->user) turn_free(co->user, strlen(co->user)+1); - if(co->password) turn_free(co->password, strlen(co->password)+1); - ns_bzero(co,sizeof(Myconninfo)); - } -} - -static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) -{ - Myconninfo *co = (Myconninfo*)turn_malloc(sizeof(Myconninfo)); - ns_bzero(co,sizeof(Myconninfo)); - if(userdb) { - char *s0=strdup(userdb); - char *s = s0; - - while(s && *s) { - - while(*s && (*s==' ')) ++s; - char *snext = strstr(s," "); - if(snext) { - *snext = 0; - ++snext; - } - - char* seq = strstr(s,"="); - if(!seq) { - MyconninfoFree(co); - co = NULL; - if(errmsg) { - *errmsg = strdup(s); - } - break; - } - - *seq = 0; - if(!strcmp(s,"host")) - co->host = strdup(seq+1); - else if(!strcmp(s,"ip")) - co->host = strdup(seq+1); - else if(!strcmp(s,"addr")) - co->host = strdup(seq+1); - else if(!strcmp(s,"ipaddr")) - co->host = strdup(seq+1); - else if(!strcmp(s,"hostaddr")) - co->host = strdup(seq+1); - else if(!strcmp(s,"dbname")) - co->dbname = strdup(seq+1); - else if(!strcmp(s,"db")) - co->dbname = strdup(seq+1); - else if(!strcmp(s,"database")) - co->dbname = strdup(seq+1); - else if(!strcmp(s,"user")) - co->user = strdup(seq+1); - else if(!strcmp(s,"uname")) - co->user = strdup(seq+1); - else if(!strcmp(s,"name")) - co->user = strdup(seq+1); - else if(!strcmp(s,"username")) - co->user = strdup(seq+1); - else if(!strcmp(s,"password")) - co->password = strdup(seq+1); - else if(!strcmp(s,"pwd")) - co->password = strdup(seq+1); - else if(!strcmp(s,"passwd")) - co->password = strdup(seq+1); - else if(!strcmp(s,"secret")) - co->password = strdup(seq+1); - else if(!strcmp(s,"port")) - co->port = (unsigned int)atoi(seq+1); - else if(!strcmp(s,"p")) - co->port = (unsigned int)atoi(seq+1); - else if(!strcmp(s,"connect_timeout")) - co->connect_timeout = (unsigned int)atoi(seq+1); - else if(!strcmp(s,"timeout")) - co->connect_timeout = (unsigned int)atoi(seq+1); - else { - MyconninfoFree(co); - co = NULL; - if(errmsg) { - *errmsg = strdup(s); - } - break; - } - - s = snext; - } - - turn_free(s0, strlen(s0)+1); - } - - if(!(co->dbname)) - co->dbname=strdup("0"); - if(!(co->host)) - co->host=strdup("127.0.0.1"); - if(!(co->user)) - co->user=strdup(""); - if(!(co->password)) - co->password=strdup(""); - - return co; -} - -static MYSQL *get_mydb_connection(void) -{ - - if(!is_mysql_userdb()) - return NULL; - - persistent_users_db_t *pud = get_persistent_users_db(); - - MYSQL *mydbconnection = (MYSQL*)(pud->connection); - - if(mydbconnection) { - if(mysql_ping(mydbconnection)) { - mysql_close(mydbconnection); - mydbconnection=NULL; - } - } - - if(!mydbconnection) { - char *errmsg=NULL; - Myconninfo *co=MyconninfoParse(pud->userdb, &errmsg); - if(!co) { - if(errmsg) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg); - turn_free(errmsg,strlen(errmsg)+1); - } else { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection <%s>, connection string format error\n",pud->userdb); - } - } else if(errmsg) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg); - turn_free(errmsg,strlen(errmsg)+1); - MyconninfoFree(co); - } else if(!(co->dbname)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "MySQL Database name is not provided: <%s>\n",pud->userdb); - MyconninfoFree(co); - } else { - mydbconnection = mysql_init(NULL); - if(!mydbconnection) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize MySQL DB connection\n"); - } else { - if(co->connect_timeout) - mysql_options(mydbconnection,MYSQL_OPT_CONNECT_TIMEOUT,&(co->connect_timeout)); - MYSQL *conn = mysql_real_connect(mydbconnection, co->host, co->user, co->password, co->dbname, co->port, NULL, CLIENT_IGNORE_SIGPIPE); - if(!conn) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection: <%s>, runtime error\n",pud->userdb); - mysql_close(mydbconnection); - mydbconnection=NULL; - } else if(mysql_select_db(mydbconnection, co->dbname)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot connect to MySQL DB: %s\n",co->dbname); - mysql_close(mydbconnection); - mydbconnection=NULL; - } else if(!donot_print_connection_success) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MySQL DB connection success: %s\n",pud->userdb); - } - } - MyconninfoFree(co); - } - pud->connection = mydbconnection; - } - return mydbconnection; -} - -#endif - - -#if !defined(TURN_NO_HIREDIS) - -static void turnFreeRedisReply(void *reply) -{ - if(reply) { - freeReplyObject(reply); - } -} - -struct _Ryconninfo { - char *host; - char *dbname; - char *password; - unsigned int connect_timeout; - unsigned int port; -}; - -typedef struct _Ryconninfo Ryconninfo; - -static void RyconninfoFree(Ryconninfo *co) { - if(co) { - if(co->host) turn_free(co->host, strlen(co->host)+1); - if(co->dbname) turn_free(co->dbname, strlen(co->username)+1); - if(co->password) turn_free(co->password, strlen(co->password)+1); - ns_bzero(co,sizeof(Ryconninfo)); - } -} - -static Ryconninfo *RyconninfoParse(const char *userdb, char **errmsg) -{ - Ryconninfo *co = (Ryconninfo*) turn_malloc(sizeof(Ryconninfo)); - ns_bzero(co,sizeof(Ryconninfo)); - if (userdb) { - char *s0 = strdup(userdb); - char *s = s0; - - while (s && *s) { - - while (*s && (*s == ' ')) - ++s; - char *snext = strstr(s, " "); - if (snext) { - *snext = 0; - ++snext; - } - - char* seq = strstr(s, "="); - if (!seq) { - RyconninfoFree(co); - co = NULL; - if (errmsg) { - *errmsg = strdup(s); - } - break; - } - - *seq = 0; - if (!strcmp(s, "host")) - co->host = strdup(seq + 1); - else if (!strcmp(s, "ip")) - co->host = strdup(seq + 1); - else if (!strcmp(s, "addr")) - co->host = strdup(seq + 1); - else if (!strcmp(s, "ipaddr")) - co->host = strdup(seq + 1); - else if (!strcmp(s, "hostaddr")) - co->host = strdup(seq + 1); - else if (!strcmp(s, "dbname")) - co->dbname = strdup(seq + 1); - else if (!strcmp(s, "db")) - co->dbname = strdup(seq + 1); - else if (!strcmp(s, "database")) - co->dbname = strdup(seq + 1); - else if (!strcmp(s, "user")) - ; - else if (!strcmp(s, "uname")) - ; - else if (!strcmp(s, "name")) - ; - else if (!strcmp(s, "username")) - ; - else if (!strcmp(s, "password")) - co->password = strdup(seq + 1); - else if (!strcmp(s, "pwd")) - co->password = strdup(seq + 1); - else if (!strcmp(s, "passwd")) - co->password = strdup(seq + 1); - else if (!strcmp(s, "secret")) - co->password = strdup(seq + 1); - else if (!strcmp(s, "port")) - co->port = (unsigned int) atoi(seq + 1); - else if (!strcmp(s, "p")) - co->port = (unsigned int) atoi(seq + 1); - else if (!strcmp(s, "connect_timeout")) - co->connect_timeout = (unsigned int) atoi(seq + 1); - else if (!strcmp(s, "timeout")) - co->connect_timeout = (unsigned int) atoi(seq + 1); - else { - RyconninfoFree(co); - co = NULL; - if (errmsg) { - *errmsg = strdup(s); - } - break; - } - - s = snext; - } - - turn_free(s0, strlen(s0)+1); - } - - if(!(co->dbname)) - co->dbname=strdup("0"); - if(!(co->host)) - co->host=strdup("127.0.0.1"); - if(!(co->password)) - co->password=strdup(""); - - return co; -} - -redis_context_handle get_redis_async_connection(struct event_base *base, const char* connection_string, int delete_keys) -{ - redis_context_handle ret = NULL; - - char *errmsg = NULL; - if(base && connection_string && connection_string[0]) { - Ryconninfo *co = RyconninfoParse(connection_string, &errmsg); - if (!co) { - if (errmsg) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", connection_string, errmsg); - turn_free(errmsg,strlen(errmsg)+1); - } else { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error\n", connection_string); - } - } else if (errmsg) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", connection_string, errmsg); - turn_free(errmsg,strlen(errmsg)+1); - RyconninfoFree(co); - } else { - - if(delete_keys) { - - redisContext *rc = NULL; - - char ip[256] = "\0"; - int port = DEFAULT_REDIS_PORT; - if (co->host) - STRCPY(ip,co->host); - if (!ip[0]) - STRCPY(ip,"127.0.0.1"); - - if (co->port) - port = (int) (co->port); - - if (co->connect_timeout) { - struct timeval tv; - tv.tv_usec = 0; - tv.tv_sec = (time_t) (co->connect_timeout); - rc = redisConnectWithTimeout(ip, port, tv); - } else { - rc = redisConnect(ip, port); - } - - if (!rc) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB async connection\n"); - } else { - if (co->password) { - turnFreeRedisReply(redisCommand(rc, "AUTH %s", co->password)); - } - if (co->dbname) { - turnFreeRedisReply(redisCommand(rc, "select %s", co->dbname)); - } - { - redisReply *reply = (redisReply*)redisCommand(rc, "keys turn/*/allocation/*/status"); - if(reply) { - secrets_list_t keys; - size_t isz = 0; - char s[513]; - - init_secrets_list(&keys); - - 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); - } - } - - for(isz=0;iszhost, co->port, co->password, atoi(co->dbname)); - - if (!ret) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB connection\n"); - } else if (is_redis_asyncconn_good(ret) && !donot_print_connection_success) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis DB async connection to be used: %s\n", connection_string); - } - RyconninfoFree(co); - } - } - - return ret; -} - -static redisContext *get_redis_connection(void) -{ - if(!is_redis_userdb()) - return NULL; - - persistent_users_db_t *pud = get_persistent_users_db(); - - redisContext *redisconnection = (redisContext*)(pud->connection); - - if(redisconnection) { - if(redisconnection->err) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot connect to redis, err=%d, flags=0x%x\n", __FUNCTION__,(int)redisconnection->err,(unsigned long)redisconnection->flags); - redisFree(redisconnection); - pud->connection = NULL; - redisconnection = NULL; - } - } - - if (!redisconnection) { - - char *errmsg = NULL; - Ryconninfo *co = RyconninfoParse(pud->userdb, &errmsg); - if (!co) { - if (errmsg) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", pud->userdb, errmsg); - turn_free(errmsg,strlen(errmsg)+1); - } else { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error\n", pud->userdb); - } - } else if (errmsg) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", pud->userdb, errmsg); - turn_free(errmsg,strlen(errmsg)+1); - RyconninfoFree(co); - } else { - char ip[256] = "\0"; - int port = DEFAULT_REDIS_PORT; - if (co->host) - STRCPY(ip,co->host); - if (!ip[0]) - STRCPY(ip,"127.0.0.1"); - - if (co->port) - port = (int) (co->port); - - if (co->connect_timeout) { - struct timeval tv; - tv.tv_usec = 0; - tv.tv_sec = (time_t) (co->connect_timeout); - redisconnection = redisConnectWithTimeout(ip, port, tv); - } else { - redisconnection = redisConnect(ip, port); - } - - if (redisconnection) { - if(redisconnection->err) { - if(redisconnection->errstr[0]) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis: %s\n",redisconnection->errstr); - } - redisFree(redisconnection); - redisconnection = NULL; - } else if (co->password) { - void *reply = redisCommand(redisconnection, "AUTH %s", co->password); - if(!reply) { - if(redisconnection->err && redisconnection->errstr[0]) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis: %s\n",redisconnection->errstr); - } - redisFree(redisconnection); - redisconnection = NULL; - } else { - turnFreeRedisReply(reply); - if (co->dbname) { - reply = redisCommand(redisconnection, "select %s", co->dbname); - if(!reply) { - if(redisconnection->err && redisconnection->errstr[0]) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis: %s\n",redisconnection->errstr); - } - redisFree(redisconnection); - redisconnection = NULL; - } else { - turnFreeRedisReply(reply); - } - } - } - } - } - - if (!redisconnection) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB connection\n"); - } else if (!donot_print_connection_success) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis DB sync connection success: %s\n", pud->userdb); - } - - RyconninfoFree(co); - } - pud->connection = redisconnection; - - pud = get_persistent_users_db(); - - redisconnection = (redisContext*)(pud->connection); - } - - return redisconnection; -} - -#endif +//////////////////////////////////////////// static int get_auth_secrets(secrets_list_t *sl, u08bits *realm) { - UNUSED_ARG(realm); - int ret = -1; + turn_dbdriver_t * dbd = get_dbdriver(); clean_secrets_list(sl); @@ -949,120 +332,10 @@ static int get_auth_secrets(secrets_list_t *sl, u08bits *realm) } ret=0; } - -#if !defined(TURN_NO_PQ) - PGconn * pqc = get_pqdb_connection(); - if(pqc) { - char statement[LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm); - 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; - for(i=0;itype == 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); - } - } - - for(isz=0;isztype == 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 { - add_to_secrets_list(sl,rget->str); - } - turnFreeRedisReply(rget); - } - } - - clean_secrets_list(&keys); - - ret = 0; - - turnFreeRedisReply(reply); - } - } -#endif + + if (dbd && dbd->get_auth_secrets) { + ret = (*dbd->get_auth_secrets)(sl, realm); + } return ret; } @@ -1252,129 +525,10 @@ int get_user_key(u08bits *usname, u08bits *realm, hmackey_t key, ioa_network_buf return 0; } -#if !defined(TURN_NO_PQ) - { - PGconn * pqc = get_pqdb_connection(); - if(pqc) { - char statement[LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"select hmackey from turnusers_lt where name='%s' and realm='%s'",usname,realm); - 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); - int len = PQgetlength(res,0,0); - if(kval) { - size_t sz = get_hmackey_size(turn_params.shatype); - if(((size_t)lentype == 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 { - size_t sz = get_hmackey_size(turn_params.shatype); - if(strlen(rget->str)str,usname); - } else if(convert_string_key_to_binary(rget->str, key, sz)<0) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key: %s, user %s\n",rget->str,usname); - } else { - ret = 0; - } - } - 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); - } - } - } - } -#endif + turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->get_user_key) { + ret = (*dbd->get_user_key)(usname, realm, key); + } return ret; } @@ -1386,93 +540,12 @@ int get_user_pwd(u08bits *usname, st_password_t pwd) { int ret = -1; - UNUSED_ARG(pwd); + turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->get_user_pwd) { + ret = (*dbd->get_user_pwd)(usname, pwd); + } - char statement[LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"select password from turnusers_st where name='%s'",usname); - - { -#if !defined(TURN_NO_PQ) - 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); - } - } -#endif -#if !defined(TURN_NO_MYSQL) - 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); - } - } -#endif -#if !defined(TURN_NO_HIREDIS) - { - redisContext * rc = get_redis_connection(); - if(rc) { - char s[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); - } - } - } -#endif - } - - return ret; + return ret; } u08bits *start_user_check(turnserver_id id, turn_credential_type ct, u08bits *usname, u08bits *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, u64bits ctxkey, int *postpone_reply) @@ -1585,7 +658,7 @@ void read_userdb_file(int to_print) if (f) { - char sbuf[LONG_STRING_SIZE]; + char sbuf[TURN_LONG_STRING_SIZE]; ur_string_map_lock(turn_params.default_users_db.ram_db.dynamic_accounts); @@ -1682,170 +755,11 @@ int add_user_account(char *user, int dynamic) static int list_users(int is_st, u08bits *realm) { - UNUSED_ARG(realm); - - donot_print_connection_success = 1; - - if(is_pqsql_userdb()){ -#if !defined(TURN_NO_PQ) - char statement[LONG_STRING_SIZE]; - 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]) { - snprintf(statement,sizeof(statement),"select name from turnusers_lt where realm='%s' order by name",realm); - } else { - snprintf(statement,sizeof(statement),"select name from turnusers_lt order by 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; - for(i=0;itype == 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); - } - - 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); - } - } - - for(isz=0;iszlist_users) { + (*dbd->list_users)(is_st, realm); } else if(!is_st) { - read_userdb_file(1); - } return 0; @@ -1853,116 +767,11 @@ static int list_users(int is_st, u08bits *realm) static int show_secret(u08bits *realm) { - char statement[LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm); - - donot_print_connection_success=1; - must_set_admin_realm(realm); - if(is_pqsql_userdb()){ -#if !defined(TURN_NO_PQ) - PGconn *pqc = get_pqdb_connection(); - if(pqc) { - 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; - for(i=0;itype == 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); - } - } - - for(isz=0;isztype == 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 { - printf("%s\n",rget->str); - } - } - turnFreeRedisReply(rget); - } - - clean_secrets_list(&keys); - - turnFreeRedisReply(reply); - } - } -#endif + turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->show_secret) { + (*dbd->show_secret)(realm); } return 0; @@ -1970,99 +779,14 @@ static int show_secret(u08bits *realm) static int del_secret(u08bits *secret, u08bits *realm) { - UNUSED_ARG(secret); - must_set_admin_realm(realm); - donot_print_connection_success=1; - - if (is_pqsql_userdb()) { -#if !defined(TURN_NO_PQ) - char statement[LONG_STRING_SIZE]; - PGconn *pqc = get_pqdb_connection(); - if (pqc) { - if(!secret || (secret[0]==0)) - snprintf(statement,sizeof(statement),"delete from turn_secret where realm='%s'",realm); - else - snprintf(statement,sizeof(statement),"delete from turn_secret where value='%s' and realm='%s'",secret,realm); - - PGresult *res = PQexec(pqc, statement); - if (res) { - PQclear(res); - } - } -#endif - } else if (is_mysql_userdb()) { -#if !defined(TURN_NO_MYSQL) - char statement[LONG_STRING_SIZE]; - MYSQL * myc = get_mydb_connection(); - if (myc) { - if(!secret || (secret[0]==0)) - snprintf(statement,sizeof(statement),"delete from turn_secret where realm='%s'",realm); - else - snprintf(statement,sizeof(statement),"delete from turn_secret where value='%s' and realm='%s'",secret,realm); - mysql_query(myc, statement); - } -#endif - } else if(is_redis_userdb()) { -#if !defined(TURN_NO_HIREDIS) - redisContext *rc = get_redis_connection(); - if(rc) { - redisReply *reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/secret/*", (char*)realm); - if(reply) { - secrets_list_t keys; - size_t isz = 0; - char s[LONG_STRING_SIZE]; - - init_secrets_list(&keys); - - 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); - } - } - - for(isz=0;isztype == 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(!strcmp((char*)secret,rget->str)) { - snprintf(s,sizeof(s),"del %s", keys.secrets[isz]); - turnFreeRedisReply(redisCommand(rc, s)); - } - } - turnFreeRedisReply(rget); - } - } - } - - turnFreeRedisReply(redisCommand(rc, "save")); - - clean_secrets_list(&keys); - - turnFreeRedisReply(reply); - } - } -#endif + 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) { @@ -2072,57 +796,11 @@ static int set_secret(u08bits *secret, u08bits *realm) { must_set_admin_realm(realm); - donot_print_connection_success = 1; - del_secret(secret, realm); - if (is_pqsql_userdb()) { -#if !defined(TURN_NO_PQ) - char statement[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_LEVEL_ERROR, - "Error inserting/updating secret key information: %s\n", - PQerrorMessage(pqc)); - } - if (res) { - PQclear(res); - } - } -#endif - } else if (is_mysql_userdb()) { -#if !defined(TURN_NO_MYSQL) - char statement[LONG_STRING_SIZE]; - MYSQL * myc = get_mydb_connection(); - if (myc) { - snprintf(statement,sizeof(statement),"insert into turn_secret (realm,value) values('%s','%s')",realm,secret); - int res = mysql_query(myc, statement); - if (res) { - TURN_LOG_FUNC( - TURN_LOG_LEVEL_ERROR, - "Error inserting/updating secret key information: %s\n", - mysql_error(myc)); - } - } -#endif - } else if(is_redis_userdb()) { -#if !defined(TURN_NO_HIREDIS) - redisContext *rc = get_redis_connection(); - if(rc) { - char s[LONG_STRING_SIZE]; - - del_secret(secret, realm); - - snprintf(s,sizeof(s),"set turn/realm/%s/secret/%lu %s", (char*)realm, (unsigned long)turn_time(), secret); - - turnFreeRedisReply(redisCommand(rc, s)); - turnFreeRedisReply(redisCommand(rc, "save")); - } -#endif + turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->set_secret) { + (*dbd->set_secret)(secret, realm); } return 0; @@ -2130,242 +808,37 @@ static int set_secret(u08bits *secret, u08bits *realm) { static int add_origin(u08bits *origin0, u08bits *realm) { - UNUSED_ARG(realm); - UNUSED_ARG(origin0); - char origin[STUN_MAX_ORIGIN_SIZE+1]; - get_canonic_origin((char*)origin0, origin, sizeof(origin)-1); -#if !defined(TURN_NO_PQ) - if(is_pqsql_userdb()) { - char statement[LONG_STRING_SIZE]; - PGconn *pqc = get_pqdb_connection(); - if(pqc) { - snprintf(statement,sizeof(statement),"insert into turn_origin_to_realm (origin,realm) values('%s','%s')",origin,realm); - PGresult *res = PQexec(pqc, statement); - if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting origin information: %s\n",PQerrorMessage(pqc)); - } - if(res) { - PQclear(res); - } - } + u08bits origin[STUN_MAX_ORIGIN_SIZE+1]; + + get_canonic_origin((const char *)origin0, (char *)origin, sizeof(origin)-1); + + turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->add_origin) { + (*dbd->add_origin)(origin, realm); } -#endif -#if !defined(TURN_NO_MYSQL) - if (is_mysql_userdb()) { - char statement[LONG_STRING_SIZE]; - MYSQL * myc = get_mydb_connection(); - if (myc) { - snprintf(statement,sizeof(statement),"insert into turn_origin_to_realm (origin,realm) values('%s','%s')",origin,realm); - int res = mysql_query(myc, statement); - if (res) { - TURN_LOG_FUNC( - TURN_LOG_LEVEL_ERROR, - "Error inserting origin information: %s\n", - mysql_error(myc)); - } - } - } -#endif - -#if !defined(TURN_NO_HIREDIS) - if(is_redis_userdb()) { - redisContext *rc = get_redis_connection(); - if(rc) { - char s[LONG_STRING_SIZE]; - - snprintf(s,sizeof(s),"set turn/origin/%s %s", (char*)origin, (char*)realm); - - turnFreeRedisReply(redisCommand(rc, s)); - turnFreeRedisReply(redisCommand(rc, "save")); - } - } -#endif return 0; } static int del_origin(u08bits *origin0) { - UNUSED_ARG(origin0); - char origin[STUN_MAX_ORIGIN_SIZE+1]; - get_canonic_origin((char*)origin0, origin, sizeof(origin)-1); -#if !defined(TURN_NO_PQ) - if(is_pqsql_userdb()) { - char statement[LONG_STRING_SIZE]; - PGconn *pqc = get_pqdb_connection(); - if(pqc) { - snprintf(statement,sizeof(statement),"delete from turn_origin_to_realm where origin='%s'",origin); - PGresult *res = PQexec(pqc, statement); - if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting origin information: %s\n",PQerrorMessage(pqc)); - } - if(res) { - PQclear(res); - } - } + u08bits origin[STUN_MAX_ORIGIN_SIZE+1]; + + get_canonic_origin((const char *)origin0, (char *)origin, sizeof(origin)-1); + + turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->del_origin) { + (*dbd->del_origin)(origin); } -#endif -#if !defined(TURN_NO_MYSQL) - if (is_mysql_userdb()) { - char statement[LONG_STRING_SIZE]; - MYSQL * myc = get_mydb_connection(); - if (myc) { - snprintf(statement,sizeof(statement),"delete from turn_origin_to_realm where origin='%s'",origin); - int res = mysql_query(myc, statement); - if (res) { - TURN_LOG_FUNC( - TURN_LOG_LEVEL_ERROR, - "Error deleting origin information: %s\n", - mysql_error(myc)); - } - } - } -#endif - -#if !defined(TURN_NO_HIREDIS) - if(is_redis_userdb()) { - redisContext *rc = get_redis_connection(); - if(rc) { - char s[LONG_STRING_SIZE]; - - snprintf(s,sizeof(s),"del turn/origin/%s", (char*)origin); - - turnFreeRedisReply(redisCommand(rc, s)); - turnFreeRedisReply(redisCommand(rc, "save")); - } - } -#endif return 0; } static int list_origins(u08bits *realm) { - UNUSED_ARG(realm); - - donot_print_connection_success = 1; - - if(is_pqsql_userdb()){ -#if !defined(TURN_NO_PQ) - char statement[LONG_STRING_SIZE]; - PGconn *pqc = get_pqdb_connection(); - if(pqc) { - 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"); - } - 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; - for(i=0;i> %s\n",oval,rval); - } - } - } - } - if(res) { - PQclear(res); - } - } -#endif - } else if(is_mysql_userdb()){ -#if !defined(TURN_NO_MYSQL) - char statement[LONG_STRING_SIZE]; - MYSQL * myc = get_mydb_connection(); - if(myc) { - 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"); - } - 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 { - for(;;) { - MYSQL_ROW row = mysql_fetch_row(mres); - if(!row) { - break; - } else { - if(row[0] && row[1]) { - printf("%s ==>> %s\n",row[0],row[1]); - } - } - } - } - - if(mres) - mysql_free_result(mres); - } - } -#endif - } else if(is_redis_userdb()) { -#if !defined(TURN_NO_HIREDIS) - redisContext *rc = get_redis_connection(); - if(rc) { - secrets_list_t keys; - size_t isz = 0; - - init_secrets_list(&keys); - - redisReply *reply = NULL; - - { - reply = (redisReply*)redisCommand(rc, "keys turn/origin/*"); - 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; - size_t offset = strlen("turn/origin/"); - for (i = 0; i < reply->elements; ++i) { - add_to_secrets_list(&keys,reply->element[i]->str+offset); - } - } - turnFreeRedisReply(reply); - } - } - - for(isz=0;isztype == REDIS_REPLY_ERROR) - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str); - else if (reply->type != REDIS_REPLY_STRING) { - if (reply->type != REDIS_REPLY_NIL) - 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); - } - } - turnFreeRedisReply(reply); - } - } - - clean_secrets_list(&keys); - } -#endif + turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->list_origins) { + (*dbd->list_origins)(realm); } return 0; @@ -2373,76 +846,14 @@ static int list_origins(u08bits *realm) static int set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) { - UNUSED_ARG(realm); - UNUSED_ARG(value); - UNUSED_ARG(opt); if(value == (unsigned long)-1) return 0; -#if !defined(TURN_NO_PQ) - if(is_pqsql_userdb()) { - char statement[LONG_STRING_SIZE]; - PGconn *pqc = get_pqdb_connection(); - if(pqc) { - { - snprintf(statement,sizeof(statement),"delete from turn_realm_option where realm='%s' and opt='%s'",realm,opt); - PGresult *res = PQexec(pqc, statement); - if(res) { - PQclear(res); - } - } - if(value>0) { - snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%lu')",realm,opt,(unsigned long)value); - PGresult *res = PQexec(pqc, statement); - if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting realm option information: %s\n",PQerrorMessage(pqc)); - } - if(res) { - PQclear(res); - } - } - } + + turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->set_realm_option_one) { + (*dbd->set_realm_option_one)(realm, value, opt); } -#endif -#if !defined(TURN_NO_MYSQL) - if (is_mysql_userdb()) { - char statement[LONG_STRING_SIZE]; - MYSQL * myc = get_mydb_connection(); - if (myc) { - { - snprintf(statement,sizeof(statement),"delete from turn_realm_option where realm='%s' and opt='%s'",realm,opt); - mysql_query(myc, statement); - } - if(value>0) { - snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%lu')",realm,opt,(unsigned long)value); - int res = mysql_query(myc, statement); - if (res) { - TURN_LOG_FUNC( - TURN_LOG_LEVEL_ERROR, - "Error inserting realm option information: %s\n", - mysql_error(myc)); - } - } - } - } -#endif - -#if !defined(TURN_NO_HIREDIS) - if(is_redis_userdb()) { - redisContext *rc = get_redis_connection(); - if(rc) { - char s[LONG_STRING_SIZE]; - - if(value>0) - snprintf(s,sizeof(s),"set turn/realm/%s/%s %lu", (char*)realm, opt, (unsigned long)value); - else - snprintf(s,sizeof(s),"del turn/realm/%s/%s", (char*)realm, opt); - - turnFreeRedisReply(redisCommand(rc, s)); - turnFreeRedisReply(redisCommand(rc, "save")); - } - } -#endif return 0; } @@ -2456,141 +867,9 @@ static int set_realm_option(u08bits *realm, perf_options_t *po) static int list_realm_options(u08bits *realm) { - UNUSED_ARG(realm); - - donot_print_connection_success = 1; - - if(is_pqsql_userdb()){ -#if !defined(TURN_NO_PQ) - char statement[LONG_STRING_SIZE]; - PGconn *pqc = get_pqdb_connection(); - if(pqc) { - if(realm && realm[0]) { - snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option where realm='%s' order by realm,opt",realm); - } else { - snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option order by realm,opt"); - } - 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; - for(i=0;itype == 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) { - if(strstr(reply->element[i]->str,"/max-bps")|| - strstr(reply->element[i]->str,"/total-quota")|| - strstr(reply->element[i]->str,"/user-quota")) { - add_to_secrets_list(&keys,reply->element[i]->str); - } - } - } - turnFreeRedisReply(reply); - } - } - - size_t offset = strlen("turn/realm/"); - - for(isz=0;isztype == REDIS_REPLY_ERROR) - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str); - else if (reply->type != REDIS_REPLY_STRING) { - if (reply->type != REDIS_REPLY_NIL) - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type); - } else { - printf("%s = %s\n",o+offset,reply->str); - } - turnFreeRedisReply(reply); - } - } - - clean_secrets_list(&keys); - } -#endif + turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->list_realm_options) { + (*dbd->list_realm_options)(realm); } return 0; @@ -2598,13 +877,10 @@ static int list_realm_options(u08bits *realm) int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08bits *origin, TURNADMIN_COMMAND_TYPE ct, int is_st, - perf_options_t *po) -{ + perf_options_t *po) { hmackey_t key; char skey[sizeof(hmackey_t)*2+1]; - donot_print_connection_success = 1; - st_password_t passwd; if(ct == TA_LIST_USERS) { @@ -2674,152 +950,40 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b } } + turn_dbdriver_t * dbd = get_dbdriver(); + if(ct == TA_PRINT_KEY) { if(!is_st) { printf("0x%s\n",skey); } - } else if(is_pqsql_userdb()){ - -#if !defined(TURN_NO_PQ) + } else if(dbd) { if(!is_st) { must_set_admin_realm(realm); } - - char statement[LONG_STRING_SIZE]; - PGconn *pqc = get_pqdb_connection(); - if(pqc) { - if(ct == TA_DELETE_USER) { - if(is_st) { - snprintf(statement,sizeof(statement),"delete from turnusers_st where name='%s'",user); - } else { - snprintf(statement,sizeof(statement),"delete from turnusers_lt where name='%s' and realm='%s'",user,realm); - } - PGresult *res = PQexec(pqc, statement); - if(res) { - PQclear(res); - } - } - - if(ct == TA_UPDATE_USER) { - if(is_st) { - snprintf(statement,sizeof(statement),"insert into turnusers_st values('%s','%s')",user,passwd); - } else { - snprintf(statement,sizeof(statement),"insert into turnusers_lt (realm,name,hmackey) values('%s','%s','%s')",realm,user,skey); - } - PGresult *res = PQexec(pqc, statement); - if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { - if(res) { - PQclear(res); - } - if(is_st) { - snprintf(statement,sizeof(statement),"update turnusers_st set password='%s' where name='%s'",passwd,user); - } else { - snprintf(statement,sizeof(statement),"update turnusers_lt set hmackey='%s' where name='%s' and realm='%s'",skey,user,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)); - } - } - if(res) { - PQclear(res); - } - } - } -#endif - } else if(is_mysql_userdb()){ - -#if !defined(TURN_NO_MYSQL) - - if(!is_st) { - must_set_admin_realm(realm); - } - - char statement[LONG_STRING_SIZE]; - MYSQL * myc = get_mydb_connection(); - if(myc) { - if(ct == TA_DELETE_USER) { - if(is_st) { - snprintf(statement,sizeof(statement),"delete from turnusers_st where name='%s'",user); - } else { - snprintf(statement,sizeof(statement),"delete from turnusers_lt where name='%s' and realm='%s'",user,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)); - } - } - - if(ct == TA_UPDATE_USER) { - if(is_st) { - snprintf(statement,sizeof(statement),"insert into turnusers_st values('%s','%s')",user,passwd); - } else { - snprintf(statement,sizeof(statement),"insert into turnusers_lt (realm,name,hmackey) values('%s','%s','%s')",realm,user,skey); - } - int res = mysql_query(myc, statement); - if(res) { - if(is_st) { - snprintf(statement,sizeof(statement),"update turnusers_st set password='%s' where name='%s'",passwd,user); - } else { - snprintf(statement,sizeof(statement),"update turnusers_lt set hmackey='%s' where name='%s' and realm='%s'",skey,user,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)); - } - } - } - } -#endif - } else if(is_redis_userdb()) { - -#if !defined(TURN_NO_HIREDIS) - - if(!is_st) { - must_set_admin_realm(realm); - } - - redisContext *rc = get_redis_connection(); - if(rc) { - char statement[LONG_STRING_SIZE]; - - if(ct == TA_DELETE_USER) { - if(is_st) { - snprintf(statement,sizeof(statement),"del turn/user/%s/password",user); - turnFreeRedisReply(redisCommand(rc, statement)); - } else { - snprintf(statement,sizeof(statement),"del turn/realm/%s/user/%s/key",(char*)realm,user); - turnFreeRedisReply(redisCommand(rc, statement)); - snprintf(statement,sizeof(statement),"del turn/realm/%s/user/%s/password",(char*)realm,user); - turnFreeRedisReply(redisCommand(rc, statement)); - } - } - - if(ct == TA_UPDATE_USER) { - if(is_st) { - snprintf(statement,sizeof(statement),"set turn/user/%s/password %s",user,passwd); - turnFreeRedisReply(redisCommand(rc, statement)); - } else { - snprintf(statement,sizeof(statement),"set turn/realm/%s/user/%s/key %s",(char*)realm,user,skey); - turnFreeRedisReply(redisCommand(rc, statement)); - snprintf(statement,sizeof(statement),"del turn/realm/%s/user/%s/password",(char*)realm,user); - turnFreeRedisReply(redisCommand(rc, statement)); - } - } - - turnFreeRedisReply(redisCommand(rc, "save")); - } -#endif + + if (ct == TA_DELETE_USER) { + if (dbd->del_user) + (*dbd->del_user)(user, is_st, realm); + } else if (ct == TA_UPDATE_USER) { + if (is_st) { + if (dbd->set_user_pwd) + (*dbd->set_user_pwd)(user, passwd); + } else { + if (dbd->set_user_key) + (*dbd->set_user_key)(user, realm, skey); + } + } + } else if(!is_st) { persistent_users_db_t *pud = get_persistent_users_db(); char *full_path_to_userdb_file = find_config_file(pud->userdb, 1); FILE *f = full_path_to_userdb_file ? fopen(full_path_to_userdb_file,"r") : NULL; int found = 0; - char us[LONG_STRING_SIZE]; + char us[TURN_LONG_STRING_SIZE]; size_t i = 0; char **content = NULL; size_t csz = 0; @@ -2832,8 +996,8 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "File %s not found, will be created.\n",pud->userdb); } else { - char sarg[LONG_STRING_SIZE]; - char sbuf[LONG_STRING_SIZE]; + char sarg[TURN_LONG_STRING_SIZE]; + char sbuf[TURN_LONG_STRING_SIZE]; for (;;) { char *s0 = fgets(sbuf, sizeof(sbuf) - 1, f); @@ -2931,55 +1095,10 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b void auth_ping(redis_context_handle rch) { - UNUSED_ARG(rch); - - donot_print_connection_success = 1; - -#if !defined(TURN_NO_PQ) - PGconn * pqc = get_pqdb_connection(); - if(pqc) { - char statement[LONG_STRING_SIZE]; - STRCPY(statement,"select value from turn_secret"); - 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)); - } - - if(res) { - PQclear(res); - } + turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->auth_ping) { + (*dbd->auth_ping)(rch); } -#endif - -#if !defined(TURN_NO_MYSQL) - MYSQL * myc = get_mydb_connection(); - if(myc) { - char statement[LONG_STRING_SIZE]; - STRCPY(statement,"select value from turn_secret"); - 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 { - mysql_free_result(mres); - } - } - } -#endif - -#if !defined(TURN_NO_HIREDIS) - redisContext *rc = get_redis_connection(); - if(rc) { - turnFreeRedisReply(redisCommand(rc, "keys turn/origin/*")); - } - if(rch) - send_message_to_redis(rch, "publish", "__XXX__", "__YYY__"); -#endif - } ///////////////// WHITE/BLACK IP LISTS /////////////////// @@ -3077,114 +1196,13 @@ const ip_range_list_t* ioa_get_blacklist(ioa_engine_handle e) static ip_range_list_t* get_ip_list(const char *kind) { - UNUSED_ARG(kind); ip_range_list_t *ret = (ip_range_list_t*)turn_malloc(sizeof(ip_range_list_t)); ns_bzero(ret,sizeof(ip_range_list_t)); -#if !defined(TURN_NO_PQ) - PGconn * pqc = get_pqdb_connection(); - if(pqc) { - char statement[LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"select ip_range from %s_peer_ip",kind); - PGresult *res = PQexec(pqc, statement); - - if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) { - int i = 0; - for(i=0;iget_ip_list) { + (*dbd->get_ip_list)(kind, ret); } -#endif - -#if !defined(TURN_NO_MYSQL) - MYSQL * myc = get_mydb_connection(); - if(myc) { - char statement[LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"select ip_range from %s_peer_ip",kind); - int res = mysql_query(myc, statement); - if(res == 0) { - MYSQL_RES *mres = mysql_store_result(myc); - if(mres && mysql_field_count(myc)==1) { - for(;;) { - MYSQL_ROW row = mysql_fetch_row(mres); - if(!row) { - break; - } else { - if(row[0]) { - unsigned long *lengths = mysql_fetch_lengths(mres); - if(lengths) { - size_t sz = lengths[0]; - char kval[LONG_STRING_SIZE]; - ns_bcopy(row[0],kval,sz); - kval[sz]=0; - add_ip_list_range(kval,ret); - } - } - } - } - } - - if(mres) - mysql_free_result(mres); - } - } -#endif - -#if !defined(TURN_NO_HIREDIS) - redisContext *rc = get_redis_connection(); - if(rc) { - char statement[LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"keys turn/%s-peer-ip/*", kind); - redisReply *reply = (redisReply*)redisCommand(rc, statement); - if(reply) { - secrets_list_t keys; - size_t isz = 0; - char s[257]; - - init_secrets_list(&keys); - - 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); - } - } - - for(isz=0;isztype == 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 { - add_ip_list_range(rget->str,ret); - } - turnFreeRedisReply(rget); - } - } - - clean_secrets_list(&keys); - - turnFreeRedisReply(reply); - } - } -#endif return ret; } @@ -3231,7 +1249,7 @@ void update_white_and_black_lists(void) /////////////// add ACL record /////////////////// -int add_ip_list_range(char* range, ip_range_list_t * list) +int add_ip_list_range(const char * range, ip_range_list_t * list) { char* separator = strchr(range, '-'); @@ -3273,41 +1291,6 @@ int add_ip_list_range(char* range, ip_range_list_t * list) /////////// REALM ////////////// -#if !defined(TURN_NO_HIREDIS) -static int set_redis_realm_opt(char *realm, const char* key, unsigned long *value) -{ - int found = 0; - - redisContext *rc = get_redis_connection(); - - if(rc) { - redisReply *rget = NULL; - - char s[1025]; - - snprintf(s, sizeof(s), "get turn/realm/%s/%s", realm, key); - - 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 { - ur_string_map_lock(realms); - *value = (unsigned long)atol(rget->str); - ur_string_map_unlock(realms); - found = 1; - } - turnFreeRedisReply(rget); - } - } - - return found; -} -#endif - void reread_realms(void) { { @@ -3319,322 +1302,10 @@ void reread_realms(void) ur_string_map_unlock(realms); } -#if !defined(TURN_NO_PQ) - PGconn * pqc = get_pqdb_connection(); - if(pqc) { - char statement[LONG_STRING_SIZE]; - - { - snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm"); - PGresult *res = PQexec(pqc, statement); - - if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) { - - ur_string_map *o_to_realm_new = ur_string_map_create(free); - - int i = 0; - for(i=0;ioptions.perf_options.max_bps = turn_params.max_bps; - ur_string_map_unlock(realms); - - ur_string_map_lock(realms); - rp->options.perf_options.total_quota = turn_params.total_quota; - ur_string_map_unlock(realms); - - ur_string_map_lock(realms); - rp->options.perf_options.user_quota = turn_params.user_quota; - ur_string_map_unlock(realms); - - } - } - - snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option"); - PGresult *res = PQexec(pqc, statement); - - if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) { - - int i = 0; - for(i=0;ioptions.perf_options.max_bps = (band_limit_t)atol(vval); - else if(!strcmp(oval,"total-quota")) - rp->options.perf_options.total_quota = (vint)atoi(vval); - else if(!strcmp(oval,"user-quota")) - rp->options.perf_options.user_quota = (vint)atoi(vval); - else { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", oval); - } - } - } - } - - if(res) { - PQclear(res); - } - } + turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->reread_realms) { + (*dbd->reread_realms)(&realms_list); } -#endif - -#if !defined(TURN_NO_MYSQL) - MYSQL * myc = get_mydb_connection(); - if(myc) { - char statement[LONG_STRING_SIZE]; - { - snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm"); - int res = mysql_query(myc, statement); - if(res == 0) { - MYSQL_RES *mres = mysql_store_result(myc); - if(mres && mysql_field_count(myc)==2) { - - ur_string_map *o_to_realm_new = ur_string_map_create(free); - - for(;;) { - MYSQL_ROW row = mysql_fetch_row(mres); - if(!row) { - break; - } else { - if(row[0] && row[1]) { - unsigned long *lengths = mysql_fetch_lengths(mres); - if(lengths) { - size_t sz = lengths[0]; - char oval[513]; - ns_bcopy(row[0],oval,sz); - oval[sz]=0; - char *rval=strdup(row[1]); - get_realm(rval); - ur_string_map_value_type value = strdup(rval); - ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) oval, value); - } - } - } - } - - TURN_MUTEX_LOCK(&o_to_realm_mutex); - ur_string_map_free(&o_to_realm); - o_to_realm = o_to_realm_new; - TURN_MUTEX_UNLOCK(&o_to_realm_mutex); - } - - if(mres) - mysql_free_result(mres); - } - } - { - size_t i = 0; - size_t rlsz = 0; - - ur_string_map_lock(realms); - rlsz = realms_list.sz; - ur_string_map_unlock(realms); - - for (i = 0; ioptions.perf_options.max_bps = turn_params.max_bps; - ur_string_map_unlock(realms); - - ur_string_map_lock(realms); - rp->options.perf_options.total_quota = turn_params.total_quota; - ur_string_map_unlock(realms); - - ur_string_map_lock(realms); - rp->options.perf_options.user_quota = turn_params.user_quota; - ur_string_map_unlock(realms); - - } - } - - snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option"); - int res = mysql_query(myc, statement); - if(res == 0) { - MYSQL_RES *mres = mysql_store_result(myc); - if(mres && mysql_field_count(myc)==3) { - - for(;;) { - MYSQL_ROW row = mysql_fetch_row(mres); - if(!row) { - break; - } else { - if(row[0] && row[1] && row[2]) { - unsigned long *lengths = mysql_fetch_lengths(mres); - if(lengths) { - char rval[513]; - size_t sz = lengths[0]; - ns_bcopy(row[0],rval,sz); - rval[sz]=0; - char oval[513]; - sz = lengths[1]; - ns_bcopy(row[1],oval,sz); - oval[sz]=0; - char vval[513]; - sz = lengths[2]; - ns_bcopy(row[2],vval,sz); - vval[sz]=0; - realm_params_t* rp = get_realm(rval); - if(!strcmp(oval,"max-bps")) - rp->options.perf_options.max_bps = (band_limit_t)atol(vval); - else if(!strcmp(oval,"total-quota")) - rp->options.perf_options.total_quota = (vint)atoi(vval); - else if(!strcmp(oval,"user-quota")) - rp->options.perf_options.user_quota = (vint)atoi(vval); - else { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", oval); - } - } - } - } - } - } - - if(mres) - mysql_free_result(mres); - } - } -#endif - -#if !defined(TURN_NO_HIREDIS) - if (is_redis_userdb()) { - redisContext *rc = get_redis_connection(); - if (rc) { - - redisReply *reply = (redisReply*) redisCommand(rc, "keys turn/origin/*"); - if (reply) { - - ur_string_map *o_to_realm_new = ur_string_map_create(free); - - secrets_list_t keys; - - init_secrets_list(&keys); - - size_t isz = 0; - - char s[1025]; - - 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); - } - } - - size_t offset = strlen("turn/origin/"); - - for (isz = 0; isz < keys.sz; ++isz) { - char *origin = keys.secrets[isz] + offset; - snprintf(s, sizeof(s), "get %s", keys.secrets[isz]); - 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 { - get_realm(rget->str); - ur_string_map_value_type value = strdup(rget->str); - ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) origin, value); - } - turnFreeRedisReply(rget); - } - } - - clean_secrets_list(&keys); - - TURN_MUTEX_LOCK(&o_to_realm_mutex); - ur_string_map_free(&o_to_realm); - o_to_realm = o_to_realm_new; - TURN_MUTEX_UNLOCK(&o_to_realm_mutex); - - turnFreeRedisReply(reply); - } - - { - size_t i = 0; - size_t rlsz = 0; - - ur_string_map_lock(realms); - rlsz = realms_list.sz; - ur_string_map_unlock(realms); - - for (i = 0; ioptions.perf_options.max_bps = turn_params.max_bps; - ur_string_map_unlock(realms); - } - rp->options.perf_options.max_bps = (band_limit_t)value; - if(!set_redis_realm_opt(realm,"total-quota",&value)) { - ur_string_map_lock(realms); - rp->options.perf_options.total_quota = turn_params.total_quota; - ur_string_map_unlock(realms); - } - rp->options.perf_options.total_quota = (vint)value; - if(!set_redis_realm_opt(realm,"user-quota",&value)) { - ur_string_map_lock(realms); - rp->options.perf_options.user_quota = turn_params.user_quota; - ur_string_map_unlock(realms); - } - rp->options.perf_options.user_quota = (vint)value; - } - } - } - } -#endif } /////////////////////////////// diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index ae4cf4a5..a529d1bb 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -77,6 +77,10 @@ struct _realm_params_t { }; +void lock_realms(void); +void unlock_realms(void); +void update_o_to_realm(ur_string_map * o_to_realm_new); + //////////// USER DB ////////////////////////////// struct auth_message { @@ -100,6 +104,9 @@ enum _TURN_USERDB_TYPE { #if !defined(TURN_NO_MYSQL) ,TURN_USERDB_TYPE_MYSQL #endif +#if !defined(TURN_NO_MONGO) + ,TURN_USERDB_TYPE_MONGO +#endif #if !defined(TURN_NO_HIREDIS) ,TURN_USERDB_TYPE_REDIS #endif @@ -194,7 +201,7 @@ 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_ip_list_range(char* range, ip_range_list_t * list); +int add_ip_list_range(const char* range, ip_range_list_t * list); ///////////// Redis ////////////////////// From 04f4277b21e365f5d2c0c01ef7d0f7cb1c042c01 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 11 Jul 2014 16:11:10 +0000 Subject: [PATCH 091/805] mongo test scripts --- turndb/schema.mongo.sh | 12 +++++++++++ turndb/testmongosetup.sh | 44 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100755 turndb/schema.mongo.sh create mode 100755 turndb/testmongosetup.sh diff --git a/turndb/schema.mongo.sh b/turndb/schema.mongo.sh new file mode 100755 index 00000000..32449eb1 --- /dev/null +++ b/turndb/schema.mongo.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +mongo $* < Date: Fri, 11 Jul 2014 16:18:02 +0000 Subject: [PATCH 092/805] mongo test script added --- .../secure_relay_with_db_mongo.sh | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh new file mode 100644 index 00000000..51159414 --- /dev/null +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh @@ -0,0 +1,66 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure mode with MongoDB database for users +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) "-r north.gov" means "use authentication realm north.gov" +# 6) --mongo-userdb="mongodb://localhost/turn" +# means that local MongoDB database "turn" will be used. +# 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 +# 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/ +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/turn" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 $@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure mode with MongoDB database for users +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) "-r north.gov" means "use authentication realm north.gov" +# 6) --mongo-userdb="mongodb://localhost/turn" +# means that local MongoDB database "turn" will be used. +# 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 +# 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/ +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/turn" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 $@ From 868f121179e9208989d7a1e70c8108d8b8c6856b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 11 Jul 2014 16:23:08 +0000 Subject: [PATCH 093/805] minor fixes --- src/apps/relay/dbdrivers/dbd_mongo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index 75dbec42..57a1afdd 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -700,7 +700,6 @@ static int mongo_list_realm_options(u08bits *realm) { if (bson_iter_init(&options_iter, &options)) { while(bson_iter_next(&options_iter)) { const char * _k = bson_iter_key(&options_iter); - printf("key %s, type %d\n", _k, bson_iter_type(&options_iter)); if (BSON_ITER_HOLDS_DOUBLE(&options_iter)) { int32_t _v = (int32_t)bson_iter_double(&options_iter); printf("%s[%s]=%d\n", _k, _realm, _v); @@ -759,7 +758,7 @@ static int mongo_get_ip_list(const char *kind, ip_range_list_t * list) { 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)) { + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "ip_range") && BSON_ITER_HOLDS_UTF8(&iter)) { value = bson_iter_utf8(&iter, &length); add_ip_list_range(value, list); } From 063fb1982fe25f40a941b66a30d81ebc63277ae6 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 11 Jul 2014 20:32:48 +0000 Subject: [PATCH 094/805] STUN BINDING fixed for 'external ip' case --- ChangeLog | 3 ++- src/apps/relay/netengine.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index caadd49e..b47135f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,9 @@ 06/25/2014 Oleg Moskalenko Version 4.0.1.4 'Severard': - - multiple origins supported. + - multiple origins supported per request. - working on compilation warnings. - "allocation mismatch" condition fixed (merged from rfc5766-turn-server). + - STUN BINDING response fixed in the case of -X (external address) option. 06/13/2014 Oleg Moskalenko Version 4.0.1.3 'Severard': diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index f0f7d420..76df6625 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -891,7 +891,7 @@ static void setup_listener(void) bufferevent_enable(turn_params.listener.in_buf, EV_READ); } - if(turn_params.listener.addrs_number<2) { + if(turn_params.listener.addrs_number<2 || turn_params.external_ip) { turn_params.rfc5780 = 0; TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: I cannot support STUN CHANGE_REQUEST functionality because only one IP address is provided\n"); } else { From 552aca708257d456c202b44cec6ffa4386ebeb1f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 12 Jul 2014 01:00:36 +0000 Subject: [PATCH 095/805] working on MongoDB. --- AUTHORS | 3 +++ ChangeLog | 6 ++++-- INSTALL | 6 ++++++ README.turnadmin | 2 ++ README.turnserver | 2 ++ README.turnutils | 2 ++ STATUS | 8 +++++-- man/man1/turnadmin.1 | 9 +++++++- man/man1/turnserver.1 | 31 ++++++++++++++++++++++------ man/man1/turnutils.1 | 4 +++- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/apps/relay/dbdrivers/dbd_mongo.c | 4 ++-- 13 files changed, 67 insertions(+), 16 deletions(-) diff --git a/AUTHORS b/AUTHORS index 6b8ea91c..4e984eed 100644 --- a/AUTHORS +++ b/AUTHORS @@ -44,3 +44,6 @@ Mutsutoshi Yoshimoto TCP routing: testing and bug fixes (since v3.2.2.7) +Federico Pinna + MongoDB support + (since v4.1.0.1) diff --git a/ChangeLog b/ChangeLog index b47135f0..eda878d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,11 @@ 06/25/2014 Oleg Moskalenko -Version 4.0.1.4 'Severard': +Version 4.1.0.1 'Vitari': + - SSODA support (TODO). + - MongoDB support (in progress) (Federico Pinna). - multiple origins supported per request. - - working on compilation warnings. - "allocation mismatch" condition fixed (merged from rfc5766-turn-server). - STUN BINDING response fixed in the case of -X (external address) option. + - working on compilation warnings. 06/13/2014 Oleg Moskalenko Version 4.0.1.3 'Severard': diff --git a/INSTALL b/INSTALL index 21d41c0a..ec69027d 100644 --- a/INSTALL +++ b/INSTALL @@ -902,6 +902,12 @@ XVI. MongoDB setup The MongoDB setup is well documented on their site http://docs.mongodb.org/manual/. +Note: if your system has a "standard" plain vanilla UNIX "make" utility +(that is not a GNU make) then you will have to use the GNU make to compile +the Mongo driver, because the Mongo compilation process was written with +the "proprietary" GNU extentions. For example, in FreeBSD in will have to use +"gmake" command. + If the TURN server was compiled with MongoDB support (mongo-c-driver is the C client library for MongoDB), then we can use the TURN server database parameter --mongo-userdb. The value of this parameter is a connection string diff --git a/README.turnadmin b/README.turnadmin index ab0233f3..121c6066 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -239,3 +239,5 @@ to see the man page. Peter Dunkley Mutsutoshi Yoshimoto + + Federico Pinna diff --git a/README.turnserver b/README.turnserver index 555a72f0..1db6f032 100644 --- a/README.turnserver +++ b/README.turnserver @@ -905,3 +905,5 @@ SEE ALSO Peter Dunkley Mutsutoshi Yoshimoto + + Federico Pinna diff --git a/README.turnutils b/README.turnutils index 1c2f5990..a9462d5e 100644 --- a/README.turnutils +++ b/README.turnutils @@ -333,3 +333,5 @@ SEE ALSO Peter Dunkley Mutsutoshi Yoshimoto + + Federico Pinna diff --git a/STATUS b/STATUS index 8febb474..21f4900b 100644 --- a/STATUS +++ b/STATUS @@ -93,9 +93,13 @@ compatibility. 39) Congestion avoidance implemented, for all protocols. -40) Multi-tenant server implemented. +40) Coturn project forked from rfc5766-turn-server. -41) Coturn project forked from rfc5766-turn-server. +41) Multi-tenant server implemented (ORIGIN support). + +42) Bandwidth draft support added. + +43) MongoDB support added. Things to be implemented in future (the development roadmap) are described in the TODO file. diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 70b13659..127c3eb5 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "25 June 2014" "" "" +.TH TURN 1 "11 July 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage @@ -152,6 +152,11 @@ MySQL user database connection string. See the \fB\-\-mysql\-userdb\fP option in the \fIturnserver\fP section. .TP .B +\fB\-J\fP, \fB\-\-mongo\-userdb\fP +MongoDB user database connection string. +See the \fB\-\-mysql\-mongo\fP option in the \fIturnserver\fP section. +.TP +.B \fB\-N\fP, \fB\-\-redis\-userdb\fP Redis user database connection string. See the \fB\-\-redis\-userdb\fP option in the \fIturnserver\fP section. @@ -323,3 +328,5 @@ Po\-sheng Lin Peter Dunkley .PP Mutsutoshi Yoshimoto +.PP +Federico Pinna diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index a4546fa2..47af6d2b 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "25 June 2014" "" "" +.TH TURN 1 "11 July 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -87,7 +87,7 @@ is equivalent to: .nf .fam C -$ \fIturnserver\fP [\fB\-n\fP | \fB\-c\fP ] [\fIflags\fP] [ \fB\-\-userdb\fP= | \fB\-\-psql\-userdb\fP= | \fB\-\-mysql\-userdb\fP= | \fB\-\-redis\-userdb\fP= ] [\fB\-z\fP | \fB\-\-no\-auth\fP | \fB\-a\fP | \fB\-\-lt\-cred\-mech\fP ] [\fIoptions\fP] +$ \fIturnserver\fP [\fB\-n\fP | \fB\-c\fP ] [\fIflags\fP] [ \fB\-\-userdb\fP= | \fB\-\-psql\-userdb\fP= | \fB\-\-mysql\-userdb\fP= | \fB\-\-mongo\-userdb\fP= | \fB\-\-redis\-userdb\fP= ] [\fB\-z\fP | \fB\-\-no\-auth\fP | \fB\-a\fP | \fB\-\-lt\-cred\-mech\fP ] [\fIoptions\fP] $ \fIturnserver\fP \fB\-h\fP .fam T @@ -173,6 +173,21 @@ for full MySQL documentation. .RE .TP .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 for secret\-based timed authentication in TURN RESP API. +The connection string format is like that: +.RS +.PP +"mongodb://[username:password@]host1[:port1][,host2[:port2],\.\.\.[,hostN[:portN]]][/[database][?\fIoptions\fP]]" +See the INSTALL file for more explanations and examples. +.PP +Also, see http://docs.mongodb.org/manual/ +for full MongoDB documentation. +.RE +.TP +.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, @@ -212,12 +227,12 @@ per\-server setting. \fB\-a\fP, \fB\-\-lt\-cred\-mech\fP Use long\-term credentials mechanism (this one you need for WebRTC usage). This option can be used with either flat file user database or -PostgreSQL DB or MySQL DB or Redis for user keys storage. +PostgreSQL DB or MySQL DB or MongoDB or Redis for user keys storage. .TP .B \fB\-A\fP, \fB\-\-st\-cred\-mech\fP Use the short\-term credentials mechanism. This option requires -a PostgreSQL or MySQL or Redis DB for short term passwords storage. +a PostgreSQL or MySQL or MongoDB or Redis DB for short term passwords storage. .TP .B \fB\-z\fP, \fB\-\-no\-auth\fP @@ -667,7 +682,7 @@ Redis status and statistics database connection string, if used (default \- empt no Redis stats DB used). This database keeps allocations status information, and it can be also used for publishing and delivering traffic and allocation event notifications. This database option can be used independently of \fB\-\-redis\-userdb\fP option, -and actually Redis can be used for status/statistics and MySQL or PostgreSQL can +and actually Redis can be used for status/statistics and MySQL or MongoDB or PostgreSQL can be used for the user database. The connection string has the same parameters as redis\-userdb connection string. .TP @@ -762,7 +777,7 @@ for that you have a number of \fIoptions\fP: b) userdb config file. - c) a database table (PostgreSQL or MySQL). You will have to set keys with + c) a database table (PostgreSQL or MySQL or MongoDB). You will have to set keys with turnadmin utility (see docs and wiki for turnadmin). You cannot use open passwords in the database. @@ -963,6 +978,8 @@ If a database is used, then users can be divided into multiple independent realm can be administered separately, and each realm can have its own set of users and its own performance \fIoptions\fP (max\-bps, user\-quota, total\-quota). .IP 7) 4 +If you use MongoDB, the database will be setup for you automatically. +.IP 8) 4 Of course, the \fIturnserver\fP can be used in non\-secure mode, when users are allowed to establish sessions anonymously. But in most cases (like WebRTC) that will not work. .PP @@ -1135,3 +1152,5 @@ Po\-sheng Lin Peter Dunkley .PP Mutsutoshi Yoshimoto +.PP +Federico Pinna diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index facf3c58..d507b920 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "25 June 2014" "" "" +.TH TURN 1 "11 July 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -449,3 +449,5 @@ Po\-sheng Lin Peter Dunkley .PP Mutsutoshi Yoshimoto +.PP +Federico Pinna diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 85abba6d..c9f5bd94 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.0.1.4 +TURNVERSION=4.1.0.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index abb36815..6f7063ea 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.0.1.4 +Version: 4.1.0.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -289,6 +289,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Fri Jul 11 2014 Oleg Moskalenko + - Sync to 4.1.0.1 * Wed Jun 25 2014 Oleg Moskalenko - Sync to 4.0.1.4 * Fri Jun 13 2014 Oleg Moskalenko diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index 57a1afdd..73debc33 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -462,7 +462,7 @@ static int mongo_del_secret(u08bits *secret, u08bits *realm) { BSON_APPEND_UTF8(&query, "value", (const char *)secret); } - mongoc_collection_delete(collection, 0, &query, NULL, NULL); + mongoc_collection_delete(collection, MONGOC_DELETE_NONE, &query, NULL, NULL); mongoc_collection_destroy(collection); bson_destroy(&query); return 0; @@ -844,7 +844,7 @@ static void mongo_reread_realms(secrets_list_t * realms_list) { if (bson_iter_init(&options_iter, &options)) { while(bson_iter_next(&options_iter)) { const char * _k = bson_iter_key(&options_iter); - int32_t _v; + int32_t _v = 0; if (BSON_ITER_HOLDS_DOUBLE(&options_iter)) { _v = (int32_t)bson_iter_double(&options_iter); } else if (BSON_ITER_HOLDS_INT32(&options_iter)) { From f2faa6704856bfeff946da11b2794baddb52ed4b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 12 Jul 2014 06:41:35 +0000 Subject: [PATCH 096/805] executable bit set on a script --- examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh old mode 100644 new mode 100755 From 87ba771c0647cdc5e7c507c01d4778aa19a5c6fc Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 12 Jul 2014 06:51:28 +0000 Subject: [PATCH 097/805] test scripts updated --- turndb/schema.mongo.sh | 4 +++- turndb/testmongosetup.sh | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/turndb/schema.mongo.sh b/turndb/schema.mongo.sh index 32449eb1..2bb65b65 100755 --- a/turndb/schema.mongo.sh +++ b/turndb/schema.mongo.sh @@ -2,6 +2,8 @@ mongo $* < Date: Sat, 12 Jul 2014 07:07:28 +0000 Subject: [PATCH 098/805] mongo script fixed --- .../secure_relay_with_db_mongo.sh | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh index 51159414..b1f0670a 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh @@ -31,36 +31,3 @@ 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/turn" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 $@ -#!/bin/sh -# -# This is an example how to start a TURN Server in -# secure mode with MongoDB database for users -# with the long-term credentials mechanism. -# -# We start here a TURN Server listening on IPv4 address -# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as -# IPv4 relay address, and we use ::1 as IPv6 relay address. -# -# 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) "-r north.gov" means "use authentication realm north.gov" -# 6) --mongo-userdb="mongodb://localhost/turn" -# means that local MongoDB database "turn" will be used. -# 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 -# 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/ -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/turn" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 $@ From b42adeb74f19ed64482855876743a1da7a937964 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 12 Jul 2014 07:17:04 +0000 Subject: [PATCH 099/805] mongo code update --- src/apps/relay/dbdrivers/dbd_mongo.c | 68 ++++++++++++++++------------ 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index 73debc33..28acbd1d 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -76,46 +76,56 @@ static void MongoFree(MONGO * info) { } } -static MONGO * get_mydb_connection(const char *realm) { - UNUSED_ARG(realm); - +static MONGO * get_mongodb_connection(void) { + persistent_users_db_t * pud = get_persistent_users_db(); - MONGO * mydbconnection = (MONGO *)(pud->connection); + MONGO * mydbconnection = (MONGO *) (pud->connection); - if(!mydbconnection) { - mongoc_init(); - mongoc_log_set_handler(&mongo_logger, NULL); + if (!mydbconnection) { + mongoc_init(); + mongoc_log_set_handler(&mongo_logger, NULL); - mydbconnection = (MONGO *)turn_malloc(sizeof(MONGO)); - mydbconnection->uri = mongoc_uri_new(pud->userdb); - - if (!mydbconnection->uri) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open parse MongoDB URI <%s>, connection string format error\n", pud->userdb); - MongoFree(mydbconnection); - mydbconnection = NULL; - } else { - mydbconnection->client = mongoc_client_new_from_uri(mydbconnection->uri); - if (!mydbconnection->client) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize MongoDB connection\n"); - MongoFree(mydbconnection); - mydbconnection = NULL; - } else { - mydbconnection->database = mongoc_uri_get_database(mydbconnection->uri); - if (!mydbconnection->database) mydbconnection->database = MONGO_DEFAULT_DB; - pud->connection = mydbconnection; - } - } - } + mydbconnection = (MONGO *) turn_malloc(sizeof(MONGO)); + mydbconnection->uri = mongoc_uri_new(pud->userdb); + + if (!mydbconnection->uri) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "Cannot open parse MongoDB URI <%s>, connection string format error\n", + pud->userdb); + MongoFree(mydbconnection); + mydbconnection = NULL; + } else { + mydbconnection->client = mongoc_client_new_from_uri( + mydbconnection->uri); + if (!mydbconnection->client) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Cannot initialize MongoDB connection\n"); + MongoFree(mydbconnection); + mydbconnection = NULL; + } else { + mydbconnection->database = mongoc_uri_get_database( + mydbconnection->uri); + if (!mydbconnection->database) + mydbconnection->database = MONGO_DEFAULT_DB; + pud->connection = mydbconnection; + TURN_LOG_FUNC( + TURN_LOG_LEVEL_INFO, + "Opened MongoDB URI <%s>\n", + pud->userdb); + } + } + } return mydbconnection; } static mongoc_collection_t * mongo_get_collection(const char * name) { - MONGO * mc = get_mydb_connection(NULL); + MONGO * mc = get_mongodb_connection(); if(!mc) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error gettting a connection to MongoDB\n"); - return NULL; + return NULL; } mongoc_collection_t * collection; From 95861605d76f7ffa894a563b3bf7e5f55d789256 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 12 Jul 2014 07:53:24 +0000 Subject: [PATCH 100/805] origin-to-realm map fixed --- src/apps/relay/dbdrivers/dbd_mongo.c | 10 +++++++--- src/apps/relay/dbdrivers/dbd_mysql.c | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index 28acbd1d..21a742de 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -815,6 +815,8 @@ static void mongo_reread_realms(secrets_list_t * realms_list) { if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "realm") && BSON_ITER_HOLDS_UTF8(&iter)) { char * _realm = strdup(bson_iter_utf8(&iter, &length)); + get_realm(_realm); + 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; @@ -827,9 +829,11 @@ static void mongo_reread_realms(secrets_list_t * realms_list) { 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); - ur_string_map_value_type value = strdup(_origin); - ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type)_realm, value); + char * _origin = strdup(bson_iter_utf8(&origin_iter, &length)); + char *rval = strdup(_realm); + ur_string_map_value_type value = (ur_string_map_value_type)(rval); + ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) _origin, value); + free(_origin); } } } diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 6027ffd7..37b4e426 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -741,14 +741,14 @@ static void mysql_reread_realms(secrets_list_t * realms_list) { oval[sz]=0; char *rval=strdup(row[1]); get_realm(rval); - ur_string_map_value_type value = strdup(rval); + ur_string_map_value_type value = (ur_string_map_value_type)rval; ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) oval, value); } } } } - update_o_to_realm(o_to_realm_new); + update_o_to_realm(o_to_realm_new); } if(mres) From b4a78d1af45c4a6448bd026a834fd11be8ff5645 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 13 Jul 2014 05:23:26 +0000 Subject: [PATCH 101/805] version bump --- src/ns_turn_defs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 636adde1..6f3ad994 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,8 +31,8 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.0.1.4" -#define TURN_SERVER_VERSION_NAME "Severard" +#define TURN_SERVER_VERSION "4.1.0.1" +#define TURN_SERVER_VERSION_NAME "Vitari" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" #if (defined(__unix__) || defined(unix)) && !defined(USG) From 541736ebed2dfbb3afd9fde5c74a25cd28d20aa1 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 13 Jul 2014 06:15:15 +0000 Subject: [PATCH 102/805] users list improved --- src/apps/relay/dbdrivers/dbd_mongo.c | 20 +++++++++++++++----- src/apps/relay/dbdrivers/dbd_mysql.c | 14 +++++++++----- src/apps/relay/dbdrivers/dbd_pgsql.c | 15 ++++++++++----- src/apps/relay/dbdrivers/dbd_redis.c | 2 +- 4 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index 21a742de..05707b80 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -386,6 +386,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); mongoc_cursor_t * cursor; cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL); @@ -398,14 +399,23 @@ static int mongo_list_users(int is_st, u08bits *realm) { 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, "name") && BSON_ITER_HOLDS_UTF8(&iter)) { - value = bson_iter_utf8(&iter, &length); - if (length) { - printf("%s\n", value); - } - } + 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); + } + if(realm && *realm) { + printf("%s[%s]\n", value, realm); + } else { + printf("%s\n", value); + } + } + } } mongoc_cursor_destroy(cursor); ret = 0; diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 37b4e426..42f5c2d8 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -400,11 +400,11 @@ static int mysql_list_users(int is_st, u08bits *realm) { MYSQL * myc = get_mydb_connection(); if(myc) { if(is_st) { - snprintf(statement,sizeof(statement),"select name from turnusers_st order by name"); + snprintf(statement,sizeof(statement),"select name,'' from turnusers_st order by name"); } else if(realm && realm[0]) { - snprintf(statement,sizeof(statement),"select name from turnusers_lt where realm='%s' order by name",realm); + snprintf(statement,sizeof(statement),"select name, realm from turnusers_lt where realm='%s' order by name",realm); } else { - snprintf(statement,sizeof(statement),"select name from turnusers_lt order by name"); + snprintf(statement,sizeof(statement),"select name, realm from turnusers_lt order by name"); } int res = mysql_query(myc, statement); if(res) { @@ -413,7 +413,7 @@ static int mysql_list_users(int is_st, 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(;;) { @@ -422,7 +422,11 @@ static int mysql_list_users(int is_st, u08bits *realm) { break; } else { if(row[0]) { - printf("%s\n",row[0]); + if(row[1] && row[1][0]) { + printf("%s[%s]\n",row[0],row[1]); + } else { + printf("%s\n",row[0]); + } } } } diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index d688e1c7..28737027 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -253,11 +253,11 @@ static int pgsql_list_users(int is_st, u08bits *realm) { PGconn *pqc = get_pqdb_connection(); if(pqc) { if(is_st) { - snprintf(statement,sizeof(statement),"select name from turnusers_st order by name"); + snprintf(statement,sizeof(statement),"select name,'' from turnusers_st order by name"); } else if(realm && realm[0]) { - snprintf(statement,sizeof(statement),"select name from turnusers_lt where realm='%s' order by name",realm); + snprintf(statement,sizeof(statement),"select name,realm from turnusers_lt where realm='%s' order by name",realm); } else { - snprintf(statement,sizeof(statement),"select name from turnusers_lt order by name"); + snprintf(statement,sizeof(statement),"select name,realm from turnusers_lt order by name"); } PGresult *res = PQexec(pqc, statement); if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) { @@ -267,10 +267,15 @@ static int pgsql_list_users(int is_st, u08bits *realm) { for(i=0;i Date: Sun, 13 Jul 2014 08:12:28 +0000 Subject: [PATCH 103/805] TODO updated --- TODO | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TODO b/TODO index d06abbbc..2b63675a 100644 --- a/TODO +++ b/TODO @@ -74,6 +74,8 @@ when necessary: 8) New security oAuth draft. +9) DTLS 1.2 (when available). + ================================================================== ### VII. MISC FEATURES ### From 82827f2314ad0c7f6e42c526210c654d52f0b0c5 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 13 Jul 2014 19:20:01 +0000 Subject: [PATCH 104/805] mongo test scripts adjusted --- .../scripts/longtermsecuredb/secure_relay_with_db_mongo.sh | 4 ++-- turndb/schema.mongo.sh | 2 +- turndb/testmongosetup.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh index b1f0670a..f5120014 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh @@ -15,7 +15,7 @@ # 3) use 3 relay threads (-m 3) # 4) use min UDP relay port 32355 and max UDP relay port 65535 # 5) "-r north.gov" means "use authentication realm north.gov" -# 6) --mongo-userdb="mongodb://localhost/turn" +# 6) --mongo-userdb="mongodb://localhost/coturn" # means that local MongoDB database "turn" will be used. # 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. @@ -30,4 +30,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/turn" --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 -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 $@ diff --git a/turndb/schema.mongo.sh b/turndb/schema.mongo.sh index 2bb65b65..c340a1be 100755 --- a/turndb/schema.mongo.sh +++ b/turndb/schema.mongo.sh @@ -2,7 +2,7 @@ mongo $* < Date: Sun, 13 Jul 2014 19:22:40 +0000 Subject: [PATCH 105/805] Changelog updated --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index eda878d8..5e4e64ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ 06/25/2014 Oleg Moskalenko Version 4.1.0.1 'Vitari': - SSODA support (TODO). - - MongoDB support (in progress) (Federico Pinna). + - DB "driver" abstraction and MongoDB support (Federico Pinna). - multiple origins supported per request. - "allocation mismatch" condition fixed (merged from rfc5766-turn-server). - STUN BINDING response fixed in the case of -X (external address) option. From 9b928bfaf965d53b600f4671dbac85d3e19f3a68 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 13 Jul 2014 23:29:59 +0000 Subject: [PATCH 106/805] compilation warning fixed --- src/apps/relay/dbdrivers/dbd_mongo.c | 2 +- src/apps/relay/userdb.c | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index 05707b80..18beef59 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -780,7 +780,7 @@ static int mongo_get_ip_list(const char *kind, ip_range_list_t * list) { while(mongoc_cursor_next(cursor, &item)) { if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "ip_range") && BSON_ITER_HOLDS_UTF8(&iter)) { value = bson_iter_utf8(&iter, &length); - add_ip_list_range(value, list); + add_ip_list_range(value, list); } } mongoc_cursor_destroy(cursor); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 59f75df6..94af2867 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -1249,8 +1249,10 @@ void update_white_and_black_lists(void) /////////////// add ACL record /////////////////// -int add_ip_list_range(const char * range, ip_range_list_t * list) +int add_ip_list_range(const char * range0, ip_range_list_t * list) { + char *range = strdup(range0); + char* separator = strchr(range, '-'); if (separator) { @@ -1261,12 +1263,14 @@ int add_ip_list_range(const char * range, ip_range_list_t * list) if (make_ioa_addr((const u08bits*) range, 0, &min) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong address format: %s\n", range); + free(range); return -1; } if (separator) { if (make_ioa_addr((const u08bits*) separator + 1, 0, &max) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong address format: %s\n", separator + 1); + free(range); return -1; } } else { @@ -1279,7 +1283,7 @@ int add_ip_list_range(const char * range, ip_range_list_t * list) ++(list->ranges_number); list->ranges = (char**) realloc(list->ranges, sizeof(char*) * list->ranges_number); - list->ranges[list->ranges_number - 1] = strdup(range); + list->ranges[list->ranges_number - 1] = range; list->encaddrsranges = (ioa_addr_range**) realloc(list->encaddrsranges, sizeof(ioa_addr_range*) * list->ranges_number); list->encaddrsranges[list->ranges_number - 1] = (ioa_addr_range*) turn_malloc(sizeof(ioa_addr_range)); From 1ae8964803d951c3458e7939db6355f8d5c6a158 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 14 Jul 2014 07:44:29 +0000 Subject: [PATCH 107/805] libevent setup fixed for CentOS --- rpm/CentOS6.pre.build.sh | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/rpm/CentOS6.pre.build.sh b/rpm/CentOS6.pre.build.sh index 7a37ac2f..2bb9306d 100755 --- a/rpm/CentOS6.pre.build.sh +++ b/rpm/CentOS6.pre.build.sh @@ -29,16 +29,6 @@ fi # Libevent2: -cd ${BUILDDIR}/SOURCES -if ! [ -f ${LIBEVENT_DISTRO} ] ; then - wget ${WGETOPTIONS} https://github.com/downloads/libevent/libevent/${LIBEVENT_DISTRO} - ER=$? - if ! [ ${ER} -eq 0 ] ; then - cd ${CPWD} - exit -1 - fi -fi - if ! [ -f ${BUILDDIR}/SPECS/${LIBEVENT_SPEC_FILE} ] ; then cd ${BUILDDIR}/tmp rm -rf ${LIBEVENT_SPEC_DIR} @@ -56,6 +46,7 @@ if ! [ -f ${BUILDDIR}/SPECS/${LIBEVENT_SPEC_FILE} ] ; then fi cp ${LIBEVENT_SPEC_DIR}/${LIBEVENT_SPEC_FILE} ${BUILDDIR}/SPECS + cp ${LIBEVENT_SPEC_DIR}/${LIBEVENT_DISTRO} ${BUILDDIR}/SOURCES fi cd ${BUILDDIR}/SPECS From f7f1784fc1ddb6d8cbcedf989df424ae82efa202 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 16 Jul 2014 07:04:11 +0000 Subject: [PATCH 108/805] working on dual allocation --- README.turnutils | 2 + man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 2 +- man/man1/turnutils.1 | 6 ++- src/apps/common/stun_buffer.c | 9 ++-- src/apps/common/stun_buffer.h | 5 +- src/apps/uclient/mainuclient.c | 8 ++- src/apps/uclient/startuclient.c | 7 ++- src/apps/uclient/uclient.h | 1 + src/client++/TurnMsgLib.h | 9 ++-- src/client/ns_turn_msg.c | 34 ++++++------ src/client/ns_turn_msg.h | 4 +- src/server/ns_turn_server.c | 91 ++++++++++++++++++++++++--------- 13 files changed, 123 insertions(+), 57 deletions(-) diff --git a/README.turnutils b/README.turnutils index a9462d5e..e1e1901f 100644 --- a/README.turnutils +++ b/README.turnutils @@ -115,6 +115,8 @@ Flags: -B Random disconnect after a few initial packets. +-Z Dual allocation. + Options with required values: -l Message length (Default: 100 Bytes). diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 127c3eb5..7eb719d0 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "11 July 2014" "" "" +.TH TURN 1 "15 July 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 47af6d2b..46fe5c28 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "11 July 2014" "" "" +.TH TURN 1 "15 July 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index d507b920..68f1c3d5 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "11 July 2014" "" "" +.TH TURN 1 "15 July 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -173,6 +173,10 @@ Generate extra requests (create permissions, channel bind). Random disconnect after a few initial packets. .TP .B +\fB\-Z\fP +Dual allocation. +.TP +.B Options with required values: .TP .B diff --git a/src/apps/common/stun_buffer.c b/src/apps/common/stun_buffer.c index eac2fc01..09990e65 100644 --- a/src/apps/common/stun_buffer.c +++ b/src/apps/common/stun_buffer.c @@ -153,17 +153,18 @@ int stun_is_channel_message(stun_buffer* buf, u16bits* chnumber, int is_padding_ /////////////////////////////////////////////////////////////////////////////// -int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int address_family, u08bits transport, int mobile) { - return stun_set_allocate_request_str(buf->buf, (size_t*)(&(buf->len)), lifetime, address_family, transport, mobile); +int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int af4, int af6, u08bits transport, int mobile) { + return stun_set_allocate_request_str(buf->buf, (size_t*)(&(buf->len)), lifetime, af4, af6, transport, mobile); } int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid, - const ioa_addr *relayed_addr, const ioa_addr *reflexive_addr, + const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2, + const ioa_addr *reflexive_addr, u32bits lifetime, int error_code, const u08bits *reason, u64bits reservation_token, char *mobile_id) { return stun_set_allocate_response_str(buf->buf, (size_t*)(&(buf->len)), tid, - relayed_addr, reflexive_addr, + relayed_addr1, relayed_addr2, reflexive_addr, lifetime, error_code, reason, reservation_token, mobile_id); diff --git a/src/apps/common/stun_buffer.h b/src/apps/common/stun_buffer.h index 7a4e0fe5..0d3e3608 100644 --- a/src/apps/common/stun_buffer.h +++ b/src/apps/common/stun_buffer.h @@ -101,9 +101,10 @@ int stun_is_channel_message(stun_buffer* buf, u16bits* chnumber, int is_padding_ /////////////////////////////////////////////////////////////// -int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int address_family, u08bits transport, int mobile); +int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int af4, int af6, u08bits transport, int mobile); int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid, - const ioa_addr *relayed_addr, const ioa_addr *reflexive_addr, + const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2, + const ioa_addr *reflexive_addr, u32bits lifetime, int error_code, const u08bits *reason, u64bits reservation_token, char *mobile_id); diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 437c69cb..37566b95 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -95,6 +95,8 @@ char origin[STUN_MAX_ORIGIN_SIZE+1] = "\0"; band_limit_t bps = 0; +int dual_allocation = 0; + //////////////// local definitions ///////////////// static char Usage[] = @@ -127,6 +129,7 @@ static char Usage[] = " (for testing the non-standard server relay functionality).\n" " -G Generate extra requests (create permissions, channel bind).\n" " -B Random disconnect after a few initial packets.\n" + " -Z Dual allocation.\n" "Options:\n" " -l Message length (Default: 100 Bytes).\n" " -i Certificate file (for secure connections only, optional).\n" @@ -201,7 +204,7 @@ int main(int argc, char **argv) ns_bzero(local_addr, sizeof(local_addr)); - while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:vsyhcxXgtTSAPDNOUHMRIGB")) != -1) { + while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:ZvsyhcxXgtTSAPDNOUHMRIGB")) != -1) { switch (c){ case 'a': bps = (band_limit_t)atol(optarg); @@ -255,6 +258,9 @@ int main(int argc, char **argv) case 'z': RTP_PACKET_INTERVAL = atoi(optarg); break; + case 'Z': + dual_allocation = 1; + break; case 'A': use_short_term = 1; break; diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index d4c35229..e9251aa5 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -338,10 +338,13 @@ static int clnet_allocate(int verbose, af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT; } + int af4 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4); + int af6 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6); + if(!dos) - stun_set_allocate_request(&message, 800, af, relay_transport, mobility); + stun_set_allocate_request(&message, 800, af4, af6, relay_transport, mobility); else - stun_set_allocate_request(&message, 300, af, relay_transport, mobility); + stun_set_allocate_request(&message, 300, af4, af6, relay_transport, mobility); if(bps) stun_attr_add_bandwidth_str(message.buf, (size_t*)(&(message.len)), bps); diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index 6c3bad3d..ab56bf8b 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -82,6 +82,7 @@ extern int mobility; extern int no_permissions; extern int extra_requests; extern band_limit_t bps; +extern int dual_allocation; extern char origin[STUN_MAX_ORIGIN_SIZE+1]; diff --git a/src/client++/TurnMsgLib.h b/src/client++/TurnMsgLib.h index db97acc6..b5b46abb 100644 --- a/src/client++/TurnMsgLib.h +++ b/src/client++/TurnMsgLib.h @@ -848,8 +848,8 @@ public: /** * Construct allocate request */ - void constructAllocateRequest(u32bits lifetime, int address_family, u08bits transport, int mobile) { - stun_set_allocate_request_str(_buffer, &_sz, lifetime, address_family, transport, mobile); + void constructAllocateRequest(u32bits lifetime, int af4, int af6, u08bits transport, int mobile) { + stun_set_allocate_request_str(_buffer, &_sz, lifetime, af4, af6, transport, mobile); } /** @@ -1011,13 +1011,14 @@ public: * Construct allocate response */ void constructAllocateResponse(stun_tid &tid, - const ioa_addr &relayed_addr, + const ioa_addr &relayed_addr1, + const ioa_addr &relayed_addr2, const ioa_addr &reflexive_addr, u32bits lifetime, int error_code, const u08bits *reason, u64bits reservation_token, char *mobile_id) { stun_set_allocate_response_str(_buffer, &_sz, &tid, - &relayed_addr, + &relayed_addr1, &relayed_addr2, &reflexive_addr, lifetime, error_code, reason, reservation_token, mobile_id); diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index b5d69d91..19349b6e 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -644,7 +644,7 @@ int stun_get_message_len_str(u08bits *buf, size_t blen, int padding, size_t *app ////////// ALLOCATE /////////////////////////////////// -int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int address_family, +int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int af4, int af6, u08bits transport, int mobile) { stun_init_request_str(STUN_METHOD_ALLOCATE, buf, len); @@ -671,30 +671,30 @@ int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, i } //ADRESS-FAMILY - switch (address_family) { - case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: - case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: - { + if (af4) { u08bits field[4]; - field[0] = (u08bits)address_family; + field[0] = (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4; field[1]=0; field[2]=0; field[3]=0; if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1; - break; } - case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT: - /* ignore */ - break; - default: - return -1; + + if (af6) { + u08bits field[4]; + field[0] = (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; + field[1]=0; + field[2]=0; + field[3]=0; + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1; }; return 0; } int stun_set_allocate_response_str(u08bits* buf, size_t *len, stun_tid* tid, - const ioa_addr *relayed_addr, const ioa_addr *reflexive_addr, + const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2, + const ioa_addr *reflexive_addr, u32bits lifetime, int error_code, const u08bits *reason, u64bits reservation_token, char* mobile_id) { @@ -702,8 +702,12 @@ int stun_set_allocate_response_str(u08bits* buf, size_t *len, stun_tid* tid, stun_init_success_response_str(STUN_METHOD_ALLOCATE, buf, len, tid); - if(relayed_addr) { - if(stun_attr_add_addr_str(buf,len,STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS,relayed_addr)<0) return -1; + if(relayed_addr1) { + if(stun_attr_add_addr_str(buf,len,STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS,relayed_addr1)<0) return -1; + } + + if(relayed_addr2) { + if(stun_attr_add_addr_str(buf,len,STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS,relayed_addr2)<0) return -1; } if(reflexive_addr) { diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 33cb9561..04f6d170 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -155,9 +155,9 @@ int stun_attr_add_channel_number_str(u08bits* buf, size_t *len, u16bits chnumber int stun_attr_add_bandwidth_str(u08bits* buf, size_t *len, band_limit_t bps); u16bits stun_attr_get_first_channel_number_str(const u08bits *buf, size_t len); -int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int address_family, u08bits transport, int mobile); +int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int af4, int af6, u08bits transport, int mobile); int stun_set_allocate_response_str(u08bits* buf, size_t *len, stun_tid* tid, - const ioa_addr *relayed_addr, + const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2, const ioa_addr *reflexive_addr, u32bits lifetime, int error_code, const u08bits *reason, u64bits reservation_token, char *mobile_id); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index fb31db19..5257dde4 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -899,22 +899,43 @@ static int handle_turn_allocate(turn_turnserver *server, *reason = (const u08bits *)"Wrong TID"; } else { size_t len = ioa_network_buffer_get_size(nbh); - ioa_addr xor_relayed_addr; - ioa_addr *relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET)); - if(!relayed_addr) - relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET6)); - if(relayed_addr) { + ioa_addr xor_relayed_addr1, *pxor_relayed_addr1=NULL; + ioa_addr xor_relayed_addr2, *pxor_relayed_addr2=NULL; + ioa_addr *relayed_addr1 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET)); + ioa_addr *relayed_addr2 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET6)); + + if(relayed_addr1) { if(server->external_ip_set) { - addr_cpy(&xor_relayed_addr, &(server->external_ip)); - addr_set_port(&xor_relayed_addr,addr_get_port(relayed_addr)); + addr_cpy(&xor_relayed_addr1, &(server->external_ip)); + addr_set_port(&xor_relayed_addr1,addr_get_port(relayed_addr1)); } else { - addr_cpy(&xor_relayed_addr, relayed_addr); + addr_cpy(&xor_relayed_addr1, relayed_addr1); + } + pxor_relayed_addr1 = &xor_relayed_addr1; + } + + if(relayed_addr2) { + if(server->external_ip_set) { + addr_cpy(&xor_relayed_addr2, &(server->external_ip)); + addr_set_port(&xor_relayed_addr2,addr_get_port(relayed_addr2)); + } else { + addr_cpy(&xor_relayed_addr2, relayed_addr2); + } + pxor_relayed_addr2 = &xor_relayed_addr2; + } + + if(pxor_relayed_addr1 || pxor_relayed_addr2) { + u32bits lifetime = 0; + if(pxor_relayed_addr1) { + lifetime = (get_relay_session(a,pxor_relayed_addr1->ss.sa_family)->expiration_time - server->ctime); + } else if(pxor_relayed_addr2) { + lifetime = (get_relay_session(a,pxor_relayed_addr2->ss.sa_family)->expiration_time - server->ctime); } stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid, - &xor_relayed_addr, + pxor_relayed_addr1, pxor_relayed_addr2, get_remote_addr_from_ioa_socket(ss->client_socket), - (get_relay_session(a,relayed_addr->ss.sa_family)->expiration_time - server->ctime), 0, NULL, 0, + lifetime, 0, NULL, 0, ss->s_mobile_id); ioa_network_buffer_set_size(nbh,len); *resp_constructed = 1; @@ -930,7 +951,8 @@ static int handle_turn_allocate(turn_turnserver *server, int even_port = -1; int dont_fragment = 0; u64bits in_reservation_token = 0; - int af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT; + int af4 = 0; + int af6 = 0; u08bits username[STUN_MAX_USERNAME_SIZE+1]="\0"; size_t ulen = 0; band_limit_t bps = 0; @@ -1047,7 +1069,7 @@ static int handle_turn_allocate(turn_turnserver *server, if (len != 8) { *err_code = 400; *reason = (const u08bits *)"Wrong Format of Reservation Token"; - } else if(af != STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT) { + } else if(af4 || af6) { *err_code = 400; *reason = (const u08bits *)"Address family attribute can not be used with reservation token request"; } else { @@ -1069,11 +1091,13 @@ static int handle_turn_allocate(turn_turnserver *server, *reason = (const u08bits *)"Address family attribute can not be used with reservation token request"; } else { int af_req = stun_get_requested_address_family(sar); - if(af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT) { + if(!af4 && !af6) { switch (af_req) { case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: + af4 = 1; + break; case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: - af = af_req; + af6 = 1; break; default: *err_code = 440; @@ -1149,6 +1173,10 @@ static int handle_turn_allocate(turn_turnserver *server, } } + int af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT; + if(af4) af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4; + else if(af6) af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; + if (*err_code || create_relay_connection(server, ss, lifetime, af, transport, even_port, in_reservation_token, &out_reservation_token, @@ -1173,20 +1201,35 @@ static int handle_turn_allocate(turn_turnserver *server, size_t len = ioa_network_buffer_get_size(nbh); - ioa_addr xor_relayed_addr; - ioa_addr *relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET)); - if(!relayed_addr) - relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET6)); - if(relayed_addr) { + ioa_addr xor_relayed_addr1, *pxor_relayed_addr1=NULL; + ioa_addr xor_relayed_addr2, *pxor_relayed_addr2=NULL; + ioa_addr *relayed_addr1 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET)); + ioa_addr *relayed_addr2 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET6)); + + if(relayed_addr1) { if(server->external_ip_set) { - addr_cpy(&xor_relayed_addr, &(server->external_ip)); - addr_set_port(&xor_relayed_addr,addr_get_port(relayed_addr)); + addr_cpy(&xor_relayed_addr1, &(server->external_ip)); + addr_set_port(&xor_relayed_addr1,addr_get_port(relayed_addr1)); } else { - addr_cpy(&xor_relayed_addr, relayed_addr); + addr_cpy(&xor_relayed_addr1, relayed_addr1); } + pxor_relayed_addr1 = &xor_relayed_addr1; + } + + if(relayed_addr2) { + if(server->external_ip_set) { + addr_cpy(&xor_relayed_addr2, &(server->external_ip)); + addr_set_port(&xor_relayed_addr2,addr_get_port(relayed_addr2)); + } else { + addr_cpy(&xor_relayed_addr2, relayed_addr2); + } + pxor_relayed_addr2 = &xor_relayed_addr2; + } + + if(pxor_relayed_addr1 || pxor_relayed_addr2) { stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid, - &xor_relayed_addr, + pxor_relayed_addr1, pxor_relayed_addr2, get_remote_addr_from_ioa_socket(ss->client_socket), lifetime, 0,NULL, out_reservation_token, @@ -1213,7 +1256,7 @@ static int handle_turn_allocate(turn_turnserver *server, } size_t len = ioa_network_buffer_get_size(nbh); - stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid, NULL, NULL, 0, *err_code, *reason, 0, ss->s_mobile_id); + stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid, NULL, NULL, NULL, 0, *err_code, *reason, 0, ss->s_mobile_id); ioa_network_buffer_set_size(nbh,len); *resp_constructed = 1; } From e15ea092fd6deffee34270863433e450a608b022 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 16 Jul 2014 07:21:44 +0000 Subject: [PATCH 109/805] working on dual allocation --- src/server/ns_turn_server.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 5257dde4..60a6e4ff 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1177,6 +1177,13 @@ static int handle_turn_allocate(turn_turnserver *server, if(af4) af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4; else if(af6) af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; + if(af4 && af6) { + if(server->external_ip_set) { + *err_code = 440; + *reason = (const u08bits *)"Dual allocation cannot be supported in the current server configuration"; + } + } + if (*err_code || create_relay_connection(server, ss, lifetime, af, transport, even_port, in_reservation_token, &out_reservation_token, From 651c5204a47160e6802a5aa3f99d05a05abecddf Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 17 Jul 2014 05:33:04 +0000 Subject: [PATCH 110/805] working on double allocation --- src/server/ns_turn_allocation.c | 10 ++++++++++ src/server/ns_turn_allocation.h | 3 +++ src/server/ns_turn_server.c | 20 ++++++++++++++++---- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/server/ns_turn_allocation.c b/src/server/ns_turn_allocation.c index b39e6bad..89b946b3 100644 --- a/src/server/ns_turn_allocation.c +++ b/src/server/ns_turn_allocation.c @@ -92,6 +92,16 @@ relay_endpoint_session *get_relay_session(allocation *a, int family) return &(a->relay_sessions[ALLOC_INDEX(family)]); } +int get_relay_session_failure(allocation *a, int family) +{ + return a->relay_sessions_failure[ALLOC_INDEX(family)]; +} + +void set_relay_session_failure(allocation *a, int family) +{ + a->relay_sessions_failure[ALLOC_INDEX(family)] = 1; +} + ioa_socket_handle get_relay_socket(allocation *a, int family) { return a->relay_sessions[ALLOC_INDEX(family)].s; diff --git a/src/server/ns_turn_allocation.h b/src/server/ns_turn_allocation.h index 40b068a4..5f84f2f9 100644 --- a/src/server/ns_turn_allocation.h +++ b/src/server/ns_turn_allocation.h @@ -176,6 +176,7 @@ typedef struct _allocation { stun_tid tid; turn_permission_hashtable addr_to_perm; relay_endpoint_session relay_sessions[ALLOC_PROTOCOLS_NUMBER]; + int relay_sessions_failure[ALLOC_PROTOCOLS_NUMBER]; ch_map chns; /* chnum-to-ch_info* */ void *owner; //ss ur_map *tcp_connections; //global (per turn server) reference @@ -208,6 +209,8 @@ ch_info* allocation_get_ch_info(allocation* a, u16bits chnum); ch_info* allocation_get_ch_info_by_peer_addr(allocation* a, ioa_addr* peer_addr); relay_endpoint_session *get_relay_session(allocation *a, int family); +int get_relay_session_failure(allocation *a, int family); +void set_relay_session_failure(allocation *a, int family); ioa_socket_handle get_relay_socket(allocation *a, int family); tcp_connection *get_and_clean_tcp_connection_by_id(ur_map *map, tcp_connection_id id); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 60a6e4ff..b8a2c25a 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -904,7 +904,10 @@ static int handle_turn_allocate(turn_turnserver *server, ioa_addr *relayed_addr1 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET)); ioa_addr *relayed_addr2 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET6)); - if(relayed_addr1) { + if(get_relay_session_failure(a,AF_INET)) { + addr_set_any(&xor_relayed_addr1); + pxor_relayed_addr1 = &xor_relayed_addr1; + } else if(relayed_addr1) { if(server->external_ip_set) { addr_cpy(&xor_relayed_addr1, &(server->external_ip)); addr_set_port(&xor_relayed_addr1,addr_get_port(relayed_addr1)); @@ -914,7 +917,10 @@ static int handle_turn_allocate(turn_turnserver *server, pxor_relayed_addr1 = &xor_relayed_addr1; } - if(relayed_addr2) { + if(get_relay_session_failure(a,AF_INET6)) { + addr_set_any(&xor_relayed_addr2); + pxor_relayed_addr2 = &xor_relayed_addr2; + } else if(relayed_addr2) { if(server->external_ip_set) { addr_cpy(&xor_relayed_addr2, &(server->external_ip)); addr_set_port(&xor_relayed_addr2,addr_get_port(relayed_addr2)); @@ -1213,7 +1219,10 @@ static int handle_turn_allocate(turn_turnserver *server, ioa_addr *relayed_addr1 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET)); ioa_addr *relayed_addr2 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET6)); - if(relayed_addr1) { + if(get_relay_session_failure(a,AF_INET)) { + addr_set_any(&xor_relayed_addr1); + pxor_relayed_addr1 = &xor_relayed_addr1; + } else if(relayed_addr1) { if(server->external_ip_set) { addr_cpy(&xor_relayed_addr1, &(server->external_ip)); addr_set_port(&xor_relayed_addr1,addr_get_port(relayed_addr1)); @@ -1223,7 +1232,10 @@ static int handle_turn_allocate(turn_turnserver *server, pxor_relayed_addr1 = &xor_relayed_addr1; } - if(relayed_addr2) { + if(get_relay_session_failure(a,AF_INET6)) { + addr_set_any(&xor_relayed_addr2); + pxor_relayed_addr2 = &xor_relayed_addr2; + } else if(relayed_addr2) { if(server->external_ip_set) { addr_cpy(&xor_relayed_addr2, &(server->external_ip)); addr_set_port(&xor_relayed_addr2,addr_get_port(relayed_addr2)); From 74c1fd3038b2566a4e7d7f30c7f2549ffbc14950 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 17 Jul 2014 08:04:52 +0000 Subject: [PATCH 111/805] working on double allocation --- src/apps/uclient/startuclient.c | 68 ++++++++++++++++----- src/server/ns_turn_server.c | 102 +++++++++++++++++++++++++------- 2 files changed, 135 insertions(+), 35 deletions(-) diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index e9251aa5..9557ea7a 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -341,6 +341,13 @@ static int clnet_allocate(int verbose, int af4 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4); int af6 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6); + if(!no_rtcp && !in_tid) { + if (!never_allocate_rtcp && allocate_rtcp) { + af4 = 0; + af6 = 0; + } + } + if(!dos) stun_set_allocate_request(&message, 800, af4, af6, relay_transport, mobility); else @@ -433,22 +440,55 @@ static int clnet_allocate(int verbose, if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); } - if (stun_attr_get_first_addr(&message, - STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, relay_addr, - NULL) < 0) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, - "%s: !!!: relay addr cannot be received\n", - __FUNCTION__); - return -1; - } else { - if (verbose) { - ioa_addr remote_addr; - memcpy(&remote_addr, relay_addr, - sizeof(ioa_addr)); - addr_debug_print(verbose, &remote_addr, - "Received relay addr"); + { + int found = 0; + + stun_attr_ref sar = stun_attr_get_first(&message); + while (sar) { + + int attr_type = stun_attr_get_type(sar); + if(attr_type == STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS) { + + if (stun_attr_get_addr(&message, sar, relay_addr, NULL) < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: !!!: relay addr cannot be received (1)\n", + __FUNCTION__); + return -1; + } else { + if (verbose) { + ioa_addr remote_addr; + memcpy(&remote_addr, relay_addr,sizeof(ioa_addr)); + addr_debug_print(verbose, &remote_addr,"Received relay addr"); + } + + if(!addr_any(relay_addr)) { + if(relay_addr->ss.sa_family == AF_INET) { + if(default_address_family != STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6) { + found = 1; + break; + } + } + if(relay_addr->ss.sa_family == AF_INET6) { + if(default_address_family == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6) { + found = 1; + break; + } + } + } + } + } + + sar = stun_attr_get_next(&message,sar); + } + + if(!found) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "%s: !!!: relay addr cannot be received (2)\n", + __FUNCTION__); + return -1; } } + stun_attr_ref rt_sar = stun_attr_get_first_by_type( &message, STUN_ATTRIBUTE_RESERVATION_TOKEN); uint64_t rtv = stun_attr_get_reservation_token_value(rt_sar); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index b8a2c25a..a7555e4c 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1097,21 +1097,16 @@ static int handle_turn_allocate(turn_turnserver *server, *reason = (const u08bits *)"Address family attribute can not be used with reservation token request"; } else { int af_req = stun_get_requested_address_family(sar); - if(!af4 && !af6) { - switch (af_req) { - case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: - af4 = 1; - break; - case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: - af6 = 1; - break; - default: - *err_code = 440; - *reason = (const u08bits *)"Unsupported address family requested"; - } - } else { - *err_code = 400; - *reason = (const u08bits *)"Only one address family attribute can be used in a request"; + switch (af_req) { + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: + af4 = af_req; + break; + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: + af6 = af_req; + break; + default: + *err_code = 440; + *reason = (const u08bits *)"Unsupported address family requested"; } } } @@ -1179,22 +1174,87 @@ static int handle_turn_allocate(turn_turnserver *server, } } - int af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT; - if(af4) af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4; - else if(af6) af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; + if(af4) af4 = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4; + if(af6) af6 = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; if(af4 && af6) { if(server->external_ip_set) { *err_code = 440; *reason = (const u08bits *)"Dual allocation cannot be supported in the current server configuration"; } + if(even_port >= 0) { + *err_code = 440; + *reason = (const u08bits *)"Dual allocation cannot be supported with even-port functionality"; + } } - if (*err_code || create_relay_connection(server, ss, lifetime, - af, transport, + if(!(*err_code)) { + if(!af4 && !af6) { + create_relay_connection(server, ss, lifetime, + STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT, transport, even_port, in_reservation_token, &out_reservation_token, err_code, reason, - tcp_peer_accept_connection) < 0) { + tcp_peer_accept_connection); + } else if(!af4 && af6) { + create_relay_connection(server, ss, lifetime, + af6, transport, + even_port, in_reservation_token, &out_reservation_token, + err_code, reason, + tcp_peer_accept_connection); + } else if(af4 && !af6) { + create_relay_connection(server, ss, lifetime, + af4, transport, + even_port, in_reservation_token, &out_reservation_token, + err_code, reason, + tcp_peer_accept_connection); + } else { + int err_code4 = 0; + const u08bits *reason4 = NULL; + if(af4) { + int af4res = create_relay_connection(server, ss, lifetime, + af4, transport, + even_port, in_reservation_token, &out_reservation_token, + &err_code4, &reason4, + tcp_peer_accept_connection); + if(af4res<0) { + set_relay_session_failure(a,AF_INET); + if(!err_code4) { + err_code4 = 437; + } + } + } + int err_code6 = 0; + const u08bits *reason6 = NULL; + if(af6) { + int af6res = create_relay_connection(server, ss, lifetime, + af6, transport, + even_port, in_reservation_token, &out_reservation_token, + &err_code6, &reason6, + tcp_peer_accept_connection); + if(af6res<0) { + set_relay_session_failure(a,AF_INET6); + if(!err_code6) { + err_code6 = 437; + } + } + } + + if(err_code4 && err_code6) { + if(reason4) { + *err_code = err_code4; + *reason = reason4; + } else if(reason6) { + *err_code = err_code6; + *reason = reason6; + } else { + *err_code = err_code4; + } + } + } + } + + + if (*err_code) { dec_quota(ss); From a56ec138fbf8a40ba348f8672e14e7b1c1caca7f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 18 Jul 2014 07:23:02 +0000 Subject: [PATCH 112/805] working on dual allocation --- src/server/ns_turn_allocation.c | 27 ++++++++- src/server/ns_turn_allocation.h | 1 + src/server/ns_turn_server.c | 97 +++++++++++++++++++++++++++------ 3 files changed, 106 insertions(+), 19 deletions(-) diff --git a/src/server/ns_turn_allocation.c b/src/server/ns_turn_allocation.c index 89b946b3..e7254208 100644 --- a/src/server/ns_turn_allocation.c +++ b/src/server/ns_turn_allocation.c @@ -62,7 +62,6 @@ void clear_allocation(allocation *a) if(tc) { delete_tcp_connection(tc); a->tcs.elems[i] = NULL; - break; } } turn_free(a->tcs.elems,sz*sizeof(tcp_connection*)); @@ -107,6 +106,32 @@ ioa_socket_handle get_relay_socket(allocation *a, int family) return a->relay_sessions[ALLOC_INDEX(family)].s; } +void set_allocation_family_invalid(allocation *a, int family) +{ + if(a) { + size_t index = ALLOC_INDEX(family); + if(a->relay_sessions[index].s) { + if(a->tcs.elems) { + size_t i; + size_t sz = a->tcs.sz; + for(i=0;itcs.elems[i]; + if(tc) { + if(tc->peer_s && (get_ioa_socket_address_family(tc->peer_s) == family)) { + delete_tcp_connection(tc); + a->tcs.elems[i] = NULL; + } + } + } + } + + clear_ioa_socket_session_if(a->relay_sessions[index].s, a->owner); + clear_relay_endpoint_session_data(&(a->relay_sessions[index])); + IOA_EVENT_DEL(a->relay_sessions[index].lifetime_ev); + } + } +} + void set_allocation_lifetime_ev(allocation *a, turn_time_t exp_time, ioa_timer_handle ev, int family) { if (a) { diff --git a/src/server/ns_turn_allocation.h b/src/server/ns_turn_allocation.h index 5f84f2f9..96da5684 100644 --- a/src/server/ns_turn_allocation.h +++ b/src/server/ns_turn_allocation.h @@ -212,6 +212,7 @@ relay_endpoint_session *get_relay_session(allocation *a, int family); int get_relay_session_failure(allocation *a, int family); void set_relay_session_failure(allocation *a, int family); ioa_socket_handle get_relay_socket(allocation *a, int family); +void set_allocation_family_invalid(allocation *a, int family); tcp_connection *get_and_clean_tcp_connection_by_id(ur_map *map, tcp_connection_id id); tcp_connection *get_tcp_connection_by_id(ur_map *map, tcp_connection_id id); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index a7555e4c..768c4dd5 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1190,23 +1190,41 @@ static int handle_turn_allocate(turn_turnserver *server, if(!(*err_code)) { if(!af4 && !af6) { - create_relay_connection(server, ss, lifetime, + int af4res = create_relay_connection(server, ss, lifetime, STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT, transport, even_port, in_reservation_token, &out_reservation_token, err_code, reason, tcp_peer_accept_connection); + if(af4res<0) { + set_relay_session_failure(a,AF_INET); + if(!(*err_code)) { + *err_code = 437; + } + } } else if(!af4 && af6) { - create_relay_connection(server, ss, lifetime, + int af6res = create_relay_connection(server, ss, lifetime, af6, transport, even_port, in_reservation_token, &out_reservation_token, err_code, reason, tcp_peer_accept_connection); + if(af6res<0) { + set_relay_session_failure(a,AF_INET6); + if(!(*err_code)) { + *err_code = 437; + } + } } else if(af4 && !af6) { - create_relay_connection(server, ss, lifetime, + int af4res = create_relay_connection(server, ss, lifetime, af4, transport, even_port, in_reservation_token, &out_reservation_token, err_code, reason, tcp_peer_accept_connection); + if(af4res<0) { + set_relay_session_failure(a,AF_INET); + if(!(*err_code)) { + *err_code = 437; + } + } } else { int err_code4 = 0; const u08bits *reason4 = NULL; @@ -1253,15 +1271,12 @@ static int handle_turn_allocate(turn_turnserver *server, } } - if (*err_code) { dec_quota(ss); - if (!*err_code) { - *err_code = 437; - if(!(*reason)) - *reason = (const u08bits *)"Cannot create relay endpoint"; + if(!(*reason)) { + *reason = (const u08bits *)"Cannot create relay endpoint(s)"; } } else { @@ -1350,13 +1365,20 @@ static int handle_turn_refresh(turn_turnserver *server, int message_integrity, int *no_response, int can_resume) { allocation* a = get_allocation_ss(ss); - int family = AF_INET; + int af4c = 0; + int af6c = 0; + int af4 = 0; + int af6 = 0; { int i; for(i = 0;irelay_sessions[i].s) { - family = get_local_addr_from_ioa_socket(a->relay_sessions[i].s)->ss.sa_family; - break; + int family = get_local_addr_from_ioa_socket(a->relay_sessions[i].s)->ss.sa_family; + if(AF_INET == family) { + af4c = 1; + } else if(AF_INET6 == family) { + af6c = 1; + } } } } @@ -1424,13 +1446,17 @@ static int handle_turn_refresh(turn_turnserver *server, int is_err = 0; switch (af_req) { case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: - if(family != AF_INET) { + if(!af4c) { is_err = 1; + } else { + af4 = 1; } break; case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: - if(family != AF_INET6) { + if(!af6c) { is_err = 1; + } else { + af6 = 1; } break; default: @@ -1531,8 +1557,16 @@ static int handle_turn_refresh(turn_turnserver *server, else lifetime = stun_adjust_allocate_lifetime(lifetime); - if (refresh_relay_connection(server, orig_ss, lifetime, 0, 0, 0, - err_code, family) < 0) { + if (af4c && refresh_relay_connection(server, orig_ss, lifetime, 0, 0, 0, + err_code, AF_INET) < 0) { + + if (!(*err_code)) { + *err_code = 437; + *reason = (const u08bits *)"Cannot refresh relay connection (internal error)"; + } + + } else if (af6c && refresh_relay_connection(server, orig_ss, lifetime, 0, 0, 0, + err_code, AF_INET6) < 0) { if (!(*err_code)) { *err_code = 437; @@ -1632,8 +1666,21 @@ static int handle_turn_refresh(turn_turnserver *server, else lifetime = stun_adjust_allocate_lifetime(lifetime); - if (refresh_relay_connection(server, ss, lifetime, 0, 0, 0, - err_code, family) < 0) { + if(!af4 && !af6) { + af4 = af4c; + af6 = af6c; + } + + if (af4 && refresh_relay_connection(server, ss, lifetime, 0, 0, 0, + err_code, AF_INET) < 0) { + + if (!(*err_code)) { + *err_code = 437; + *reason = (const u08bits *)"Cannot refresh relay connection (internal error)"; + } + + } else if (af6 && refresh_relay_connection(server, ss, lifetime, 0, 0, 0, + err_code, AF_INET6) < 0) { if (!(*err_code)) { *err_code = 437; @@ -4162,7 +4209,21 @@ static int refresh_relay_connection(turn_turnserver* server, if (server && ss && is_allocation_valid(a)) { if (lifetime < 1) { - set_allocation_valid(&(ss->alloc),0); + + set_allocation_family_invalid(&(ss->alloc),family); + + if(family == AF_INET) { + if(get_relay_socket(&(ss->alloc), AF_INET6)) { + return 0; + } + } + + if(family == AF_INET6) { + if(get_relay_socket(&(ss->alloc), AF_INET)) { + return 0; + } + } + lifetime = 1; } From 16c41f88807bb804cc539a827cb7fb0e8ca64c70 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 19 Jul 2014 07:43:07 +0000 Subject: [PATCH 113/805] working on double allocations --- src/server/ns_turn_allocation.c | 15 +++++-- src/server/ns_turn_server.c | 70 +++++++++++++++------------------ 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/src/server/ns_turn_allocation.c b/src/server/ns_turn_allocation.c index e7254208..26980dde 100644 --- a/src/server/ns_turn_allocation.c +++ b/src/server/ns_turn_allocation.c @@ -88,22 +88,29 @@ void clear_allocation(allocation *a) relay_endpoint_session *get_relay_session(allocation *a, int family) { - return &(a->relay_sessions[ALLOC_INDEX(family)]); + if(a) + return &(a->relay_sessions[ALLOC_INDEX(family)]); + return NULL; } int get_relay_session_failure(allocation *a, int family) { - return a->relay_sessions_failure[ALLOC_INDEX(family)]; + if(a) + return a->relay_sessions_failure[ALLOC_INDEX(family)]; + return 0; } void set_relay_session_failure(allocation *a, int family) { - a->relay_sessions_failure[ALLOC_INDEX(family)] = 1; + if(a) + a->relay_sessions_failure[ALLOC_INDEX(family)] = 1; } ioa_socket_handle get_relay_socket(allocation *a, int family) { - return a->relay_sessions[ALLOC_INDEX(family)].s; + if(a) + return a->relay_sessions[ALLOC_INDEX(family)].s; + return NULL; } void set_allocation_family_invalid(allocation *a, int family) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 768c4dd5..cc4ea85e 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -890,11 +890,11 @@ static int handle_turn_allocate(turn_turnserver *server, int *err_code, const u08bits **reason, u16bits *unknown_attrs, u16bits *ua_num, ioa_net_data *in_buffer, ioa_network_buffer_handle nbh) { - allocation* a = get_allocation_ss(ss); + allocation* alloc = get_allocation_ss(ss); - if (is_allocation_valid(a)) { + if (is_allocation_valid(alloc)) { - if (!stun_tid_equals(tid, &(a->tid))) { + if (!stun_tid_equals(tid, &(alloc->tid))) { *err_code = 437; *reason = (const u08bits *)"Wrong TID"; } else { @@ -904,7 +904,7 @@ static int handle_turn_allocate(turn_turnserver *server, ioa_addr *relayed_addr1 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET)); ioa_addr *relayed_addr2 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET6)); - if(get_relay_session_failure(a,AF_INET)) { + if(get_relay_session_failure(alloc,AF_INET)) { addr_set_any(&xor_relayed_addr1); pxor_relayed_addr1 = &xor_relayed_addr1; } else if(relayed_addr1) { @@ -917,7 +917,7 @@ static int handle_turn_allocate(turn_turnserver *server, pxor_relayed_addr1 = &xor_relayed_addr1; } - if(get_relay_session_failure(a,AF_INET6)) { + if(get_relay_session_failure(alloc,AF_INET6)) { addr_set_any(&xor_relayed_addr2); pxor_relayed_addr2 = &xor_relayed_addr2; } else if(relayed_addr2) { @@ -933,9 +933,9 @@ static int handle_turn_allocate(turn_turnserver *server, if(pxor_relayed_addr1 || pxor_relayed_addr2) { u32bits lifetime = 0; if(pxor_relayed_addr1) { - lifetime = (get_relay_session(a,pxor_relayed_addr1->ss.sa_family)->expiration_time - server->ctime); + lifetime = (get_relay_session(alloc,pxor_relayed_addr1->ss.sa_family)->expiration_time - server->ctime); } else if(pxor_relayed_addr2) { - lifetime = (get_relay_session(a,pxor_relayed_addr2->ss.sa_family)->expiration_time - server->ctime); + lifetime = (get_relay_session(alloc,pxor_relayed_addr2->ss.sa_family)->expiration_time - server->ctime); } stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid, @@ -950,8 +950,6 @@ static int handle_turn_allocate(turn_turnserver *server, } else { - a = NULL; - u08bits transport = 0; u32bits lifetime = 0; int even_port = -1; @@ -1196,7 +1194,7 @@ static int handle_turn_allocate(turn_turnserver *server, err_code, reason, tcp_peer_accept_connection); if(af4res<0) { - set_relay_session_failure(a,AF_INET); + set_relay_session_failure(alloc,AF_INET); if(!(*err_code)) { *err_code = 437; } @@ -1208,7 +1206,7 @@ static int handle_turn_allocate(turn_turnserver *server, err_code, reason, tcp_peer_accept_connection); if(af6res<0) { - set_relay_session_failure(a,AF_INET6); + set_relay_session_failure(alloc,AF_INET6); if(!(*err_code)) { *err_code = 437; } @@ -1220,7 +1218,7 @@ static int handle_turn_allocate(turn_turnserver *server, err_code, reason, tcp_peer_accept_connection); if(af4res<0) { - set_relay_session_failure(a,AF_INET); + set_relay_session_failure(alloc,AF_INET); if(!(*err_code)) { *err_code = 437; } @@ -1235,7 +1233,7 @@ static int handle_turn_allocate(turn_turnserver *server, &err_code4, &reason4, tcp_peer_accept_connection); if(af4res<0) { - set_relay_session_failure(a,AF_INET); + set_relay_session_failure(alloc,AF_INET); if(!err_code4) { err_code4 = 437; } @@ -1250,7 +1248,7 @@ static int handle_turn_allocate(turn_turnserver *server, &err_code6, &reason6, tcp_peer_accept_connection); if(af6res<0) { - set_relay_session_failure(a,AF_INET6); + set_relay_session_failure(alloc,AF_INET6); if(!err_code6) { err_code6 = 437; } @@ -1281,11 +1279,9 @@ static int handle_turn_allocate(turn_turnserver *server, } else { - a = get_allocation_ss(ss); + set_allocation_valid(alloc,1); - set_allocation_valid(a,1); - - stun_tid_cpy(&(a->tid), tid); + stun_tid_cpy(&(alloc->tid), tid); size_t len = ioa_network_buffer_get_size(nbh); @@ -1294,7 +1290,7 @@ static int handle_turn_allocate(turn_turnserver *server, ioa_addr *relayed_addr1 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET)); ioa_addr *relayed_addr2 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET6)); - if(get_relay_session_failure(a,AF_INET)) { + if(get_relay_session_failure(alloc,AF_INET)) { addr_set_any(&xor_relayed_addr1); pxor_relayed_addr1 = &xor_relayed_addr1; } else if(relayed_addr1) { @@ -1307,7 +1303,7 @@ static int handle_turn_allocate(turn_turnserver *server, pxor_relayed_addr1 = &xor_relayed_addr1; } - if(get_relay_session_failure(a,AF_INET6)) { + if(get_relay_session_failure(alloc,AF_INET6)) { addr_set_any(&xor_relayed_addr2); pxor_relayed_addr2 = &xor_relayed_addr2; } else if(relayed_addr2) { @@ -4057,7 +4053,12 @@ static void client_ss_allocation_timeout_handler(ioa_engine_handle e, void *arg) if (!arg) return; - ts_ur_super_session* ss = (ts_ur_super_session*)arg; + relay_endpoint_session *rsession = (relay_endpoint_session*)arg; + + if(!(rsession->s)) + return; + + ts_ur_super_session* ss = get_ioa_socket_session(rsession->s); if (!ss) return; @@ -4073,7 +4074,13 @@ static void client_ss_allocation_timeout_handler(ioa_engine_handle e, void *arg) FUNCSTART; - shutdown_client_connection(server, ss, 0, "allocation timeout"); + int family = get_ioa_socket_address_family(rsession->s); + + set_allocation_family_invalid(a,family); + + if(!get_relay_socket(a, AF_INET) && !get_relay_socket(a, AF_INET6)) { + shutdown_client_connection(server, ss, 0, "allocation timeout"); + } FUNCEND; } @@ -4184,7 +4191,7 @@ static int create_relay_connection(turn_turnserver* server, lifetime = STUN_MAX_ALLOCATE_LIFETIME; ioa_timer_handle ev = set_ioa_timer(server->e, lifetime, 0, - client_ss_allocation_timeout_handler, ss, 0, + client_ss_allocation_timeout_handler, newelem, 0, "client_ss_allocation_timeout_handler"); set_allocation_lifetime_ev(a, server->ctime + lifetime, ev, get_local_addr_from_ioa_socket(newelem->s)->ss.sa_family); @@ -4209,26 +4216,11 @@ static int refresh_relay_connection(turn_turnserver* server, if (server && ss && is_allocation_valid(a)) { if (lifetime < 1) { - - set_allocation_family_invalid(&(ss->alloc),family); - - if(family == AF_INET) { - if(get_relay_socket(&(ss->alloc), AF_INET6)) { - return 0; - } - } - - if(family == AF_INET6) { - if(get_relay_socket(&(ss->alloc), AF_INET)) { - return 0; - } - } - lifetime = 1; } ioa_timer_handle ev = set_ioa_timer(server->e, lifetime, 0, - client_ss_allocation_timeout_handler, ss, 0, + client_ss_allocation_timeout_handler, get_relay_session(a,family), 0, "refresh_client_ss_allocation_timeout_handler"); set_allocation_lifetime_ev(a, server->ctime + lifetime, ev, family); From b439a358a48481948ab6d3c6cedd5451aff1c830 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 19 Jul 2014 08:56:51 +0000 Subject: [PATCH 114/805] pu command fixed --- src/apps/relay/turncli.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index b25ce026..ee711f69 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -433,26 +433,28 @@ static int print_session(ur_map_key_type key, ur_map_value_type value, void *arg return 0; if(csarg->users) { + + const char *pn=csarg->pname; + if(pn[0]) { + if(!strcmp(pn,"TLS") || !strcmp(pn,"tls") || !strcmp(pn,"Tls")) { + if(tsi->client_protocol != TLS_SOCKET) + return 0; + } else if(!strcmp(pn,"DTLS") || !strcmp(pn,"dtls") || !strcmp(pn,"Dtls")) { + if(tsi->client_protocol != DTLS_SOCKET) + return 0; + } else if(!strcmp(pn,"TCP") || !strcmp(pn,"tcp") || !strcmp(pn,"Tcp")) { + if(tsi->client_protocol != TCP_SOCKET) + return 0; + } else if(!strcmp(pn,"UDP") || !strcmp(pn,"udp") || !strcmp(pn,"Udp")) { + if(tsi->client_protocol != UDP_SOCKET) + return 0; + } else { + return 0; + } + } + ur_string_map_value_type value; if(!ur_string_map_get(csarg->users, (ur_string_map_key_type)(char*)tsi->username, &value)) { - const char *pn=csarg->pname; - if(pn[0]) { - if(!strcmp(pn,"TLS") || !strcmp(pn,"tls") || !strcmp(pn,"Tls")) { - if(tsi->client_protocol != TLS_SOCKET) - return 0; - } else if(!strcmp(pn,"DTLS") || !strcmp(pn,"dtls") || !strcmp(pn,"Dtls")) { - if(tsi->client_protocol != DTLS_SOCKET) - return 0; - } else if(!strcmp(pn,"TCP") || !strcmp(pn,"tcp") || !strcmp(pn,"Tcp")) { - if(tsi->client_protocol != TCP_SOCKET) - return 0; - } else if(!strcmp(pn,"UDP") || !strcmp(pn,"udp") || !strcmp(pn,"Udp")) { - if(tsi->client_protocol != UDP_SOCKET) - return 0; - } else { - return 0; - } - } value = (ur_string_map_value_type)csarg->users_number; csarg->users_number += 1; csarg->user_counters = (size_t*)turn_realloc(csarg->user_counters, From 93540a6c0d7ad4c1b43b36712a661c38a8612281 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 19 Jul 2014 09:06:36 +0000 Subject: [PATCH 115/805] changelog updated --- ChangeLog | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5e4e64ad..188a8076 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,11 @@ 06/25/2014 Oleg Moskalenko Version 4.1.0.1 'Vitari': - - SSODA support (TODO). - - DB "driver" abstraction and MongoDB support (Federico Pinna). + - SSODA (double allocation) draft support added. + - DB "driver" abstraction and MongoDB support (by Federico Pinna). - multiple origins supported per request. - "allocation mismatch" condition fixed (merged from rfc5766-turn-server). - STUN BINDING response fixed in the case of -X (external address) option. + - "pu" CLI command fixed. - working on compilation warnings. 06/13/2014 Oleg Moskalenko From 3cb635b566c06a58e2f924eca1040fb0201cbea9 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 19 Jul 2014 09:32:21 +0000 Subject: [PATCH 116/805] changelog updated --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 188a8076..884a3796 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,7 @@ Version 4.1.0.1 'Vitari': - "allocation mismatch" condition fixed (merged from rfc5766-turn-server). - STUN BINDING response fixed in the case of -X (external address) option. - "pu" CLI command fixed. + - session cleaning fixed in TCP relay functionality (RFC 6062). - working on compilation warnings. 06/13/2014 Oleg Moskalenko From 0e2a7c54582f6e52502b2d9c26aab948e7425d82 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 19 Jul 2014 17:37:05 +0000 Subject: [PATCH 117/805] minor fixes --- src/apps/relay/netengine.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 76df6625..6ce5e13a 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -42,8 +42,8 @@ static pthread_barrier_t barrier; #define get_real_general_relay_servers_number() (turn_params.general_relay_servers_number > 1 ? turn_params.general_relay_servers_number : 1) #define get_real_udp_relay_servers_number() (turn_params.udp_relay_servers_number > 1 ? turn_params.udp_relay_servers_number : 1) -static struct relay_server **general_relay_servers = NULL; -static struct relay_server **udp_relay_servers = NULL; +static struct relay_server *general_relay_servers[1+((turnserver_id)-1)]; +static struct relay_server *udp_relay_servers[1+((turnserver_id)-1)]; ////////////////////////////////////////////// @@ -979,7 +979,6 @@ static void setup_socket_per_endpoint_udp_listener_servers(void) { if (!turn_params.no_udp || !turn_params.no_dtls) { - udp_relay_servers = (struct relay_server**) allocate_super_memory_engine(turn_params.listener.ioa_eng, sizeof(struct relay_server *)*get_real_udp_relay_servers_number()); for (i = 0; i < get_real_udp_relay_servers_number(); i++) { @@ -1520,8 +1519,6 @@ static void setup_general_relay_servers(void) { size_t i = 0; - general_relay_servers = (struct relay_server**)allocate_super_memory_engine(turn_params.listener.ioa_eng, sizeof(struct relay_server *)*get_real_general_relay_servers_number()); - for(i=0;i Date: Sat, 19 Jul 2014 23:53:21 +0000 Subject: [PATCH 118/805] configure fixed PR --- configure | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 0ad77694..a36a504b 100755 --- a/configure +++ b/configure @@ -990,10 +990,10 @@ if [ -z "${TURN_NO_MONGO}" ] ; then if ! [ ${ER} -eq 0 ] ; then ${ECHO_CMD} "MongoDB found." else - TURN_NO_MYSQL="-DTURN_NO_MONGO" + TURN_NO_MONGO="-DTURN_NO_MONGO" fi else - TURN_NO_MYSQL="-DTURN_NO_MONGO" + TURN_NO_MONGO="-DTURN_NO_MONGO" fi ########################### @@ -1068,7 +1068,7 @@ ${ECHO_CMD} "LDFLAGS += ${OSLIBS}" >> Makefile ${ECHO_CMD} "DBLIBS += ${DBLIBS}" >> Makefile ${ECHO_CMD} "CFLAGS += ${OSCFLAGS}" >> Makefile ${ECHO_CMD} "CPPFLAGS = ${CPPFLAGS}" >> Makefile -${ECHO_CMD} "DBCFLAGS += ${DBCFLAGS} ${TURN_NO_PQ} ${TURN_NO_MYSQL} ${TURN_NO_HIREDIS}" >> Makefile +${ECHO_CMD} "DBCFLAGS += ${DBCFLAGS} ${TURN_NO_PQ} ${TURN_NO_MYSQL} ${TURN_NO_MONGO} ${TURN_NO_HIREDIS}" >> Makefile ${ECHO_CMD} "#" >> Makefile ${ECHO_CMD} "PORTNAME = ${PORTNAME}" >> Makefile ${ECHO_CMD} "PREFIX = ${PREFIX}" >> Makefile From 553b16dfa115b8985810b749390c8262d72fc38e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 20 Jul 2014 06:18:26 +0000 Subject: [PATCH 119/805] working on crashes --- ChangeLog | 1 + src/apps/relay/netengine.c | 111 +++++++++++++++++++++++++++---------- 2 files changed, 82 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index 884a3796..a00ca20f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,7 @@ Version 4.1.0.1 'Vitari': - STUN BINDING response fixed in the case of -X (external address) option. - "pu" CLI command fixed. - session cleaning fixed in TCP relay functionality (RFC 6062). + - some crash conditions fixed. - working on compilation warnings. 06/13/2014 Oleg Moskalenko diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 6ce5e13a..8f7f7e1d 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -401,6 +401,11 @@ static void auth_server_receive_message(struct bufferevent *bev, void *ptr) TURN_LOG_LEVEL_ERROR, "%s: Too large UDP relay number: %d\n", __FUNCTION__,(int)dest); + } else if(!(udp_relay_servers[dest])) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Wrong UDP relay number: %d, total %d\n", + __FUNCTION__,(int)dest, (int)get_real_udp_relay_servers_number()); } else { output = bufferevent_get_output(udp_relay_servers[dest]->auth_out_buf); } @@ -408,8 +413,13 @@ static void auth_server_receive_message(struct bufferevent *bev, void *ptr) if(dest >= get_real_general_relay_servers_number()) { TURN_LOG_FUNC( TURN_LOG_LEVEL_ERROR, - "%s: Too large general relay number: %d\n", - __FUNCTION__,(int)dest); + "%s: Too large general relay number: %d, total %d\n", + __FUNCTION__,(int)dest,(int)get_real_general_relay_servers_number()); + } else if(!(general_relay_servers[dest])) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Wrong general relay number: %d, total %d\n", + __FUNCTION__,(int)dest,(int)get_real_general_relay_servers_number()); } else { output = bufferevent_get_output(general_relay_servers[dest]->auth_out_buf); } @@ -437,37 +447,38 @@ static int send_socket_to_general_relay(ioa_engine_handle e, struct message_to_r smptr->t = RMT_SOCKET; - { - struct evbuffer *output = NULL; - int success = 0; + struct evbuffer *output = NULL; + int success = 0; - output = bufferevent_get_output(rdest->out_buf); + if(!rdest) { + success = -1; + goto label_end; + } - if(output) { + output = bufferevent_get_output(rdest->out_buf); - if(evbuffer_add(output,smptr,sizeof(struct message_to_relay))<0) { - TURN_LOG_FUNC( - TURN_LOG_LEVEL_ERROR, - "%s: Cannot add message to relay output buffer\n", - __FUNCTION__); - } else { + if(output) { - success = 1; - smptr->m.sm.nd.nbh=NULL; - } - - } - - if(!success) { - ioa_network_buffer_delete(e, smptr->m.sm.nd.nbh); + if(evbuffer_add(output,smptr,sizeof(struct message_to_relay))<0) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Cannot add message to relay output buffer\n", + __FUNCTION__); + } else { + success = 1; smptr->m.sm.nd.nbh=NULL; - - IOA_CLOSE_SOCKET(smptr->m.sm.s); - - return -1; } } + label_end: + + if(!success) { + ioa_network_buffer_delete(e, smptr->m.sm.nd.nbh); + smptr->m.sm.nd.nbh=NULL; + IOA_CLOSE_SOCKET(smptr->m.sm.s); + return -1; + } + return 0; } @@ -487,23 +498,39 @@ static int send_socket_to_relay(turnserver_id id, u64bits cid, stun_tid *tid, io if(dest >= get_real_udp_relay_servers_number()) { TURN_LOG_FUNC( TURN_LOG_LEVEL_ERROR, - "%s: Too large UDP relay number: %d, rmt=%d\n", - __FUNCTION__,(int)dest,(int)rmt); + "%s: Too large UDP relay number: %d, rmt=%d, total=%d\n", + __FUNCTION__,(int)dest,(int)rmt, (int)get_real_udp_relay_servers_number()); ret = -1; goto err; } rs = udp_relay_servers[dest]; + if(!rs) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Wrong UDP relay number: %d, rmt=%d, total=%d\n", + __FUNCTION__,(int)dest,(int)rmt, (int)get_real_udp_relay_servers_number()); + ret = -1; + goto err; + } } else { size_t dest = id; if(dest >= get_real_general_relay_servers_number()) { TURN_LOG_FUNC( TURN_LOG_LEVEL_ERROR, - "%s: Too large general relay number: %d, rmt=%d\n", - __FUNCTION__,(int)dest,(int)rmt); + "%s: Too large general relay number: %d, rmt=%d, total=%d\n", + __FUNCTION__,(int)dest,(int)rmt, (int)get_real_general_relay_servers_number()); ret = -1; goto err; } rs = general_relay_servers[dest]; + if(!rs) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Wrong general relay number: %d, rmt=%d, total=%d\n", + __FUNCTION__,(int)dest,(int)rmt, (int)get_real_general_relay_servers_number()); + ret = -1; + goto err; + } } switch (rmt) { @@ -749,7 +776,12 @@ static void listener_receive_message(struct bufferevent *bev, void *ptr) if(turn_params.net_engine_version == NEV_UDP_SOCKET_PER_THREAD) { size_t ri; for(ri=0;rithr == pthread_self()) { + if(!(general_relay_servers[ri])) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Wrong general relay number: %d, total %d\n", + __FUNCTION__,(int)ri,(int)get_real_general_relay_servers_number()); + } else if(general_relay_servers[ri]->thr == pthread_self()) { relay_thread_index=ri; break; } @@ -1655,6 +1687,25 @@ void setup_server(void) setup_tcp_listener_servers(turn_params.listener.ioa_eng, NULL); } + { + int tot = 0; + if(udp_relay_servers[0]) { + tot = get_real_udp_relay_servers_number(); + } + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Total UDP servers: %d\n",(int)tot); + } + + { + int tot = get_real_general_relay_servers_number(); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Total General servers: %d\n",(int)tot); + int i; + for(i = 0;i Date: Mon, 21 Jul 2014 07:10:24 +0000 Subject: [PATCH 120/805] new mongo scripts added to rpm --- rpm/turnserver.spec | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 6f7063ea..4f6e9b2f 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -192,9 +192,11 @@ fi %{_docdir}/%{name}/schema.userdb.redis %dir %{_datadir}/%{name} %{_datadir}/%{name}/schema.sql +%{_datadir}/%{name}/schema.mongo.sh %{_datadir}/%{name}/schema.stats.redis %{_datadir}/%{name}/schema.userdb.redis %{_datadir}/%{name}/testredisdbsetup.sh +%{_datadir}/%{name}/testmongodbsetup.sh %{_datadir}/%{name}/testsqldbsetup.sql %dir %{_datadir}/%{name}/etc %{_datadir}/%{name}/etc/turn_server_cert.pem @@ -232,6 +234,7 @@ fi %{_datadir}/%{name}/scripts/longtermsecure/secure_udp_client.sh %dir %{_datadir}/%{name}/scripts/longtermsecuredb %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh +%{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_psql.sh %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_redis.sh %dir %{_datadir}/%{name}/scripts/restapi From 24507274d401e209f92b52fece8575f04ec42622 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Jul 2014 04:48:23 +0000 Subject: [PATCH 121/805] status updated --- STATUS | 2 ++ TODO | 21 ++++++--------------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/STATUS b/STATUS index 21f4900b..f76f353e 100644 --- a/STATUS +++ b/STATUS @@ -100,6 +100,8 @@ compatibility. 42) Bandwidth draft support added. 43) MongoDB support added. + +44) Double (dual) allocation added (SSODA draft). Things to be implemented in future (the development roadmap) are described in the TODO file. diff --git a/TODO b/TODO index 2b63675a..a356a783 100644 --- a/TODO +++ b/TODO @@ -55,26 +55,17 @@ ================================================================== -1) Follow the draft ICE endpoint mobility standard and apply changes -when necessary: +1) For extra difficult NAT/FWs, consider implementing Websockets. - https://ietf.org/doc/draft-wing-mmusic-ice-mobility/ +2) MS TURN, MS STUN extensions. -2) For extra difficult NAT/FWs, consider implementing Websockets. +3) ALPN with TLS and DTLS (when OpenSSL 1.0.2 is available). -3) MS TURN, MS STUN extensions. +4) Redirect draft. -4) Multiple origins. +5) New security oAuth draft. -5) ALPN with TLS and DTLS (when OpenSSL 1.0.2 is available). - -6) Redirect draft. - -7) Dual allocation draft. - -8) New security oAuth draft. - -9) DTLS 1.2 (when available). +6) DTLS 1.2 (when available). ================================================================== From d6765856d86315a04ba3c0d8354df1c3e3e60102 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Jul 2014 05:03:22 +0000 Subject: [PATCH 122/805] packaging fixed --- rpm/turnserver.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 4f6e9b2f..f07ec9d4 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -196,7 +196,7 @@ fi %{_datadir}/%{name}/schema.stats.redis %{_datadir}/%{name}/schema.userdb.redis %{_datadir}/%{name}/testredisdbsetup.sh -%{_datadir}/%{name}/testmongodbsetup.sh +%{_datadir}/%{name}/testmongosetup.sh %{_datadir}/%{name}/testsqldbsetup.sql %dir %{_datadir}/%{name}/etc %{_datadir}/%{name}/etc/turn_server_cert.pem From 57bfed32a172a0353ab1057108c5206d725445a5 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Jul 2014 07:29:14 +0000 Subject: [PATCH 123/805] mongo rpm fix --- rpm/turnserver.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index f07ec9d4..e1962616 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -188,6 +188,7 @@ fi %{_docdir}/%{name}/README.turnadmin %{_docdir}/%{name}/README.turnserver %{_docdir}/%{name}/schema.sql +%{_docdir}/%{name}/schema.mongo.sh %{_docdir}/%{name}/schema.stats.redis %{_docdir}/%{name}/schema.userdb.redis %dir %{_datadir}/%{name} From 77a20cf1d5e45c8f8db8755272abf1526620f5fc Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Jul 2014 07:33:51 +0000 Subject: [PATCH 124/805] mongo install fixed --- Makefile.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile.in b/Makefile.in index 171164d3..7a90ea22 100755 --- a/Makefile.in +++ b/Makefile.in @@ -132,7 +132,10 @@ install: all ${MAKE_DEPS} ${INSTALL_DATA} postinstall.txt ${DESTDIR}${DOCSDIR} ${INSTALL_DATA} turndb/schema.sql ${DESTDIR}${DOCSDIR} ${INSTALL_DATA} turndb/schema.sql ${DESTDIR}${SCHEMADIR} + ${INSTALL_DATA} turndb/schema.mongo.sh ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} turndb/schema.mongo.sh ${DESTDIR}${SCHEMADIR} ${INSTALL_DATA} turndb/testredisdbsetup.sh ${DESTDIR}${SCHEMADIR} + ${INSTALL_DATA} turndb/testmongosetup.sh ${DESTDIR}${SCHEMADIR} ${INSTALL_DATA} turndb/testsqldbsetup.sql ${DESTDIR}${SCHEMADIR} ${INSTALL_DATA} turndb/schema.userdb.redis ${DESTDIR}${DOCSDIR} ${INSTALL_DATA} turndb/schema.userdb.redis ${DESTDIR}${SCHEMADIR} From 2e5c0f2f3cacf225779d16021b2635b0e8d57551 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Jul 2014 19:16:18 +0000 Subject: [PATCH 125/805] man page fix --- README.turnserver | 31 ++++++++++++++++++------------- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 33 +++++++++++++++++++-------------- man/man1/turnutils.1 | 2 +- 4 files changed, 39 insertions(+), 29 deletions(-) diff --git a/README.turnserver b/README.turnserver index 1db6f032..566a40d5 100644 --- a/README.turnserver +++ b/README.turnserver @@ -83,13 +83,14 @@ User database settings: -b, --userdb User database file name (default - turnuserdb.conf), for long-term credentials mechanism only. - This user file database is being dynamically checked while the turnserver - is working, and the user accounts can be changed dynamically by - editing the database. + This user file database is being dynamically checked while the + turnserver is working, and the user accounts can be changed + dynamically by editing the database. -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 for secret-based timed authentication in TURN RESP API. + This database can be used for long-term and short-term + credentials mechanisms, and it can store the secret value + for secret-based timed authentication in TURN RESP API. The connection string format is like that: "host= dbname= user= password= connect_timeout=" @@ -97,14 +98,16 @@ User database settings: Or: - "postgresql://username:password@hostname:port/databasename" (for 9.x or newer Postgres). + "postgresql://username:password@hostname:port/databasename" + (for 9.x or newer Postgres). See the INSTALL file for more explanations and examples. 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 secret-based timed authentication in TURN RESP API. + This database can be used for long-term and short-term + credentials mechanisms, and it can store the secret value for + secret-based timed authentication in TURN RESP API. The connection string format is like that: "host= dbname= user= password= connect_timeout=" @@ -114,19 +117,21 @@ User database settings: for full MySQL documentation. -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 for secret-based timed authentication in TURN RESP API. + This database can be used for long-term and short-term + credentials mechanisms, and it can store the secret value + for secret-based timed authentication in TURN RESP API. The connection string format is like that: - "mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]" + "mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]] [/[database][?options]]" See the INSTALL file for more explanations and examples. Also, see http://docs.mongodb.org/manual/ 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 value for secret-based timed authentication in TURN RESP API. + This database can be used for long-term and short-term + credentials mechanisms, and it can store the secret + value for secret-based timed authentication in TURN RESP API. The connection string format is like that: "ip= dbname= password= connect_timeout=" diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 7eb719d0..0c5f98e7 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "15 July 2014" "" "" +.TH TURN 1 "22 July 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 46fe5c28..f204d431 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "15 July 2014" "" "" +.TH TURN 1 "22 July 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -134,15 +134,16 @@ User database settings: \fB\-b\fP, \fB\-\-userdb\fP User database file name (default \- turnuserdb.conf), for long\-term credentials mechanism only. -This user file database is being dynamically checked while the \fIturnserver\fP -is working, and the user accounts can be changed dynamically by -editing the database. +This user file database is being dynamically checked while the +\fIturnserver\fP is working, and the user accounts can be changed +dynamically by editing the database. .TP .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 for secret\-based timed authentication in TURN RESP API. +This database can be used for long\-term and short\-term +credentials mechanisms, and it can store the secret value +for secret\-based timed authentication in TURN RESP API. The connection string format is like that: .RS .PP @@ -151,7 +152,8 @@ The connection string format is like that: .PP Or: .PP -"postgresql://username:password@hostname:port/databasename" (for 9.x or newer Postgres). +"postgresql://username:password@hostname:port/databasename" +(for 9.x or newer Postgres). See the INSTALL file for more explanations and examples. .PP Also, see http://www.PostgreSQL.org for full PostgreSQL documentation. @@ -160,8 +162,9 @@ 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 secret\-based timed authentication in TURN RESP API. +This database can be used for long\-term and short\-term +credentials mechanisms, and it can store the secret value for +secret\-based timed authentication in TURN RESP API. The connection string format is like that: .RS .PP @@ -175,12 +178,13 @@ for full MySQL documentation. .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 for secret\-based timed authentication in TURN RESP API. +This database can be used for long\-term and short\-term +credentials mechanisms, and it can store the secret value +for secret\-based timed authentication in TURN RESP API. The connection string format is like that: .RS .PP -"mongodb://[username:password@]host1[:port1][,host2[:port2],\.\.\.[,hostN[:portN]]][/[database][?\fIoptions\fP]]" +"mongodb://[username:password@]host1[:port1][,host2[:port2],\.\.\.[,hostN[:portN]]] [/[database][?\fIoptions\fP]]" See the INSTALL file for more explanations and examples. .PP Also, see http://docs.mongodb.org/manual/ @@ -190,8 +194,9 @@ 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 value for secret\-based timed authentication in TURN RESP API. +This database can be used for long\-term and short\-term +credentials mechanisms, and it can store the secret +value for secret\-based timed authentication in TURN RESP API. The connection string format is like that: .RS .PP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 68f1c3d5..1d1ceae0 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "15 July 2014" "" "" +.TH TURN 1 "22 July 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used From cfae9e2012762d39edae49577e276b541b320287 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Jul 2014 19:18:26 +0000 Subject: [PATCH 126/805] man page fixes --- README.turnserver | 3 ++- man/man1/turnserver.1 | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.turnserver b/README.turnserver index 566a40d5..ccaf1c16 100644 --- a/README.turnserver +++ b/README.turnserver @@ -122,7 +122,8 @@ User database settings: for secret-based timed authentication in TURN RESP API. The connection string format is like that: - "mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]] [/[database][?options]]" + "mongodb://[username:password@]host1[:port1][,host2[:port2],... + [,hostN[:portN]]][/[database][?options]]" See the INSTALL file for more explanations and examples. Also, see http://docs.mongodb.org/manual/ diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index f204d431..6c25ff21 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -184,7 +184,8 @@ for secret\-based timed authentication in TURN RESP API. The connection string format is like that: .RS .PP -"mongodb://[username:password@]host1[:port1][,host2[:port2],\.\.\.[,hostN[:portN]]] [/[database][?\fIoptions\fP]]" +"mongodb://[username:password@]host1[:port1][,host2[:port2],\.\.\. +[,hostN[:portN]]][/[database][?\fIoptions\fP]]" See the INSTALL file for more explanations and examples. .PP Also, see http://docs.mongodb.org/manual/ From 1b9c8e2a923954fb1c1f13d97f60e73168045ac6 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Jul 2014 19:28:13 +0000 Subject: [PATCH 127/805] man page fixes --- README.turnserver | 3 +-- man/man1/turnserver.1 | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/README.turnserver b/README.turnserver index ccaf1c16..72da1ce6 100644 --- a/README.turnserver +++ b/README.turnserver @@ -122,8 +122,7 @@ User database settings: for secret-based timed authentication in TURN RESP API. The connection string format is like that: - "mongodb://[username:password@]host1[:port1][,host2[:port2],... - [,hostN[:portN]]][/[database][?options]]" + "mongodb://username:password@host:port/database?options" See the INSTALL file for more explanations and examples. Also, see http://docs.mongodb.org/manual/ diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 6c25ff21..d188187d 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -184,8 +184,7 @@ for secret\-based timed authentication in TURN RESP API. The connection string format is like that: .RS .PP -"mongodb://[username:password@]host1[:port1][,host2[:port2],\.\.\. -[,hostN[:portN]]][/[database][?\fIoptions\fP]]" +"mongodb://username:password@host:port/database?\fIoptions\fP" See the INSTALL file for more explanations and examples. .PP Also, see http://docs.mongodb.org/manual/ From a8a2f91982f6b5d240816dec3567fe437e263c23 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Jul 2014 20:00:27 +0000 Subject: [PATCH 128/805] man page fix --- README.turnserver | 9 +++++---- man/man1/turnserver.1 | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/README.turnserver b/README.turnserver index 72da1ce6..1074416e 100644 --- a/README.turnserver +++ b/README.turnserver @@ -592,14 +592,15 @@ limited time by an application that has to create a TURN server connection. The "classic" long-term credentials mechanism (LTCM) is described here: http://tools.ietf.org/html/rfc5389#section-10.2 + http://tools.ietf.org/html/rfc5389#section-15.4 -For authentication, each user must know two things: the username and the -password. Optionally, the user must supply the ORIGIN value, so that the +For authentication, each user must know two things: the username and the +password. Optionally, the user must supply the ORIGIN value, so that the server can figure out the realm to be used for the user. The nonce and the realm values are supplied by the TURN server. But LTCM is not saying -anything about the nature and about the persistence -of the username and of the password; and this is used by the REST API. +anything about the nature and about the persistence of the username and +of the password; and this is used by the REST API. In the TURN REST API, there is no persistent passwords for users. A user has just the username. The password is always temporary, and it is generated by diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index d188187d..9a7d19a0 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -827,14 +827,15 @@ limited time by an application that has to create a TURN server connection. The "classic" long\-term credentials mechanism (LTCM) is described here: .PP http://tools.ietf.org/html/rfc5389#section\-10.2 +.PP http://tools.ietf.org/html/rfc5389#section\-15.4 .PP -For authentication, each user must know two things: the username and the -password. Optionally, the user must supply the ORIGIN value, so that the +For authentication, each user must know two things: the username and the +password. Optionally, the user must supply the ORIGIN value, so that the server can figure out the realm to be used for the user. The nonce and the realm values are supplied by the TURN server. But LTCM is not saying -anything about the nature and about the persistence -of the username and of the password; and this is used by the REST API. +anything about the nature and about the persistence of the username and +of the password; and this is used by the REST API. .PP In the TURN REST API, there is no persistent passwords for users. A user has just the username. The password is always temporary, and it is generated by From 12cc3f7c9a0ee290030c7cf6241f63343ecf126e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Jul 2014 20:02:05 +0000 Subject: [PATCH 129/805] man page fix --- README.turnserver | 12 ++++++------ man/man1/turnserver.1 | 3 +-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/README.turnserver b/README.turnserver index 1074416e..63c8dd11 100644 --- a/README.turnserver +++ b/README.turnserver @@ -874,17 +874,17 @@ SEE ALSO WEB RESOURCES - project page: +project page: - http://code.google.com/p/coturn/ +http://code.google.com/p/coturn/ - Wiki page: +Wiki page: - http://code.google.com/p/coturn/wiki/Readme +http://code.google.com/p/coturn/wiki/Readme - forum: +forum: - https://groups.google.com/forum/?fromgroups=#!forum/turn-server-project-rfc5766-turn-server/ +https://groups.google.com/forum/?fromgroups=#!forum/turn-server-project-rfc5766-turn-server ====================================== diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 9a7d19a0..60ff5ec3 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1131,8 +1131,7 @@ http://code.google.com/p/coturn/wiki/Readme .PP forum: .PP -https://groups.google.com/forum/?fromgroups=#!forum/turn\-server\-project\-rfc5766\-turn\-server/ -.RE +https://groups.google.com/forum/?fromgroups=#!forum/turn\-server\-project\-rfc5766\-turn\-server .PP ====================================== .SS AUTHORS From 648cd2b149f021d980d6990dead1896d92a58cbb Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 22 Jul 2014 20:20:23 +0000 Subject: [PATCH 130/805] version bump --- ChangeLog | 2 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 6 +++--- src/ns_turn_defs.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index a00ca20f..bc1e6f46 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ 06/25/2014 Oleg Moskalenko -Version 4.1.0.1 'Vitari': +Version 4.1.0.2 'Vitari': - SSODA (double allocation) draft support added. - DB "driver" abstraction and MongoDB support (by Federico Pinna). - multiple origins supported per request. diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index c9f5bd94..2a19a88d 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.1.0.1 +TURNVERSION=4.1.0.2 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index e1962616..01b42f96 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.1.0.1 +Version: 4.1.0.2 Release: 0%{dist} Summary: Coturn TURN Server @@ -293,8 +293,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Fri Jul 11 2014 Oleg Moskalenko - - Sync to 4.1.0.1 +* Tue Jul 22 2014 Oleg Moskalenko + - Sync to 4.1.0.2 * Wed Jun 25 2014 Oleg Moskalenko - Sync to 4.0.1.4 * Fri Jun 13 2014 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 6f3ad994..704ec927 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.1.0.1" +#define TURN_SERVER_VERSION "4.1.0.2" #define TURN_SERVER_VERSION_NAME "Vitari" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 218fe7f81db77c09cf25835e6d5f7ae15f0d4d6b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 23 Jul 2014 04:32:08 +0000 Subject: [PATCH 131/805] man page fixes --- README.turnserver | 4 ++++ README.turnutils | 2 +- man/man1/turnserver.1 | 4 ++++ man/man1/turnutils.1 | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/README.turnserver b/README.turnserver index 63c8dd11..043c08e1 100644 --- a/README.turnserver +++ b/README.turnserver @@ -100,6 +100,7 @@ User database settings: "postgresql://username:password@hostname:port/databasename" (for 9.x or newer Postgres). + See the INSTALL file for more explanations and examples. Also, see http://www.PostgreSQL.org for full PostgreSQL documentation. @@ -111,6 +112,7 @@ User database settings: The connection string format is like that: "host= dbname= user= password= connect_timeout=" + See the INSTALL file for more explanations and examples. Also, see http://www.mysql.org or http://mariadb.org @@ -123,6 +125,7 @@ User database settings: The connection string format is like that: "mongodb://username:password@host:port/database?options" + See the INSTALL file for more explanations and examples. Also, see http://docs.mongodb.org/manual/ @@ -135,6 +138,7 @@ User database settings: The connection string format is like that: "ip= dbname= password= connect_timeout=" + See the INSTALL file for more explanations and examples. Also, see http://redis.io for full Redis documentation. diff --git a/README.turnutils b/README.turnutils index e1e1901f..beb3e8d5 100644 --- a/README.turnutils +++ b/README.turnutils @@ -115,7 +115,7 @@ Flags: -B Random disconnect after a few initial packets. --Z Dual allocation. +-Z Dual allocation (SSODA draft support). Options with required values: diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 60ff5ec3..7ccca41f 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -154,6 +154,7 @@ Or: .PP "postgresql://username:password@hostname:port/databasename" (for 9.x or newer Postgres). +.PP See the INSTALL file for more explanations and examples. .PP Also, see http://www.PostgreSQL.org for full PostgreSQL documentation. @@ -169,6 +170,7 @@ The connection string format is like that: .RS .PP "host= dbname= user= password= connect_timeout=" +.PP See the INSTALL file for more explanations and examples. .PP Also, see http://www.mysql.org or http://mariadb.org @@ -185,6 +187,7 @@ The connection string format is like that: .RS .PP "mongodb://username:password@host:port/database?\fIoptions\fP" +.PP See the INSTALL file for more explanations and examples. .PP Also, see http://docs.mongodb.org/manual/ @@ -201,6 +204,7 @@ The connection string format is like that: .RS .PP "ip= dbname= password= connect_timeout=" +.PP See the INSTALL file for more explanations and examples. .PP Also, see http://redis.io for full Redis documentation. diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 1d1ceae0..9e745393 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -174,7 +174,7 @@ Random disconnect after a few initial packets. .TP .B \fB\-Z\fP -Dual allocation. +Dual allocation (SSODA draft support). .TP .B Options with required values: From a1d67117fbe1f4136a7a11be55430f6543f5c6d0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 26 Jul 2014 05:51:12 +0000 Subject: [PATCH 132/805] CentOS7 script --- rpm/CentOS7.pre.build.sh | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100755 rpm/CentOS7.pre.build.sh diff --git a/rpm/CentOS7.pre.build.sh b/rpm/CentOS7.pre.build.sh new file mode 100755 index 00000000..82996859 --- /dev/null +++ b/rpm/CentOS7.pre.build.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# CentOS7 preparation script. + +CPWD=`pwd` + +. ./common.pre.build.sh + +cd ${CPWD} + +EPELRPM=epel-release-6-8.noarch.rpm + +# Common packs + +PACKS="libevent-devel mariadb-devel" +sudo yum -y install ${PACKS} +ER=$? +if ! [ ${ER} -eq 0 ] ; then + echo "Cannot install package(s) ${PACKS}" + cd ${CPWD} + exit -1 +fi + +# EPEL (for hiredis) + +cd ${CPWD} +./epel.install.sh + +# Platform file + +echo "CentOS7" > ${BUILDDIR}/platform + +cp ${CPWD}/epel.install.sh ${BUILDDIR}/install.sh + +cd ${CPWD} From cb8027b3a5d72918ab7ed13a9f1b5a22fe004d31 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 28 Jul 2014 06:20:59 +0000 Subject: [PATCH 133/805] forceful session cancellation --- ChangeLog | 10 +++-- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +- src/apps/relay/netengine.c | 75 +++++++++++++++++++++++++++++++++ src/apps/relay/ns_ioalib_impl.h | 7 +++ src/apps/relay/turncli.c | 13 ++++++ src/ns_turn_defs.h | 2 +- src/server/ns_turn_server.c | 14 +++++- src/server/ns_turn_server.h | 8 +++- 9 files changed, 126 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index bc1e6f46..fbc89432 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ -06/25/2014 Oleg Moskalenko +07/29/2014 Oleg Moskalenko +Version 4.1.1.1 'Vitari': + - Forceful session concellation (TODO). + +07/22/2014 Oleg Moskalenko Version 4.1.0.2 'Vitari': - SSODA (double allocation) draft support added. - DB "driver" abstraction and MongoDB support (by Federico Pinna). @@ -10,12 +14,12 @@ Version 4.1.0.2 'Vitari': - some crash conditions fixed. - working on compilation warnings. -06/13/2014 Oleg Moskalenko +06/21/2014 Oleg Moskalenko Version 4.0.1.3 'Severard': - Redis DB connection status fixed (Issue 129). - Logfile reset on SIGHUP (Gustavo Garcia suggestion). - - Log reset CLi command. + - Log reset CLI command. - Some error code corrections: * "Mobility forbidden" error changed, to value 405. * "Wrong credentials" situation is now treated as error 441. diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 2a19a88d..77f1f2c4 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.1.0.2 +TURNVERSION=4.1.1.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 01b42f96..cfb2201b 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.1.0.2 +Version: 4.1.1.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -293,6 +293,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Tue Jul 29 2014 Oleg Moskalenko + - Sync to 4.1.1.1 * Tue Jul 22 2014 Oleg Moskalenko - Sync to 4.1.0.2 * Wed Jun 25 2014 Oleg Moskalenko diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 8f7f7e1d..5f857c79 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -610,12 +610,87 @@ static int send_socket_to_relay(turnserver_id id, u64bits cid, stun_tid *tid, io return ret; } +int send_session_cancellation_to_relay(turnsession_id sid) +{ + int ret = 0; + + struct message_to_relay sm; + ns_bzero(&sm,sizeof(struct message_to_relay)); + sm.t = RMT_CANCEL_SESSION; + + turnserver_id id = (turnserver_id)(sid / TURN_SESSION_ID_FACTOR); + + struct relay_server *rs = NULL; + if(id>=TURNSERVER_ID_BOUNDARY_BETWEEN_TCP_AND_UDP) { + size_t dest = id-TURNSERVER_ID_BOUNDARY_BETWEEN_TCP_AND_UDP; + if(dest >= get_real_udp_relay_servers_number()) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Too large UDP relay number: %d, total=%d\n", + __FUNCTION__,(int)dest,(int)get_real_udp_relay_servers_number()); + ret = -1; + goto err; + } + rs = udp_relay_servers[dest]; + if(!rs) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Wrong UDP relay number: %d, total=%d\n", + __FUNCTION__,(int)dest,(int)get_real_udp_relay_servers_number()); + ret = -1; + goto err; + } + } else { + size_t dest = id; + if(dest >= get_real_general_relay_servers_number()) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Too large general relay number: %d, total=%d\n", + __FUNCTION__,(int)dest,(int)get_real_general_relay_servers_number()); + ret = -1; + goto err; + } + rs = general_relay_servers[dest]; + if(!rs) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Wrong general relay number: %d, total=%d\n", + __FUNCTION__,(int)dest,(int)get_real_general_relay_servers_number()); + ret = -1; + goto err; + } + } + + sm.relay_server = rs; + sm.m.csm.id = sid; + + { + struct evbuffer *output = bufferevent_get_output(rs->out_buf); + if(output) { + evbuffer_add(output,&sm,sizeof(struct message_to_relay)); + } else { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "%s: Empty output buffer\n", + __FUNCTION__); + ret = -1; + } + } + + err: + return ret; +} + static int handle_relay_message(relay_server_handle rs, struct message_to_relay *sm) { if(rs && sm) { switch (sm->t) { + case RMT_CANCEL_SESSION: { + turn_cancel_session(&(rs->server),sm->m.csm.id); + } + break; case RMT_SOCKET: { if (sm->m.sm.s->defer_nbh) { diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index dd161c9c..9a3d8a27 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -94,6 +94,10 @@ struct cb_socket_message { int can_resume; }; +struct cancelled_session_message { + turnsession_id id; +}; + struct relay_server { turnserver_id id; super_memory_t* sm; @@ -113,6 +117,7 @@ struct message_to_relay { union { struct socket_message sm; struct cb_socket_message cb_sm; + struct cancelled_session_message csm; } m; }; @@ -281,6 +286,8 @@ int set_raw_socket_tos_options(evutil_socket_t fd, int family); int set_socket_options_fd(evutil_socket_t fd, int tcp, int family); int set_socket_options(ioa_socket_handle s); +int send_session_cancellation_to_relay(turnsession_id sid); + ///////////////////////// SUPER MEMORY //////// #define allocate_super_memory_engine(e,size) allocate_super_memory_engine_func(e, size, __FILE__, __FUNCTION__, __LINE__) diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index ee711f69..6b3a2306 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -139,6 +139,8 @@ static const char *CLI_HELP_STR[] = " atas ip[:port] - add a TLS alternate server reference", " dtas ip[:port] - delete a TLS alternate server reference", "", + " cs - cancel session, forcefully" + "", NULL}; static const char *CLI_GREETING_STR[] = { @@ -552,6 +554,14 @@ static int print_session(ur_map_key_type key, ur_map_value_type value, void *arg return 0; } +static void cancel_session(struct cli_session* cs, const char* ssid) +{ + if(cs && cs->ts && ssid && *ssid) { + turnsession_id sid = strtoull(ssid,NULL,10); + send_session_cancellation_to_relay(sid); + } +} + static void print_sessions(struct cli_session* cs, const char* pn, int exact_match, int print_users) { if(cs && cs->ts && pn) { @@ -1035,6 +1045,9 @@ static int run_cli_input(struct cli_session* cs, const char *buf0, unsigned int } else if(strstr(cmd,"ps") == cmd) { print_sessions(cs,cmd+2,1,0); type_cli_cursor(cs); + } else if(strstr(cmd,"cs ") == cmd) { + cancel_session(cs,cmd+3); + type_cli_cursor(cs); } else if(strstr(cmd,"lr") == cmd) { log_reset(cs); type_cli_cursor(cs); diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 704ec927..a4befb83 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.1.0.2" +#define TURN_SERVER_VERSION "4.1.1.1" #define TURN_SERVER_VERSION_NAME "Vitari" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index cc4ea85e..57ebaa8c 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -673,14 +673,13 @@ static void put_session_into_map(ts_ur_super_session *ss) if(ss && ss->server) { turn_turnserver* server = (turn_turnserver*)(ss->server); if(!(ss->id)) { - ss->id = (turnsession_id)((turnsession_id)server->id * 1000000000000000LL); + ss->id = (turnsession_id)((turnsession_id)server->id * TURN_SESSION_ID_FACTOR); ss->id += ++(server->session_id_counter); ss->start_time = server->ctime; } ur_map_put(server->sessions_map, (ur_map_key_type)(ss->id), (ur_map_value_type)ss); put_session_into_mobile_map(ss); } - } static void delete_session_from_mobile_map(ts_ur_super_session *ss) @@ -716,6 +715,17 @@ static ts_ur_super_session* get_session_from_map(turn_turnserver* server, turnse return ss; } +void turn_cancel_session(turn_turnserver *server, turnsession_id sid) +{ + if(server) { + ts_ur_super_session* ts = get_session_from_map(server, sid); + if(ts) { + ts->to_be_closed = 1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Session %018llu to be forcefully canceled\n",(unsigned long long)sid); + } + } +} + static ts_ur_super_session* get_session_from_mobile_map(turn_turnserver* server, mobile_id_t mid) { ts_ur_super_session *ss = NULL; diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index 88134652..feaad20d 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -38,6 +38,9 @@ extern "C" { #endif +//////////// defines ////////////// + +#define TURN_SESSION_ID_FACTOR (1000000000000000LL) //////////// ALTERNATE-SERVER ///////////// @@ -67,7 +70,8 @@ enum _MESSAGE_TO_RELAY_TYPE { RMT_UNKNOWN = 0, RMT_SOCKET, RMT_CB_SOCKET, - RMT_MOBILE_SOCKET + RMT_MOBILE_SOCKET, + RMT_CANCEL_SESSION }; typedef enum _MESSAGE_TO_RELAY_TYPE MESSAGE_TO_RELAY_TYPE; @@ -209,6 +213,8 @@ int report_turn_session_info(turn_turnserver *server, ts_ur_super_session *ss, i turn_time_t get_turn_server_time(turn_turnserver *server); +void turn_cancel_session(turn_turnserver *server, turnsession_id sid); + /////////////////////////////////////////// #ifdef __cplusplus From 8cb9a75dbdfe81b1eba60f15797808b000194135 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 28 Jul 2014 07:07:27 +0000 Subject: [PATCH 134/805] working on session cancellation --- src/server/ns_turn_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 57ebaa8c..deb6cf5d 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -720,8 +720,8 @@ void turn_cancel_session(turn_turnserver *server, turnsession_id sid) if(server) { ts_ur_super_session* ts = get_session_from_map(server, sid); if(ts) { - ts->to_be_closed = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Session %018llu to be forcefully canceled\n",(unsigned long long)sid); + shutdown_client_connection(server, ts, 0, "Forceful shutdown"); } } } From 247e5849e4d79f263847e2ad53769770666eec10 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 31 Jul 2014 08:29:56 +0000 Subject: [PATCH 135/805] typo fixed --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index fbc89432..97f942a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ 07/29/2014 Oleg Moskalenko Version 4.1.1.1 'Vitari': - - Forceful session concellation (TODO). + - Forceful session cancellation. 07/22/2014 Oleg Moskalenko Version 4.1.0.2 'Vitari': From e4cbb2963de15c9300feb25a2cdb9df8fd6c8072 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 31 Jul 2014 08:37:02 +0000 Subject: [PATCH 136/805] changelog fixed --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 97f942a1..edd26ca6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ 07/29/2014 Oleg Moskalenko Version 4.1.1.1 'Vitari': - - Forceful session cancellation. + - Forceful server-side session cancellation implemented (in telnet console). 07/22/2014 Oleg Moskalenko Version 4.1.0.2 'Vitari': From 0b6e94d5424b9ee018e5bc6e7db3ee4dfcafc016 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 31 Jul 2014 08:40:56 +0000 Subject: [PATCH 137/805] changelog fixed --- ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index edd26ca6..db26d99c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 07/29/2014 Oleg Moskalenko Version 4.1.1.1 'Vitari': - - Forceful server-side session cancellation implemented (in telnet console). + - Forceful server-side session cancellation implemented + (in telnet console). 07/22/2014 Oleg Moskalenko Version 4.1.0.2 'Vitari': From 2ebb02b647267f4234586ef46339dc046320e05a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 4 Aug 2014 06:45:38 +0000 Subject: [PATCH 138/805] origin is checked in subsequent session messages --- ChangeLog | 5 +++ rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 ++- src/apps/uclient/startuclient.c | 29 +++++++++++++---- src/apps/uclient/startuclient.h | 2 ++ src/apps/uclient/uclient.c | 3 ++ src/client/ns_turn_msg.c | 48 +++++++++++++++++++++++++++ src/client/ns_turn_msg.h | 2 ++ src/ns_turn_defs.h | 2 +- src/server/ns_turn_server.c | 58 ++++++++++++++++++++++++++++++++- 10 files changed, 144 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index db26d99c..660735e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +08/03/2014 Oleg Moskalenko +Version 4.1.1.2 'Vitari': + - The origin attribute is verified in the subsequent + session messages. + 07/29/2014 Oleg Moskalenko Version 4.1.1.1 'Vitari': - Forceful server-side session cancellation implemented diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 77f1f2c4..8103666c 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.1.1.1 +TURNVERSION=4.1.1.2 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index cfb2201b..3dd47b72 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.1.1.1 +Version: 4.1.1.2 Release: 0%{dist} Summary: Coturn TURN Server @@ -293,6 +293,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Sun Aug 03 2014 Oleg Moskalenko + - Sync to 4.1.1.2 * Tue Jul 29 2014 Oleg Moskalenko - Sync to 4.1.1.1 * Tue Jul 22 2014 Oleg Moskalenko diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 9557ea7a..734df9bc 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -302,6 +302,17 @@ int read_mobility_ticket(app_ur_conn_info *clnet_info, stun_buffer *message) return ret; } +void add_origin(stun_buffer *message) +{ + if(message && origin[0]) { + const char* some_origin = "https://carleon.gov:443"; + stun_attr_add(message, STUN_ATTRIBUTE_ORIGIN, some_origin, strlen(some_origin)); + stun_attr_add(message, STUN_ATTRIBUTE_ORIGIN, origin, strlen(origin)); + some_origin = "ftp://uffrith.net"; + stun_attr_add(message, STUN_ATTRIBUTE_ORIGIN, some_origin, strlen(some_origin)); + } +} + static int clnet_allocate(int verbose, app_ur_conn_info *clnet_info, ioa_addr *relay_addr, @@ -372,13 +383,7 @@ static int clnet_allocate(int verbose, } } - if(origin[0]) { - const char* some_origin = "https://carleon.gov:443"; - stun_attr_add(&message, STUN_ATTRIBUTE_ORIGIN, some_origin, strlen(some_origin)); - stun_attr_add(&message, STUN_ATTRIBUTE_ORIGIN, origin, strlen(origin)); - some_origin = "ftp://uffrith.net"; - stun_attr_add(&message, STUN_ATTRIBUTE_ORIGIN, some_origin, strlen(some_origin)); - } + add_origin(&message); if(add_integrity(clnet_info, &message)<0) return -1; @@ -645,6 +650,8 @@ static int clnet_allocate(int verbose, stun_attr_add(&message, STUN_ATTRIBUTE_MOBILITY_TICKET, (const char*)clnet_info->s_mobile_id, strlen(clnet_info->s_mobile_id)); } + add_origin(&message); + if(add_integrity(clnet_info, &message)<0) return -1; stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); @@ -734,6 +741,8 @@ static int turn_channel_bind(int verbose, uint16_t *chn, *chn = stun_set_channel_bind_request(&message, peer_addr, *chn); } + add_origin(&message); + if(add_integrity(clnet_info, &message)<0) return -1; stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); @@ -845,6 +854,8 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, } } + add_origin(&message); + if(add_integrity(clnet_info, &message)<0) return -1; stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); @@ -1388,6 +1399,8 @@ int turn_tcp_connect(int verbose, app_ur_conn_info *clnet_info, ioa_addr *peer_a stun_init_request(STUN_METHOD_CONNECT, &message); stun_attr_add_addr(&message, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, peer_addr); + add_origin(&message); + if(add_integrity(clnet_info, &message)<0) return -1; stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); @@ -1427,6 +1440,8 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a stun_attr_add(&message, STUN_ATTRIBUTE_CONNECTION_ID, (const s08bits*)&cid,4); + add_origin(&message); + if(add_integrity(clnet_info, &message)<0) return -1; stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); diff --git a/src/apps/uclient/startuclient.h b/src/apps/uclient/startuclient.h index fbef34e7..30b6d31e 100644 --- a/src/apps/uclient/startuclient.h +++ b/src/apps/uclient/startuclient.h @@ -43,6 +43,8 @@ extern "C" { int rare_event(void); int not_rare_event(void); +void add_origin(stun_buffer *message); + int start_c2c_connection(uint16_t clnet_remote_port, const char *remote_address, const unsigned char* ifname, const char *local_address, diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 4180eb36..77cc57a8 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1083,6 +1083,7 @@ static int refresh_channel(app_ur_session* elem, u16bits method, uint32_t lt) stun_init_request(STUN_METHOD_REFRESH, &message); lt = htonl(lt); stun_attr_add(&message, STUN_ATTRIBUTE_LIFETIME, (const char*) <, 4); + add_origin(&message); if(add_integrity(clnet_info, &message)<0) return -1; if(use_fingerprints) stun_attr_add_fingerprint_str(message.buf, (size_t*) &(message.len)); @@ -1095,6 +1096,7 @@ static int refresh_channel(app_ur_session* elem, u16bits method, uint32_t lt) if (!method || (method == STUN_METHOD_CREATE_PERMISSION)) { stun_init_request(STUN_METHOD_CREATE_PERMISSION, &message); stun_attr_add_addr(&message, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &(elem->pinfo.peer_addr)); + add_origin(&message); if(add_integrity(clnet_info, &message)<0) return -1; if(use_fingerprints) stun_attr_add_fingerprint_str(message.buf, (size_t*) &(message.len)); @@ -1105,6 +1107,7 @@ static int refresh_channel(app_ur_session* elem, u16bits method, uint32_t lt) if (!method || (method == STUN_METHOD_CHANNEL_BIND)) { if (STUN_VALID_CHANNEL(elem->chnum)) { stun_set_channel_bind_request(&message, &(elem->pinfo.peer_addr), elem->chnum); + add_origin(&message); if(add_integrity(clnet_info, &message)<0) return -1; if(use_fingerprints) stun_attr_add_fingerprint_str(message.buf, (size_t*) &(message.len)); diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 19349b6e..514d68ca 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -43,6 +43,54 @@ /////////// +int stun_method_str(u16bits method, char *smethod) +{ + int ret = 0; + + const char* s = "UNKNOWN"; + + switch(method) { + case STUN_METHOD_BINDING: + s = "BINDING"; + break; + case STUN_METHOD_ALLOCATE: + s = "ALLOCATE"; + break; + case STUN_METHOD_REFRESH: + s = "REFRESH"; + break; + case STUN_METHOD_SEND: + s = "SEND"; + break; + case STUN_METHOD_DATA: + s = "DATA"; + break; + case STUN_METHOD_CREATE_PERMISSION: + s = "CREATE_PERMISSION"; + break; + case STUN_METHOD_CHANNEL_BIND: + s = "CHANNEL_BIND"; + break; + case STUN_METHOD_CONNECT: + s = "CONNECT"; + break; + case STUN_METHOD_CONNECTION_BIND: + s = "CONNECTION_BIND"; + break; + case STUN_METHOD_CONNECTION_ATTEMPT: + s = "CONNECTION_ATTEMPT"; + break; + default: + ret = -1; + }; + + if(smethod) { + STRCPY(smethod,s); + } + + return ret; +} + long turn_random(void) { long ret = 0; diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 04f6d170..f8abfac8 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -94,6 +94,8 @@ u32bits stun_adjust_allocate_lifetime(u32bits lifetime); ///////////// STR //////////////////////////////////////////////// +int stun_method_str(u16bits method, char *smethod); + int stun_get_message_len_str(u08bits *buf, size_t len, int padding, size_t *app_len); void stun_init_buffer_str(u08bits *buf, size_t *len); diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index a4befb83..79b361b7 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.1.1.1" +#define TURN_SERVER_VERSION "4.1.1.2" #define TURN_SERVER_VERSION_NAME "Vitari" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index deb6cf5d..0b35a37d 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3472,7 +3472,63 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, } } - if(!(ss->realm_set) && (method == STUN_METHOD_ALLOCATE)) { + /* check that the realm is the same as in the original request */ + if(ss->realm_set) { + stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh)); + + int origin_found = 0; + int norigins = 0; + + while(sar && !origin_found) { + if(stun_attr_get_type(sar) == STUN_ATTRIBUTE_ORIGIN) { + int sarlen = stun_attr_get_len(sar); + if(sarlen>0) { + ++norigins; + char *o = (char*)turn_malloc(sarlen+1); + ns_bcopy(stun_attr_get_value(sar),o,sarlen); + o[sarlen]=0; + char *corigin = (char*)turn_malloc(STUN_MAX_ORIGIN_SIZE+1); + corigin[0]=0; + if(get_canonic_origin(o,corigin,STUN_MAX_ORIGIN_SIZE)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "%s: Wrong origin format: %s\n", + __FUNCTION__, o); + } + if(!strncmp(ss->origin,corigin,STUN_MAX_ORIGIN_SIZE)) { + origin_found = 1; + } + turn_free(corigin,sarlen+1); + turn_free(o,sarlen+1); + } + } + sar = stun_attr_get_next_str(ioa_network_buffer_data(in_buffer->nbh), + ioa_network_buffer_get_size(in_buffer->nbh), sar); + } + + if(ss->origin[0]) { + if(!origin_found) { + err_code = 441; + reason = (const u08bits *)"The origin attribute does not match the initial session origin value"; + if(server->verbose) { + char smethod[129]; + stun_method_str(method,smethod); + log_method(ss, smethod, err_code, reason); + } + } + } else if(norigins > 0){ + err_code = 441; + reason = (const u08bits *)"The origin attribute is empty, does not match the initial session origin value"; + if(server->verbose) { + char smethod[129]; + stun_method_str(method,smethod); + log_method(ss, smethod, err_code, reason); + } + } + } + + /* get the initial origin value */ + if(!err_code && !(ss->realm_set) && (method == STUN_METHOD_ALLOCATE)) { stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh)); From 7711f2c4d8076511e6353dc6547848db8f25e08d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 12 Aug 2014 06:49:25 +0000 Subject: [PATCH 139/805] docs fixes. --- README.turnserver | 1 + examples/etc/turnserver.conf | 2 ++ man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 3 ++- man/man1/turnutils.1 | 2 +- src/apps/relay/mainrelay.c | 4 +++- 6 files changed, 10 insertions(+), 4 deletions(-) diff --git a/README.turnserver b/README.turnserver index 043c08e1..57c61a82 100644 --- a/README.turnserver +++ b/README.turnserver @@ -224,6 +224,7 @@ Flags: --simple-log This flag means that no log file rollover will be used, and the log file name will be constructed as-is, without PID and date appendage. + This option can be used, for example, together with the logrotate tool. --secure-stun Require authentication of the STUN Binding request. By default, the clients are allowed anonymous access to the STUN Binding functionality. diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index b389b79b..844fe77d 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -441,6 +441,8 @@ # This flag means that no log file rollover will be used, and the log file # name will be constructed as-is, without PID and date appendage. +# This option can be used, for example, together with the logrotate tool. +# #simple-log # Option to set the "redirection" mode. The value of this option diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 0c5f98e7..dc1bb6a3 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "22 July 2014" "" "" +.TH TURN 1 "11 August 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 7ccca41f..8f2fef05 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "22 July 2014" "" "" +.TH TURN 1 "11 August 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -343,6 +343,7 @@ With this flag, all log will be redirected to the system log (syslog). \fB\-\-simple\-log\fP This flag means that no log file rollover will be used, and the log file name will be constructed as\-is, without PID and date appendage. +This option can be used, for example, together with the logrotate tool. .TP .B \fB\-\-secure\-stun\fP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 9e745393..5f0a9d90 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "22 July 2014" "" "" +.TH TURN 1 "11 August 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 3118eb99..bce9a590 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -361,7 +361,8 @@ static char Usage[] = "Usage: turnserver [options]\n" " -X, --external-ip TURN Server public/private address mapping, if the server is behind NAT.\n" " In that situation, if a -X is used in form \"-X ip\" then that ip will be reported\n" " as relay IP address of all allocations. This scenario works only in a simple case\n" -" when one single relay address is be used, and no STUN CHANGE_REQUEST functionality is required.\n" +" when one single relay address is be used, and no STUN CHANGE_REQUEST\n" +" functionality is required.\n" " That single relay address must be mapped by NAT to the 'external' IP.\n" " For that 'external' IP, NAT must forward ports directly (relayed port 12345\n" " must be always mapped to the same 'external' port 12345).\n" @@ -499,6 +500,7 @@ static char Usage[] = "Usage: turnserver [options]\n" " --syslog Output all log information into the system log (syslog), do not use the file output.\n" " --simple-log This flag means that no log file rollover will be used, and the log file\n" " name will be constructed as-is, without PID and date appendage.\n" +" This option can be used, for example, together with the logrotate tool.\n" " --stale-nonce Use extra security with nonce value having limited lifetime (600 secs).\n" " -S, --stun-only Option to set standalone STUN operation only, all TURN requests will be ignored.\n" " --no-stun Option to suppress STUN functionality, only TURN requests will be processed.\n" From 17755579adcfe579e6f369e879ad3af410f0c503 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 14 Aug 2014 05:42:54 +0000 Subject: [PATCH 140/805] TODO updated --- TODO | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/TODO b/TODO index a356a783..e839426f 100644 --- a/TODO +++ b/TODO @@ -47,7 +47,7 @@ ================================================================== -1) RADIUS integration ? +1) New security oAuth draft. ================================================================== @@ -63,9 +63,7 @@ 4) Redirect draft. -5) New security oAuth draft. - -6) DTLS 1.2 (when available). +5) DTLS 1.2 (when available). ================================================================== From f904f0796917993971760591584a0079f6051e13 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 15 Aug 2014 06:45:01 +0000 Subject: [PATCH 141/805] crash fixed on wrong DB connection string --- ChangeLog | 6 ++++-- INSTALL | 3 +-- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 6 +++--- src/apps/relay/dbdrivers/dbd_mysql.c | 18 ++++++++++-------- src/apps/relay/dbdrivers/dbd_redis.c | 14 ++++++++------ src/ns_turn_defs.h | 2 +- 7 files changed, 28 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 660735e5..5e9898d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,9 @@ -08/03/2014 Oleg Moskalenko -Version 4.1.1.2 'Vitari': +08/14/2014 Oleg Moskalenko +Version 4.1.2.1 'Vitari': - The origin attribute is verified in the subsequent session messages. + - Crash fixed when the DB connection string is incorrect. + - Minor docs fixes. 07/29/2014 Oleg Moskalenko Version 4.1.1.1 'Vitari': diff --git a/INSTALL b/INSTALL index ec69027d..c9e57915 100644 --- a/INSTALL +++ b/INSTALL @@ -232,8 +232,7 @@ The following platforms have been used in the development: - FreeBSD 8.x, i386 - PC-BSD 9.x, x86_64 - Solaris 11, x86_64 - - Linux CentOS / Red Hat Enterprise Edition 6.3, x86_64 (amd64) - - Linux CentOS / Red Hat Enterprise Edition 6.4, x86_32 (i386) + - Linux CentOS / Red Hat Enterprise Edition 6.x-7.0, x86_64 (i386 & amd64) - Linux Debian 'Squeeze', i386 - Linux Mint 14.1 'Nadia', i386 - Linux Mint 16 'Petra', i386 diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 8103666c..acbe1a2b 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.1.1.2 +TURNVERSION=4.1.2.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 3dd47b72..5d816d2e 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.1.1.2 +Version: 4.1.2.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -293,8 +293,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Sun Aug 03 2014 Oleg Moskalenko - - Sync to 4.1.1.2 +* Thu Aug 14 2014 Oleg Moskalenko + - Sync to 4.1.2.1 * Tue Jul 29 2014 Oleg Moskalenko - Sync to 4.1.1.1 * Tue Jul 22 2014 Oleg Moskalenko diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 42f5c2d8..4681dba3 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -142,14 +142,16 @@ static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) { turn_free(s0, strlen(s0)+1); } - if(!(co->dbname)) - co->dbname=strdup("0"); - if(!(co->host)) - co->host=strdup("127.0.0.1"); - if(!(co->user)) - co->user=strdup(""); - if(!(co->password)) - co->password=strdup(""); + if(co) { + if(!(co->dbname)) + co->dbname=strdup("0"); + if(!(co->host)) + co->host=strdup("127.0.0.1"); + if(!(co->user)) + co->user=strdup(""); + if(!(co->password)) + co->password=strdup(""); + } return co; } diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index c0eaa487..c368ec33 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -148,12 +148,14 @@ static Ryconninfo *RyconninfoParse(const char *userdb, char **errmsg) { turn_free(s0, strlen(s0)+1); } - if(!(co->dbname)) - co->dbname=strdup("0"); - if(!(co->host)) - co->host=strdup("127.0.0.1"); - if(!(co->password)) - co->password=strdup(""); + if(co) { + if(!(co->dbname)) + co->dbname=strdup("0"); + if(!(co->host)) + co->host=strdup("127.0.0.1"); + if(!(co->password)) + co->password=strdup(""); + } return co; } diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 79b361b7..1eba81b7 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.1.1.2" +#define TURN_SERVER_VERSION "4.1.2.1" #define TURN_SERVER_VERSION_NAME "Vitari" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 00f2a84f563a032bccad0d77778f491a365f7d84 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 16 Aug 2014 06:51:58 +0000 Subject: [PATCH 142/805] MySQL SSL support added --- ChangeLog | 1 + INSTALL | 5 ++++ README.turnserver | 4 ++++ STATUS | 2 ++ examples/etc/turnserver.conf | 7 +++++- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 6 ++++- man/man1/turnutils.1 | 2 +- src/apps/relay/dbdrivers/dbd_mysql.c | 35 ++++++++++++++++++++++++++++ src/apps/relay/mainrelay.c | 11 +++++---- 10 files changed, 67 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5e9898d2..3dd1bcc3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,7 @@ Version 4.1.2.1 'Vitari': - The origin attribute is verified in the subsequent session messages. + - MySQL SSL connection support. - Crash fixed when the DB connection string is incorrect. - Minor docs fixes. diff --git a/INSTALL b/INSTALL index c9e57915..d68f5ff2 100644 --- a/INSTALL +++ b/INSTALL @@ -897,6 +897,11 @@ Or in the turnserver.conf file: mysql-userdb="host=localhost dbname=turn user=turn password=turn connect_timeout=30" +If you have to use a secure MySQL connection (SSL) then you have to use also +the optional connection string parameters for the secure communications: +ca, capath, cert, key, cipher (see +http://dev.mysql.com/doc/refman/5.0/en/mysql-ssl-set.html for the description). + XVI. MongoDB setup The MongoDB setup is well documented on their site http://docs.mongodb.org/manual/. diff --git a/README.turnserver b/README.turnserver index 57c61a82..e7191d38 100644 --- a/README.turnserver +++ b/README.turnserver @@ -118,6 +118,10 @@ User database settings: Also, see http://www.mysql.org or http://mariadb.org for full MySQL documentation. + Optional connection string parameters for the secure communications (SSL): + ca, capath, cert, key, cipher + (see http://dev.mysql.com/doc/refman/5.0/en/mysql-ssl-set.html for the 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 diff --git a/STATUS b/STATUS index f76f353e..6d4090fa 100644 --- a/STATUS +++ b/STATUS @@ -102,6 +102,8 @@ compatibility. 43) MongoDB support added. 44) Double (dual) allocation added (SSODA draft). + +45) Secure MySQL connection implemented. Things to be implemented in future (the development roadmap) are described in the TODO file. diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 844fe77d..9f8c8ea9 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -263,7 +263,12 @@ # 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 -# and it can store the secret value for secret-based timed authentication in TURN RESP API. +# 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): +# ca, capath, cert, key, cipher +# (see http://dev.mysql.com/doc/refman/5.0/en/mysql-ssl-set.html for the description). +# # Use string format as below (space separated parameters, all optional): # #mysql-userdb="host= dbname= user= password= port= connect_timeout=" diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index dc1bb6a3..8617d631 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "11 August 2014" "" "" +.TH TURN 1 "15 August 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 8f2fef05..03a01007 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "11 August 2014" "" "" +.TH TURN 1 "15 August 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -175,6 +175,10 @@ See the INSTALL file for more explanations and examples. .PP Also, see http://www.mysql.org or http://mariadb.org for full MySQL documentation. +.PP +Optional connection string parameters for the secure communications (SSL): +ca, capath, cert, key, cipher +(see http://dev.mysql.com/doc/refman/5.0/en/mysql\-ssl\-set.html for the description). .RE .TP .B diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 5f0a9d90..2de9b76a 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "11 August 2014" "" "" +.TH TURN 1 "15 August 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 4681dba3..dee2feb9 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -46,6 +46,13 @@ struct _Myconninfo { char *password; unsigned int port; unsigned int connect_timeout; + /* SSL ==>> */ + char *key; + char *ca; + char *cert; + char *capath; + char *cipher; + /* <<== SSL : see http://dev.mysql.com/doc/refman/5.0/en/mysql-ssl-set.html */ }; typedef struct _Myconninfo Myconninfo; @@ -56,6 +63,11 @@ static void MyconninfoFree(Myconninfo *co) { if(co->dbname) turn_free(co->dbname, strlen(co->dbname)+1); if(co->user) turn_free(co->user, strlen(co->user)+1); if(co->password) turn_free(co->password, strlen(co->password)+1); + if(co->key) turn_free(co->key, strlen(co->key)+1); + if(co->ca) turn_free(co->ca, strlen(co->ca)+1); + if(co->cert) turn_free(co->cert, strlen(co->cert)+1); + if(co->capath) turn_free(co->capath, strlen(co->capath)+1); + if(co->cipher) turn_free(co->cipher, strlen(co->cipher)+1); ns_bzero(co,sizeof(Myconninfo)); } } @@ -127,6 +139,26 @@ static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) { co->connect_timeout = (unsigned int)atoi(seq+1); else if(!strcmp(s,"timeout")) co->connect_timeout = (unsigned int)atoi(seq+1); + else if(!strcmp(s,"key")) + co->key = strdup(seq+1); + else if(!strcmp(s,"ssl-key")) + co->key = strdup(seq+1); + else if(!strcmp(s,"ca")) + co->ca = strdup(seq+1); + else if(!strcmp(s,"ssl-ca")) + co->ca = strdup(seq+1); + else if(!strcmp(s,"capath")) + co->capath = strdup(seq+1); + else if(!strcmp(s,"ssl-capath")) + co->capath = strdup(seq+1); + else if(!strcmp(s,"cert")) + co->cert = strdup(seq+1); + else if(!strcmp(s,"ssl-cert")) + co->cert = strdup(seq+1); + else if(!strcmp(s,"cipher")) + co->cipher = strdup(seq+1); + else if(!strcmp(s,"ssl-cipher")) + co->cipher = strdup(seq+1); else { MyconninfoFree(co); co = NULL; @@ -192,6 +224,9 @@ static MYSQL *get_mydb_connection(void) { } else { if(co->connect_timeout) mysql_options(mydbconnection,MYSQL_OPT_CONNECT_TIMEOUT,&(co->connect_timeout)); + if(co->ca || co->capath || co->cert || co->cipher || co->key) { + mysql_ssl_set(mydbconnection, co->key, co->cert, co->ca, co->capath, co->cipher); + } MYSQL *conn = mysql_real_connect(mydbconnection, co->host, co->user, co->password, co->dbname, co->port, NULL, CLIENT_IGNORE_SIGPIPE); if(!conn) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection: <%s>, runtime error\n",pud->userdb); diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index bce9a590..ce6a2492 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -425,8 +425,11 @@ static char Usage[] = "Usage: turnserver [options]\n" " This database can be used for long-term and short-term credentials mechanisms,\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= dbname= user= \\\n password= port= connect_timeout=\".\n" -" All parameters are optional.\n" +" \"host= dbname= user= \\\n password= port= connect_timeout=\".\n\n" +" The connection string parameters for the secure communications (SSL):\n" +" ca, capath, cert, key, cipher\n" +" (see http://dev.mysql.com/doc/refman/5.0/en/mysql-ssl-set.html for the description).\n\n" +" All connection-string parameters are optional.\n\n" #endif #if !defined(TURN_NO_MONGO) " -J, --mongo-userdb MongoDB connection string, if used (default - empty, no MongoDB used).\n" @@ -438,8 +441,8 @@ static char Usage[] = "Usage: turnserver [options]\n" " This database can be used for long-term and short-term credentials mechanisms,\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= dbname= \\\n password= port= connect_timeout=\".\n" -" All parameters are optional.\n" +" \"host= dbname= \\\n password= port= connect_timeout=\".\n\n" +" All connection-string parameters are optional.\n\n" " -O, --redis-statsdb Redis status and statistics database connection string, if used \n" " (default - empty, no Redis stats DB used).\n" " This database keeps allocations status information, and it can be also used for publishing\n" From 70d8f5d8039c2a3e71d8804c5b491f3a4f53e50e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 17 Aug 2014 06:50:20 +0000 Subject: [PATCH 143/805] new mysql ssl script added --- .../secure_relay_with_db_mysql_ssl.sh | 35 +++++++++++++++++++ rpm/turnserver.spec | 1 + 2 files changed, 36 insertions(+) create mode 100755 examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh new file mode 100755 index 00000000..c107168b --- /dev/null +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure mode with SSL connection to a MySQL database for users +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) "-r north.gov" means "use authentication realm north.gov" +# 6) --mysql-userdb="host=localhost dbname=coturn user=turn password=turn cipher=DHE-RSA-AES256-SHA connect_timeout=30" +# means that local MySQL database "coturn" will be used, with database user "turn" and +# database user password "turn", and with SSL connection with cipher DHE-RSA-AES256-SHA, +# and connection timeout 30 seconds. +# 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 +# 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 -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=turn 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 $@ diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 5d816d2e..0dcaba2e 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -235,6 +235,7 @@ fi %{_datadir}/%{name}/scripts/longtermsecure/secure_udp_client.sh %dir %{_datadir}/%{name}/scripts/longtermsecuredb %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh +%{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_psql.sh %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_redis.sh From 863de36bb4ea1b09a09eb09ef165cfa142b946dc Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 17 Aug 2014 17:27:10 +0000 Subject: [PATCH 144/805] docs fixes --- INSTALL | 3 ++- README.turnserver | 3 ++- examples/etc/turnserver.conf | 3 ++- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 5 +++-- man/man1/turnutils.1 | 2 +- src/apps/relay/mainrelay.c | 3 ++- 7 files changed, 13 insertions(+), 8 deletions(-) diff --git a/INSTALL b/INSTALL index d68f5ff2..61bb168c 100644 --- a/INSTALL +++ b/INSTALL @@ -900,7 +900,8 @@ mysql-userdb="host=localhost dbname=turn user=turn password=turn connect_timeout If you have to use a secure MySQL connection (SSL) then you have to use also the optional connection string parameters for the secure communications: ca, capath, cert, key, cipher (see -http://dev.mysql.com/doc/refman/5.0/en/mysql-ssl-set.html for the description). +http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the +command options description). XVI. MongoDB setup diff --git a/README.turnserver b/README.turnserver index e7191d38..0a014d98 100644 --- a/README.turnserver +++ b/README.turnserver @@ -120,7 +120,8 @@ User database settings: Optional connection string parameters for the secure communications (SSL): ca, capath, cert, key, cipher - (see http://dev.mysql.com/doc/refman/5.0/en/mysql-ssl-set.html for the description). + (see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the + command options description). -J, --mongo-userdb User database connection string for MongoDB. This database can be used for long-term and short-term diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 9f8c8ea9..a6012850 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -267,7 +267,8 @@ # # Optional connection string parameters for the secure communications (SSL): # ca, capath, cert, key, cipher -# (see http://dev.mysql.com/doc/refman/5.0/en/mysql-ssl-set.html for the description). +# (see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the +# command options description). # # Use string format as below (space separated parameters, all optional): # diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 8617d631..e5800532 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "15 August 2014" "" "" +.TH TURN 1 "17 August 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 03a01007..3f668545 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "15 August 2014" "" "" +.TH TURN 1 "17 August 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -178,7 +178,8 @@ for full MySQL documentation. .PP Optional connection string parameters for the secure communications (SSL): ca, capath, cert, key, cipher -(see http://dev.mysql.com/doc/refman/5.0/en/mysql\-ssl\-set.html for the description). +(see http://dev.mysql.com/doc/refman/5.1/en/ssl\-options.html for the +command \fIoptions\fP description). .RE .TP .B diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 2de9b76a..8e822401 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "15 August 2014" "" "" +.TH TURN 1 "17 August 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index ce6a2492..bfd60209 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -428,7 +428,8 @@ static char Usage[] = "Usage: turnserver [options]\n" " \"host= dbname= user= \\\n password= port= connect_timeout=\".\n\n" " The connection string parameters for the secure communications (SSL):\n" " ca, capath, cert, key, cipher\n" -" (see http://dev.mysql.com/doc/refman/5.0/en/mysql-ssl-set.html for the description).\n\n" +" (see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the\n" +" command options description).\n\n" " All connection-string parameters are optional.\n\n" #endif #if !defined(TURN_NO_MONGO) From 851409a197c9762432ae6f7ce3ff466fa7b9f539 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 19 Aug 2014 06:38:19 +0000 Subject: [PATCH 145/805] check-origin-consistency --- ChangeLog | 2 +- README.turnserver | 9 +++++++-- examples/etc/turnserver.conf | 7 +++++++ man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 13 ++++++++++--- man/man1/turnutils.1 | 2 +- src/apps/relay/mainrelay.c | 11 ++++++++++- src/apps/relay/mainrelay.h | 2 ++ src/apps/relay/netengine.c | 1 + src/server/ns_turn_server.c | 26 +++++++++++++++----------- src/server/ns_turn_server.h | 2 ++ 11 files changed, 57 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3dd1bcc3..9e29c956 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ 08/14/2014 Oleg Moskalenko Version 4.1.2.1 'Vitari': - The origin attribute is verified in the subsequent - session messages. + session messages (server flag --check-origin-consistency). - MySQL SSL connection support. - Crash fixed when the DB connection string is incorrect. - Minor docs fixes. diff --git a/README.turnserver b/README.turnserver index 0a014d98..ec163486 100644 --- a/README.turnserver +++ b/README.turnserver @@ -269,6 +269,11 @@ Flags: (if configured). The load balancing is using the ALTERNATE-SERVER mechanism. The TURN client must support 300 ALTERNATE-SERVER response for this functionality. + +--check-origin-consistency The flag that sets the origin consistency + check: across the session, all requests must have the same + main ORIGIN attribute value (if the ORIGIN was + initially used by the session). -h Help. @@ -388,8 +393,8 @@ Options with required values: and the userdb file). Must be used with long-term credentials mechanism or with TURN REST API. --C, --rest-api-separator This is the timestamp/username separator symbol (character) in TURN REST API. - The default value is :. +-C, --rest-api-separator This is the timestamp/username separator symbol + (character) in TURN REST API. The default value is :. -q, --user-quota Per-user allocations quota: how many concurrent allocations a user can create. This option can also be set diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index a6012850..b35391f8 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -306,6 +306,13 @@ # #realm=mycompany.org +# The flag that sets the origin consistency +# check: across the session, all requests must have the same +# main ORIGIN attribute value (if the ORIGIN was +# initially used by the session). +# +#check-origin-consistency + # Per-user allocation quota. # default value is 0 (no quota, unlimited number of sessions per user). # This option can also be set through the database, for a particular realm. diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index e5800532..72dd3e6f 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "17 August 2014" "" "" +.TH TURN 1 "18 August 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 3f668545..2e3878da 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "17 August 2014" "" "" +.TH TURN 1 "18 August 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -410,6 +410,13 @@ ALTERNATE\-SERVER mechanism. The TURN client must support 300 ALTERNATE\-SERVER response for this functionality. .TP .B +\fB\-\-check\-origin\-consistency\fP +The flag that sets the origin consistency +check: across the session, all requests must have the same +main ORIGIN attribute value (if the ORIGIN was +initially used by the session). +.TP +.B \fB\-h\fP Help. .TP @@ -566,8 +573,8 @@ mechanism or with TURN REST API. .TP .B \fB\-C\fP, \fB\-\-rest\-api\-separator\fP -This is the timestamp/username separator symbol (character) in TURN REST API. -The default value is :. +This is the timestamp/username separator symbol +(character) in TURN REST API. The default value is :. .TP .B \fB\-q\fP, \fB\-\-user\-quota\fP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 8e822401..4182b7f7 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "17 August 2014" "" "" +.TH TURN 1 "18 August 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index bfd60209..f29fc79e 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -81,7 +81,7 @@ DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,1, NEV_UNKNOWN, { "Unknown", "UDP listening socket per session", "UDP thread per network endpoint", "UDP thread per CPU core" }, //////////////// Relay servers ////////////////////////////////// -LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,"", +LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,0,"", 0,NULL,0,NULL,DEFAULT_GENERAL_RELAY_SERVERS_NUMBER,0, ////////////// Auth server ///////////////////////////////////// {NULL,NULL,NULL,0,NULL}, @@ -397,6 +397,10 @@ static char Usage[] = "Usage: turnserver [options]\n" " server is not using any database (just the commands-line settings\n" " and the userdb file). Must be used with long-term credentials \n" " mechanism or with TURN REST API.\n" +" --check-origin-consistency The flag that sets the origin consistency check:\n" +" across the session, all requests must have the same\n" +" main ORIGIN attribute value (if the ORIGIN was\n" +" initially used by the session).\n" " -q, --user-quota Per-user allocation quota: how many concurrent allocations a user can create.\n" " This option can also be set through the database, for a particular realm.\n" " -Q, --total-quota Total allocations quota: global limit on concurrent allocations.\n" @@ -670,6 +674,7 @@ enum EXTRA_OPTS { NO_TLSV1_OPT, NO_TLSV1_1_OPT, NO_TLSV1_2_OPT, + CHECK_ORIGIN_CONSISTENCY_OPT, ADMIN_MAX_BPS_OPT, ADMIN_TOTAL_QUOTA_OPT, ADMIN_USER_QUOTA_OPT @@ -734,6 +739,7 @@ static const struct myoption long_options[] = { { "Verbose", optional_argument, NULL, 'V' }, { "daemon", optional_argument, NULL, 'o' }, { "fingerprint", optional_argument, NULL, 'f' }, + { "check-origin-consistency", optional_argument, NULL, CHECK_ORIGIN_CONSISTENCY_OPT }, { "no-udp", optional_argument, NULL, NO_UDP_OPT }, { "no-tcp", optional_argument, NULL, NO_TCP_OPT }, { "no-tls", optional_argument, NULL, NO_TLS_OPT }, @@ -1152,6 +1158,9 @@ static void set_option(int c, char *value) turn_params.bps_capacity = (band_limit_t)atoi(value); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%lu bytes per second allowed, combined server capacity\n",(unsigned long)turn_params.bps_capacity); break; + case CHECK_ORIGIN_CONSISTENCY_OPT: + turn_params.check_origin = get_bool_value(value); + break; case NO_UDP_OPT: turn_params.no_udp = get_bool_value(value); break; diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index 22b16902..d105b459 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -250,6 +250,8 @@ typedef struct _turn_params_ { u16bits min_port; u16bits max_port; + vint check_origin; + vint no_multicast_peers; vint no_loopback_peers; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 5f857c79..5adb222d 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1574,6 +1574,7 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int check_new_allocation_quota, release_allocation_quota, turn_params.external_ip, + &turn_params.check_origin, &turn_params.no_tcp_relay, &turn_params.no_udp_relay, &turn_params.stale_nonce, diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 0b35a37d..de00da58 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3506,24 +3506,26 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, ioa_network_buffer_get_size(in_buffer->nbh), sar); } - if(ss->origin[0]) { - if(!origin_found) { + if(server->check_origin && *(server->check_origin)) { + if(ss->origin[0]) { + if(!origin_found) { + err_code = 441; + reason = (const u08bits *)"The origin attribute does not match the initial session origin value"; + if(server->verbose) { + char smethod[129]; + stun_method_str(method,smethod); + log_method(ss, smethod, err_code, reason); + } + } + } else if(norigins > 0){ err_code = 441; - reason = (const u08bits *)"The origin attribute does not match the initial session origin value"; + reason = (const u08bits *)"The origin attribute is empty, does not match the initial session origin value"; if(server->verbose) { char smethod[129]; stun_method_str(method,smethod); log_method(ss, smethod, err_code, reason); } } - } else if(norigins > 0){ - err_code = 441; - reason = (const u08bits *)"The origin attribute is empty, does not match the initial session origin value"; - if(server->verbose) { - char smethod[129]; - stun_method_str(method,smethod); - log_method(ss, smethod, err_code, reason); - } } } @@ -4675,6 +4677,7 @@ void init_turn_server(turn_turnserver* server, check_new_allocation_quota_cb chquotacb, release_allocation_quota_cb raqcb, ioa_addr *external_ip, + vintp check_origin, vintp no_tcp_relay, vintp no_udp_relay, vintp stale_nonce, @@ -4718,6 +4721,7 @@ void init_turn_server(turn_turnserver* server, TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"turn server id=%d created\n",(int)id); + server->check_origin = check_origin; server->no_tcp_relay = no_tcp_relay; server->no_udp_relay = no_udp_relay; diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index feaad20d..1aba589e 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -112,6 +112,7 @@ struct _turn_turnserver { int verbose; int fingerprint; int rfc5780; + vintp check_origin; vintp stale_nonce; vintp stun_only; vintp no_stun; @@ -174,6 +175,7 @@ void init_turn_server(turn_turnserver* server, check_new_allocation_quota_cb chquotacb, release_allocation_quota_cb raqcb, ioa_addr *external_addr, + vintp check_origin, vintp no_tcp_relay, vintp no_udp_relay, vintp stale_nonce, From 3d9510bd03167559c670e444c29321deb480caf1 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 19 Aug 2014 16:59:28 +0000 Subject: [PATCH 146/805] docs fix --- README.turnserver | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.turnserver b/README.turnserver index ec163486..7bd560be 100644 --- a/README.turnserver +++ b/README.turnserver @@ -227,9 +227,9 @@ Flags: --syslog With this flag, all log will be redirected to the system log (syslog). ---simple-log This flag means that no log file rollover will be used, and the log file - name will be constructed as-is, without PID and date appendage. - This option can be used, for example, together with the logrotate tool. +--simple-log This flag means that no log file rollover will be used, and the log file + name will be constructed as-is, without PID and date appendage. + This option can be used, for example, together with the logrotate tool. --secure-stun Require authentication of the STUN Binding request. By default, the clients are allowed anonymous access to the STUN Binding functionality. @@ -270,7 +270,7 @@ Flags: ALTERNATE-SERVER mechanism. The TURN client must support 300 ALTERNATE-SERVER response for this functionality. ---check-origin-consistency The flag that sets the origin consistency +--check-origin-consistency The flag that sets the origin consistency check: across the session, all requests must have the same main ORIGIN attribute value (if the ORIGIN was initially used by the session). @@ -316,7 +316,7 @@ Options with required values: on that endpoint only for "symmetry". --alt-tls-listening-port Alternative listening port for TLS and DTLS protocols. - Default (or zero) value means "TLS listening port plus one". + Default (or zero) value means "TLS listening port plus one". --aux-server Auxiliary STUN/TURN server listening endpoint. Aux servers have almost full TURN and STUN functionality. @@ -538,7 +538,7 @@ Options with required values: --cli-max-output-sessions Maximum number of output sessions in ps CLI command. This value can be changed on-the-fly in CLI. The default value is 256. ---ne=[1|2|3] Set network engine type for the process (for internal purposes). +--ne=[1|2|3] Set network engine type for the process (for internal purposes). ================================== From a448918b695ef7b35606f5c3b185ebcf800e64cc Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 20 Aug 2014 05:19:45 +0000 Subject: [PATCH 147/805] typo fixed --- src/apps/relay/dbdrivers/dbd_mongo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index 18beef59..d6ae37ec 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -124,7 +124,7 @@ static mongoc_collection_t * mongo_get_collection(const char * name) { MONGO * mc = get_mongodb_connection(); if(!mc) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error gettting a connection to MongoDB\n"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error getting a connection to MongoDB\n"); return NULL; } From 3bee9c0960decf75052e02d49f1333707689b7a4 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 20 Aug 2014 18:54:38 +0000 Subject: [PATCH 148/805] TODO updated --- TODO | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TODO b/TODO index e839426f..56ebc9b2 100644 --- a/TODO +++ b/TODO @@ -65,6 +65,8 @@ 5) DTLS 1.2 (when available). +7) TURN Proxy ? http://tools.ietf.org/html/draft-schwartz-rtcweb-return-00 + ================================================================== ### VII. MISC FEATURES ### From 84f12a9ed496dd2007630b3e87e29ce92174e0bf Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 23 Aug 2014 07:01:05 +0000 Subject: [PATCH 149/805] SHA256 memory leak fixed. --- ChangeLog | 4 ++++ rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/client/ns_turn_msg.c | 1 + src/ns_turn_defs.h | 2 +- 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9e29c956..2a6b6551 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +08/22/2014 Oleg Moskalenko +Version 4.1.2.2 'Vitari': + - SHA-256 memory leak fixed. + 08/14/2014 Oleg Moskalenko Version 4.1.2.1 'Vitari': - The origin attribute is verified in the subsequent diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index acbe1a2b..cb9ca5e8 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.1.2.1 +TURNVERSION=4.1.2.2 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 0dcaba2e..7e688f8a 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.1.2.1 +Version: 4.1.2.2 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,6 +294,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Thu Aug 22 2014 Oleg Moskalenko + - Sync to 4.1.2.2 * Thu Aug 14 2014 Oleg Moskalenko - Sync to 4.1.2.1 * Tue Jul 29 2014 Oleg Moskalenko diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 514d68ca..c6e49c8a 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -155,6 +155,7 @@ int stun_produce_integrity_key_str(u08bits *uname, u08bits *realm, u08bits *upwd EVP_DigestInit(&ctx,EVP_sha256()); EVP_DigestUpdate(&ctx,str,strl); EVP_DigestFinal(&ctx,key,&keylen); + EVP_MD_CTX_cleanup(&ctx); } else #endif { diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 1eba81b7..64dafaeb 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.1.2.1" +#define TURN_SERVER_VERSION "4.1.2.2" #define TURN_SERVER_VERSION_NAME "Vitari" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 18180cafdc664035e14bc30abb199b06c6976012 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 24 Aug 2014 08:43:58 +0000 Subject: [PATCH 150/805] working on oauth --- src/client/ns_turn_msg.c | 214 ++++++++++++++++++++++++++++++ src/client/ns_turn_msg.h | 3 + src/client/ns_turn_msg_defs_new.h | 81 ++++++++++- turndb/schema.sql | 13 ++ turndb/schema.userdb.redis | 2 +- 5 files changed, 308 insertions(+), 5 deletions(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index c6e49c8a..6b96daff 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1631,4 +1631,218 @@ int stun_attr_add_padding_str(u08bits *buf, size_t *len, u16bits padding_len) return stun_attr_add_str(buf, len, STUN_ATTRIBUTE_PADDING, avalue, padding_len); } +/* OAUTH */ + +static void remove_spaces(char *s) +{ + char *sfns = s; + while(*sfns) { + if(*sfns != ' ') + break; + ++sfns; + } + if(*sfns) { + if(sfns != s) { + while(*sfns && (*sfns != ' ')) { + *s = *sfns; + ++s; + ++sfns; + }; + *s = 0; + } else { + while(*s) { + if(*s == ' ') { + *s = 0; + break; + } + ++s; + } + } + } +} + +static void normalize_algorithm(char *s) +{ + char c = *s; + while(c) { + if(c=='_') c='-'; + else if((c>='a')&&(c<='z')) { + c = c - 'a' + 'A'; + } + ++s; + c = *s; + } +} + +static size_t calculate_enc_key_length(ENC_ALG a) +{ + switch(a) { + case AES_128_CBC: + return 16; + case AES_256_CBC: + return 32; + default: + ; + }; + + return 32; +} + +static size_t calculate_auth_key_length(AUTH_ALG a) +{ + switch(a) { + case AUTH_ALG_HMAC_SHA_1: + return 20; + case AUTH_ALG_HMAC_SHA_256_128: + return 32; + case AUTH_ALG_HMAC_SHA_256: + return 32; + default: + ; + }; + + return 32; +} + +static int calculate_key(char *key, size_t key_size, char *new_key, size_t new_key_size, SHATYPE shatype, + char *err_msg, size_t err_msg_size) +{ + //Extract: + u08bits prk[128]; + unsigned int prk_len = 0; + stun_calculate_hmac((const u08bits *)key, key_size, (const u08bits *)"", 0, prk, &prk_len, shatype); + + //Expand: + u08bits buf[128]; + buf[0]=1; + u08bits hmac[128]; + unsigned int hmac_len = 0; + stun_calculate_hmac((const u08bits *)buf, 1, prk, prk_len, hmac, &hmac_len, shatype); + ns_bcopy(hmac,new_key,hmac_len); + + //Check + if(new_key_size>hmac_len) { + ns_bcopy(hmac,buf,hmac_len); + buf[hmac_len]=2; + u08bits hmac1[128]; + unsigned int hmac1_len = 0; + stun_calculate_hmac((const u08bits *)buf, hmac_len+1, prk, prk_len, hmac1, &hmac1_len, shatype); + ns_bcopy(hmac1,new_key+hmac_len,hmac1_len); + if(new_key_size > (hmac_len + hmac1_len)) { + if(err_msg) { + snprintf(err_msg,err_msg_size,"Wrong HKDF procedure (key sizes): output.sz=%lu, hmac(1)=%lu, hmac(2)=%lu",(unsigned long)new_key_size,(unsigned long)hmac_len,(unsigned long)hmac1_len); + } + return -1; + } + } + + return 0; +} + +int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, size_t err_msg_size) +{ + if(oakd && key) { + + if(!(oakd->ikm_key_size)) { + if(!(oakd->as_rs_key_size)) { + if(err_msg) { + snprintf(err_msg,err_msg_size,"AS-RS key is not defined"); + } + return -1; + } + if(!(oakd->auth_key_size)) { + if(err_msg) { + snprintf(err_msg,err_msg_size,"AUTH key is not defined"); + } + return -1; + } + } + + remove_spaces(oakd->kid); + + remove_spaces(oakd->hkdf_hash_func); + remove_spaces(oakd->as_rs_alg); + remove_spaces(oakd->auth_alg); + + normalize_algorithm(oakd->hkdf_hash_func); + normalize_algorithm(oakd->as_rs_alg); + normalize_algorithm(oakd->auth_alg); + + if(!(oakd->kid[0])) { + if(err_msg) { + snprintf(err_msg,err_msg_size,"KID is not defined"); + } + return -1; + } + + ns_bzero(key,sizeof(oauth_key)); + + STRCPY(key->kid,oakd->kid); + + ns_bcopy(oakd->as_rs_key,key->as_rs_key,sizeof(key->as_rs_key)); + key->as_rs_key_size = oakd->as_rs_key_size; + ns_bcopy(oakd->auth_key,key->auth_key,sizeof(key->auth_key)); + key->auth_key_size = oakd->auth_key_size; + ns_bcopy(oakd->ikm_key,key->ikm_key,sizeof(key->ikm_key)); + key->ikm_key_size = oakd->ikm_key_size; + + key->timestamp = oakd->timestamp; + key->lifetime = oakd->lifetime; + + key->hkdf_hash_func = SHATYPE_SHA256; + if(!strcmp(oakd->hkdf_hash_func,"SHA1") || !strcmp(oakd->hkdf_hash_func,"SHA-1")) { + key->hkdf_hash_func = SHATYPE_SHA1; + } else if(!strcmp(oakd->hkdf_hash_func,"SHA256") || !strcmp(oakd->hkdf_hash_func,"SHA-256")) { + key->hkdf_hash_func = SHATYPE_SHA256; + } else if(oakd->hkdf_hash_func[0]) { + if(err_msg) { + snprintf(err_msg,err_msg_size,"Wrong HKDF hash function algorithm: %s",oakd->hkdf_hash_func); + } + return -1; + } + + key->as_rs_alg = ENC_ALG_DEFAULT; + if(!strcmp(oakd->as_rs_alg,"AES-128-CBC")) { + key->as_rs_alg = AES_128_CBC; + } else if(!strcmp(oakd->as_rs_alg,"AES-256-CBC")) { + key->as_rs_alg = AES_256_CBC; + } else if(oakd->as_rs_alg[0]) { + if(err_msg) { + snprintf(err_msg,err_msg_size,"Wrong oAuth token encryption algorithm: %s",oakd->as_rs_alg); + } + return -1; + } + + key->auth_alg = AUTH_ALG_DEFAULT; + if(!strcmp(oakd->auth_alg,"HMAC-SHA-1") || !strcmp(oakd->auth_alg,"HMAC-SHA1")) { + key->auth_alg = AUTH_ALG_HMAC_SHA_1; + } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256")) { + key->auth_alg = AUTH_ALG_HMAC_SHA_256; + } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256-128")) { + key->auth_alg = AUTH_ALG_HMAC_SHA_256_128; + } else if(oakd->auth_alg[0]) { + if(err_msg) { + snprintf(err_msg,err_msg_size,"Wrong oAuth token hash algorithm: %s",oakd->auth_alg); + } + return -1; + } + } + + if(!(key->auth_key_size)) { + key->auth_key_size = calculate_auth_key_length(key->auth_alg); + if(calculate_key(key->ikm_key,key->ikm_key_size,key->auth_key,key->auth_key_size,key->hkdf_hash_func,err_msg,err_msg_size)<0) { + return -1; + } + } + + if(!(key->as_rs_key_size)) { + key->as_rs_key_size = calculate_enc_key_length(key->as_rs_alg); + if(calculate_key(key->ikm_key,key->ikm_key_size,key->as_rs_key,key->as_rs_key_size,key->hkdf_hash_func,err_msg,err_msg_size)<0) { + return -1; + } + } + + return 0; +} + /////////////////////////////////////////////////////////////// diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index f8abfac8..f4a0bd83 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -209,6 +209,9 @@ 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); +/* OAUTH */ +int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, size_t err_msg_size); + /////////////////////////////////////////////////////////////// #ifdef __cplusplus diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 57b64c2a..b65f9df8 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -38,6 +38,12 @@ #define STUN_ATTRIBUTE_ORIGIN (0x802F) /* <<== Origin */ +/* Bandwidth */ + +#define STUN_ATTRIBUTE_NEW_BANDWIDTH (0x8000 + STUN_ATTRIBUTE_BANDWIDTH) + +/* <<== Bandwidth */ + /* SHA AGILITY ==>> */ #define SHA1SIZEBYTES (20) @@ -46,7 +52,9 @@ #define MAXSHASIZE (128) enum _SHATYPE { - SHATYPE_SHA1 = 0, + SHATYPE_ERROR = -1, + SHATYPE_DEFAULT=0, + SHATYPE_SHA1=SHATYPE_DEFAULT, SHATYPE_SHA256 }; @@ -58,10 +66,75 @@ typedef enum _SHATYPE SHATYPE; /* <<== SHA AGILITY */ -/* Bandwidth */ +/* OAUTH TOKEN ENC ALG ==> */ -#define STUN_ATTRIBUTE_NEW_BANDWIDTH (0x8000 + STUN_ATTRIBUTE_BANDWIDTH) +enum _ENC_ALG { + ENC_ALG_ERROR=-1, + ENC_ALG_DEFAULT=0, + AES_128_CBC=ENC_ALG_DEFAULT, + AES_256_CBC, + ENG_ALG_NUM +}; -/* <<== Bandwidth */ +typedef enum _ENC_ALG ENC_ALG; + +/* <<== OAUTH TOKEN ENC ALG */ + +/* OAUTH TOKEN AUTH ALG ==> */ + +enum _AUTH_ALG { + AUTH_ALG_ERROR = -1, + AUTH_ALG_DEFAULT = 0, + AUTH_ALG_HMAC_SHA_256_128 = AUTH_ALG_DEFAULT, + AUTH_ALG_HMAC_SHA_1, + AUTH_ALG_HMAC_SHA_256 +}; + +typedef enum _AUTH_ALG AUTH_ALG; + +/* <<== OAUTH TOKEN AUTH ALG */ + +/** + * oAuth struct + */ + +#define OAUTH_KID_SIZE (128) +#define OAUTH_HASH_FUNC_SIZE (64) +#define OAUTH_ALG_SIZE (64) +#define OAUTH_KEY_SIZE (256) + +struct _oauth_key_data { + char kid[OAUTH_KID_SIZE+1]; + char ikm_key[OAUTH_KEY_SIZE+1]; + size_t ikm_key_size; + u64bits timestamp; + turn_time_t lifetime; + char hkdf_hash_func[OAUTH_HASH_FUNC_SIZE+1]; + char as_rs_alg[OAUTH_ALG_SIZE+1]; + char as_rs_key[OAUTH_KEY_SIZE+1]; + size_t as_rs_key_size; + char auth_alg[OAUTH_ALG_SIZE+1]; + char auth_key[OAUTH_KEY_SIZE+1]; + size_t auth_key_size; +}; + +typedef struct _oauth_key_data oauth_key_data; + +struct _oauth_key { + char kid[OAUTH_KID_SIZE+1]; + char ikm_key[OAUTH_KEY_SIZE+1]; + size_t ikm_key_size; + u64bits timestamp; + turn_time_t lifetime; + SHATYPE hkdf_hash_func; + ENC_ALG as_rs_alg; + char as_rs_key[OAUTH_KEY_SIZE+1]; + size_t as_rs_key_size; + AUTH_ALG auth_alg; + char auth_key[OAUTH_KEY_SIZE+1]; + size_t auth_key_size; +}; + +typedef struct _oauth_key oauth_key; #endif //__LIB_TURN_MSG_DEFS_NEW__ diff --git a/turndb/schema.sql b/turndb/schema.sql index 36dee3cc..e438bce6 100644 --- a/turndb/schema.sql +++ b/turndb/schema.sql @@ -39,3 +39,16 @@ CREATE TABLE turn_realm_option ( value varchar(128), primary key (realm,opt) ); + +CREATE TABLE oauth_key ( + kid varchar(128), + ikm_key varchar(256), + timestamp bigint, + lifetime integer, + hkdf_hash_func varchar(64), + as_rs_alg varchar(64), + as_rs_key varchar(256), + auth_alg varchar(64), + auth_key varchar(256), + primary key (kid) +); diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis index 69b5f2ef..0d3cae3b 100644 --- a/turndb/schema.userdb.redis +++ b/turndb/schema.userdb.redis @@ -116,7 +116,7 @@ save IV. Redis database configuration parameters TURN Server connects to the Redis and keeps the same connection during the -TURN server lifetime. That means that we have to take care about that +TURN Server process lifetime. That means that we have to take care about that connection - it must not expire. You have to take care about Redis connection parameters, the timeout and the From 58922756279842f900f3ed31d338d380a0ff4bb4 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 24 Aug 2014 19:08:21 +0000 Subject: [PATCH 151/805] working on oauth --- src/apps/relay/dbdrivers/dbdriver.c | 50 +++++++++++++++++++++++++++++ src/apps/relay/dbdrivers/dbdriver.h | 20 ++++++++++++ src/client/ns_turn_msg.c | 3 ++ src/client/ns_turn_msg_defs_new.h | 7 ++-- 4 files changed, 78 insertions(+), 2 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbdriver.c b/src/apps/relay/dbdrivers/dbdriver.c index 807ad715..4f84901c 100644 --- a/src/apps/relay/dbdrivers/dbdriver.c +++ b/src/apps/relay/dbdrivers/dbdriver.c @@ -30,6 +30,9 @@ */ #include "../mainrelay.h" + +#include "apputils.h" + #include "dbdriver.h" #include "dbd_pgsql.h" #include "dbd_mysql.h" @@ -86,5 +89,52 @@ turn_dbdriver_t * get_dbdriver() { return _driver; } +/////////// OAUTH ///////////////// +void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *oakd) +{ + if(raw && oakd) { + + ns_bzero(oakd,sizeof(oauth_key_data)); + + oakd->timestamp = (turn_time_t)raw->timestamp; + oakd->lifetime = raw->lifetime; + + ns_bcopy(raw->as_rs_alg,oakd->as_rs_alg,sizeof(oakd->as_rs_alg)); + ns_bcopy(raw->auth_alg,oakd->auth_alg,sizeof(oakd->auth_alg)); + ns_bcopy(raw->hkdf_hash_func,oakd->hkdf_hash_func,sizeof(oakd->hkdf_hash_func)); + ns_bcopy(raw->kid,oakd->kid,sizeof(oakd->kid)); + + { + size_t ikm_key_size = 0; + char *ikm_key = base64_encode((const unsigned char *)(raw->ikm_key),strlen(raw->ikm_key),&ikm_key_size); + if(ikm_key) { + ns_bcopy(ikm_key,oakd->ikm_key,ikm_key_size); + oakd->ikm_key_size = ikm_key_size; + turn_free(ikm_key,ikm_key_size); + } + } + + { + size_t as_rs_key_size = 0; + char *as_rs_key = base64_encode((const unsigned char *)(raw->as_rs_key),strlen(raw->as_rs_key),&as_rs_key_size); + if(as_rs_key) { + ns_bcopy(as_rs_key,oakd->as_rs_key,as_rs_key_size); + oakd->as_rs_key_size = as_rs_key_size; + turn_free(as_rs_key,as_rs_key_size); + } + } + + { + size_t as_rs_key_size = 0; + char *as_rs_key = base64_encode((const unsigned char *)(raw->as_rs_key),strlen(raw->as_rs_key),&as_rs_key_size); + if(as_rs_key) { + ns_bcopy(as_rs_key,oakd->as_rs_key,as_rs_key_size); + oakd->as_rs_key_size = as_rs_key_size; + turn_free(as_rs_key,as_rs_key_size); + } + } + + } +} diff --git a/src/apps/relay/dbdrivers/dbdriver.h b/src/apps/relay/dbdrivers/dbdriver.h index d123e93e..13102548 100644 --- a/src/apps/relay/dbdrivers/dbdriver.h +++ b/src/apps/relay/dbdrivers/dbdriver.h @@ -34,6 +34,8 @@ #include "../userdb.h" +#include "ns_turn_msg_defs_new.h" + #ifdef __cplusplus extern "C" { #endif @@ -67,6 +69,24 @@ int convert_string_key_to_binary(char* keysource, hmackey_t key, size_t sz); persistent_users_db_t * get_persistent_users_db(void); turn_dbdriver_t * get_dbdriver(void); +////////////// OAUTH UTILS //////////////// + +struct _oauth_key_data_raw { + char kid[OAUTH_KID_SIZE+1]; + char ikm_key[OAUTH_KEY_SIZE+1]; + u64bits timestamp; + u32bits lifetime; + char hkdf_hash_func[OAUTH_HASH_FUNC_SIZE+1]; + char as_rs_alg[OAUTH_ALG_SIZE+1]; + char as_rs_key[OAUTH_KEY_SIZE+1]; + char auth_alg[OAUTH_ALG_SIZE+1]; + char auth_key[OAUTH_KEY_SIZE+1]; +}; + +typedef struct _oauth_key_data_raw oauth_key_data_raw; + +void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *oakd); + //////////////////////////////////////////// #ifdef __cplusplus diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 6b96daff..85229b8e 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1789,6 +1789,9 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, key->timestamp = oakd->timestamp; key->lifetime = oakd->lifetime; + if(!(key->timestamp)) key->timestamp = OAUTH_DEFAULT_TIMESTAMP; + if(!(key->lifetime)) key->lifetime = OAUTH_DEFAULT_LIFETIME; + key->hkdf_hash_func = SHATYPE_SHA256; if(!strcmp(oakd->hkdf_hash_func,"SHA1") || !strcmp(oakd->hkdf_hash_func,"SHA-1")) { key->hkdf_hash_func = SHATYPE_SHA1; diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index b65f9df8..e4e7bbbf 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -103,11 +103,14 @@ typedef enum _AUTH_ALG AUTH_ALG; #define OAUTH_ALG_SIZE (64) #define OAUTH_KEY_SIZE (256) +#define OAUTH_DEFAULT_LIFETIME (0) +#define OAUTH_DEFAULT_TIMESTAMP (turn_time()) + struct _oauth_key_data { char kid[OAUTH_KID_SIZE+1]; char ikm_key[OAUTH_KEY_SIZE+1]; size_t ikm_key_size; - u64bits timestamp; + turn_time_t timestamp; turn_time_t lifetime; char hkdf_hash_func[OAUTH_HASH_FUNC_SIZE+1]; char as_rs_alg[OAUTH_ALG_SIZE+1]; @@ -124,7 +127,7 @@ struct _oauth_key { char kid[OAUTH_KID_SIZE+1]; char ikm_key[OAUTH_KEY_SIZE+1]; size_t ikm_key_size; - u64bits timestamp; + turn_time_t timestamp; turn_time_t lifetime; SHATYPE hkdf_hash_func; ENC_ALG as_rs_alg; From e6bc87dd08e4acd38bcb075ed7f59421846e3af9 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 24 Aug 2014 21:18:28 +0000 Subject: [PATCH 152/805] test database setup for oauth --- src/client/ns_turn_msg_defs_new.h | 4 ++-- turndb/schema.mongo.sh | 1 + turndb/schema.userdb.redis | 36 +++++++++++++++++++++++++++++++ turndb/testmongosetup.sh | 2 ++ turndb/testredisdbsetup.sh | 2 ++ turndb/testsqldbsetup.sql | 4 ++++ 6 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index e4e7bbbf..22e10904 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -71,8 +71,8 @@ typedef enum _SHATYPE SHATYPE; enum _ENC_ALG { ENC_ALG_ERROR=-1, ENC_ALG_DEFAULT=0, - AES_128_CBC=ENC_ALG_DEFAULT, - AES_256_CBC, + AES_256_CBC=ENC_ALG_DEFAULT, + AES_128_CBC, ENG_ALG_NUM }; diff --git a/turndb/schema.mongo.sh b/turndb/schema.mongo.sh index c340a1be..867dbb66 100755 --- a/turndb/schema.mongo.sh +++ b/turndb/schema.mongo.sh @@ -8,6 +8,7 @@ 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.realm.ensureIndex({ realm: 1 }, { unique: 1 }); +db.oauth_key.ensureIndex({ kid: 1 }, {unique: 1 }); exit diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis index 0d3cae3b..84d59c47 100644 --- a/turndb/schema.userdb.redis +++ b/turndb/schema.userdb.redis @@ -37,6 +37,39 @@ the option values are "static" (they remain the same for the lifetime of the turnserver process) but 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 +"turn/oauth/kid/". The kid structure fields are: + + ikm_key - (optional) base64-encoded key ("input keying material"); + The ikm_key is not needed if the as_rs_key and auth_key are defined + explicitly in the database; + + timestamp - (optional) the timestamp (in seconds) when the key + lifetime started; + + lifetime - (optional) the key lifetime in seconds; the default value + is 0 - unlimited lifetime. + + hkdf_hash_func - (optional) hash function for HKDF procedure; the + valid values are SHA-1 and SHA-256, with SHA-256 as default; + The hkdf_hash_func is not needed if the as_rs_key and auth_key + are defined explicitly in the database; + + as_rs_alg - oAuth token encryption algorithm; the valid values are + "AES-128-CBC" and "AES-256-CBC", with "AES-256-CBC" as default; + + as_rs_key - (optional) base64-encoded AS-RS key. If not defined, then + calculated with ikm_key and hkdf_hash_func. The as_rs_key length + is defined by as_rs_alg. + + auth_alg - oAuth token authentication algorithm; the valid values are + "HMAC-SHA-256-128", "HMAC-SHA-256" and "HMAC-SHA-1", with + "HMAC-SHA-256-128" as default; + + 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. + II. Extra realms data in the database We can use more than one realm with the same instance of the TURN server. @@ -68,6 +101,7 @@ 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 shell command would be: @@ -109,6 +143,8 @@ set turn/denied-peer-ip/234567 "123::45" set turn/allowed-peer-ip/345678 "172.17.13.200" +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' + save ! diff --git a/turndb/testmongosetup.sh b/turndb/testmongosetup.sh index 067d5d56..7567942a 100755 --- a/turndb/testmongosetup.sh +++ b/turndb/testmongosetup.sh @@ -41,6 +41,8 @@ db.allowed_peer_ip.insert({ ip_range: '172.17.13.200' }); db.denied_peer_ip.insert({ ip_range: '172.17.13.133-172.17.14.56' }); db.denied_peer_ip.insert({ ip_range: '123::45' }); +db.oauth_key.insert({ kid: 'north', ikm_key: 'Y2FybGVvbg==', hkdf_hash_func: 'SHA-256', as_rs_alg: 'AES-128-CBC', auth_alg: 'HMAC-SHA-256-128' }); + exit EOF diff --git a/turndb/testredisdbsetup.sh b/turndb/testredisdbsetup.sh index 888fe672..bfeb8713 100755 --- a/turndb/testredisdbsetup.sh +++ b/turndb/testredisdbsetup.sh @@ -38,6 +38,8 @@ set turn/denied-peer-ip/234567 "123::45" set turn/allowed-peer-ip/345678 "172.17.13.200" +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' + save ! diff --git a/turndb/testsqldbsetup.sql b/turndb/testsqldbsetup.sql index 32b390ed..acbddc38 100644 --- a/turndb/testsqldbsetup.sql +++ b/turndb/testsqldbsetup.sql @@ -26,3 +26,7 @@ insert into allowed_peer_ip (ip_range) values('172.17.13.200'); insert into denied_peer_ip (ip_range) values('172.17.13.133-172.17.14.56'); insert into denied_peer_ip (ip_range) values('123::45'); + +insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('north','Y2FybGVvbg==',0,0,'SHA-256','AES-256-CBC','','HMAC-SHA-256-128',''); + +); From 268de3e3d139a3d0bfe1620eb020ec704a36db18 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 27 Aug 2014 07:19:48 +0000 Subject: [PATCH 153/805] working on oauth --- INSTALL | 15 ++ src/apps/relay/dbdrivers/dbd_mongo.c | 220 ++++++++++++++++++++++++++- src/apps/relay/dbdrivers/dbd_mysql.c | 177 ++++++++++++++++++++- src/apps/relay/dbdrivers/dbd_pgsql.c | 140 ++++++++++++++++- src/apps/relay/dbdrivers/dbd_redis.c | 131 +++++++++++++++- src/apps/relay/dbdrivers/dbdriver.h | 34 +++-- turndb/schema.sql | 16 +- 7 files changed, 702 insertions(+), 31 deletions(-) diff --git a/INSTALL b/INSTALL index 61bb168c..258bec21 100644 --- a/INSTALL +++ b/INSTALL @@ -769,6 +769,21 @@ 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. +# oAuth key storage table. +# +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) +); + 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. diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index d6ae37ec..ae02593c 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -234,6 +234,79 @@ static int mongo_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) { bson_destroy(&fields); return ret; } + +static int mongo_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { + + mongoc_collection_t * collection = mongo_get_collection("oauth_key"); + + if (!collection) + return -1; + + bson_t query; + bson_init(&query); + BSON_APPEND_UTF8(&query, "kid", (const char *)key->kid); + + bson_t fields; + bson_init(&fields); + BSON_APPEND_INT32(&fields, "lifetime", 1); + BSON_APPEND_INT32(&fields, "timestamp", 1); + BSON_APPEND_INT32(&fields, "as_rs_alg", 1); + BSON_APPEND_INT32(&fields, "as_rs_key", 1); + BSON_APPEND_INT32(&fields, "auth_alg", 1); + BSON_APPEND_INT32(&fields, "auth_key", 1); + BSON_APPEND_INT32(&fields, "hkdf_hash_func", 1); + BSON_APPEND_INT32(&fields, "ikm_key", 1); + + mongoc_cursor_t * cursor; + cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 1, 0, + &query, &fields, NULL); + + int ret = -1; + + ns_bzero(key,sizeof(oauth_key_data_raw)); + STRCPY(key->kid,kid); + + if (!cursor) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Error querying MongoDB collection 'oauth_key'\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, "as_rs_alg") && BSON_ITER_HOLDS_UTF8(&iter)) { + STRCPY(key->as_rs_alg,bson_iter_utf8(&iter, &length)); + } + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "as_rs_key") && BSON_ITER_HOLDS_UTF8(&iter)) { + STRCPY(key->as_rs_key,bson_iter_utf8(&iter, &length)); + } + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "auth_alg") && BSON_ITER_HOLDS_UTF8(&iter)) { + STRCPY(key->auth_alg,bson_iter_utf8(&iter, &length)); + } + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "auth_key") && BSON_ITER_HOLDS_UTF8(&iter)) { + STRCPY(key->auth_key,bson_iter_utf8(&iter, &length)); + } + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "ikm_key") && BSON_ITER_HOLDS_UTF8(&iter)) { + STRCPY(key->ikm_key,bson_iter_utf8(&iter, &length)); + } + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "hkdf_hash_func") && BSON_ITER_HOLDS_UTF8(&iter)) { + STRCPY(key->hkdf_hash_func,bson_iter_utf8(&iter, &length)); + } + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "timestamp") && BSON_ITER_HOLDS_INT64(&iter)) { + key->timestamp = (u64bits)bson_iter_int64(&iter); + } + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "lifetime") && BSON_ITER_HOLDS_INT32(&iter)) { + key->lifetime = (u32bits)bson_iter_int32(&iter); + } + ret = 0; + } + mongoc_cursor_destroy(cursor); + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + bson_destroy(&fields); + return ret; +} static int mongo_get_user_pwd(u08bits *usname, st_password_t pwd) { mongoc_collection_t * collection = mongo_get_collection("turnusers_st"); @@ -302,7 +375,43 @@ static int mongo_set_user_key(u08bits *usname, u08bits *realm, const char *key) 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"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user key information\n"); + } else { + ret = 0; + } + mongoc_collection_destroy(collection); + bson_destroy(&doc); + bson_destroy(&query); + return ret; +} + +static int mongo_set_oauth_key(oauth_key_data_raw *key) { + + mongoc_collection_t * collection = mongo_get_collection("oauth_key"); + + if(!collection) + return -1; + + bson_t query; + bson_init(&query); + BSON_APPEND_UTF8(&query, "kid", (const char *)key->kid); + + bson_t doc; + bson_init(&doc); + BSON_APPEND_UTF8(&query, "kid", (const char *)key->kid); + BSON_APPEND_UTF8(&doc, "as_rs_alg", (const char *)key->as_rs_alg); + BSON_APPEND_UTF8(&doc, "as_rs_key", (const char *)key->as_rs_key); + BSON_APPEND_UTF8(&doc, "auth_alg", (const char *)key->auth_alg); + BSON_APPEND_UTF8(&doc, "auth_key", (const char *)key->auth_key); + BSON_APPEND_UTF8(&doc, "hkdf_hash_func", (const char *)key->hkdf_hash_func); + BSON_APPEND_UTF8(&doc, "ikm_key", (const char *)key->ikm_key); + BSON_APPEND_INT64(&doc, "timestamp", (int64_t)key->timestamp); + BSON_APPEND_INT32(&doc, "lifetime", (int32_t)key->lifetime); + + 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 oauth key information\n"); } else { ret = 0; } @@ -364,6 +473,29 @@ static int mongo_del_user(u08bits *usname, int is_st, u08bits *realm) { bson_destroy(&query); return ret; } + +static int mongo_del_oauth_key(const u08bits *kid) { + + mongoc_collection_t * collection = mongo_get_collection("oauth_key"); + + if(!collection) + return -1; + + bson_t query; + bson_init(&query); + BSON_APPEND_UTF8(&query, "kid", (const char *)kid); + + int ret = -1; + + if (!mongoc_collection_delete(collection, MONGOC_DELETE_SINGLE_REMOVE, &query, NULL, NULL)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting oauth key information\n"); + } else { + ret = 0; + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + return ret; +} static int mongo_list_users(int is_st, u08bits *realm) { const char * collection_name = is_st ? "turnusers_st" : "turnusers_lt"; @@ -425,6 +557,86 @@ static int mongo_list_users(int is_st, u08bits *realm) { bson_destroy(&fields); return ret; } + +static int mongo_list_oauth_keys(void) { + + const char * collection_name = "oauth_key"; + 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, "kid", -1, 1); + bson_append_document_end(&query, &child); + + bson_t fields; + bson_init(&fields); + BSON_APPEND_INT32(&fields, "kid", 1); + BSON_APPEND_INT32(&fields, "lifetime", 1); + BSON_APPEND_INT32(&fields, "timestamp", 1); + BSON_APPEND_INT32(&fields, "as_rs_alg", 1); + BSON_APPEND_INT32(&fields, "as_rs_key", 1); + BSON_APPEND_INT32(&fields, "auth_alg", 1); + BSON_APPEND_INT32(&fields, "auth_key", 1); + BSON_APPEND_INT32(&fields, "hkdf_hash_func", 1); + BSON_APPEND_INT32(&fields, "ikm_key", 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; + oauth_key_data_raw key_; + oauth_key_data_raw *key=&key_; + uint32_t length; + bson_iter_t iter; + while (mongoc_cursor_next(cursor, &item)) { + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "kid") && BSON_ITER_HOLDS_UTF8(&iter)) { + STRCPY(key->kid,bson_iter_utf8(&iter, &length)); + } + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "as_rs_alg") && BSON_ITER_HOLDS_UTF8(&iter)) { + STRCPY(key->as_rs_alg,bson_iter_utf8(&iter, &length)); + } + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "as_rs_key") && BSON_ITER_HOLDS_UTF8(&iter)) { + STRCPY(key->as_rs_key,bson_iter_utf8(&iter, &length)); + } + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "auth_alg") && BSON_ITER_HOLDS_UTF8(&iter)) { + STRCPY(key->auth_alg,bson_iter_utf8(&iter, &length)); + } + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "auth_key") && BSON_ITER_HOLDS_UTF8(&iter)) { + STRCPY(key->auth_key,bson_iter_utf8(&iter, &length)); + } + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "ikm_key") && BSON_ITER_HOLDS_UTF8(&iter)) { + STRCPY(key->ikm_key,bson_iter_utf8(&iter, &length)); + } + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "hkdf_hash_func") && BSON_ITER_HOLDS_UTF8(&iter)) { + STRCPY(key->hkdf_hash_func,bson_iter_utf8(&iter, &length)); + } + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "timestamp") && BSON_ITER_HOLDS_INT64(&iter)) { + key->timestamp = (u64bits)bson_iter_int64(&iter); + } + 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); + } + mongoc_cursor_destroy(cursor); + ret = 0; + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + bson_destroy(&fields); + return ret; +} static int mongo_show_secret(u08bits *realm) { mongoc_collection_t * collection = mongo_get_collection("turn_secret"); @@ -921,7 +1133,11 @@ static turn_dbdriver_t driver = { &mongo_list_realm_options, &mongo_auth_ping, &mongo_get_ip_list, - &mongo_reread_realms + &mongo_reread_realms, + &mongo_set_oauth_key, + &mongo_get_oauth_key, + &mongo_del_oauth_key, + &mongo_list_oauth_keys }; turn_dbdriver_t * get_mongo_dbdriver(void) { diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index dee2feb9..ee091f61 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -372,6 +372,140 @@ static int mysql_get_user_pwd(u08bits *usname, st_password_t pwd) { } return ret; } + +static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { + + int ret = 1; + char statement[TURN_LONG_STRING_SIZE]; + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key from oauth_key where kid='%s'",(const char*)kid); + + 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)!=8) { + 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) { + STRCPY((char*)key->kid,kid); + ns_bcopy(row[0],key->ikm_key,lengths[0]); + key->ikm_key[lengths[0]]=0; + + char stimestamp[128]; + ns_bcopy(row[1],stimestamp,lengths[1]); + stimestamp[lengths[1]]=0; + key->timestamp = (u64bits)strtoull(stimestamp,NULL,10); + + char slifetime[128]; + ns_bcopy(row[2],slifetime,lengths[2]); + slifetime[lengths[2]]=0; + key->lifetime = (u32bits)strtoul(slifetime,NULL,10); + + ns_bcopy(row[3],key->hkdf_hash_func,lengths[3]); + key->hkdf_hash_func[lengths[3]]=0; + + ns_bcopy(row[4],key->as_rs_alg,lengths[4]); + key->as_rs_alg[lengths[4]]=0; + + ns_bcopy(row[5],key->as_rs_key,lengths[5]); + key->as_rs_key[lengths[5]]=0; + + ns_bcopy(row[6],key->auth_alg,lengths[6]); + key->auth_alg[lengths[6]]=0; + + ns_bcopy(row[7],key->auth_key,lengths[7]); + key->auth_key[lengths[7]]=0; + + ret = 0; + } + } + } + + if(mres) + mysql_free_result(mres); + } + } + return ret; +} + +static int mysql_list_oauth_keys(void) { + + oauth_key_data_raw key_; + oauth_key_data_raw *key=&key_; + int ret = 1; + char statement[TURN_LONG_STRING_SIZE]; + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key,kid from oauth_key order by kid"); + + 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)!=9) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement); + } else { + MYSQL_ROW row = mysql_fetch_row(mres); + while(row) { + unsigned long *lengths = mysql_fetch_lengths(mres); + if(lengths) { + + ns_bcopy(row[0],key->ikm_key,lengths[0]); + key->ikm_key[lengths[0]]=0; + + char stimestamp[128]; + ns_bcopy(row[1],stimestamp,lengths[1]); + stimestamp[lengths[1]]=0; + key->timestamp = (u64bits)strtoull(stimestamp,NULL,10); + + char slifetime[128]; + ns_bcopy(row[2],slifetime,lengths[2]); + slifetime[lengths[2]]=0; + key->lifetime = (u32bits)strtoul(slifetime,NULL,10); + + ns_bcopy(row[3],key->hkdf_hash_func,lengths[3]); + key->hkdf_hash_func[lengths[3]]=0; + ns_bcopy(row[4],key->as_rs_alg,lengths[4]); + key->as_rs_alg[lengths[4]]=0; + + ns_bcopy(row[5],key->as_rs_key,lengths[5]); + key->as_rs_key[lengths[5]]=0; + + ns_bcopy(row[6],key->auth_alg,lengths[6]); + key->auth_alg[lengths[6]]=0; + + ns_bcopy(row[7],key->auth_key,lengths[7]); + key->auth_key[lengths[7]]=0; + + 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", + 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); + } + } + + if(mres) + mysql_free_result(mres); + } + } + + return ret; +} static int mysql_set_user_key(u08bits *usname, u08bits *realm, const char *key) { int ret = 1; @@ -390,6 +524,27 @@ static int mysql_set_user_key(u08bits *usname, u08bits *realm, const char *key) } return ret; } + +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) { + snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s','%s','%s')", + 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); + int res = mysql_query(myc, statement); + if(res) { + snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, hkdf_hash_func = '%s', as_rs_alg='%s',as_rs_key='%s',auth_alg='%s',auth_key='%s' where kid='%s'",key->ikm_key,(unsigned 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,key->kid); + res = mysql_query(myc, statement); + if(res) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating oauth key information: %s\n",mysql_error(myc)); + } + } + } + return ret; +} static int mysql_set_user_pwd(u08bits *usname, st_password_t pwd) { int ret = 1; @@ -430,6 +585,22 @@ static int mysql_del_user(u08bits *usname, int is_st, u08bits *realm) { } return ret; } + +static int mysql_del_oauth_key(const u08bits *kid) { + int ret = 1; + char statement[TURN_LONG_STRING_SIZE]; + MYSQL * myc = get_mydb_connection(); + if(myc) { + snprintf(statement,sizeof(statement),"delete from oauth_key where kid = '%s'",(const char*)kid); + int res = mysql_query(myc, statement); + if(res) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting oauth key information: %s\n",mysql_error(myc)); + } else { + ret = 0; + } + } + return ret; +} static int mysql_list_users(int is_st, u08bits *realm) { int ret = 1; @@ -893,7 +1064,11 @@ static turn_dbdriver_t driver = { &mysql_list_realm_options, &mysql_auth_ping, &mysql_get_ip_list, - &mysql_reread_realms + &mysql_reread_realms, + &mysql_set_oauth_key, + &mysql_get_oauth_key, + &mysql_del_oauth_key, + &mysql_list_oauth_keys }; turn_dbdriver_t * get_mysql_dbdriver(void) { diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index 28737027..fd2548fa 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -174,6 +174,86 @@ static int pgsql_get_user_pwd(u08bits *usname, st_password_t pwd) { } return ret; } + +static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { + + int ret = 1; + + char statement[TURN_LONG_STRING_SIZE]; + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key from oauth_key where kid='%s'",(const char*)kid); + + 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 { + STRCPY((char*)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); + ret = 0; + } + + if(res) { + PQclear(res); + } + } + + return ret; +} + +static int pgsql_list_oauth_keys(void) { + + oauth_key_data_raw key_; + oauth_key_data_raw *key=&key_; + + int ret = 1; + + char statement[TURN_LONG_STRING_SIZE]; + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key,kid from oauth_key order by kid"); + + PGconn * pqc = get_pqdb_connection(); + if(pqc) { + 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; + for(i=0;iikm_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)); + + 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; + } + } + + if(res) { + PQclear(res); + } + } + + return ret; +} static int pgsql_set_user_key(u08bits *usname, u08bits *realm, const char *key) { int ret = 1; @@ -201,7 +281,38 @@ static int pgsql_set_user_key(u08bits *usname, u08bits *realm, const char *key) } return ret; } - + +static int pgsql_set_oauth_key(oauth_key_data_raw *key) { + + int ret = 1; + char statement[TURN_LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if(pqc) { + snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s','%s','%s')", + 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); + + PGresult *res = PQexec(pqc, statement); + if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { + if(res) { + PQclear(res); + } + snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, hkdf_hash_func = '%s', as_rs_alg='%s',as_rs_key='%s',auth_alg='%s',auth_key='%s' where kid='%s'",key->ikm_key,(unsigned 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,key->kid); + res = PQexec(pqc, statement); + if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating oauth_key information: %s\n",PQerrorMessage(pqc)); + } 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]; @@ -246,6 +357,27 @@ static int pgsql_del_user(u08bits *usname, int is_st, u08bits *realm) { } return ret; } + +static int pgsql_del_oauth_key(const u08bits *kid) { + + int ret = 1; + char statement[TURN_LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if(pqc) { + snprintf(statement,sizeof(statement),"delete from oauth_key where kid = '%s'",(const char*)kid); + + PGresult *res = PQexec(pqc, statement); + if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting oauth_key information: %s\n",PQerrorMessage(pqc)); + } else { + ret = 0; + } + if(res) { + PQclear(res); + } + } + return ret; +} static int pgsql_list_users(int is_st, u08bits *realm) { int ret = 1; @@ -655,7 +787,11 @@ static turn_dbdriver_t driver = { &pgsql_list_realm_options, &pgsql_auth_ping, &pgsql_get_ip_list, - &pgsql_reread_realms + &pgsql_reread_realms, + &pgsql_set_oauth_key, + &pgsql_get_oauth_key, + &pgsql_del_oauth_key, + &pgsql_list_oauth_keys }; turn_dbdriver_t * get_pgsql_dbdriver(void) { diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index c368ec33..5f34cf50 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -492,6 +492,53 @@ static int redis_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) { } return ret; } + +static int redis_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { + int ret = 1; + redisContext * rc = get_redis_connection(); + if(rc) { + char s[TURN_LONG_STRING_SIZE]; + ns_bzero(key,sizeof(oauth_key_data_raw)); + STRCPY(key->kid,kid); + snprintf(s,sizeof(s),"hgetall turn/oauth/kid/%s", (const char*)kid); + 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 { + size_t i; + for (i = 0; i < (reply->elements)/2; ++i) { + char *kw = reply->element[i]->str; + if(kw) { + if(!strcmp(kw,"as_rs_alg")) { + STRCPY(key->as_rs_alg,reply->element[i+1]->str); + } else if(!strcmp(kw,"as_rs_key")) { + STRCPY(key->as_rs_key,reply->element[i+1]->str); + } else if(!strcmp(kw,"auth_key")) { + STRCPY(key->auth_key,reply->element[i+1]->str); + } else if(!strcmp(kw,"auth_alg")) { + STRCPY(key->auth_alg,reply->element[i+1]->str); + } else if(!strcmp(kw,"ikm_key")) { + STRCPY(key->ikm_key,reply->element[i+1]->str); + } else if(!strcmp(kw,"hkdf_hash_func")) { + STRCPY(key->hkdf_hash_func,reply->element[i+1]->str); + } else if(!strcmp(kw,"timestamp")) { + key->timestamp = (u64bits)strtoull(reply->element[i+1]->str,NULL,10); + } else if(!strcmp(kw,"lifetime")) { + key->lifetime = (u32bits)strtoul(reply->element[i+1]->str,NULL,10); + } + } + } + } + turnFreeRedisReply(reply); + ret = 0; + } + } + return ret; +} static int redis_get_user_pwd(u08bits *usname, st_password_t pwd) { int ret = 1; @@ -531,16 +578,30 @@ static int redis_set_user_key(u08bits *usname, u08bits *realm, const char *key) } return ret; } + +static int redis_set_oauth_key(oauth_key_data_raw *key) { + int ret = 1; + 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", + 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")); + ret = 0; + } + return ret; +} static int redis_set_user_pwd(u08bits *usname, st_password_t pwd) { 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)); + snprintf(statement,sizeof(statement),"set turn/user/%s/password %s",usname,pwd); + turnFreeRedisReply(redisCommand(rc, statement)); turnFreeRedisReply(redisCommand(rc, "save")); - ret = 0; + ret = 0; } return ret; } @@ -565,6 +626,19 @@ static int redis_del_user(u08bits *usname, int is_st, u08bits *realm) { } return ret; } + +static int redis_del_oauth_key(const u08bits *kid) { + int ret = 1; + redisContext *rc = get_redis_connection(); + if(rc) { + char statement[TURN_LONG_STRING_SIZE]; + snprintf(statement,sizeof(statement),"del turn/oauth/kid/%s",(const char*)kid); + turnFreeRedisReply(redisCommand(rc, statement)); + turnFreeRedisReply(redisCommand(rc, "save")); + ret = 0; + } + return ret; +} static int redis_list_users(int is_st, u08bits *realm) { int ret = 1; @@ -656,6 +730,51 @@ static int redis_list_users(int is_st, u08bits *realm) { } return ret; } + +static int redis_list_oauth_keys(void) { + int ret = 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/oauth/kid/*"); + 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); + } + } + + for(isz=0;iszkid, 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); + } + } + + clean_secrets_list(&keys); + ret = 0; + + return ret; +} static int redis_show_secret(u08bits *realm) { int ret = 1; @@ -1134,7 +1253,11 @@ static turn_dbdriver_t driver = { &redis_list_realm_options, &redis_auth_ping, &redis_get_ip_list, - &redis_reread_realms + &redis_reread_realms, + &redis_set_oauth_key, + &redis_get_oauth_key, + &redis_del_oauth_key, + &redis_list_oauth_keys }; turn_dbdriver_t * get_redis_dbdriver(void) { diff --git a/src/apps/relay/dbdrivers/dbdriver.h b/src/apps/relay/dbdrivers/dbdriver.h index 13102548..e68da531 100644 --- a/src/apps/relay/dbdrivers/dbdriver.h +++ b/src/apps/relay/dbdrivers/dbdriver.h @@ -42,6 +42,22 @@ extern "C" { //////////////////////////////////////////// +struct _oauth_key_data_raw { + char kid[OAUTH_KID_SIZE+1]; + char ikm_key[OAUTH_KEY_SIZE+1]; + u64bits timestamp; + u32bits lifetime; + char hkdf_hash_func[OAUTH_HASH_FUNC_SIZE+1]; + char as_rs_alg[OAUTH_ALG_SIZE+1]; + char as_rs_key[OAUTH_KEY_SIZE+1]; + char auth_alg[OAUTH_ALG_SIZE+1]; + char auth_key[OAUTH_KEY_SIZE+1]; +}; + +typedef struct _oauth_key_data_raw oauth_key_data_raw; + +//////////////////////////////////////////// + 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); @@ -61,6 +77,10 @@ typedef struct _turn_dbdriver_t { void (*auth_ping)(void * rch); int (*get_ip_list)(const char *kind, ip_range_list_t * list); 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); } turn_dbdriver_t; /////////// USER DB CHECK ////////////////// @@ -71,20 +91,6 @@ turn_dbdriver_t * get_dbdriver(void); ////////////// OAUTH UTILS //////////////// -struct _oauth_key_data_raw { - char kid[OAUTH_KID_SIZE+1]; - char ikm_key[OAUTH_KEY_SIZE+1]; - u64bits timestamp; - u32bits lifetime; - char hkdf_hash_func[OAUTH_HASH_FUNC_SIZE+1]; - char as_rs_alg[OAUTH_ALG_SIZE+1]; - char as_rs_key[OAUTH_KEY_SIZE+1]; - char auth_alg[OAUTH_ALG_SIZE+1]; - char auth_key[OAUTH_KEY_SIZE+1]; -}; - -typedef struct _oauth_key_data_raw oauth_key_data_raw; - void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *oakd); //////////////////////////////////////////// diff --git a/turndb/schema.sql b/turndb/schema.sql index e438bce6..cdbb48de 100644 --- a/turndb/schema.sql +++ b/turndb/schema.sql @@ -42,13 +42,13 @@ CREATE TABLE turn_realm_option ( CREATE TABLE oauth_key ( kid varchar(128), - ikm_key varchar(256), - timestamp bigint, - lifetime integer, - hkdf_hash_func varchar(64), - as_rs_alg varchar(64), - as_rs_key varchar(256), - auth_alg varchar(64), - auth_key varchar(256), + 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) ); From 00336faf3dc7ea306d15797df479bd8e960ee022 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 28 Aug 2014 07:05:48 +0000 Subject: [PATCH 154/805] oauth db tests --- src/apps/relay/dbdrivers/dbd_mongo.c | 8 +++++++- src/apps/relay/dbdrivers/dbd_redis.c | 28 ++++++++++++++++------------ src/apps/relay/netengine.c | 3 +++ src/apps/relay/userdb.c | 14 ++++++++++++++ src/apps/relay/userdb.h | 4 ++++ turndb/testmongosetup.sh | 2 +- turndb/testredisdbsetup.sh | 2 +- 7 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index ae02593c..65a0acd6 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -566,11 +566,15 @@ static int mongo_list_oauth_keys(void) { if(!collection) return -1; - bson_t query, child; + bson_t query; bson_init(&query); + + bson_t child; bson_append_document_begin(&query, "$orderby", -1, &child); bson_append_int32(&child, "kid", -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); @@ -598,6 +602,8 @@ static int mongo_list_oauth_keys(void) { uint32_t length; bson_iter_t iter; while (mongoc_cursor_next(cursor, &item)) { + + ns_bzero(key,sizeof(oauth_key_data_raw)); if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "kid") && BSON_ITER_HOLDS_UTF8(&iter)) { STRCPY(key->kid,bson_iter_utf8(&iter, &length)); } diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index 5f34cf50..2966bc3d 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -511,24 +511,25 @@ static int redis_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { } else { size_t i; for (i = 0; i < (reply->elements)/2; ++i) { - char *kw = reply->element[i]->str; + char *kw = reply->element[2*i]->str; + char *val = reply->element[2*i+1]->str; if(kw) { if(!strcmp(kw,"as_rs_alg")) { - STRCPY(key->as_rs_alg,reply->element[i+1]->str); + STRCPY(key->as_rs_alg,val); } else if(!strcmp(kw,"as_rs_key")) { - STRCPY(key->as_rs_key,reply->element[i+1]->str); + STRCPY(key->as_rs_key,val); } else if(!strcmp(kw,"auth_key")) { - STRCPY(key->auth_key,reply->element[i+1]->str); + STRCPY(key->auth_key,val); } else if(!strcmp(kw,"auth_alg")) { - STRCPY(key->auth_alg,reply->element[i+1]->str); + STRCPY(key->auth_alg,val); } else if(!strcmp(kw,"ikm_key")) { - STRCPY(key->ikm_key,reply->element[i+1]->str); + STRCPY(key->ikm_key,val); } else if(!strcmp(kw,"hkdf_hash_func")) { - STRCPY(key->hkdf_hash_func,reply->element[i+1]->str); + STRCPY(key->hkdf_hash_func,val); } else if(!strcmp(kw,"timestamp")) { - key->timestamp = (u64bits)strtoull(reply->element[i+1]->str,NULL,10); + key->timestamp = (u64bits)strtoull(val,NULL,10); } else if(!strcmp(kw,"lifetime")) { - key->lifetime = (u32bits)strtoul(reply->element[i+1]->str,NULL,10); + key->lifetime = (u32bits)strtoul(val,NULL,10); } } } @@ -739,16 +740,18 @@ static int redis_list_oauth_keys(void) { init_secrets_list(&keys); if(rc) { + redisReply *reply = NULL; reply = (redisReply*)redisCommand(rc, "keys turn/oauth/kid/*"); if(reply) { - if (reply->type == REDIS_REPLY_ERROR) + 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) + } 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) { @@ -761,6 +764,7 @@ static int redis_list_oauth_keys(void) { for(isz=0;iszrch); +#if defined(DB_TEST) + run_db_test(); +#endif } return arg; diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 94af2867..5bc6d0cc 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -1101,6 +1101,20 @@ void auth_ping(redis_context_handle rch) } } +///////////////// TEST ///////////////// + +#if defined(DB_TEST) + +void run_db_test(void) +{ + turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd) { + dbd->list_oauth_keys(); + } +} + +#endif + ///////////////// WHITE/BLACK IP LISTS /////////////////// #if !defined(TURN_NO_RWLOCK) diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index a529d1bb..5932cbbe 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -195,6 +195,10 @@ void release_allocation_quota(u08bits *username, u08bits *realm); /////////// Handle user DB ///////////////// +#if defined(DB_TEST) + void run_db_test(void); +#endif + void read_userdb_file(int to_print); void auth_ping(redis_context_handle rch); void reread_realms(void); diff --git a/turndb/testmongosetup.sh b/turndb/testmongosetup.sh index 7567942a..190dee29 100755 --- a/turndb/testmongosetup.sh +++ b/turndb/testmongosetup.sh @@ -41,7 +41,7 @@ db.allowed_peer_ip.insert({ ip_range: '172.17.13.200' }); db.denied_peer_ip.insert({ ip_range: '172.17.13.133-172.17.14.56' }); db.denied_peer_ip.insert({ ip_range: '123::45' }); -db.oauth_key.insert({ kid: 'north', ikm_key: 'Y2FybGVvbg==', hkdf_hash_func: 'SHA-256', as_rs_alg: 'AES-128-CBC', auth_alg: 'HMAC-SHA-256-128' }); +db.oauth_key.insert({ kid: 'north', ikm_key: 'Y2FybGVvbg==', hkdf_hash_func: 'SHA-256', as_rs_alg: 'AES-256-CBC', auth_alg: 'HMAC-SHA-256-128' }); exit diff --git a/turndb/testredisdbsetup.sh b/turndb/testredisdbsetup.sh index bfeb8713..d4d97198 100755 --- a/turndb/testredisdbsetup.sh +++ b/turndb/testredisdbsetup.sh @@ -38,7 +38,7 @@ set turn/denied-peer-ip/234567 "123::45" set turn/allowed-peer-ip/345678 "172.17.13.200" -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-256-CBC' auth_alg 'HMAC-SHA-256-128' save From fe19f4dee088e0f2a0fa630e39f2d6b778c71491 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 28 Aug 2014 07:49:33 +0000 Subject: [PATCH 155/805] oauth db fixes --- .../secure_relay_with_db_mysql_ssl.sh | 2 +- src/apps/relay/dbdrivers/dbd_mongo.c | 4 +-- src/apps/relay/userdb.c | 36 +++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh index c107168b..4cd1725d 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh @@ -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 -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=turn 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 $@ +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 --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 $@ diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index 65a0acd6..12ac65f2 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -244,7 +244,7 @@ static int mongo_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { bson_t query; bson_init(&query); - BSON_APPEND_UTF8(&query, "kid", (const char *)key->kid); + BSON_APPEND_UTF8(&query, "kid", (const char *)kid); bson_t fields; bson_init(&fields); @@ -398,7 +398,7 @@ static int mongo_set_oauth_key(oauth_key_data_raw *key) { bson_t doc; bson_init(&doc); - BSON_APPEND_UTF8(&query, "kid", (const char *)key->kid); + BSON_APPEND_UTF8(&doc, "kid", (const char *)key->kid); BSON_APPEND_UTF8(&doc, "as_rs_alg", (const char *)key->as_rs_alg); BSON_APPEND_UTF8(&doc, "as_rs_key", (const char *)key->as_rs_key); BSON_APPEND_UTF8(&doc, "auth_alg", (const char *)key->auth_alg); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 5bc6d0cc..540b3975 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -1109,7 +1109,43 @@ void run_db_test(void) { turn_dbdriver_t * dbd = get_dbdriver(); if (dbd) { + + printf("DB TEST 1:\n"); dbd->list_oauth_keys(); + + printf("DB TEST 2:\n"); + oauth_key_data_raw key_; + oauth_key_data_raw *key=&key_; + dbd->get_oauth_key((const u08bits*)"north",key); + 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); + + printf("DB TEST 3:\n"); + + STRCPY(key->as_rs_alg,"as_rs_alg"); + STRCPY(key->as_rs_key,"as_rs_key"); + STRCPY(key->auth_alg,"auth_alg"); + STRCPY(key->auth_key,"auth_key"); + STRCPY(key->hkdf_hash_func,"hkdf"); + STRCPY(key->ikm_key,"ikm_key"); + STRCPY(key->kid,"kid"); + key->timestamp = 123; + key->lifetime = 456; + dbd->del_oauth_key((const u08bits*)"kid"); + dbd->set_oauth_key(key); + dbd->list_oauth_keys(); + + printf("DB TEST 4:\n"); + dbd->get_oauth_key((const u08bits*)"kid",key); + 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); + + printf("DB TEST 5:\n"); + dbd->del_oauth_key((const u08bits*)"kid"); + dbd->list_oauth_keys(); + printf("DB TEST END\n"); } } From 294d7906ed19349e3cf6b4405266d9fab433f866 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 28 Aug 2014 15:01:51 +0000 Subject: [PATCH 156/805] working on oauth --- src/apps/relay/dbdrivers/dbdriver.c | 18 +++++----- src/client/ns_turn_msg.c | 56 +++++++++++++++-------------- src/client/ns_turn_msg_defs_new.h | 3 +- 3 files changed, 40 insertions(+), 37 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbdriver.c b/src/apps/relay/dbdrivers/dbdriver.c index 4f84901c..9344eccd 100644 --- a/src/apps/relay/dbdrivers/dbdriver.c +++ b/src/apps/relay/dbdrivers/dbdriver.c @@ -105,7 +105,7 @@ void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *o ns_bcopy(raw->hkdf_hash_func,oakd->hkdf_hash_func,sizeof(oakd->hkdf_hash_func)); ns_bcopy(raw->kid,oakd->kid,sizeof(oakd->kid)); - { + if(raw->ikm_key[0]) { size_t ikm_key_size = 0; char *ikm_key = base64_encode((const unsigned char *)(raw->ikm_key),strlen(raw->ikm_key),&ikm_key_size); if(ikm_key) { @@ -115,7 +115,7 @@ void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *o } } - { + if(raw->as_rs_key[0]) { size_t as_rs_key_size = 0; char *as_rs_key = base64_encode((const unsigned char *)(raw->as_rs_key),strlen(raw->as_rs_key),&as_rs_key_size); if(as_rs_key) { @@ -125,13 +125,13 @@ void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *o } } - { - size_t as_rs_key_size = 0; - char *as_rs_key = base64_encode((const unsigned char *)(raw->as_rs_key),strlen(raw->as_rs_key),&as_rs_key_size); - if(as_rs_key) { - ns_bcopy(as_rs_key,oakd->as_rs_key,as_rs_key_size); - oakd->as_rs_key_size = as_rs_key_size; - turn_free(as_rs_key,as_rs_key_size); + if(raw->auth_key[0]) { + size_t auth_key_size = 0; + char *auth_key = base64_encode((const unsigned char *)(raw->auth_key),strlen(raw->auth_key),&auth_key_size); + if(auth_key) { + ns_bcopy(auth_key,oakd->auth_key,auth_key_size); + oakd->auth_key_size = auth_key_size; + turn_free(auth_key,auth_key_size); } } diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 85229b8e..ae06f33d 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1751,10 +1751,7 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, return -1; } if(!(oakd->auth_key_size)) { - if(err_msg) { - snprintf(err_msg,err_msg_size,"AUTH key is not defined"); - } - return -1; + //AEAD ? } } @@ -1804,6 +1801,21 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, return -1; } + key->auth_alg = AUTH_ALG_DEFAULT; + if(!strcmp(oakd->auth_alg,"HMAC-SHA-1") || !strcmp(oakd->auth_alg,"HMAC-SHA1")) { + key->auth_alg = AUTH_ALG_HMAC_SHA_1; + } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256")) { + key->auth_alg = AUTH_ALG_HMAC_SHA_256; + } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256-128")) { + key->auth_alg = AUTH_ALG_HMAC_SHA_256_128; + } else if(oakd->auth_alg[0]) { + if(err_msg) { + snprintf(err_msg,err_msg_size,"Wrong oAuth token hash algorithm: %s",oakd->auth_alg); + } + key->auth_alg = AUTH_ALG_ERROR; + return -1; + } + key->as_rs_alg = ENC_ALG_DEFAULT; if(!strcmp(oakd->as_rs_alg,"AES-128-CBC")) { key->as_rs_alg = AES_128_CBC; @@ -1816,32 +1828,22 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, return -1; } - key->auth_alg = AUTH_ALG_DEFAULT; - if(!strcmp(oakd->auth_alg,"HMAC-SHA-1") || !strcmp(oakd->auth_alg,"HMAC-SHA1")) { - key->auth_alg = AUTH_ALG_HMAC_SHA_1; - } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256")) { - key->auth_alg = AUTH_ALG_HMAC_SHA_256; - } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256-128")) { - key->auth_alg = AUTH_ALG_HMAC_SHA_256_128; - } else if(oakd->auth_alg[0]) { - if(err_msg) { - snprintf(err_msg,err_msg_size,"Wrong oAuth token hash algorithm: %s",oakd->auth_alg); + if(key->auth_alg == AUTH_ALG_UNDEFINED) { + //AEAD + key->auth_key_size = 0; + key->auth_key[0] = 0; + } else if(!(key->auth_key_size)) { + key->auth_key_size = calculate_auth_key_length(key->auth_alg); + if(calculate_key(key->ikm_key,key->ikm_key_size,key->auth_key,key->auth_key_size,key->hkdf_hash_func,err_msg,err_msg_size)<0) { + return -1; } - return -1; } - } - if(!(key->auth_key_size)) { - key->auth_key_size = calculate_auth_key_length(key->auth_alg); - if(calculate_key(key->ikm_key,key->ikm_key_size,key->auth_key,key->auth_key_size,key->hkdf_hash_func,err_msg,err_msg_size)<0) { - return -1; - } - } - - if(!(key->as_rs_key_size)) { - key->as_rs_key_size = calculate_enc_key_length(key->as_rs_alg); - if(calculate_key(key->ikm_key,key->ikm_key_size,key->as_rs_key,key->as_rs_key_size,key->hkdf_hash_func,err_msg,err_msg_size)<0) { - return -1; + if(!(key->as_rs_key_size)) { + key->as_rs_key_size = calculate_enc_key_length(key->as_rs_alg); + if(calculate_key(key->ikm_key,key->ikm_key_size,key->as_rs_key,key->as_rs_key_size,key->hkdf_hash_func,err_msg,err_msg_size)<0) { + return -1; + } } } diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 22e10904..f16a8946 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -84,7 +84,8 @@ typedef enum _ENC_ALG ENC_ALG; enum _AUTH_ALG { AUTH_ALG_ERROR = -1, - AUTH_ALG_DEFAULT = 0, + AUTH_ALG_UNDEFINED = 0, + AUTH_ALG_DEFAULT = 1, AUTH_ALG_HMAC_SHA_256_128 = AUTH_ALG_DEFAULT, AUTH_ALG_HMAC_SHA_1, AUTH_ALG_HMAC_SHA_256 From 01ba5fbffe4603e8e75118c6033c8678ad829d8a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 28 Aug 2014 16:05:12 +0000 Subject: [PATCH 157/805] AEAD added --- src/client/ns_turn_msg.c | 12 ++++++++++-- src/client/ns_turn_msg_defs_new.h | 4 ++++ turndb/schema.userdb.redis | 10 ++++++---- turndb/testmongosetup.sh | 12 +++++++++++- turndb/testredisdbsetup.sh | 1 + turndb/testsqldbsetup.sql | 1 + 6 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index ae06f33d..d6e314c8 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1678,9 +1678,9 @@ static size_t calculate_enc_key_length(ENC_ALG a) { switch(a) { case AES_128_CBC: + case AEAD_AES_128_CCM: + case AEAD_AES_128_GCM: return 16; - case AES_256_CBC: - return 32; default: ; }; @@ -1821,6 +1821,14 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, key->as_rs_alg = AES_128_CBC; } else if(!strcmp(oakd->as_rs_alg,"AES-256-CBC")) { 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; + } else if(!strcmp(oakd->as_rs_alg,"AEAD-AES-256-GCM")) { + key->as_rs_alg = AEAD_AES_256_GCM; + } else if(!strcmp(oakd->as_rs_alg,"AEAD-AES-128-CCM")) { + key->as_rs_alg = AEAD_AES_128_CCM; + } else if(!strcmp(oakd->as_rs_alg,"AEAD_AES_256_CCM")) { + key->as_rs_alg = AEAD_AES_256_CCM; } else if(oakd->as_rs_alg[0]) { if(err_msg) { snprintf(err_msg,err_msg_size,"Wrong oAuth token encryption algorithm: %s",oakd->as_rs_alg); diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index f16a8946..258ff5b5 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -73,6 +73,10 @@ enum _ENC_ALG { ENC_ALG_DEFAULT=0, AES_256_CBC=ENC_ALG_DEFAULT, AES_128_CBC, + AEAD_AES_128_GCM, + AEAD_AES_256_GCM, + AEAD_AES_128_CCM, + AEAD_AES_256_CCM, ENG_ALG_NUM }; diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis index 84d59c47..f77e936b 100644 --- a/turndb/schema.userdb.redis +++ b/turndb/schema.userdb.redis @@ -56,15 +56,17 @@ and they will be almost immediately "seen" by the turnserver process. are defined explicitly in the database; as_rs_alg - oAuth token encryption algorithm; the valid values are - "AES-128-CBC" and "AES-256-CBC", with "AES-256-CBC" as default; + "AES-128-CBC" and "AES-256-CBC", , "AEAD-AES-128-GCM", + "AEAD-AES-256-GCM", "AEAD-AES-128-CCM", "AEAD-AES-256-CCM". + The default value is "AES-256-CBC"; as_rs_key - (optional) base64-encoded AS-RS key. If not defined, then calculated with ikm_key and hkdf_hash_func. The as_rs_key length is defined by as_rs_alg. - auth_alg - oAuth token authentication algorithm; the valid values are - "HMAC-SHA-256-128", "HMAC-SHA-256" and "HMAC-SHA-1", with - "HMAC-SHA-256-128" as default; + auth_alg - (optional) oAuth token authentication algorithm; the valid values are + "HMAC-SHA-256-128", "HMAC-SHA-256" and "HMAC-SHA-1". + The default value is "HMAC-SHA-256-128". auth_key - (optional) base64-encoded AUTH key. If not defined, then calculated with ikm_key and hkdf_hash_func. The auth_key length diff --git a/turndb/testmongosetup.sh b/turndb/testmongosetup.sh index 190dee29..93fcdcdd 100755 --- a/turndb/testmongosetup.sh +++ b/turndb/testmongosetup.sh @@ -41,7 +41,17 @@ db.allowed_peer_ip.insert({ ip_range: '172.17.13.200' }); db.denied_peer_ip.insert({ ip_range: '172.17.13.133-172.17.14.56' }); db.denied_peer_ip.insert({ ip_range: '123::45' }); -db.oauth_key.insert({ kid: 'north', ikm_key: 'Y2FybGVvbg==', hkdf_hash_func: 'SHA-256', as_rs_alg: 'AES-256-CBC', auth_alg: 'HMAC-SHA-256-128' }); +db.oauth_key.insert({ kid: 'north', + ikm_key: 'Y2FybGVvbg==', + hkdf_hash_func: 'SHA-256', + as_rs_alg: 'AES-256-CBC', + auth_alg: 'HMAC-SHA-256-128' }); + +db.oauth_key.insert({ kid: 'oldempire', + ikm_key: 'YXVsY3Vz', + hkdf_hash_func: 'SHA-256', + as_rs_alg: 'AEAD-AES-256-GCM', + auth_alg: '' }); exit diff --git a/turndb/testredisdbsetup.sh b/turndb/testredisdbsetup.sh index d4d97198..5e4f2b4a 100755 --- a/turndb/testredisdbsetup.sh +++ b/turndb/testredisdbsetup.sh @@ -39,6 +39,7 @@ set turn/denied-peer-ip/234567 "123::45" set turn/allowed-peer-ip/345678 "172.17.13.200" 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' save diff --git a/turndb/testsqldbsetup.sql b/turndb/testsqldbsetup.sql index acbddc38..d53fb94a 100644 --- a/turndb/testsqldbsetup.sql +++ b/turndb/testsqldbsetup.sql @@ -28,5 +28,6 @@ insert into denied_peer_ip (ip_range) values('172.17.13.133-172.17.14.56'); insert into denied_peer_ip (ip_range) values('123::45'); insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('north','Y2FybGVvbg==',0,0,'SHA-256','AES-256-CBC','','HMAC-SHA-256-128',''); +insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('oldempire','YXVsY3Vz',0,0,'SHA-256','AEAD-AES-256-GCM','','',''); ); From e8e571778afe5b7baf2cd2cfef595fc4a48355c5 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 29 Aug 2014 05:53:29 +0000 Subject: [PATCH 158/805] working on oauth --- src/apps/relay/dbdrivers/dbdriver.c | 6 +++--- src/apps/relay/userdb.c | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbdriver.c b/src/apps/relay/dbdrivers/dbdriver.c index 9344eccd..e3b3b997 100644 --- a/src/apps/relay/dbdrivers/dbdriver.c +++ b/src/apps/relay/dbdrivers/dbdriver.c @@ -107,7 +107,7 @@ void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *o if(raw->ikm_key[0]) { size_t ikm_key_size = 0; - char *ikm_key = base64_encode((const unsigned char *)(raw->ikm_key),strlen(raw->ikm_key),&ikm_key_size); + char *ikm_key = (char*)base64_decode(raw->ikm_key,strlen(raw->ikm_key),&ikm_key_size); if(ikm_key) { ns_bcopy(ikm_key,oakd->ikm_key,ikm_key_size); oakd->ikm_key_size = ikm_key_size; @@ -117,7 +117,7 @@ void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *o if(raw->as_rs_key[0]) { size_t as_rs_key_size = 0; - char *as_rs_key = base64_encode((const unsigned char *)(raw->as_rs_key),strlen(raw->as_rs_key),&as_rs_key_size); + char *as_rs_key = (char*)base64_decode(raw->as_rs_key,strlen(raw->as_rs_key),&as_rs_key_size); if(as_rs_key) { ns_bcopy(as_rs_key,oakd->as_rs_key,as_rs_key_size); oakd->as_rs_key_size = as_rs_key_size; @@ -127,7 +127,7 @@ void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *o if(raw->auth_key[0]) { size_t auth_key_size = 0; - char *auth_key = base64_encode((const unsigned char *)(raw->auth_key),strlen(raw->auth_key),&auth_key_size); + char *auth_key = (char*)base64_decode(raw->auth_key,strlen(raw->auth_key),&auth_key_size); if(auth_key) { ns_bcopy(auth_key,oakd->auth_key,auth_key_size); oakd->auth_key_size = auth_key_size; diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 540b3975..6763bcab 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -1145,6 +1145,25 @@ void run_db_test(void) printf("DB TEST 5:\n"); dbd->del_oauth_key((const u08bits*)"kid"); dbd->list_oauth_keys(); + + printf("DB TEST 6:\n"); + + dbd->get_oauth_key((const u08bits*)"north",key); + + oauth_key_data oakd; + convert_oauth_key_data_raw(key, &oakd); + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, hkdf_hash_func=%s, as_rs_alg=%s, as_rs_key_size=%d, auth_alg=%s, auth_key_size=%d\n", + oakd.kid, oakd.ikm_key, (unsigned long long)oakd.timestamp, (unsigned long)oakd.lifetime, oakd.hkdf_hash_func, + oakd.as_rs_alg, (int)oakd.as_rs_key_size, oakd.auth_alg, (int)oakd.auth_key_size); + + oauth_key oak; + char err_msg[1025]; + err_msg[0]=0; + if(convert_oauth_key_data(&oakd,&oak,err_msg,sizeof(err_msg)-1)<0) { + printf(" ERROR: %s\n",err_msg); + } else { + printf(" OK!\n"); + } printf("DB TEST END\n"); } } From 4f94e424944c135bbfa1bdecf552c11fc258a45f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 1 Sep 2014 09:15:22 +0000 Subject: [PATCH 159/805] Mobility ticket retransmission fixed. --- ChangeLog | 3 ++- src/apps/uclient/startuclient.c | 9 +++++++++ src/server/ns_turn_server.c | 18 ++++++++++++++---- src/server/ns_turn_session.h | 1 + 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2a6b6551..3d203a30 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 08/22/2014 Oleg Moskalenko Version 4.1.2.2 'Vitari': - - SHA-256 memory leak fixed. + - SHA-256 memory leak fixed. + - Mobility ticket retransmission fixed. 08/14/2014 Oleg Moskalenko Version 4.1.2.1 'Vitari': diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 734df9bc..efb2aca7 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -665,6 +665,11 @@ static int clnet_allocate(int verbose, TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "refresh sent\n"); } refresh_sent = 1; + + if(clnet_info->s_mobile_id[0]) { + usleep(10000); + send_buffer(clnet_info, &message, 0,0); + } } else { perror("send"); exit(1); @@ -682,6 +687,10 @@ static int clnet_allocate(int verbose, int len = recv_buffer(clnet_info, &message, 1, 0); + if(clnet_info->s_mobile_id[0]) { + len = recv_buffer(clnet_info, &message, 1, 0); + } + if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index de00da58..709d7d68 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1411,9 +1411,6 @@ static int handle_turn_refresh(turn_turnserver *server, if(!(*(server->mobility))) { *err_code = 405; *reason = (const u08bits *)"Mobility forbidden"; - } if(is_allocation_valid(a)) { - *err_code = 400; - *reason = (const u08bits *)"Mobility ticket cannot be used for a stable, already established allocation"; } else { int smid_len = stun_attr_get_len(sar); if(smid_len>0 && (((size_t)smid_len)old_mobile_id)) { + *err_code = 400; + *reason = (const u08bits *)"Mobility ticket cannot be used for a stable, already established allocation"; + } } } else { *err_code = 400; @@ -1610,6 +1611,7 @@ static int handle_turn_refresh(turn_turnserver *server, //Use new buffer and redefine ss: nbh = ioa_network_buffer_allocate(server->e); ss = orig_ss; + ss->old_mobile_id = mid; size_t len = ioa_network_buffer_get_size(nbh); turn_report_allocation_set(&(ss->alloc), lifetime, 1); @@ -1699,10 +1701,18 @@ static int handle_turn_refresh(turn_turnserver *server, size_t len = ioa_network_buffer_get_size(nbh); stun_init_success_response_str(STUN_METHOD_REFRESH, ioa_network_buffer_data(nbh), &len, tid); - u32bits lt = nswap32(lifetime); + if(ss->s_mobile_id[0]) { + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, + STUN_ATTRIBUTE_MOBILITY_TICKET, + (u08bits*)ss->s_mobile_id,strlen(ss->s_mobile_id)); + ioa_network_buffer_set_size(nbh,len); + } + + u32bits lt = nswap32(lifetime); stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_LIFETIME, (const u08bits*) <, 4); + ioa_network_buffer_set_size(nbh,len); *resp_constructed = 1; diff --git a/src/server/ns_turn_session.h b/src/server/ns_turn_session.h index cfb469ab..44886d6e 100644 --- a/src/server/ns_turn_session.h +++ b/src/server/ns_turn_session.h @@ -97,6 +97,7 @@ struct _ts_ur_super_session { /* Mobile */ int is_mobile; mobile_id_t mobile_id; + mobile_id_t old_mobile_id; char s_mobile_id[33]; /* Realm */ realm_options_t realm_options; From 31089e909c84087664d7462b70a6dd1afd7e3f43 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 1 Sep 2014 18:51:37 +0000 Subject: [PATCH 160/805] db operations fixed --- ChangeLog | 2 ++ src/apps/relay/dbdrivers/dbd_mysql.c | 40 +++++++++++++------------- src/apps/relay/dbdrivers/dbd_pgsql.c | 40 +++++++++++++------------- src/apps/relay/dbdrivers/dbd_redis.c | 42 ++++++++++++++-------------- turndb/testredisdbsetup.sh | 9 ++++++ 5 files changed, 73 insertions(+), 60 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3d203a30..b6826399 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 08/22/2014 Oleg Moskalenko Version 4.1.2.2 'Vitari': + - redis user key operation fixed. + - redis, mysql and psql db operations fixed. - SHA-256 memory leak fixed. - Mobility ticket retransmission fixed. diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index ee091f61..44244d54 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -335,7 +335,9 @@ static int mysql_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) { } static int mysql_get_user_pwd(u08bits *usname, st_password_t pwd) { - int ret = 1; + + int ret = -1; + char statement[TURN_LONG_STRING_SIZE]; snprintf(statement,sizeof(statement),"select password from turnusers_st where name='%s'",usname); @@ -375,7 +377,7 @@ static int mysql_get_user_pwd(u08bits *usname, st_password_t pwd) { static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key from oauth_key where kid='%s'",(const char*)kid); @@ -440,7 +442,7 @@ static int mysql_list_oauth_keys(void) { oauth_key_data_raw key_; oauth_key_data_raw *key=&key_; - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key,kid from oauth_key order by kid"); @@ -508,7 +510,7 @@ static int mysql_list_oauth_keys(void) { } static int mysql_set_user_key(u08bits *usname, u08bits *realm, const char *key) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); if(myc) { @@ -526,7 +528,7 @@ static int mysql_set_user_key(u08bits *usname, u08bits *realm, const char *key) } static int mysql_set_oauth_key(oauth_key_data_raw *key) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); if(myc) { @@ -547,7 +549,7 @@ static int mysql_set_oauth_key(oauth_key_data_raw *key) { } static int mysql_set_user_pwd(u08bits *usname, st_password_t pwd) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); if(myc) { @@ -567,7 +569,7 @@ static int mysql_set_user_pwd(u08bits *usname, st_password_t pwd) { } static int mysql_del_user(u08bits *usname, int is_st, u08bits *realm) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); if(myc) { @@ -587,7 +589,7 @@ static int mysql_del_user(u08bits *usname, int is_st, u08bits *realm) { } static int mysql_del_oauth_key(const u08bits *kid) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); if(myc) { @@ -603,7 +605,7 @@ static int mysql_del_oauth_key(const u08bits *kid) { } static int mysql_list_users(int is_st, u08bits *realm) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); if(myc) { @@ -649,7 +651,7 @@ static int mysql_list_users(int is_st, u08bits *realm) { } static int mysql_show_secret(u08bits *realm) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm); @@ -688,7 +690,7 @@ static int mysql_show_secret(u08bits *realm) { } static int mysql_del_secret(u08bits *secret, u08bits *realm) { - int ret = 1; + int ret = -1; donot_print_connection_success=1; char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); @@ -704,7 +706,7 @@ static int mysql_del_secret(u08bits *secret, u08bits *realm) { } static int mysql_set_secret(u08bits *secret, u08bits *realm) { - int ret = 1; + int ret = -1; donot_print_connection_success = 1; char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); @@ -724,7 +726,7 @@ static int mysql_set_secret(u08bits *secret, u08bits *realm) { } static int mysql_add_origin(u08bits *origin, u08bits *realm) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); if (myc) { @@ -743,7 +745,7 @@ static int mysql_add_origin(u08bits *origin, u08bits *realm) { } static int mysql_del_origin(u08bits *origin) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); if (myc) { @@ -762,7 +764,7 @@ static int mysql_del_origin(u08bits *origin) { } static int mysql_list_origins(u08bits *realm) { - int ret = 1; + int ret = -1; donot_print_connection_success = 1; char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); @@ -803,7 +805,7 @@ static int mysql_list_origins(u08bits *realm) { } static int mysql_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); if (myc) { @@ -828,7 +830,7 @@ static int mysql_set_realm_option_one(u08bits *realm, unsigned long value, const } static int mysql_list_realm_options(u08bits *realm) { - int ret = 1; + int ret = -1; donot_print_connection_success = 1; char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); @@ -890,7 +892,7 @@ static void mysql_auth_ping(void * rch) { } static int mysql_get_ip_list(const char *kind, ip_range_list_t * list) { - int ret = 1; + int ret = -1; MYSQL * myc = get_mydb_connection(); if(myc) { char statement[TURN_LONG_STRING_SIZE]; @@ -916,7 +918,7 @@ static int mysql_get_ip_list(const char *kind, ip_range_list_t * list) { } } } - ret = 0; + ret = 0; } if(mres) diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index fd2548fa..6efbe40b 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -86,7 +86,7 @@ static PGconn *get_pqdb_connection(void) { /////////////////////////////////////////////////////////////////////////////////////////////////////////// static int pgsql_get_auth_secrets(secrets_list_t *sl, u08bits *realm) { - int ret = 1; + int ret = -1; PGconn * pqc = get_pqdb_connection(); if(pqc) { char statement[TURN_LONG_STRING_SIZE]; @@ -114,7 +114,7 @@ static int pgsql_get_auth_secrets(secrets_list_t *sl, u08bits *realm) { } static int pgsql_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) { - int ret = 1; + int ret = -1; PGconn * pqc = get_pqdb_connection(); if(pqc) { char statement[TURN_LONG_STRING_SIZE]; @@ -148,7 +148,7 @@ static int pgsql_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) { } static int pgsql_get_user_pwd(u08bits *usname, st_password_t pwd) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; snprintf(statement,sizeof(statement),"select password from turnusers_st where name='%s'",usname); @@ -177,7 +177,7 @@ static int pgsql_get_user_pwd(u08bits *usname, st_password_t pwd) { static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key from oauth_key where kid='%s'",(const char*)kid); @@ -214,7 +214,7 @@ static int pgsql_list_oauth_keys(void) { oauth_key_data_raw key_; oauth_key_data_raw *key=&key_; - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key,kid from oauth_key order by kid"); @@ -256,7 +256,7 @@ static int pgsql_list_oauth_keys(void) { } static int pgsql_set_user_key(u08bits *usname, u08bits *realm, const char *key) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); if(pqc) { @@ -284,7 +284,7 @@ static int pgsql_set_user_key(u08bits *usname, u08bits *realm, const char *key) static int pgsql_set_oauth_key(oauth_key_data_raw *key) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); if(pqc) { @@ -314,7 +314,7 @@ static int pgsql_set_oauth_key(oauth_key_data_raw *key) { } static int pgsql_set_user_pwd(u08bits *usname, st_password_t pwd) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); if(pqc) { @@ -340,7 +340,7 @@ static int pgsql_set_user_pwd(u08bits *usname, st_password_t pwd) { } static int pgsql_del_user(u08bits *usname, int is_st, u08bits *realm) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); if(pqc) { @@ -360,7 +360,7 @@ static int pgsql_del_user(u08bits *usname, int is_st, u08bits *realm) { static int pgsql_del_oauth_key(const u08bits *kid) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); if(pqc) { @@ -380,7 +380,7 @@ static int pgsql_del_oauth_key(const u08bits *kid) { } static int pgsql_list_users(int is_st, u08bits *realm) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); if(pqc) { @@ -417,7 +417,7 @@ static int pgsql_list_users(int is_st, u08bits *realm) { } static int pgsql_show_secret(u08bits *realm) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm); @@ -446,7 +446,7 @@ static int pgsql_show_secret(u08bits *realm) { } static int pgsql_del_secret(u08bits *secret, u08bits *realm) { - int ret = 1; + int ret = -1; donot_print_connection_success=1; char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); @@ -466,7 +466,7 @@ static int pgsql_del_secret(u08bits *secret, u08bits *realm) { } static int pgsql_set_secret(u08bits *secret, u08bits *realm) { - int ret = 1; + int ret = -1; donot_print_connection_success = 1; char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); @@ -490,7 +490,7 @@ static int pgsql_set_secret(u08bits *secret, u08bits *realm) { } static int pgsql_add_origin(u08bits *origin, u08bits *realm) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); if(pqc) { @@ -509,7 +509,7 @@ static int pgsql_add_origin(u08bits *origin, u08bits *realm) { } static int pgsql_del_origin(u08bits *origin) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); if(pqc) { @@ -528,7 +528,7 @@ static int pgsql_del_origin(u08bits *origin) { } static int pgsql_list_origins(u08bits *realm) { - int ret = 1; + int ret = -1; donot_print_connection_success = 1; char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); @@ -562,7 +562,7 @@ static int pgsql_list_origins(u08bits *realm) { } static int pgsql_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) { - int ret = 1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); if(pqc) { @@ -590,7 +590,7 @@ static int pgsql_set_realm_option_one(u08bits *realm, unsigned long value, const } static int pgsql_list_realm_options(u08bits *realm) { - int ret = 1; + int ret = -1; donot_print_connection_success = 1; char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); @@ -646,7 +646,7 @@ static void pgsql_auth_ping(void * rch) { } static int pgsql_get_ip_list(const char *kind, ip_range_list_t * list) { - int ret = 1; + int ret = -1; PGconn * pqc = get_pqdb_connection(); if(pqc) { char statement[TURN_LONG_STRING_SIZE]; diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index 2966bc3d..d30633ad 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -397,7 +397,7 @@ static int set_redis_realm_opt(char *realm, const char* key, unsigned long *valu /////////////////////////////////////////////////////////////////////////////////////////////////////////// static int redis_get_auth_secrets(secrets_list_t *sl, u08bits *realm) { - int ret = 1; + int ret = -1; redisContext *rc = get_redis_connection(); if(rc) { redisReply *reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/secret/*", (char*)realm); @@ -448,7 +448,7 @@ static int redis_get_auth_secrets(secrets_list_t *sl, u08bits *realm) { } static int redis_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) { - int ret = 1; + int ret = -1; redisContext * rc = get_redis_connection(); if(rc) { char s[TURN_LONG_STRING_SIZE]; @@ -472,7 +472,7 @@ static int redis_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) { } turnFreeRedisReply(rget); } - if(ret != 0) { + if(ret == 0) { snprintf(s,sizeof(s),"get turn/realm/%s/user/%s/password", (char*)realm, usname); rget = (redisReply *)redisCommand(rc, s); if(rget) { @@ -494,7 +494,7 @@ static int redis_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) { } static int redis_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { - int ret = 1; + int ret = -1; redisContext * rc = get_redis_connection(); if(rc) { char s[TURN_LONG_STRING_SIZE]; @@ -542,7 +542,7 @@ static int redis_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { } static int redis_get_user_pwd(u08bits *usname, st_password_t pwd) { - int ret = 1; + int ret = -1; redisContext * rc = get_redis_connection(); if(rc) { char s[TURN_LONG_STRING_SIZE]; @@ -566,7 +566,7 @@ static int redis_get_user_pwd(u08bits *usname, st_password_t pwd) { } static int redis_set_user_key(u08bits *usname, u08bits *realm, const char *key) { - int ret = 1; + int ret = -1; redisContext *rc = get_redis_connection(); if(rc) { char statement[TURN_LONG_STRING_SIZE]; @@ -581,7 +581,7 @@ static int redis_set_user_key(u08bits *usname, u08bits *realm, const char *key) } static int redis_set_oauth_key(oauth_key_data_raw *key) { - int ret = 1; + int ret = -1; redisContext *rc = get_redis_connection(); if(rc) { char statement[TURN_LONG_STRING_SIZE]; @@ -595,7 +595,7 @@ static int redis_set_oauth_key(oauth_key_data_raw *key) { } static int redis_set_user_pwd(u08bits *usname, st_password_t pwd) { - int ret = 1; + int ret = -1; redisContext *rc = get_redis_connection(); if(rc) { char statement[TURN_LONG_STRING_SIZE]; @@ -608,7 +608,7 @@ static int redis_set_user_pwd(u08bits *usname, st_password_t pwd) { } static int redis_del_user(u08bits *usname, int is_st, u08bits *realm) { - int ret = 1; + int ret = -1; redisContext *rc = get_redis_connection(); if(rc) { char statement[TURN_LONG_STRING_SIZE]; @@ -629,7 +629,7 @@ static int redis_del_user(u08bits *usname, int is_st, u08bits *realm) { } static int redis_del_oauth_key(const u08bits *kid) { - int ret = 1; + int ret = -1; redisContext *rc = get_redis_connection(); if(rc) { char statement[TURN_LONG_STRING_SIZE]; @@ -642,7 +642,7 @@ static int redis_del_oauth_key(const u08bits *kid) { } static int redis_list_users(int is_st, u08bits *realm) { - int ret = 1; + int ret = -1; redisContext *rc = get_redis_connection(); if(rc) { secrets_list_t keys; @@ -733,7 +733,7 @@ static int redis_list_users(int is_st, u08bits *realm) { } static int redis_list_oauth_keys(void) { - int ret = 1; + int ret = -1; redisContext *rc = get_redis_connection(); secrets_list_t keys; size_t isz = 0; @@ -781,7 +781,7 @@ static int redis_list_oauth_keys(void) { } static int redis_show_secret(u08bits *realm) { - int ret = 1; + int ret = -1; donot_print_connection_success = 1; redisContext *rc = get_redis_connection(); if(rc) { @@ -836,7 +836,7 @@ static int redis_show_secret(u08bits *realm) { } static int redis_del_secret(u08bits *secret, u08bits *realm) { - int ret = 1; + int ret = -1; donot_print_connection_success = 1; redisContext *rc = get_redis_connection(); if(rc) { @@ -896,7 +896,7 @@ static int redis_del_secret(u08bits *secret, u08bits *realm) { } static int redis_set_secret(u08bits *secret, u08bits *realm) { - int ret = 1; + int ret = -1; donot_print_connection_success = 1; redisContext *rc = get_redis_connection(); if(rc) { @@ -914,7 +914,7 @@ static int redis_set_secret(u08bits *secret, u08bits *realm) { } static int redis_add_origin(u08bits *origin, u08bits *realm) { - int ret = 1; + int ret = -1; redisContext *rc = get_redis_connection(); if(rc) { char s[TURN_LONG_STRING_SIZE]; @@ -929,7 +929,7 @@ static int redis_add_origin(u08bits *origin, u08bits *realm) { } static int redis_del_origin(u08bits *origin) { - int ret = 1; + int ret = -1; redisContext *rc = get_redis_connection(); if(rc) { char s[TURN_LONG_STRING_SIZE]; @@ -944,7 +944,7 @@ static int redis_del_origin(u08bits *origin) { } static int redis_list_origins(u08bits *realm) { - int ret = 1; + int ret = -1; donot_print_connection_success = 1; redisContext *rc = get_redis_connection(); if(rc) { @@ -1002,7 +1002,7 @@ static int redis_list_origins(u08bits *realm) { } static int redis_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) { - int ret = 1; + int ret = -1; redisContext *rc = get_redis_connection(); if(rc) { char s[TURN_LONG_STRING_SIZE]; @@ -1020,7 +1020,7 @@ static int redis_set_realm_option_one(u08bits *realm, unsigned long value, const } static int redis_list_realm_options(u08bits *realm) { - int ret = 1; + int ret = -1; donot_print_connection_success = 1; redisContext *rc = get_redis_connection(); if(rc) { @@ -1095,7 +1095,7 @@ static void redis_auth_ping(void * rch) { } static int redis_get_ip_list(const char *kind, ip_range_list_t * list) { - int ret = 1; + int ret = -1; redisContext *rc = get_redis_connection(); if(rc) { char statement[TURN_LONG_STRING_SIZE]; diff --git a/turndb/testredisdbsetup.sh b/turndb/testredisdbsetup.sh index 5e4f2b4a..e939f202 100755 --- a/turndb/testredisdbsetup.sh +++ b/turndb/testredisdbsetup.sh @@ -7,11 +7,17 @@ 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" @@ -20,6 +26,9 @@ set turn/realm/crinna.org/secret/777888999 "north" 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" From 433485e07cc8636bb291307734a9ab731cb505d6 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 1 Sep 2014 21:39:43 +0000 Subject: [PATCH 161/805] working on oauth --- src/apps/relay/mainrelay.c | 14 +++++++++++++- src/apps/relay/mainrelay.h | 4 ++-- src/apps/relay/netengine.c | 19 +++++++++++++++++++ src/server/ns_turn_ioalib.h | 2 ++ src/server/ns_turn_server.c | 8 ++++---- src/server/ns_turn_session.h | 2 +- 6 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index f29fc79e..0d811e4c 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -85,6 +85,7 @@ LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,0,"", 0,NULL,0,NULL,DEFAULT_GENERAL_RELAY_SERVERS_NUMBER,0, ////////////// Auth server ///////////////////////////////////// {NULL,NULL,NULL,0,NULL}, +"", /////////////// AUX SERVERS //////////////// {NULL,0,{0,NULL}},0, /////////////// ALTERNATE SERVERS //////////////// @@ -1556,7 +1557,7 @@ static int adminmain(int argc, char **argv) static void print_features(unsigned long mfn) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\nRFC 3489/5389/5766/5780/6062/6156 STUN/TURN Server\nVersion %s\n",TURN_SOFTWARE); - + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Server name: %s\n",turn_params.oauth_server_name); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\nMax number of open files/sockets allowed for this process: %lu\n",mfn); if(turn_params.net_engine_version == 1) mfn = mfn/3; @@ -1678,6 +1679,16 @@ static void drop_privileges(void) } } +static void init_oauth_server_name(void) { + struct utsname name; + if(!uname(&name)) { + STRCPY(turn_params.oauth_server_name,name.nodename); + } + if(!turn_params.oauth_server_name[0]) { + STRCPY(turn_params.oauth_server_name,TURN_SOFTWARE); + } +} + int main(int argc, char **argv) { int c = 0; @@ -1703,6 +1714,7 @@ int main(int argc, char **argv) init_listener(); init_secrets_list(&turn_params.default_users_db.ram_db.static_auth_secrets); init_dynamic_ip_lists(); + init_oauth_server_name(); if (!strstr(argv[0], "turnadmin")) { diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index d105b459..be56bd4e 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -65,8 +66,6 @@ #include #include -#include - #include "ns_turn_utils.h" #include "ns_turn_khash.h" @@ -272,6 +271,7 @@ typedef struct _turn_params_ { ////////////// Auth server //////////////// struct auth_server authserver; + char oauth_server_name[1025]; /////////////// AUX SERVERS //////////////// diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 030bb2fd..6198ebdb 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1797,4 +1797,23 @@ void init_listener(void) ns_bzero(&turn_params.listener,sizeof(struct listener_server)); } +void get_oauth_server_name(const char* realm, char *server_name, size_t server_name_size) +{ + if(server_name && server_name_size) { + strncpy(server_name,turn_params.oauth_server_name,server_name_size); + if(realm && realm[0]) { + char* sat = strstr(server_name,"@"); + if(sat) { + *sat = 0; + } + size_t snl = strlen(server_name); + size_t rl = strlen(realm); + if(snl+1+rlquota_used) && ss->server && ((turn_turnserver*)ss->server)->chquotacb && username) { if(((turn_turnserver*)ss->server)->ct == TURN_CREDENTIALS_LONG_TERM) { - if(!(ss->realm_set)) { + if(!(ss->origin_set)) { return -1; } } @@ -3483,7 +3483,7 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, } /* check that the realm is the same as in the original request */ - if(ss->realm_set) { + if(ss->origin_set) { stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh)); @@ -3540,7 +3540,7 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, } /* get the initial origin value */ - if(!err_code && !(ss->realm_set) && (method == STUN_METHOD_ALLOCATE)) { + if(!err_code && !(ss->origin_set) && (method == STUN_METHOD_ALLOCATE)) { stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh)); @@ -3571,7 +3571,7 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, ioa_network_buffer_get_size(in_buffer->nbh), sar); } - ss->realm_set = 1; + ss->origin_set = 1; } if(!err_code && !(*resp_constructed) && !no_response) { diff --git a/src/server/ns_turn_session.h b/src/server/ns_turn_session.h index 44886d6e..8a85477e 100644 --- a/src/server/ns_turn_session.h +++ b/src/server/ns_turn_session.h @@ -101,7 +101,7 @@ struct _ts_ur_super_session { char s_mobile_id[33]; /* Realm */ realm_options_t realm_options; - int realm_set; + int origin_set; s08bits origin[STUN_MAX_ORIGIN_SIZE + 1]; /* Bandwidth */ band_limit_t bps; From 515d31cc4d504b794126024c4058469d420cbc10 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 2 Sep 2014 05:44:45 +0000 Subject: [PATCH 162/805] changelog updated --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index b6826399..baaaeb32 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ Version 4.1.2.2 'Vitari': - redis, mysql and psql db operations fixed. - SHA-256 memory leak fixed. - Mobility ticket retransmission fixed. + - Move debian package from SVN to GIT. (TODO) 08/14/2014 Oleg Moskalenko Version 4.1.2.1 'Vitari': From 7484f1ca0456d90653db80e1f16a6f3b35f777cd Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 2 Sep 2014 08:16:06 +0000 Subject: [PATCH 163/805] changelog update --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index baaaeb32..639def8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,8 @@ Version 4.1.2.2 'Vitari': - SHA-256 memory leak fixed. - Mobility ticket retransmission fixed. - Move debian package from SVN to GIT. (TODO) + - Move secondary download area to coturn.net. (TODO) + - oAuth security implementation. (TODO) 08/14/2014 Oleg Moskalenko Version 4.1.2.1 'Vitari': From e78003e23080122fc06d64fdf61d919510262f19 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 3 Sep 2014 05:31:31 +0000 Subject: [PATCH 164/805] changelog fixed --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 639def8a..646cadb5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,7 +4,7 @@ Version 4.1.2.2 'Vitari': - redis, mysql and psql db operations fixed. - SHA-256 memory leak fixed. - Mobility ticket retransmission fixed. - - Move debian package from SVN to GIT. (TODO) + - Move debian package from SVN to GIT. - Move secondary download area to coturn.net. (TODO) - oAuth security implementation. (TODO) From 841fa05ee8b1e6a8eef5b5513665a4c017e74693 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 3 Sep 2014 06:37:47 +0000 Subject: [PATCH 165/805] changelog updated --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 646cadb5..383ed9ce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,7 +5,7 @@ Version 4.1.2.2 'Vitari': - SHA-256 memory leak fixed. - Mobility ticket retransmission fixed. - Move debian package from SVN to GIT. - - Move secondary download area to coturn.net. (TODO) + - Move secondary download area to coturn.net. - oAuth security implementation. (TODO) 08/14/2014 Oleg Moskalenko From 6a2dc493ce583d7e31c8fd5b97332038b5c0512a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 4 Sep 2014 06:54:01 +0000 Subject: [PATCH 166/805] working on oauth --- src/client/ns_turn_msg.c | 12 ++++++++++++ src/client/ns_turn_msg.h | 2 ++ src/client/ns_turn_msg_defs_new.h | 25 +++++++++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index d6e314c8..1d47ebda 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1858,4 +1858,16 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, return 0; } +int decode_oauth_token(encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +{ + //TODO + return 0; +} + +int encode_oauth_token(encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +{ + //TODO + return 0; +} + /////////////////////////////////////////////////////////////// diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index f4a0bd83..d7e73b10 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -211,6 +211,8 @@ int is_http_get(const char *s, size_t blen); /* OAUTH */ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, size_t err_msg_size); +int decode_oauth_token(encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken); +int encode_oauth_token(encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken); /////////////////////////////////////////////////////////////// diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 258ff5b5..96551b35 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -145,4 +145,29 @@ struct _oauth_key { typedef struct _oauth_key oauth_key; +struct _oauth_encrypted_block { + uint16_t key_length; + uint8_t mac_key[MAXSHASIZE]; + uint64_t timestamp; + uint32_t lifetime; +}; + +typedef struct _oauth_encrypted_block oauth_encrypted_block; + +struct _oauth_token { + oauth_encrypted_block enc_block; + uint8_t mac[MAXSHASIZE]; +}; + +typedef struct _oauth_token oauth_token; + +#define MAX_ENCODED_OAUTH_TOKEN_SIZE (1024) + +struct _encoded_oauth_token { + char token[MAX_ENCODED_OAUTH_TOKEN_SIZE]; + size_t size; +}; + +typedef struct _encoded_oauth_token encoded_oauth_token; + #endif //__LIB_TURN_MSG_DEFS_NEW__ From 65db0bb9f6622652472a3f5fcec0832f89593dfb Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 5 Sep 2014 07:32:28 +0000 Subject: [PATCH 167/805] SSL renegotiation DOS fix merged from parent project --- src/apps/relay/ns_ioalib_engine_impl.c | 67 +++++++++++++++++++++----- src/apps/relay/ns_ioalib_impl.h | 1 + 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 8e71ad36..84fd9742 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -80,6 +80,8 @@ struct turn_sock_extended_err { #define TRIAL_EFFORTS_TO_SEND (2) +#define SSL_MAX_RENEG_NUMBER (3) + const int predef_timer_intervals[PREDEF_TIMERS_NUM] = {30,60,90,120,240,300,360,540,600,700,800,900,1800,3600}; /************** Forward function declarations ******/ @@ -1500,6 +1502,43 @@ ioa_socket_handle create_ioa_socket_from_fd(ioa_engine_handle e, return ret; } +static void ssl_info_callback(SSL *ssl, int where, int ret) { + + UNUSED_ARG(ret); + + if (0 != (where & SSL_CB_HANDSHAKE_START)) { + ioa_socket_handle s = (ioa_socket_handle)SSL_get_app_data(ssl); + if(s) { + ++(s->ssl_renegs); + } + } else if (0 != (where & SSL_CB_HANDSHAKE_DONE)) { + if(ssl->s3) { + ioa_socket_handle s = (ioa_socket_handle)SSL_get_app_data(ssl); + if(s) { + if(s->ssl_renegs>SSL_MAX_RENEG_NUMBER) { + ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; + } + } + } + } +} + +typedef void (*ssl_info_callback_t)(const SSL *ssl,int type,int val); + +static void set_socket_ssl(ioa_socket_handle s, SSL *ssl) +{ + if(s && (s->ssl != ssl)) { + if(s->ssl) { + SSL_set_app_data(s->ssl,NULL); + } + s->ssl = ssl; + if(ssl) { + SSL_set_app_data(ssl,s); + SSL_set_info_callback(ssl, (ssl_info_callback_t)ssl_info_callback); + } + } +} + /* Only must be called for DTLS_SOCKET */ ioa_socket_handle create_ioa_socket_from_ssl(ioa_engine_handle e, ioa_socket_handle parent_s, SSL* ssl, SOCKET_TYPE st, SOCKET_APP_TYPE sat, const ioa_addr *remote_addr, const ioa_addr *local_addr) { @@ -1509,7 +1548,7 @@ ioa_socket_handle create_ioa_socket_from_ssl(ioa_engine_handle e, ioa_socket_han ioa_socket_handle ret = create_ioa_socket_from_fd(e, parent_s->fd, parent_s, st, sat, remote_addr, local_addr); if(ret) { - ret->ssl = ssl; + set_socket_ssl(ret,ssl); if(st == DTLS_SOCKET) STRCPY(ret->orig_ctx_type,"DTLSv1.0"); } @@ -1697,7 +1736,7 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach) ret->username_hash = s->username_hash; ret->realm_hash = s->realm_hash; - ret->ssl = s->ssl; + set_socket_ssl(ret,s->ssl); ret->fd = s->fd; ret->family = s->family; @@ -1752,7 +1791,7 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach) ret->current_tos = s->current_tos; ret->default_tos = s->default_tos; - s->ssl = NULL; + set_socket_ssl(s,NULL); s->fd = -1; } @@ -2324,7 +2363,7 @@ static int socket_input_worker(ioa_socket_handle s) #if defined(SSL_TXT_TLSV1_2) case TURN_TLS_v1_2: if(s->e->tls_ctx_v1_2) { - s->ssl = SSL_new(s->e->tls_ctx_v1_2); + set_socket_ssl(s,SSL_new(s->e->tls_ctx_v1_2)); STRCPY(s->orig_ctx_type,"TLSv1.2"); } break; @@ -2332,35 +2371,37 @@ static int socket_input_worker(ioa_socket_handle s) #if defined(SSL_TXT_TLSV1_1) case TURN_TLS_v1_1: if(s->e->tls_ctx_v1_1) { - s->ssl = SSL_new(s->e->tls_ctx_v1_1); + set_socket_ssl(s,SSL_new(s->e->tls_ctx_v1_1)); STRCPY(s->orig_ctx_type,"TLSv1.1"); } break; #endif case TURN_TLS_v1_0: if(s->e->tls_ctx_v1_0) { - s->ssl = SSL_new(s->e->tls_ctx_v1_0); + set_socket_ssl(s,SSL_new(s->e->tls_ctx_v1_0)); STRCPY(s->orig_ctx_type,"TLSv1.0"); } break; default: if(s->e->tls_ctx_ssl23) { - s->ssl = SSL_new(s->e->tls_ctx_ssl23); + set_socket_ssl(s,SSL_new(s->e->tls_ctx_ssl23)); STRCPY(s->orig_ctx_type,"SSLv23"); } else { s->tobeclosed = 1; return 0; } }; - s->bev = bufferevent_openssl_socket_new(s->e->event_base, + if(s->ssl) { + s->bev = bufferevent_openssl_socket_new(s->e->event_base, s->fd, s->ssl, BUFFEREVENT_SSL_ACCEPTING, BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); - 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. */ + 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. */ + } } else #endif //TURN_NO_TLS { @@ -3212,7 +3253,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in #if !defined(TURN_NO_TLS) if(!(s->ssl)) { //??? how we can get to this point ??? - s->ssl = SSL_new(e->tls_ctx_ssl23); + set_socket_ssl(s,SSL_new(e->tls_ctx_ssl23)); STRCPY(s->orig_ctx_type,"SSLv23"); s->bev = bufferevent_openssl_socket_new(s->e->event_base, s->fd, diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 9a3d8a27..a44f288b 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -179,6 +179,7 @@ struct _ioa_socket SOCKET_TYPE st; SOCKET_APP_TYPE sat; SSL* ssl; + u32bits ssl_renegs; int in_write; char orig_ctx_type[16]; int bound; From 49a8f18cf3f6306de0be837f6684fa68a1ec0f3a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 5 Sep 2014 16:37:52 +0000 Subject: [PATCH 168/805] changelog updated --- ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 383ed9ce..60469ba1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,7 +5,8 @@ Version 4.1.2.2 'Vitari': - SHA-256 memory leak fixed. - Mobility ticket retransmission fixed. - Move debian package from SVN to GIT. - - Move secondary download area to coturn.net. + - Move secondary download area to coturn.net. + - TLS renegotiation DoS attack prevention implemented; - oAuth security implementation. (TODO) 08/14/2014 Oleg Moskalenko From ada99b9898c63dcd53955cbf2b76281ccc9470dd Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 8 Sep 2014 20:55:28 +0000 Subject: [PATCH 169/805] issue 6 fixed --- ChangeLog | 1 + src/client/ns_turn_ioaddr.c | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 60469ba1..9822088c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,7 @@ Version 4.1.2.2 'Vitari': - Move debian package from SVN to GIT. - Move secondary download area to coturn.net. - TLS renegotiation DoS attack prevention implemented; + - FQDN as relay-ip and listener-ip parameters (issue 6); - oAuth security implementation. (TODO) 08/14/2014 Oleg Moskalenko diff --git a/src/client/ns_turn_ioaddr.c b/src/client/ns_turn_ioaddr.c index 26925f36..2c9f44f2 100644 --- a/src/client/ns_turn_ioaddr.c +++ b/src/client/ns_turn_ioaddr.c @@ -29,6 +29,8 @@ */ #include "ns_turn_ioaddr.h" +#include +#include ////////////////////////////////////////////////////////////// @@ -202,7 +204,38 @@ int make_ioa_addr(const u08bits* saddr, int port, ioa_addr *addr) { #endif addr->s6.sin6_port = nswap16(port); } else { - return -1; + struct addrinfo addr_hints; + struct addrinfo *addr_result = NULL; + int err; + + memset(&addr_hints, 0, sizeof(struct addrinfo)); + addr_hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + addr_hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ + addr_hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ + addr_hints.ai_protocol = 0; /* Any protocol */ + addr_hints.ai_canonname = NULL; + addr_hints.ai_addr = NULL; + addr_hints.ai_next = NULL; + + err = getaddrinfo((const char*)saddr, NULL, &addr_hints, &addr_result); + if (err != 0) { + fprintf(stderr,"error resolving '%s' hostname: %s\n",saddr,gai_strerror(err)); + return -1; + } + + // getaddrinfo() returns a list of address structures. We just take the + // first one. + ns_bcopy(addr_result->ai_addr, addr, addr_result->ai_addrlen); + if (addr_result->ai_family == AF_INET) { + addr->s4.sin_port = nswap16(port); + } else if (addr_result->ai_family == AF_INET6) { + addr->s6.sin6_port = nswap16(port); +#if defined(SIN6_LEN) /* this define is required by IPv6 if used */ + addr->s6.sin6_len = sizeof(struct sockaddr_in6); +#endif + } + + freeaddrinfo(addr_result); } return 0; From 8846596e3634a94a535883ed9111e6a2052873c0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 8 Sep 2014 21:27:59 +0000 Subject: [PATCH 170/805] FQDN as listener name --- src/apps/relay/netengine.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 6198ebdb..0e285045 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -286,6 +286,10 @@ void add_listener_addr(const char* addr) { if(make_ioa_addr((const u08bits*)addr,0,&baddr)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot add a listener address: %s\n",addr); } else { + + char sbaddr[129]; + addr_to_string_no_port(&baddr,(u08bits*)sbaddr); + size_t i = 0; for(i=0;i Date: Mon, 8 Sep 2014 21:33:11 +0000 Subject: [PATCH 171/805] FQDN as listener name --- ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 9822088c..99a72291 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,7 +7,8 @@ Version 4.1.2.2 'Vitari': - Move debian package from SVN to GIT. - Move secondary download area to coturn.net. - TLS renegotiation DoS attack prevention implemented; - - FQDN as relay-ip and listener-ip parameters (issue 6); + - FQDN as relay-ip and listener-ip parameters (issue 6) + (patch provided by Iñaki Baz Castillo); - oAuth security implementation. (TODO) 08/14/2014 Oleg Moskalenko From 3465392cc83daca8ee977741b8137638349eb5f3 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 9 Sep 2014 05:29:20 +0000 Subject: [PATCH 172/805] FQDN in relay-ip and listener-ip --- src/client/ns_turn_ioaddr.c | 45 ++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/src/client/ns_turn_ioaddr.c b/src/client/ns_turn_ioaddr.c index 2c9f44f2..afbe3700 100644 --- a/src/client/ns_turn_ioaddr.c +++ b/src/client/ns_turn_ioaddr.c @@ -218,24 +218,47 @@ int make_ioa_addr(const u08bits* saddr, int port, ioa_addr *addr) { addr_hints.ai_next = NULL; err = getaddrinfo((const char*)saddr, NULL, &addr_hints, &addr_result); - if (err != 0) { + if ((err != 0)||(!addr_result)) { fprintf(stderr,"error resolving '%s' hostname: %s\n",saddr,gai_strerror(err)); return -1; } - // getaddrinfo() returns a list of address structures. We just take the - // first one. - ns_bcopy(addr_result->ai_addr, addr, addr_result->ai_addrlen); - if (addr_result->ai_family == AF_INET) { - addr->s4.sin_port = nswap16(port); - } else if (addr_result->ai_family == AF_INET6) { - addr->s6.sin6_port = nswap16(port); -#if defined(SIN6_LEN) /* this define is required by IPv6 if used */ - addr->s6.sin6_len = sizeof(struct sockaddr_in6); + int family = AF_INET; + struct addrinfo *addr_result_orig = addr_result; + int found = 0; + + beg_af: + + while(!found && addr_result) { + + if(addr_result->ai_family == family) { + ns_bcopy(addr_result->ai_addr, addr, addr_result->ai_addrlen); + if (addr_result->ai_family == AF_INET) { + addr->s4.sin_port = nswap16(port); +#if defined(TURN_HAS_SIN_LEN) /* tested when configured */ + addr->s4.sin_len = sizeof(struct sockaddr_in); #endif + } else if (addr_result->ai_family == AF_INET6) { + addr->s6.sin6_port = nswap16(port); +#if defined(SIN6_LEN) /* this define is required by IPv6 if used */ + addr->s6.sin6_len = sizeof(struct sockaddr_in6); +#endif + } else { + continue; + } + found = 1; + } + + addr_result = addr_result->ai_next; + } + + if(!found && family == AF_INET) { + family = AF_INET6; + addr_result = addr_result_orig; + goto beg_af; } - freeaddrinfo(addr_result); + freeaddrinfo(addr_result_orig); } return 0; From 9cccc673202703d14941b7bb4de8442ef7560b17 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 15 Sep 2014 07:50:24 +0000 Subject: [PATCH 173/805] working on oauth --- src/client/ns_turn_msg.c | 222 ++++++++++++++++++++++++++++-- src/client/ns_turn_msg.h | 4 +- src/client/ns_turn_msg_defs_new.h | 5 +- turndb/schema.userdb.redis | 2 +- 4 files changed, 219 insertions(+), 14 deletions(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 1d47ebda..ecc02b0c 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1678,7 +1678,6 @@ static size_t calculate_enc_key_length(ENC_ALG a) { switch(a) { case AES_128_CBC: - case AEAD_AES_128_CCM: case AEAD_AES_128_GCM: return 16; default: @@ -1704,6 +1703,23 @@ static size_t calculate_auth_key_length(AUTH_ALG a) return 32; } +size_t calculate_auth_output_length(AUTH_ALG a); +size_t calculate_auth_output_length(AUTH_ALG a) +{ + switch(a) { + case AUTH_ALG_HMAC_SHA_1: + return 20; + case AUTH_ALG_HMAC_SHA_256_128: + return 16; + case AUTH_ALG_HMAC_SHA_256: + return 32; + default: + ; + }; + + return 32; +} + static int calculate_key(char *key, size_t key_size, char *new_key, size_t new_key_size, SHATYPE shatype, char *err_msg, size_t err_msg_size) { @@ -1825,10 +1841,6 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, key->as_rs_alg = AEAD_AES_128_GCM; } else if(!strcmp(oakd->as_rs_alg,"AEAD-AES-256-GCM")) { key->as_rs_alg = AEAD_AES_256_GCM; - } else if(!strcmp(oakd->as_rs_alg,"AEAD-AES-128-CCM")) { - key->as_rs_alg = AEAD_AES_128_CCM; - } else if(!strcmp(oakd->as_rs_alg,"AEAD_AES_256_CCM")) { - key->as_rs_alg = AEAD_AES_256_CCM; } else if(oakd->as_rs_alg[0]) { if(err_msg) { snprintf(err_msg,err_msg_size,"Wrong oAuth token encryption algorithm: %s",oakd->as_rs_alg); @@ -1858,16 +1870,208 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, return 0; } -int decode_oauth_token(encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +int decode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) { //TODO return 0; } -int encode_oauth_token(encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +static const EVP_CIPHER *get_cipher_type(ENC_ALG enc_alg) { - //TODO - return 0; + switch(enc_alg) { + case AES_256_CBC: + return EVP_aes_256_cbc(); + case AES_128_CBC: + return EVP_aes_128_cbc(); + case AEAD_AES_128_GCM: + return EVP_aes_128_gcm(); + case AEAD_AES_256_GCM: + return EVP_aes_256_gcm(); + default: + ; + } + return NULL; +} + +static void generate_random_nonce(unsigned char *nonce, size_t sz) { + if(!RAND_bytes(nonce, sz)<0) { + size_t i; + for(i=0;i> 1; + default: + ; + }; + } +} + +static int encode_oauth_token_normal(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +{ + if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<=128)) { + + unsigned char orig_field[MAX_ENCODED_OAUTH_TOKEN_SIZE]; + + size_t len = 0; + *((uint16_t*)(orig_field+len)) = nswap16(dtoken->enc_block.key_length); + len +=2; + + ns_bcopy(dtoken->enc_block.mac_key,orig_field+len,dtoken->enc_block.key_length); + len += dtoken->enc_block.key_length; + + *((uint64_t*)(orig_field+len)) = nswap64(dtoken->enc_block.timestamp); + len += 8; + + *((uint32_t*)(orig_field+len)) = nswap32(dtoken->enc_block.lifetime); + len += 4; + + const EVP_CIPHER * cipher = get_cipher_type(key->as_rs_alg); + if(!cipher) + return -1; + + unsigned char *encoded_field = (unsigned char*)etoken->token; + + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + EVP_EncryptInit_ex(&ctx, cipher, NULL, (unsigned char *)key->as_rs_key, NULL); + int outl=0; + EVP_EncryptUpdate(&ctx, encoded_field, &outl, orig_field, (int)len); + EVP_EncryptFinal_ex(&ctx, encoded_field + outl, &outl); + + size_t sn_len = strlen((char*)server_name); + ns_bcopy(server_name,encoded_field+outl,sn_len); + outl += sn_len; + + const EVP_MD *md = get_auth_type(key->auth_alg); + if(!md) + return -1; + + unsigned int hmac_len = EVP_MD_size(md); + if (!HMAC(md, key->auth_key, key->auth_key_size, encoded_field, outl, encoded_field + outl, &hmac_len)) { + return -1; + } + + update_hmac_len(key->auth_alg, &hmac_len); + + ns_bcopy(encoded_field + outl, encoded_field + outl - sn_len, hmac_len); + outl -= sn_len; + outl += hmac_len; //encoded+hmac + + etoken->size = outl; + + return 0; + } + return -1; +} + +static int encode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +{ + if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<128)) { + + unsigned char orig_field[MAX_ENCODED_OAUTH_TOKEN_SIZE]; + + size_t len = 0; + *((uint16_t*)(orig_field+len)) = nswap16(dtoken->enc_block.key_length); + len +=2; + + ns_bcopy(dtoken->enc_block.mac_key,orig_field+len,dtoken->enc_block.key_length); + len += dtoken->enc_block.key_length; + + *((uint64_t*)(orig_field+len)) = nswap64(dtoken->enc_block.timestamp); + len += 8; + + *((uint32_t*)(orig_field+len)) = nswap32(dtoken->enc_block.lifetime); + len += 4; + + const EVP_CIPHER * cipher = get_cipher_type(key->as_rs_alg); + if(!cipher) + return -1; + + unsigned char *encoded_field = (unsigned char*)etoken->token; + + unsigned char nonce[OAUTH_AEAD_NONCE_SIZE]; + generate_random_nonce(nonce, sizeof(nonce)); + + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + + /* Initialise the encryption operation. */ + if(1 != EVP_EncryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) + return -1; + + /* Set IV length if default 12 bytes (96 bits) is not appropriate */ + if(1 != EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, OAUTH_AEAD_NONCE_SIZE, NULL)) + return -1; + + /* Initialise key and IV */ + if(1 != EVP_EncryptInit_ex(&ctx, NULL, NULL, (unsigned char *)key->as_rs_key, nonce)) + return -1; + + int outl=0; + size_t sn_len = strlen((char*)server_name); + + /* Provide any AAD data. This can be called zero or more times as + * required + */ + if(1 != EVP_EncryptUpdate(&ctx, NULL, &outl, server_name, (int)sn_len)) + return -1; + + EVP_EncryptUpdate(&ctx, encoded_field, &outl, orig_field, (int)len); + + int tmp_outl = 0; + EVP_EncryptFinal_ex(&ctx, encoded_field + outl, &tmp_outl); + outl += tmp_outl; + + EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, OAUTH_AEAD_TAG_SIZE, encoded_field + outl); + outl += OAUTH_AEAD_TAG_SIZE; + + ns_bcopy(nonce, encoded_field + outl, OAUTH_AEAD_NONCE_SIZE); + outl += OAUTH_AEAD_NONCE_SIZE; //encoded+hmac + + etoken->size = outl; + + return 0; + } + return -1; +} + +int encode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +{ + if(server_name && etoken && key && dtoken) { + switch(key->as_rs_alg) { + case AES_256_CBC: + case AES_128_CBC: + return encode_oauth_token_normal(server_name, etoken,key,dtoken); + case AEAD_AES_128_GCM: + case AEAD_AES_256_GCM: + return encode_oauth_token_aead(server_name, etoken,key,dtoken); + default: + fprintf(stderr,"Wrong AS_RS algorithm: %d\n",(int)key->as_rs_alg); + }; + } + return -1; } /////////////////////////////////////////////////////////////// diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index d7e73b10..87c6d27d 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -211,8 +211,8 @@ int is_http_get(const char *s, size_t blen); /* OAUTH */ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, size_t err_msg_size); -int decode_oauth_token(encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken); -int encode_oauth_token(encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken); +int decode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken); +int encode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken); /////////////////////////////////////////////////////////////// diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 96551b35..8de90b14 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -75,8 +75,6 @@ enum _ENC_ALG { AES_128_CBC, AEAD_AES_128_GCM, AEAD_AES_256_GCM, - AEAD_AES_128_CCM, - AEAD_AES_256_CCM, ENG_ALG_NUM }; @@ -107,6 +105,8 @@ typedef enum _AUTH_ALG AUTH_ALG; #define OAUTH_HASH_FUNC_SIZE (64) #define OAUTH_ALG_SIZE (64) #define OAUTH_KEY_SIZE (256) +#define OAUTH_AEAD_NONCE_SIZE (12) +#define OAUTH_AEAD_TAG_SIZE (16) #define OAUTH_DEFAULT_LIFETIME (0) #define OAUTH_DEFAULT_TIMESTAMP (turn_time()) @@ -157,6 +157,7 @@ typedef struct _oauth_encrypted_block oauth_encrypted_block; struct _oauth_token { oauth_encrypted_block enc_block; uint8_t mac[MAXSHASIZE]; + size_t mac_size; }; typedef struct _oauth_token oauth_token; diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis index f77e936b..371645e1 100644 --- a/turndb/schema.userdb.redis +++ b/turndb/schema.userdb.redis @@ -57,7 +57,7 @@ and they will be almost immediately "seen" by the turnserver process. as_rs_alg - oAuth token encryption algorithm; the valid values are "AES-128-CBC" and "AES-256-CBC", , "AEAD-AES-128-GCM", - "AEAD-AES-256-GCM", "AEAD-AES-128-CCM", "AEAD-AES-256-CCM". + "AEAD-AES-256-GCM". The default value is "AES-256-CBC"; as_rs_key - (optional) base64-encoded AS-RS key. If not defined, then From 67918a67819e865120cb5560cf1af49ca666e61f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 15 Sep 2014 17:14:16 +0000 Subject: [PATCH 174/805] cosmetics --- src/client/ns_turn_msg.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index ecc02b0c..6eb6b18d 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1870,12 +1870,6 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, return 0; } -int decode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) -{ - //TODO - return 0; -} - static const EVP_CIPHER *get_cipher_type(ENC_ALG enc_alg) { switch(enc_alg) { @@ -2048,7 +2042,7 @@ static int encode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et outl += OAUTH_AEAD_TAG_SIZE; ns_bcopy(nonce, encoded_field + outl, OAUTH_AEAD_NONCE_SIZE); - outl += OAUTH_AEAD_NONCE_SIZE; //encoded+hmac + outl += OAUTH_AEAD_NONCE_SIZE; //encoded+tag+hmac etoken->size = outl; @@ -2074,4 +2068,10 @@ int encode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_ return -1; } +int decode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +{ + //TODO + return 0; +} + /////////////////////////////////////////////////////////////// From ff288fe3f58b7b9b25182cae3c02e1474eae4c7a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 15 Sep 2014 21:06:00 +0000 Subject: [PATCH 175/805] mac os x compilation fixed --- src/client/ns_turn_msg.c | 66 +++++++++++++++++++++++++------ src/client/ns_turn_msg_defs_new.h | 6 +++ 2 files changed, 61 insertions(+), 11 deletions(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 6eb6b18d..9cd3fcbc 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -101,7 +101,7 @@ long turn_random(void) void turn_random32_size(u32bits *ar, size_t sz) { - if(!RAND_bytes((unsigned char *)ar, sz<<2)<0) { + if(!RAND_bytes((unsigned char *)ar, sz<<2)) { size_t i; for(i=0;ias_rs_alg = AES_128_CBC; } else if(!strcmp(oakd->as_rs_alg,"AES-256-CBC")) { key->as_rs_alg = AES_256_CBC; +#if !defined(TURN_NO_GCM_SUPPORT) } else if(!strcmp(oakd->as_rs_alg,"AEAD-AES-128-GCM")) { key->as_rs_alg = AEAD_AES_128_GCM; } else if(!strcmp(oakd->as_rs_alg,"AEAD-AES-256-GCM")) { key->as_rs_alg = AEAD_AES_256_GCM; +#endif } else if(oakd->as_rs_alg[0]) { if(err_msg) { snprintf(err_msg,err_msg_size,"Wrong oAuth token encryption algorithm: %s",oakd->as_rs_alg); @@ -1877,25 +1881,18 @@ static const EVP_CIPHER *get_cipher_type(ENC_ALG enc_alg) return EVP_aes_256_cbc(); case AES_128_CBC: return EVP_aes_128_cbc(); +#if !defined(TURN_NO_GCM_SUPPORT) case AEAD_AES_128_GCM: return EVP_aes_128_gcm(); case AEAD_AES_256_GCM: return EVP_aes_256_gcm(); +#endif default: ; } return NULL; } -static void generate_random_nonce(unsigned char *nonce, size_t sz) { - if(!RAND_bytes(nonce, sz)<0) { - size_t i; - for(i=0;i> 1; + break; default: ; }; @@ -1980,6 +1978,26 @@ static int encode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * return -1; } +static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +{ + if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<=128)) { + + //TODO + } + return -1; +} + +#if !defined(TURN_NO_GCM_SUPPORT) + +static void generate_random_nonce(unsigned char *nonce, size_t sz) { + if(!RAND_bytes(nonce, sz)) { + size_t i; + for(i=0;ienc_block.key_length<128)) { @@ -2051,6 +2069,17 @@ static int encode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et return -1; } +static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +{ + if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<128)) { + + //TODO + } + return -1; +} + +#endif + int encode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) { if(server_name && etoken && key && dtoken) { @@ -2058,9 +2087,11 @@ int encode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_ case AES_256_CBC: case AES_128_CBC: return encode_oauth_token_normal(server_name, etoken,key,dtoken); +#if !defined(TURN_NO_GCM_SUPPORT) case AEAD_AES_128_GCM: case AEAD_AES_256_GCM: return encode_oauth_token_aead(server_name, etoken,key,dtoken); +#endif default: fprintf(stderr,"Wrong AS_RS algorithm: %d\n",(int)key->as_rs_alg); }; @@ -2070,7 +2101,20 @@ int encode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_ int decode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) { - //TODO + if(server_name && etoken && key && dtoken) { + switch(key->as_rs_alg) { + case AES_256_CBC: + case AES_128_CBC: + return decode_oauth_token_normal(server_name, etoken,key,dtoken); +#if !defined(TURN_NO_GCM_SUPPORT) + case AEAD_AES_128_GCM: + case AEAD_AES_256_GCM: + return decode_oauth_token_aead(server_name, etoken,key,dtoken); +#endif + default: + fprintf(stderr,"Wrong AS_RS algorithm: %d\n",(int)key->as_rs_alg); + }; + } return 0; } diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 8de90b14..3016e17c 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -68,13 +68,19 @@ typedef enum _SHATYPE SHATYPE; /* OAUTH TOKEN ENC ALG ==> */ +#if !defined(EVP_CIPH_GCM_MODE) +#define TURN_NO_GCM_SUPPORT +#endif + enum _ENC_ALG { ENC_ALG_ERROR=-1, ENC_ALG_DEFAULT=0, AES_256_CBC=ENC_ALG_DEFAULT, AES_128_CBC, +#if !defined(TURN_NO_GCM_SUPPORT) AEAD_AES_128_GCM, AEAD_AES_256_GCM, +#endif ENG_ALG_NUM }; From 475e4c22e368ea09201ff876cf948e2465810a61 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 15 Sep 2014 21:46:54 +0000 Subject: [PATCH 176/805] mac os x compilation fixed --- src/client/ns_turn_msg.c | 68 +++++++++++++++++++++++++++++++++++++--- src/ns_turn_defs.h | 1 + 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 9cd3fcbc..86ae567e 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1705,8 +1705,7 @@ static size_t calculate_auth_key_length(AUTH_ALG a) return 32; } -size_t calculate_auth_output_length(AUTH_ALG a); -size_t calculate_auth_output_length(AUTH_ALG a) +static size_t calculate_auth_output_length(AUTH_ALG a) { switch(a) { case AUTH_ALG_HMAC_SHA_1: @@ -1980,9 +1979,68 @@ static int encode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) { - if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<=128)) { + if(server_name && etoken && key && dtoken) { - //TODO + size_t mac_size = calculate_auth_output_length(key->auth_alg); + size_t min_encoded_field_size = 2+4+8+calculate_auth_output_length(AUTH_ALG_HMAC_SHA_256_128); + if(etoken->size < mac_size+min_encoded_field_size) { + return -1; + } + + unsigned char* encoded_field = (unsigned char*)etoken->token; + unsigned int encoded_field_size = (unsigned int)etoken->size-mac_size; + unsigned char* mac = ((unsigned char*)etoken->token) + etoken->size - mac_size; + + { + const EVP_MD *md = get_auth_type(key->auth_alg); + if(!md) + return -1; + unsigned int hmac_len = EVP_MD_size(md); + if(hmac_len != mac_size) + return -1; + unsigned char check_mac[MAXSHASIZE]; + if (!HMAC(md, key->auth_key, key->auth_key_size, encoded_field, encoded_field_size, check_mac, &hmac_len)) { + return -1; + } + + if(ns_bcmp(check_mac,mac,mac_size)) + return -1; + } + + ns_bcopy(mac,dtoken->mac,mac_size); + dtoken->mac_size = mac_size; + + unsigned char decoded_field[MAX_ENCODED_OAUTH_TOKEN_SIZE]; + + const EVP_CIPHER * cipher = get_cipher_type(key->as_rs_alg); + if(!cipher) + return -1; + + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + EVP_DecryptInit_ex(&ctx, cipher, NULL, (unsigned char *)key->as_rs_key, NULL); + int outl=0; + EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size); + EVP_DecryptFinal_ex(&ctx, decoded_field + outl, &outl); + + if(outl<(int)min_encoded_field_size) + return -1; + + size_t len = 0; + + dtoken->enc_block.key_length = nswap16(*((uint16_t*)(decoded_field+len))); + len += 2; + + ns_bcopy(decoded_field+len,dtoken->enc_block.mac_key,dtoken->enc_block.key_length); + len += dtoken->enc_block.key_length; + + dtoken->enc_block.timestamp = nswap64(*((uint64_t*)(decoded_field+len))); + len += 8; + + dtoken->enc_block.lifetime = nswap32(*((uint32_t*)(decoded_field+len))); + len += 4; + + return 0; } return -1; } @@ -2037,7 +2095,7 @@ static int encode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et if(1 != EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, OAUTH_AEAD_NONCE_SIZE, NULL)) return -1; - /* Initialise key and IV */ + /* Initialize key and IV */ if(1 != EVP_EncryptInit_ex(&ctx, NULL, NULL, (unsigned char *)key->as_rs_key, nonce)) return -1; diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 64dafaeb..42a5b3a4 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -76,6 +76,7 @@ extern "C" { #define ns_bcopy(src,dst,sz) bcopy((src),(dst),(sz)) #define ns_bzero(ptr,sz) bzero((ptr),(sz)) +#define ns_bcmp(ptr1,ptr2,sz) bcmp((ptr1),(ptr2),(sz)) #define nswap16(s) ntohs(s) #define nswap32(ul) ntohl(ul) From 901c80d4af8bae40cee84363379bd1ac3aa31454 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 16 Sep 2014 00:15:29 +0000 Subject: [PATCH 177/805] mac os x compilation fixed --- configure | 50 ++++++++++++++++- src/client/ns_turn_msg.c | 90 +++++++++++++++++++++++++++---- src/client/ns_turn_msg_defs_new.h | 6 +-- 3 files changed, 129 insertions(+), 17 deletions(-) diff --git a/configure b/configure index a36a504b..43b9275d 100755 --- a/configure +++ b/configure @@ -9,6 +9,8 @@ cleanup() { rm -rf ${TH_TMPCPROGB} rm -rf ${DTLS_TMPCPROGC} rm -rf ${DTLS_TMPCPROGB} + rm -rf ${GCM_TMPCPROGC} + rm -rf ${GCM_TMPCPROGB} rm -rf ${PQ_TMPCPROGC} rm -rf ${PQ_TMPCPROGB} rm -rf ${MYSQL_TMPCPROGC} @@ -237,6 +239,21 @@ dtls_testlib() { fi } +gcm_testlib() { + + if [ -z "${TURN_NO_GCM}" ] ; then + ${CC} ${GCM_TMPCPROGC} -o ${GCM_TMPCPROGB} ${OSCFLAGS} ${OSLIBS} 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + return 1 + else + return 0 + fi + else + return 0 + fi +} + testdaemon() { ${CC} ${D_TMPCPROGC} -o ${D_TMPCPROGB} ${OSCFLAGS} ${OSLIBS} 2>>/dev/null @@ -628,6 +645,19 @@ int main(int argc, char** argv) { } ! +GCM_TMPCPROG=__test__ccomp__gcm__$$ +GCM_TMPCPROGC=${TMPDIR}/${GCM_TMPCPROG}.c +GCM_TMPCPROGB=${TMPDIR}/${GCM_TMPCPROG} + +cat > ${GCM_TMPCPROGC} < +#include +#include +int main(int argc, char** argv) { + return (int)EVP_CIPH_GCM_MODE; +} +! + D_TMPCPROG=__test__ccomp__daemon__$$ D_TMPCPROGC=${TMPDIR}/${D_TMPCPROG}.c D_TMPCPROGB=${TMPDIR}/${D_TMPCPROG} @@ -885,6 +915,24 @@ else TURN_NO_DTLS="-DTURN_NO_DTLS" fi +########################### +# Can we use GCM cipher ? +########################### + +if [ -z ${TURN_NO_GCM} ] ; then + +gcm_testlib +ER=$? +if [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "WARNING: Cannot find GCM support." + ${ECHO_CMD} "Turning GCM off." + TURN_NO_GCM="-DTURN_NO_GCM" +fi + +else + TURN_NO_GCM="-DTURN_NO_GCM" +fi + ########################### # Test Libevent2 setup ########################### @@ -1044,7 +1092,7 @@ fi # So, what we have now: ############################### -OSCFLAGS="${OSCFLAGS} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX}" +OSCFLAGS="${OSCFLAGS} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX}" if ! [ -z "${TURN_ACCEPT_RPATH}" ] ; then if [ -z "${TURN_DISABLE_RPATH}" ] ; then diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 86ae567e..df15ea3f 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -39,6 +39,8 @@ #include #include +/////////// + #include /////////// @@ -1678,7 +1680,7 @@ static size_t calculate_enc_key_length(ENC_ALG a) { switch(a) { case AES_128_CBC: -#if !defined(TURN_NO_GCM_SUPPORT) +#if !defined(TURN_NO_GCM) case AEAD_AES_128_GCM: #endif return 16; @@ -1838,7 +1840,7 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, key->as_rs_alg = AES_128_CBC; } else if(!strcmp(oakd->as_rs_alg,"AES-256-CBC")) { key->as_rs_alg = AES_256_CBC; -#if !defined(TURN_NO_GCM_SUPPORT) +#if !defined(TURN_NO_GCM) } else if(!strcmp(oakd->as_rs_alg,"AEAD-AES-128-GCM")) { key->as_rs_alg = AEAD_AES_128_GCM; } else if(!strcmp(oakd->as_rs_alg,"AEAD-AES-256-GCM")) { @@ -1880,7 +1882,7 @@ static const EVP_CIPHER *get_cipher_type(ENC_ALG enc_alg) return EVP_aes_256_cbc(); case AES_128_CBC: return EVP_aes_128_cbc(); -#if !defined(TURN_NO_GCM_SUPPORT) +#if !defined(TURN_NO_GCM) case AEAD_AES_128_GCM: return EVP_aes_128_gcm(); case AEAD_AES_256_GCM: @@ -1911,7 +1913,7 @@ static void update_hmac_len(AUTH_ALG aa, unsigned int *hmac_len) if(hmac_len) { switch(aa) { case AUTH_ALG_HMAC_SHA_256_128: - *hmac_len = *hmac_len >> 1; + *hmac_len = 16; break; default: ; @@ -1982,7 +1984,7 @@ static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * if(server_name && etoken && key && dtoken) { size_t mac_size = calculate_auth_output_length(key->auth_alg); - size_t min_encoded_field_size = 2+4+8+calculate_auth_output_length(AUTH_ALG_HMAC_SHA_256_128); + size_t min_encoded_field_size = 2+4+8+calculate_auth_output_length(AUTH_ALG_HMAC_SHA_1); if(etoken->size < mac_size+min_encoded_field_size) { return -1; } @@ -2045,7 +2047,7 @@ static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * return -1; } -#if !defined(TURN_NO_GCM_SUPPORT) +#if !defined(TURN_NO_GCM) static void generate_random_nonce(unsigned char *nonce, size_t sz) { if(!RAND_bytes(nonce, sz)) { @@ -2087,7 +2089,7 @@ static int encode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); - /* Initialise the encryption operation. */ + /* Initialize the encryption operation. */ if(1 != EVP_EncryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) return -1; @@ -2129,9 +2131,75 @@ static int encode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) { - if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<128)) { + if(server_name && etoken && key && dtoken) { - //TODO + size_t min_encoded_field_size = 2+4+8+OAUTH_AEAD_NONCE_SIZE+OAUTH_AEAD_TAG_SIZE+calculate_auth_output_length(AUTH_ALG_HMAC_SHA_1); + if(etoken->size < min_encoded_field_size) { + return -1; + } + + unsigned char* encoded_field = (unsigned char*)etoken->token; + unsigned int encoded_field_size = (unsigned int)etoken->size-OAUTH_AEAD_NONCE_SIZE; + unsigned char* nonce = ((unsigned char*)etoken->token) + encoded_field_size; + unsigned char* tag = ((unsigned char*)etoken->token) + encoded_field_size - OAUTH_AEAD_TAG_SIZE; + + dtoken->mac_size = 0; + + unsigned char decoded_field[MAX_ENCODED_OAUTH_TOKEN_SIZE]; + + const EVP_CIPHER * cipher = get_cipher_type(key->as_rs_alg); + if(!cipher) + return -1; + + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + /* Initialize the encryption operation. */ + if(1 != EVP_EncryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) + return -1; + + /* Set IV length if default 12 bytes (96 bits) is not appropriate */ + if(1 != EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, OAUTH_AEAD_NONCE_SIZE, NULL)) + return -1; + + /* Initialize key and IV */ + if(1 != EVP_EncryptInit_ex(&ctx, NULL, NULL, (unsigned char *)key->as_rs_key, nonce)) + return -1; + + EVP_CIPHER_CTX_ctrl (&ctx, EVP_CTRL_GCM_SET_TAG, OAUTH_AEAD_TAG_SIZE, tag); + + int outl=0; + size_t sn_len = strlen((char*)server_name); + + /* Provide any AAD data. This can be called zero or more times as + * required + */ + if(1 != EVP_EncryptUpdate(&ctx, NULL, &outl, server_name, (int)sn_len)) + return -1; + EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size); + int tmp_outl = 0; + if(EVP_DecryptFinal_ex(&ctx, decoded_field + outl, &tmp_outl)<1) + return -1; + + outl += tmp_outl; + + if(outl<(int)min_encoded_field_size) + return -1; + + size_t len = 0; + + dtoken->enc_block.key_length = nswap16(*((uint16_t*)(decoded_field+len))); + len += 2; + + ns_bcopy(decoded_field+len,dtoken->enc_block.mac_key,dtoken->enc_block.key_length); + len += dtoken->enc_block.key_length; + + dtoken->enc_block.timestamp = nswap64(*((uint64_t*)(decoded_field+len))); + len += 8; + + dtoken->enc_block.lifetime = nswap32(*((uint32_t*)(decoded_field+len))); + len += 4; + + return 0; } return -1; } @@ -2145,7 +2213,7 @@ int encode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_ case AES_256_CBC: case AES_128_CBC: return encode_oauth_token_normal(server_name, etoken,key,dtoken); -#if !defined(TURN_NO_GCM_SUPPORT) +#if !defined(TURN_NO_GCM) case AEAD_AES_128_GCM: case AEAD_AES_256_GCM: return encode_oauth_token_aead(server_name, etoken,key,dtoken); @@ -2164,7 +2232,7 @@ int decode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_ case AES_256_CBC: case AES_128_CBC: return decode_oauth_token_normal(server_name, etoken,key,dtoken); -#if !defined(TURN_NO_GCM_SUPPORT) +#if !defined(TURN_NO_GCM) case AEAD_AES_128_GCM: case AEAD_AES_256_GCM: return decode_oauth_token_aead(server_name, etoken,key,dtoken); diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 3016e17c..f7718ff3 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -68,16 +68,12 @@ typedef enum _SHATYPE SHATYPE; /* OAUTH TOKEN ENC ALG ==> */ -#if !defined(EVP_CIPH_GCM_MODE) -#define TURN_NO_GCM_SUPPORT -#endif - enum _ENC_ALG { ENC_ALG_ERROR=-1, ENC_ALG_DEFAULT=0, AES_256_CBC=ENC_ALG_DEFAULT, AES_128_CBC, -#if !defined(TURN_NO_GCM_SUPPORT) +#if !defined(TURN_NO_GCM) AEAD_AES_128_GCM, AEAD_AES_256_GCM, #endif From 37a1ae3cfcd50ec78b6d1e802e5cd75dcf09f39e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 16 Sep 2014 01:13:30 +0000 Subject: [PATCH 178/805] mac os x compilation fixed --- src/client/ns_turn_msg.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index df15ea3f..f2e8c218 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1635,6 +1635,8 @@ int stun_attr_add_padding_str(u08bits *buf, size_t *len, u16bits padding_len) /* OAUTH */ +#define OAUTH_ERROR(...) fprintf(stderr,__VA_ARGS__) + static void remove_spaces(char *s) { char *sfns = s; @@ -1751,6 +1753,7 @@ static int calculate_key(char *key, size_t key_size, char *new_key, size_t new_k if(err_msg) { snprintf(err_msg,err_msg_size,"Wrong HKDF procedure (key sizes): output.sz=%lu, hmac(1)=%lu, hmac(2)=%lu",(unsigned long)new_key_size,(unsigned long)hmac_len,(unsigned long)hmac1_len); } + OAUTH_ERROR("Wrong HKDF procedure (key sizes): output.sz=%lu, hmac(1)=%lu, hmac(2)=%lu",(unsigned long)new_key_size,(unsigned long)hmac_len,(unsigned long)hmac1_len); return -1; } } @@ -1767,6 +1770,7 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, if(err_msg) { snprintf(err_msg,err_msg_size,"AS-RS key is not defined"); } + OAUTH_ERROR("AS-RS key is not defined"); return -1; } if(!(oakd->auth_key_size)) { @@ -1788,6 +1792,7 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, if(err_msg) { snprintf(err_msg,err_msg_size,"KID is not defined"); } + OAUTH_ERROR("KID is not defined"); return -1; } @@ -1817,6 +1822,7 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, if(err_msg) { snprintf(err_msg,err_msg_size,"Wrong HKDF hash function algorithm: %s",oakd->hkdf_hash_func); } + OAUTH_ERROR("Wrong HKDF hash function algorithm: %s",oakd->hkdf_hash_func); return -1; } @@ -1832,6 +1838,7 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, snprintf(err_msg,err_msg_size,"Wrong oAuth token hash algorithm: %s",oakd->auth_alg); } key->auth_alg = AUTH_ALG_ERROR; + OAUTH_ERROR("Wrong oAuth token hash algorithm: %s",oakd->auth_alg); return -1; } @@ -1850,6 +1857,7 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, if(err_msg) { snprintf(err_msg,err_msg_size,"Wrong oAuth token encryption algorithm: %s",oakd->as_rs_alg); } + OAUTH_ERROR("Wrong oAuth token encryption algorithm: %s",oakd->as_rs_alg); return -1; } @@ -1891,6 +1899,7 @@ static const EVP_CIPHER *get_cipher_type(ENC_ALG enc_alg) default: ; } + OAUTH_ERROR("%s: Unknown enc algorithm: %d\n",__FUNCTION__,(int)enc_alg); return NULL; } @@ -1905,6 +1914,7 @@ static const EVP_MD *get_auth_type(AUTH_ALG aa) default: ; }; + OAUTH_ERROR("%s: Unknown auth algorithm: %d\n",__FUNCTION__,(int)aa); return NULL; } @@ -1986,6 +1996,7 @@ static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * size_t mac_size = calculate_auth_output_length(key->auth_alg); size_t min_encoded_field_size = 2+4+8+calculate_auth_output_length(AUTH_ALG_HMAC_SHA_1); if(etoken->size < mac_size+min_encoded_field_size) { + OAUTH_ERROR("%s: token size too small: %d\n",__FUNCTION__,(int)etoken->size); return -1; } @@ -1998,15 +2009,19 @@ static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * if(!md) return -1; unsigned int hmac_len = EVP_MD_size(md); - if(hmac_len != mac_size) + if(hmac_len != mac_size) { + OAUTH_ERROR("%s: mac size is wrong: %d, must be %d\n",__FUNCTION__,(int)mac_size,(int)hmac_len); return -1; + } unsigned char check_mac[MAXSHASIZE]; if (!HMAC(md, key->auth_key, key->auth_key_size, encoded_field, encoded_field_size, check_mac, &hmac_len)) { return -1; } - if(ns_bcmp(check_mac,mac,mac_size)) + if(ns_bcmp(check_mac,mac,mac_size)) { + OAUTH_ERROR("%s: mac is wrong\n",__FUNCTION__); return -1; + } } ns_bcopy(mac,dtoken->mac,mac_size); @@ -2025,8 +2040,10 @@ static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size); EVP_DecryptFinal_ex(&ctx, decoded_field + outl, &outl); - if(outl<(int)min_encoded_field_size) + if(outl<(int)min_encoded_field_size) { + OAUTH_ERROR("%s: decrypted output has wrong size: %d\n",__FUNCTION__,(int)outl); return -1; + } size_t len = 0; @@ -2110,7 +2127,8 @@ static int encode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et if(1 != EVP_EncryptUpdate(&ctx, NULL, &outl, server_name, (int)sn_len)) return -1; - EVP_EncryptUpdate(&ctx, encoded_field, &outl, orig_field, (int)len); + if(1 != EVP_EncryptUpdate(&ctx, encoded_field, &outl, orig_field, (int)len)) + return -1; int tmp_outl = 0; EVP_EncryptFinal_ex(&ctx, encoded_field + outl, &tmp_outl); @@ -2135,6 +2153,7 @@ static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et size_t min_encoded_field_size = 2+4+8+OAUTH_AEAD_NONCE_SIZE+OAUTH_AEAD_TAG_SIZE+calculate_auth_output_length(AUTH_ALG_HMAC_SHA_1); if(etoken->size < min_encoded_field_size) { + OAUTH_ERROR("%s: token size too small: %d\n",__FUNCTION__,(int)etoken->size); return -1; } @@ -2153,8 +2172,8 @@ static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); - /* Initialize the encryption operation. */ - if(1 != EVP_EncryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) + /* Initialize the decryption operation. */ + if(1 != EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) return -1; /* Set IV length if default 12 bytes (96 bits) is not appropriate */ @@ -2162,7 +2181,7 @@ static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et return -1; /* Initialize key and IV */ - if(1 != EVP_EncryptInit_ex(&ctx, NULL, NULL, (unsigned char *)key->as_rs_key, nonce)) + if(1 != EVP_DecryptInit_ex(&ctx, NULL, NULL, (unsigned char *)key->as_rs_key, nonce)) return -1; EVP_CIPHER_CTX_ctrl (&ctx, EVP_CTRL_GCM_SET_TAG, OAUTH_AEAD_TAG_SIZE, tag); @@ -2173,9 +2192,10 @@ static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et /* Provide any AAD data. This can be called zero or more times as * required */ - if(1 != EVP_EncryptUpdate(&ctx, NULL, &outl, server_name, (int)sn_len)) + if(1 != EVP_DecryptUpdate(&ctx, NULL, &outl, server_name, (int)sn_len)) + return -1; + if(1 != EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size)) return -1; - EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size); int tmp_outl = 0; if(EVP_DecryptFinal_ex(&ctx, decoded_field + outl, &tmp_outl)<1) return -1; @@ -2241,7 +2261,7 @@ int decode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_ fprintf(stderr,"Wrong AS_RS algorithm: %d\n",(int)key->as_rs_alg); }; } - return 0; + return -1; } /////////////////////////////////////////////////////////////// From fb1ff83d6ae0d2aac07dffd69cb3f177f92c152e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 16 Sep 2014 01:15:44 +0000 Subject: [PATCH 179/805] mac os x compilation fixed --- src/apps/relay/mainrelay.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 0d811e4c..2496e340 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1582,6 +1582,12 @@ static void print_features(unsigned long mfn) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS supported\n"); #endif +#if defined(TURN_NO_GCM) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "AEAD is not supported\n"); +#else + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "AEAD supported\n"); +#endif + #if !defined(TURN_NO_HIREDIS) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis supported\n"); #else From 0e85945afa5bd0fe1edc809e97c089fe7c2de6d5 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 16 Sep 2014 06:20:15 +0000 Subject: [PATCH 180/805] cleaning --- src/apps/common/apputils.c | 49 +++++++++++++++++++++++++++++ src/apps/common/apputils.h | 21 +++++++++++++ src/apps/common/ns_turn_utils.c | 2 ++ src/apps/common/ns_turn_utils.h | 3 +- src/apps/relay/dbdrivers/dbdriver.c | 49 ----------------------------- src/apps/relay/dbdrivers/dbdriver.h | 20 ------------ src/client/ns_turn_msg.c | 15 ++++----- 7 files changed, 81 insertions(+), 78 deletions(-) diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c index 0ef52c05..32cad8b7 100644 --- a/src/apps/common/apputils.c +++ b/src/apps/common/apputils.c @@ -899,4 +899,53 @@ struct event_base *turn_event_base_new(void) return event_base_new_with_config(cfg); } +/////////// OAUTH ///////////////// + +void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *oakd) +{ + if(raw && oakd) { + + ns_bzero(oakd,sizeof(oauth_key_data)); + + oakd->timestamp = (turn_time_t)raw->timestamp; + oakd->lifetime = raw->lifetime; + + ns_bcopy(raw->as_rs_alg,oakd->as_rs_alg,sizeof(oakd->as_rs_alg)); + ns_bcopy(raw->auth_alg,oakd->auth_alg,sizeof(oakd->auth_alg)); + ns_bcopy(raw->hkdf_hash_func,oakd->hkdf_hash_func,sizeof(oakd->hkdf_hash_func)); + ns_bcopy(raw->kid,oakd->kid,sizeof(oakd->kid)); + + if(raw->ikm_key[0]) { + size_t ikm_key_size = 0; + char *ikm_key = (char*)base64_decode(raw->ikm_key,strlen(raw->ikm_key),&ikm_key_size); + if(ikm_key) { + ns_bcopy(ikm_key,oakd->ikm_key,ikm_key_size); + oakd->ikm_key_size = ikm_key_size; + turn_free(ikm_key,ikm_key_size); + } + } + + if(raw->as_rs_key[0]) { + size_t as_rs_key_size = 0; + char *as_rs_key = (char*)base64_decode(raw->as_rs_key,strlen(raw->as_rs_key),&as_rs_key_size); + if(as_rs_key) { + ns_bcopy(as_rs_key,oakd->as_rs_key,as_rs_key_size); + oakd->as_rs_key_size = as_rs_key_size; + turn_free(as_rs_key,as_rs_key_size); + } + } + + if(raw->auth_key[0]) { + size_t auth_key_size = 0; + char *auth_key = (char*)base64_decode(raw->auth_key,strlen(raw->auth_key),&auth_key_size); + if(auth_key) { + ns_bcopy(auth_key,oakd->auth_key,auth_key_size); + oakd->auth_key_size = auth_key_size; + turn_free(auth_key,auth_key_size); + } + } + + } +} + ////////////////////////////////////////////////////////////// diff --git a/src/apps/common/apputils.h b/src/apps/common/apputils.h index 21815c4c..0868d6e9 100644 --- a/src/apps/common/apputils.h +++ b/src/apps/common/apputils.h @@ -36,6 +36,7 @@ #include #include "ns_turn_ioaddr.h" +#include "ns_turn_msg_defs.h" #ifdef __cplusplus extern "C" { @@ -69,6 +70,22 @@ enum _TURN_TLS_TYPE { typedef enum _TURN_TLS_TYPE TURN_TLS_TYPE; +//////////////////////////////////////////// + +struct _oauth_key_data_raw { + char kid[OAUTH_KID_SIZE+1]; + char ikm_key[OAUTH_KEY_SIZE+1]; + u64bits timestamp; + u32bits lifetime; + char hkdf_hash_func[OAUTH_HASH_FUNC_SIZE+1]; + char as_rs_alg[OAUTH_ALG_SIZE+1]; + char as_rs_key[OAUTH_KEY_SIZE+1]; + char auth_alg[OAUTH_ALG_SIZE+1]; + char auth_key[OAUTH_KEY_SIZE+1]; +}; + +typedef struct _oauth_key_data_raw oauth_key_data_raw; + ////////////////////////////////////////// #define EVENT_DEL(ev) if(ev) { event_del(ev); event_free(ev); ev=NULL; } @@ -150,6 +167,10 @@ unsigned char *base64_decode(const char *data, const char* turn_get_ssl_method(SSL *ssl, const char* mdefault); +////////////// OAUTH UTILS //////////////// + +void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *oakd); + //////////// Event Base ///////////////////// struct event_base *turn_event_base_new(void); diff --git a/src/apps/common/ns_turn_utils.c b/src/apps/common/ns_turn_utils.c index 211d9f8f..aaba035d 100644 --- a/src/apps/common/ns_turn_utils.c +++ b/src/apps/common/ns_turn_utils.c @@ -32,6 +32,8 @@ #include "ns_turn_ioalib.h" #include "ns_turn_msg_defs.h" +#include + #include #include diff --git a/src/apps/common/ns_turn_utils.h b/src/apps/common/ns_turn_utils.h index 3b0a92e6..f57fea5c 100644 --- a/src/apps/common/ns_turn_utils.h +++ b/src/apps/common/ns_turn_utils.h @@ -36,8 +36,7 @@ #endif #include "ns_turn_ioaddr.h" - -#include +//#include #ifdef __cplusplus extern "C" { diff --git a/src/apps/relay/dbdrivers/dbdriver.c b/src/apps/relay/dbdrivers/dbdriver.c index e3b3b997..abf797fd 100644 --- a/src/apps/relay/dbdrivers/dbdriver.c +++ b/src/apps/relay/dbdrivers/dbdriver.c @@ -89,52 +89,3 @@ turn_dbdriver_t * get_dbdriver() { return _driver; } -/////////// OAUTH ///////////////// - -void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *oakd) -{ - if(raw && oakd) { - - ns_bzero(oakd,sizeof(oauth_key_data)); - - oakd->timestamp = (turn_time_t)raw->timestamp; - oakd->lifetime = raw->lifetime; - - ns_bcopy(raw->as_rs_alg,oakd->as_rs_alg,sizeof(oakd->as_rs_alg)); - ns_bcopy(raw->auth_alg,oakd->auth_alg,sizeof(oakd->auth_alg)); - ns_bcopy(raw->hkdf_hash_func,oakd->hkdf_hash_func,sizeof(oakd->hkdf_hash_func)); - ns_bcopy(raw->kid,oakd->kid,sizeof(oakd->kid)); - - if(raw->ikm_key[0]) { - size_t ikm_key_size = 0; - char *ikm_key = (char*)base64_decode(raw->ikm_key,strlen(raw->ikm_key),&ikm_key_size); - if(ikm_key) { - ns_bcopy(ikm_key,oakd->ikm_key,ikm_key_size); - oakd->ikm_key_size = ikm_key_size; - turn_free(ikm_key,ikm_key_size); - } - } - - if(raw->as_rs_key[0]) { - size_t as_rs_key_size = 0; - char *as_rs_key = (char*)base64_decode(raw->as_rs_key,strlen(raw->as_rs_key),&as_rs_key_size); - if(as_rs_key) { - ns_bcopy(as_rs_key,oakd->as_rs_key,as_rs_key_size); - oakd->as_rs_key_size = as_rs_key_size; - turn_free(as_rs_key,as_rs_key_size); - } - } - - if(raw->auth_key[0]) { - size_t auth_key_size = 0; - char *auth_key = (char*)base64_decode(raw->auth_key,strlen(raw->auth_key),&auth_key_size); - if(auth_key) { - ns_bcopy(auth_key,oakd->auth_key,auth_key_size); - oakd->auth_key_size = auth_key_size; - turn_free(auth_key,auth_key_size); - } - } - - } -} - diff --git a/src/apps/relay/dbdrivers/dbdriver.h b/src/apps/relay/dbdrivers/dbdriver.h index e68da531..29e8ef20 100644 --- a/src/apps/relay/dbdrivers/dbdriver.h +++ b/src/apps/relay/dbdrivers/dbdriver.h @@ -42,22 +42,6 @@ extern "C" { //////////////////////////////////////////// -struct _oauth_key_data_raw { - char kid[OAUTH_KID_SIZE+1]; - char ikm_key[OAUTH_KEY_SIZE+1]; - u64bits timestamp; - u32bits lifetime; - char hkdf_hash_func[OAUTH_HASH_FUNC_SIZE+1]; - char as_rs_alg[OAUTH_ALG_SIZE+1]; - char as_rs_key[OAUTH_KEY_SIZE+1]; - char auth_alg[OAUTH_ALG_SIZE+1]; - char auth_key[OAUTH_KEY_SIZE+1]; -}; - -typedef struct _oauth_key_data_raw oauth_key_data_raw; - -//////////////////////////////////////////// - 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); @@ -89,10 +73,6 @@ int convert_string_key_to_binary(char* keysource, hmackey_t key, size_t sz); persistent_users_db_t * get_persistent_users_db(void); turn_dbdriver_t * get_dbdriver(void); -////////////// OAUTH UTILS //////////////// - -void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *oakd); - //////////////////////////////////////////// #ifdef __cplusplus diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index f2e8c218..9b08250d 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -2019,7 +2019,7 @@ static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * } if(ns_bcmp(check_mac,mac,mac_size)) { - OAUTH_ERROR("%s: mac is wrong\n",__FUNCTION__); + OAUTH_ERROR("%s: token integrity check failed\n",__FUNCTION__); return -1; } } @@ -2158,9 +2158,9 @@ static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et } unsigned char* encoded_field = (unsigned char*)etoken->token; - unsigned int encoded_field_size = (unsigned int)etoken->size-OAUTH_AEAD_NONCE_SIZE; - unsigned char* nonce = ((unsigned char*)etoken->token) + encoded_field_size; - unsigned char* tag = ((unsigned char*)etoken->token) + encoded_field_size - OAUTH_AEAD_TAG_SIZE; + unsigned int encoded_field_size = (unsigned int)etoken->size-OAUTH_AEAD_NONCE_SIZE - OAUTH_AEAD_TAG_SIZE; + unsigned char* nonce = ((unsigned char*)etoken->token) + encoded_field_size + OAUTH_AEAD_TAG_SIZE; + unsigned char* tag = ((unsigned char*)etoken->token) + encoded_field_size; dtoken->mac_size = 0; @@ -2184,8 +2184,6 @@ static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et if(1 != EVP_DecryptInit_ex(&ctx, NULL, NULL, (unsigned char *)key->as_rs_key, nonce)) return -1; - EVP_CIPHER_CTX_ctrl (&ctx, EVP_CTRL_GCM_SET_TAG, OAUTH_AEAD_TAG_SIZE, tag); - int outl=0; size_t sn_len = strlen((char*)server_name); @@ -2197,8 +2195,11 @@ static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et if(1 != EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size)) return -1; int tmp_outl = 0; - if(EVP_DecryptFinal_ex(&ctx, decoded_field + outl, &tmp_outl)<1) + EVP_CIPHER_CTX_ctrl (&ctx, EVP_CTRL_GCM_SET_TAG, OAUTH_AEAD_TAG_SIZE, tag); + if(EVP_DecryptFinal_ex(&ctx, decoded_field + outl, &tmp_outl)<1) { + OAUTH_ERROR("%s: token integrity check failed\n",__FUNCTION__); return -1; + } outl += tmp_outl; From 449e39a7e1c2a6d019bb60286f4e96370466a2ae Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 16 Sep 2014 16:07:14 +0000 Subject: [PATCH 181/805] working on oauth --- src/apps/common/ns_turn_utils.h | 1 - src/apps/rfc5769/rfc5769check.c | 80 ++++++++++++++++++++++++++++++ src/client/ns_turn_msg.c | 88 +++++++++++++++++++++++++-------- 3 files changed, 147 insertions(+), 22 deletions(-) diff --git a/src/apps/common/ns_turn_utils.h b/src/apps/common/ns_turn_utils.h index f57fea5c..72da8e29 100644 --- a/src/apps/common/ns_turn_utils.h +++ b/src/apps/common/ns_turn_utils.h @@ -36,7 +36,6 @@ #endif #include "ns_turn_ioaddr.h" -//#include #ifdef __cplusplus extern "C" { diff --git a/src/apps/rfc5769/rfc5769check.c b/src/apps/rfc5769/rfc5769check.c index a8dc6cf0..224449b2 100644 --- a/src/apps/rfc5769/rfc5769check.c +++ b/src/apps/rfc5769/rfc5769check.c @@ -39,6 +39,81 @@ #include "apputils.h" #include "stun_buffer.h" +//////////// OAUTH ////////////////// + +static int check_oauth(void) +{ + oauth_key_data_raw okdr = { + "0123456789", + "01234567890123456789012345678901", + 123456789, + 3600, + "SHA1", + "AES-256-CBC", + "", + "HMAC-SHA-1", + "" + }; + + oauth_key_data okd; + + convert_oauth_key_data_raw(&okdr,&okd); + + char err_msg[1025]="\0"; + size_t err_msg_size = sizeof(err_msg)-1; + oauth_key key; + + if(convert_oauth_key_data(&okd, &key, err_msg, err_msg_size)<0) { + fprintf(stderr,"%s\n",err_msg); + return -1; + } + + oauth_token ot = { + { + 20, + "01234567890123456789", + 123456789, + 3600 + }, + "",0 + }; + + char server_name[33]="herod"; + encoded_oauth_token etoken; + + if(encode_oauth_token((u08bits *)server_name, &etoken, &key, &ot)<0) { + fprintf(stderr,"%s: cannot encode oauth token\n",__FUNCTION__); + return -1; + } + + oauth_token dot; + + if(decode_oauth_token((u08bits *)server_name, &etoken, &key, &dot)<0) { + fprintf(stderr,"%s: cannot decode oauth token\n",__FUNCTION__); + return -1; + } + + if(strcmp((char*)ot.enc_block.mac_key,(char*)dot.enc_block.mac_key)) { + fprintf(stderr,"%s: wrong mac key: %s, must be %s\n",__FUNCTION__,(char*)dot.enc_block.mac_key,(char*)ot.enc_block.mac_key); + return -1; + } + + if(ot.enc_block.key_length != dot.enc_block.key_length) { + fprintf(stderr,"%s: wrong key length: %d, must be %d\n",__FUNCTION__,(int)dot.enc_block.key_length,(int)ot.enc_block.key_length); + return -1; + } + if(ot.enc_block.timestamp != dot.enc_block.timestamp) { + fprintf(stderr,"%s: wrong timestamp: %llu, must be %llu\n",__FUNCTION__,(unsigned long long)dot.enc_block.timestamp,(unsigned long long)ot.enc_block.timestamp); + return -1; + } + if(ot.enc_block.lifetime != dot.enc_block.lifetime) { + fprintf(stderr,"%s: wrong lifetime: %lu, must be %lu\n",__FUNCTION__,(unsigned long)dot.enc_block.lifetime,(unsigned long)ot.enc_block.lifetime); + return -1; + } + + return 0; +} + ////////////////////////////////////////////////// static SHATYPE shatype = SHATYPE_SHA1; @@ -401,5 +476,10 @@ int main(int argc, const char **argv) } } + { + if(check_oauth()<0) + exit(-1); + } + return 0; } diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 9b08250d..8e674b42 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1931,11 +1931,54 @@ static void update_hmac_len(AUTH_ALG aa, unsigned int *hmac_len) } } +static int my_EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, const unsigned char *in, int inl) +{ + int cycle = 0; + int out_len = 0; + while((out_len>\n",name); + size_t i; + for(i = 0;i",(unsigned int)f[i]); + } + printf("\n<<==field %s\n",name); +} + static int encode_oauth_token_normal(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) { if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<=128)) { unsigned char orig_field[MAX_ENCODED_OAUTH_TOKEN_SIZE]; + ns_bzero(orig_field,sizeof(orig_field)); size_t len = 0; *((uint16_t*)(orig_field+len)) = nswap16(dtoken->enc_block.key_length); @@ -1960,8 +2003,10 @@ static int encode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * EVP_CIPHER_CTX_init(&ctx); EVP_EncryptInit_ex(&ctx, cipher, NULL, (unsigned char *)key->as_rs_key, NULL); int outl=0; - EVP_EncryptUpdate(&ctx, encoded_field, &outl, orig_field, (int)len); - EVP_EncryptFinal_ex(&ctx, encoded_field + outl, &outl); + my_EVP_EncryptUpdate(&ctx, encoded_field, &outl, orig_field, (int)len); + int tmp_outl = 0; + EVP_EncryptFinal_ex(&ctx, encoded_field + outl, &tmp_outl); + outl += tmp_outl; size_t sn_len = strlen((char*)server_name); ns_bcopy(server_name,encoded_field+outl,sn_len); @@ -1994,9 +2039,9 @@ static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * if(server_name && etoken && key && dtoken) { size_t mac_size = calculate_auth_output_length(key->auth_alg); - size_t min_encoded_field_size = 2+4+8+calculate_auth_output_length(AUTH_ALG_HMAC_SHA_1); + size_t min_encoded_field_size = 2+4+8+1; if(etoken->size < mac_size+min_encoded_field_size) { - OAUTH_ERROR("%s: token size too small: %d\n",__FUNCTION__,(int)etoken->size); + OAUTH_ERROR("%s: token size too small: %d, mac_size=%d, min_encoded_field_size=%d\n",__FUNCTION__,(int)etoken->size,(int)mac_size,(int)min_encoded_field_size); return -1; } @@ -2013,8 +2058,12 @@ static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * OAUTH_ERROR("%s: mac size is wrong: %d, must be %d\n",__FUNCTION__,(int)mac_size,(int)hmac_len); return -1; } + unsigned char efield[MAX_ENCODED_OAUTH_TOKEN_SIZE]; unsigned char check_mac[MAXSHASIZE]; - if (!HMAC(md, key->auth_key, key->auth_key_size, encoded_field, encoded_field_size, check_mac, &hmac_len)) { + ns_bcopy(encoded_field,efield,encoded_field_size); + size_t sn_len = strlen((char*)server_name); + ns_bcopy(server_name,efield+encoded_field_size,sn_len); + if (!HMAC(md, key->auth_key, key->auth_key_size, efield, encoded_field_size+sn_len, check_mac, &hmac_len)) { return -1; } @@ -2037,13 +2086,11 @@ static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * EVP_CIPHER_CTX_init(&ctx); EVP_DecryptInit_ex(&ctx, cipher, NULL, (unsigned char *)key->as_rs_key, NULL); int outl=0; - EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size); - EVP_DecryptFinal_ex(&ctx, decoded_field + outl, &outl); + my_EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size); - if(outl<(int)min_encoded_field_size) { - OAUTH_ERROR("%s: decrypted output has wrong size: %d\n",__FUNCTION__,(int)outl); - return -1; - } + int tmp_outl = 0; + EVP_DecryptFinal_ex(&ctx, decoded_field + outl, &tmp_outl); + outl += tmp_outl; size_t len = 0; @@ -2080,6 +2127,7 @@ static int encode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<128)) { unsigned char orig_field[MAX_ENCODED_OAUTH_TOKEN_SIZE]; + ns_bzero(orig_field,sizeof(orig_field)); size_t len = 0; *((uint16_t*)(orig_field+len)) = nswap16(dtoken->enc_block.key_length); @@ -2124,10 +2172,10 @@ static int encode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et /* Provide any AAD data. This can be called zero or more times as * required */ - if(1 != EVP_EncryptUpdate(&ctx, NULL, &outl, server_name, (int)sn_len)) + if(1 != my_EVP_EncryptUpdate(&ctx, NULL, &outl, server_name, (int)sn_len)) return -1; - if(1 != EVP_EncryptUpdate(&ctx, encoded_field, &outl, orig_field, (int)len)) + if(1 != my_EVP_EncryptUpdate(&ctx, encoded_field, &outl, orig_field, (int)len)) return -1; int tmp_outl = 0; @@ -2151,7 +2199,7 @@ static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et { if(server_name && etoken && key && dtoken) { - size_t min_encoded_field_size = 2+4+8+OAUTH_AEAD_NONCE_SIZE+OAUTH_AEAD_TAG_SIZE+calculate_auth_output_length(AUTH_ALG_HMAC_SHA_1); + size_t min_encoded_field_size = 2+4+8+OAUTH_AEAD_NONCE_SIZE+OAUTH_AEAD_TAG_SIZE+1; if(etoken->size < min_encoded_field_size) { OAUTH_ERROR("%s: token size too small: %d\n",__FUNCTION__,(int)etoken->size); return -1; @@ -2190,22 +2238,20 @@ static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et /* Provide any AAD data. This can be called zero or more times as * required */ - if(1 != EVP_DecryptUpdate(&ctx, NULL, &outl, server_name, (int)sn_len)) + if(1 != my_EVP_DecryptUpdate(&ctx, NULL, &outl, server_name, (int)sn_len)) return -1; - if(1 != EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size)) + if(1 != my_EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size)) return -1; - int tmp_outl = 0; + EVP_CIPHER_CTX_ctrl (&ctx, EVP_CTRL_GCM_SET_TAG, OAUTH_AEAD_TAG_SIZE, tag); + + int tmp_outl = 0; if(EVP_DecryptFinal_ex(&ctx, decoded_field + outl, &tmp_outl)<1) { OAUTH_ERROR("%s: token integrity check failed\n",__FUNCTION__); return -1; } - outl += tmp_outl; - if(outl<(int)min_encoded_field_size) - return -1; - size_t len = 0; dtoken->enc_block.key_length = nswap16(*((uint16_t*)(decoded_field+len))); From a620b61e04235c25501aea707e98957dd176d397 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 16 Sep 2014 22:04:39 +0000 Subject: [PATCH 182/805] oauth --- src/apps/rfc5769/rfc5769check.c | 145 ++++++++++++++++++------------ src/client/ns_turn_msg.c | 27 +++--- src/client/ns_turn_msg_defs_new.h | 2 - 3 files changed, 104 insertions(+), 70 deletions(-) diff --git a/src/apps/rfc5769/rfc5769check.c b/src/apps/rfc5769/rfc5769check.c index 224449b2..4c7b2fb6 100644 --- a/src/apps/rfc5769/rfc5769check.c +++ b/src/apps/rfc5769/rfc5769check.c @@ -41,74 +41,105 @@ //////////// OAUTH ////////////////// -static int check_oauth(void) -{ - oauth_key_data_raw okdr = { - "0123456789", - "01234567890123456789012345678901", - 123456789, - 3600, - "SHA1", - "AES-256-CBC", - "", - "HMAC-SHA-1", - "" - }; +static const char* shas[]={"SHA1","SHA256",NULL}; +static const char* encs[]={"AES-256-CBC","AES-128-CBC", +#if !defined(TURN_NO_GCM) + "AEAD_AES_128_GCM", "AEAD_AES_256_GCM", +#endif + NULL}; +static const char* hmacs[]={"HMAC-SHA-1","HMAC-SHA-256","HMAC-SHA-256-128",NULL}; - oauth_key_data okd; +static int check_oauth(void) { - convert_oauth_key_data_raw(&okdr,&okd); + const char server_name[33] = "herod"; - char err_msg[1025]="\0"; - size_t err_msg_size = sizeof(err_msg)-1; - oauth_key key; + for (size_t i_hmacs = 0; hmacs[i_hmacs]; ++i_hmacs) { - if(convert_oauth_key_data(&okd, &key, err_msg, err_msg_size)<0) { - fprintf(stderr,"%s\n",err_msg); - return -1; - } + for (size_t i_shas = 0; shas[i_shas]; ++i_shas) { - oauth_token ot = { - { - 20, - "01234567890123456789", - 123456789, - 3600 - }, - "",0 - }; + for (size_t i_encs = 0; encs[i_encs]; ++i_encs) { - char server_name[33]="herod"; - encoded_oauth_token etoken; + printf("oauth token %s:%s:%s:",hmacs[i_hmacs],shas[i_shas],encs[i_encs]); - if(encode_oauth_token((u08bits *)server_name, &etoken, &key, &ot)<0) { - fprintf(stderr,"%s: cannot encode oauth token\n",__FUNCTION__); - return -1; - } + oauth_token ot = { { 20, "01234567890123456789", 123456789, 3600 } }; + oauth_token dot; + oauth_key key; - oauth_token dot; + { + oauth_key_data okd; - if(decode_oauth_token((u08bits *)server_name, &etoken, &key, &dot)<0) { - fprintf(stderr,"%s: cannot decode oauth token\n",__FUNCTION__); - return -1; - } + { + oauth_key_data_raw okdr = { "0123456789", + "01234567890123456789012345678901", 123456789, + 3600, "", "", "", "", "" }; - if(strcmp((char*)ot.enc_block.mac_key,(char*)dot.enc_block.mac_key)) { - fprintf(stderr,"%s: wrong mac key: %s, must be %s\n",__FUNCTION__,(char*)dot.enc_block.mac_key,(char*)ot.enc_block.mac_key); - return -1; - } + STRCPY(okdr.as_rs_alg, encs[i_encs]); + STRCPY(okdr.auth_alg, hmacs[i_hmacs]); + STRCPY(okdr.hkdf_hash_func, shas[i_shas]); - if(ot.enc_block.key_length != dot.enc_block.key_length) { - fprintf(stderr,"%s: wrong key length: %d, must be %d\n",__FUNCTION__,(int)dot.enc_block.key_length,(int)ot.enc_block.key_length); - return -1; - } - if(ot.enc_block.timestamp != dot.enc_block.timestamp) { - fprintf(stderr,"%s: wrong timestamp: %llu, must be %llu\n",__FUNCTION__,(unsigned long long)dot.enc_block.timestamp,(unsigned long long)ot.enc_block.timestamp); - return -1; - } - if(ot.enc_block.lifetime != dot.enc_block.lifetime) { - fprintf(stderr,"%s: wrong lifetime: %lu, must be %lu\n",__FUNCTION__,(unsigned long)dot.enc_block.lifetime,(unsigned long)ot.enc_block.lifetime); - return -1; + convert_oauth_key_data_raw(&okdr, &okd); + + char err_msg[1025] = "\0"; + size_t err_msg_size = sizeof(err_msg) - 1; + + if (convert_oauth_key_data(&okd, &key, err_msg, + err_msg_size) < 0) { + fprintf(stderr, "%s\n", err_msg); + return -1; + } + } + } + + { + encoded_oauth_token etoken; + + if (encode_oauth_token((u08bits *) server_name, &etoken, + &key, &ot) < 0) { + fprintf(stderr, "%s: cannot encode oauth token\n", + __FUNCTION__); + return -1; + } + + if (decode_oauth_token((u08bits *) server_name, &etoken, + &key, &dot) < 0) { + fprintf(stderr, "%s: cannot decode oauth token\n", + __FUNCTION__); + return -1; + } + } + + if (strcmp((char*) ot.enc_block.mac_key, + (char*) dot.enc_block.mac_key)) { + fprintf(stderr, "%s: wrong mac key: %s, must be %s\n", + __FUNCTION__, (char*) dot.enc_block.mac_key, + (char*) ot.enc_block.mac_key); + return -1; + } + + if (ot.enc_block.key_length != dot.enc_block.key_length) { + fprintf(stderr, "%s: wrong key length: %d, must be %d\n", + __FUNCTION__, (int) dot.enc_block.key_length, + (int) ot.enc_block.key_length); + return -1; + } + if (ot.enc_block.timestamp != dot.enc_block.timestamp) { + fprintf(stderr, "%s: wrong timestamp: %llu, must be %llu\n", + __FUNCTION__, + (unsigned long long) dot.enc_block.timestamp, + (unsigned long long) ot.enc_block.timestamp); + return -1; + } + if (ot.enc_block.lifetime != dot.enc_block.lifetime) { + fprintf(stderr, "%s: wrong lifetime: %lu, must be %lu\n", + __FUNCTION__, + (unsigned long) dot.enc_block.lifetime, + (unsigned long) ot.enc_block.lifetime); + return -1; + } + + printf("OK\n"); + } + } } return 0; diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 8e674b42..82e64a60 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1669,9 +1669,9 @@ static void normalize_algorithm(char *s) { char c = *s; while(c) { - if(c=='_') c='-'; + if(c=='_') *s='-'; else if((c>='a')&&(c<='z')) { - c = c - 'a' + 'A'; + *s = c - 'a' + 'A'; } ++s; c = *s; @@ -1835,10 +1835,10 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, key->auth_alg = AUTH_ALG_HMAC_SHA_256_128; } else if(oakd->auth_alg[0]) { if(err_msg) { - snprintf(err_msg,err_msg_size,"Wrong oAuth token hash algorithm: %s",oakd->auth_alg); + snprintf(err_msg,err_msg_size,"Wrong oAuth token hash algorithm: %s (1)\n",oakd->auth_alg); } key->auth_alg = AUTH_ALG_ERROR; - OAUTH_ERROR("Wrong oAuth token hash algorithm: %s",oakd->auth_alg); + OAUTH_ERROR("Wrong oAuth token hash algorithm: %s (2)\n",oakd->auth_alg); return -1; } @@ -1855,9 +1855,9 @@ int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, #endif } else if(oakd->as_rs_alg[0]) { if(err_msg) { - snprintf(err_msg,err_msg_size,"Wrong oAuth token encryption algorithm: %s",oakd->as_rs_alg); + snprintf(err_msg,err_msg_size,"Wrong oAuth token encryption algorithm: %s (2)\n",oakd->as_rs_alg); } - OAUTH_ERROR("Wrong oAuth token encryption algorithm: %s",oakd->as_rs_alg); + OAUTH_ERROR("Wrong oAuth token encryption algorithm: %s (3)\n",oakd->as_rs_alg); return -1; } @@ -2008,6 +2008,8 @@ static int encode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * EVP_EncryptFinal_ex(&ctx, encoded_field + outl, &tmp_outl); outl += tmp_outl; + EVP_CIPHER_CTX_cleanup(&ctx); + size_t sn_len = strlen((char*)server_name); ns_bcopy(server_name,encoded_field+outl,sn_len); outl += sn_len; @@ -2054,6 +2056,7 @@ static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * if(!md) return -1; unsigned int hmac_len = EVP_MD_size(md); + update_hmac_len(key->auth_alg,&hmac_len); if(hmac_len != mac_size) { OAUTH_ERROR("%s: mac size is wrong: %d, must be %d\n",__FUNCTION__,(int)mac_size,(int)hmac_len); return -1; @@ -2073,9 +2076,6 @@ static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * } } - ns_bcopy(mac,dtoken->mac,mac_size); - dtoken->mac_size = mac_size; - unsigned char decoded_field[MAX_ENCODED_OAUTH_TOKEN_SIZE]; const EVP_CIPHER * cipher = get_cipher_type(key->as_rs_alg); @@ -2092,6 +2092,8 @@ static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * EVP_DecryptFinal_ex(&ctx, decoded_field + outl, &tmp_outl); outl += tmp_outl; + EVP_CIPHER_CTX_cleanup(&ctx); + size_t len = 0; dtoken->enc_block.key_length = nswap16(*((uint16_t*)(decoded_field+len))); @@ -2190,6 +2192,8 @@ static int encode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et etoken->size = outl; + EVP_CIPHER_CTX_cleanup(&ctx); + return 0; } return -1; @@ -2210,8 +2214,6 @@ static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et unsigned char* nonce = ((unsigned char*)etoken->token) + encoded_field_size + OAUTH_AEAD_TAG_SIZE; unsigned char* tag = ((unsigned char*)etoken->token) + encoded_field_size; - dtoken->mac_size = 0; - unsigned char decoded_field[MAX_ENCODED_OAUTH_TOKEN_SIZE]; const EVP_CIPHER * cipher = get_cipher_type(key->as_rs_alg); @@ -2247,11 +2249,14 @@ static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et int tmp_outl = 0; if(EVP_DecryptFinal_ex(&ctx, decoded_field + outl, &tmp_outl)<1) { + EVP_CIPHER_CTX_cleanup(&ctx); OAUTH_ERROR("%s: token integrity check failed\n",__FUNCTION__); return -1; } outl += tmp_outl; + EVP_CIPHER_CTX_cleanup(&ctx); + size_t len = 0; dtoken->enc_block.key_length = nswap16(*((uint16_t*)(decoded_field+len))); diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index f7718ff3..965e7979 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -158,8 +158,6 @@ typedef struct _oauth_encrypted_block oauth_encrypted_block; struct _oauth_token { oauth_encrypted_block enc_block; - uint8_t mac[MAXSHASIZE]; - size_t mac_size; }; typedef struct _oauth_token oauth_token; From a297664c1e5c5f9471767f08e6e9592cff8be197 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 17 Sep 2014 05:48:29 +0000 Subject: [PATCH 183/805] compilation fixed --- src/apps/rfc5769/rfc5769check.c | 14 ++++++---- src/client/ns_turn_msg.c | 49 +++++++++++++++++++-------------- src/client/ns_turn_msg.h | 6 ++-- 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/src/apps/rfc5769/rfc5769check.c b/src/apps/rfc5769/rfc5769check.c index 4c7b2fb6..55a48cc7 100644 --- a/src/apps/rfc5769/rfc5769check.c +++ b/src/apps/rfc5769/rfc5769check.c @@ -51,13 +51,15 @@ static const char* hmacs[]={"HMAC-SHA-1","HMAC-SHA-256","HMAC-SHA-256-128",NULL} static int check_oauth(void) { - const char server_name[33] = "herod"; + const char server_name[33] = "blackdow.carleon.gov"; - for (size_t i_hmacs = 0; hmacs[i_hmacs]; ++i_hmacs) { + size_t i_hmacs,i_shas,i_encs; - for (size_t i_shas = 0; shas[i_shas]; ++i_shas) { + for (i_hmacs = 0; hmacs[i_hmacs]; ++i_hmacs) { - for (size_t i_encs = 0; encs[i_encs]; ++i_encs) { + for (i_shas = 0; shas[i_shas]; ++i_shas) { + + for (i_encs = 0; encs[i_encs]; ++i_encs) { printf("oauth token %s:%s:%s:",hmacs[i_hmacs],shas[i_shas],encs[i_encs]); @@ -93,14 +95,14 @@ static int check_oauth(void) { { encoded_oauth_token etoken; - if (encode_oauth_token((u08bits *) server_name, &etoken, + if (encode_oauth_token((const u08bits *) server_name, &etoken, &key, &ot) < 0) { fprintf(stderr, "%s: cannot encode oauth token\n", __FUNCTION__); return -1; } - if (decode_oauth_token((u08bits *) server_name, &etoken, + if (decode_oauth_token((const u08bits *) server_name, &etoken, &key, &dot) < 0) { fprintf(stderr, "%s: cannot decode oauth token\n", __FUNCTION__); diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 82e64a60..4afccee0 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1761,9 +1761,13 @@ static int calculate_key(char *key, size_t key_size, char *new_key, size_t new_k return 0; } -int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, size_t err_msg_size) +int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *err_msg, size_t err_msg_size) { - if(oakd && key) { + if(oakd0 && key) { + + oauth_key_data oakd_obj; + ns_bcopy(oakd0,&oakd_obj,sizeof(oauth_key_data)); + oauth_key_data *oakd = &oakd_obj; if(!(oakd->ikm_key_size)) { if(!(oakd->as_rs_key_size)) { @@ -1973,7 +1977,7 @@ void print_field(const char* name, const unsigned char* f, size_t len) { printf("\n<<==field %s\n",name); } -static int encode_oauth_token_normal(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +static int encode_oauth_token_normal(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken) { if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<=128)) { @@ -2001,7 +2005,7 @@ static int encode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); - EVP_EncryptInit_ex(&ctx, cipher, NULL, (unsigned char *)key->as_rs_key, NULL); + EVP_EncryptInit_ex(&ctx, cipher, NULL, (const unsigned char *)key->as_rs_key, NULL); int outl=0; my_EVP_EncryptUpdate(&ctx, encoded_field, &outl, orig_field, (int)len); int tmp_outl = 0; @@ -2010,7 +2014,7 @@ static int encode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * EVP_CIPHER_CTX_cleanup(&ctx); - size_t sn_len = strlen((char*)server_name); + size_t sn_len = strlen((const char*)server_name); ns_bcopy(server_name,encoded_field+outl,sn_len); outl += sn_len; @@ -2036,7 +2040,7 @@ static int encode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * return -1; } -static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +static int decode_oauth_token_normal(const u08bits *server_name, const encoded_oauth_token *etoken, const oauth_key *key, oauth_token *dtoken) { if(server_name && etoken && key && dtoken) { @@ -2047,9 +2051,9 @@ static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * return -1; } - unsigned char* encoded_field = (unsigned char*)etoken->token; + const unsigned char* encoded_field = (const unsigned char*)etoken->token; unsigned int encoded_field_size = (unsigned int)etoken->size-mac_size; - unsigned char* mac = ((unsigned char*)etoken->token) + etoken->size - mac_size; + const unsigned char* mac = ((const unsigned char*)etoken->token) + etoken->size - mac_size; { const EVP_MD *md = get_auth_type(key->auth_alg); @@ -2064,7 +2068,7 @@ static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * unsigned char efield[MAX_ENCODED_OAUTH_TOKEN_SIZE]; unsigned char check_mac[MAXSHASIZE]; ns_bcopy(encoded_field,efield,encoded_field_size); - size_t sn_len = strlen((char*)server_name); + size_t sn_len = strlen((const char*)server_name); ns_bcopy(server_name,efield+encoded_field_size,sn_len); if (!HMAC(md, key->auth_key, key->auth_key_size, efield, encoded_field_size+sn_len, check_mac, &hmac_len)) { return -1; @@ -2084,7 +2088,7 @@ static int decode_oauth_token_normal(u08bits *server_name, encoded_oauth_token * EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); - EVP_DecryptInit_ex(&ctx, cipher, NULL, (unsigned char *)key->as_rs_key, NULL); + EVP_DecryptInit_ex(&ctx, cipher, NULL, (const unsigned char *)key->as_rs_key, NULL); int outl=0; my_EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size); @@ -2124,7 +2128,7 @@ static void generate_random_nonce(unsigned char *nonce, size_t sz) { } } -static int encode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +static int encode_oauth_token_aead(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken) { if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<128)) { @@ -2165,11 +2169,11 @@ static int encode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et return -1; /* Initialize key and IV */ - if(1 != EVP_EncryptInit_ex(&ctx, NULL, NULL, (unsigned char *)key->as_rs_key, nonce)) + if(1 != EVP_EncryptInit_ex(&ctx, NULL, NULL, (const unsigned char *)key->as_rs_key, nonce)) return -1; int outl=0; - size_t sn_len = strlen((char*)server_name); + size_t sn_len = strlen((const char*)server_name); /* Provide any AAD data. This can be called zero or more times as * required @@ -2199,7 +2203,7 @@ static int encode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et return -1; } -static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +static int decode_oauth_token_aead(const u08bits *server_name, const encoded_oauth_token *etoken, const oauth_key *key, oauth_token *dtoken) { if(server_name && etoken && key && dtoken) { @@ -2209,10 +2213,12 @@ static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et return -1; } - unsigned char* encoded_field = (unsigned char*)etoken->token; + const unsigned char* encoded_field = (const unsigned char*)etoken->token; unsigned int encoded_field_size = (unsigned int)etoken->size-OAUTH_AEAD_NONCE_SIZE - OAUTH_AEAD_TAG_SIZE; - unsigned char* nonce = ((unsigned char*)etoken->token) + encoded_field_size + OAUTH_AEAD_TAG_SIZE; - unsigned char* tag = ((unsigned char*)etoken->token) + encoded_field_size; + const unsigned char* nonce = ((const unsigned char*)etoken->token) + encoded_field_size + OAUTH_AEAD_TAG_SIZE; + + unsigned char tag[OAUTH_AEAD_TAG_SIZE]; + ns_bcopy(((const unsigned char*)etoken->token) + encoded_field_size, tag ,sizeof(tag)); unsigned char decoded_field[MAX_ENCODED_OAUTH_TOKEN_SIZE]; @@ -2231,11 +2237,11 @@ static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et return -1; /* Initialize key and IV */ - if(1 != EVP_DecryptInit_ex(&ctx, NULL, NULL, (unsigned char *)key->as_rs_key, nonce)) + if(1 != EVP_DecryptInit_ex(&ctx, NULL, NULL, (const unsigned char *)key->as_rs_key, nonce)) return -1; int outl=0; - size_t sn_len = strlen((char*)server_name); + size_t sn_len = strlen((const char*)server_name); /* Provide any AAD data. This can be called zero or more times as * required @@ -2245,6 +2251,7 @@ static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et if(1 != my_EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size)) return -1; + EVP_CIPHER_CTX_ctrl (&ctx, EVP_CTRL_GCM_SET_TAG, OAUTH_AEAD_TAG_SIZE, tag); int tmp_outl = 0; @@ -2278,7 +2285,7 @@ static int decode_oauth_token_aead(u08bits *server_name, encoded_oauth_token *et #endif -int encode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +int encode_oauth_token(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken) { if(server_name && etoken && key && dtoken) { switch(key->as_rs_alg) { @@ -2297,7 +2304,7 @@ int encode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_ return -1; } -int decode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken) +int decode_oauth_token(const u08bits *server_name, const encoded_oauth_token *etoken, const oauth_key *key, oauth_token *dtoken) { if(server_name && etoken && key && dtoken) { switch(key->as_rs_alg) { diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 87c6d27d..239eb67d 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -210,9 +210,9 @@ int stun_attr_add_padding_str(u08bits *buf, size_t *len, u16bits padding_len); int is_http_get(const char *s, size_t blen); /* OAUTH */ -int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, size_t err_msg_size); -int decode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken); -int encode_oauth_token(u08bits *server_name, encoded_oauth_token *etoken, oauth_key *key, oauth_token *dtoken); +int convert_oauth_key_data(const oauth_key_data *oakd, oauth_key *key, char *err_msg, size_t err_msg_size); +int decode_oauth_token(const u08bits *server_name, const encoded_oauth_token *etoken, const oauth_key *key, oauth_token *dtoken); +int encode_oauth_token(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken); /////////////////////////////////////////////////////////////// From 7b444a1441069589bec726a2ed218deed87c0bfa Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 17 Sep 2014 06:50:35 +0000 Subject: [PATCH 184/805] server-name parameter. --- README.turnserver | 4 ++++ examples/etc/turnserver.conf | 8 ++++++- .../secure_relay_with_db_mongo.sh | 2 +- .../secure_relay_with_db_mysql.sh | 2 +- .../secure_relay_with_db_mysql_ssl.sh | 2 +- .../secure_relay_with_db_psql.sh | 4 ++-- .../secure_relay_with_db_redis.sh | 2 +- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 8 ++++++- man/man1/turnutils.1 | 2 +- src/apps/relay/mainrelay.c | 24 +++++++++++++++++-- 11 files changed, 48 insertions(+), 12 deletions(-) diff --git a/README.turnserver b/README.turnserver index 7bd560be..aba2478b 100644 --- a/README.turnserver +++ b/README.turnserver @@ -420,6 +420,10 @@ Options with required values: value can be changed on-the-fly by a separate program, so this is why that other mode is dynamic. Multiple shared secrets can be used (both in the database and in the "static" fashion). + +--server-name Server name used (when necessary) for + the authentication purposes (oauth). + The default value is the FQDN of the host. --cert Certificate file, PEM format. Same file search rules applied as for the configuration diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index b35391f8..5d7c8ec1 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -208,7 +208,13 @@ # in user database (if present). The database-stored value can be changed on-the-fly # by a separate program, so this is why that other mode is 'dynamic'. # -#static-auth-secret +#static-auth-secret=north + +# Server name used (when necessary) for +# the authentication purposes (oauth). +# The default value is the FQDN of the host. +# +#server-name=blackdow.carleon.gov # 'Static' user accounts for long term credentials mechanism, only. # This option cannot be used with TURN REST API or with short-term credentials diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh index f5120014..bf8c1a4d 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh @@ -30,4 +30,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 $@ +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 --mongo-userdb="mongodb://localhost/coturn" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh index e53c8ef5..b71ef9bb 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh @@ -31,4 +31,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 -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 $@ +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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh index 4cd1725d..7d3ec658 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh @@ -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 -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 $@ +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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh index 4f1245d9..741ab701 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh @@ -31,7 +31,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 -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 $@ +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 $@ # Newer PostgreSQL style connection string example: -# 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 --psql-userdb=postgresql://turn:turn@/turn --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 $@ +# 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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh index 9800883f..905a875f 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh @@ -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 -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 $@ +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 --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 $@ diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 72dd3e6f..60c968e7 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "18 August 2014" "" "" +.TH TURN 1 "16 September 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 2e3878da..2a345d54 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "18 August 2014" "" "" +.TH TURN 1 "16 September 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -612,6 +612,12 @@ that other mode is dynamic. Multiple shared secrets can be used (both in the database and in the "static" fashion). .TP .B +\fB\-\-server\-name\fP +Server name used (when necessary) for +the authentication purposes (oauth). +The default value is the FQDN of the host. +.TP +.B \fB\-\-cert\fP Certificate file, PEM format. Same file search rules applied as for the configuration diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 4182b7f7..9f7db2a0 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "18 August 2014" "" "" +.TH TURN 1 "16 September 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 2496e340..6d6527b0 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -464,6 +464,9 @@ static char Usage[] = "Usage: turnserver [options]\n" " That database value can be changed on-the-fly\n" " by a separate program, so this is why it is 'dynamic'.\n" " Multiple shared secrets can be used (both in the database and in the \"static\" fashion).\n" +" --server-name Server name used (when necessary) for\n" +" the authentication purposes (oauth).\n" +" The default value is the FQDN of the host.\n" " -n Do not use configuration file, take all parameters from the command line only.\n" " --cert Certificate file, PEM format. Same file search rules\n" " applied as for the configuration file.\n" @@ -678,7 +681,8 @@ enum EXTRA_OPTS { CHECK_ORIGIN_CONSISTENCY_OPT, ADMIN_MAX_BPS_OPT, ADMIN_TOTAL_QUOTA_OPT, - ADMIN_USER_QUOTA_OPT + ADMIN_USER_QUOTA_OPT, + SERVER_NAME_OPT }; struct myoption { @@ -732,6 +736,7 @@ static const struct myoption long_options[] = { { "static-auth-secret", required_argument, NULL, STATIC_AUTH_SECRET_VAL_OPT }, /* deprecated: */ { "secret-ts-exp-time", optional_argument, NULL, AUTH_SECRET_TS_EXP }, { "realm", required_argument, NULL, 'r' }, + { "server-name", required_argument, NULL, SERVER_NAME_OPT }, { "user-quota", required_argument, NULL, 'q' }, { "total-quota", required_argument, NULL, 'Q' }, { "max-bps", required_argument, NULL, 's' }, @@ -860,6 +865,9 @@ static void set_option(int c, char *value) } switch (c) { + case SERVER_NAME_OPT: + STRCPY(turn_params.oauth_server_name,value); + break; case NO_SSLV2_OPT: turn_params.no_sslv2 = get_bool_value(value); break; @@ -1557,7 +1565,6 @@ static int adminmain(int argc, char **argv) static void print_features(unsigned long mfn) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\nRFC 3489/5389/5766/5780/6062/6156 STUN/TURN Server\nVersion %s\n",TURN_SOFTWARE); - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Server name: %s\n",turn_params.oauth_server_name); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\nMax number of open files/sockets allowed for this process: %lu\n",mfn); if(turn_params.net_engine_version == 1) mfn = mfn/3; @@ -1693,6 +1700,17 @@ static void init_oauth_server_name(void) { if(!turn_params.oauth_server_name[0]) { STRCPY(turn_params.oauth_server_name,TURN_SOFTWARE); } + { + char domain[513]; + if(getdomainname(domain,sizeof(domain)-1)>=0) { + size_t dlen = strlen(domain); + if(dlen>0) { + size_t slen = strlen(turn_params.oauth_server_name); + turn_params.oauth_server_name[slen]='.'; + ns_bcopy(domain,turn_params.oauth_server_name+slen+1,strlen(domain)+1); + } + } + } } int main(int argc, char **argv) @@ -1797,6 +1815,8 @@ int main(int argc, char **argv) read_config_file(argc,argv,1); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Server name: %s\n",turn_params.oauth_server_name); + optind = 0; while (((c = getopt_long(argc, argv, OPTIONS, uo.u.o, NULL)) != -1)) { From 219d1da23d75ff519849357b2aa29d91232d6a99 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 17 Sep 2014 06:59:43 +0000 Subject: [PATCH 185/805] domain name fix --- src/apps/relay/mainrelay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 6d6527b0..9942910d 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1704,7 +1704,7 @@ static void init_oauth_server_name(void) { char domain[513]; if(getdomainname(domain,sizeof(domain)-1)>=0) { size_t dlen = strlen(domain); - if(dlen>0) { + if(dlen>0 && domain[0] != '(') { size_t slen = strlen(turn_params.oauth_server_name); turn_params.oauth_server_name[slen]='.'; ns_bcopy(domain,turn_params.oauth_server_name+slen+1,strlen(domain)+1); From 2ddd6d4c9e0df0f286c4de8e093d9c5f67d8aed0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 17 Sep 2014 17:50:36 +0000 Subject: [PATCH 186/805] vectors output --- src/apps/rfc5769/rfc5769check.c | 51 +++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/src/apps/rfc5769/rfc5769check.c b/src/apps/rfc5769/rfc5769check.c index 55a48cc7..0dcc1b45 100644 --- a/src/apps/rfc5769/rfc5769check.c +++ b/src/apps/rfc5769/rfc5769check.c @@ -49,35 +49,71 @@ static const char* encs[]={"AES-256-CBC","AES-128-CBC", NULL}; static const char* hmacs[]={"HMAC-SHA-1","HMAC-SHA-256","HMAC-SHA-256-128",NULL}; +void print_field5769(const char* name, const void* f0, size_t len); +void print_field5769(const char* name, const void* f0, size_t len) { + const unsigned char* f = (const unsigned char*)f0; + printf("\nfield %s==>>\n",name); + size_t i; + for(i = 0;i Date: Wed, 17 Sep 2014 20:13:15 +0000 Subject: [PATCH 187/805] oauth cleaning --- src/apps/rfc5769/rfc5769check.c | 14 +++++++++++--- src/client/ns_turn_msg.c | 29 ++++++++++++++++++++++------- src/client/ns_turn_msg.h | 2 +- src/client/ns_turn_msg_defs_new.h | 1 + 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/apps/rfc5769/rfc5769check.c b/src/apps/rfc5769/rfc5769check.c index 0dcc1b45..5710f68c 100644 --- a/src/apps/rfc5769/rfc5769check.c +++ b/src/apps/rfc5769/rfc5769check.c @@ -52,7 +52,7 @@ static const char* hmacs[]={"HMAC-SHA-1","HMAC-SHA-256","HMAC-SHA-256-128",NULL} void print_field5769(const char* name, const void* f0, size_t len); void print_field5769(const char* name, const void* f0, size_t len) { const unsigned char* f = (const unsigned char*)f0; - printf("\nfield %s==>>\n",name); + printf("\nfield %s %lu==>>\n",name,(unsigned long)len); size_t i; for(i = 0;ias_rs_key, NULL); + EVP_CIPHER_CTX_set_padding(&ctx,1); int outl=0; my_EVP_EncryptUpdate(&ctx, encoded_field, &outl, orig_field, (int)len); - int tmp_outl = 0; - EVP_EncryptFinal_ex(&ctx, encoded_field + outl, &tmp_outl); - outl += tmp_outl; + if(outl % OAUTH_ENC_ALG_BLOCK_SIZE) { + int tmp_outl = 0; + EVP_EncryptFinal_ex(&ctx, encoded_field + outl, &tmp_outl); + outl += tmp_outl; + } EVP_CIPHER_CTX_cleanup(&ctx); @@ -2089,6 +2092,7 @@ static int decode_oauth_token_normal(const u08bits *server_name, const encoded_o EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); EVP_DecryptInit_ex(&ctx, cipher, NULL, (const unsigned char *)key->as_rs_key, NULL); + EVP_CIPHER_CTX_set_padding(&ctx,1); int outl=0; my_EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size); @@ -2128,7 +2132,7 @@ static void generate_random_nonce(unsigned char *nonce, size_t sz) { } } -static int encode_oauth_token_aead(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken) +static int encode_oauth_token_aead(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken, const u08bits* nonce0) { if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<128)) { @@ -2155,7 +2159,11 @@ static int encode_oauth_token_aead(const u08bits *server_name, encoded_oauth_tok unsigned char *encoded_field = (unsigned char*)etoken->token; unsigned char nonce[OAUTH_AEAD_NONCE_SIZE]; - generate_random_nonce(nonce, sizeof(nonce)); + if(nonce0) { + ns_bcopy(nonce0,nonce,sizeof(nonce)); + } else { + generate_random_nonce(nonce, sizeof(nonce)); + } EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); @@ -2164,6 +2172,8 @@ static int encode_oauth_token_aead(const u08bits *server_name, encoded_oauth_tok if(1 != EVP_EncryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) return -1; + EVP_CIPHER_CTX_set_padding(&ctx,1); + /* Set IV length if default 12 bytes (96 bits) is not appropriate */ if(1 != EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, OAUTH_AEAD_NONCE_SIZE, NULL)) return -1; @@ -2181,6 +2191,8 @@ static int encode_oauth_token_aead(const u08bits *server_name, encoded_oauth_tok if(1 != my_EVP_EncryptUpdate(&ctx, NULL, &outl, server_name, (int)sn_len)) return -1; + outl=0; + if(1 != my_EVP_EncryptUpdate(&ctx, encoded_field, &outl, orig_field, (int)len)) return -1; @@ -2232,6 +2244,8 @@ static int decode_oauth_token_aead(const u08bits *server_name, const encoded_oau if(1 != EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) return -1; + EVP_CIPHER_CTX_set_padding(&ctx,1); + /* Set IV length if default 12 bytes (96 bits) is not appropriate */ if(1 != EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, OAUTH_AEAD_NONCE_SIZE, NULL)) return -1; @@ -2285,8 +2299,9 @@ static int decode_oauth_token_aead(const u08bits *server_name, const encoded_oau #endif -int encode_oauth_token(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken) +int encode_oauth_token(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken, const u08bits *nonce) { + UNUSED_ARG(nonce); if(server_name && etoken && key && dtoken) { switch(key->as_rs_alg) { case AES_256_CBC: @@ -2295,7 +2310,7 @@ int encode_oauth_token(const u08bits *server_name, encoded_oauth_token *etoken, #if !defined(TURN_NO_GCM) case AEAD_AES_128_GCM: case AEAD_AES_256_GCM: - return encode_oauth_token_aead(server_name, etoken,key,dtoken); + return encode_oauth_token_aead(server_name, etoken,key,dtoken,nonce); #endif default: fprintf(stderr,"Wrong AS_RS algorithm: %d\n",(int)key->as_rs_alg); diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 239eb67d..f54c2354 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -212,7 +212,7 @@ int is_http_get(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); int decode_oauth_token(const u08bits *server_name, const encoded_oauth_token *etoken, const oauth_key *key, oauth_token *dtoken); -int encode_oauth_token(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken); +int encode_oauth_token(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken, const u08bits *nonce); /////////////////////////////////////////////////////////////// diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 965e7979..9da460d3 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -109,6 +109,7 @@ typedef enum _AUTH_ALG AUTH_ALG; #define OAUTH_KEY_SIZE (256) #define OAUTH_AEAD_NONCE_SIZE (12) #define OAUTH_AEAD_TAG_SIZE (16) +#define OAUTH_ENC_ALG_BLOCK_SIZE (16) #define OAUTH_DEFAULT_LIFETIME (0) #define OAUTH_DEFAULT_TIMESTAMP (turn_time()) From 4dc822e3e15f87fef2dd487fad6ee8e193ee0107 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 17 Sep 2014 21:16:15 +0000 Subject: [PATCH 188/805] constant timestamp in the samples --- src/apps/rfc5769/rfc5769check.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/apps/rfc5769/rfc5769check.c b/src/apps/rfc5769/rfc5769check.c index 5710f68c..c0821fe8 100644 --- a/src/apps/rfc5769/rfc5769check.c +++ b/src/apps/rfc5769/rfc5769check.c @@ -76,9 +76,7 @@ static int check_oauth(void) { const char mac_key[33] = "ZksjpweoixXmvn67534m"; const size_t mac_key_length=strlen(mac_key); - uint64_t token_timestamp0 = turn_time(); - const uint64_t token_timestamp = token_timestamp0 << 16; - printf("key timestamp: %llu\n",(unsigned long long)token_timestamp); + const uint64_t token_timestamp = 92470300704768; const uint32_t token_lifetime = 3600; const char kid[33] = "2783466234"; From 6d9303218c0a6d85592a4fc71bd6517b73b17fcd Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 17 Sep 2014 21:47:51 +0000 Subject: [PATCH 189/805] output cleaned --- src/apps/rfc5769/rfc5769check.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/apps/rfc5769/rfc5769check.c b/src/apps/rfc5769/rfc5769check.c index c0821fe8..ec19252e 100644 --- a/src/apps/rfc5769/rfc5769check.c +++ b/src/apps/rfc5769/rfc5769check.c @@ -49,6 +49,8 @@ static const char* encs[]={"AES-256-CBC","AES-128-CBC", NULL}; static const char* hmacs[]={"HMAC-SHA-1","HMAC-SHA-256","HMAC-SHA-256-128",NULL}; +static int print_extra = 0; + void print_field5769(const char* name, const void* f0, size_t len); void print_field5769(const char* name, const void* f0, size_t len) { const unsigned char* f = (const unsigned char*)f0; @@ -91,7 +93,10 @@ static int check_oauth(void) { for (i_encs = 0; encs[i_encs]; ++i_encs) { - printf("oauth token %s:%s:%s:\n",hmacs[i_hmacs],shas[i_shas],encs[i_encs]); + printf("oauth token %s:%s:%s:",hmacs[i_hmacs],shas[i_shas],encs[i_encs]); + + if(print_extra) + printf("\n"); oauth_token ot; ot.enc_block.key_length = (uint16_t)mac_key_length; @@ -133,8 +138,10 @@ static int check_oauth(void) { } } - print_field5769("AS-RS",key.as_rs_key,key.as_rs_key_size); - print_field5769("AUTH",key.auth_key,key.auth_key_size); + if(print_extra) { + print_field5769("AS-RS",key.as_rs_key,key.as_rs_key_size); + print_field5769("AUTH",key.auth_key,key.auth_key_size); + } { encoded_oauth_token etoken; @@ -147,7 +154,9 @@ static int check_oauth(void) { return -1; } - print_field5769("encoded token",etoken.token,etoken.size); + if(print_extra) { + print_field5769("encoded token",etoken.token,etoken.size); + } if (decode_oauth_token((const u08bits *) server_name, &etoken, &key, &dot) < 0) { @@ -205,6 +214,9 @@ int main(int argc, const char **argv) UNUSED_ARG(argc); UNUSED_ARG(argv); + if(argc>1) + print_extra = 1; + set_logfile("stdout"); set_system_parameters(0); From f2cc2e9457174b93a2809ec994386af6917efbdd Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 18 Sep 2014 06:26:50 +0000 Subject: [PATCH 190/805] server name cleaning --- src/apps/relay/mainrelay.c | 51 ++++++++++++++++++--------- src/apps/relay/mainrelay.h | 1 + src/apps/relay/ns_ioalib_impl.h | 2 +- src/apps/relay/userdb.c | 61 ++++++++++++--------------------- 4 files changed, 58 insertions(+), 57 deletions(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 9942910d..462646af 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -85,7 +85,7 @@ LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,0,"", 0,NULL,0,NULL,DEFAULT_GENERAL_RELAY_SERVERS_NUMBER,0, ////////////// Auth server ///////////////////////////////////// {NULL,NULL,NULL,0,NULL}, -"", +"","", /////////////// AUX SERVERS //////////////// {NULL,0,{0,NULL}},0, /////////////// ALTERNATE SERVERS //////////////// @@ -1693,26 +1693,38 @@ static void drop_privileges(void) } static void init_oauth_server_name(void) { - struct utsname name; - if(!uname(&name)) { - STRCPY(turn_params.oauth_server_name,name.nodename); - } + if(!turn_params.oauth_server_name[0]) { - STRCPY(turn_params.oauth_server_name,TURN_SOFTWARE); - } - { - char domain[513]; - if(getdomainname(domain,sizeof(domain)-1)>=0) { - size_t dlen = strlen(domain); - if(dlen>0 && domain[0] != '(') { - size_t slen = strlen(turn_params.oauth_server_name); + + struct utsname name; + + if(!uname(&name)) { + STRCPY(turn_params.oauth_server_name,name.nodename); + } + if(!turn_params.oauth_server_name[0]) { + STRCPY(turn_params.oauth_server_name,TURN_SOFTWARE); + } + + size_t slen = strlen(turn_params.oauth_server_name); + + if(get_realm(NULL)->options.name[0]) { + turn_params.oauth_server_name[slen]='.'; + ns_bcopy(get_realm(NULL)->options.name,turn_params.oauth_server_name+slen+1,strlen(get_realm(NULL)->options.name)+1); + } else { + size_t dlen = strlen(turn_params.domain); + if(dlen>0 && turn_params.domain[0] != '(') { turn_params.oauth_server_name[slen]='.'; - ns_bcopy(domain,turn_params.oauth_server_name+slen+1,strlen(domain)+1); + ns_bcopy(turn_params.domain,turn_params.oauth_server_name+slen+1,strlen(turn_params.domain)+1); } } } } +static void init_domain(void) +{ + getdomainname(turn_params.domain,sizeof(turn_params.domain)-1); +} + int main(int argc, char **argv) { int c = 0; @@ -1727,7 +1739,8 @@ int main(int argc, char **argv) redis_async_init(); #endif - create_new_realm(NULL); + init_domain(); + create_default_realm(); init_turn_server_addrs_list(&turn_params.alternate_servers_list); init_turn_server_addrs_list(&turn_params.tls_alternate_servers_list); @@ -1738,7 +1751,6 @@ int main(int argc, char **argv) init_listener(); init_secrets_list(&turn_params.default_users_db.ram_db.static_auth_secrets); init_dynamic_ip_lists(); - init_oauth_server_name(); if (!strstr(argv[0], "turnadmin")) { @@ -1815,6 +1827,13 @@ int main(int argc, char **argv) read_config_file(argc,argv,1); + if(!get_realm(NULL)->options.name[0]) { + STRCPY(get_realm(NULL)->options.name,turn_params.domain); + } + + init_oauth_server_name(); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Domain name: %s\n",turn_params.domain); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Default realm: %s\n",get_realm(NULL)->options.name); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Server name: %s\n",turn_params.oauth_server_name); optind = 0; diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index be56bd4e..da45b0d3 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -272,6 +272,7 @@ typedef struct _turn_params_ { struct auth_server authserver; char oauth_server_name[1025]; + char domain[1025]; /////////////// AUX SERVERS //////////////// diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index a44f288b..a0934b90 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -236,7 +236,7 @@ typedef struct _timer_event /* realm */ -void create_new_realm(char* name); +void create_default_realm(); int get_realm_data(char* name, realm_params_t* rp); /* engine handling */ diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 6763bcab..a00b58b3 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -65,15 +65,6 @@ //////////// REALM ////////////// static realm_params_t *default_realm_params_ptr = NULL; -static const realm_params_t _default_realm_params = -{ - 1, - { - "\0", /* name */ - {0,0,0} - }, - {0,NULL} -}; static ur_string_map *realms = NULL; static turn_mutex o_to_realm_mutex; @@ -95,40 +86,30 @@ void update_o_to_realm(ur_string_map * o_to_realm_new) { TURN_MUTEX_UNLOCK(&o_to_realm_mutex); } -void create_new_realm(char* name) +void create_default_realm() { - realm_params_t *ret = NULL; - - if((name == NULL)||(name[0]==0)) { - if(default_realm_params_ptr) { - return; - } - /* init everything: */ - TURN_MUTEX_INIT_RECURSIVE(&o_to_realm_mutex); - init_secrets_list(&realms_list); - o_to_realm = ur_string_map_create(free); - default_realm_params_ptr = (realm_params_t*)malloc(sizeof(realm_params_t)); - ns_bcopy(&_default_realm_params,default_realm_params_ptr,sizeof(realm_params_t)); - realms = ur_string_map_create(NULL); - ur_string_map_lock(realms); - ret = default_realm_params_ptr; - } else { - ur_string_map_value_type value = 0; - ur_string_map_lock(realms); - if (!ur_string_map_get(realms, (const ur_string_map_key_type) name, &value)) { - ret = (realm_params_t*)turn_malloc(sizeof(realm_params_t)); - ns_bcopy(default_realm_params_ptr,ret,sizeof(realm_params_t)); - STRCPY(ret->options.name,name); - value = (ur_string_map_value_type)ret; - ur_string_map_put(realms, (const ur_string_map_key_type) name, value); - add_to_secrets_list(&realms_list, name); - } else { - ur_string_map_unlock(realms); - return; - } + if(default_realm_params_ptr) { + return; } - ret->status.alloc_counters = ur_string_map_create(NULL); + static realm_params_t _default_realm_params = + { + 1, + { + "\0", /* name */ + {0,0,0} + }, + {0,NULL} + }; + + /* init everything: */ + TURN_MUTEX_INIT_RECURSIVE(&o_to_realm_mutex); + init_secrets_list(&realms_list); + o_to_realm = ur_string_map_create(free); + default_realm_params_ptr = &_default_realm_params; + realms = ur_string_map_create(NULL); + ur_string_map_lock(realms); + default_realm_params_ptr->status.alloc_counters = ur_string_map_create(NULL); ur_string_map_unlock(realms); } From 2fbd4138de4a54e396e339da56735ba387c42e4b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 19 Sep 2014 07:04:53 +0000 Subject: [PATCH 191/805] working on oauth --- README.turnserver | 2 ++ examples/etc/turnserver.conf | 4 ++++ man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 6 +++++- man/man1/turnutils.1 | 2 +- src/apps/relay/mainrelay.c | 14 +++++++++++--- src/apps/relay/mainrelay.h | 1 + src/apps/relay/netengine.c | 3 ++- src/client/ns_turn_msg_defs_new.h | 2 ++ src/server/ns_turn_server.c | 17 ++++++++++++++++- src/server/ns_turn_server.h | 8 +++++++- 11 files changed, 52 insertions(+), 9 deletions(-) diff --git a/README.turnserver b/README.turnserver index aba2478b..8ac4de46 100644 --- a/README.turnserver +++ b/README.turnserver @@ -190,6 +190,8 @@ Flags: 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. + --dh566 Use 566 bits predefined DH TLS key. Default size of the key is 1066. --dh2066 Use 2066 bits predefined DH TLS key. Default size of the key is 1066. diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 5d7c8ec1..f52b8e47 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -216,6 +216,10 @@ # #server-name=blackdow.carleon.gov +# Flag to support 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. diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 60c968e7..d47dae33 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "16 September 2014" "" "" +.TH TURN 1 "18 September 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 2a345d54..45bfc49f 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "16 September 2014" "" "" +.TH TURN 1 "18 September 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -276,6 +276,10 @@ 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 +Support oAuth authentication. +.TP +.B \fB\-\-dh566\fP Use 566 bits predefined DH TLS key. Default size of the key is 1066. .TP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 9f7db2a0..90169288 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "16 September 2014" "" "" +.TH TURN 1 "18 September 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 462646af..234e706c 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -85,7 +85,7 @@ LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,0,"", 0,NULL,0,NULL,DEFAULT_GENERAL_RELAY_SERVERS_NUMBER,0, ////////////// Auth server ///////////////////////////////////// {NULL,NULL,NULL,0,NULL}, -"","", +"","",0, /////////////// AUX SERVERS //////////////// {NULL,0,{0,NULL}},0, /////////////// ALTERNATE SERVERS //////////////// @@ -467,6 +467,7 @@ static char Usage[] = "Usage: turnserver [options]\n" " --server-name Server name used (when necessary) for\n" " the authentication purposes (oauth).\n" " The default value is the FQDN of the host.\n" +" --oauth Support oAuth authentication.\n" " -n Do not use configuration file, take all parameters from the command line only.\n" " --cert Certificate file, PEM format. Same file search rules\n" " applied as for the configuration file.\n" @@ -682,7 +683,8 @@ enum EXTRA_OPTS { ADMIN_MAX_BPS_OPT, ADMIN_TOTAL_QUOTA_OPT, ADMIN_USER_QUOTA_OPT, - SERVER_NAME_OPT + SERVER_NAME_OPT, + OAUTH_OPT }; struct myoption { @@ -737,6 +739,7 @@ static const struct myoption long_options[] = { /* deprecated: */ { "secret-ts-exp-time", optional_argument, NULL, AUTH_SECRET_TS_EXP }, { "realm", required_argument, NULL, 'r' }, { "server-name", required_argument, NULL, SERVER_NAME_OPT }, + { "oauth", optional_argument, NULL, OAUTH_OPT }, { "user-quota", required_argument, NULL, 'q' }, { "total-quota", required_argument, NULL, 'Q' }, { "max-bps", required_argument, NULL, 's' }, @@ -868,6 +871,9 @@ static void set_option(int c, char *value) case SERVER_NAME_OPT: STRCPY(turn_params.oauth_server_name,value); break; + case OAUTH_OPT: + turn_params.oauth = get_bool_value(value); + break; case NO_SSLV2_OPT: turn_params.no_sslv2 = get_bool_value(value); break; @@ -1834,7 +1840,9 @@ int main(int argc, char **argv) init_oauth_server_name(); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Domain name: %s\n",turn_params.domain); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Default realm: %s\n",get_realm(NULL)->options.name); - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Server name: %s\n",turn_params.oauth_server_name); + if(turn_params.oauth) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "oAuth server name: %s\n",turn_params.oauth_server_name); + } optind = 0; diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index da45b0d3..0b684c95 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -273,6 +273,7 @@ typedef struct _turn_params_ { struct auth_server authserver; char oauth_server_name[1025]; char domain[1025]; + int oauth; /////////////// AUX SERVERS //////////////// diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 0e285045..a3311381 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1594,7 +1594,8 @@ 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, - allocate_bps); + allocate_bps, + turn_params.oauth, turn_params.oauth_server_name); if(to_set_rfc5780) { set_rfc5780(&(rs->server), get_alt_addr, send_message_from_listener_to_client); diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 9da460d3..b5f9b9b4 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -103,6 +103,8 @@ typedef enum _AUTH_ALG AUTH_ALG; * oAuth struct */ +#define STUN_ATTRIBUTE_THIRD_PARTY_AUTHORIZATION (0x8030) + #define OAUTH_KID_SIZE (128) #define OAUTH_HASH_FUNC_SIZE (64) #define OAUTH_ALG_SIZE (64) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index b80a321b..51a4663c 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3075,6 +3075,17 @@ static int create_challenge_response(ts_ur_super_session *ss, stun_tid *tid, int char *realm = ss->realm_options.name; stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_REALM, (u08bits*)realm, (int)(strlen((s08bits*)(realm)))); + + if(ss->server) { + turn_turnserver* server = (turn_turnserver*)ss->server; + if(server->oauth && (server->oauth_server_name)&&(server->oauth_server_name[0])) { + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, + STUN_ATTRIBUTE_THIRD_PARTY_AUTHORIZATION, + (const u08bits*)(server->oauth_server_name), + strlen(server->oauth_server_name)); + } + } + ioa_network_buffer_set_size(nbh,len); return 0; } @@ -4702,7 +4713,8 @@ 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, - allocate_bps_cb allocate_bps_func) { + allocate_bps_cb allocate_bps_func, + int oauth, const char* oauth_server_name) { if (!server) return; @@ -4726,6 +4738,9 @@ 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->oauth = oauth; + if(oauth) + server->oauth_server_name = oauth_server_name; if(mobility) server->mobile_connections_map = ur_map_create(); diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index 1aba589e..360d0eac 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -160,6 +160,10 @@ struct _turn_turnserver { /* Bandwidth draft: */ allocate_bps_cb allocate_bps_func; + + /* oAuth: */ + int oauth; + const char* oauth_server_name; }; /////////////////////////////////////////// @@ -195,7 +199,9 @@ void init_turn_server(turn_turnserver* server, vintp mobility, int server_relay, send_turn_session_info_cb send_turn_session_info, - allocate_bps_cb allocate_bps_func); + allocate_bps_cb allocate_bps_func, + int oauth, + const char* oauth_server_name); ioa_engine_handle turn_server_get_engine(turn_turnserver *s); From f1e1605177c4b553c372bb5e7271564f18878204 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 20 Sep 2014 05:57:16 +0000 Subject: [PATCH 192/805] compilation warning fixed --- src/apps/relay/ns_ioalib_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index a0934b90..e31347f6 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -236,7 +236,7 @@ typedef struct _timer_event /* realm */ -void create_default_realm(); +void create_default_realm(void); int get_realm_data(char* name, realm_params_t* rp); /* engine handling */ From ca26155a2a863f89df5a98b9621cb594f98f1994 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 20 Sep 2014 06:29:26 +0000 Subject: [PATCH 193/805] fixes for openssl1.0.1c and earlier (AEAD) --- src/client/ns_turn_msg.c | 55 +++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 6bbd55d5..61ce1970 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1687,7 +1687,7 @@ static size_t calculate_enc_key_length(ENC_ALG a) #endif return 16; default: - ; + break; }; return 32; @@ -1703,7 +1703,7 @@ static size_t calculate_auth_key_length(AUTH_ALG a) case AUTH_ALG_HMAC_SHA_256: return 32; default: - ; + break; }; return 32; @@ -1719,7 +1719,7 @@ static size_t calculate_auth_output_length(AUTH_ALG a) case AUTH_ALG_HMAC_SHA_256: return 32; default: - ; + break; }; return 32; @@ -1901,7 +1901,7 @@ static const EVP_CIPHER *get_cipher_type(ENC_ALG enc_alg) return EVP_aes_256_gcm(); #endif default: - ; + break; } OAUTH_ERROR("%s: Unknown enc algorithm: %d\n",__FUNCTION__,(int)enc_alg); return NULL; @@ -1916,7 +1916,7 @@ static const EVP_MD *get_auth_type(AUTH_ALG aa) case AUTH_ALG_HMAC_SHA_256: return EVP_sha256(); default: - ; + break; }; OAUTH_ERROR("%s: Unknown auth algorithm: %d\n",__FUNCTION__,(int)aa); return NULL; @@ -1930,7 +1930,7 @@ static void update_hmac_len(AUTH_ALG aa, unsigned int *hmac_len) *hmac_len = 16; break; default: - ; + break; }; } } @@ -1942,7 +1942,10 @@ static int my_EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int out_len = 0; while((out_lenas_rs_alg); - if(!cipher) + if(!cipher) { + OAUTH_ERROR("%s: Cannot find cipher for algorithm: %d\n",__FUNCTION__,(int)key->as_rs_alg); return -1; + } EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); /* Initialize the decryption operation. */ - if(1 != EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) + if(1 != EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) { + OAUTH_ERROR("%s: Cannot initialize decryption\n",__FUNCTION__); return -1; + } - EVP_CIPHER_CTX_set_padding(&ctx,1); + //EVP_CIPHER_CTX_set_padding(&ctx,1); /* Set IV length if default 12 bytes (96 bits) is not appropriate */ - if(1 != EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, OAUTH_AEAD_NONCE_SIZE, NULL)) + if(1 != EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, OAUTH_AEAD_NONCE_SIZE, NULL)) { + OAUTH_ERROR("%s: Cannot set nonce length\n",__FUNCTION__); return -1; + } /* Initialize key and IV */ - if(1 != EVP_DecryptInit_ex(&ctx, NULL, NULL, (const unsigned char *)key->as_rs_key, nonce)) + if(1 != EVP_DecryptInit_ex(&ctx, NULL, NULL, (const unsigned char *)key->as_rs_key, nonce)) { + OAUTH_ERROR("%s: Cannot set nonce\n",__FUNCTION__); return -1; + } + + /* Set expected tag value. A restriction in OpenSSL 1.0.1c and earlier + + * required the tag before any AAD or ciphertext */ + EVP_CIPHER_CTX_ctrl (&ctx, EVP_CTRL_GCM_SET_TAG, OAUTH_AEAD_TAG_SIZE, tag); int outl=0; size_t sn_len = strlen((const char*)server_name); @@ -2260,13 +2278,14 @@ static int decode_oauth_token_aead(const u08bits *server_name, const encoded_oau /* Provide any AAD data. This can be called zero or more times as * required */ - if(1 != my_EVP_DecryptUpdate(&ctx, NULL, &outl, server_name, (int)sn_len)) + if(1 != my_EVP_DecryptUpdate(&ctx, NULL, &outl, server_name, (int)sn_len)) { + OAUTH_ERROR("%s: Cannot decrypt update server_name: %s, len=%d\n",__FUNCTION__,server_name,(int)sn_len); return -1; - if(1 != my_EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size)) + } + if(1 != my_EVP_DecryptUpdate(&ctx, decoded_field, &outl, encoded_field, (int)encoded_field_size)) { + OAUTH_ERROR("%s: Cannot decrypt update\n",__FUNCTION__); return -1; - - - EVP_CIPHER_CTX_ctrl (&ctx, EVP_CTRL_GCM_SET_TAG, OAUTH_AEAD_TAG_SIZE, tag); + } int tmp_outl = 0; if(EVP_DecryptFinal_ex(&ctx, decoded_field + outl, &tmp_outl)<1) { From 5fb22f9bbc0d8e21a01e70ff712d3f394dbd5edd Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 20 Sep 2014 06:32:52 +0000 Subject: [PATCH 194/805] compilation warning fixed) --- src/apps/rfc5769/rfc5769check.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/rfc5769/rfc5769check.c b/src/apps/rfc5769/rfc5769check.c index ec19252e..a1a93ac5 100644 --- a/src/apps/rfc5769/rfc5769check.c +++ b/src/apps/rfc5769/rfc5769check.c @@ -78,7 +78,7 @@ static int check_oauth(void) { const char mac_key[33] = "ZksjpweoixXmvn67534m"; const size_t mac_key_length=strlen(mac_key); - const uint64_t token_timestamp = 92470300704768; + const uint64_t token_timestamp = (uint64_t)(92470300704768LL); const uint32_t token_lifetime = 3600; const char kid[33] = "2783466234"; From a222183daaf05f49a1140209b29926e904df05c7 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 20 Sep 2014 07:23:55 +0000 Subject: [PATCH 195/805] compilation warning fixed --- src/client/ns_turn_msg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 61ce1970..1159d967 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -87,7 +87,7 @@ int stun_method_str(u16bits method, char *smethod) }; if(smethod) { - STRCPY(smethod,s); + ns_bcopy(s,smethod,strlen(s)+1); } return ret; From 952c89006f670eacd7ad7d7dbe5222b39127dd8c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 20 Sep 2014 07:46:34 +0000 Subject: [PATCH 196/805] compilation warnings fixed --- configure | 2 +- src/apps/relay/mainrelay.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 43b9275d..447316f0 100755 --- a/configure +++ b/configure @@ -584,7 +584,7 @@ SYSTEM=`uname` if [ "${SYSTEM}" = "SunOS" ] ; then # Solaris ? is this you ?! - OSCFLAGS="${OSCFLAGS} -D__EXTENSIONS__ -D_XOPEN_SOURCE=500" + OSCFLAGS="${OSCFLAGS} -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 -DNO_GETDOMAINNAME" fi ######################### diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 234e706c..69eb7eea 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1704,11 +1704,11 @@ static void init_oauth_server_name(void) { struct utsname name; - if(!uname(&name)) { + if(uname(&name)>=0) { STRCPY(turn_params.oauth_server_name,name.nodename); } if(!turn_params.oauth_server_name[0]) { - STRCPY(turn_params.oauth_server_name,TURN_SOFTWARE); + STRCPY(turn_params.oauth_server_name,"coturn"); } size_t slen = strlen(turn_params.oauth_server_name); @@ -1728,7 +1728,9 @@ static void init_oauth_server_name(void) { static void init_domain(void) { +#if !defined(NO_GETDOMAINNAME) getdomainname(turn_params.domain,sizeof(turn_params.domain)-1); +#endif } int main(int argc, char **argv) From 32b1b98e1a34ee306515dada4ca2de8d52f578bb Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 20 Sep 2014 16:16:07 +0000 Subject: [PATCH 197/805] compilation fixed for old openssls --- src/apps/rfc5769/rfc5769check.c | 12 ++++++++++-- src/client/ns_turn_msg.c | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/apps/rfc5769/rfc5769check.c b/src/apps/rfc5769/rfc5769check.c index a1a93ac5..59fdc40d 100644 --- a/src/apps/rfc5769/rfc5769check.c +++ b/src/apps/rfc5769/rfc5769check.c @@ -41,13 +41,21 @@ //////////// OAUTH ////////////////// -static const char* shas[]={"SHA1","SHA256",NULL}; +static const char* shas[]={"SHA1", +#if !defined(OPENSSL_NO_SHA256) && defined(SSL_TXT_SHA256) + "SHA256", +#endif + NULL}; static const char* encs[]={"AES-256-CBC","AES-128-CBC", #if !defined(TURN_NO_GCM) "AEAD_AES_128_GCM", "AEAD_AES_256_GCM", #endif NULL}; -static const char* hmacs[]={"HMAC-SHA-1","HMAC-SHA-256","HMAC-SHA-256-128",NULL}; +static const char* hmacs[]={"HMAC-SHA-1", +#if !defined(OPENSSL_NO_SHA256) && defined(SSL_TXT_SHA256) + "HMAC-SHA-256","HMAC-SHA-256-128", +#endif + NULL}; static int print_extra = 0; diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 1159d967..2d1c5a6b 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1912,9 +1912,11 @@ static const EVP_MD *get_auth_type(AUTH_ALG aa) switch(aa) { case AUTH_ALG_HMAC_SHA_1: return EVP_sha1(); +#if !defined(OPENSSL_NO_SHA256) && defined(SSL_TXT_SHA256) case AUTH_ALG_HMAC_SHA_256_128: case AUTH_ALG_HMAC_SHA_256: return EVP_sha256(); +#endif default: break; }; From 5c66dd79a25d1d26fd93c42d5c39d1d3252b1040 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 21 Sep 2014 06:12:15 +0000 Subject: [PATCH 198/805] old openssl lib fixes --- configure | 2 +- src/apps/relay/mainrelay.c | 2 +- src/client/ns_turn_msg.c | 16 ++++++++++------ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 447316f0..d7e2ee77 100755 --- a/configure +++ b/configure @@ -584,7 +584,7 @@ SYSTEM=`uname` if [ "${SYSTEM}" = "SunOS" ] ; then # Solaris ? is this you ?! - OSCFLAGS="${OSCFLAGS} -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 -DNO_GETDOMAINNAME" + OSCFLAGS="${OSCFLAGS} -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 -DTURN_NO_GETDOMAINNAME" fi ######################### diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 69eb7eea..d51f4dde 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1728,7 +1728,7 @@ static void init_oauth_server_name(void) { static void init_domain(void) { -#if !defined(NO_GETDOMAINNAME) +#if !defined(TURN_NO_GETDOMAINNAME) getdomainname(turn_params.domain,sizeof(turn_params.domain)-1); #endif } diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 2d1c5a6b..385dc2d9 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -116,14 +116,16 @@ int stun_calculate_hmac(const u08bits *buf, size_t len, const u08bits *key, size ERR_clear_error(); UNUSED_ARG(shatype); -#if !defined(OPENSSL_NO_SHA256) && defined(SSL_TXT_SHA256) if(shatype == SHATYPE_SHA256) { +#if !defined(OPENSSL_NO_SHA256) && defined(SSL_TXT_SHA256) if (!HMAC(EVP_sha256(), key, keylen, buf, len, hmac, hmac_len)) { return -1; } - } else +#else + fprintf(stderr,"SHA256 is not supported\n"); + return -1; #endif - + } else if (!HMAC(EVP_sha1(), key, keylen, buf, len, hmac, hmac_len)) { return -1; } @@ -150,17 +152,19 @@ int stun_produce_integrity_key_str(u08bits *uname, u08bits *realm, u08bits *upwd strncpy((s08bits*)str+ulen+1+rlen+1,(s08bits*)upwd,sz-ulen-1-rlen-1); str[strl]=0; -#if !defined(OPENSSL_NO_SHA256) && defined(SSL_TXT_SHA256) if(shatype == SHATYPE_SHA256) { +#if !defined(OPENSSL_NO_SHA256) && defined(SSL_TXT_SHA256) unsigned int keylen = 0; EVP_MD_CTX ctx; EVP_DigestInit(&ctx,EVP_sha256()); EVP_DigestUpdate(&ctx,str,strl); EVP_DigestFinal(&ctx,key,&keylen); EVP_MD_CTX_cleanup(&ctx); - } else +#else + fprintf(stderr,"SHA256 is not supported\n"); + return -1; #endif - { + } else { MD5_CTX ctx; MD5_Init(&ctx); MD5_Update(&ctx,str,strl); From ff6120ca7b25b87741205141981cfd0806beac38 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 21 Sep 2014 06:43:20 +0000 Subject: [PATCH 199/805] fixes for old openssl --- src/apps/rfc5769/rfc5769check.c | 4 ++-- src/client/ns_turn_msg.c | 18 ++++++++---------- src/client/ns_turn_msg_defs_new.h | 2 -- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/apps/rfc5769/rfc5769check.c b/src/apps/rfc5769/rfc5769check.c index 59fdc40d..d2aa46b2 100644 --- a/src/apps/rfc5769/rfc5769check.c +++ b/src/apps/rfc5769/rfc5769check.c @@ -42,7 +42,7 @@ //////////// OAUTH ////////////////// static const char* shas[]={"SHA1", -#if !defined(OPENSSL_NO_SHA256) && defined(SSL_TXT_SHA256) +#if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH) "SHA256", #endif NULL}; @@ -52,7 +52,7 @@ static const char* encs[]={"AES-256-CBC","AES-128-CBC", #endif NULL}; static const char* hmacs[]={"HMAC-SHA-1", -#if !defined(OPENSSL_NO_SHA256) && defined(SSL_TXT_SHA256) +#if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH) "HMAC-SHA-256","HMAC-SHA-256-128", #endif NULL}; diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 385dc2d9..25f8825e 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -117,7 +117,7 @@ int stun_calculate_hmac(const u08bits *buf, size_t len, const u08bits *key, size UNUSED_ARG(shatype); if(shatype == SHATYPE_SHA256) { -#if !defined(OPENSSL_NO_SHA256) && defined(SSL_TXT_SHA256) +#if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH) if (!HMAC(EVP_sha256(), key, keylen, buf, len, hmac, hmac_len)) { return -1; } @@ -153,7 +153,7 @@ int stun_produce_integrity_key_str(u08bits *uname, u08bits *realm, u08bits *upwd str[strl]=0; if(shatype == SHATYPE_SHA256) { -#if !defined(OPENSSL_NO_SHA256) && defined(SSL_TXT_SHA256) +#if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH) unsigned int keylen = 0; EVP_MD_CTX ctx; EVP_DigestInit(&ctx,EVP_sha256()); @@ -1686,9 +1686,7 @@ static size_t calculate_enc_key_length(ENC_ALG a) { switch(a) { case AES_128_CBC: -#if !defined(TURN_NO_GCM) case AEAD_AES_128_GCM: -#endif return 16; default: break; @@ -1855,12 +1853,10 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er key->as_rs_alg = AES_128_CBC; } else if(!strcmp(oakd->as_rs_alg,"AES-256-CBC")) { key->as_rs_alg = AES_256_CBC; -#if !defined(TURN_NO_GCM) } else if(!strcmp(oakd->as_rs_alg,"AEAD-AES-128-GCM")) { key->as_rs_alg = AEAD_AES_128_GCM; } else if(!strcmp(oakd->as_rs_alg,"AEAD-AES-256-GCM")) { key->as_rs_alg = AEAD_AES_256_GCM; -#endif } 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); @@ -1907,7 +1903,7 @@ static const EVP_CIPHER *get_cipher_type(ENC_ALG enc_alg) default: break; } - OAUTH_ERROR("%s: Unknown enc algorithm: %d\n",__FUNCTION__,(int)enc_alg); + OAUTH_ERROR("%s: Unsupported enc algorithm: %d\n",__FUNCTION__,(int)enc_alg); return NULL; } @@ -1916,7 +1912,7 @@ static const EVP_MD *get_auth_type(AUTH_ALG aa) switch(aa) { case AUTH_ALG_HMAC_SHA_1: return EVP_sha1(); -#if !defined(OPENSSL_NO_SHA256) && defined(SSL_TXT_SHA256) +#if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH) case AUTH_ALG_HMAC_SHA_256_128: case AUTH_ALG_HMAC_SHA_256: return EVP_sha256(); @@ -2338,7 +2334,8 @@ int encode_oauth_token(const u08bits *server_name, encoded_oauth_token *etoken, return encode_oauth_token_aead(server_name, etoken,key,dtoken,nonce); #endif default: - fprintf(stderr,"Wrong AS_RS algorithm: %d\n",(int)key->as_rs_alg); + fprintf(stderr,"Unsupported AS_RS algorithm: %d\n",(int)key->as_rs_alg); + break; }; } return -1; @@ -2357,7 +2354,8 @@ int decode_oauth_token(const u08bits *server_name, const encoded_oauth_token *et return decode_oauth_token_aead(server_name, etoken,key,dtoken); #endif default: - fprintf(stderr,"Wrong AS_RS algorithm: %d\n",(int)key->as_rs_alg); + fprintf(stderr,"Unsupported AS_RS algorithm: %d\n",(int)key->as_rs_alg); + break; }; } return -1; diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index b5f9b9b4..4315f02a 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -73,10 +73,8 @@ enum _ENC_ALG { ENC_ALG_DEFAULT=0, AES_256_CBC=ENC_ALG_DEFAULT, AES_128_CBC, -#if !defined(TURN_NO_GCM) AEAD_AES_128_GCM, AEAD_AES_256_GCM, -#endif ENG_ALG_NUM }; From 6aae7b0e3f9e0c6266afebebc8ad734b391df097 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 21 Sep 2014 06:47:50 +0000 Subject: [PATCH 200/805] domainname fix --- src/apps/relay/mainrelay.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index d51f4dde..39c8bb08 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1730,6 +1730,8 @@ static void init_domain(void) { #if !defined(TURN_NO_GETDOMAINNAME) getdomainname(turn_params.domain,sizeof(turn_params.domain)-1); + if(!strcmp(turn_params.domain,"(none)")) + turn_params.domain[0]=0; #endif } From a3871c9435dbed8791f8088170c5cb8dc21225c0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 23 Sep 2014 00:39:19 +0000 Subject: [PATCH 201/805] author added --- AUTHORS | 4 ++++ README.turnadmin | 2 ++ README.turnserver | 2 ++ README.turnutils | 2 ++ 4 files changed, 10 insertions(+) diff --git a/AUTHORS b/AUTHORS index 4e984eed..9b07296e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -47,3 +47,7 @@ Mutsutoshi Yoshimoto Federico Pinna MongoDB support (since v4.1.0.1) + +Bradley T. Hughes + FreeBSD port + (since v4.1.2.1) diff --git a/README.turnadmin b/README.turnadmin index 121c6066..bd0bc514 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -241,3 +241,5 @@ to see the man page. Mutsutoshi Yoshimoto Federico Pinna + + Bradley T. Hughes diff --git a/README.turnserver b/README.turnserver index 8ac4de46..2308e320 100644 --- a/README.turnserver +++ b/README.turnserver @@ -934,3 +934,5 @@ https://groups.google.com/forum/?fromgroups=#!forum/turn-server-project-rfc5766- Mutsutoshi Yoshimoto Federico Pinna + + Bradley T. Hughes diff --git a/README.turnutils b/README.turnutils index beb3e8d5..b76a6eb8 100644 --- a/README.turnutils +++ b/README.turnutils @@ -337,3 +337,5 @@ SEE ALSO Mutsutoshi Yoshimoto Federico Pinna + + Bradley T. Hughes From 491d7d7eba723aa4fc03b99693294c92f610d2c8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 23 Sep 2014 05:41:31 +0000 Subject: [PATCH 202/805] man pages --- man/man1/turnadmin.1 | 4 +++- man/man1/turnserver.1 | 4 +++- man/man1/turnutils.1 | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index d47dae33..f1dd07f6 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "18 September 2014" "" "" +.TH TURN 1 "22 September 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage @@ -330,3 +330,5 @@ Peter Dunkley Mutsutoshi Yoshimoto .PP Federico Pinna +.PP +Bradley T. Hughes diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 45bfc49f..23271dcb 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "18 September 2014" "" "" +.TH TURN 1 "22 September 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -1186,3 +1186,5 @@ Peter Dunkley Mutsutoshi Yoshimoto .PP Federico Pinna +.PP +Bradley T. Hughes diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 90169288..ad2cd4ad 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "18 September 2014" "" "" +.TH TURN 1 "22 September 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -455,3 +455,5 @@ Peter Dunkley Mutsutoshi Yoshimoto .PP Federico Pinna +.PP +Bradley T. Hughes From 21054d7af4064ed934796d0d8da441decde0c77e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 23 Sep 2014 06:36:04 +0000 Subject: [PATCH 203/805] new access-token attribute introduced --- src/client/ns_turn_msg_defs_new.h | 1 + src/server/ns_turn_server.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 4315f02a..9e9111e6 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -102,6 +102,7 @@ typedef enum _AUTH_ALG AUTH_ALG; */ #define STUN_ATTRIBUTE_THIRD_PARTY_AUTHORIZATION (0x8030) +#define STUN_ATTRIBUTE_OAUTH_ACCESS_TOKEN (0x0030) #define OAUTH_KID_SIZE (128) #define OAUTH_HASH_FUNC_SIZE (64) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 51a4663c..db3ac439 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -881,7 +881,7 @@ static int update_channel_lifetime(ts_ur_super_session *ss, ch_info* chn) /////////////// TURN /////////////////////////// -#define SKIP_ATTRIBUTES case STUN_ATTRIBUTE_PRIORITY: case STUN_ATTRIBUTE_FINGERPRINT: case STUN_ATTRIBUTE_MESSAGE_INTEGRITY: break; \ +#define SKIP_ATTRIBUTES case STUN_ATTRIBUTE_OAUTH_ACCESS_TOKEN: case STUN_ATTRIBUTE_PRIORITY: case STUN_ATTRIBUTE_FINGERPRINT: case STUN_ATTRIBUTE_MESSAGE_INTEGRITY: break; \ case STUN_ATTRIBUTE_USERNAME: case STUN_ATTRIBUTE_REALM: case STUN_ATTRIBUTE_NONCE: case STUN_ATTRIBUTE_ORIGIN: \ sar = stun_attr_get_next_str(ioa_network_buffer_data(in_buffer->nbh),\ ioa_network_buffer_get_size(in_buffer->nbh), sar); \ From 664be4d8e6a7413fb719ef635f476c88ea6e24e1 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 25 Sep 2014 02:12:40 +0000 Subject: [PATCH 204/805] working on oauth --- ChangeLog | 6 +++--- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 6 +++--- src/ns_turn_defs.h | 2 +- src/server/ns_turn_server.c | 27 +++++++++++---------------- 5 files changed, 19 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 99a72291..0b7dceae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 08/22/2014 Oleg Moskalenko -Version 4.1.2.2 'Vitari': +Version 4.1.3.2 'Vitari': + - oAuth security implementation. (TODO) - redis user key operation fixed. - redis, mysql and psql db operations fixed. - SHA-256 memory leak fixed. @@ -8,8 +9,7 @@ Version 4.1.2.2 'Vitari': - Move secondary download area to coturn.net. - TLS renegotiation DoS attack prevention implemented; - FQDN as relay-ip and listener-ip parameters (issue 6) - (patch provided by Iñaki Baz Castillo); - - oAuth security implementation. (TODO) + (patch provided by Iñaki Baz Castillo); 08/14/2014 Oleg Moskalenko Version 4.1.2.1 'Vitari': diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index cb9ca5e8..21e4f21d 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.1.2.2 +TURNVERSION=4.1.3.2 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 7e688f8a..9ddde605 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.1.2.2 +Version: 4.1.3.2 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,8 +294,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Thu Aug 22 2014 Oleg Moskalenko - - Sync to 4.1.2.2 +* Wed Sep 24 2014 Oleg Moskalenko + - Sync to 4.1.3.2 * Thu Aug 14 2014 Oleg Moskalenko - Sync to 4.1.2.1 * Tue Jul 29 2014 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 42a5b3a4..f3ac7368 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.1.2.2" +#define TURN_SERVER_VERSION "4.1.3.2" #define TURN_SERVER_VERSION_NAME "Vitari" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index db3ac439..8d64450b 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3308,29 +3308,24 @@ static int check_stun_auth(turn_turnserver *server, /* Password */ if(!(ss->hmackey_set) && (ss->pwd[0] == 0)) { - ur_string_map_value_type ukey = NULL; if(can_resume) { - ukey = (server->userkeycb)(server->id, server->ct, usname, realm, resume_processing_after_username_check, in_buffer, ss->id, postpone_reply); + (server->userkeycb)(server->id, server->ct, usname, realm, resume_processing_after_username_check, in_buffer, ss->id, postpone_reply); if(*postpone_reply) { return 0; } } /* we always return NULL for short-term credentials here */ - if(!ukey) { - /* 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; - } + /* 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; } - ns_bcopy(ukey,ss->hmackey,16); - ss->hmackey_set = 1; } /* Check integrity */ From 262394600488edc1942f7eebe84ac0d913980e91 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 25 Sep 2014 05:41:04 +0000 Subject: [PATCH 205/805] version bump --- ChangeLog | 2 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 ++-- src/ns_turn_defs.h | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0b7dceae..e7fe4935 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ 08/22/2014 Oleg Moskalenko -Version 4.1.3.2 'Vitari': +Version 4.2.1.1 'Monza': - oAuth security implementation. (TODO) - redis user key operation fixed. - redis, mysql and psql db operations fixed. diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 21e4f21d..cf368334 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.1.3.2 +TURNVERSION=4.2.1.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 9ddde605..bc61f5b6 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.1.3.2 +Version: 4.2.1.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -295,7 +295,7 @@ fi %changelog * Wed Sep 24 2014 Oleg Moskalenko - - Sync to 4.1.3.2 + - Sync to 4.2.1.1 * Thu Aug 14 2014 Oleg Moskalenko - Sync to 4.1.2.1 * Tue Jul 29 2014 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index f3ac7368..9e166ea8 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,8 +31,8 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.1.3.2" -#define TURN_SERVER_VERSION_NAME "Vitari" +#define TURN_SERVER_VERSION "4.2.1.1" +#define TURN_SERVER_VERSION_NAME "Monza" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" #if (defined(__unix__) || defined(unix)) && !defined(USG) From 91c596d2954b2d662493825e8383dd6bdc072cf7 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 25 Sep 2014 06:56:00 +0000 Subject: [PATCH 206/805] working on oauth --- src/apps/relay/netengine.c | 4 ++-- src/apps/relay/userdb.c | 9 ++++++--- src/apps/relay/userdb.h | 5 +++-- src/server/ns_turn_server.c | 24 +++++++++++++++--------- src/server/ns_turn_server.h | 4 ++-- src/server/ns_turn_session.h | 16 +++++++++------- 6 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index a3311381..b48e4dd6 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -386,7 +386,7 @@ static void auth_server_receive_message(struct bufferevent *bev, void *ptr) } } else { hmackey_t key; - if(get_user_key(am.username,am.realm,key,am.in_buffer.nbh)<0) { + if(get_user_key(&(am.oauth),am.username,am.realm,key,am.in_buffer.nbh)<0) { am.success = 0; } else { ns_bcopy(key,am.key,sizeof(hmackey_t)); @@ -768,7 +768,7 @@ static int handle_relay_message(relay_server_handle rs, struct message_to_relay static void handle_relay_auth_message(struct relay_server *rs, struct auth_message *am) { - am->resume_func(am->success, am->key, am->pwd, + am->resume_func(am->success, am->oauth, am->key, am->pwd, &(rs->server), am->ctxkey, &(am->in_buffer)); if (am->in_buffer.nbh) { ioa_network_buffer_delete(rs->ioa_eng, am->in_buffer.nbh); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index a00b58b3..6b62946a 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -396,10 +396,12 @@ static char *get_real_username(char *usname) } /* - * Long-term mechanism password retrieval + * Password retrieval */ -int get_user_key(u08bits *usname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh) +int get_user_key(int *oauth, u08bits *usname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh) { + UNUSED_ARG(oauth); + int ret = -1; if(turn_params.use_auth_secret_with_timestamp) { @@ -529,7 +531,7 @@ int get_user_pwd(u08bits *usname, st_password_t pwd) return ret; } -u08bits *start_user_check(turnserver_id id, turn_credential_type ct, u08bits *usname, u08bits *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, u64bits ctxkey, int *postpone_reply) +u08bits *start_user_check(turnserver_id id, turn_credential_type ct, int oauth, u08bits *usname, u08bits *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, u64bits ctxkey, int *postpone_reply) { *postpone_reply = 1; @@ -537,6 +539,7 @@ u08bits *start_user_check(turnserver_id id, turn_credential_type ct, u08bits *us ns_bzero(&am,sizeof(struct auth_message)); am.id = id; am.ct = ct; + am.oauth = oauth; STRCPY(am.username,usname); STRCPY(am.realm,realm); am.resume_func = resume; diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index 5932cbbe..80fe4b04 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -86,6 +86,7 @@ void update_o_to_realm(ur_string_map * o_to_realm_new); struct auth_message { turnserver_id id; turn_credential_type ct; + int oauth; u08bits username[STUN_MAX_USERNAME_SIZE + 1]; u08bits realm[STUN_MAX_REALM_SIZE + 1]; hmackey_t key; @@ -187,9 +188,9 @@ void add_to_secrets_list(secrets_list_t *sl, const char* elem); /////////// USER DB CHECK ////////////////// -int get_user_key(u08bits *uname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh); +int get_user_key(int *oauth, 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, u08bits *uname, u08bits *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, u64bits ctxkey, int *postpone_reply); +u08bits *start_user_check(turnserver_id id, turn_credential_type ct, int 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, u08bits *realm); void release_allocation_quota(u08bits *username, u08bits *realm); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 8d64450b..35f7f61a 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3094,7 +3094,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, 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, hmackey_t hmackey, st_password_t pwd, turn_turnserver *server, u64bits ctxkey, ioa_net_data *in_buffer) { if(server && in_buffer && in_buffer->nbh) { @@ -3106,6 +3106,7 @@ static void resume_processing_after_username_check(int success, hmackey_t hmack if(success) { ns_bcopy(hmackey,ss->hmackey,sizeof(hmackey_t)); ss->hmackey_set = 1; + ss->oauth = oauth; ns_bcopy(pwd,ss->pwd,sizeof(st_password_t)); } @@ -3260,14 +3261,19 @@ static int check_stun_auth(turn_turnserver *server, if(ss->username[0]) { if(strcmp((char*)ss->username,(char*)usname)) { - if(method == STUN_METHOD_ALLOCATE) { - *err_code = 437; - *reason = (const u08bits*)"Allocation mismatch: wrong credentials"; + if(ss->oauth) { + STRCPY(ss->username,usname); + set_username_hash(ss->client_socket,ss->username,(u08bits*)ss->realm_options.name); } else { - *err_code = 441; - *reason = (const u08bits*)"Wrong credentials"; + if(method == STUN_METHOD_ALLOCATE) { + *err_code = 437; + *reason = (const u08bits*)"Allocation mismatch: wrong credentials"; + } else { + *err_code = 441; + *reason = (const u08bits*)"Wrong credentials"; + } + return -1; } - return -1; } } else { STRCPY(ss->username,usname); @@ -3309,7 +3315,7 @@ static int check_stun_auth(turn_turnserver *server, /* Password */ if(!(ss->hmackey_set) && (ss->pwd[0] == 0)) { if(can_resume) { - (server->userkeycb)(server->id, server->ct, usname, realm, resume_processing_after_username_check, in_buffer, ss->id, postpone_reply); + (server->userkeycb)(server->id, server->ct, server->oauth, usname, realm, resume_processing_after_username_check, in_buffer, ss->id, postpone_reply); if(*postpone_reply) { return 0; } @@ -3351,7 +3357,7 @@ static int check_stun_auth(turn_turnserver *server, } if(can_resume) { - (server->userkeycb)(server->id, server->ct, usname, realm, resume_processing_after_username_check, in_buffer, ss->id, postpone_reply); + (server->userkeycb)(server->id, server->ct, server->oauth, usname, realm, resume_processing_after_username_check, in_buffer, ss->id, postpone_reply); if(*postpone_reply) { return 0; } diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index 360d0eac..6aee926a 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -90,8 +90,8 @@ typedef enum { struct _turn_turnserver; typedef struct _turn_turnserver turn_turnserver; -typedef void (*get_username_resume_cb)(int success, hmackey_t hmackey, st_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, u08bits *uname, u08bits *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, u64bits ctxkey, int *postpone_reply); +typedef void (*get_username_resume_cb)(int success, int oauth, hmackey_t hmackey, st_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 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, u08bits *realm); typedef void (*release_allocation_quota_cb)(u08bits *username, 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); diff --git a/src/server/ns_turn_session.h b/src/server/ns_turn_session.h index 8a85477e..f8510794 100644 --- a/src/server/ns_turn_session.h +++ b/src/server/ns_turn_session.h @@ -72,16 +72,22 @@ struct _ts_ur_super_session { ioa_socket_handle client_socket; allocation alloc; ioa_timer_handle to_be_allocated_timeout_ev; + int enforce_fingerprints; + int is_tcp_relay; + int to_be_closed; + /* Auth */ u08bits nonce[NONCE_MAX_SIZE]; turn_time_t nonce_expiration_time; u08bits username[STUN_MAX_USERNAME_SIZE+1]; hmackey_t hmackey; int hmackey_set; st_password_t pwd; - int enforce_fingerprints; - int is_tcp_relay; - int to_be_closed; int quota_used; + int oauth; + /* Realm */ + realm_options_t realm_options; + int origin_set; + s08bits origin[STUN_MAX_ORIGIN_SIZE + 1]; /* Stats */ u32bits received_packets; u32bits sent_packets; @@ -99,10 +105,6 @@ struct _ts_ur_super_session { mobile_id_t mobile_id; mobile_id_t old_mobile_id; char s_mobile_id[33]; - /* Realm */ - realm_options_t realm_options; - int origin_set; - s08bits origin[STUN_MAX_ORIGIN_SIZE + 1]; /* Bandwidth */ band_limit_t bps; }; From 1b82b7ca9731cf1ab29515b6bfa1a3c667dcb778 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 25 Sep 2014 23:12:45 +0000 Subject: [PATCH 207/805] oauth --- ChangeLog | 6 +-- src/apps/relay/netengine.c | 3 +- src/apps/relay/userdb.c | 103 +++++++++++++++++++++++++++++++++++-- src/apps/relay/userdb.h | 2 +- src/client/ns_turn_msg.c | 2 +- 5 files changed, 106 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index e7fe4935..e7bc1dd2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,15 +1,15 @@ 08/22/2014 Oleg Moskalenko Version 4.2.1.1 'Monza': - oAuth security implementation. (TODO) + - TLS renegotiation DoS attack prevention implemented; + - FQDN as relay-ip and listener-ip parameters (issue 6) + (patch provided by Iñaki Baz Castillo); - redis user key operation fixed. - redis, mysql and psql db operations fixed. - SHA-256 memory leak fixed. - Mobility ticket retransmission fixed. - Move debian package from SVN to GIT. - Move secondary download area to coturn.net. - - TLS renegotiation DoS attack prevention implemented; - - FQDN as relay-ip and listener-ip parameters (issue 6) - (patch provided by Iñaki Baz Castillo); 08/14/2014 Oleg Moskalenko Version 4.1.2.1 'Vitari': diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index b48e4dd6..52312de8 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -378,6 +378,7 @@ static void auth_server_receive_message(struct bufferevent *bev, void *ptr) if(am.ct == TURN_CREDENTIALS_SHORT_TERM) { st_password_t pwd; + am.oauth = 0; if(get_user_pwd(am.username,pwd)<0) { am.success = 0; } else { @@ -386,7 +387,7 @@ static void auth_server_receive_message(struct bufferevent *bev, void *ptr) } } else { hmackey_t key; - if(get_user_key(&(am.oauth),am.username,am.realm,key,am.in_buffer.nbh)<0) { + if(get_user_key(am.oauth,&(am.oauth),am.username,am.realm,key,am.in_buffer.nbh)<0) { am.success = 0; } else { ns_bcopy(key,am.key,sizeof(hmackey_t)); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 6b62946a..6d0025cf 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -398,12 +398,107 @@ static char *get_real_username(char *usname) /* * Password retrieval */ -int get_user_key(int *oauth, u08bits *usname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh) +int get_user_key(int in_oauth, int *out_oauth, u08bits *usname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh) { - UNUSED_ARG(oauth); - int ret = -1; + if(in_oauth && out_oauth && usname && usname[0] && realm && realm[0]) { + + *out_oauth = 0; + + stun_attr_ref sar = stun_attr_get_first_by_type_str(ioa_network_buffer_data(nbh), + ioa_network_buffer_get_size(nbh), + STUN_ATTRIBUTE_OAUTH_ACCESS_TOKEN); + if(sar) { + + int len = stun_attr_get_len(sar); + const u08bits *value = stun_attr_get_value(sar); + + *out_oauth = 1; + + if(len>0 && value) { + + turn_dbdriver_t * dbd = get_dbdriver(); + + if (dbd && dbd->get_oauth_key) { + + oauth_key_data_raw rawKey; + ns_bzero(&rawKey,sizeof(rawKey)); + + int gres = (*(dbd->get_oauth_key))(usname,&rawKey); + if(gres<0) + return ret; + + oauth_key_data okd; + ns_bzero(&okd,sizeof(okd)); + + convert_oauth_key_data_raw(&rawKey, &okd); + + char err_msg[1025] = "\0"; + size_t err_msg_size = sizeof(err_msg) - 1; + + oauth_key okey; + ns_bzero(&okey,sizeof(okey)); + + if (convert_oauth_key_data(&okd, &okey, err_msg, err_msg_size) < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s\n", err_msg); + return -1; + } + + oauth_token dot; + ns_bzero((&dot),sizeof(dot)); + + encoded_oauth_token etoken; + ns_bzero(&etoken,sizeof(etoken)); + + if((size_t)len > sizeof(etoken.token)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Encoded oAuth token is too large\n"); + return -1; + } + ns_bcopy(value,etoken.token,(size_t)len); + etoken.size = (size_t)len; + + if (decode_oauth_token((const u08bits *) turn_params.oauth_server_name, &etoken,&okey, &dot) < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot decode oauth token\n"); + return -1; + } + + switch(dot.enc_block.key_length) { + case SHA1SIZEBYTES: + if(turn_params.shatype != SHATYPE_SHA1) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(1): %d\n",(int)dot.enc_block.key_length); + return -1; + } + break; + case SHA256SIZEBYTES: + if(turn_params.shatype != SHATYPE_SHA256) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(2): %d\n",(int)dot.enc_block.key_length); + return -1; + } + break; + default: + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(3): %d\n",(int)dot.enc_block.key_length); + return -1; + }; + + st_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), + dot.enc_block.mac_key, + pwdtmp, + turn_params.shatype,NULL)>0) { + ns_bcopy(dot.enc_block.mac_key,&key,dot.enc_block.key_length); + ret = 0; + } + } + } + } + } + + if(out_oauth && *out_oauth) + return ret; + if(turn_params.use_auth_secret_with_timestamp) { turn_time_t ctime = (turn_time_t) time(NULL); @@ -510,7 +605,7 @@ int get_user_key(int *oauth, u08bits *usname, u08bits *realm, hmackey_t key, ioa turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->get_user_key) { - ret = (*dbd->get_user_key)(usname, realm, key); + ret = (*(dbd->get_user_key))(usname, realm, key); } return ret; diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index 80fe4b04..784835bc 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -188,7 +188,7 @@ void add_to_secrets_list(secrets_list_t *sl, const char* elem); /////////// USER DB CHECK ////////////////// -int get_user_key(int *oauth, u08bits *uname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh); +int get_user_key(int in_oauth, int *out_oauth, 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 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, u08bits *realm); diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 25f8825e..cdac6781 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1550,7 +1550,7 @@ int stun_check_message_integrity_by_key_str(turn_credential_type ct, u08bits *bu if(bcmp(old_hmac,new_hmac,shasize)) return 0; - return 1; + return +1; } /* From 064aca0fa7a199274c67f5c62b990649a9efcee9 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 26 Sep 2014 00:31:20 +0000 Subject: [PATCH 208/805] oauth --- README.turnutils | 2 ++ src/apps/uclient/mainuclient.c | 11 ++++++++++- src/apps/uclient/uclient.h | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/README.turnutils b/README.turnutils index b76a6eb8..516219af 100644 --- a/README.turnutils +++ b/README.turnutils @@ -117,6 +117,8 @@ Flags: -Z Dual allocation (SSODA draft support). +-J Use oAuth. + Options with required values: -l Message length (Default: 100 Bytes). diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 37566b95..c2bc91b9 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -97,6 +97,11 @@ band_limit_t bps = 0; int dual_allocation = 0; +int oauth = 0; +oauth_key_data_raw okdr = { + "north","Y2FybGVvbg==",0,0,"SHA-256","AES-256-CBC","","HMAC-SHA-256-128","" +}; + //////////////// local definitions ///////////////// static char Usage[] = @@ -130,6 +135,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.\n" "Options:\n" " -l Message length (Default: 100 Bytes).\n" " -i Certificate file (for secure connections only, optional).\n" @@ -204,8 +210,11 @@ int main(int argc, char **argv) ns_bzero(local_addr, sizeof(local_addr)); - while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:ZvsyhcxXgtTSAPDNOUHMRIGB")) != -1) { + while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:ZvsyhcxXgtTSAPDNOUHMRIGBJ")) != -1) { switch (c){ + case 'J': + oauth = 1; + break; case 'a': bps = (band_limit_t)atol(optarg); break; diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index ab56bf8b..fab59208 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -86,6 +86,9 @@ extern int dual_allocation; extern char origin[STUN_MAX_ORIGIN_SIZE+1]; +extern int oauth; +extern oauth_key_data_raw okdr; + #define is_TCP_relay() (relay_transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) void start_mclient(const char *remote_address, int port, From 6aa1af102c751fc25e2029686a1effd8324619db Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 26 Sep 2014 06:51:04 +0000 Subject: [PATCH 209/805] working on oauth --- ChangeLog | 9 +++++- src/apps/uclient/mainuclient.c | 47 ++++++++++++++++++++++++++-- src/apps/uclient/session.h | 3 ++ src/apps/uclient/startuclient.c | 35 +++------------------ src/apps/uclient/uclient.c | 55 ++++++++++++++++++++++++--------- src/apps/uclient/uclient.h | 4 ++- src/client/ns_turn_msg.c | 17 ++++++---- src/client/ns_turn_msg.h | 1 + src/client/ns_turn_msg_defs.h | 1 + 9 files changed, 117 insertions(+), 55 deletions(-) diff --git a/ChangeLog b/ChangeLog index e7bc1dd2..34e0a330 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,13 @@ 08/22/2014 Oleg Moskalenko Version 4.2.1.1 'Monza': - - oAuth security implementation. (TODO) + - oAuth security implementation: + TODO: + - clients's check_integrity method(); + - security dialog; + - authorization process - test; + - access-token must be cached and included only in ALLOCATE and REFRESH; + - token timeout; + - kid timeout; - TLS renegotiation DoS attack prevention implemented; - FQDN as relay-ip and listener-ip parameters (issue 6) (patch provided by Iñaki Baz Castillo); diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index c2bc91b9..ddc81de0 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -46,6 +46,7 @@ #include #include +#include /////////////// extern definitions ///////////////////// @@ -98,7 +99,10 @@ band_limit_t bps = 0; int dual_allocation = 0; int oauth = 0; -oauth_key_data_raw okdr = { +oauth_key okey; +oauth_token otoken; + +static oauth_key_data_raw okdr = { "north","Y2FybGVvbg==",0,0,"SHA-256","AES-256-CBC","","HMAC-SHA-256-128","" }; @@ -212,8 +216,26 @@ int main(int argc, char **argv) while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:ZvsyhcxXgtTSAPDNOUHMRIGBJ")) != -1) { switch (c){ - case 'J': + case 'J': { + oauth = 1; + + if(use_short_term) { + fprintf(stderr,"Short-term mechanism cannot be used together with oAuth.\n"); + exit(-1); + } + + oauth_key_data okd; + convert_oauth_key_data_raw(&okdr, &okd); + + char err_msg[1025] = "\0"; + size_t err_msg_size = sizeof(err_msg) - 1; + + if (convert_oauth_key_data(&okd, &okey, err_msg, err_msg_size) < 0) { + fprintf(stderr, "%s\n", err_msg); + exit(-1); + } + } break; case 'a': bps = (band_limit_t)atol(optarg); @@ -271,6 +293,10 @@ int main(int argc, char **argv) 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': @@ -375,6 +401,23 @@ int main(int argc, char **argv) } } + if(oauth) { + + otoken.enc_block.lifetime = 0; + otoken.enc_block.timestamp = 0; + + switch(shatype) { + case SHATYPE_SHA256: + otoken.enc_block.key_length = 32; + break; + default: + otoken.enc_block.key_length = 20; + break; + }; + + RAND_bytes((unsigned char *)(otoken.enc_block.mac_key), otoken.enc_block.key_length); + } + if(g_use_auth_secret_with_timestamp) { if(use_short_term) { diff --git a/src/apps/uclient/session.h b/src/apps/uclient/session.h index 5635c529..b7f98e2b 100644 --- a/src/apps/uclient/session.h +++ b/src/apps/uclient/session.h @@ -80,6 +80,9 @@ typedef struct { int broken; u08bits nonce[STUN_MAX_NONCE_SIZE+1]; u08bits realm[STUN_MAX_REALM_SIZE+1]; + /* oAuth */ + int oauth; + u08bits server_name[STUN_MAX_SERVER_NAME_SIZE+1]; /* RFC 6062 */ app_tcp_conn_info **tcp_conn; size_t tcp_conn_number; diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index efb2aca7..b725784d 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -433,13 +433,8 @@ static int clnet_allocate(int verbose, allocate_finished = 1; if(clnet_info->nonce[0] || use_short_term) { - SHATYPE sht = clnet_info->shatype; - if(stun_check_message_integrity_str(get_turn_credentials_type(), - message.buf, (size_t)(message.len), g_uname, - clnet_info->realm, g_upwd, sht)<1) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in allocate message received from server\n"); + if(check_integrity(clnet_info, &message)<0) return -1; - } } if (verbose) { @@ -524,13 +519,8 @@ static int clnet_allocate(int verbose, if(err_code == 300) { if(clnet_info->nonce[0] || use_short_term) { - SHATYPE sht = clnet_info->shatype; - if(stun_check_message_integrity_str(get_turn_credentials_type(), - message.buf, (size_t)(message.len), g_uname, - clnet_info->realm, g_upwd, sht)<1) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in allocate message received from server\n"); + if(check_integrity(clnet_info, &message)<0) return -1; - } } ioa_addr alternate_server; @@ -795,13 +785,8 @@ static int turn_channel_bind(int verbose, uint16_t *chn, cb_received = 1; if(clnet_info->nonce[0] || use_short_term) { - SHATYPE sht = clnet_info->shatype; - if(stun_check_message_integrity_str(get_turn_credentials_type(), - message.buf, (size_t)(message.len), g_uname, - clnet_info->realm, g_upwd, sht)<1) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in channel bind message received from server\n"); + if(check_integrity(clnet_info, &message)<0) return -1; - } } if (verbose) { @@ -909,13 +894,8 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, cp_received = 1; if(clnet_info->nonce[0] || use_short_term) { - SHATYPE sht = clnet_info->shatype; - if(stun_check_message_integrity_str(get_turn_credentials_type(), - message.buf, (size_t)(message.len), g_uname, - clnet_info->realm, g_upwd, sht)<1) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in create permission message received from server\n"); + if(check_integrity(clnet_info, &message)<0) return -1; - } } if (verbose) { @@ -1495,13 +1475,8 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a if (stun_is_success_response(&message)) { if(clnet_info->nonce[0] || use_short_term) { - SHATYPE sht = clnet_info->shatype; - if(stun_check_message_integrity_str(get_turn_credentials_type(), - message.buf, (size_t)(message.len), g_uname, - clnet_info->realm, g_upwd, sht)<1) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in connect bind message received from server\n"); + if(check_integrity(clnet_info, &message)<0) return -1; - } } if(stun_get_method(&message)!=STUN_METHOD_CONNECTION_BIND) diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 77cc57a8..7292e55f 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -38,6 +38,7 @@ #include #include +#include static int verbose_packets=0; @@ -510,13 +511,9 @@ 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) { - SHATYPE sht = elem->pinfo.shatype; - if(stun_check_message_integrity_str(get_turn_credentials_type(), - elem->in_buffer.buf, (size_t)(elem->in_buffer.len), g_uname, - elem->pinfo.realm, g_upwd, sht)<1) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in indication message 0x%x received from server\n",(unsigned int)stun_get_method(&(elem->in_buffer))); + + if(check_integrity(&(elem->pinfo), &(elem->in_buffer))<0) return -1; - } } uint16_t method = stun_get_method(&elem->in_buffer); @@ -569,13 +566,8 @@ 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) { - SHATYPE sht = elem->pinfo.shatype; - if(stun_check_message_integrity_str(get_turn_credentials_type(), - elem->in_buffer.buf, (size_t)(elem->in_buffer.len), g_uname, - elem->pinfo.realm, g_upwd, sht)<1) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in success message 0x%x received from server\n",(unsigned int)stun_get_method(&(elem->in_buffer))); + if(check_integrity(&(elem->pinfo), &(elem->in_buffer))<0) return -1; - } } if(is_TCP_relay() && (stun_get_method(&(elem->in_buffer)) == STUN_METHOD_CONNECT)) { @@ -1437,15 +1429,48 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) return -1; } } else if(clnet_info->nonce[0]) { - if(stun_attr_add_integrity_by_user_str(message->buf, (size_t*)&(message->len), g_uname, + + if(oauth && clnet_info->oauth) { + encoded_oauth_token etoken; + u08bits nonce[12]; + RAND_bytes((unsigned char*)nonce,12); + if(encode_oauth_token(clnet_info->server_name, &etoken, &okey, &otoken, nonce)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot encode token\n"); + return -1; + } + stun_attr_add_str(message->buf, (size_t*)&(message->len), STUN_ATTRIBUTE_OAUTH_ACCESS_TOKEN, + (const u08bits*)etoken.token, (int)etoken.size); + + hmackey_t key; + ns_bcopy(otoken.enc_block.mac_key,key,otoken.enc_block.key_length); + if(stun_attr_add_integrity_by_key_str(message->buf, (size_t*)&(message->len), g_uname, + clnet_info->realm, key, clnet_info->nonce, clnet_info->shatype)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot add integrity to the message\n"); + return -1; + } + } else { + if(stun_attr_add_integrity_by_user_str(message->buf, (size_t*)&(message->len), g_uname, clnet_info->realm, g_upwd, clnet_info->nonce, clnet_info->shatype)<0) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot add integrity to the message\n"); - return -1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot add integrity to the message\n"); + return -1; + } } } return 0; } +int check_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) +{ + SHATYPE sht = clnet_info->shatype; + if(stun_check_message_integrity_str(get_turn_credentials_type(), + message->buf, (size_t)(message->len), g_uname, + clnet_info->realm, g_upwd, sht)<1) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in a message received from server\n"); + return -1; + } + return 0; +} + /////////////////////////////////////////// diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index fab59208..ffb20cbd 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -87,7 +87,8 @@ extern int dual_allocation; extern char origin[STUN_MAX_ORIGIN_SIZE+1]; extern int oauth; -extern oauth_key_data_raw okdr; +extern oauth_key okey; +extern oauth_token otoken; #define is_TCP_relay() (relay_transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) @@ -103,6 +104,7 @@ void client_input_handler(evutil_socket_t fd, short what, void* arg); turn_credential_type get_turn_credentials_type(void); int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message); +int check_integrity(app_ur_conn_info *clnet_info, stun_buffer *message); void recalculate_restapi_hmac(void); diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index cdac6781..bda8e477 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1449,13 +1449,8 @@ int stun_attr_add_integrity_str(turn_credential_type ct, u08bits *buf, size_t *l return 0; } -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_key_str(u08bits *buf, size_t *len, u08bits *uname, u08bits *realm, hmackey_t key, u08bits *nonce, SHATYPE shatype) { - hmackey_t key; - - if(stun_produce_integrity_key_str(uname, realm, upwd, key, shatype)<0) - return -1; - if(stun_attr_add_str(buf, len, STUN_ATTRIBUTE_USERNAME, uname, strlen((s08bits*)uname))<0) return -1; @@ -1469,6 +1464,16 @@ int stun_attr_add_integrity_by_user_str(u08bits *buf, size_t *len, u08bits *unam return stun_attr_add_integrity_str(TURN_CREDENTIALS_LONG_TERM, buf, len, key, p, shatype); } +int stun_attr_add_integrity_by_user_str(u08bits *buf, size_t *len, u08bits *uname, u08bits *realm, u08bits *upwd, u08bits *nonce, SHATYPE shatype) +{ + hmackey_t key; + + if(stun_produce_integrity_key_str(uname, realm, upwd, key, shatype)<0) + return -1; + + 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) { if(stun_attr_add_str(buf, len, STUN_ATTRIBUTE_USERNAME, uname, strlen((s08bits*)uname))<0) diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index f54c2354..e5f86dce 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -183,6 +183,7 @@ void print_bin_func(const char *name, size_t len, const void *s, const char *fun 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_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_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); size_t get_hmackey_size(SHATYPE shatype); diff --git a/src/client/ns_turn_msg_defs.h b/src/client/ns_turn_msg_defs.h index 11548456..cde11dd6 100644 --- a/src/client/ns_turn_msg_defs.h +++ b/src/client/ns_turn_msg_defs.h @@ -43,6 +43,7 @@ #define STUN_MAX_USERNAME_SIZE (513) #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 STUN_MAGIC_COOKIE (0x2112A442) From 87f1b413824e63129394a1e5784c78cf032f321a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 26 Sep 2014 07:02:20 +0000 Subject: [PATCH 210/805] oauth --- ChangeLog | 1 - src/apps/uclient/uclient.c | 21 ++++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 34e0a330..dfe5470f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,7 +2,6 @@ Version 4.2.1.1 'Monza': - oAuth security implementation: TODO: - - clients's check_integrity method(); - security dialog; - authorization process - test; - access-token must be cached and included only in ALLOCATE and REFRESH; diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 7292e55f..e40a8061 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1463,12 +1463,27 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) int check_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) { SHATYPE sht = clnet_info->shatype; - if(stun_check_message_integrity_str(get_turn_credentials_type(), + + if(oauth && clnet_info->oauth) { + + hmackey_t key; + st_password_t pwd; + + ns_bcopy(otoken.enc_block.mac_key,key,otoken.enc_block.key_length); + + return stun_check_message_integrity_by_key_str(get_turn_credentials_type(), + message->buf, (size_t)(message->len), key, pwd, sht, NULL); + + } else { + + if(stun_check_message_integrity_str(get_turn_credentials_type(), message->buf, (size_t)(message->len), g_uname, clnet_info->realm, g_upwd, sht)<1) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in a message received from server\n"); - return -1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Wrong integrity in a message received from server\n"); + return -1; + } } + return 0; } From a4c47215952d60da4410038c00ecf39c72444df3 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 26 Sep 2014 23:51:40 +0000 Subject: [PATCH 211/805] dialog done --- ChangeLog | 1 - src/apps/relay/dbdrivers/dbd_redis.c | 4 ++-- src/apps/uclient/startuclient.c | 15 ++++++++++----- src/apps/uclient/uclient.c | 15 +++++++++++++-- src/client++/TurnMsgLib.h | 7 ++++--- src/client/ns_turn_msg.c | 27 +++++++++++++++++++++++---- src/client/ns_turn_msg.h | 2 +- 7 files changed, 53 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index dfe5470f..3e730e18 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,7 +2,6 @@ Version 4.2.1.1 'Monza': - oAuth security implementation: TODO: - - security dialog; - authorization process - test; - access-token must be cached and included only in ALLOCATE and REFRESH; - token timeout; diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index d30633ad..b50bc6bf 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -508,7 +508,7 @@ static int redis_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { 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 { + } else if(reply->elements > 1) { size_t i; for (i = 0; i < (reply->elements)/2; ++i) { char *kw = reply->element[2*i]->str; @@ -533,9 +533,9 @@ static int redis_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { } } } + ret = 0; } turnFreeRedisReply(reply); - ret = 0; } } return ret; diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index b725784d..003f51aa 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -501,7 +501,8 @@ static int clnet_allocate(int verbose, } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, &err_code,err_msg,sizeof(err_msg), - clnet_info->realm,clnet_info->nonce)) { + clnet_info->realm,clnet_info->nonce, + clnet_info->server_name, &(clnet_info->oauth))) { if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { clnet_info->shatype = SHATYPE_SHA256; recalculate_restapi_hmac(); @@ -697,7 +698,8 @@ static int clnet_allocate(int verbose, } } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, &err_code,err_msg,sizeof(err_msg), - clnet_info->realm,clnet_info->nonce)) { + clnet_info->realm,clnet_info->nonce, + clnet_info->server_name, &(clnet_info->oauth))) { if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { clnet_info->shatype = SHATYPE_SHA256; recalculate_restapi_hmac(); @@ -795,7 +797,8 @@ static int turn_channel_bind(int verbose, uint16_t *chn, } } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, &err_code,err_msg,sizeof(err_msg), - clnet_info->realm,clnet_info->nonce)) { + clnet_info->realm,clnet_info->nonce, + clnet_info->server_name, &(clnet_info->oauth))) { if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { clnet_info->shatype = SHATYPE_SHA256; recalculate_restapi_hmac(); @@ -903,7 +906,8 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, } } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, &err_code,err_msg,sizeof(err_msg), - clnet_info->realm,clnet_info->nonce)) { + clnet_info->realm,clnet_info->nonce, + clnet_info->server_name, &(clnet_info->oauth))) { if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { clnet_info->shatype = SHATYPE_SHA256; recalculate_restapi_hmac(); @@ -1488,7 +1492,8 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a atc->tcp_data_bound = 1; } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, &err_code,err_msg,sizeof(err_msg), - clnet_info->realm,clnet_info->nonce)) { + clnet_info->realm,clnet_info->nonce, + clnet_info->server_name, &(clnet_info->oauth))) { if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { clnet_info->shatype = SHATYPE_SHA256; recalculate_restapi_hmac(); diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index e40a8061..889e1825 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -587,7 +587,8 @@ static int client_read(app_ur_session *elem, int is_tcp_data, app_tcp_conn_info return rc; } else if (stun_is_challenge_response_str(elem->in_buffer.buf, (size_t)elem->in_buffer.len, &err_code,err_msg,sizeof(err_msg), - clnet_info->realm,clnet_info->nonce)) { + clnet_info->realm,clnet_info->nonce, + clnet_info->server_name, &(clnet_info->oauth))) { if(err_code == SHA_TOO_WEAK_ERROR_CODE && (elem->pinfo.shatype == SHATYPE_SHA1)) { elem->pinfo.shatype = SHATYPE_SHA256; recalculate_restapi_hmac(); @@ -1443,11 +1444,21 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) hmackey_t key; ns_bcopy(otoken.enc_block.mac_key,key,otoken.enc_block.key_length); - if(stun_attr_add_integrity_by_key_str(message->buf, (size_t*)&(message->len), g_uname, + if(stun_attr_add_integrity_by_key_str(message->buf, (size_t*)&(message->len), (u08bits*)okey.kid, clnet_info->realm, key, clnet_info->nonce, clnet_info->shatype)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot add integrity to the message\n"); return -1; } + + //self-test: + { + st_password_t pwd; + if(stun_check_message_integrity_by_key_str(get_turn_credentials_type(), + message->buf, (size_t)(message->len), key, pwd, clnet_info->shatype, NULL)<1) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR," Self-test of integrity does not comple correctly !\n"); + return -1; + } + } } else { if(stun_attr_add_integrity_by_user_str(message->buf, (size_t*)&(message->len), g_uname, clnet_info->realm, g_upwd, clnet_info->nonce, clnet_info->shatype)<0) { diff --git a/src/client++/TurnMsgLib.h b/src/client++/TurnMsgLib.h index b5b46abb..008bbc05 100644 --- a/src/client++/TurnMsgLib.h +++ b/src/client++/TurnMsgLib.h @@ -665,8 +665,9 @@ public: */ static bool isChallengeResponse(const u08bits* buf, size_t sz, int &err_code, u08bits *err_msg, size_t err_msg_size, - u08bits *realm, u08bits *nonce) { - return stun_is_challenge_response_str(buf, sz, &err_code, err_msg, err_msg_size, realm, nonce); + u08bits *realm, u08bits *nonce, + u08bits *server_name, int *oauth) { + return stun_is_challenge_response_str(buf, sz, &err_code, err_msg, err_msg_size, realm, nonce, server_name, oauth); } /** @@ -970,7 +971,7 @@ public: size_t err_msg_size=sizeof(err_msg); u08bits srealm[0xFFFF]; u08bits snonce[0xFFFF]; - ret = stun_is_challenge_response_str(_buffer, _sz, &err_code, err_msg, err_msg_size, srealm, snonce); + ret = stun_is_challenge_response_str(_buffer, _sz, &err_code, err_msg, err_msg_size, srealm, snonce, NULL, NULL); if(ret) { realm = (char*)srealm; nonce = (char*)snonce; diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index bda8e477..f588ed8a 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -332,7 +332,7 @@ int stun_is_error_response_str(const u08bits* buf, size_t len, int *err_code, u0 } int stun_is_challenge_response_str(const u08bits* buf, size_t len, int *err_code, u08bits *err_msg, size_t err_msg_size, - u08bits *realm, u08bits *nonce) + u08bits *realm, u08bits *nonce, u08bits *server_name, int *oauth) { int ret = stun_is_error_response_str(buf, len, err_code, err_msg, err_msg_size); @@ -345,6 +345,25 @@ int stun_is_challenge_response_str(const u08bits* buf, size_t len, int *err_code size_t vlen = (size_t)stun_attr_get_len(sar); ns_bcopy(value,realm,vlen); realm[vlen]=0; + + { + stun_attr_ref sar = stun_attr_get_first_by_type_str(buf,len,STUN_ATTRIBUTE_THIRD_PARTY_AUTHORIZATION); + if(sar) { + const u08bits *value = stun_attr_get_value(sar); + if(value) { + size_t vlen = (size_t)stun_attr_get_len(sar); + if(vlen>0) { + if(server_name) { + ns_bcopy(value,server_name,vlen); + } + if(oauth) { + *oauth = 1; + } + } + } + } + } + sar = stun_attr_get_first_by_type_str(buf,len,STUN_ATTRIBUTE_NONCE); if(sar) { value = stun_attr_get_value(sar); @@ -1781,7 +1800,7 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er if(err_msg) { snprintf(err_msg,err_msg_size,"AS-RS key is not defined"); } - OAUTH_ERROR("AS-RS key is not defined"); + OAUTH_ERROR("AS-RS key is not defined\n"); return -1; } if(!(oakd->auth_key_size)) { @@ -1803,7 +1822,7 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er if(err_msg) { snprintf(err_msg,err_msg_size,"KID is not defined"); } - OAUTH_ERROR("KID is not defined"); + OAUTH_ERROR("KID is not defined\n"); return -1; } @@ -1833,7 +1852,7 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er if(err_msg) { snprintf(err_msg,err_msg_size,"Wrong HKDF hash function algorithm: %s",oakd->hkdf_hash_func); } - OAUTH_ERROR("Wrong HKDF hash function algorithm: %s",oakd->hkdf_hash_func); + OAUTH_ERROR("Wrong HKDF hash function algorithm: %s\n",oakd->hkdf_hash_func); return -1; } diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index e5f86dce..d756ad06 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -116,7 +116,7 @@ int stun_is_command_message_offset_str(const u08bits* buf, size_t blen, int offs int stun_is_request_str(const u08bits* buf, size_t len); int stun_is_success_response_str(const u08bits* buf, size_t len); int stun_is_error_response_str(const u08bits* buf, size_t len, int *err_code, u08bits *err_msg, size_t err_msg_size); -int stun_is_challenge_response_str(const u08bits* buf, size_t len, int *err_code, u08bits *err_msg, size_t err_msg_size, u08bits *realm, u08bits *nonce); +int stun_is_challenge_response_str(const u08bits* buf, size_t len, int *err_code, u08bits *err_msg, size_t err_msg_size, u08bits *realm, u08bits *nonce, u08bits *server_name, int *oauth); int stun_is_response_str(const u08bits* buf, size_t len); int stun_is_indication_str(const u08bits* buf, size_t len); u16bits stun_get_method_str(const u08bits *buf, size_t len); From a04c9a0b4f59cff1058b7d78694b0d693c5ce76c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 27 Sep 2014 02:13:07 +0000 Subject: [PATCH 212/805] oauth auth fixed --- ChangeLog | 1 - src/apps/relay/userdb.c | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3e730e18..13986234 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,7 +2,6 @@ Version 4.2.1.1 'Monza': - oAuth security implementation: TODO: - - authorization process - test; - access-token must be cached and included only in ALLOCATE and REFRESH; - token timeout; - kid timeout; diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 6d0025cf..8239aa8a 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -488,7 +488,7 @@ int get_user_key(int in_oauth, int *out_oauth, u08bits *usname, u08bits *realm, dot.enc_block.mac_key, pwdtmp, turn_params.shatype,NULL)>0) { - ns_bcopy(dot.enc_block.mac_key,&key,dot.enc_block.key_length); + ns_bcopy(dot.enc_block.mac_key,key,dot.enc_block.key_length); ret = 0; } } @@ -496,8 +496,9 @@ int get_user_key(int in_oauth, int *out_oauth, u08bits *usname, u08bits *realm, } } - if(out_oauth && *out_oauth) + if(out_oauth && *out_oauth) { return ret; + } if(turn_params.use_auth_secret_with_timestamp) { From bb8ccd8a91259341c3ae8d43cbab117b8e25ec54 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 27 Sep 2014 05:45:35 +0000 Subject: [PATCH 213/805] oauth support added to DB scripts --- .../scripts/longtermsecuredb/secure_relay_with_db_mongo.sh | 3 ++- .../scripts/longtermsecuredb/secure_relay_with_db_mysql.sh | 3 ++- .../longtermsecuredb/secure_relay_with_db_mysql_ssl.sh | 3 ++- .../scripts/longtermsecuredb/secure_relay_with_db_psql.sh | 5 +++-- .../scripts/longtermsecuredb/secure_relay_with_db_redis.sh | 3 ++- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 2 +- man/man1/turnutils.1 | 6 +++++- 8 files changed, 18 insertions(+), 9 deletions(-) diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh index bf8c1a4d..c5b959fd 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh @@ -21,6 +21,7 @@ # 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 # Other parameters (config file name, etc) are default. if [ -d examples ] ; then @@ -30,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 --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 --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 --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 --mongo-userdb="mongodb://localhost/coturn" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 --oauth $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh index b71ef9bb..198f7c6e 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh @@ -22,6 +22,7 @@ # 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 # Other parameters (config file name, etc) are default. if [ -d examples ] ; then @@ -31,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 $@ +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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh index 7d3ec658..773020a4 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh @@ -23,6 +23,7 @@ # 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 # Other parameters (config file name, etc) are default. if [ -d examples ] ; then @@ -32,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 $@ +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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh index 741ab701..86949285 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh @@ -22,6 +22,7 @@ # 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 # Other parameters (config file name, etc) are default. if [ -d examples ] ; then @@ -31,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 $@ +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 $@ # 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 $@ +# 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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh index 905a875f..319a2442 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh @@ -25,6 +25,7 @@ # 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 # Other parameters (config file name, etc) are default. if [ -d examples ] ; then @@ -34,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" -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 --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 $@ +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 --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 $@ diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index f1dd07f6..2b020eea 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "22 September 2014" "" "" +.TH TURN 1 "26 September 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 23271dcb..ca18f0d4 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "22 September 2014" "" "" +.TH TURN 1 "26 September 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index ad2cd4ad..1aec62aa 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "22 September 2014" "" "" +.TH TURN 1 "26 September 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -177,6 +177,10 @@ Random disconnect after a few initial packets. Dual allocation (SSODA draft support). .TP .B +\fB\-J\fP +Use oAuth. +.TP +.B Options with required values: .TP .B From 76b5527c33dbd0ef6b13b34892e490acccff8903 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 27 Sep 2014 05:55:51 +0000 Subject: [PATCH 214/805] uclent help fixed. --- README.turnutils | 2 +- man/man1/turnutils.1 | 2 +- src/apps/uclient/mainuclient.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.turnutils b/README.turnutils index 516219af..618800b4 100644 --- a/README.turnutils +++ b/README.turnutils @@ -117,7 +117,7 @@ Flags: -Z Dual allocation (SSODA draft support). --J Use oAuth. +-J Use oAuth with default test key kid='north'. Options with required values: diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 1aec62aa..179fbf7c 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -178,7 +178,7 @@ Dual allocation (SSODA draft support). .TP .B \fB\-J\fP -Use oAuth. +Use oAuth with default test key kid='north'. .TP .B Options with required values: diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index ddc81de0..3efc1f89 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -139,7 +139,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.\n" + " -J Use oAuth with default test key kid='north'.\n" "Options:\n" " -l Message length (Default: 100 Bytes).\n" " -i Certificate file (for secure connections only, optional).\n" From 0cace2dceae2b021378e6d0eae11bb1d913b3707 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 27 Sep 2014 06:20:17 +0000 Subject: [PATCH 215/805] working on oauth --- src/apps/relay/netengine.c | 7 ++++--- src/apps/relay/userdb.c | 7 +++---- src/apps/relay/userdb.h | 5 +++-- src/server/ns_turn_server.c | 4 ++-- src/server/ns_turn_server.h | 2 +- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 52312de8..829fff98 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -378,7 +378,8 @@ static void auth_server_receive_message(struct bufferevent *bev, void *ptr) if(am.ct == TURN_CREDENTIALS_SHORT_TERM) { st_password_t pwd; - am.oauth = 0; + am.in_oauth = 0; + am.out_oauth = 0; if(get_user_pwd(am.username,pwd)<0) { am.success = 0; } else { @@ -387,7 +388,7 @@ static void auth_server_receive_message(struct bufferevent *bev, void *ptr) } } else { hmackey_t key; - if(get_user_key(am.oauth,&(am.oauth),am.username,am.realm,key,am.in_buffer.nbh)<0) { + if(get_user_key(am.in_oauth,&(am.out_oauth),am.username,am.realm,key,am.in_buffer.nbh)<0) { am.success = 0; } else { ns_bcopy(key,am.key,sizeof(hmackey_t)); @@ -769,7 +770,7 @@ static int handle_relay_message(relay_server_handle rs, struct message_to_relay static void handle_relay_auth_message(struct relay_server *rs, struct auth_message *am) { - am->resume_func(am->success, am->oauth, am->key, am->pwd, + am->resume_func(am->success, am->out_oauth, am->key, am->pwd, &(rs->server), am->ctxkey, &(am->in_buffer)); if (am->in_buffer.nbh) { ioa_network_buffer_delete(rs->ioa_eng, am->in_buffer.nbh); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 8239aa8a..30ff57fa 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -404,8 +404,6 @@ int get_user_key(int in_oauth, int *out_oauth, u08bits *usname, u08bits *realm, if(in_oauth && out_oauth && usname && usname[0] && realm && realm[0]) { - *out_oauth = 0; - stun_attr_ref sar = stun_attr_get_first_by_type_str(ioa_network_buffer_data(nbh), ioa_network_buffer_get_size(nbh), STUN_ATTRIBUTE_OAUTH_ACCESS_TOKEN); @@ -627,7 +625,7 @@ int get_user_pwd(u08bits *usname, st_password_t pwd) return ret; } -u08bits *start_user_check(turnserver_id id, turn_credential_type ct, int oauth, u08bits *usname, u08bits *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, u64bits ctxkey, int *postpone_reply) +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; @@ -635,7 +633,8 @@ u08bits *start_user_check(turnserver_id id, turn_credential_type ct, int oauth, ns_bzero(&am,sizeof(struct auth_message)); am.id = id; am.ct = ct; - am.oauth = oauth; + am.in_oauth = in_oauth; + am.out_oauth = *out_oauth; STRCPY(am.username,usname); STRCPY(am.realm,realm); am.resume_func = resume; diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index 784835bc..4fd6c7c5 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -86,7 +86,8 @@ void update_o_to_realm(ur_string_map * o_to_realm_new); struct auth_message { turnserver_id id; turn_credential_type ct; - int oauth; + int in_oauth; + int out_oauth; u08bits username[STUN_MAX_USERNAME_SIZE + 1]; u08bits realm[STUN_MAX_REALM_SIZE + 1]; hmackey_t key; @@ -190,7 +191,7 @@ void add_to_secrets_list(secrets_list_t *sl, const char* elem); int get_user_key(int in_oauth, int *out_oauth, 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 oauth, u08bits *uname, u08bits *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, u64bits ctxkey, int *postpone_reply); +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, u08bits *realm); void release_allocation_quota(u08bits *username, u08bits *realm); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 35f7f61a..de697a91 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3315,7 +3315,7 @@ static int check_stun_auth(turn_turnserver *server, /* Password */ if(!(ss->hmackey_set) && (ss->pwd[0] == 0)) { if(can_resume) { - (server->userkeycb)(server->id, server->ct, server->oauth, usname, realm, resume_processing_after_username_check, in_buffer, ss->id, postpone_reply); + (server->userkeycb)(server->id, server->ct, server->oauth, &(ss->oauth), usname, realm, resume_processing_after_username_check, in_buffer, ss->id, postpone_reply); if(*postpone_reply) { return 0; } @@ -3357,7 +3357,7 @@ static int check_stun_auth(turn_turnserver *server, } if(can_resume) { - (server->userkeycb)(server->id, server->ct, server->oauth, usname, realm, resume_processing_after_username_check, in_buffer, ss->id, postpone_reply); + (server->userkeycb)(server->id, server->ct, server->oauth, &(ss->oauth), usname, realm, resume_processing_after_username_check, in_buffer, ss->id, postpone_reply); if(*postpone_reply) { return 0; } diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index 6aee926a..fdc2e133 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -91,7 +91,7 @@ struct _turn_turnserver; typedef struct _turn_turnserver turn_turnserver; typedef void (*get_username_resume_cb)(int success, int oauth, hmackey_t hmackey, st_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 oauth, u08bits *uname, u08bits *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, u64bits ctxkey, int *postpone_reply); +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, u08bits *realm); typedef void (*release_allocation_quota_cb)(u08bits *username, 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); From 1b8b3eff5ccfb833ef494608a235709ebe809ae5 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 27 Sep 2014 07:41:20 +0000 Subject: [PATCH 216/805] token cache --- ChangeLog | 1 - src/apps/uclient/session.h | 2 ++ src/apps/uclient/uclient.c | 32 ++++++++++++++++++++------------ src/server/ns_turn_server.c | 1 + 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 13986234..b347d462 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,7 +2,6 @@ Version 4.2.1.1 'Monza': - oAuth security implementation: TODO: - - access-token must be cached and included only in ALLOCATE and REFRESH; - token timeout; - kid timeout; - TLS renegotiation DoS attack prevention implemented; diff --git a/src/apps/uclient/session.h b/src/apps/uclient/session.h index b7f98e2b..7c078e5a 100644 --- a/src/apps/uclient/session.h +++ b/src/apps/uclient/session.h @@ -83,6 +83,8 @@ typedef struct { /* oAuth */ int oauth; u08bits server_name[STUN_MAX_SERVER_NAME_SIZE+1]; + hmackey_t key; + int key_set; /* RFC 6062 */ app_tcp_conn_info **tcp_conn; size_t tcp_conn_number; diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 889e1825..0413285d 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1432,20 +1432,28 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) } else if(clnet_info->nonce[0]) { if(oauth && clnet_info->oauth) { - encoded_oauth_token etoken; - u08bits nonce[12]; - RAND_bytes((unsigned char*)nonce,12); - if(encode_oauth_token(clnet_info->server_name, &etoken, &okey, &otoken, nonce)<0) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot encode token\n"); - return -1; - } - stun_attr_add_str(message->buf, (size_t*)&(message->len), STUN_ATTRIBUTE_OAUTH_ACCESS_TOKEN, + + u16bits method = stun_get_method_str(message->buf, message->len); + + if(((method == STUN_METHOD_ALLOCATE) || (method == STUN_METHOD_REFRESH)) || !(clnet_info->key_set)) + { + + encoded_oauth_token etoken; + u08bits nonce[12]; + RAND_bytes((unsigned char*)nonce,12); + if(encode_oauth_token(clnet_info->server_name, &etoken, &okey, &otoken, nonce)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot encode token\n"); + return -1; + } + stun_attr_add_str(message->buf, (size_t*)&(message->len), STUN_ATTRIBUTE_OAUTH_ACCESS_TOKEN, (const u08bits*)etoken.token, (int)etoken.size); - hmackey_t key; - ns_bcopy(otoken.enc_block.mac_key,key,otoken.enc_block.key_length); + ns_bcopy(otoken.enc_block.mac_key,clnet_info->key,otoken.enc_block.key_length); + clnet_info->key_set = 1; + } + if(stun_attr_add_integrity_by_key_str(message->buf, (size_t*)&(message->len), (u08bits*)okey.kid, - clnet_info->realm, key, clnet_info->nonce, clnet_info->shatype)<0) { + clnet_info->realm, clnet_info->key, clnet_info->nonce, clnet_info->shatype)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot add integrity to the message\n"); return -1; } @@ -1454,7 +1462,7 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) { st_password_t pwd; if(stun_check_message_integrity_by_key_str(get_turn_credentials_type(), - message->buf, (size_t)(message->len), key, pwd, clnet_info->shatype, NULL)<1) { + 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"); return -1; } diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index de697a91..aa1515ed 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3262,6 +3262,7 @@ static int check_stun_auth(turn_turnserver *server, if(ss->username[0]) { if(strcmp((char*)ss->username,(char*)usname)) { if(ss->oauth) { + ss->hmackey_set = 0; STRCPY(ss->username,usname); set_username_hash(ss->client_socket,ss->username,(u08bits*)ss->realm_options.name); } else { From 968f5f57290f66a497a951f8561cce28b4324cc6 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 27 Sep 2014 08:25:40 +0000 Subject: [PATCH 217/805] oauth attributes new numbers --- src/client/ns_turn_msg_defs_new.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 9e9111e6..4e64dabf 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -101,8 +101,8 @@ typedef enum _AUTH_ALG AUTH_ALG; * oAuth struct */ -#define STUN_ATTRIBUTE_THIRD_PARTY_AUTHORIZATION (0x8030) -#define STUN_ATTRIBUTE_OAUTH_ACCESS_TOKEN (0x0030) +#define STUN_ATTRIBUTE_THIRD_PARTY_AUTHORIZATION (0x8031) +#define STUN_ATTRIBUTE_OAUTH_ACCESS_TOKEN (0x0031) #define OAUTH_KID_SIZE (128) #define OAUTH_HASH_FUNC_SIZE (64) From 4451b4f5ddee56e9816c27f97dd96ed9d54e33a0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 27 Sep 2014 09:07:06 +0000 Subject: [PATCH 218/805] oauth --- src/apps/relay/ns_ioalib_engine_impl.c | 13 ++------- src/apps/relay/ns_ioalib_impl.h | 1 - src/apps/uclient/mainuclient.c | 37 +++++++++++++++++--------- src/apps/uclient/session.h | 1 + src/apps/uclient/uclient.c | 15 ++++++++--- src/apps/uclient/uclient.h | 4 +-- src/server/ns_turn_ioalib.h | 4 +-- src/server/ns_turn_server.c | 12 ++++----- 8 files changed, 49 insertions(+), 38 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 84fd9742..157bd51d 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1733,7 +1733,6 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach) ret->magic = SOCKET_MAGIC; - ret->username_hash = s->username_hash; ret->realm_hash = s->realm_hash; set_socket_ssl(ret,s->ssl); @@ -3342,14 +3341,9 @@ static u32bits string_hash(const u08bits *str) { return hash; } -int check_username_hash(ioa_socket_handle s, u08bits *username, u08bits *realm) +int check_realm_hash(ioa_socket_handle s, u08bits *realm) { if(s) { - if(username && username[0]) { - if(s->username_hash != string_hash(username)) { - return 0; - } - } if(realm && realm[0]) { if(s->realm_hash != string_hash(realm)) { return 0; @@ -3359,12 +3353,9 @@ int check_username_hash(ioa_socket_handle s, u08bits *username, u08bits *realm) return 1; } -void set_username_hash(ioa_socket_handle s, u08bits *username, u08bits *realm) +void set_realm_hash(ioa_socket_handle s, u08bits *realm) { if(s) { - if(username && username[0]) { - s->username_hash = string_hash(username); - } if(realm && realm[0]) { s->realm_hash = string_hash(realm); } diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index e31347f6..198e7d9a 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -214,7 +214,6 @@ struct _ioa_socket connect_cb conn_cb; void *conn_arg; //Transferable sockets user data - u32bits username_hash; u32bits realm_hash; //Accept: struct evconnlistener *list_ev; diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 3efc1f89..73bd096b 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -99,11 +99,12 @@ band_limit_t bps = 0; int dual_allocation = 0; int oauth = 0; -oauth_key okey; -oauth_token otoken; +oauth_key okey_array[2]; +oauth_token otoken_array[2]; -static oauth_key_data_raw okdr = { - "north","Y2FybGVvbg==",0,0,"SHA-256","AES-256-CBC","","HMAC-SHA-256-128","" +static oauth_key_data_raw okdr_array[2] = { + {"north","Y2FybGVvbg==",0,0,"SHA-256","AES-256-CBC","","HMAC-SHA-256-128",""}, + {"oldempire","YXVsY3Vz",0,0,"SHA-256","AEAD-AES-256-GCM","","",""} }; //////////////// local definitions ///////////////// @@ -225,13 +226,19 @@ int main(int argc, char **argv) exit(-1); } - oauth_key_data okd; - convert_oauth_key_data_raw(&okdr, &okd); + 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]); char err_msg[1025] = "\0"; size_t err_msg_size = sizeof(err_msg) - 1; - if (convert_oauth_key_data(&okd, &okey, err_msg, err_msg_size) < 0) { + if (convert_oauth_key_data(&okd_array[0], &okey_array[0], err_msg, err_msg_size) < 0) { + fprintf(stderr, "%s\n", err_msg); + exit(-1); + } + + if (convert_oauth_key_data(&okd_array[1], &okey_array[1], err_msg, err_msg_size) < 0) { fprintf(stderr, "%s\n", err_msg); exit(-1); } @@ -403,19 +410,25 @@ int main(int argc, char **argv) if(oauth) { - otoken.enc_block.lifetime = 0; - otoken.enc_block.timestamp = 0; + otoken_array[0].enc_block.lifetime = 0; + otoken_array[0].enc_block.timestamp = 0; + + otoken_array[1].enc_block.lifetime = 0; + otoken_array[1].enc_block.timestamp = 0; switch(shatype) { case SHATYPE_SHA256: - otoken.enc_block.key_length = 32; + otoken_array[0].enc_block.key_length = 32; + otoken_array[1].enc_block.key_length = 32; break; default: - otoken.enc_block.key_length = 20; + otoken_array[0].enc_block.key_length = 20; + otoken_array[1].enc_block.key_length = 20; break; }; - RAND_bytes((unsigned char *)(otoken.enc_block.mac_key), otoken.enc_block.key_length); + RAND_bytes((unsigned char *)(otoken_array[0].enc_block.mac_key), otoken_array[0].enc_block.key_length); + RAND_bytes((unsigned char *)(otoken_array[1].enc_block.mac_key), otoken_array[1].enc_block.key_length); } if(g_use_auth_secret_with_timestamp) { diff --git a/src/apps/uclient/session.h b/src/apps/uclient/session.h index 7c078e5a..66a2d52b 100644 --- a/src/apps/uclient/session.h +++ b/src/apps/uclient/session.h @@ -85,6 +85,7 @@ typedef struct { u08bits server_name[STUN_MAX_SERVER_NAME_SIZE+1]; hmackey_t key; int key_set; + int cok; /* RFC 6062 */ app_tcp_conn_info **tcp_conn; size_t tcp_conn_number; diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 0413285d..8412cb1a 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1435,24 +1435,29 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) u16bits method = stun_get_method_str(message->buf, message->len); + int cok = clnet_info->cok; + if(((method == STUN_METHOD_ALLOCATE) || (method == STUN_METHOD_REFRESH)) || !(clnet_info->key_set)) { + if(!mobility) + cok=(++(clnet_info->cok))%2; + clnet_info->cok = cok; encoded_oauth_token etoken; u08bits nonce[12]; RAND_bytes((unsigned char*)nonce,12); - if(encode_oauth_token(clnet_info->server_name, &etoken, &okey, &otoken, nonce)<0) { + if(encode_oauth_token(clnet_info->server_name, &etoken, &(okey_array[cok]), &(otoken_array[cok]), nonce)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot encode token\n"); return -1; } stun_attr_add_str(message->buf, (size_t*)&(message->len), STUN_ATTRIBUTE_OAUTH_ACCESS_TOKEN, (const u08bits*)etoken.token, (int)etoken.size); - ns_bcopy(otoken.enc_block.mac_key,clnet_info->key,otoken.enc_block.key_length); + ns_bcopy(otoken_array[cok].enc_block.mac_key,clnet_info->key,otoken_array[cok].enc_block.key_length); clnet_info->key_set = 1; } - if(stun_attr_add_integrity_by_key_str(message->buf, (size_t*)&(message->len), (u08bits*)okey.kid, + if(stun_attr_add_integrity_by_key_str(message->buf, (size_t*)&(message->len), (u08bits*)okey_array[cok].kid, clnet_info->realm, clnet_info->key, clnet_info->nonce, clnet_info->shatype)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot add integrity to the message\n"); return -1; @@ -1488,7 +1493,9 @@ int check_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) hmackey_t key; st_password_t pwd; - ns_bcopy(otoken.enc_block.mac_key,key,otoken.enc_block.key_length); + int cok = clnet_info->cok; + + ns_bcopy(otoken_array[cok].enc_block.mac_key,key,otoken_array[cok].enc_block.key_length); return stun_check_message_integrity_by_key_str(get_turn_credentials_type(), message->buf, (size_t)(message->len), key, pwd, sht, NULL); diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index ffb20cbd..83e3a0be 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -87,8 +87,8 @@ extern int dual_allocation; extern char origin[STUN_MAX_ORIGIN_SIZE+1]; extern int oauth; -extern oauth_key okey; -extern oauth_token otoken; +extern oauth_key okey_array[2]; +extern oauth_token otoken_array[2]; #define is_TCP_relay() (relay_transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 1ca57230..f673ff2a 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -242,8 +242,8 @@ void set_do_not_use_df(ioa_socket_handle s); int ioa_socket_tobeclosed(ioa_socket_handle s); void set_ioa_socket_tobeclosed(ioa_socket_handle s); void close_ioa_socket_after_processing_if_necessary(ioa_socket_handle s); -int check_username_hash(ioa_socket_handle s, u08bits *username, u08bits *realm); -void set_username_hash(ioa_socket_handle s, u08bits *username, u08bits *realm); +int check_realm_hash(ioa_socket_handle s, u08bits *realm); +void set_realm_hash(ioa_socket_handle s, u08bits *realm); ////////////////// Base64 ///////////////////////////// diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index aa1515ed..38f5269f 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3264,7 +3264,7 @@ static int check_stun_auth(turn_turnserver *server, if(ss->oauth) { ss->hmackey_set = 0; STRCPY(ss->username,usname); - set_username_hash(ss->client_socket,ss->username,(u08bits*)ss->realm_options.name); + set_realm_hash(ss->client_socket,(u08bits*)ss->realm_options.name); } else { if(method == STUN_METHOD_ALLOCATE) { *err_code = 437; @@ -3278,7 +3278,7 @@ static int check_stun_auth(turn_turnserver *server, } } else { STRCPY(ss->username,usname); - set_username_hash(ss->client_socket,ss->username,(u08bits*)ss->realm_options.name); + set_realm_hash(ss->client_socket,(u08bits*)ss->realm_options.name); } if(server->ct != TURN_CREDENTIALS_SHORT_TERM) { @@ -4210,10 +4210,10 @@ static int create_relay_connection(turn_turnserver* server, ns_bzero(newelem, sizeof(relay_endpoint_session)); newelem->s = s; - if(!check_username_hash(newelem->s,ss->username,(u08bits*)ss->realm_options.name)) { + if(!check_realm_hash(newelem->s,(u08bits*)ss->realm_options.name)) { IOA_CLOSE_SOCKET(newelem->s); *err_code = 508; - *reason = (const u08bits *)"Cannot find a valid reserved socket for this username"; + *reason = (const u08bits *)"Cannot find a valid reserved socket for this realm"; return -1; } @@ -4251,11 +4251,11 @@ static int create_relay_connection(turn_turnserver* server, return -1; } - set_username_hash(newelem->s,ss->username,(u08bits*)ss->realm_options.name); + set_realm_hash(newelem->s,(u08bits*)ss->realm_options.name); if (rtcp_s) { if (out_reservation_token && *out_reservation_token) { - set_username_hash(rtcp_s,ss->username,(u08bits*)ss->realm_options.name); + set_realm_hash(rtcp_s,(u08bits*)ss->realm_options.name); /* OK */ } else { IOA_CLOSE_SOCKET(newelem->s); From a87196485eba01c916e0eab1812b17675f0e4de8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 27 Sep 2014 17:49:20 +0000 Subject: [PATCH 219/805] mobile authentication fixed --- src/apps/uclient/uclient.c | 3 +-- src/server/ns_turn_server.c | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 8412cb1a..4b705863 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1440,8 +1440,7 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) if(((method == STUN_METHOD_ALLOCATE) || (method == STUN_METHOD_REFRESH)) || !(clnet_info->key_set)) { - if(!mobility) - cok=(++(clnet_info->cok))%2; + cok=(++(clnet_info->cok))%2; clnet_info->cok = cok; encoded_oauth_token etoken; u08bits nonce[12]; diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 38f5269f..f1e92621 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1548,8 +1548,24 @@ static int handle_turn_refresh(turn_turnserver *server, //Check security: int postpone_reply = 0; - check_stun_auth(server, orig_ss, tid, resp_constructed, err_code, reason, in_buffer, nbh, - STUN_METHOD_REFRESH, &message_integrity, &postpone_reply, can_resume); + + ns_bcopy(orig_ss->nonce,ss->nonce,sizeof(ss->nonce)); + ss->nonce_expiration_time = orig_ss->nonce_expiration_time; + ns_bcopy(&(orig_ss->realm_options),&(ss->realm_options),sizeof(ss->realm_options)); + ns_bcopy(orig_ss->username,ss->username,sizeof(ss->username)); + ss->hmackey_set = orig_ss->hmackey_set; + ns_bcopy(orig_ss->hmackey,ss->hmackey,sizeof(ss->hmackey)); + ss->oauth = orig_ss->oauth; + ns_bcopy(orig_ss->origin,ss->origin,sizeof(ss->origin)); + ss->origin_set = orig_ss->origin_set; + ns_bcopy(orig_ss->pwd,ss->pwd,sizeof(ss->pwd)); + + if(check_stun_auth(server, ss, tid, resp_constructed, err_code, reason, in_buffer, nbh, + STUN_METHOD_REFRESH, &message_integrity, &postpone_reply, can_resume)<0) { + if(!(*err_code)) { + *err_code = 401; + } + } if(postpone_reply) { From 2208dc60ab247077ba8ceb2faaacc478e7719856 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 28 Sep 2014 00:33:41 +0000 Subject: [PATCH 220/805] oauth key timestamp implemented --- ChangeLog | 1 - src/apps/relay/userdb.c | 9 +++++++++ src/client/ns_turn_msg_defs_new.h | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b347d462..9e432aef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,7 +3,6 @@ Version 4.2.1.1 'Monza': - oAuth security implementation: TODO: - token timeout; - - kid timeout; - TLS renegotiation DoS attack prevention implemented; - FQDN as relay-ip and listener-ip parameters (issue 6) (patch provided by Iñaki Baz Castillo); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 30ff57fa..3dd9fe6f 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -427,6 +427,15 @@ int get_user_key(int in_oauth, int *out_oauth, u08bits *usname, u08bits *realm, if(gres<0) return ret; + if(!rawKey.kid[0]) + return ret; + + if(rawKey.lifetime) { + if(!turn_time_before(turn_time(),(turn_time_t)(rawKey.timestamp + rawKey.lifetime+OAUTH_TIME_DELTA))) { + return ret; + } + } + oauth_key_data okd; ns_bzero(&okd,sizeof(okd)); diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 4e64dabf..82909716 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -115,6 +115,8 @@ typedef enum _AUTH_ALG AUTH_ALG; #define OAUTH_DEFAULT_LIFETIME (0) #define OAUTH_DEFAULT_TIMESTAMP (turn_time()) +#define OAUTH_TIME_DELTA (5) + struct _oauth_key_data { char kid[OAUTH_KID_SIZE+1]; char ikm_key[OAUTH_KEY_SIZE+1]; From cbb37c645f45db38d07c70a457571cae3579f098 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 28 Sep 2014 08:38:15 +0000 Subject: [PATCH 221/805] token timeout implemented --- ChangeLog | 6 ++---- src/apps/relay/netengine.c | 4 ++-- src/apps/relay/userdb.c | 25 ++++++++++++++++++++++++- src/apps/relay/userdb.h | 3 ++- src/apps/uclient/mainuclient.c | 4 ++-- src/apps/uclient/startuclient.c | 9 ++++----- src/apps/uclient/uclient.c | 1 + src/apps/uclient/uclient.h | 3 +++ src/server/ns_turn_server.c | 13 +++++++++++-- src/server/ns_turn_server.h | 2 +- src/server/ns_turn_session.h | 1 + 11 files changed, 53 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9e432aef..4fdbf85d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,7 @@ 08/22/2014 Oleg Moskalenko Version 4.2.1.1 'Monza': - - oAuth security implementation: - TODO: - - token timeout; - - TLS renegotiation DoS attack prevention implemented; + - oAuth security experimental implementation; + - The "TLS renegotiation" DoS attack prevention implemented; - FQDN as relay-ip and listener-ip parameters (issue 6) (patch provided by Iñaki Baz Castillo); - redis user key operation fixed. diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 829fff98..a73bd589 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -388,7 +388,7 @@ static void auth_server_receive_message(struct bufferevent *bev, void *ptr) } } else { hmackey_t key; - if(get_user_key(am.in_oauth,&(am.out_oauth),am.username,am.realm,key,am.in_buffer.nbh)<0) { + 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; } else { ns_bcopy(key,am.key,sizeof(hmackey_t)); @@ -770,7 +770,7 @@ static int handle_relay_message(relay_server_handle rs, struct message_to_relay static void handle_relay_auth_message(struct relay_server *rs, struct auth_message *am) { - am->resume_func(am->success, am->out_oauth, am->key, am->pwd, + am->resume_func(am->success, am->out_oauth, am->max_session_time, am->key, am->pwd, &(rs->server), am->ctxkey, &(am->in_buffer)); if (am->in_buffer.nbh) { ioa_network_buffer_delete(rs->ioa_eng, am->in_buffer.nbh); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 3dd9fe6f..48fefc05 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -398,10 +398,13 @@ static char *get_real_username(char *usname) /* * Password retrieval */ -int get_user_key(int in_oauth, int *out_oauth, u08bits *usname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh) +int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *usname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh) { int ret = -1; + if(max_session_time) + *max_session_time = 0; + if(in_oauth && out_oauth && usname && usname[0] && realm && realm[0]) { stun_attr_ref sar = stun_attr_get_first_by_type_str(ioa_network_buffer_data(nbh), @@ -495,7 +498,27 @@ int get_user_key(int in_oauth, int *out_oauth, u08bits *usname, u08bits *realm, dot.enc_block.mac_key, pwdtmp, turn_params.shatype,NULL)>0) { + + turn_time_t lifetime = (turn_time_t)(dot.enc_block.lifetime); + if(lifetime) { + turn_time_t ts = (turn_time_t)(dot.enc_block.timestamp >> 16); + turn_time_t to = ts + lifetime + OAUTH_TIME_DELTA; + turn_time_t ct = turn_time(); + if(!turn_time_before(ct,to)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "oAuth token is too old\n"); + return -1; + } + if(max_session_time) { + *max_session_time = to - ct; + if(*max_session_time > OAUTH_TIME_DELTA) + *max_session_time -= OAUTH_TIME_DELTA; + if(*max_session_time < OAUTH_TIME_DELTA) + *max_session_time = OAUTH_TIME_DELTA; + } + } + ns_bcopy(dot.enc_block.mac_key,key,dot.enc_block.key_length); + ret = 0; } } diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index 4fd6c7c5..036ea4f0 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -88,6 +88,7 @@ struct auth_message { turn_credential_type ct; int in_oauth; int out_oauth; + int max_session_time; u08bits username[STUN_MAX_USERNAME_SIZE + 1]; u08bits realm[STUN_MAX_REALM_SIZE + 1]; hmackey_t key; @@ -189,7 +190,7 @@ 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, u08bits *uname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh); +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, u08bits *realm); diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 73bd096b..b2372372 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -410,10 +410,10 @@ int main(int argc, char **argv) if(oauth) { - otoken_array[0].enc_block.lifetime = 0; + otoken_array[0].enc_block.lifetime = OAUTH_SESSION_LIFETIME; otoken_array[0].enc_block.timestamp = 0; - otoken_array[1].enc_block.lifetime = 0; + otoken_array[1].enc_block.lifetime = OAUTH_SESSION_LIFETIME; otoken_array[1].enc_block.timestamp = 0; switch(shatype) { diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 003f51aa..2012ecdb 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -360,9 +360,9 @@ static int clnet_allocate(int verbose, } if(!dos) - stun_set_allocate_request(&message, 800, af4, af6, relay_transport, mobility); + stun_set_allocate_request(&message, UCLIENT_SESSION_LIFETIME, af4, af6, relay_transport, mobility); else - stun_set_allocate_request(&message, 300, af4, af6, relay_transport, mobility); + stun_set_allocate_request(&message, UCLIENT_SESSION_LIFETIME/3, af4, af6, relay_transport, mobility); if(bps) stun_attr_add_bandwidth_str(message.buf, (size_t*)(&(message.len)), bps); @@ -633,9 +633,8 @@ static int clnet_allocate(int verbose, stun_buffer message; stun_init_request(STUN_METHOD_REFRESH, &message); - uint32_t lt = htonl(600); - stun_attr_add(&message, STUN_ATTRIBUTE_LIFETIME, (const char*) <, - 4); + uint32_t lt = htonl(UCLIENT_SESSION_LIFETIME); + stun_attr_add(&message, STUN_ATTRIBUTE_LIFETIME, (const char*) <, 4); if(clnet_info->s_mobile_id[0]) { stun_attr_add(&message, STUN_ATTRIBUTE_MOBILITY_TICKET, (const char*)clnet_info->s_mobile_id, strlen(clnet_info->s_mobile_id)); diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 4b705863..865f766d 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1445,6 +1445,7 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) encoded_oauth_token etoken; u08bits nonce[12]; RAND_bytes((unsigned char*)nonce,12); + otoken_array[cok].enc_block.timestamp = ((uint64_t)turn_time()) << 16; if(encode_oauth_token(clnet_info->server_name, &etoken, &(okey_array[cok]), &(otoken_array[cok]), nonce)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot encode token\n"); return -1; diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index 83e3a0be..734de669 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -90,6 +90,9 @@ extern int oauth; extern oauth_key okey_array[2]; extern oauth_token otoken_array[2]; +#define UCLIENT_SESSION_LIFETIME (777) +#define OAUTH_SESSION_LIFETIME (555) + #define is_TCP_relay() (relay_transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) void start_mclient(const char *remote_address, int port, diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index f1e92621..9574c683 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1159,6 +1159,9 @@ static int handle_turn_allocate(turn_turnserver *server, } lifetime = stun_adjust_allocate_lifetime(lifetime); + if(ss->max_session_time_auth && (ss->max_session_time_auth < lifetime)) { + lifetime = ss->max_session_time_auth; + } u64bits out_reservation_token = 0; if(inc_quota(ss, username)<0) { @@ -1559,6 +1562,7 @@ static int handle_turn_refresh(turn_turnserver *server, ns_bcopy(orig_ss->origin,ss->origin,sizeof(ss->origin)); ss->origin_set = orig_ss->origin_set; ns_bcopy(orig_ss->pwd,ss->pwd,sizeof(ss->pwd)); + ss->max_session_time_auth = orig_ss->max_session_time_auth; if(check_stun_auth(server, ss, tid, resp_constructed, err_code, reason, in_buffer, nbh, STUN_METHOD_REFRESH, &message_integrity, &postpone_reply, can_resume)<0) { @@ -1577,8 +1581,12 @@ static int handle_turn_refresh(turn_turnserver *server, if (to_delete) lifetime = 0; - else + else { lifetime = stun_adjust_allocate_lifetime(lifetime); + if(ss->max_session_time_auth && (ss->max_session_time_auth < lifetime)) { + lifetime = ss->max_session_time_auth; + } + } if (af4c && refresh_relay_connection(server, orig_ss, lifetime, 0, 0, 0, err_code, AF_INET) < 0) { @@ -3110,7 +3118,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, 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, st_password_t pwd, turn_turnserver *server, u64bits ctxkey, ioa_net_data *in_buffer) { if(server && in_buffer && in_buffer->nbh) { @@ -3123,6 +3131,7 @@ static void resume_processing_after_username_check(int success, int oauth, hmac ns_bcopy(hmackey,ss->hmackey,sizeof(hmackey_t)); 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)); } diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index fdc2e133..91ac0136 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -90,7 +90,7 @@ typedef enum { struct _turn_turnserver; typedef struct _turn_turnserver turn_turnserver; -typedef void (*get_username_resume_cb)(int success, int oauth, 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, st_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, u08bits *realm); typedef void (*release_allocation_quota_cb)(u08bits *username, u08bits *realm); diff --git a/src/server/ns_turn_session.h b/src/server/ns_turn_session.h index f8510794..c1a2c70e 100644 --- a/src/server/ns_turn_session.h +++ b/src/server/ns_turn_session.h @@ -84,6 +84,7 @@ struct _ts_ur_super_session { st_password_t pwd; int quota_used; int oauth; + turn_time_t max_session_time_auth; /* Realm */ realm_options_t realm_options; int origin_set; From 01b0294bcf76f57dc982c89c3add7f2d2d3e44ec Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 28 Sep 2014 09:37:52 +0000 Subject: [PATCH 222/805] mobile fixes --- src/client/ns_turn_msg.c | 14 ++++++++---- src/client/ns_turn_msg.h | 2 +- src/server/ns_turn_server.c | 43 +++++++++++++++++-------------------- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index f588ed8a..3ea77448 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -962,10 +962,16 @@ void stun_tid_generate_in_message_str(u08bits* buf, stun_tid* id) { /////////////////// TIME //////////////////////////////////////////////////////// -u32bits stun_adjust_allocate_lifetime(u32bits lifetime) { - if(!lifetime) return STUN_DEFAULT_ALLOCATE_LIFETIME; - else if(lifetimeSTUN_MAX_ALLOCATE_LIFETIME) return STUN_MAX_ALLOCATE_LIFETIME; +turn_time_t stun_adjust_allocate_lifetime(turn_time_t lifetime, turn_time_t max_lifetime) { + + if(!lifetime) lifetime = STUN_DEFAULT_ALLOCATE_LIFETIME; + else if(lifetimeSTUN_MAX_ALLOCATE_LIFETIME) lifetime = STUN_MAX_ALLOCATE_LIFETIME; + + if(max_lifetime && (max_lifetime < lifetime)) { + lifetime = max_lifetime; + } + return lifetime; } diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index d756ad06..09e29d01 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -90,7 +90,7 @@ u16bits stun_make_error_response(u16bits method); /////////////////////////////////////////////////////////////// -u32bits stun_adjust_allocate_lifetime(u32bits lifetime); +turn_time_t stun_adjust_allocate_lifetime(turn_time_t lifetime, turn_time_t max_lifetime); ///////////// STR //////////////////////////////////////////////// diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 9574c683..aac5dc26 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -961,7 +961,7 @@ static int handle_turn_allocate(turn_turnserver *server, } else { u08bits transport = 0; - u32bits lifetime = 0; + turn_time_t lifetime = 0; int even_port = -1; int dont_fragment = 0; u64bits in_reservation_token = 0; @@ -1158,10 +1158,7 @@ static int handle_turn_allocate(turn_turnserver *server, } } - lifetime = stun_adjust_allocate_lifetime(lifetime); - if(ss->max_session_time_auth && (ss->max_session_time_auth < lifetime)) { - lifetime = ss->max_session_time_auth; - } + lifetime = stun_adjust_allocate_lifetime(lifetime, ss->max_session_time_auth); u64bits out_reservation_token = 0; if(inc_quota(ss, username)<0) { @@ -1399,7 +1396,7 @@ static int handle_turn_refresh(turn_turnserver *server, } else { - u32bits lifetime = 0; + turn_time_t lifetime = 0; int to_delete = 0; mobile_id_t mid = 0; char smid[sizeof(ss->s_mobile_id)] = "\0"; @@ -1552,17 +1549,19 @@ static int handle_turn_refresh(turn_turnserver *server, //Check security: int postpone_reply = 0; - ns_bcopy(orig_ss->nonce,ss->nonce,sizeof(ss->nonce)); - ss->nonce_expiration_time = orig_ss->nonce_expiration_time; - ns_bcopy(&(orig_ss->realm_options),&(ss->realm_options),sizeof(ss->realm_options)); - ns_bcopy(orig_ss->username,ss->username,sizeof(ss->username)); - ss->hmackey_set = orig_ss->hmackey_set; - ns_bcopy(orig_ss->hmackey,ss->hmackey,sizeof(ss->hmackey)); - ss->oauth = orig_ss->oauth; - ns_bcopy(orig_ss->origin,ss->origin,sizeof(ss->origin)); - ss->origin_set = orig_ss->origin_set; - ns_bcopy(orig_ss->pwd,ss->pwd,sizeof(ss->pwd)); - ss->max_session_time_auth = orig_ss->max_session_time_auth; + if(!ss->hmackey_set) { + ns_bcopy(orig_ss->nonce,ss->nonce,sizeof(ss->nonce)); + ss->nonce_expiration_time = orig_ss->nonce_expiration_time; + ns_bcopy(&(orig_ss->realm_options),&(ss->realm_options),sizeof(ss->realm_options)); + ns_bcopy(orig_ss->username,ss->username,sizeof(ss->username)); + ss->hmackey_set = orig_ss->hmackey_set; + ns_bcopy(orig_ss->hmackey,ss->hmackey,sizeof(ss->hmackey)); + ss->oauth = orig_ss->oauth; + ns_bcopy(orig_ss->origin,ss->origin,sizeof(ss->origin)); + ss->origin_set = orig_ss->origin_set; + ns_bcopy(orig_ss->pwd,ss->pwd,sizeof(ss->pwd)); + ss->max_session_time_auth = orig_ss->max_session_time_auth; + } if(check_stun_auth(server, ss, tid, resp_constructed, err_code, reason, in_buffer, nbh, STUN_METHOD_REFRESH, &message_integrity, &postpone_reply, can_resume)<0) { @@ -1582,10 +1581,7 @@ static int handle_turn_refresh(turn_turnserver *server, if (to_delete) lifetime = 0; else { - lifetime = stun_adjust_allocate_lifetime(lifetime); - if(ss->max_session_time_auth && (ss->max_session_time_auth < lifetime)) { - lifetime = ss->max_session_time_auth; - } + lifetime = stun_adjust_allocate_lifetime(lifetime, ss->max_session_time_auth); } if (af4c && refresh_relay_connection(server, orig_ss, lifetime, 0, 0, 0, @@ -1695,8 +1691,9 @@ static int handle_turn_refresh(turn_turnserver *server, if (to_delete) lifetime = 0; - else - lifetime = stun_adjust_allocate_lifetime(lifetime); + else { + lifetime = stun_adjust_allocate_lifetime(lifetime, ss->max_session_time_auth); + } if(!af4 && !af6) { af4 = af4c; From 221570886da0d48d83e6936b91a4d017e88909a4 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 28 Sep 2014 09:39:41 +0000 Subject: [PATCH 223/805] cosmetics --- src/server/ns_turn_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index aac5dc26..e60d66b8 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1549,7 +1549,7 @@ static int handle_turn_refresh(turn_turnserver *server, //Check security: int postpone_reply = 0; - if(!ss->hmackey_set) { + if(!(ss->hmackey_set)) { ns_bcopy(orig_ss->nonce,ss->nonce,sizeof(ss->nonce)); ss->nonce_expiration_time = orig_ss->nonce_expiration_time; ns_bcopy(&(orig_ss->realm_options),&(ss->realm_options),sizeof(ss->realm_options)); From 9ddf00a4c228db8b24d6bee225c527d745d25e35 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 29 Sep 2014 02:11:27 +0000 Subject: [PATCH 224/805] quota and server name ixes --- README.turnserver | 6 +- examples/etc/turnserver.conf | 6 +- .../secure_relay_with_db_mongo.sh | 2 +- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 8 +-- man/man1/turnutils.1 | 2 +- src/apps/relay/mainrelay.c | 37 ++---------- src/apps/relay/netengine.c | 19 ------ src/apps/relay/userdb.c | 31 ++++++---- src/apps/relay/userdb.h | 4 +- src/server/ns_turn_ioalib.h | 2 - src/server/ns_turn_server.c | 59 ++++++++++--------- src/server/ns_turn_server.h | 4 +- 13 files changed, 71 insertions(+), 111 deletions(-) diff --git a/README.turnserver b/README.turnserver index 2308e320..cb339a2a 100644 --- a/README.turnserver +++ b/README.turnserver @@ -423,9 +423,9 @@ Options with required values: that other mode is dynamic. Multiple shared secrets can be used (both in the database and in the "static" fashion). ---server-name Server name used (when necessary) for - the authentication purposes (oauth). - The default value is the FQDN of the host. +--server-name Server name used for + the oAuth authentication purposes. + The default value is the realm name. --cert Certificate file, PEM format. Same file search rules applied as for the configuration diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index f52b8e47..0d1aef0b 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -210,9 +210,9 @@ # #static-auth-secret=north -# Server name used (when necessary) for -# the authentication purposes (oauth). -# The default value is the FQDN of the host. +# Server name used for +# the oAuth authentication purposes. +# The default value is the realm name. # #server-name=blackdow.carleon.gov diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh index c5b959fd..fd793c72 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh @@ -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 --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 --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:SSLv2 --oauth $@ diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 2b020eea..e47caf77 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "26 September 2014" "" "" +.TH TURN 1 "28 September 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index ca18f0d4..cd6d82f7 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "26 September 2014" "" "" +.TH TURN 1 "28 September 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -617,9 +617,9 @@ that other mode is dynamic. Multiple shared secrets can be used .TP .B \fB\-\-server\-name\fP -Server name used (when necessary) for -the authentication purposes (oauth). -The default value is the FQDN of the host. +Server name used for +the oAuth authentication purposes. +The default value is the realm name. .TP .B \fB\-\-cert\fP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 179fbf7c..ec39407f 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "26 September 2014" "" "" +.TH TURN 1 "28 September 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 39c8bb08..e0c5e432 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -464,9 +464,9 @@ static char Usage[] = "Usage: turnserver [options]\n" " That database value can be changed on-the-fly\n" " by a separate program, so this is why it is 'dynamic'.\n" " Multiple shared secrets can be used (both in the database and in the \"static\" fashion).\n" -" --server-name Server name used (when necessary) for\n" -" the authentication purposes (oauth).\n" -" The default value is the FQDN of the host.\n" +" --server-name Server name used for\n" +" the oAuth authentication purposes.\n" +" The default value is the realm name.\n" " --oauth Support oAuth authentication.\n" " -n Do not use configuration file, take all parameters from the command line only.\n" " --cert Certificate file, PEM format. Same file search rules\n" @@ -1698,34 +1698,6 @@ static void drop_privileges(void) } } -static void init_oauth_server_name(void) { - - if(!turn_params.oauth_server_name[0]) { - - struct utsname name; - - if(uname(&name)>=0) { - STRCPY(turn_params.oauth_server_name,name.nodename); - } - if(!turn_params.oauth_server_name[0]) { - STRCPY(turn_params.oauth_server_name,"coturn"); - } - - size_t slen = strlen(turn_params.oauth_server_name); - - if(get_realm(NULL)->options.name[0]) { - turn_params.oauth_server_name[slen]='.'; - ns_bcopy(get_realm(NULL)->options.name,turn_params.oauth_server_name+slen+1,strlen(get_realm(NULL)->options.name)+1); - } else { - size_t dlen = strlen(turn_params.domain); - if(dlen>0 && turn_params.domain[0] != '(') { - turn_params.oauth_server_name[slen]='.'; - ns_bcopy(turn_params.domain,turn_params.oauth_server_name+slen+1,strlen(turn_params.domain)+1); - } - } - } -} - static void init_domain(void) { #if !defined(TURN_NO_GETDOMAINNAME) @@ -1841,10 +1813,9 @@ int main(int argc, char **argv) STRCPY(get_realm(NULL)->options.name,turn_params.domain); } - init_oauth_server_name(); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Domain name: %s\n",turn_params.domain); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Default realm: %s\n",get_realm(NULL)->options.name); - if(turn_params.oauth) { + if(turn_params.oauth && turn_params.oauth_server_name[0]) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "oAuth server name: %s\n",turn_params.oauth_server_name); } diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index a73bd589..795b724d 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1804,23 +1804,4 @@ void init_listener(void) ns_bzero(&turn_params.listener,sizeof(struct listener_server)); } -void get_oauth_server_name(const char* realm, char *server_name, size_t server_name_size) -{ - if(server_name && server_name_size) { - strncpy(server_name,turn_params.oauth_server_name,server_name_size); - if(realm && realm[0]) { - char* sat = strstr(server_name,"@"); - if(sat) { - *sat = 0; - } - size_t snl = strlen(server_name); - size_t rl = strlen(realm); - if(snl+1+rlstatus.alloc_counters); if (rp->options.perf_options.total_quota && (rp->status.total_current_allocs >= rp->options.perf_options.total_quota)) { @@ -712,17 +717,19 @@ int check_new_allocation_quota(u08bits *user, u08bits *realm) return ret; } -void release_allocation_quota(u08bits *user, u08bits *realm) +void release_allocation_quota(u08bits *user, int oauth, u08bits *realm) { if (user) { - u08bits *username = (u08bits*)get_real_username((char*)user); + u08bits *username = oauth ? (u08bits*)strdup("") : (u08bits*)get_real_username((char*)user); realm_params_t *rp = get_realm((char*)realm); ur_string_map_lock(rp->status.alloc_counters); - ur_string_map_value_type value = 0; - ur_string_map_get(rp->status.alloc_counters, (ur_string_map_key_type) username, &value); - if (value) { - value = (ur_string_map_value_type)(((size_t)value) - 1); - ur_string_map_put(rp->status.alloc_counters, (ur_string_map_key_type) username, value); + if(username[0]) { + ur_string_map_value_type value = 0; + ur_string_map_get(rp->status.alloc_counters, (ur_string_map_key_type) username, &value); + if (value) { + value = (ur_string_map_value_type)(((size_t)value) - 1); + ur_string_map_put(rp->status.alloc_counters, (ur_string_map_key_type) username, value); + } } if (rp->status.total_current_allocs) --(rp->status.total_current_allocs); diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index 036ea4f0..6e5b96fb 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -193,8 +193,8 @@ void add_to_secrets_list(secrets_list_t *sl, const char* elem); 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, u08bits *realm); -void release_allocation_quota(u08bits *username, u08bits *realm); +int check_new_allocation_quota(u08bits *username, int oauth, u08bits *realm); +void release_allocation_quota(u08bits *username, int oauth, u08bits *realm); /////////// Handle user DB ///////////////// diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index f673ff2a..3a29e8dd 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -265,8 +265,6 @@ void get_realm_options_by_name(char *realm, realm_options_t* ro); int get_canonic_origin(const char* o, char *co, int sz); int get_default_protocol_port(const char* scheme, size_t slen); -void get_oauth_server_name(const char* realm, char *server_name, size_t server_name_size); - /////////////////////////////////////// #ifdef __cplusplus diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index e60d66b8..7e3eaf6f 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -155,7 +155,7 @@ static int inc_quota(ts_ur_super_session* ss, u08bits *username) } } - if((((turn_turnserver*)ss->server)->chquotacb)(username, (u08bits*)ss->realm_options.name)<0) { + if((((turn_turnserver*)ss->server)->chquotacb)(username, ss->oauth, (u08bits*)ss->realm_options.name)<0) { return -1; @@ -183,7 +183,7 @@ static void dec_quota(ts_ur_super_session* ss) ss->bps = 0; } - (((turn_turnserver*)ss->server)->raqcb)(ss->username, (u08bits*)ss->realm_options.name); + (((turn_turnserver*)ss->server)->raqcb)(ss->username, ss->oauth, (u08bits*)ss->realm_options.name); } } @@ -1281,8 +1281,6 @@ static int handle_turn_allocate(turn_turnserver *server, if (*err_code) { - dec_quota(ss); - if(!(*reason)) { *reason = (const u08bits *)"Cannot create relay endpoint(s)"; } @@ -1364,6 +1362,22 @@ static int handle_turn_allocate(turn_turnserver *server, return 0; } +static void copy_auth_parameters(ts_ur_super_session *orig_ss, ts_ur_super_session *ss) { + if(orig_ss && ss) { + ns_bcopy(orig_ss->nonce,ss->nonce,sizeof(ss->nonce)); + ss->nonce_expiration_time = orig_ss->nonce_expiration_time; + ns_bcopy(&(orig_ss->realm_options),&(ss->realm_options),sizeof(ss->realm_options)); + ns_bcopy(orig_ss->username,ss->username,sizeof(ss->username)); + ss->hmackey_set = orig_ss->hmackey_set; + ns_bcopy(orig_ss->hmackey,ss->hmackey,sizeof(ss->hmackey)); + ss->oauth = orig_ss->oauth; + ns_bcopy(orig_ss->origin,ss->origin,sizeof(ss->origin)); + ss->origin_set = orig_ss->origin_set; + ns_bcopy(orig_ss->pwd,ss->pwd,sizeof(ss->pwd)); + ss->max_session_time_auth = orig_ss->max_session_time_auth; + } +} + static int handle_turn_refresh(turn_turnserver *server, ts_ur_super_session *ss, stun_tid *tid, int *resp_constructed, int *err_code, const u08bits **reason, u16bits *unknown_attrs, u16bits *ua_num, @@ -1550,17 +1564,7 @@ static int handle_turn_refresh(turn_turnserver *server, int postpone_reply = 0; if(!(ss->hmackey_set)) { - ns_bcopy(orig_ss->nonce,ss->nonce,sizeof(ss->nonce)); - ss->nonce_expiration_time = orig_ss->nonce_expiration_time; - ns_bcopy(&(orig_ss->realm_options),&(ss->realm_options),sizeof(ss->realm_options)); - ns_bcopy(orig_ss->username,ss->username,sizeof(ss->username)); - ss->hmackey_set = orig_ss->hmackey_set; - ns_bcopy(orig_ss->hmackey,ss->hmackey,sizeof(ss->hmackey)); - ss->oauth = orig_ss->oauth; - ns_bcopy(orig_ss->origin,ss->origin,sizeof(ss->origin)); - ss->origin_set = orig_ss->origin_set; - ns_bcopy(orig_ss->pwd,ss->pwd,sizeof(ss->pwd)); - ss->max_session_time_auth = orig_ss->max_session_time_auth; + copy_auth_parameters(orig_ss,ss); } if(check_stun_auth(server, ss, tid, resp_constructed, err_code, reason, in_buffer, nbh, @@ -1600,11 +1604,6 @@ static int handle_turn_refresh(turn_turnserver *server, *reason = (const u08bits *)"Cannot refresh relay connection (internal error)"; } - } else if(!to_delete && orig_ss && (inc_quota(orig_ss, orig_ss->username)<0)) { - - *err_code = 486; - *reason = (const u08bits *)"Allocation Quota Reached"; - } else { //Transfer socket: @@ -1614,16 +1613,18 @@ static int handle_turn_refresh(turn_turnserver *server, ss->to_be_closed = 1; if(!s) { - dec_quota(orig_ss); *err_code = 500; } else { if(attach_socket_to_session(server, s, orig_ss) < 0) { IOA_CLOSE_SOCKET(s); *err_code = 500; - dec_quota(orig_ss); } else { + if(ss->hmackey_set) { + copy_auth_parameters(ss,orig_ss); + } + delete_session_from_mobile_map(ss); delete_session_from_mobile_map(orig_ss); put_session_into_mobile_map(orig_ss); @@ -1663,7 +1664,6 @@ static int handle_turn_refresh(turn_turnserver *server, if ((server->fingerprint) || ss->enforce_fingerprints) { if (stun_attr_add_fingerprint_str(ioa_network_buffer_data(nbh), &len) < 0) { - dec_quota(ss); *err_code = 500; ioa_network_buffer_delete(server->e, nbh); return -1; @@ -3099,11 +3099,15 @@ static int create_challenge_response(ts_ur_super_session *ss, stun_tid *tid, int if(ss->server) { turn_turnserver* server = (turn_turnserver*)ss->server; - if(server->oauth && (server->oauth_server_name)&&(server->oauth_server_name[0])) { - stun_attr_add_str(ioa_network_buffer_data(nbh), &len, + if(server->oauth) { + const char *server_name = server->oauth_server_name; + if(!(server_name && server_name[0])) { + server_name = realm; + } + stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_THIRD_PARTY_AUTHORIZATION, - (const u08bits*)(server->oauth_server_name), - strlen(server->oauth_server_name)); + (const u08bits*)(server_name), + strlen(server_name)); } } @@ -3286,7 +3290,6 @@ static int check_stun_auth(turn_turnserver *server, if(ss->oauth) { ss->hmackey_set = 0; STRCPY(ss->username,usname); - set_realm_hash(ss->client_socket,(u08bits*)ss->realm_options.name); } else { if(method == STUN_METHOD_ALLOCATE) { *err_code = 437; diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index 91ac0136..3506e617 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -92,8 +92,8 @@ 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 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, u08bits *realm); -typedef void (*release_allocation_quota_cb)(u08bits *username, u08bits *realm); +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); From 55eb21b5b73447a2ebb57d91ef57b52c4ae4ef91 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 29 Sep 2014 04:18:50 +0000 Subject: [PATCH 225/805] docs fixes. --- INSTALL | 63 +++++++++++++++++++++++++++++++++++++++-------- README.turnserver | 2 +- 2 files changed, 54 insertions(+), 11 deletions(-) diff --git a/INSTALL b/INSTALL index 258bec21..d158a1c9 100644 --- a/INSTALL +++ b/INSTALL @@ -706,6 +706,15 @@ CREATE TABLE turnusers_lt ( PRIMARY KEY (realm,name) ); +The field hmackey contains HEX string representation of the key. +We do not store the user open passwords for long-term credentials, for security reasons. +Storing only the HMAC key has its own implications - if you change the realm, +you will have to update the HMAC keys of all users, because the realm is +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 ( @@ -760,19 +769,10 @@ CREATE TABLE turn_realm_option ( primary key (realm,opt) ); -The field hmackey contains HEX string representation of the key. -We do not store the user open passwords for long-term credentials, for security reasons. -Storing only the HMAC key has its own implications - if you change the realm, -you will have to update the HMAC keys of all users, because the realm is -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. - # oAuth key storage table. # CREATE TABLE oauth_key ( - kid varchar(128), + kid varchar(128), /* ikm_key varchar(256) default '', timestamp bigint default 0, lifetime integer default 0, @@ -784,6 +784,42 @@ CREATE TABLE oauth_key ( primary key (kid) ); +The oauth_key table fields meanings are: + + kid: the kid of the key; + + ikm_key - (optional) base64-encoded key ("input keying material"); + The ikm_key is not needed if the as_rs_key and auth_key are defined + explicitly in the database; + + timestamp - (optional) the timestamp (in seconds) when the key + lifetime started; + + lifetime - (optional) the key lifetime in seconds; the default value + is 0 - unlimited lifetime. + + hkdf_hash_func - (optional) hash function for HKDF procedure; the + valid values are SHA-1 and SHA-256, with SHA-256 as default; + The hkdf_hash_func is not needed if the as_rs_key and auth_key + are defined explicitly in the database; + + as_rs_alg - oAuth token encryption algorithm; the valid values are + "AES-128-CBC" and "AES-256-CBC", , "AEAD-AES-128-GCM", + "AEAD-AES-256-GCM". + The default value is "AES-256-CBC"; + + as_rs_key - (optional) base64-encoded AS-RS key. If not defined, then + calculated with ikm_key and hkdf_hash_func. The as_rs_key length + is defined by as_rs_alg. + + auth_alg - (optional) oAuth token authentication algorithm; the valid values are + "HMAC-SHA-256-128", "HMAC-SHA-256" and "HMAC-SHA-1". + The default value is "HMAC-SHA-256-128". + + 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. + 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. @@ -945,6 +981,11 @@ Or in the turnserver.conf file: mongo-userdb="mongodb://localhost:27017/turndb" +The meanings of the MongoDB keys are the same as for the other databases, see the +explanations for the Postgres, for example. + +See the file testmongosetup.sh for the database structure examples. + XVII. Redis setup The Redis setup is well documented on their site http://redis.io. @@ -1013,6 +1054,8 @@ Redis TURN admin commands: $ bin/turnadmin -A -N "host=localhost dbname=0 user=turn password=turn" -u gorst -r north.gov -p hero $ bin/turnadmin -A -N "host=localhost dbname=0 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + +See the file testredisdbsetup.sh for the data structure examples. XVIII. Performance tuning diff --git a/README.turnserver b/README.turnserver index cb339a2a..31812e4e 100644 --- a/README.turnserver +++ b/README.turnserver @@ -190,7 +190,7 @@ Flags: 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. +--oauth Support oAuth authentication, as in the third-party TURN specs document. --dh566 Use 566 bits predefined DH TLS key. Default size of the key is 1066. From 26fb56d1642368186f5a7ff032ff78956d692d41 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 29 Sep 2014 07:11:29 +0000 Subject: [PATCH 226/805] sql db schema fixed --- turndb/testsqldbsetup.sql | 2 -- 1 file changed, 2 deletions(-) diff --git a/turndb/testsqldbsetup.sql b/turndb/testsqldbsetup.sql index d53fb94a..19e92eba 100644 --- a/turndb/testsqldbsetup.sql +++ b/turndb/testsqldbsetup.sql @@ -29,5 +29,3 @@ insert into denied_peer_ip (ip_range) values('123::45'); insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('north','Y2FybGVvbg==',0,0,'SHA-256','AES-256-CBC','','HMAC-SHA-256-128',''); insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('oldempire','YXVsY3Vz',0,0,'SHA-256','AEAD-AES-256-GCM','','',''); - -); From e04cd2c49268065f3144f9f7f0fecd5348987069 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 29 Sep 2014 07:34:43 +0000 Subject: [PATCH 227/805] time fix --- src/apps/relay/userdb.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index b5f136a5..5292ef03 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -515,10 +515,6 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u } if(max_session_time) { *max_session_time = to - ct; - if(*max_session_time > OAUTH_TIME_DELTA) - *max_session_time -= OAUTH_TIME_DELTA; - if(*max_session_time < OAUTH_TIME_DELTA) - *max_session_time = OAUTH_TIME_DELTA; } } From 5bde0026b0ade5c7db315271a1e290cace062496 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 29 Sep 2014 08:57:39 +0000 Subject: [PATCH 228/805] test client improved --- src/apps/uclient/mainuclient.c | 3 --- src/apps/uclient/uclient.c | 8 ++------ 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index b2372372..4bff0ee0 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -426,9 +426,6 @@ int main(int argc, char **argv) otoken_array[1].enc_block.key_length = 20; break; }; - - RAND_bytes((unsigned char *)(otoken_array[0].enc_block.mac_key), otoken_array[0].enc_block.key_length); - RAND_bytes((unsigned char *)(otoken_array[1].enc_block.mac_key), otoken_array[1].enc_block.key_length); } if(g_use_auth_secret_with_timestamp) { diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 865f766d..74194dba 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1446,6 +1446,7 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) u08bits nonce[12]; RAND_bytes((unsigned char*)nonce,12); otoken_array[cok].enc_block.timestamp = ((uint64_t)turn_time()) << 16; + RAND_bytes((unsigned char *)(otoken_array[cok].enc_block.mac_key), otoken_array[cok].enc_block.key_length); if(encode_oauth_token(clnet_info->server_name, &etoken, &(okey_array[cok]), &(otoken_array[cok]), nonce)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot encode token\n"); return -1; @@ -1490,15 +1491,10 @@ int check_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) if(oauth && clnet_info->oauth) { - hmackey_t key; st_password_t pwd; - int cok = clnet_info->cok; - - ns_bcopy(otoken_array[cok].enc_block.mac_key,key,otoken_array[cok].enc_block.key_length); - return stun_check_message_integrity_by_key_str(get_turn_credentials_type(), - message->buf, (size_t)(message->len), key, pwd, sht, NULL); + message->buf, (size_t)(message->len), clnet_info->key, pwd, sht, NULL); } else { From 879a91f5db8974de0fc7c7e2be530cac569512b6 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 29 Sep 2014 16:40:32 +0000 Subject: [PATCH 229/805] uclient improved --- src/apps/uclient/mainuclient.c | 21 --------------------- src/apps/uclient/uclient.c | 22 ++++++++++++++++++---- src/apps/uclient/uclient.h | 1 - 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 4bff0ee0..646831dc 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -100,7 +100,6 @@ int dual_allocation = 0; int oauth = 0; oauth_key okey_array[2]; -oauth_token otoken_array[2]; static oauth_key_data_raw okdr_array[2] = { {"north","Y2FybGVvbg==",0,0,"SHA-256","AES-256-CBC","","HMAC-SHA-256-128",""}, @@ -408,26 +407,6 @@ int main(int argc, char **argv) } } - if(oauth) { - - otoken_array[0].enc_block.lifetime = OAUTH_SESSION_LIFETIME; - otoken_array[0].enc_block.timestamp = 0; - - otoken_array[1].enc_block.lifetime = OAUTH_SESSION_LIFETIME; - otoken_array[1].enc_block.timestamp = 0; - - switch(shatype) { - case SHATYPE_SHA256: - otoken_array[0].enc_block.key_length = 32; - otoken_array[1].enc_block.key_length = 32; - break; - default: - otoken_array[0].enc_block.key_length = 20; - otoken_array[1].enc_block.key_length = 20; - break; - }; - } - if(g_use_auth_secret_with_timestamp) { if(use_short_term) { diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 74194dba..a2142aa2 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1442,19 +1442,33 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) cok=(++(clnet_info->cok))%2; clnet_info->cok = cok; + oauth_token otoken; encoded_oauth_token etoken; u08bits nonce[12]; RAND_bytes((unsigned char*)nonce,12); - otoken_array[cok].enc_block.timestamp = ((uint64_t)turn_time()) << 16; - RAND_bytes((unsigned char *)(otoken_array[cok].enc_block.mac_key), otoken_array[cok].enc_block.key_length); - if(encode_oauth_token(clnet_info->server_name, &etoken, &(okey_array[cok]), &(otoken_array[cok]), nonce)<0) { + long halflifetime = OAUTH_SESSION_LIFETIME/2; + long random_lifetime = 0; + while(!random_lifetime) { + random_lifetime = random(); + } + if(random_lifetime<0) random_lifetime=-random_lifetime; + random_lifetime = random_lifetime % halflifetime; + otoken.enc_block.lifetime = (uint32_t)(halflifetime + random_lifetime); + otoken.enc_block.timestamp = ((uint64_t)turn_time()) << 16; + if(shatype == SHATYPE_SHA256) { + otoken.enc_block.key_length = 32; + } else { + otoken.enc_block.key_length = 20; + } + RAND_bytes((unsigned char *)(otoken.enc_block.mac_key), otoken.enc_block.key_length); + if(encode_oauth_token(clnet_info->server_name, &etoken, &(okey_array[cok]), &otoken, nonce)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot encode token\n"); return -1; } stun_attr_add_str(message->buf, (size_t*)&(message->len), STUN_ATTRIBUTE_OAUTH_ACCESS_TOKEN, (const u08bits*)etoken.token, (int)etoken.size); - ns_bcopy(otoken_array[cok].enc_block.mac_key,clnet_info->key,otoken_array[cok].enc_block.key_length); + ns_bcopy(otoken.enc_block.mac_key,clnet_info->key,otoken.enc_block.key_length); clnet_info->key_set = 1; } diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index 734de669..8891f988 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -88,7 +88,6 @@ extern char origin[STUN_MAX_ORIGIN_SIZE+1]; extern int oauth; extern oauth_key okey_array[2]; -extern oauth_token otoken_array[2]; #define UCLIENT_SESSION_LIFETIME (777) #define OAUTH_SESSION_LIFETIME (555) From 00e1cc1bf49c7466d2b0c63c8f88fb2ba3509c28 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 29 Sep 2014 16:43:22 +0000 Subject: [PATCH 230/805] uclient improved --- src/apps/uclient/uclient.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index a2142aa2..65a46d41 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1440,7 +1440,8 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) if(((method == STUN_METHOD_ALLOCATE) || (method == STUN_METHOD_REFRESH)) || !(clnet_info->key_set)) { - cok=(++(clnet_info->cok))%2; + cok=(random())%2; + if(cok<0) cok=-cok; clnet_info->cok = cok; oauth_token otoken; encoded_oauth_token etoken; From a54da85c1239f283b8686468ee27ee582b8e9f76 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 29 Sep 2014 18:11:29 +0000 Subject: [PATCH 231/805] quota fixed --- src/server/ns_turn_server.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 7e3eaf6f..8aa8a82b 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1364,6 +1364,7 @@ static int handle_turn_allocate(turn_turnserver *server, static void copy_auth_parameters(ts_ur_super_session *orig_ss, ts_ur_super_session *ss) { if(orig_ss && ss) { + dec_quota(ss); ns_bcopy(orig_ss->nonce,ss->nonce,sizeof(ss->nonce)); ss->nonce_expiration_time = orig_ss->nonce_expiration_time; ns_bcopy(&(orig_ss->realm_options),&(ss->realm_options),sizeof(ss->realm_options)); @@ -1375,6 +1376,7 @@ static void copy_auth_parameters(ts_ur_super_session *orig_ss, ts_ur_super_sessi ss->origin_set = orig_ss->origin_set; ns_bcopy(orig_ss->pwd,ss->pwd,sizeof(ss->pwd)); ss->max_session_time_auth = orig_ss->max_session_time_auth; + inc_quota(ss,ss->username); } } @@ -1631,7 +1633,11 @@ static int handle_turn_refresh(turn_turnserver *server, //Use new buffer and redefine ss: nbh = ioa_network_buffer_allocate(server->e); + + dec_quota(ss); ss = orig_ss; + inc_quota(ss,ss->username); + ss->old_mobile_id = mid; size_t len = ioa_network_buffer_get_size(nbh); From e897762728a6aae70dc9ea99c0d55a17d19f1c29 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 30 Sep 2014 08:29:09 +0000 Subject: [PATCH 232/805] minor fixes --- src/apps/relay/netengine.c | 2 +- src/client/ns_turn_msg.c | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 795b724d..cc1118eb 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -732,7 +732,7 @@ static int handle_relay_message(relay_server_handle rs, struct message_to_relay turnserver_accept_tcp_client_data_connection(&(rs->server), sm->m.cb_sm.connection_id, &(sm->m.cb_sm.tid), sm->m.cb_sm.s, sm->m.cb_sm.message_integrity, &(sm->m.cb_sm.nd), - sm->m.cb_sm.can_resume); + /*sm->m.cb_sm.can_resume*//* we cannot resume this call, it must be authenticated in-place:*/0); ioa_network_buffer_delete(rs->ioa_eng, sm->m.cb_sm.nd.nbh); sm->m.cb_sm.nd.nbh = NULL; diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 3ea77448..29571f40 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -340,6 +340,9 @@ int stun_is_challenge_response_str(const u08bits* buf, size_t len, int *err_code stun_attr_ref sar = stun_attr_get_first_by_type_str(buf,len,STUN_ATTRIBUTE_REALM); if(sar) { + + int found_oauth = 0; + const u08bits *value = stun_attr_get_value(sar); if(value) { size_t vlen = (size_t)stun_attr_get_len(sar); @@ -356,9 +359,7 @@ int stun_is_challenge_response_str(const u08bits* buf, size_t len, int *err_code if(server_name) { ns_bcopy(value,server_name,vlen); } - if(oauth) { - *oauth = 1; - } + found_oauth = 1; } } } @@ -371,6 +372,9 @@ int stun_is_challenge_response_str(const u08bits* buf, size_t len, int *err_code vlen = (size_t)stun_attr_get_len(sar); ns_bcopy(value,nonce,vlen); nonce[vlen]=0; + if(oauth) { + *oauth = found_oauth; + } return 1; } } From b8a775b5f2563868ead9fd8587faf11870b37fed Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 30 Sep 2014 17:34:08 +0000 Subject: [PATCH 233/805] cosmetics --- src/apps/relay/netengine.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index cc1118eb..98c56b87 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -732,7 +732,13 @@ static int handle_relay_message(relay_server_handle rs, struct message_to_relay turnserver_accept_tcp_client_data_connection(&(rs->server), sm->m.cb_sm.connection_id, &(sm->m.cb_sm.tid), sm->m.cb_sm.s, sm->m.cb_sm.message_integrity, &(sm->m.cb_sm.nd), - /*sm->m.cb_sm.can_resume*//* we cannot resume this call, it must be authenticated in-place:*/0); + /*sm->m.cb_sm.can_resume*/ + /* Note: we cannot resume this call, it must be authenticated in-place. + * There are two reasons for that: + * 1) Technical. That's very difficult with the current code structure. + * 2) Security (more important). We do not want 'stealing' connections between the users. + * */ + 0); ioa_network_buffer_delete(rs->ioa_eng, sm->m.cb_sm.nd.nbh); sm->m.cb_sm.nd.nbh = NULL; From a0308d7f058e49077ed8cad382611ee590395090 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 2 Oct 2014 05:23:58 +0000 Subject: [PATCH 234/805] core dump fixed --- src/apps/relay/ns_ioalib_engine_impl.c | 14 +++++++++++--- src/server/ns_turn_server.c | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 157bd51d..3a87eb8f 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1859,7 +1859,7 @@ void set_ioa_socket_app_type(ioa_socket_handle s, SOCKET_APP_TYPE sat) { if(s) s->sat = sat; } - + ioa_addr* get_local_addr_from_ioa_socket(ioa_socket_handle s) { if (s && (s->magic == SOCKET_MAGIC) && !(s->done)) { @@ -1893,7 +1893,11 @@ ioa_addr* get_local_addr_from_ioa_socket(ioa_socket_handle s) } } } - return NULL; + + { + static ioa_addr lbad_addr; + return &lbad_addr; + } } ioa_addr* get_remote_addr_from_ioa_socket(ioa_socket_handle s) @@ -1904,7 +1908,11 @@ ioa_addr* get_remote_addr_from_ioa_socket(ioa_socket_handle s) return &(s->remote_addr); } } - return NULL; + + { + static ioa_addr rbad_addr; + return &rbad_addr; + } } int get_local_mtu_ioa_socket(ioa_socket_handle s) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 8aa8a82b..98a0383b 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1394,7 +1394,7 @@ static int handle_turn_refresh(turn_turnserver *server, { int i; for(i = 0;irelay_sessions[i].s) { + if(a->relay_sessions[i].s && !ioa_socket_tobeclosed(a->relay_sessions[i].s)) { int family = get_local_addr_from_ioa_socket(a->relay_sessions[i].s)->ss.sa_family; if(AF_INET == family) { af4c = 1; From 55c13bfa461e8dba62c0078a1e6b26a98f2185f2 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 2 Oct 2014 05:42:16 +0000 Subject: [PATCH 235/805] changelog updated. --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 4fdbf85d..cda992b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,8 @@ Version 4.2.1.1 'Monza': - Mobility ticket retransmission fixed. - Move debian package from SVN to GIT. - Move secondary download area to coturn.net. + - Auota allocation fixed. + - Core dump fixed. 08/14/2014 Oleg Moskalenko Version 4.1.2.1 'Vitari': From caada86ab7890cb670a8bce9a8667cfb49700133 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 3 Oct 2014 05:31:52 +0000 Subject: [PATCH 236/805] cosmetics --- src/apps/relay/turncli.c | 4 ++-- src/server/ns_turn_server.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index 6b3a2306..5c4bf5b2 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -820,9 +820,9 @@ static void cli_print_configuration(struct cli_session* cs) cli_print_flag(cs,1,"Short-term authorization mechanism",0); else cli_print_flag(cs,1,"Anonymous credentials",0); - cli_print_flag(cs,turn_params.use_auth_secret_with_timestamp,"REST API support",0); + cli_print_flag(cs,turn_params.use_auth_secret_with_timestamp,"TURN REST API support",0); if(turn_params.use_auth_secret_with_timestamp && turn_params.rest_api_separator) - cli_print_uint(cs,turn_params.rest_api_separator,"REST API separator ASCII number",0); + cli_print_uint(cs,turn_params.rest_api_separator,"TURN REST API separator ASCII number",0); myprintf(cs,"\n"); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 98a0383b..b9aa96f0 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4498,6 +4498,7 @@ static int read_client_connection(turn_turnserver *server, 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))) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTP request: %s\n", __FUNCTION__, (char*)ioa_network_buffer_data(in_buffer->nbh)); write_http_echo(server,ss); } } From ee20e42feae27cb972de55a07d4b0ade1b89b801 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 3 Oct 2014 05:38:08 +0000 Subject: [PATCH 237/805] status updated --- STATUS | 2 ++ TODO | 15 ++++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/STATUS b/STATUS index 6d4090fa..d5cd76e0 100644 --- a/STATUS +++ b/STATUS @@ -104,6 +104,8 @@ compatibility. 44) Double (dual) allocation added (SSODA draft). 45) Secure MySQL connection implemented. + +46) Third-party security mechanism (through oAuth) implemented. Things to be implemented in future (the development roadmap) are described in the TODO file. diff --git a/TODO b/TODO index 56ebc9b2..ead7305b 100644 --- a/TODO +++ b/TODO @@ -47,7 +47,6 @@ ================================================================== -1) New security oAuth draft. ================================================================== @@ -57,15 +56,13 @@ 1) For extra difficult NAT/FWs, consider implementing Websockets. -2) MS TURN, MS STUN extensions. +2) ALPN with TLS and DTLS (when OpenSSL 1.0.2 is available). -3) ALPN with TLS and DTLS (when OpenSSL 1.0.2 is available). +3) Redirect draft. -4) Redirect draft. +4) DTLS 1.2 (when available). -5) DTLS 1.2 (when available). - -7) TURN Proxy ? http://tools.ietf.org/html/draft-schwartz-rtcweb-return-00 +5) TURN Proxy ? http://tools.ietf.org/html/draft-schwartz-rtcweb-return-00 ================================================================== @@ -97,6 +94,10 @@ 4) Ganglia monitoring. +5) Web API to the database (oAuth keys, for example). + +6) Key exchange mechanism for oAuth. + ================================================================== ### VIII. CODING STUFF ### From 0856920e29de26beb6b684e5f98bc3c3a52221f2 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 4 Oct 2014 07:55:58 +0000 Subject: [PATCH 238/805] fixes --- src/apps/relay/netengine.c | 3 ++- src/apps/relay/ns_ioalib_engine_impl.c | 9 +++++---- src/server/ns_turn_server.c | 19 +++++++++++-------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 98c56b87..5ca674fc 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -457,7 +457,6 @@ static int send_socket_to_general_relay(ioa_engine_handle e, struct message_to_r int success = 0; if(!rdest) { - success = -1; goto label_end; } @@ -719,6 +718,7 @@ static int handle_relay_message(relay_server_handle rs, struct message_to_relay "%s: socket wrongly preset: 0x%lx : 0x%lx\n", __FUNCTION__, (long) s->read_event, (long) s->bev); IOA_CLOSE_SOCKET(s); + sm->m.sm.s = NULL; } else { s->e = rs->ioa_eng; open_client_connection_session(&(rs->server), &(sm->m.sm)); @@ -756,6 +756,7 @@ static int handle_relay_message(relay_server_handle rs, struct message_to_relay "%s: mobile socket wrongly preset: 0x%lx : 0x%lx\n", __FUNCTION__, (long) s->read_event, (long) s->bev); IOA_CLOSE_SOCKET(s); + sm->m.sm.s = NULL; } else { s->e = rs->ioa_eng; open_client_connection_session(&(rs->server), &(sm->m.sm)); diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 3a87eb8f..d297ff73 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1530,6 +1530,7 @@ static void set_socket_ssl(ioa_socket_handle s, SSL *ssl) if(s && (s->ssl != ssl)) { if(s->ssl) { SSL_set_app_data(s->ssl,NULL); + SSL_set_info_callback(s->ssl, (ssl_info_callback_t)NULL); } s->ssl = ssl; if(ssl) { @@ -1615,16 +1616,16 @@ void detach_socket_net_data(ioa_socket_handle s) if(s->list_ev) { evconnlistener_free(s->list_ev); s->list_ev = NULL; - s->acb = NULL; - s->acbarg = NULL; } + s->acb = NULL; + s->acbarg = NULL; if(s->conn_bev) { bufferevent_disable(s->conn_bev,EV_READ|EV_WRITE); bufferevent_free(s->conn_bev); s->conn_bev=NULL; - s->conn_arg=NULL; - s->conn_cb=NULL; } + s->conn_arg=NULL; + s->conn_cb=NULL; if(s->bev) { bufferevent_disable(s->bev,EV_READ|EV_WRITE); bufferevent_free(s->bev); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index b9aa96f0..ed1b2db5 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1543,7 +1543,7 @@ static int handle_turn_refresh(turn_turnserver *server, } else { ts_ur_super_session *orig_ss = get_session_from_mobile_map(server, mid); - if(!orig_ss) { + if(!orig_ss || orig_ss->to_be_closed || ioa_socket_tobeclosed(orig_ss->client_socket)) { *err_code = 404; *reason = (const u08bits *)"Allocation not found"; } else if(orig_ss == ss) { @@ -1619,7 +1619,9 @@ static int handle_turn_refresh(turn_turnserver *server, } else { if(attach_socket_to_session(server, s, orig_ss) < 0) { - IOA_CLOSE_SOCKET(s); + if(orig_ss->client_socket != s) { + IOA_CLOSE_SOCKET(s); + } *err_code = 500; } else { @@ -2017,8 +2019,10 @@ static int tcp_start_connection_to_peer(turn_turnserver *server, ts_ur_super_ses } tc->state = TC_STATE_CLIENT_TO_PEER_CONNECTING; - IOA_CLOSE_SOCKET(tc->peer_s); - tc->peer_s = tcs; + if(tc->peer_s != tcs) { + IOA_CLOSE_SOCKET(tc->peer_s); + tc->peer_s = tcs; + } set_ioa_socket_sub_session(tc->peer_s,tc); FUNCEND; @@ -2086,8 +2090,7 @@ static void tcp_peer_accept_connection(ioa_socket_handle s, void *arg) if(register_callback_on_ioa_socket(server->e, s, IOA_EV_READ, tcp_peer_input_handler, tc, 1)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: cannot set TCP peer data input callback\n", __FUNCTION__); - close_ioa_socket(s); - tc->peer_s = NULL; + IOA_CLOSE_SOCKET(tc->peer_s); tc->state = TC_STATE_UNKNOWN; FUNCEND; return; @@ -4378,7 +4381,7 @@ static int read_client_connection(turn_turnserver *server, FUNCSTART; - if (!server || !ss || !in_buffer || !(ss->client_socket)) { + if (!server || !ss || !in_buffer || !(ss->client_socket) || ss->to_be_closed || ioa_socket_tobeclosed(ss->client_socket)) { FUNCEND; return -1; } @@ -4514,7 +4517,7 @@ static int attach_socket_to_session(turn_turnserver* server, ioa_socket_handle s int ret = -1; FUNCSTART; - if(s && server && ss) { + if(s && server && ss && !ioa_socket_tobeclosed(s)) { if(ss->client_socket != s) { From 79ff9f7dfaa1139899476a5d1bb654fd19c43fca Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 4 Oct 2014 08:50:27 +0000 Subject: [PATCH 239/805] fixes --- src/apps/relay/ns_ioalib_engine_impl.c | 14 +++++--------- src/client/ns_turn_msg.c | 8 +++++--- src/server/ns_turn_server.c | 15 ++++++++++----- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index d297ff73..03af0d6c 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1478,18 +1478,20 @@ ioa_socket_handle create_ioa_socket_from_fd(ioa_engine_handle e, ret->magic = SOCKET_MAGIC; ret->fd = fd; - ret->family = local_addr->ss.sa_family; ret->st = st; ret->sat = sat; ret->e = e; if (local_addr) { + ret->family = local_addr->ss.sa_family; ret->bound = 1; addr_cpy(&(ret->local_addr), local_addr); } if (remote_addr) { ret->connected = 1; + if(!(ret->family)) + ret->family = remote_addr->ss.sa_family; addr_cpy(&(ret->remote_addr), remote_addr); } @@ -1895,10 +1897,7 @@ ioa_addr* get_local_addr_from_ioa_socket(ioa_socket_handle s) } } - { - static ioa_addr lbad_addr; - return &lbad_addr; - } + return NULL; } ioa_addr* get_remote_addr_from_ioa_socket(ioa_socket_handle s) @@ -1910,10 +1909,7 @@ ioa_addr* get_remote_addr_from_ioa_socket(ioa_socket_handle s) } } - { - static ioa_addr rbad_addr; - return &rbad_addr; - } + return NULL; } int get_local_mtu_ioa_socket(ioa_socket_handle s) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 29571f40..aa48440d 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -866,12 +866,14 @@ int stun_set_binding_response_str(u08bits* buf, size_t *len, stun_tid* tid, } else { old_stun_init_success_response_str(STUN_METHOD_BINDING, buf, len, tid, cookie); } - if(!old_stun) { + if(!old_stun && reflexive_addr) { if (stun_attr_add_addr_str(buf, len, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, reflexive_addr) < 0) return -1; } - if (stun_attr_add_addr_str(buf, len, STUN_ATTRIBUTE_MAPPED_ADDRESS, reflexive_addr) < 0) - return -1; + if(reflexive_addr) { + if (stun_attr_add_addr_str(buf, len, STUN_ATTRIBUTE_MAPPED_ADDRESS, reflexive_addr) < 0) + return -1; + } } else if (!old_stun) { stun_init_error_response_str(STUN_METHOD_BINDING, buf, len, error_code, reason, tid); } else { diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index ed1b2db5..9451b5f6 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1395,7 +1395,7 @@ static int handle_turn_refresh(turn_turnserver *server, int i; for(i = 0;irelay_sessions[i].s && !ioa_socket_tobeclosed(a->relay_sessions[i].s)) { - int family = get_local_addr_from_ioa_socket(a->relay_sessions[i].s)->ss.sa_family; + int family = get_ioa_socket_address_family(a->relay_sessions[i].s); if(AF_INET == family) { af4c = 1; } else if(AF_INET6 == family) { @@ -2045,6 +2045,11 @@ static void tcp_peer_accept_connection(ioa_socket_handle s, void *arg) allocation *a = &(ss->alloc); ioa_addr *peer_addr = get_remote_addr_from_ioa_socket(s); + if(!peer_addr) { + close_ioa_socket(s); + FUNCEND; + return; + } tcp_connection *tc = get_tcp_connection_by_peer(a, peer_addr); if(tc) { @@ -2731,7 +2736,7 @@ static int handle_turn_binding(turn_turnserver *server, ; - } else if(ss->client_socket) { + } else if(ss->client_socket && get_remote_addr_from_ioa_socket(ss->client_socket)) { size_t len = ioa_network_buffer_get_size(nbh); if (stun_set_binding_response_str(ioa_network_buffer_data(nbh), &len, tid, @@ -4301,8 +4306,8 @@ static int create_relay_connection(turn_turnserver* server, } /* RFC6156: do not use DF when IPv6 is involved: */ - if((get_local_addr_from_ioa_socket(newelem->s)->ss.sa_family == AF_INET6) || - (get_local_addr_from_ioa_socket(ss->client_socket)->ss.sa_family == AF_INET6)) + if((get_ioa_socket_address_family(newelem->s) == AF_INET6) || + (get_ioa_socket_address_family(ss->client_socket) == AF_INET6)) set_do_not_use_df(newelem->s); if(get_ioa_socket_type(newelem->s) != TCP_SOCKET) { @@ -4318,7 +4323,7 @@ static int create_relay_connection(turn_turnserver* server, ioa_timer_handle ev = set_ioa_timer(server->e, lifetime, 0, client_ss_allocation_timeout_handler, newelem, 0, "client_ss_allocation_timeout_handler"); - set_allocation_lifetime_ev(a, server->ctime + lifetime, ev, get_local_addr_from_ioa_socket(newelem->s)->ss.sa_family); + set_allocation_lifetime_ev(a, server->ctime + lifetime, ev, get_ioa_socket_address_family(newelem->s)); set_ioa_socket_session(newelem->s, ss); } From bddda9da650fc44af8cb9d435038bf16c45b36c8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 5 Oct 2014 07:12:48 +0000 Subject: [PATCH 240/805] minor changes --- src/server/ns_turn_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 9451b5f6..b385cfde 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1543,7 +1543,7 @@ static int handle_turn_refresh(turn_turnserver *server, } else { ts_ur_super_session *orig_ss = get_session_from_mobile_map(server, mid); - if(!orig_ss || orig_ss->to_be_closed || ioa_socket_tobeclosed(orig_ss->client_socket)) { + if(!orig_ss) { *err_code = 404; *reason = (const u08bits *)"Allocation not found"; } else if(orig_ss == ss) { From 7ce481bcf8b99530785512f37e119690c64f7024 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 5 Oct 2014 07:14:41 +0000 Subject: [PATCH 241/805] version bump --- ChangeLog | 4 ++-- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 6 +++--- src/ns_turn_defs.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index cda992b8..bac14448 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ -08/22/2014 Oleg Moskalenko -Version 4.2.1.1 'Monza': +10/05/2014 Oleg Moskalenko +Version 4.2.1.2 'Monza': - oAuth security experimental implementation; - The "TLS renegotiation" DoS attack prevention implemented; - FQDN as relay-ip and listener-ip parameters (issue 6) diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index cf368334..84d5ac35 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.2.1.1 +TURNVERSION=4.2.1.2 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index bc61f5b6..a014ae7e 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.2.1.1 +Version: 4.2.1.2 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,8 +294,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Wed Sep 24 2014 Oleg Moskalenko - - Sync to 4.2.1.1 +* Sun Oct 05 2014 Oleg Moskalenko + - Sync to 4.2.1.2 * Thu Aug 14 2014 Oleg Moskalenko - Sync to 4.1.2.1 * Tue Jul 29 2014 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 9e166ea8..b5ba7279 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.2.1.1" +#define TURN_SERVER_VERSION "4.2.1.2" #define TURN_SERVER_VERSION_NAME "Monza" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 0204f7b0fef822a5de27e86df3353139a047822c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 5 Oct 2014 23:55:42 +0000 Subject: [PATCH 242/805] fixes --- src/apps/relay/ns_ioalib_engine_impl.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 03af0d6c..1771694c 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -3642,8 +3642,11 @@ void* allocate_super_memory_region_func(super_memory_t *r, size_t size, const ch UNUSED_ARG(func); UNUSED_ARG(line); - if(!r) - return malloc(size); + if(!r) { + void *ret = malloc(size); + ns_bzero(ret, size); + return ret; + } void *ret = NULL; @@ -3697,8 +3700,10 @@ void* allocate_super_memory_region_func(super_memory_t *r, size_t size, const ch pthread_mutex_unlock(&r->mutex_sm); - if(!ret) + if(!ret) { ret = malloc(size); + ns_bzero(ret, size); + } return ret; } From b0a4a5389a08c3fe55060ce49ac44c48ec250d7f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 6 Oct 2014 00:01:48 +0000 Subject: [PATCH 243/805] fixes --- src/apps/relay/ns_ioalib_engine_impl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 1771694c..e834ec30 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -3642,14 +3642,14 @@ void* allocate_super_memory_region_func(super_memory_t *r, size_t size, const ch UNUSED_ARG(func); UNUSED_ARG(line); + void *ret = NULL; + if(!r) { - void *ret = malloc(size); + ret = malloc(size); ns_bzero(ret, size); return ret; } - void *ret = NULL; - pthread_mutex_lock(&r->mutex_sm); size = ((size_t)((size+sizeof(void*))/(sizeof(void*)))) * sizeof(void*); From c0fc90a468182dc4ae49b68a239bd2f38f08cc57 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 6 Oct 2014 06:15:53 +0000 Subject: [PATCH 244/805] fixes --- src/server/ns_turn_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index b385cfde..9451b5f6 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1543,7 +1543,7 @@ static int handle_turn_refresh(turn_turnserver *server, } else { ts_ur_super_session *orig_ss = get_session_from_mobile_map(server, mid); - if(!orig_ss) { + if(!orig_ss || orig_ss->to_be_closed || ioa_socket_tobeclosed(orig_ss->client_socket)) { *err_code = 404; *reason = (const u08bits *)"Allocation not found"; } else if(orig_ss == ss) { From bdf281e64800287473b14a6b608979e4d970f6c0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 7 Oct 2014 00:31:39 +0000 Subject: [PATCH 245/805] connect fixes --- src/apps/relay/netengine.c | 1 + src/server/ns_turn_server.c | 59 ++++++++++++++++++++++++------------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 5ca674fc..9ce59243 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -457,6 +457,7 @@ static int send_socket_to_general_relay(ioa_engine_handle e, struct message_to_r int success = 0; if(!rdest) { + success = -1; goto label_end; } diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 9451b5f6..75053e65 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1911,8 +1911,18 @@ static void tcp_peer_connection_completed_callback(int success, void *arg) } else { tc->state = TC_STATE_FAILED; - if(!err_code) + if(!err_code) { err_code = 447; + } + { + char ls[257]="\0"; + char rs[257]="\0"; + ioa_addr *laddr = get_local_addr_from_ioa_socket(ss->client_socket); + if(laddr) + addr_to_string(laddr,(u08bits*)ls); + addr_to_string(&(tc->peer_addr),(u08bits*)rs); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: failure to connect from %s to %s\n", __FUNCTION__, ls,rs); + } const u08bits *reason = (const u08bits *)"Connection Timeout or Failure"; stun_init_error_response_str(STUN_METHOD_CONNECT, ioa_network_buffer_data(nbh), &len, err_code, reason, &(tc->tid)); } @@ -2233,7 +2243,12 @@ static int handle_turn_connection_bind(turn_turnserver *server, u16bits method = STUN_METHOD_CONNECTION_BIND; - if (is_allocation_valid(a)) { + if(ss->to_be_closed) { + + *err_code = 400; + *reason = (const u08bits *)"Bad request"; + + } if (is_allocation_valid(a)) { *err_code = 400; *reason = (const u08bits *)"Bad request: CONNECTION_BIND cannot be issued after allocation"; @@ -2288,7 +2303,7 @@ static int handle_turn_connection_bind(turn_turnserver *server, if(server->send_socket_to_relay) { turnserver_id sid = (id & 0xFF000000)>>24; ioa_socket_handle s = ss->client_socket; - if(s) { + if(s && !ioa_socket_tobeclosed(s)) { ioa_socket_handle new_s = detach_ioa_socket(s,1); if(new_s) { if(server->send_socket_to_relay(sid, id, tid, new_s, message_integrity, RMT_CB_SOCKET, in_buffer, can_resume)<0) { @@ -2351,27 +2366,31 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co } else { ss = (ts_ur_super_session*)(a->owner); - //Check security: - int postpone_reply = 0; - check_stun_auth(server, ss, tid, &resp_constructed, &err_code, &reason, in_buffer, nbh, + if(ss->to_be_closed) { + err_code = 404; + } else { + //Check security: + int postpone_reply = 0; + check_stun_auth(server, ss, tid, &resp_constructed, &err_code, &reason, in_buffer, nbh, STUN_METHOD_CONNECTION_BIND, &message_integrity, &postpone_reply, can_resume); - if(postpone_reply) { + if(postpone_reply) { - ioa_network_buffer_delete(server->e, nbh); - return 0; + ioa_network_buffer_delete(server->e, nbh); + return 0; - } else if(!err_code) { - tc->state = TC_STATE_READY; - tc->client_s = s; - set_ioa_socket_session(s,ss); - set_ioa_socket_sub_session(s,tc); - set_ioa_socket_app_type(s,TCP_CLIENT_DATA_SOCKET); - if(register_callback_on_ioa_socket(server->e, s, IOA_EV_READ, tcp_client_input_handler_rfc6062data, tc, 1)<0) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: cannot set TCP client data input callback\n", __FUNCTION__); - err_code = 500; - } else { - IOA_EVENT_DEL(tc->conn_bind_timeout); + } else if(!err_code) { + tc->state = TC_STATE_READY; + tc->client_s = s; + set_ioa_socket_session(s,ss); + set_ioa_socket_sub_session(s,tc); + set_ioa_socket_app_type(s,TCP_CLIENT_DATA_SOCKET); + if(register_callback_on_ioa_socket(server->e, s, IOA_EV_READ, tcp_client_input_handler_rfc6062data, tc, 1)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: cannot set TCP client data input callback\n", __FUNCTION__); + err_code = 500; + } else { + IOA_EVENT_DEL(tc->conn_bind_timeout); + } } } } From ef416505bc331a411f66c058dc6e7163a852d524 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 7 Oct 2014 00:35:52 +0000 Subject: [PATCH 246/805] connect fixes --- src/server/ns_turn_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 75053e65..a60305cb 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -2248,7 +2248,7 @@ static int handle_turn_connection_bind(turn_turnserver *server, *err_code = 400; *reason = (const u08bits *)"Bad request"; - } if (is_allocation_valid(a)) { + } else if (is_allocation_valid(a)) { *err_code = 400; *reason = (const u08bits *)"Bad request: CONNECTION_BIND cannot be issued after allocation"; From 456046060ac1e168a585c5a1651fea5b4a0ec7e9 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 7 Oct 2014 06:25:54 +0000 Subject: [PATCH 247/805] fixes --- src/server/ns_turn_server.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index a60305cb..88e55941 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -2352,6 +2352,8 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co int err_code = 0; const u08bits *reason = NULL; + ioa_socket_handle s_to_delete = s; + if(tcid && tid && s) { tc = get_tcp_connection_by_id(server->tcp_relay_connections, tcid); @@ -2382,6 +2384,7 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co } else if(!err_code) { tc->state = TC_STATE_READY; tc->client_s = s; + s_to_delete = NULL; set_ioa_socket_session(s,ss); set_ioa_socket_sub_session(s,tc); set_ioa_socket_app_type(s,TCP_CLIENT_DATA_SOCKET); @@ -2451,12 +2454,8 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co } } - if(s) { - if(tc && (s==tc->client_s)) { - ; - } else { - close_ioa_socket(s); - } + if(s_to_delete) { + close_ioa_socket(s_to_delete); } FUNCEND; From 8a71523654281fc0f5d1dd49ec3b4ebf3199a34f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 7 Oct 2014 06:41:51 +0000 Subject: [PATCH 248/805] fixes --- src/server/ns_turn_server.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 88e55941..0a853b00 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -2441,6 +2441,7 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co if(ss && !err_code) { send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE); tcp_deliver_delayed_buffer(&(tc->ub_to_client),s,ss); + IOA_CLOSE_SOCKET(s_to_delete); FUNCEND; return 0; } else { @@ -2454,9 +2455,7 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co } } - if(s_to_delete) { - close_ioa_socket(s_to_delete); - } + IOA_CLOSE_SOCKET(s_to_delete); FUNCEND; return -1; From d7f8a30f0fa964f409ecede3c89abe37d8069e8b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 7 Oct 2014 07:25:33 +0000 Subject: [PATCH 249/805] fixes --- src/server/ns_turn_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 0a853b00..1b45e2eb 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -2368,7 +2368,7 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co } else { ss = (ts_ur_super_session*)(a->owner); - if(ss->to_be_closed) { + if(ss->to_be_closed || ioa_socket_tobeclosed(ss->client_socket)) { err_code = 404; } else { //Check security: From 37f1912eb17129e5c9b71d041a33b70827860061 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 8 Oct 2014 07:06:58 +0000 Subject: [PATCH 250/805] fixes --- src/apps/relay/netengine.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 9ce59243..3eb452ef 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -457,7 +457,6 @@ static int send_socket_to_general_relay(ioa_engine_handle e, struct message_to_r int success = 0; if(!rdest) { - success = -1; goto label_end; } @@ -492,12 +491,14 @@ static int send_socket_to_relay(turnserver_id id, u64bits cid, stun_tid *tid, io int message_integrity, MESSAGE_TO_RELAY_TYPE rmt, ioa_net_data *nd, int can_resume) { - int ret = 0; + int ret = -1; struct message_to_relay sm; ns_bzero(&sm,sizeof(struct message_to_relay)); sm.t = rmt; + ioa_socket_handle s_to_delete = s; + struct relay_server *rs = NULL; if(id>=TURNSERVER_ID_BOUNDARY_BETWEEN_TCP_AND_UDP) { size_t dest = id-TURNSERVER_ID_BOUNDARY_BETWEEN_TCP_AND_UDP; @@ -506,7 +507,6 @@ static int send_socket_to_relay(turnserver_id id, u64bits cid, stun_tid *tid, io TURN_LOG_LEVEL_ERROR, "%s: Too large UDP relay number: %d, rmt=%d, total=%d\n", __FUNCTION__,(int)dest,(int)rmt, (int)get_real_udp_relay_servers_number()); - ret = -1; goto err; } rs = udp_relay_servers[dest]; @@ -515,7 +515,6 @@ static int send_socket_to_relay(turnserver_id id, u64bits cid, stun_tid *tid, io TURN_LOG_LEVEL_ERROR, "%s: Wrong UDP relay number: %d, rmt=%d, total=%d\n", __FUNCTION__,(int)dest,(int)rmt, (int)get_real_udp_relay_servers_number()); - ret = -1; goto err; } } else { @@ -525,7 +524,6 @@ static int send_socket_to_relay(turnserver_id id, u64bits cid, stun_tid *tid, io TURN_LOG_LEVEL_ERROR, "%s: Too large general relay number: %d, rmt=%d, total=%d\n", __FUNCTION__,(int)dest,(int)rmt, (int)get_real_general_relay_servers_number()); - ret = -1; goto err; } rs = general_relay_servers[dest]; @@ -534,7 +532,6 @@ static int send_socket_to_relay(turnserver_id id, u64bits cid, stun_tid *tid, io TURN_LOG_LEVEL_ERROR, "%s: Wrong general relay number: %d, rmt=%d, total=%d\n", __FUNCTION__,(int)dest,(int)rmt, (int)get_real_general_relay_servers_number()); - ret = -1; goto err; } } @@ -556,6 +553,8 @@ static int send_socket_to_relay(turnserver_id id, u64bits cid, stun_tid *tid, io sm.m.cb_sm.can_resume = can_resume; nd->nbh = NULL; + s_to_delete = NULL; + ret = 0; } break; @@ -569,17 +568,19 @@ static int send_socket_to_relay(turnserver_id id, u64bits cid, stun_tid *tid, io sm.m.sm.nd.recv_ttl = nd->recv_ttl; sm.m.sm.nd.nbh = nd->nbh; sm.m.sm.can_resume = can_resume; + nd->nbh = NULL; + s_to_delete = NULL; + ret = 0; + } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Empty buffer with mobile socket\n",__FUNCTION__); - ret = -1; } break; } default: { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: UNKNOWN RMT message: %d\n",__FUNCTION__,(int)rmt); - ret = -1; } } @@ -594,16 +595,19 @@ static int send_socket_to_relay(turnserver_id id, u64bits cid, stun_tid *tid, io "%s: Empty output buffer\n", __FUNCTION__); ret = -1; + s_to_delete = s; } } err: - if(ret < 0) { - IOA_CLOSE_SOCKET(s); - if(nd) { - ioa_network_buffer_delete(NULL, nd->nbh); - nd->nbh = NULL; - } + + IOA_CLOSE_SOCKET(s_to_delete); + if(nd && nd->nbh) { + ioa_network_buffer_delete(NULL, nd->nbh); + nd->nbh = NULL; + } + + if(ret<0) { if(rmt == RMT_MOBILE_SOCKET) { ioa_network_buffer_delete(NULL, sm.m.sm.nd.nbh); sm.m.sm.nd.nbh = NULL; From 58efbf9635670eb780d00e3ec6bc3ce78f4cd7d1 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 9 Oct 2014 08:37:42 +0000 Subject: [PATCH 251/805] fixes --- src/apps/relay/dtls_listener.c | 16 ++---- src/apps/relay/ns_ioalib_engine_impl.c | 15 ++++- src/apps/relay/ns_ioalib_impl.h | 1 - src/apps/relay/tls_listener.c | 2 - src/server/ns_turn_maps.c | 76 ++++++++++++++++++++++++++ src/server/ns_turn_maps.h | 1 + src/server/ns_turn_server.c | 2 +- 7 files changed, 96 insertions(+), 17 deletions(-) diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index e763f496..a68aad0e 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -229,9 +229,6 @@ static ioa_socket_handle dtls_accept_client_connection( ioa_socket_handle ioas = create_ioa_socket_from_ssl(server->e, sock, ssl, DTLS_SOCKET, CLIENT_SOCKET, remote_addr, local_addr); if(ioas) { - - ioas->listener_server = server; - addr_cpy(&(server->sm.m.sm.nd.src_addr),remote_addr); server->sm.m.sm.nd.recv_ttl = TTL_IGNORE; server->sm.m.sm.nd.recv_tos = TOS_IGNORE; @@ -437,7 +434,6 @@ static int handle_udp_packet(dtls_listener_relay_server_type *server, __FUNCTION__, (char*) saddr,(char*) rsaddr); } s->e = ioa_eng; - s->listener_server = server; add_socket_to_map(s, amap); open_client_connection_session(ts, &(sm->m.sm)); } @@ -565,7 +561,6 @@ static int create_new_connected_udp_socket( "Accepted DTLS connection from"); ret->ssl = connecting_ssl; - ret->listener_server = server; ioa_network_buffer_delete(server->e, server->sm.m.sm.nd.nbh); server->sm.m.sm.nd.nbh = NULL; @@ -583,9 +578,8 @@ static void udp_server_input_handler(evutil_socket_t fd, short what, void* arg) { int cycle = 0; - ioa_socket_handle s = (ioa_socket_handle)arg; - - dtls_listener_relay_server_type* server = (dtls_listener_relay_server_type*)s->listener_server; + dtls_listener_relay_server_type* server = (dtls_listener_relay_server_type*)arg; + ioa_socket_handle s = server->udp_listen_s; FUNCSTART; @@ -726,8 +720,6 @@ static int create_server_socket(dtls_listener_relay_server_type* server, int rep server->udp_listen_s = create_ioa_socket_from_fd(server->e, udp_listen_fd, NULL, UDP_SOCKET, LISTENER_SOCKET, NULL, &(server->addr)); - server->udp_listen_s->listener_server = server; - set_sock_buf_size(udp_listen_fd,UR_SERVER_SOCK_BUF_SIZE); if(sock_bind_to_device(udp_listen_fd, (unsigned char*)server->ifname)<0) { @@ -756,7 +748,7 @@ static int create_server_socket(dtls_listener_relay_server_type* server, int rep server->udp_listen_ev = event_new(server->e->event_base,udp_listen_fd, EV_READ|EV_PERSIST,udp_server_input_handler, - server->udp_listen_s); + server); event_add(server->udp_listen_ev,NULL); } @@ -827,7 +819,7 @@ static int reopen_server_socket(dtls_listener_relay_server_type* server, evutil_ server->udp_listen_ev = event_new(server->e->event_base, udp_listen_fd, EV_READ | EV_PERSIST, udp_server_input_handler, - server->udp_listen_s); + server); event_add(server->udp_listen_ev, NULL ); } diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index e834ec30..626f74de 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1448,16 +1448,23 @@ void add_socket_to_map(ioa_socket_handle s, ur_addr_map *amap) &(s->remote_addr), (ur_addr_map_value_type)s); s->sockets_container = amap; + + //printf("%s: 111.111: amap=0x%lx: ne=%lu, sz=%lu\n",__FUNCTION__,(unsigned long)amap,(unsigned long)ur_addr_map_num_elements(amap),(unsigned long)ur_addr_map_size(amap)); } } void delete_socket_from_map(ioa_socket_handle s) { if(s && s->sockets_container) { + + //ur_addr_map *amap = s->sockets_container; + ur_addr_map_del(s->sockets_container, &(s->remote_addr), NULL); s->sockets_container = NULL; + + //printf("%s: 111.222: amap=0x%lx: ne=%lu, sz=%lu\n",__FUNCTION__,(unsigned long)amap,(unsigned long)ur_addr_map_num_elements(amap),(unsigned long)ur_addr_map_size(amap)); } } @@ -1741,7 +1748,11 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach) set_socket_ssl(ret,s->ssl); ret->fd = s->fd; - ret->family = s->family; + if(s->parent_s) + ret->family = s->parent_s->family; + else + ret->family = s->family; + ret->st = s->st; ret->sat = s->sat; ret->bound = s->bound; @@ -1836,6 +1847,8 @@ void set_ioa_socket_sub_session(ioa_socket_handle s, tcp_connection *tc) int get_ioa_socket_address_family(ioa_socket_handle s) { if(!s) { return AF_INET; + } else if(s->done) { + return s->family; } else if(s->parent_s) { return s->parent_s->family; } else { diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 198e7d9a..998860a7 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -170,7 +170,6 @@ struct _ioa_socket { evutil_socket_t fd; struct _ioa_socket *parent_s; - void *listener_server; u32bits magic; ur_addr_map *sockets_container; /* relay container for UDP sockets */ struct bufferevent *bev; diff --git a/src/apps/relay/tls_listener.c b/src/apps/relay/tls_listener.c index 53a605e8..03208b4a 100644 --- a/src/apps/relay/tls_listener.c +++ b/src/apps/relay/tls_listener.c @@ -98,8 +98,6 @@ static void server_input_handler(struct evconnlistener *l, evutil_socket_t fd, if (ioas) { - ioas->listener_server = server; - server->sm.m.sm.nd.recv_ttl = TTL_IGNORE; server->sm.m.sm.nd.recv_tos = TOS_IGNORE; server->sm.m.sm.nd.nbh = NULL; diff --git a/src/server/ns_turn_maps.c b/src/server/ns_turn_maps.c index 7fc1bc76..623e7535 100644 --- a/src/server/ns_turn_maps.c +++ b/src/server/ns_turn_maps.c @@ -692,6 +692,48 @@ static void addr_list_foreach(addr_list_header* slh, ur_addr_map_func func) { } } +static size_t addr_list_num_elements(const addr_list_header* slh) { + + size_t ret = 0; + + if (slh) { + + size_t i; + + for (i = 0; i < ADDR_ARRAY_SIZE; ++i) { + const addr_elem *elem = &(slh->main_list[i]); + if (elem->value) { + ++ret; + } + } + + if (slh->extra_list) { + for (i = 0; i < slh->extra_sz; ++i) { + addr_elem *elem = &(slh->extra_list[i]); + if (elem->value) { + ++ret; + } + } + } + } + + return ret; +} + +static size_t addr_list_size(const addr_list_header* slh) { + + size_t ret = 0; + + if (slh) { + + ret += ADDR_ARRAY_SIZE; + + ret += slh->extra_sz; + } + + return ret; +} + static addr_elem* addr_list_get(addr_list_header* slh, const ioa_addr* key) { if(!slh || !key) return NULL; @@ -863,6 +905,40 @@ void ur_addr_map_foreach(ur_addr_map* map, ur_addr_map_func func) { } } +size_t ur_addr_map_num_elements(const ur_addr_map* map) { + + size_t ret = 0; + + if (ur_addr_map_valid(map)) { + u32bits i = 0; + for (i = 0; i < ADDR_MAP_SIZE; i++) { + + const addr_list_header* slh = &(map->lists[i]); + + ret += addr_list_num_elements(slh); + } + } + + return ret; +} + +size_t ur_addr_map_size(const ur_addr_map* map) { + + size_t ret = 0; + + if (ur_addr_map_valid(map)) { + u32bits i = 0; + for (i = 0; i < ADDR_MAP_SIZE; i++) { + + const addr_list_header* slh = &(map->lists[i]); + + ret += addr_list_size(slh); + } + } + + return ret; +} + //////////////////// STRING LISTS /////////////////////////////////// typedef struct _string_list { diff --git a/src/server/ns_turn_maps.h b/src/server/ns_turn_maps.h index 3a873aa6..636e7aac 100644 --- a/src/server/ns_turn_maps.h +++ b/src/server/ns_turn_maps.h @@ -216,6 +216,7 @@ int ur_addr_map_del(ur_addr_map* map, ioa_addr* key,ur_addr_map_func func); */ void ur_addr_map_foreach(ur_addr_map* map, ur_addr_map_func func); +size_t ur_addr_map_num_elements(const ur_addr_map* map); size_t ur_addr_map_size(const ur_addr_map* map); //////////////// UR STRING MAP ////////////////// diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 1b45e2eb..f128fcb5 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1610,7 +1610,7 @@ static int handle_turn_refresh(turn_turnserver *server, //Transfer socket: - ioa_socket_handle s = detach_ioa_socket(ss->client_socket,0); + ioa_socket_handle s = detach_ioa_socket(ss->client_socket,1); ss->to_be_closed = 1; From 5177adb626c5fa58bedee89fd04d149ad9bc02a1 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 10 Oct 2014 17:24:19 +0000 Subject: [PATCH 252/805] memory debug --- src/apps/common/apputils.c | 6 +- src/apps/common/hiredis_libevent2.c | 4 +- src/apps/common/ns_turn_utils.c | 163 ++++++++++++++++++++++++++- src/apps/relay/dbdrivers/dbd_redis.c | 2 +- src/apps/relay/mainrelay.c | 2 +- src/apps/relay/netengine.c | 21 ++-- src/apps/relay/userdb.c | 42 +++---- src/ns_turn_defs.h | 30 ++++- 8 files changed, 225 insertions(+), 45 deletions(-) diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c index 32cad8b7..e76e3910 100644 --- a/src/apps/common/apputils.c +++ b/src/apps/common/apputils.c @@ -549,7 +549,7 @@ void set_execdir(void) /* On some systems, this may give us the execution path */ char *_var = getenv("_"); if(_var && *_var) { - _var = strdup(_var); + _var = turn_strdup(_var); char *edir=_var; if(edir[0]!='.') edir = strstr(edir,"/"); @@ -559,7 +559,7 @@ void set_execdir(void) edir = dirname(_var); if(c_execdir) turn_free(c_execdir,strlen(c_execdir)+1); - c_execdir = strdup(edir); + c_execdir = turn_strdup(edir); turn_free(_var,strlen(_var)+1); } } @@ -604,7 +604,7 @@ char* find_config_file(const char *config_file, int print_file_name) FILE *f = fopen(config_file, "r"); if (f) { fclose(f); - full_path_to_config_file = strdup(config_file); + full_path_to_config_file = turn_strdup(config_file); } } else { int i = 0; diff --git a/src/apps/common/hiredis_libevent2.c b/src/apps/common/hiredis_libevent2.c index 2b6837eb..f4b62c00 100644 --- a/src/apps/common/hiredis_libevent2.c +++ b/src/apps/common/hiredis_libevent2.c @@ -250,10 +250,10 @@ redis_context_handle redisLibeventAttach(struct event_base *base, char *ip0, int e->allocated = 1; e->context = ac; e->base = base; - e->ip = strdup(ip); + e->ip = turn_strdup(ip); e->port = port; if(pwd) - e->pwd = strdup(pwd); + e->pwd = turn_strdup(pwd); e->db = db; /* Register functions to start/stop listening for events */ diff --git a/src/apps/common/ns_turn_utils.c b/src/apps/common/ns_turn_utils.c index aaba035d..a16514cf 100644 --- a/src/apps/common/ns_turn_utils.c +++ b/src/apps/common/ns_turn_utils.c @@ -295,11 +295,11 @@ static void set_log_file_name_func(char *base, char *f, size_t fsz) } char logdate[125]; - char *tail=strdup(".log"); + char *tail=turn_strdup(".log"); get_date(logdate,sizeof(logdate)); - char *base1=strdup(base); + char *base1=turn_strdup(base); int len=(int)strlen(base1); @@ -319,11 +319,11 @@ static void set_log_file_name_func(char *base, char *f, size_t fsz) break; else if(base1[len]=='.') { turn_free(tail,strlen(tail)+1); - tail=strdup(base1+len); + tail=turn_strdup(base1+len); base1[len]=0; if(strlen(tail)<2) { turn_free(tail,strlen(tail)+1); - tail = strdup(".log"); + tail = turn_strdup(".log"); } break; } @@ -656,3 +656,158 @@ int get_canonic_origin(const char* o, char *co, int sz) } ////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus + +#include +#include +#include + +using namespace std; + +static volatile int tmm_init = 0; +static pthread_mutex_t tm; + +typedef void* ptrtype; +typedef set ptrs_t; +typedef map str_to_ptrs_t; +typedef map ptr_to_str_t; + +static str_to_ptrs_t str_to_ptrs; +static ptr_to_str_t ptr_to_str; + +static void tm_init(void) { + if(!tmm_init) { + pthread_mutex_init(&tm,NULL); + tmm_init = 1; + } +} + +static void add_tm_ptr(void *ptr, const char *id) { + + UNUSED_ARG(ptr); + UNUSED_ARG(id); + + if(!ptr) + return; + + pthread_mutex_lock(&tm); + + string sid(id); + if(str_to_ptrs.find(sid) == str_to_ptrs.end()) { + set sp; + str_to_ptrs[sid]=sp; + } + + str_to_ptrs[sid].insert(ptr); + ptr_to_str[ptr]=sid; + + pthread_mutex_unlock(&tm); +} + +static void del_tm_ptr(void *ptr, const char *id) { + + UNUSED_ARG(ptr); + UNUSED_ARG(id); + + if(!ptr) + return; + + pthread_mutex_lock(&tm); + + ptr_to_str_t::iterator pts_iter = ptr_to_str.find(ptr); + if(pts_iter != ptr_to_str.end()) { + string sid = pts_iter->second; + ptr_to_str.erase(pts_iter); + if(str_to_ptrs.find(sid) != str_to_ptrs.end()) { + str_to_ptrs[sid].erase(ptr); + } + } + + pthread_mutex_unlock(&tm); +} + +static void tm_id(char *id, const char* file, int line) { + sprintf(id,"%s:%d",file,line); +} + +#define TM_START() char id[128];tm_id(id,file,line);tm_init() + +void tm_print_func(void); +void tm_print_func(void) { + pthread_mutex_lock(&tm); + printf("=============================================\n"); + for(str_to_ptrs_t::const_iterator iter=str_to_ptrs.begin();iter != str_to_ptrs.end();++iter) { + printf("%s: %s: %d\n",__FUNCTION__,iter->first.c_str(),(int)(iter->second.size())); + } + printf("=============================================\n"); + pthread_mutex_unlock(&tm); +} + +void *turn_malloc_func(size_t sz, const char* file, int line); +void *turn_malloc_func(size_t sz, const char* file, int line) { + + TM_START(); + + void *ptr = malloc(sz); + + add_tm_ptr(ptr,id); + + return ptr; +} + +void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* file, int line); +void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* file, int line) { + + UNUSED_ARG(old_sz); + + TM_START(); + + del_tm_ptr(ptr,id); + + ptr = realloc(ptr,new_sz); + + add_tm_ptr(ptr,id); + + return ptr; +} + +void turn_free_func(void *ptr, size_t sz, const char* file, int line); +void turn_free_func(void *ptr, size_t sz, const char* file, int line) { + + UNUSED_ARG(sz); + + TM_START(); + + del_tm_ptr(ptr,id); + + free(ptr); +} + +void *turn_calloc_func(size_t number, size_t size, const char* file, int line); +void *turn_calloc_func(size_t number, size_t size, const char* file, int line) { + + TM_START(); + + void *ptr = calloc(number,size); + + add_tm_ptr(ptr,id); + + return ptr; +} + +char *turn_strdup_func(const char* s, const char* file, int line); +char *turn_strdup_func(const char* s, const char* file, int line) { + + TM_START(); + + char *ptr = strdup(s); + + add_tm_ptr(ptr,id); + + return ptr; +} + +#endif + +////////////////////////////////////////////////////////////////// diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index b50bc6bf..8553bda6 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -59,7 +59,7 @@ typedef struct _Ryconninfo Ryconninfo; static void RyconninfoFree(Ryconninfo *co) { if(co) { if(co->host) turn_free(co->host, strlen(co->host)+1); - if(co->dbname) turn_free(co->dbname, strlen(co->username)+1); + if(co->dbname) turn_free(co->dbname, strlen(co->dbname)+1); if(co->password) turn_free(co->password, strlen(co->password)+1); ns_bzero(co,sizeof(Ryconninfo)); } diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index e0c5e432..6a53b75f 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1034,7 +1034,7 @@ static void set_option(int c, char *value) if(value) { char *div = strchr(value,'/'); if(div) { - char *nval=strdup(value); + char *nval=turn_strdup(value); div = strchr(nval,'/'); div[0]=0; ++div; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 3eb452ef..8f80ac51 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -168,7 +168,7 @@ static void add_aux_server_list(const char *saddr, turn_server_addrs_list_t *lis if(make_ioa_addr_from_full_string((const u08bits*)saddr, 0, &addr)!=0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong full address format: %s\n",saddr); } else { - list->addrs = (ioa_addr*)realloc(list->addrs,sizeof(ioa_addr)*(list->size+1)); + list->addrs = (ioa_addr*)turn_realloc(list->addrs,0,sizeof(ioa_addr)*(list->size+1)); addr_cpy(&(list->addrs[(list->size)++]),&addr); { u08bits s[1025]; @@ -196,7 +196,7 @@ static void add_alt_server(const char *saddr, int default_port, turn_server_addr if(make_ioa_addr_from_full_string((const u08bits*)saddr, default_port, &addr)!=0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong IP address format: %s\n",saddr); } else { - list->addrs = (ioa_addr*)realloc(list->addrs,sizeof(ioa_addr)*(list->size+1)); + list->addrs = (ioa_addr*)turn_realloc(list->addrs,0,sizeof(ioa_addr)*(list->size+1)); addr_cpy(&(list->addrs[(list->size)++]),&addr); { u08bits s[1025]; @@ -233,7 +233,7 @@ static void del_alt_server(const char *saddr, int default_port, turn_server_addr if(found) { size_t j; - ioa_addr *new_addrs = (ioa_addr*)malloc(sizeof(ioa_addr)*(list->size-1)); + ioa_addr *new_addrs = (ioa_addr*)turn_malloc(sizeof(ioa_addr)*(list->size-1)); for(j=0;jaddrs[j])); } @@ -241,7 +241,7 @@ static void del_alt_server(const char *saddr, int default_port, turn_server_addr addr_cpy(&(new_addrs[j]),&(list->addrs[j+1])); } - free(list->addrs); + turn_free(list->addrs,0); list->addrs = new_addrs; list->size -= 1; @@ -298,9 +298,9 @@ void add_listener_addr(const char* addr) { } ++turn_params.listener.addrs_number; ++turn_params.listener.services_number; - turn_params.listener.addrs = (char**)realloc(turn_params.listener.addrs, sizeof(char*)*turn_params.listener.addrs_number); - turn_params.listener.addrs[turn_params.listener.addrs_number-1]=strdup(sbaddr); - turn_params.listener.encaddrs = (ioa_addr**)realloc(turn_params.listener.encaddrs, sizeof(ioa_addr*)*turn_params.listener.addrs_number); + turn_params.listener.addrs = (char**)turn_realloc(turn_params.listener.addrs, 0, sizeof(char*)*turn_params.listener.addrs_number); + turn_params.listener.addrs[turn_params.listener.addrs_number-1]=turn_strdup(sbaddr); + turn_params.listener.encaddrs = (ioa_addr**)turn_realloc(turn_params.listener.encaddrs, 0, sizeof(ioa_addr*)*turn_params.listener.addrs_number); turn_params.listener.encaddrs[turn_params.listener.addrs_number-1]=(ioa_addr*)turn_malloc(sizeof(ioa_addr)); addr_cpy(turn_params.listener.encaddrs[turn_params.listener.addrs_number-1],&baddr); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Listener address to use: %s\n",sbaddr); @@ -325,8 +325,8 @@ int add_relay_addr(const char* addr) { } ++turn_params.relays_number; - turn_params.relay_addrs = (char**)realloc(turn_params.relay_addrs, sizeof(char*)*turn_params.relays_number); - turn_params.relay_addrs[turn_params.relays_number-1]=strdup(sbaddr); + turn_params.relay_addrs = (char**)turn_realloc(turn_params.relay_addrs, 0, sizeof(char*)*turn_params.relays_number); + turn_params.relay_addrs[turn_params.relays_number-1]=turn_strdup(sbaddr); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Relay address to use: %s\n",sbaddr); return 1; @@ -1539,6 +1539,9 @@ void run_listener_server(struct listener_server *ls) run_events(ls->event_base, ls->ioa_eng); rollover_logfile(); + + tm_print(); + } } diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 5292ef03..9387231f 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -174,7 +174,7 @@ int get_realm_options_by_origin(char *origin, realm_options_t* ro) realm_params_t rp; get_realm_data(realm, &rp); ns_bcopy(&(rp.options),ro,sizeof(realm_options_t)); - free(realm); + turn_free(realm,strlen(realm)+1); return 1; } else { TURN_MUTEX_UNLOCK(&o_to_realm_mutex); @@ -291,9 +291,9 @@ const char* get_secrets_list_elem(secrets_list_t *sl, size_t i) void add_to_secrets_list(secrets_list_t *sl, const char* elem) { if(sl && elem) { - sl->secrets = (char**)realloc(sl->secrets,(sizeof(char*)*(sl->sz+1))); - sl->secrets[sl->sz] = strdup(elem); - sl->sz += 1; + sl->secrets = (char**)turn_realloc(sl->secrets,0,(sizeof(char*)*(sl->sz+1))); + sl->secrets[sl->sz] = strdup(elem); + sl->sz += 1; } } @@ -707,7 +707,7 @@ int check_new_allocation_quota(u08bits *user, int oauth, u08bits *realm) } else { ++(rp->status.total_current_allocs); } - turn_free(username,strlen(username)+1); + turn_free(username,strlen((char*)username)+1); ur_string_map_unlock(rp->status.alloc_counters); } return ret; @@ -730,7 +730,7 @@ void release_allocation_quota(u08bits *user, int oauth, u08bits *realm) if (rp->status.total_current_allocs) --(rp->status.total_current_allocs); ur_string_map_unlock(rp->status.alloc_counters); - turn_free(username, strlen(username)+1); + turn_free(username, strlen((char*)username)+1); } } @@ -839,8 +839,8 @@ int add_user_account(char *user, int dynamic) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key format: %s\n",s); } if(convert_string_key_to_binary(keysource, *key, sz)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key: %s\n",s); - free(usname); - free(key); + turn_free(usname,strlen(usname)+1); + turn_free(key,sizeof(hmackey_t)); return -1; } } else { @@ -857,7 +857,7 @@ int add_user_account(char *user, int dynamic) ur_string_map_unlock(turn_params.default_users_db.ram_db.static_accounts); } turn_params.default_users_db.ram_db.users_number++; - free(usname); + turn_free(usname,strlen(usname)+1); return 0; } } @@ -1153,7 +1153,7 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b } add_and_cont: - content = (char**)realloc(content, sizeof(char*) * (++csz)); + content = (char**)turn_realloc(content, 0, sizeof(char*) * (++csz)); content[csz - 1] = strdup(s0); } @@ -1168,7 +1168,7 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b for(i=0;iranges_number;++i) { if(l->ranges && l->ranges[i]) - free(l->ranges[i]); + turn_free(l->ranges[i],0); if(l->encaddrsranges && l->encaddrsranges[i]) - free(l->encaddrsranges[i]); + turn_free(l->encaddrsranges[i],0); } if(l->ranges) - free(l->ranges); + turn_free(l->ranges,0); if(l->encaddrsranges) - free(l->encaddrsranges); - free(l); + turn_free(l->encaddrsranges,0); + turn_free(l,sizeof(ip_range_list_t)); } } @@ -1446,14 +1446,14 @@ int add_ip_list_range(const char * range0, ip_range_list_t * list) if (make_ioa_addr((const u08bits*) range, 0, &min) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong address format: %s\n", range); - free(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 format: %s\n", separator + 1); - free(range); + turn_free(range,0); return -1; } } else { @@ -1465,9 +1465,9 @@ int add_ip_list_range(const char * range0, ip_range_list_t * list) *separator = '-'; ++(list->ranges_number); - list->ranges = (char**) realloc(list->ranges, sizeof(char*) * list->ranges_number); + list->ranges = (char**) turn_realloc(list->ranges, 0, sizeof(char*) * list->ranges_number); list->ranges[list->ranges_number - 1] = range; - list->encaddrsranges = (ioa_addr_range**) realloc(list->encaddrsranges, sizeof(ioa_addr_range*) * list->ranges_number); + list->encaddrsranges = (ioa_addr_range**) turn_realloc(list->encaddrsranges, 0, sizeof(ioa_addr_range*) * list->ranges_number); list->encaddrsranges[list->ranges_number - 1] = (ioa_addr_range*) turn_malloc(sizeof(ioa_addr_range)); diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index b5ba7279..d023e1cc 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -111,10 +111,32 @@ static inline u64bits _ioa_ntoh64(u64bits v) #define ioa_ntoh64 _ioa_ntoh64 #define ioa_hton64 _ioa_ntoh64 -#define turn_malloc(sz) malloc(sz) -#define turn_free(ptr,sz) free(ptr) -#define turn_realloc(ptr, old_sz, new_sz) realloc((ptr),(new_sz)) -#define turn_calloc(number, sz) calloc((number),(sz)) +#if defined(TURN_MEMORY_DEBUG) + + void tm_print_func(void); + void *turn_malloc_func(size_t sz, const char* file, int line); + void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* file, int line); + void turn_free_func(void *ptr, size_t sz, const char* file, int line); + void *turn_calloc_func(size_t number, size_t size, const char* file, int line); + char *turn_strdup_func(const char* s, const char* file, int line); + +#define tm_print() tm_print_func() +#define turn_malloc(sz) turn_malloc_func((size_t)(sz),__FUNCTION__,__LINE__) +#define turn_free(ptr,sz) turn_free_func((ptr),(size_t)(sz),__FUNCTION__,__LINE__) +#define turn_realloc(ptr, old_sz, new_sz) turn_realloc_func((ptr),(size_t)(old_sz),(size_t)(new_sz),__FUNCTION__,__LINE__) +#define turn_calloc(number, sz) turn_calloc_func((number),(size_t)(sz),__FUNCTION__,__LINE__) +#define turn_strdup(s) turn_strdup_func((s),__FUNCTION__,__LINE__) + +#else + +#define tm_print() +#define turn_malloc(sz) malloc((size_t)(sz)) +#define turn_free(ptr,sz) free((ptr)) +#define turn_realloc(ptr, old_sz, new_sz) realloc((ptr),(size_t)(new_sz)) +#define turn_calloc(number, sz) calloc((number),(size_t)(sz)) +#define turn_strdup(s) strdup((s)) + +#endif #define turn_time() ((turn_time_t)time(NULL)) From 04f354d563ad39e374fdc8d784eb7536fbbc98a4 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 11 Oct 2014 06:49:35 +0000 Subject: [PATCH 253/805] memory cleaning --- .../secure_relay_with_db_redis.sh | 2 +- src/apps/common/ns_turn_utils.c | 51 ++++- src/apps/relay/dbdrivers/dbd_mongo.c | 201 ++++++++++-------- src/apps/relay/dbdrivers/dbd_mysql.c | 70 +++--- src/apps/relay/dbdrivers/dbd_pgsql.c | 4 +- src/apps/relay/dbdrivers/dbd_redis.c | 40 ++-- src/apps/relay/mainrelay.c | 4 +- src/apps/relay/ns_ioalib_engine_impl.c | 20 +- src/apps/relay/turncli.c | 6 +- src/apps/relay/userdb.c | 22 +- src/client/ns_turn_ioaddr.c | 10 +- src/ns_turn_defs.h | 2 + 12 files changed, 243 insertions(+), 189 deletions(-) diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh index 319a2442..6a18c40c 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh @@ -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" -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 --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:SSLv2 --oauth $@ diff --git a/src/apps/common/ns_turn_utils.c b/src/apps/common/ns_turn_utils.c index a16514cf..4388ff56 100644 --- a/src/apps/common/ns_turn_utils.c +++ b/src/apps/common/ns_turn_utils.c @@ -658,6 +658,7 @@ int get_canonic_origin(const char* o, char *co, int sz) ////////////////////////////////////////////////////////////////// #ifdef __cplusplus +#if defined(TURN_MEMORY_DEBUG) #include #include @@ -691,15 +692,22 @@ static void add_tm_ptr(void *ptr, const char *id) { if(!ptr) return; + string sid(id); + + str_to_ptrs_t::iterator iter; + pthread_mutex_lock(&tm); - string sid(id); - if(str_to_ptrs.find(sid) == str_to_ptrs.end()) { + iter = str_to_ptrs.find(sid); + + if(iter == str_to_ptrs.end()) { set sp; + sp.insert(ptr); str_to_ptrs[sid]=sp; + } else { + iter->second.insert(ptr); } - str_to_ptrs[sid].insert(ptr); ptr_to_str[ptr]=sid; pthread_mutex_unlock(&tm); @@ -716,11 +724,25 @@ static void del_tm_ptr(void *ptr, const char *id) { pthread_mutex_lock(&tm); ptr_to_str_t::iterator pts_iter = ptr_to_str.find(ptr); - if(pts_iter != ptr_to_str.end()) { + if(pts_iter == ptr_to_str.end()) { + + printf("Tring to free unknown pointer (1): %s\n",id); + + } else { + string sid = pts_iter->second; ptr_to_str.erase(pts_iter); - if(str_to_ptrs.find(sid) != str_to_ptrs.end()) { - str_to_ptrs[sid].erase(ptr); + + str_to_ptrs_t::iterator iter = str_to_ptrs.find(sid); + + if(iter == str_to_ptrs.end()) { + + printf("Tring to free unknown pointer (2): %s\n",id); + + } else { + + iter->second.erase(ptr); + } } @@ -738,7 +760,8 @@ void tm_print_func(void) { pthread_mutex_lock(&tm); printf("=============================================\n"); for(str_to_ptrs_t::const_iterator iter=str_to_ptrs.begin();iter != str_to_ptrs.end();++iter) { - printf("%s: %s: %d\n",__FUNCTION__,iter->first.c_str(),(int)(iter->second.size())); + if(iter->second.size()) + printf("%s: %s: %d\n",__FUNCTION__,iter->first.c_str(),(int)(iter->second.size())); } printf("=============================================\n"); pthread_mutex_unlock(&tm); @@ -763,7 +786,8 @@ void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* fil TM_START(); - del_tm_ptr(ptr,id); + if(ptr) + del_tm_ptr(ptr,id); ptr = realloc(ptr,new_sz); @@ -784,6 +808,16 @@ void turn_free_func(void *ptr, size_t sz, const char* file, int line) { free(ptr); } +void turn_free_simple(void *ptr); +void turn_free_simple(void *ptr) { + + tm_init(); + + del_tm_ptr(ptr,__FUNCTION__); + + free(ptr); +} + void *turn_calloc_func(size_t number, size_t size, const char* file, int line); void *turn_calloc_func(size_t number, size_t size, const char* file, int line) { @@ -808,6 +842,7 @@ char *turn_strdup_func(const char* s, const char* file, int line) { return ptr; } +#endif #endif ////////////////////////////////////////////////////////////////// diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index 12ac65f2..21f18284 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -72,7 +72,7 @@ static void MongoFree(MONGO * info) { if(info) { if(info->uri) mongoc_uri_destroy(info->uri); if(info->client) mongoc_client_destroy(info->client); - turn_free(info, sizeof(MONGO)); + turn_free(info, sizeof(MONGO)); } } @@ -860,7 +860,8 @@ static int mongo_set_realm_option_one(u08bits *realm, unsigned long value, const BSON_APPEND_UTF8(&query, "realm", (const char *)realm); bson_init(&doc); - char * _k = (char *)turn_malloc(9 + strlen(opt)); + size_t klen = 9 + strlen(opt); + char * _k = (char *)turn_malloc(klen); strcpy(_k, "options."); strcat(_k, opt); @@ -873,7 +874,7 @@ static int mongo_set_realm_option_one(u08bits *realm, unsigned long value, const BSON_APPEND_INT32(&child, _k, 1); bson_append_document_end(&doc, &child); } - free(_k); + turn_free(_k,klen); int ret = -1; @@ -1010,113 +1011,129 @@ static int mongo_get_ip_list(const char *kind, ip_range_list_t * list) { return ret; } + static void mongo_reread_realms(secrets_list_t * realms_list) { + UNUSED_ARG(realms_list); - mongoc_collection_t * collection = mongo_get_collection("realm"); + mongoc_collection_t * collection = mongo_get_collection("realm"); - if(!collection) - return; + if (!collection) + return; - bson_t query; - bson_init(&query); + bson_t query; + bson_init(&query); - bson_t fields; - bson_init(&fields); - BSON_APPEND_INT32(&fields, "realm", 1); - BSON_APPEND_INT32(&fields, "origin", 1); - BSON_APPEND_INT32(&fields, "options", 1); - - mongoc_cursor_t * cursor; - cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL); + bson_t fields; + bson_init(&fields); + BSON_APPEND_INT32(&fields, "realm", 1); + BSON_APPEND_INT32(&fields, "origin", 1); + BSON_APPEND_INT32(&fields, "options", 1); - if (!cursor) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection 'realm'\n"); - } else { - ur_string_map *o_to_realm_new = ur_string_map_create(free); + mongoc_cursor_t * cursor; + cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, + &query, &fields, NULL); - const bson_t * item; - uint32_t length; - bson_iter_t iter; + if (!cursor) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Error querying MongoDB collection 'realm'\n"); + } else { + ur_string_map *o_to_realm_new = ur_string_map_create(turn_free_simple); - while (mongoc_cursor_next(cursor, &item)) { - if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "realm") && BSON_ITER_HOLDS_UTF8(&iter)) { - char * _realm = strdup(bson_iter_utf8(&iter, &length)); + const bson_t * item; + uint32_t length; + bson_iter_t iter; - get_realm(_realm); + while (mongoc_cursor_next(cursor, &item)) { - 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, "realm") + && BSON_ITER_HOLDS_UTF8(&iter)) { - bson_iter_array(&iter, &doclen, &docbuf); - bson_init_static(&origin_array, docbuf, doclen); + char * _realm = turn_strdup(bson_iter_utf8(&iter, &length)); - if (bson_iter_init(&origin_iter, &origin_array)) { - while(bson_iter_next(&origin_iter)) { - if (BSON_ITER_HOLDS_UTF8(&origin_iter)) { - char * _origin = strdup(bson_iter_utf8(&origin_iter, &length)); - char *rval = strdup(_realm); - ur_string_map_value_type value = (ur_string_map_value_type)(rval); - ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) _origin, value); - free(_origin); - } - } - } - } - - realm_params_t* rp = get_realm(_realm); - lock_realms(); - rp->options.perf_options.max_bps = turn_params.max_bps; - rp->options.perf_options.total_quota = turn_params.total_quota; - rp->options.perf_options.user_quota = turn_params.user_quota; - unlock_realms(); + get_realm(_realm); - if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "options") && BSON_ITER_HOLDS_DOCUMENT(&iter)) { - const uint8_t *docbuf = NULL; - uint32_t doclen = 0; - bson_t options; - bson_iter_t options_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_document(&iter, &doclen, &docbuf); - bson_init_static(&options, docbuf, doclen); + bson_iter_array(&iter, &doclen, &docbuf); + bson_init_static(&origin_array, docbuf, doclen); - if (bson_iter_init(&options_iter, &options)) { - while(bson_iter_next(&options_iter)) { - const char * _k = bson_iter_key(&options_iter); - int32_t _v = 0; - if (BSON_ITER_HOLDS_DOUBLE(&options_iter)) { - _v = (int32_t)bson_iter_double(&options_iter); - } else if (BSON_ITER_HOLDS_INT32(&options_iter)) { - _v = bson_iter_int32(&options_iter); - } else if (BSON_ITER_HOLDS_INT64(&options_iter)) { - _v = (int32_t)bson_iter_int64(&options_iter); - } - if (_v) { - if(!strcmp(_k,"max-bps")) - rp->options.perf_options.max_bps = (band_limit_t)_v; - else if(!strcmp(_k,"total-quota")) - rp->options.perf_options.total_quota = (vint)_v; - else if(!strcmp(_k,"user-quota")) - rp->options.perf_options.user_quota = (vint)_v; + if (bson_iter_init(&origin_iter, &origin_array)) { + while (bson_iter_next(&origin_iter)) { + if (BSON_ITER_HOLDS_UTF8(&origin_iter)) { + char* _origin = turn_strdup(bson_iter_utf8(&origin_iter, &length)); + char *rval = turn_strdup(_realm); + ur_string_map_value_type value = + (ur_string_map_value_type) (rval); + ur_string_map_put(o_to_realm_new, + (const ur_string_map_key_type) _origin, + value); + turn_free(_origin,strlen(_origin)+1); + } + } + } + } + + realm_params_t* rp = get_realm(_realm); + lock_realms(); + rp->options.perf_options.max_bps = turn_params.max_bps; + rp->options.perf_options.total_quota = turn_params.total_quota; + rp->options.perf_options.user_quota = turn_params.user_quota; + unlock_realms(); + + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, + "options") && BSON_ITER_HOLDS_DOCUMENT(&iter)) { + const uint8_t *docbuf = NULL; + uint32_t doclen = 0; + bson_t options; + bson_iter_t options_iter; + + bson_iter_document(&iter, &doclen, &docbuf); + bson_init_static(&options, docbuf, doclen); + + if (bson_iter_init(&options_iter, &options)) { + while (bson_iter_next(&options_iter)) { + const char * _k = bson_iter_key(&options_iter); + int32_t _v = 0; + if (BSON_ITER_HOLDS_DOUBLE(&options_iter)) { + _v = (int32_t) bson_iter_double(&options_iter); + } else if (BSON_ITER_HOLDS_INT32(&options_iter)) { + _v = bson_iter_int32(&options_iter); + } else if (BSON_ITER_HOLDS_INT64(&options_iter)) { + _v = (int32_t) bson_iter_int64(&options_iter); + } + if (_v) { + if (!strcmp(_k, "max-bps")) + rp->options.perf_options.max_bps + = (band_limit_t) _v; + else if (!strcmp(_k, "total-quota")) + rp->options.perf_options.total_quota + = (vint) _v; + else if (!strcmp(_k, "user-quota")) + rp->options.perf_options.user_quota + = (vint) _v; else { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", _k); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Unknown realm option: %s\n", _k); } - } - } - } - } - free(_realm); - } - } - update_o_to_realm(o_to_realm_new); - mongoc_cursor_destroy(cursor); - } - mongoc_collection_destroy(collection); - bson_destroy(&query); - bson_destroy(&fields); + } + } + } + } + turn_free(_realm,strlen(_realm)+1); + } + } + update_o_to_realm(o_to_realm_new); + mongoc_cursor_destroy(cursor); + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + bson_destroy(&fields); } /////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 44244d54..6f3c07ee 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -76,7 +76,7 @@ static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) { Myconninfo *co = (Myconninfo*)turn_malloc(sizeof(Myconninfo)); ns_bzero(co,sizeof(Myconninfo)); if(userdb) { - char *s0=strdup(userdb); + char *s0=turn_strdup(userdb); char *s = s0; while(s && *s) { @@ -93,44 +93,44 @@ static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) { MyconninfoFree(co); co = NULL; if(errmsg) { - *errmsg = strdup(s); + *errmsg = turn_strdup(s); } break; } *seq = 0; if(!strcmp(s,"host")) - co->host = strdup(seq+1); + co->host = turn_strdup(seq+1); else if(!strcmp(s,"ip")) - co->host = strdup(seq+1); + co->host = turn_strdup(seq+1); else if(!strcmp(s,"addr")) - co->host = strdup(seq+1); + co->host = turn_strdup(seq+1); else if(!strcmp(s,"ipaddr")) - co->host = strdup(seq+1); + co->host = turn_strdup(seq+1); else if(!strcmp(s,"hostaddr")) - co->host = strdup(seq+1); + co->host = turn_strdup(seq+1); else if(!strcmp(s,"dbname")) - co->dbname = strdup(seq+1); + co->dbname = turn_strdup(seq+1); else if(!strcmp(s,"db")) - co->dbname = strdup(seq+1); + co->dbname = turn_strdup(seq+1); else if(!strcmp(s,"database")) - co->dbname = strdup(seq+1); + co->dbname = turn_strdup(seq+1); else if(!strcmp(s,"user")) - co->user = strdup(seq+1); + co->user = turn_strdup(seq+1); else if(!strcmp(s,"uname")) - co->user = strdup(seq+1); + co->user = turn_strdup(seq+1); else if(!strcmp(s,"name")) - co->user = strdup(seq+1); + co->user = turn_strdup(seq+1); else if(!strcmp(s,"username")) - co->user = strdup(seq+1); + co->user = turn_strdup(seq+1); else if(!strcmp(s,"password")) - co->password = strdup(seq+1); + co->password = turn_strdup(seq+1); else if(!strcmp(s,"pwd")) - co->password = strdup(seq+1); + co->password = turn_strdup(seq+1); else if(!strcmp(s,"passwd")) - co->password = strdup(seq+1); + co->password = turn_strdup(seq+1); else if(!strcmp(s,"secret")) - co->password = strdup(seq+1); + co->password = turn_strdup(seq+1); else if(!strcmp(s,"port")) co->port = (unsigned int)atoi(seq+1); else if(!strcmp(s,"p")) @@ -140,30 +140,30 @@ static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) { else if(!strcmp(s,"timeout")) co->connect_timeout = (unsigned int)atoi(seq+1); else if(!strcmp(s,"key")) - co->key = strdup(seq+1); + co->key = turn_strdup(seq+1); else if(!strcmp(s,"ssl-key")) - co->key = strdup(seq+1); + co->key = turn_strdup(seq+1); else if(!strcmp(s,"ca")) - co->ca = strdup(seq+1); + co->ca = turn_strdup(seq+1); else if(!strcmp(s,"ssl-ca")) - co->ca = strdup(seq+1); + co->ca = turn_strdup(seq+1); else if(!strcmp(s,"capath")) - co->capath = strdup(seq+1); + co->capath = turn_strdup(seq+1); else if(!strcmp(s,"ssl-capath")) - co->capath = strdup(seq+1); + co->capath = turn_strdup(seq+1); else if(!strcmp(s,"cert")) - co->cert = strdup(seq+1); + co->cert = turn_strdup(seq+1); else if(!strcmp(s,"ssl-cert")) - co->cert = strdup(seq+1); + co->cert = turn_strdup(seq+1); else if(!strcmp(s,"cipher")) - co->cipher = strdup(seq+1); + co->cipher = turn_strdup(seq+1); else if(!strcmp(s,"ssl-cipher")) - co->cipher = strdup(seq+1); + co->cipher = turn_strdup(seq+1); else { MyconninfoFree(co); co = NULL; if(errmsg) { - *errmsg = strdup(s); + *errmsg = turn_strdup(s); } break; } @@ -176,13 +176,13 @@ static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) { if(co) { if(!(co->dbname)) - co->dbname=strdup("0"); + co->dbname=turn_strdup("0"); if(!(co->host)) - co->host=strdup("127.0.0.1"); + co->host=turn_strdup("127.0.0.1"); if(!(co->user)) - co->user=strdup(""); + co->user=turn_strdup(""); if(!(co->password)) - co->password=strdup(""); + co->password=turn_strdup(""); } return co; @@ -939,7 +939,7 @@ static void mysql_reread_realms(secrets_list_t * realms_list) { MYSQL_RES *mres = mysql_store_result(myc); if(mres && mysql_field_count(myc)==2) { - ur_string_map *o_to_realm_new = ur_string_map_create(free); + ur_string_map *o_to_realm_new = ur_string_map_create(turn_free_simple); for(;;) { MYSQL_ROW row = mysql_fetch_row(mres); @@ -953,7 +953,7 @@ static void mysql_reread_realms(secrets_list_t * realms_list) { char oval[513]; ns_bcopy(row[0],oval,sz); oval[sz]=0; - char *rval=strdup(row[1]); + char *rval=turn_strdup(row[1]); get_realm(rval); ur_string_map_value_type value = (ur_string_map_value_type)rval; ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) oval, value); diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index 6efbe40b..0a8b317f 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -682,7 +682,7 @@ static void pgsql_reread_realms(secrets_list_t * realms_list) { if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) { - ur_string_map *o_to_realm_new = ur_string_map_create(free); + ur_string_map *o_to_realm_new = ur_string_map_create(turn_free_simple); int i = 0; for(i=0;ihost = strdup(seq + 1); + co->host = turn_strdup(seq + 1); else if (!strcmp(s, "ip")) - co->host = strdup(seq + 1); + co->host = turn_strdup(seq + 1); else if (!strcmp(s, "addr")) - co->host = strdup(seq + 1); + co->host = turn_strdup(seq + 1); else if (!strcmp(s, "ipaddr")) - co->host = strdup(seq + 1); + co->host = turn_strdup(seq + 1); else if (!strcmp(s, "hostaddr")) - co->host = strdup(seq + 1); + co->host = turn_strdup(seq + 1); else if (!strcmp(s, "dbname")) - co->dbname = strdup(seq + 1); + co->dbname = turn_strdup(seq + 1); else if (!strcmp(s, "db")) - co->dbname = strdup(seq + 1); + co->dbname = turn_strdup(seq + 1); else if (!strcmp(s, "database")) - co->dbname = strdup(seq + 1); + co->dbname = turn_strdup(seq + 1); else if (!strcmp(s, "user")) ; else if (!strcmp(s, "uname")) @@ -118,13 +118,13 @@ static Ryconninfo *RyconninfoParse(const char *userdb, char **errmsg) { else if (!strcmp(s, "username")) ; else if (!strcmp(s, "password")) - co->password = strdup(seq + 1); + co->password = turn_strdup(seq + 1); else if (!strcmp(s, "pwd")) - co->password = strdup(seq + 1); + co->password = turn_strdup(seq + 1); else if (!strcmp(s, "passwd")) - co->password = strdup(seq + 1); + co->password = turn_strdup(seq + 1); else if (!strcmp(s, "secret")) - co->password = strdup(seq + 1); + co->password = turn_strdup(seq + 1); else if (!strcmp(s, "port")) co->port = (unsigned int) atoi(seq + 1); else if (!strcmp(s, "p")) @@ -137,7 +137,7 @@ static Ryconninfo *RyconninfoParse(const char *userdb, char **errmsg) { RyconninfoFree(co); co = NULL; if (errmsg) { - *errmsg = strdup(s); + *errmsg = turn_strdup(s); } break; } @@ -150,11 +150,11 @@ static Ryconninfo *RyconninfoParse(const char *userdb, char **errmsg) { if(co) { if(!(co->dbname)) - co->dbname=strdup("0"); + co->dbname=turn_strdup("0"); if(!(co->host)) - co->host=strdup("127.0.0.1"); + co->host=turn_strdup("127.0.0.1"); if(!(co->password)) - co->password=strdup(""); + co->password=turn_strdup(""); } return co; @@ -1152,7 +1152,7 @@ static void redis_reread_realms(secrets_list_t * realms_list) { redisReply *reply = (redisReply*) redisCommand(rc, "keys turn/origin/*"); if (reply) { - ur_string_map *o_to_realm_new = ur_string_map_create(free); + ur_string_map *o_to_realm_new = ur_string_map_create(turn_free_simple); secrets_list_t keys; @@ -1188,7 +1188,7 @@ static void redis_reread_realms(secrets_list_t * realms_list) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type); } else { get_realm(rget->str); - ur_string_map_value_type value = strdup(rget->str); + ur_string_map_value_type value = turn_strdup(rget->str); ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) origin, value); } turnFreeRedisReply(rget); diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 6a53b75f..c7b8b797 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1785,8 +1785,8 @@ int main(int argc, char **argv) #endif 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(free); - turn_params.default_users_db.ram_db.dynamic_accounts = ur_string_map_create(free); + 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); diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 626f74de..4a02764f 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -576,7 +576,7 @@ ioa_timer_handle set_ioa_timer(ioa_engine_handle e, int secs, int ms, ioa_timer_ te->e = e; te->ev = ev; te->cb = cb; - te->txt = strdup(txt); + te->txt = turn_strdup(txt); if(!ms) { tv.tv_usec = 0; @@ -3620,11 +3620,11 @@ static void init_super_memory_region(super_memory_t *r) if(r) { ns_bzero(r,sizeof(super_memory_t)); - r->super_memory = (char**)malloc(sizeof(char*)); - r->super_memory[0] = (char*)malloc(TURN_SM_SIZE); + r->super_memory = (char**)turn_malloc(sizeof(char*)); + r->super_memory[0] = (char*)turn_malloc(TURN_SM_SIZE); ns_bzero(r->super_memory[0],TURN_SM_SIZE); - r->sm_allocated = (size_t*)malloc(sizeof(size_t*)); + r->sm_allocated = (size_t*)turn_malloc(sizeof(size_t*)); r->sm_allocated[0] = 0; r->sm_total_sz = TURN_SM_SIZE; @@ -3644,7 +3644,7 @@ void init_super_memory(void) super_memory_t* new_super_memory_region(void) { - super_memory_t* r = (super_memory_t*)malloc(sizeof(super_memory_t)); + super_memory_t* r = (super_memory_t*)turn_malloc(sizeof(super_memory_t)); init_super_memory_region(r); return r; } @@ -3658,7 +3658,7 @@ void* allocate_super_memory_region_func(super_memory_t *r, size_t size, const ch void *ret = NULL; if(!r) { - ret = malloc(size); + ret = turn_malloc(size); ns_bzero(ret, size); return ret; } @@ -3691,10 +3691,10 @@ void* allocate_super_memory_region_func(super_memory_t *r, size_t size, const ch if(!region) { r->sm_chunk += 1; - r->super_memory = (char**)realloc(r->super_memory,(r->sm_chunk+1) * sizeof(char*)); - r->super_memory[r->sm_chunk] = (char*)malloc(TURN_SM_SIZE); + r->super_memory = (char**)turn_realloc(r->super_memory,0,(r->sm_chunk+1) * sizeof(char*)); + r->super_memory[r->sm_chunk] = (char*)turn_malloc(TURN_SM_SIZE); ns_bzero(r->super_memory[r->sm_chunk],TURN_SM_SIZE); - r->sm_allocated = (size_t*)realloc(r->sm_allocated,(r->sm_chunk+1) * sizeof(size_t*)); + r->sm_allocated = (size_t*)turn_realloc(r->sm_allocated,0,(r->sm_chunk+1) * sizeof(size_t*)); r->sm_allocated[r->sm_chunk] = 0; region = r->super_memory[r->sm_chunk]; rsz = r->sm_allocated + r->sm_chunk; @@ -3714,7 +3714,7 @@ void* allocate_super_memory_region_func(super_memory_t *r, size_t size, const ch pthread_mutex_unlock(&r->mutex_sm); if(!ret) { - ret = malloc(size); + ret = turn_malloc(size); ns_bzero(ret, size); } diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index 5c4bf5b2..a2656e6b 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -465,7 +465,7 @@ static int print_session(ur_map_key_type key, ur_map_value_type value, void *arg csarg->user_names = (char**)turn_realloc(csarg->user_names, (size_t)value * sizeof(char*), csarg->users_number * sizeof(char*)); - csarg->user_names[(size_t)value] = strdup((char*)tsi->username); + csarg->user_names[(size_t)value] = turn_strdup((char*)tsi->username); csarg->user_counters[(size_t)value] = 0; ur_string_map_put(csarg->users, (ur_string_map_key_type)(char*)tsi->username, value); } @@ -939,7 +939,7 @@ static int run_cli_input(struct cli_session* cs, const char *buf0, unsigned int if(cs && buf0 && cs->ts && cs->bev) { - char *buf = (char*)malloc(len+1); + char *buf = (char*)turn_malloc(len+1); ns_bcopy(buf0,buf,len); buf[len]=0; @@ -1078,7 +1078,7 @@ static int run_cli_input(struct cli_session* cs, const char *buf0, unsigned int type_cli_cursor(cs); } - free(buf); + turn_free(buf,len+1); } return ret; diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 9387231f..7505da77 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -105,7 +105,7 @@ void create_default_realm() /* init everything: */ TURN_MUTEX_INIT_RECURSIVE(&o_to_realm_mutex); init_secrets_list(&realms_list); - o_to_realm = ur_string_map_create(free); + o_to_realm = ur_string_map_create(turn_free_simple); default_realm_params_ptr = &_default_realm_params; realms = ur_string_map_create(NULL); ur_string_map_lock(realms); @@ -169,7 +169,7 @@ int get_realm_options_by_origin(char *origin, realm_options_t* ro) ur_string_map_value_type value = 0; TURN_MUTEX_LOCK(&o_to_realm_mutex); if (ur_string_map_get(o_to_realm, (ur_string_map_key_type) origin, &value) && value) { - char *realm = strdup((char*)value); + char *realm = turn_strdup((char*)value); TURN_MUTEX_UNLOCK(&o_to_realm_mutex); realm_params_t rp; get_realm_data(realm, &rp); @@ -292,7 +292,7 @@ void add_to_secrets_list(secrets_list_t *sl, const char* elem) { if(sl && elem) { sl->secrets = (char**)turn_realloc(sl->secrets,0,(sizeof(char*)*(sl->sz+1))); - sl->secrets[sl->sz] = strdup(elem); + sl->secrets[sl->sz] = turn_strdup(elem); sl->sz += 1; } } @@ -384,7 +384,7 @@ static char *get_real_username(char *usname) usname = col+1; } else { *col=0; - usname = strdup(usname); + usname = turn_strdup(usname); *col=turn_params.rest_api_separator; return usname; } @@ -392,7 +392,7 @@ static char *get_real_username(char *usname) } } - return strdup(usname); + return turn_strdup(usname); } /* @@ -684,7 +684,7 @@ int check_new_allocation_quota(u08bits *user, int oauth, u08bits *realm) { int ret = 0; if (user || oauth) { - u08bits *username = oauth ? (u08bits*)strdup("") : (u08bits*)get_real_username((char*)user); + u08bits *username = oauth ? (u08bits*)turn_strdup("") : (u08bits*)get_real_username((char*)user); realm_params_t *rp = get_realm((char*)realm); ur_string_map_lock(rp->status.alloc_counters); if (rp->options.perf_options.total_quota && (rp->status.total_current_allocs >= rp->options.perf_options.total_quota)) { @@ -716,7 +716,7 @@ int check_new_allocation_quota(u08bits *user, int oauth, u08bits *realm) void release_allocation_quota(u08bits *user, int oauth, u08bits *realm) { if (user) { - u08bits *username = oauth ? (u08bits*)strdup("") : (u08bits*)get_real_username((char*)user); + u08bits *username = oauth ? (u08bits*)turn_strdup("") : (u08bits*)get_real_username((char*)user); realm_params_t *rp = get_realm((char*)realm); ur_string_map_lock(rp->status.alloc_counters); if(username[0]) { @@ -1154,7 +1154,7 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b add_and_cont: content = (char**)turn_realloc(content, 0, sizeof(char*) * (++csz)); - content[csz - 1] = strdup(s0); + content[csz - 1] = turn_strdup(s0); } fclose(f); @@ -1169,11 +1169,11 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b snprintf(us+strlen(us),sizeof(us)-strlen(us),"%02x",(unsigned int)key[i]); } content = (char**)turn_realloc(content,0,sizeof(char*)*(++csz)); - content[csz-1]=strdup(us); + content[csz-1]=turn_strdup(us); } if(!full_path_to_userdb_file) - full_path_to_userdb_file=strdup(pud->userdb); + full_path_to_userdb_file=turn_strdup(pud->userdb); size_t dirsz = strlen(full_path_to_userdb_file)+21; char *dir = (char*)turn_malloc(dirsz+1); @@ -1434,7 +1434,7 @@ void update_white_and_black_lists(void) int add_ip_list_range(const char * range0, ip_range_list_t * list) { - char *range = strdup(range0); + char *range = turn_strdup(range0); char* separator = strchr(range, '-'); diff --git a/src/client/ns_turn_ioaddr.c b/src/client/ns_turn_ioaddr.c index afbe3700..13fb33d1 100644 --- a/src/client/ns_turn_ioaddr.c +++ b/src/client/ns_turn_ioaddr.c @@ -313,7 +313,7 @@ int make_ioa_addr_from_full_string(const u08bits* saddr, int default_port, ioa_a port = default_port; ret = make_ioa_addr((u08bits*)sa,port,addr); } - turn_free(s,strlen(s)+1); + free(s); return ret; } @@ -493,10 +493,10 @@ static size_t msz = 0; void ioa_addr_add_mapping(ioa_addr *apub, ioa_addr *apriv) { size_t new_size = msz + sizeof(ioa_addr*); - public_addrs = (ioa_addr**)turn_realloc(public_addrs, msz, new_size); - private_addrs = (ioa_addr**)turn_realloc(private_addrs, msz, new_size); - public_addrs[mcount]=(ioa_addr*)turn_malloc(sizeof(ioa_addr)); - private_addrs[mcount]=(ioa_addr*)turn_malloc(sizeof(ioa_addr)); + public_addrs = (ioa_addr**)realloc(public_addrs, new_size); + private_addrs = (ioa_addr**)realloc(private_addrs, new_size); + public_addrs[mcount]=(ioa_addr*)malloc(sizeof(ioa_addr)); + private_addrs[mcount]=(ioa_addr*)malloc(sizeof(ioa_addr)); addr_cpy(public_addrs[mcount],apub); addr_cpy(private_addrs[mcount],apriv); ++mcount; diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index d023e1cc..6e95c385 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -117,6 +117,7 @@ static inline u64bits _ioa_ntoh64(u64bits v) void *turn_malloc_func(size_t sz, const char* file, int line); void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* file, int line); void turn_free_func(void *ptr, size_t sz, const char* file, int line); + void turn_free_simple(void *ptr); void *turn_calloc_func(size_t number, size_t size, const char* file, int line); char *turn_strdup_func(const char* s, const char* file, int line); @@ -135,6 +136,7 @@ static inline u64bits _ioa_ntoh64(u64bits v) #define turn_realloc(ptr, old_sz, new_sz) realloc((ptr),(size_t)(new_sz)) #define turn_calloc(number, sz) calloc((number),(size_t)(sz)) #define turn_strdup(s) strdup((s)) +#define turn_free_simple free #endif From 2b06ed4e2d44aacf761e13c3db3fc1bdf9181c3a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 11 Oct 2014 06:57:55 +0000 Subject: [PATCH 254/805] minor fix --- src/apps/common/ns_turn_utils.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/apps/common/ns_turn_utils.c b/src/apps/common/ns_turn_utils.c index 4388ff56..4406d007 100644 --- a/src/apps/common/ns_turn_utils.c +++ b/src/apps/common/ns_turn_utils.c @@ -755,7 +755,7 @@ static void tm_id(char *id, const char* file, int line) { #define TM_START() char id[128];tm_id(id,file,line);tm_init() -void tm_print_func(void); +extern "C" void tm_print_func(void); void tm_print_func(void) { pthread_mutex_lock(&tm); printf("=============================================\n"); @@ -767,7 +767,7 @@ void tm_print_func(void) { pthread_mutex_unlock(&tm); } -void *turn_malloc_func(size_t sz, const char* file, int line); +extern "C" void *turn_malloc_func(size_t sz, const char* file, int line); void *turn_malloc_func(size_t sz, const char* file, int line) { TM_START(); @@ -779,7 +779,7 @@ void *turn_malloc_func(size_t sz, const char* file, int line) { return ptr; } -void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* file, int line); +extern "C" void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* file, int line); void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* file, int line) { UNUSED_ARG(old_sz); @@ -796,7 +796,7 @@ void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* fil return ptr; } -void turn_free_func(void *ptr, size_t sz, const char* file, int line); +extern "C" void turn_free_func(void *ptr, size_t sz, const char* file, int line); void turn_free_func(void *ptr, size_t sz, const char* file, int line) { UNUSED_ARG(sz); @@ -808,7 +808,7 @@ void turn_free_func(void *ptr, size_t sz, const char* file, int line) { free(ptr); } -void turn_free_simple(void *ptr); +extern "C" void turn_free_simple(void *ptr); void turn_free_simple(void *ptr) { tm_init(); @@ -818,7 +818,7 @@ void turn_free_simple(void *ptr) { free(ptr); } -void *turn_calloc_func(size_t number, size_t size, const char* file, int line); +extern "C" void *turn_calloc_func(size_t number, size_t size, const char* file, int line); void *turn_calloc_func(size_t number, size_t size, const char* file, int line) { TM_START(); @@ -830,7 +830,7 @@ void *turn_calloc_func(size_t number, size_t size, const char* file, int line) { return ptr; } -char *turn_strdup_func(const char* s, const char* file, int line); +extern "C" char *turn_strdup_func(const char* s, const char* file, int line); char *turn_strdup_func(const char* s, const char* file, int line) { TM_START(); From 40cd178b1fb8d9e12a4b5abb522b91f409c6ddba Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 11 Oct 2014 08:39:52 +0000 Subject: [PATCH 255/805] bandwidth allocation fixed --- ChangeLog | 1 + src/server/ns_turn_server.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index bac14448..af088438 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,7 @@ Version 4.2.1.2 'Monza': - Move secondary download area to coturn.net. - Auota allocation fixed. - Core dump fixed. + - Bandwidth allocation fixed. 08/14/2014 Oleg Moskalenko Version 4.1.2.1 'Vitari': diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index f128fcb5..2d8dcc96 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -176,14 +176,20 @@ static void dec_quota(ts_ur_super_session* ss) ss->quota_used = 0; + (((turn_turnserver*)ss->server)->raqcb)(ss->username, ss->oauth, (u08bits*)ss->realm_options.name); + } +} + +static void dec_bps(ts_ur_super_session* ss) +{ + if(ss && ss->server) { + if(ss->bps) { if(((turn_turnserver*)ss->server)->allocate_bps_func) { ((turn_turnserver*)ss->server)->allocate_bps_func(ss->bps,0); } ss->bps = 0; } - - (((turn_turnserver*)ss->server)->raqcb)(ss->username, ss->oauth, (u08bits*)ss->realm_options.name); } } @@ -4064,6 +4070,7 @@ int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, report_turn_session_info(server,ss,1); dec_quota(ss); + dec_bps(ss); if(!force && ss->is_mobile) { From c0442c38c7507fd96af84bec731491bafc6392d6 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 11 Oct 2014 09:15:02 +0000 Subject: [PATCH 256/805] bandwidth fix --- src/apps/relay/netengine.c | 2 +- src/server/ns_turn_server.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 8f80ac51..a63bc3c7 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -107,7 +107,6 @@ static band_limit_t allocate_bps(band_limit_t bps, int positive) if(turn_params.bps_capacity_allocated >= bps) { turn_params.bps_capacity_allocated -= bps; - ret = turn_params.bps_capacity_allocated; } else { turn_params.bps_capacity_allocated = 0; } @@ -115,6 +114,7 @@ static band_limit_t allocate_bps(band_limit_t bps, int positive) pthread_mutex_unlock(&mutex_bps); } + return ret; } diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 2d8dcc96..0904d7ca 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1179,7 +1179,7 @@ static int handle_turn_allocate(turn_turnserver *server, if(max_bps && (!bps || (bps && (bps>max_bps)))) { bps = max_bps; } - if(bps) { + if(bps && (ss->bps == 0)) { ss->bps = server->allocate_bps_func(bps,1); if(!(ss->bps)) { *err_code = 486; From 24250784250145b7816d9044b5ccf72171f2c071 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 11 Oct 2014 18:18:23 +0000 Subject: [PATCH 257/805] log fixes --- ChangeLog | 3 ++- src/apps/common/hiredis_libevent2.c | 6 +++--- src/apps/common/ns_turn_utils.h | 1 + src/apps/relay/dbdrivers/dbd_mongo.c | 4 +++- src/apps/relay/dbdrivers/dbd_redis.c | 2 +- src/apps/relay/mainrelay.c | 10 +++++----- src/apps/relay/ns_ioalib_engine_impl.c | 4 +++- src/apps/uclient/startuclient.c | 4 ++-- src/ns_turn_defs.h | 6 ++++++ 9 files changed, 26 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index af088438..44233a4b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,9 +10,10 @@ Version 4.2.1.2 'Monza': - Mobility ticket retransmission fixed. - Move debian package from SVN to GIT. - Move secondary download area to coturn.net. - - Auota allocation fixed. + - Quota allocation fixed. - Core dump fixed. - Bandwidth allocation fixed. + - Logging fixes. 08/14/2014 Oleg Moskalenko Version 4.1.2.1 'Vitari': diff --git a/src/apps/common/hiredis_libevent2.c b/src/apps/common/hiredis_libevent2.c index f4b62c00..24ca2fa0 100644 --- a/src/apps/common/hiredis_libevent2.c +++ b/src/apps/common/hiredis_libevent2.c @@ -91,7 +91,7 @@ static void redisLibeventReadEvent(int fd, short event, void *arg) { } while((len<0)&&(errno == EINTR)); if(len<1) { e->invalid = 1; - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis connection broken: e=0x%lx\n", __FUNCTION__, (unsigned long)e); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Redis connection broken: e=0x%lx\n", __FUNCTION__, ((unsigned long)e)); } } if(redis_le_valid(e)) { @@ -213,7 +213,7 @@ void send_message_to_redis(redis_context_handle rch, const char *command, const if((redisAsyncCommand(ac, NULL, e, rm.format, rm.arg)!=REDIS_OK)) { e->invalid = 1; - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis connection broken: ac=0x%lx, e=0x%x\n", __FUNCTION__,(unsigned long)ac,(unsigned long)e); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Redis connection broken: ac=0x%lx, e=0x%lx\n", __FUNCTION__,(unsigned long)ac,(unsigned long)e); } } } @@ -372,7 +372,7 @@ static void redis_reconnect(struct redisLibeventEvents *e) } if(redis_le_valid(e)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Re-connected to redis, async\n", __FUNCTION__); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: Re-connected to redis, async\n", __FUNCTION__); } } diff --git a/src/apps/common/ns_turn_utils.h b/src/apps/common/ns_turn_utils.h index 72da8e29..1df95651 100644 --- a/src/apps/common/ns_turn_utils.h +++ b/src/apps/common/ns_turn_utils.h @@ -32,6 +32,7 @@ #define __TURN_ULIB__ #if !defined(TURN_LOG_FUNC) +//#define TURN_LOG_FUNC(level, ...) printf (__VA_ARGS__) #define TURN_LOG_FUNC turn_log_func_default #endif diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index 21f18284..e8478b2b 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -52,8 +52,10 @@ static void mongo_logger(mongoc_log_level_t log_level, const char * log_domain, UNUSED_ARG(log_domain); UNUSED_ARG(user_data); - TURN_LOG_LEVEL l; + TURN_LOG_LEVEL l = TURN_LOG_LEVEL_INFO; + UNUSED_ARG(l); + switch(log_level) { case MONGOC_LOG_LEVEL_ERROR: l = TURN_LOG_LEVEL_ERROR; diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index 731757af..e3547cfd 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -268,7 +268,7 @@ static redisContext *get_redis_connection(void) { if(redisconnection) { if(redisconnection->err) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot connect to redis, err=%d, flags=0x%x\n", __FUNCTION__,(int)redisconnection->err,(unsigned long)redisconnection->flags); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Cannot connect to redis, err=%d, flags=0x%lx\n", __FUNCTION__,(int)redisconnection->err,(unsigned long)redisconnection->flags); redisFree(redisconnection); pud->connection = NULL; redisconnection = NULL; diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index c7b8b797..9b6bcb6d 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1918,7 +1918,7 @@ int main(int argc, char **argv) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "===========Discovering listener addresses: =========\n"); int maddrs = make_local_listeners_list(); if((maddrs<1) || !turn_params.listener.addrs_number) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot configure any meaningful IP listener address\n", __FUNCTION__); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Cannot configure any meaningful IP listener address\n", __FUNCTION__); fprintf(stderr,"\n%s\n", Usage); exit(-1); } @@ -1953,7 +1953,7 @@ int main(int argc, char **argv) } if (!turn_params.relays_number) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "You must specify the relay address(es)\n", + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: You must specify the relay address(es)\n", __FUNCTION__); fprintf(stderr,"\n%s\n", Usage); exit(-1); @@ -2345,7 +2345,7 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) EC_KEY *ecdh = EC_KEY_new_by_curve_name(nid); if (!ecdh) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, - "%s: ERROR: allocate EC suite\n"); + "%s: ERROR: allocate EC suite\n",__FUNCTION__); } else { SSL_CTX_set_tmp_ecdh(ctx, ecdh); EC_KEY_free(ecdh); @@ -2379,10 +2379,10 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) } if(!dh) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot allocate DH suite\n"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot allocate DH suite\n",__FUNCTION__); } else { if (1 != SSL_CTX_set_tmp_dh (ctx, dh)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot set DH\n"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot set DH\n",__FUNCTION__); } DH_free (dh); } diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 4a02764f..c42a5e00 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -188,6 +188,8 @@ static void log_socket_event(ioa_socket_handle s, const char *msg, int error) { if(error) ll = TURN_LOG_LEVEL_ERROR; + UNUSED_ARG(ll); + { char sraddr[129]="\0"; char sladdr[129]="\0"; @@ -367,7 +369,7 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm, } if (!relays_number || !relay_addrs || !tp) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot create TURN engine\n", __FUNCTION__); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Cannot create TURN engine\n", __FUNCTION__); return NULL; } else { ioa_engine_handle e = (ioa_engine_handle)allocate_super_memory_region(sm, sizeof(ioa_engine)); diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 2012ecdb..db9457cb 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -495,7 +495,7 @@ static int clnet_allocate(int verbose, current_reservation_token = rtv; if (verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, - "%s: rtv=%llu\n", __FUNCTION__, rtv); + "%s: rtv=%llu\n", __FUNCTION__, (long long unsigned int)rtv); read_mobility_ticket(clnet_info, &message); @@ -542,7 +542,7 @@ static int clnet_allocate(int verbose, return -1; } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, - "trying allocate again...\n", err_code); + "trying allocate again %d...\n", err_code); sleep(1); reopen_socket = 1; } diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 6e95c385..ef53e765 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -113,6 +113,12 @@ static inline u64bits _ioa_ntoh64(u64bits v) #if defined(TURN_MEMORY_DEBUG) +#if defined(TURN_LOG_FUNC) +#undef TURN_LOG_FUNC +#endif + +#define TURN_LOG_FUNC(level, ...) printf (__VA_ARGS__) + void tm_print_func(void); void *turn_malloc_func(size_t sz, const char* file, int line); void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* file, int line); From 929e5fc46322a99d3912adb4d013b08c85fbbae9 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 13 Oct 2014 01:05:46 +0000 Subject: [PATCH 258/805] a minor fix --- src/client/ns_turn_msg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index aa48440d..c2106aea 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -143,7 +143,7 @@ int stun_produce_integrity_key_str(u08bits *uname, u08bits *realm, u08bits *upwd size_t plen = strlen((s08bits*)upwd); size_t sz = ulen+1+rlen+1+plen+1+10; size_t strl = ulen+1+rlen+1+plen; - u08bits *str = (u08bits*)malloc(sz+1); + u08bits *str = (u08bits*)turn_malloc(sz+1); strncpy((s08bits*)str,(s08bits*)uname,sz); str[ulen]=':'; @@ -171,7 +171,7 @@ int stun_produce_integrity_key_str(u08bits *uname, u08bits *realm, u08bits *upwd MD5_Final(key,&ctx); } - free(str); + turn_free(str,sz+1); return 0; } From 2bfc50f5e00cf76cc4d654e8c2dd974cbe1e6c03 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 13 Oct 2014 01:06:27 +0000 Subject: [PATCH 259/805] changelog updated --- ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 44233a4b..86ad9dad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,7 +13,8 @@ Version 4.2.1.2 'Monza': - Quota allocation fixed. - Core dump fixed. - Bandwidth allocation fixed. - - Logging fixes. + - Memory code clening. + - Logging fixed. 08/14/2014 Oleg Moskalenko Version 4.1.2.1 'Vitari': From 11b7156e5d09acd426f35c1dbb943d0bb865ea5f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 13 Oct 2014 07:23:19 +0000 Subject: [PATCH 260/805] cleaning --- ChangeLog | 4 ++++ rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/apps/common/ns_turn_utils.c | 14 ++++++-------- src/ns_turn_defs.h | 2 +- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 86ad9dad..6c7d863a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +10/13/2014 Oleg Moskalenko +Version 4.2.1.3 'Monza': + - Code cleaning. + 10/05/2014 Oleg Moskalenko Version 4.2.1.2 'Monza': - oAuth security experimental implementation; diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 84d5ac35..1d327744 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.2.1.2 +TURNVERSION=4.2.1.3 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index a014ae7e..f32362b3 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.2.1.2 +Version: 4.2.1.3 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,6 +294,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Mon Oct 13 2014 Oleg Moskalenko + - Sync to 4.2.1.3 * Sun Oct 05 2014 Oleg Moskalenko - Sync to 4.2.1.2 * Thu Aug 14 2014 Oleg Moskalenko diff --git a/src/apps/common/ns_turn_utils.c b/src/apps/common/ns_turn_utils.c index 4406d007..ae96519f 100644 --- a/src/apps/common/ns_turn_utils.c +++ b/src/apps/common/ns_turn_utils.c @@ -664,15 +664,13 @@ int get_canonic_origin(const char* o, char *co, int sz) #include #include -using namespace std; - static volatile int tmm_init = 0; static pthread_mutex_t tm; typedef void* ptrtype; -typedef set ptrs_t; -typedef map str_to_ptrs_t; -typedef map ptr_to_str_t; +typedef std::set ptrs_t; +typedef std::map str_to_ptrs_t; +typedef std::map ptr_to_str_t; static str_to_ptrs_t str_to_ptrs; static ptr_to_str_t ptr_to_str; @@ -692,7 +690,7 @@ static void add_tm_ptr(void *ptr, const char *id) { if(!ptr) return; - string sid(id); + std::string sid(id); str_to_ptrs_t::iterator iter; @@ -701,7 +699,7 @@ static void add_tm_ptr(void *ptr, const char *id) { iter = str_to_ptrs.find(sid); if(iter == str_to_ptrs.end()) { - set sp; + std::set sp; sp.insert(ptr); str_to_ptrs[sid]=sp; } else { @@ -730,7 +728,7 @@ static void del_tm_ptr(void *ptr, const char *id) { } else { - string sid = pts_iter->second; + std::string sid = pts_iter->second; ptr_to_str.erase(pts_iter); str_to_ptrs_t::iterator iter = str_to_ptrs.find(sid); diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index ef53e765..037b74f4 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.2.1.2" +#define TURN_SERVER_VERSION "4.2.1.3" #define TURN_SERVER_VERSION_NAME "Monza" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 6d4be6640e770d897a3389cbd28a72306b030ee8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 13 Oct 2014 09:32:26 +0000 Subject: [PATCH 261/805] changelog typo fixed. Compilation warning fixed. --- ChangeLog | 2 +- src/apps/relay/mainrelay.c | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6c7d863a..1dc6aaa7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -17,7 +17,7 @@ Version 4.2.1.2 'Monza': - Quota allocation fixed. - Core dump fixed. - Bandwidth allocation fixed. - - Memory code clening. + - Memory code cleaning. - Logging fixed. 08/14/2014 Oleg Moskalenko diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 9b6bcb6d..11dd9dc0 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1701,9 +1701,11 @@ static void drop_privileges(void) static void init_domain(void) { #if !defined(TURN_NO_GETDOMAINNAME) - getdomainname(turn_params.domain,sizeof(turn_params.domain)-1); - if(!strcmp(turn_params.domain,"(none)")) - turn_params.domain[0]=0; + if(getdomainname(turn_params.domain,sizeof(turn_params.domain)-1)<0) { + turn_params.domain[0]=0; + } else if(!strcmp(turn_params.domain,"(none)")) { + turn_params.domain[0]=0; + } #endif } From 423501395019beb58a30dfb9b9eadc2ea2c15e95 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 14 Oct 2014 07:27:00 +0000 Subject: [PATCH 262/805] TCP/TLS tests --- ChangeLog | 3 ++- src/apps/uclient/session.h | 1 + src/apps/uclient/startuclient.c | 10 ++++++---- src/apps/uclient/uclient.c | 33 +++++++++++++++++++++------------ src/apps/uclient/uclient.h | 4 ++-- 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1dc6aaa7..a1104209 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ -10/13/2014 Oleg Moskalenko +10/14/2014 Oleg Moskalenko Version 4.2.1.3 'Monza': - Code cleaning. + - TCP/TLS tests extended. 10/05/2014 Oleg Moskalenko Version 4.2.1.2 'Monza': diff --git a/src/apps/uclient/session.h b/src/apps/uclient/session.h index 66a2d52b..a4149865 100644 --- a/src/apps/uclient/session.h +++ b/src/apps/uclient/session.h @@ -75,6 +75,7 @@ typedef struct { char rsaddr[129]; char ifname[129]; ioa_addr peer_addr; + ioa_addr relay_addr; ioa_socket_raw fd; SSL *ssl; int broken; diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index db9457cb..893def56 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -456,21 +456,23 @@ static int clnet_allocate(int verbose, return -1; } else { if (verbose) { - ioa_addr remote_addr; - memcpy(&remote_addr, relay_addr,sizeof(ioa_addr)); - addr_debug_print(verbose, &remote_addr,"Received relay addr"); + ioa_addr raddr; + memcpy(&raddr, relay_addr,sizeof(ioa_addr)); + addr_debug_print(verbose, &raddr,"Received relay addr"); } if(!addr_any(relay_addr)) { if(relay_addr->ss.sa_family == AF_INET) { if(default_address_family != STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6) { found = 1; + addr_cpy(&(clnet_info->relay_addr),relay_addr); break; } } if(relay_addr->ss.sa_family == AF_INET6) { if(default_address_family == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6) { found = 1; + addr_cpy(&(clnet_info->relay_addr),relay_addr); break; } } @@ -1535,7 +1537,7 @@ void tcp_data_connect(app_ur_session *elem, u32bits cid) ++elem->pinfo.tcp_conn_number; int i = (int)(elem->pinfo.tcp_conn_number-1); - elem->pinfo.tcp_conn=(app_tcp_conn_info**)realloc(elem->pinfo.tcp_conn,elem->pinfo.tcp_conn_number*sizeof(app_tcp_conn_info*)); + elem->pinfo.tcp_conn=(app_tcp_conn_info**)turn_realloc(elem->pinfo.tcp_conn,0,elem->pinfo.tcp_conn_number*sizeof(app_tcp_conn_info*)); elem->pinfo.tcp_conn[i]=(app_tcp_conn_info*)turn_malloc(sizeof(app_tcp_conn_info)); ns_bzero(elem->pinfo.tcp_conn[i],sizeof(app_tcp_conn_info)); diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 65a46d41..9071d5bf 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -153,8 +153,10 @@ static void uc_delete_session_elem_data(app_ur_session* cdi) { } } cdi->pinfo.tcp_conn_number=0; - turn_free(cdi->pinfo.tcp_conn, 111); - cdi->pinfo.tcp_conn=NULL; + if(cdi->pinfo.tcp_conn) { + turn_free(cdi->pinfo.tcp_conn, 111); + cdi->pinfo.tcp_conn=NULL; + } } if(cdi->pinfo.ssl && !(cdi->pinfo.broken)) { if(!(SSL_get_shutdown(cdi->pinfo.ssl) & SSL_SENT_SHUTDOWN)) { @@ -1294,9 +1296,12 @@ void start_mclient(const char *remote_address, int port, int connect_err = 0; socket_connect(elems[i]->pinfo.fd, &(elems[i]->pinfo.remote_addr), &connect_err); } - } else if((i%2) == 0) { - if (turn_tcp_connect(clnet_verbose, &(elems[i]->pinfo), &(elems[i]->pinfo.peer_addr)) < 0) { - exit(-1); + } else { + int j = 0; + for(j=i+1;jpinfo), &(elems[j]->pinfo.relay_addr)) < 0) { + exit(-1); + } } } } @@ -1328,18 +1333,22 @@ void start_mclient(const char *remote_address, int port, break; } else { for(i=0;ipinfo.tcp_conn_number>0 && - elems[i]->pinfo.tcp_conn[0]->tcp_data_bound) { - completed += elems[i]->pinfo.tcp_conn_number; + int j = 0; + for(j=0;j<(int)elems[i]->pinfo.tcp_conn_number;j++) { + if(elems[i]->pinfo.tcp_conn[j]->tcp_data_bound) { + completed++; + } } } - if(completed >= total_clients) + if(completed >= total_clients*(total_clients-1)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%d connections are completed\n",(int)(completed)); break; + } } run_events(0); - if(current_time > connect_wait_start_time + STARTING_TCP_RELAY_TIME) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: %d connections are not completed\n", - (int)(total_clients - completed)); + if(current_time > connect_wait_start_time + STARTING_TCP_RELAY_TIME + total_clients) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: %d connections are completed, not enough\n", + (int)(completed)); break; } } diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index 8891f988..ea3958a1 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -43,8 +43,8 @@ extern "C" { ////////////////////////////////////////////// -#define STOPPING_TIME (5) -#define STARTING_TCP_RELAY_TIME (10) +#define STOPPING_TIME (10) +#define STARTING_TCP_RELAY_TIME (30) extern int clmessage_length; extern int do_not_use_channel; From 7e67aa404846f3b9b7d81076e8e1c142337bc40b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 14 Oct 2014 16:52:55 +0000 Subject: [PATCH 263/805] minor fix --- src/apps/uclient/uclient.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 9071d5bf..0bc2ba9f 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1221,7 +1221,7 @@ void start_mclient(const char *remote_address, int port, ++mclient; } - elems = (app_ur_session**)malloc(sizeof(app_ur_session)*((mclient*2)+1)+sizeof(void*)); + elems = (app_ur_session**)turn_malloc(sizeof(app_ur_session)*((mclient*2)+1)+sizeof(void*)); __turn_getMSTime(); u32bits stime = current_time; @@ -1419,7 +1419,7 @@ void start_mclient(const char *remote_address, int port, (unsigned long)min_jitter, (unsigned long)max_jitter); - free(elems); + turn_free(elems,0); } /////////////////////////////////////////// From e50080c7532ddaa51c856d1e8617184b02bc1505 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 15 Oct 2014 05:49:25 +0000 Subject: [PATCH 264/805] version bump --- ChangeLog | 2 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 ++-- src/ns_turn_defs.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index a1104209..4c680ff6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ 10/14/2014 Oleg Moskalenko -Version 4.2.1.3 'Monza': +Version 4.2.1.4 'Monza': - Code cleaning. - TCP/TLS tests extended. diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 1d327744..8cfb0989 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.2.1.3 +TURNVERSION=4.2.1.4 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index f32362b3..bdff0f76 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.2.1.3 +Version: 4.2.1.4 Release: 0%{dist} Summary: Coturn TURN Server @@ -295,7 +295,7 @@ fi %changelog * Mon Oct 13 2014 Oleg Moskalenko - - Sync to 4.2.1.3 + - Sync to 4.2.1.4 * Sun Oct 05 2014 Oleg Moskalenko - Sync to 4.2.1.2 * Thu Aug 14 2014 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 037b74f4..3c4f9199 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.2.1.3" +#define TURN_SERVER_VERSION "4.2.1.4" #define TURN_SERVER_VERSION_NAME "Monza" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 7973a31f01ee51a787848eaa5b064e1037e28b46 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 15 Oct 2014 06:44:53 +0000 Subject: [PATCH 265/805] more debug information --- src/apps/common/ns_turn_utils.c | 42 ++++++++++++------ src/apps/relay/dtls_listener.c | 8 ++-- src/apps/relay/ns_ioalib_engine_impl.c | 61 ++++++++------------------ src/apps/relay/turncli.c | 8 +--- src/apps/uclient/startuclient.c | 7 ++- src/apps/uclient/uclient.c | 12 ++--- src/ns_turn_defs.h | 21 ++++++--- 7 files changed, 77 insertions(+), 82 deletions(-) diff --git a/src/apps/common/ns_turn_utils.c b/src/apps/common/ns_turn_utils.c index ae96519f..ddc937a4 100644 --- a/src/apps/common/ns_turn_utils.c +++ b/src/apps/common/ns_turn_utils.c @@ -747,11 +747,27 @@ static void del_tm_ptr(void *ptr, const char *id) { pthread_mutex_unlock(&tm); } -static void tm_id(char *id, const char* file, int line) { - sprintf(id,"%s:%d",file,line); +static void tm_id(char *id, const char* function, int line) { + sprintf(id,"%s:%d",function,line); } -#define TM_START() char id[128];tm_id(id,file,line);tm_init() +#define TM_START() char id[128];tm_id(id,function,line);tm_init() + +extern "C" void* debug_ptr_add_func(void *ptr, const char* function, int line) { + + TM_START(); + + add_tm_ptr(ptr,id); + + return ptr; +} + +extern "C" void debug_ptr_del_func(void *ptr, const char* function, int line) { + + TM_START(); + + del_tm_ptr(ptr,id); +} extern "C" void tm_print_func(void); void tm_print_func(void) { @@ -765,8 +781,8 @@ void tm_print_func(void) { pthread_mutex_unlock(&tm); } -extern "C" void *turn_malloc_func(size_t sz, const char* file, int line); -void *turn_malloc_func(size_t sz, const char* file, int line) { +extern "C" void *turn_malloc_func(size_t sz, const char* function, int line); +void *turn_malloc_func(size_t sz, const char* function, int line) { TM_START(); @@ -777,8 +793,8 @@ void *turn_malloc_func(size_t sz, const char* file, int line) { return ptr; } -extern "C" void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* file, int line); -void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* file, int line) { +extern "C" void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* function, int line); +void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* function, int line) { UNUSED_ARG(old_sz); @@ -794,8 +810,8 @@ void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* fil return ptr; } -extern "C" void turn_free_func(void *ptr, size_t sz, const char* file, int line); -void turn_free_func(void *ptr, size_t sz, const char* file, int line) { +extern "C" void turn_free_func(void *ptr, size_t sz, const char* function, int line); +void turn_free_func(void *ptr, size_t sz, const char* function, int line) { UNUSED_ARG(sz); @@ -816,8 +832,8 @@ void turn_free_simple(void *ptr) { free(ptr); } -extern "C" void *turn_calloc_func(size_t number, size_t size, const char* file, int line); -void *turn_calloc_func(size_t number, size_t size, const char* file, int line) { +extern "C" void *turn_calloc_func(size_t number, size_t size, const char* function, int line); +void *turn_calloc_func(size_t number, size_t size, const char* function, int line) { TM_START(); @@ -828,8 +844,8 @@ void *turn_calloc_func(size_t number, size_t size, const char* file, int line) { return ptr; } -extern "C" char *turn_strdup_func(const char* s, const char* file, int line); -char *turn_strdup_func(const char* s, const char* file, int line) { +extern "C" char *turn_strdup_func(const char* s, const char* function, int line); +char *turn_strdup_func(const char* s, const char* function, int line) { TM_START(); diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index a68aad0e..f6847ec3 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -266,7 +266,7 @@ static ioa_socket_handle dtls_server_input_handler(dtls_listener_relay_server_ty timeout.tv_usec = 0; BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); - connecting_ssl = SSL_new(server->dtls_ctx); + connecting_ssl = SSL_NEW(server->dtls_ctx); SSL_set_accept_state(connecting_ssl); @@ -285,7 +285,7 @@ static ioa_socket_handle dtls_server_input_handler(dtls_listener_relay_server_ty SSL_set_shutdown(connecting_ssl, SSL_RECEIVED_SHUTDOWN); SSL_shutdown(connecting_ssl); } - SSL_free(connecting_ssl); + SSL_FREE(connecting_ssl); } return rc; @@ -536,7 +536,7 @@ static int create_new_connected_udp_socket( timeout.tv_usec = 0; BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); - connecting_ssl = SSL_new(server->dtls_ctx); + connecting_ssl = SSL_NEW(server->dtls_ctx); SSL_set_accept_state(connecting_ssl); @@ -552,7 +552,7 @@ static int create_new_connected_udp_socket( SSL_set_shutdown(connecting_ssl, SSL_RECEIVED_SHUTDOWN); SSL_shutdown(connecting_ssl); } - SSL_free(connecting_ssl); + SSL_FREE(connecting_ssl); IOA_CLOSE_SOCKET(ret); return -1; } diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index c42a5e00..66f12804 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1305,11 +1305,7 @@ static void connect_eventcb(struct bufferevent *bev, short events, void *ptr) if (events & BEV_EVENT_CONNECTED) { ret->conn_cb = NULL; ret->conn_arg = NULL; - if(ret->conn_bev) { - bufferevent_disable(ret->conn_bev,EV_READ|EV_WRITE); - bufferevent_free(ret->conn_bev); - ret->conn_bev=NULL; - } + BUFFEREVENT_FREE(ret->conn_bev); ret->connected = 1; if(cb) { cb(1,arg); @@ -1318,11 +1314,7 @@ static void connect_eventcb(struct bufferevent *bev, short events, void *ptr) /* An error occured while connecting. */ ret->conn_cb = NULL; ret->conn_arg = NULL; - if(ret->conn_bev) { - bufferevent_disable(ret->conn_bev,EV_READ|EV_WRITE); - bufferevent_free(ret->conn_bev); - ret->conn_bev=NULL; - } + BUFFEREVENT_FREE(ret->conn_bev); if(cb) { cb(0,arg); } @@ -1364,15 +1356,12 @@ ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, io set_ioa_socket_session(ret, s->session); - if(ret->conn_bev) { - bufferevent_disable(ret->conn_bev,EV_READ|EV_WRITE); - bufferevent_free(ret->conn_bev); - ret->conn_bev=NULL; - } + BUFFEREVENT_FREE(ret->conn_bev); ret->conn_bev = bufferevent_socket_new(ret->e->event_base, ret->fd, BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + debug_ptr_add(ret->conn_bev); bufferevent_setcb(ret->conn_bev, NULL, NULL, connect_eventcb, ret); ret->conn_arg = arg; @@ -1577,16 +1566,8 @@ static void close_socket_net_data(ioa_socket_handle s) evconnlistener_free(s->list_ev); s->list_ev = NULL; } - if(s->conn_bev) { - bufferevent_disable(s->conn_bev,EV_READ|EV_WRITE); - bufferevent_free(s->conn_bev); - s->conn_bev=NULL; - } - if(s->bev) { - bufferevent_disable(s->bev,EV_READ|EV_WRITE); - bufferevent_free(s->bev); - s->bev=NULL; - } + BUFFEREVENT_FREE(s->conn_bev); + BUFFEREVENT_FREE(s->bev); if (s->ssl) { if (!s->broken) { @@ -1607,8 +1588,7 @@ static void close_socket_net_data(ioa_socket_handle s) log_socket_event(s, "SSL shutdown received, socket to be closed",0); } } - SSL_free(s->ssl); - s->ssl = NULL; + SSL_FREE(s->ssl); } if (s->fd >= 0) { @@ -1630,18 +1610,10 @@ void detach_socket_net_data(ioa_socket_handle s) } s->acb = NULL; s->acbarg = NULL; - if(s->conn_bev) { - bufferevent_disable(s->conn_bev,EV_READ|EV_WRITE); - bufferevent_free(s->conn_bev); - s->conn_bev=NULL; - } + BUFFEREVENT_FREE(s->conn_bev); s->conn_arg=NULL; s->conn_cb=NULL; - if(s->bev) { - bufferevent_disable(s->bev,EV_READ|EV_WRITE); - bufferevent_free(s->bev); - s->bev=NULL; - } + BUFFEREVENT_FREE(s->bev); } } @@ -2382,7 +2354,7 @@ static int socket_input_worker(ioa_socket_handle s) #if defined(SSL_TXT_TLSV1_2) case TURN_TLS_v1_2: if(s->e->tls_ctx_v1_2) { - set_socket_ssl(s,SSL_new(s->e->tls_ctx_v1_2)); + set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_2)); STRCPY(s->orig_ctx_type,"TLSv1.2"); } break; @@ -2390,20 +2362,20 @@ static int socket_input_worker(ioa_socket_handle s) #if defined(SSL_TXT_TLSV1_1) case TURN_TLS_v1_1: if(s->e->tls_ctx_v1_1) { - set_socket_ssl(s,SSL_new(s->e->tls_ctx_v1_1)); + set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_1)); STRCPY(s->orig_ctx_type,"TLSv1.1"); } break; #endif case TURN_TLS_v1_0: if(s->e->tls_ctx_v1_0) { - set_socket_ssl(s,SSL_new(s->e->tls_ctx_v1_0)); + set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_0)); STRCPY(s->orig_ctx_type,"TLSv1.0"); } break; default: if(s->e->tls_ctx_ssl23) { - set_socket_ssl(s,SSL_new(s->e->tls_ctx_ssl23)); + set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_ssl23)); STRCPY(s->orig_ctx_type,"SSLv23"); } else { s->tobeclosed = 1; @@ -2416,6 +2388,7 @@ static int socket_input_worker(ioa_socket_handle s) s->ssl, BUFFEREVENT_SSL_ACCEPTING, BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + 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); @@ -2431,6 +2404,7 @@ static int socket_input_worker(ioa_socket_handle s) s->bev = bufferevent_socket_new(s->e->event_base, s->fd, BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + 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); @@ -3255,6 +3229,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in s->bev = bufferevent_socket_new(s->e->event_base, s->fd, BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + 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); @@ -3272,19 +3247,21 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in #if !defined(TURN_NO_TLS) if(!(s->ssl)) { //??? how we can get to this point ??? - set_socket_ssl(s,SSL_new(e->tls_ctx_ssl23)); + set_socket_ssl(s,SSL_NEW(e->tls_ctx_ssl23)); STRCPY(s->orig_ctx_type,"SSLv23"); s->bev = bufferevent_openssl_socket_new(s->e->event_base, s->fd, s->ssl, BUFFEREVENT_SSL_ACCEPTING, BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + debug_ptr_add(s->bev); } else { s->bev = bufferevent_openssl_socket_new(s->e->event_base, s->fd, s->ssl, BUFFEREVENT_SSL_OPEN, BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + debug_ptr_add(s->bev); } bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev, eventcb_bev, s); diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index a2656e6b..f7ac8026 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -882,12 +882,7 @@ static void close_cli_session(struct cli_session* cs) cs->ts = NULL; } - if(cs->bev) { - bufferevent_flush(cs->bev,EV_READ|EV_WRITE,BEV_FLUSH); - bufferevent_disable(cs->bev,EV_READ|EV_WRITE); - bufferevent_free(cs->bev); - cs->bev=NULL; - } + BUFFEREVENT_FREE(cs->bev); if(cs->fd>=0) { close(cs->fd); @@ -1175,6 +1170,7 @@ static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd clisession->bev = bufferevent_socket_new(cliserver.event_base, fd, BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + debug_ptr_add(clisession->bev); bufferevent_setcb(clisession->bev, cli_socket_input_handler_bev, NULL, cli_eventcb_bev, clisession); bufferevent_setwatermark(clisession->bev, EV_READ|EV_WRITE, 0, BUFFEREVENT_HIGH_WATERMARK); diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 893def56..c60da2cd 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -80,7 +80,7 @@ static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr) { int ctxtype = (int)(((unsigned long)random())%root_tls_ctx_num); - SSL *ssl = SSL_new(root_tls_ctx[ctxtype]); + SSL *ssl = SSL_NEW(root_tls_ctx[ctxtype]); if(use_tcp) { SSL_set_fd(ssl, fd); @@ -590,8 +590,7 @@ static int clnet_allocate(int verbose, int close_socket = (int)(random()%2); if(ssl && !close_socket) { SSL_shutdown(ssl); - SSL_free(ssl); - ssl = NULL; + SSL_FREE(ssl); fd = -1; } else if(fd>=0) { close(fd); @@ -615,7 +614,7 @@ static int clnet_allocate(int verbose, if(ssl) { SSL_shutdown(ssl); - SSL_free(ssl); + SSL_FREE(ssl); } else if(fd>=0) { close(fd); } diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 0bc2ba9f..d7aa0db5 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -140,8 +140,7 @@ static void uc_delete_session_elem_data(app_ur_session* cdi) { SSL_shutdown(cdi->pinfo.tcp_conn[i]->tcp_data_ssl); } if(cdi->pinfo.tcp_conn[i]->tcp_data_ssl) { - SSL_free(cdi->pinfo.tcp_conn[i]->tcp_data_ssl); - cdi->pinfo.tcp_conn[i]->tcp_data_ssl = NULL; + SSL_FREE(cdi->pinfo.tcp_conn[i]->tcp_data_ssl); } if(cdi->pinfo.tcp_conn[i]->tcp_data_fd>=0) { socket_closesocket(cdi->pinfo.tcp_conn[i]->tcp_data_fd); @@ -165,8 +164,7 @@ static void uc_delete_session_elem_data(app_ur_session* cdi) { } } if(cdi->pinfo.ssl) { - SSL_free(cdi->pinfo.ssl); - cdi->pinfo.ssl = NULL; + SSL_FREE(cdi->pinfo.ssl); } if(cdi->pinfo.fd>=0) { socket_closesocket(cdi->pinfo.fd); @@ -865,8 +863,7 @@ static int start_client(const char *remote_address, int port, clnet_info_rtcp, &chnum_rtcp); if(clnet_info_probe.ssl) { - SSL_free(clnet_info_probe.ssl); - clnet_info_probe.ssl = NULL; + SSL_FREE(clnet_info_probe.ssl); clnet_info_probe.fd = -1; } else if(clnet_info_probe.fd != -1) { socket_closesocket(clnet_info_probe.fd); @@ -971,8 +968,7 @@ static int start_c2c(const char *remote_address, int port, clnet_info2_rtcp, &chnum2_rtcp); if(clnet_info_probe.ssl) { - SSL_free(clnet_info_probe.ssl); - clnet_info_probe.ssl = NULL; + SSL_FREE(clnet_info_probe.ssl); clnet_info_probe.fd = -1; } else if(clnet_info_probe.fd != -1) { socket_closesocket(clnet_info_probe.fd); diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 3c4f9199..9d357a35 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -120,13 +120,17 @@ static inline u64bits _ioa_ntoh64(u64bits v) #define TURN_LOG_FUNC(level, ...) printf (__VA_ARGS__) void tm_print_func(void); - void *turn_malloc_func(size_t sz, const char* file, int line); - void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* file, int line); - void turn_free_func(void *ptr, size_t sz, const char* file, int line); + void *turn_malloc_func(size_t sz, const char* function, int line); + void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* function, int line); + void turn_free_func(void *ptr, size_t sz, const char* function, int line); void turn_free_simple(void *ptr); - void *turn_calloc_func(size_t number, size_t size, const char* file, int line); - char *turn_strdup_func(const char* s, const char* file, int line); + void *turn_calloc_func(size_t number, size_t size, const char* function, int line); + char *turn_strdup_func(const char* s, const char* function, int line); + void* debug_ptr_add_func(void *ptr, const char* function, int line); + void debug_ptr_del_func(void *ptr, const char* function, int line); +#define debug_ptr_add(ptr) debug_ptr_add_func((ptr),__FUNCTION__,__LINE__) +#define debug_ptr_del(ptr) debug_ptr_del_func((ptr),__FUNCTION__,__LINE__) #define tm_print() tm_print_func() #define turn_malloc(sz) turn_malloc_func((size_t)(sz),__FUNCTION__,__LINE__) #define turn_free(ptr,sz) turn_free_func((ptr),(size_t)(sz),__FUNCTION__,__LINE__) @@ -136,6 +140,8 @@ static inline u64bits _ioa_ntoh64(u64bits v) #else +#define debug_ptr_add(ptr) (ptr) +#define debug_ptr_del(ptr) #define tm_print() #define turn_malloc(sz) malloc((size_t)(sz)) #define turn_free(ptr,sz) free((ptr)) @@ -146,6 +152,11 @@ static inline u64bits _ioa_ntoh64(u64bits v) #endif +#define SSL_NEW(ctx) ((SSL*)debug_ptr_add(SSL_new(ctx))) +#define SSL_FREE(ssl) do { debug_ptr_del(ssl); SSL_free(ssl); ssl = NULL; } while(0) + +#define BUFFEREVENT_FREE(be) do { if(be) { debug_ptr_del(be); bufferevent_flush(be,EV_READ|EV_WRITE,BEV_FLUSH); bufferevent_disable(be,EV_READ|EV_WRITE); bufferevent_free(be); be = NULL;} } while(0) + #define turn_time() ((turn_time_t)time(NULL)) typedef int vint; From 1d22cb19864264bac9e5c94a58ee88b91aa7a5c4 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 15 Oct 2014 06:52:57 +0000 Subject: [PATCH 266/805] debug fixes --- src/ns_turn_defs.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 9d357a35..514359f6 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -138,9 +138,11 @@ static inline u64bits _ioa_ntoh64(u64bits v) #define turn_calloc(number, sz) turn_calloc_func((number),(size_t)(sz),__FUNCTION__,__LINE__) #define turn_strdup(s) turn_strdup_func((s),__FUNCTION__,__LINE__) +#define SSL_NEW(ctx) ((SSL*)debug_ptr_add(SSL_new(ctx))) + #else -#define debug_ptr_add(ptr) (ptr) +#define debug_ptr_add(ptr) #define debug_ptr_del(ptr) #define tm_print() #define turn_malloc(sz) malloc((size_t)(sz)) @@ -150,11 +152,11 @@ static inline u64bits _ioa_ntoh64(u64bits v) #define turn_strdup(s) strdup((s)) #define turn_free_simple free +#define SSL_NEW(ctx) SSL_new(ctx) + #endif -#define SSL_NEW(ctx) ((SSL*)debug_ptr_add(SSL_new(ctx))) #define SSL_FREE(ssl) do { debug_ptr_del(ssl); SSL_free(ssl); ssl = NULL; } while(0) - #define BUFFEREVENT_FREE(be) do { if(be) { debug_ptr_del(be); bufferevent_flush(be,EV_READ|EV_WRITE,BEV_FLUSH); bufferevent_disable(be,EV_READ|EV_WRITE); bufferevent_free(be); be = NULL;} } while(0) #define turn_time() ((turn_time_t)time(NULL)) From 7be2848ea8479436cf8c0b07ea1b03417196d563 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 15 Oct 2014 07:38:23 +0000 Subject: [PATCH 267/805] linux udp socket optimization --- src/server/ns_turn_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 0904d7ca..99cbac28 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1616,7 +1616,7 @@ static int handle_turn_refresh(turn_turnserver *server, //Transfer socket: - ioa_socket_handle s = detach_ioa_socket(ss->client_socket,1); + ioa_socket_handle s = detach_ioa_socket(ss->client_socket,0); ss->to_be_closed = 1; From 4a9cbf732e71dc9374e325f99fefce9b1512f5f6 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 16 Oct 2014 08:15:34 +0000 Subject: [PATCH 268/805] rtcp ports fixed --- ChangeLog | 3 ++- rpm/turnserver.spec | 2 +- src/apps/relay/ns_ioalib_engine_impl.c | 21 ++++++++++++++++----- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4c680ff6..021e4b97 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,8 @@ -10/14/2014 Oleg Moskalenko +10/16/2014 Oleg Moskalenko Version 4.2.1.4 'Monza': - Code cleaning. - TCP/TLS tests extended. + - relay RTCP sockets ports allocation fixed. 10/05/2014 Oleg Moskalenko Version 4.2.1.2 'Monza': diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index bdff0f76..2e44efe4 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -294,7 +294,7 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Mon Oct 13 2014 Oleg Moskalenko +* Thu Oct 16 2014 Oleg Moskalenko - Sync to 4.2.1.4 * Sun Oct 05 2014 Oleg Moskalenko - Sync to 4.2.1.2 diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 66f12804..c8ac1fc3 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1166,12 +1166,17 @@ int create_relay_ioa_sockets(ioa_engine_handle e, (transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) ? TCP_SOCKET : UDP_SOCKET, RELAY_SOCKET); if (*rtp_s == NULL) { - if (rtcp_s) + int rtcp_bound = 0; + if (rtcp_s && *rtcp_s) { + rtcp_bound = (*rtcp_s)->bound; IOA_CLOSE_SOCKET(*rtcp_s); + } addr_set_port(&local_addr, port); turnipports_release(tp, transport, &local_addr); - if (rtcp_port >= 0) + if (rtcp_port >= 0 && !rtcp_bound) { + addr_set_port(&rtcp_local_addr, rtcp_port); turnipports_release(tp, transport, &rtcp_local_addr); + } perror("socket"); return -1; } @@ -1184,12 +1189,17 @@ int create_relay_ioa_sockets(ioa_engine_handle e, break; } else { IOA_CLOSE_SOCKET(*rtp_s); - if (rtcp_s) + int rtcp_bound = 0; + if (rtcp_s && *rtcp_s) { + rtcp_bound = (*rtcp_s)->bound; IOA_CLOSE_SOCKET(*rtcp_s); + } addr_set_port(&local_addr, port); turnipports_release(tp, transport, &local_addr); - if (rtcp_port >= 0) + if (rtcp_port >= 0 && !rtcp_bound) { + addr_set_port(&rtcp_local_addr, rtcp_port); turnipports_release(tp, transport, &rtcp_local_addr); + } rtcp_port = -1; } } @@ -1638,7 +1648,8 @@ void close_ioa_socket(ioa_socket_handle s) ioa_network_buffer_delete(s->e, s->defer_nbh); - if(s->bound && s->e && s->e->tp) { + if(s->bound && s->e && s->e->tp && + ((s->sat == RELAY_SOCKET)||(s->sat == RELAY_RTCP_SOCKET))) { turnipports_release(s->e->tp, ((s->st == TCP_SOCKET) ? STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE : STUN_ATTRIBUTE_TRANSPORT_UDP_VALUE), &(s->local_addr)); From 7f938dcede42f2c04bdc9c116bea0d642e7f654b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 17 Oct 2014 05:53:15 +0000 Subject: [PATCH 269/805] minor cleaning --- src/apps/relay/ns_ioalib_engine_impl.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index c8ac1fc3..02ba88b0 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1449,8 +1449,6 @@ void add_socket_to_map(ioa_socket_handle s, ur_addr_map *amap) &(s->remote_addr), (ur_addr_map_value_type)s); s->sockets_container = amap; - - //printf("%s: 111.111: amap=0x%lx: ne=%lu, sz=%lu\n",__FUNCTION__,(unsigned long)amap,(unsigned long)ur_addr_map_num_elements(amap),(unsigned long)ur_addr_map_size(amap)); } } @@ -1458,14 +1456,10 @@ void delete_socket_from_map(ioa_socket_handle s) { if(s && s->sockets_container) { - //ur_addr_map *amap = s->sockets_container; - ur_addr_map_del(s->sockets_container, &(s->remote_addr), NULL); s->sockets_container = NULL; - - //printf("%s: 111.222: amap=0x%lx: ne=%lu, sz=%lu\n",__FUNCTION__,(unsigned long)amap,(unsigned long)ur_addr_map_num_elements(amap),(unsigned long)ur_addr_map_size(amap)); } } From e570458b237dcfa3190a835b27090573259feb4e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 18 Oct 2014 20:53:41 +0000 Subject: [PATCH 270/805] TODO updated --- TODO | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/TODO b/TODO index ead7305b..05e9ab79 100644 --- a/TODO +++ b/TODO @@ -47,7 +47,8 @@ ================================================================== - +1) Per-realm black/white lists. + ================================================================== ### VI. STANDARDS SUPPORT ### From 5ab2e049295c03fb7385541062918e02f82d876f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 20 Oct 2014 06:16:37 +0000 Subject: [PATCH 271/805] TODO updated --- TODO | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TODO b/TODO index 05e9ab79..ca641e02 100644 --- a/TODO +++ b/TODO @@ -11,6 +11,8 @@ Cygwin is supported. A "real" MS-Windows port would involve a usable GUI. +3) Debian is complaining about libdl, libnsl and libevent-extra (unused dependencies). Investigate. + ================================================================== ### II. DOCS ### From f6dd86264945858b8990dca25e36503fe354fc14 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 20 Oct 2014 06:23:58 +0000 Subject: [PATCH 272/805] TODO updated --- TODO | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TODO b/TODO index ca641e02..c494d9dd 100644 --- a/TODO +++ b/TODO @@ -13,6 +13,8 @@ 3) Debian is complaining about libdl, libnsl and libevent-extra (unused dependencies). Investigate. +4) Debian: update control to 3.9.6 + ================================================================== ### II. DOCS ### From 85c3d68aff3f2dc3a061e6f8912fbfdf31b754de Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 20 Oct 2014 07:09:35 +0000 Subject: [PATCH 273/805] list of libraries cleaned --- ChangeLog | 3 ++- configure | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 021e4b97..05c32ecf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,7 +3,8 @@ Version 4.2.1.4 'Monza': - Code cleaning. - TCP/TLS tests extended. - relay RTCP sockets ports allocation fixed. - + - list of libraries cleaned. + 10/05/2014 Oleg Moskalenko Version 4.2.1.2 'Monza': - oAuth security experimental implementation; diff --git a/configure b/configure index d7e2ee77..58047ced 100755 --- a/configure +++ b/configure @@ -823,8 +823,6 @@ fi ########################### testlib socket -testlib nsl -testlib dl testlib rt testlib wldap32 ER=$? @@ -952,13 +950,23 @@ fi testlib event_core ER=$? if ! [ ${ER} -eq 0 ] ; then - testlib event_extra ${ECHO_CMD} "Libevent2 runtime found." + testlib event_extra + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "Libevent2 runtime 'extra' found." + else + ${ECHO_CMD} "ERROR: Libevent2 'extra' runtime library is not installed properly in required location." + ${ECHO_CMD} "See the INSTALL file." + ${ECHO_CMD} "Abort." + cleanup + exit + fi else testlib event ER=$? if ! [ ${ER} -eq 0 ] ; then - ${ECHO_CMD} "Libevent2 runtime found." + ${ECHO_CMD} "Libevent2 runtime found (old style)." else ${ECHO_CMD} "ERROR: Libevent2 runtime libraries are not installed properly in required location." ${ECHO_CMD} "See the INSTALL file." From 31ebc0cc185b62f00bd2c4f5b8b06dcb0ab37353 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 20 Oct 2014 07:19:26 +0000 Subject: [PATCH 274/805] TODO updated --- TODO | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/TODO b/TODO index c494d9dd..c5d31573 100644 --- a/TODO +++ b/TODO @@ -11,9 +11,7 @@ Cygwin is supported. A "real" MS-Windows port would involve a usable GUI. -3) Debian is complaining about libdl, libnsl and libevent-extra (unused dependencies). Investigate. - -4) Debian: update control to 3.9.6 +3) Debian: update control to 3.9.6 ================================================================== From 394ce4a38e4a01726527f2d8be7bb1382ee55bd5 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 20 Oct 2014 07:42:36 +0000 Subject: [PATCH 275/805] lib adjustment for Solaris --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 58047ced..bc315886 100755 --- a/configure +++ b/configure @@ -585,6 +585,7 @@ SYSTEM=`uname` if [ "${SYSTEM}" = "SunOS" ] ; then # Solaris ? is this you ?! OSCFLAGS="${OSCFLAGS} -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 -DTURN_NO_GETDOMAINNAME" + OSLIBS="${OSLIBS} -lnsl" fi ######################### From d555a417c50923158f95a1d61516e172eaf58283 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 20 Oct 2014 17:46:05 +0000 Subject: [PATCH 276/805] minor fix --- src/apps/relay/ns_ioalib_engine_impl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 02ba88b0..b6801255 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1828,8 +1828,8 @@ int get_ioa_socket_address_family(ioa_socket_handle s) { return AF_INET; } else if(s->done) { return s->family; - } else if(s->parent_s) { - return s->parent_s->family; + } else if(s->parent_s && (s != s->parent_s)) { + return get_ioa_socket_address_family(s->parent_s); } else { return s->family; } From 6a7349d57de29092e131e9b8494f7145aa378b1d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 21 Oct 2014 06:20:49 +0000 Subject: [PATCH 277/805] working on segfaults --- src/server/ns_turn_server.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 99cbac28..502c6871 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4072,6 +4072,11 @@ int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, dec_quota(ss); dec_bps(ss); + allocation* alloc = get_allocation_ss(ss); + if (!is_allocation_valid(alloc)) { + force = 1; + } + if(!force && ss->is_mobile) { if (ss->client_socket && server->verbose) { @@ -4246,7 +4251,7 @@ static int create_relay_connection(turn_turnserver* server, int *err_code, const u08bits **reason, accept_cb acb) { - if (server && ss && ss->client_socket) { + if (server && ss && ss->client_socket && !ioa_socket_tobeclosed(ss->client_socket)) { allocation* a = get_allocation_ss(ss); relay_endpoint_session* newelem = NULL; @@ -4256,8 +4261,10 @@ static int create_relay_connection(turn_turnserver* server, ioa_socket_handle s = NULL; - if (get_ioa_socket_from_reservation(server->e, in_reservation_token, - &s) < 0) { + if ((get_ioa_socket_from_reservation(server->e, in_reservation_token,&s) < 0)|| + !s || + ioa_socket_tobeclosed(s)) { + IOA_CLOSE_SOCKET(s); *err_code = 508; *reason = (const u08bits *)"Cannot find reserved socket"; From 25a5b4267c7abc5affb7eaa775eaa8547c85d9f9 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 21 Oct 2014 06:40:36 +0000 Subject: [PATCH 278/805] working on segfaults --- src/apps/relay/ns_ioalib_engine_impl.c | 1 - src/server/ns_turn_maps_rtcp.c | 5 ++--- src/server/ns_turn_maps_rtcp.h | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index b6801255..d0ba4839 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -686,7 +686,6 @@ int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_ if (e && in_reservation_token && s) { *s = rtcp_map_get(e->map_rtcp, in_reservation_token); if (*s) { - rtcp_map_del_savefd(e->map_rtcp, in_reservation_token); return 0; } } diff --git a/src/server/ns_turn_maps_rtcp.c b/src/server/ns_turn_maps_rtcp.c index 704d3b18..ae2fe624 100644 --- a/src/server/ns_turn_maps_rtcp.c +++ b/src/server/ns_turn_maps_rtcp.c @@ -166,13 +166,14 @@ int rtcp_map_put(rtcp_map* map, rtcp_token_type token, ioa_socket_handle s) { * >=0 - success * <0 - not found */ -ioa_socket_handle rtcp_map_get(const rtcp_map* map, rtcp_token_type token) { +ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token) { if(!rtcp_map_valid(map)) return NULL; else { ur_map_value_type value; TURN_MUTEX_LOCK(&map->mutex); int ret = ur_map_get(map->map,token,&value); //TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: 111.111: ret=%d, value=%llu, token=%llu\n",__FUNCTION__,ret,(unsigned long)value,token); + rtcp_map_del_savefd(map, token); TURN_MUTEX_UNLOCK(&map->mutex); if(!ret) return NULL; rtcp_alloc_type* rval=(rtcp_alloc_type*)value; @@ -224,9 +225,7 @@ int rtcp_map_del(rtcp_map* map, rtcp_token_type token) { int rtcp_map_del_savefd(rtcp_map* map, rtcp_token_type token) { if(!rtcp_map_valid(map)) return 0; else { - TURN_MUTEX_LOCK(&map->mutex); int ret = ur_map_del(map->map,token,rtcp_alloc_free_savefd); - TURN_MUTEX_UNLOCK(&map->mutex); return ret; } } diff --git a/src/server/ns_turn_maps_rtcp.h b/src/server/ns_turn_maps_rtcp.h index 19ce3cb0..44222ba3 100644 --- a/src/server/ns_turn_maps_rtcp.h +++ b/src/server/ns_turn_maps_rtcp.h @@ -61,7 +61,7 @@ int rtcp_map_put(rtcp_map* map, rtcp_token_type key, ioa_socket_handle s); * >=0 - success * <0 - not found */ -ioa_socket_handle rtcp_map_get(const rtcp_map* map, rtcp_token_type token); +ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token); /** * @ret: From 3955c8a0202a047b50e2e250d41731c414f9442b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 21 Oct 2014 06:46:35 +0000 Subject: [PATCH 279/805] working on segfaults --- src/server/ns_turn_maps_rtcp.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/server/ns_turn_maps_rtcp.c b/src/server/ns_turn_maps_rtcp.c index ae2fe624..95266d41 100644 --- a/src/server/ns_turn_maps_rtcp.c +++ b/src/server/ns_turn_maps_rtcp.c @@ -167,20 +167,21 @@ int rtcp_map_put(rtcp_map* map, rtcp_token_type token, ioa_socket_handle s) { * <0 - not found */ ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token) { - if(!rtcp_map_valid(map)) return NULL; - else { - ur_map_value_type value; - TURN_MUTEX_LOCK(&map->mutex); - int ret = ur_map_get(map->map,token,&value); - //TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: 111.111: ret=%d, value=%llu, token=%llu\n",__FUNCTION__,ret,(unsigned long)value,token); - rtcp_map_del_savefd(map, token); - TURN_MUTEX_UNLOCK(&map->mutex); - if(!ret) return NULL; - rtcp_alloc_type* rval=(rtcp_alloc_type*)value; - if(!rval) return NULL; - //TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: 111.222: ret=%d, token=%llu\n",__FUNCTION__,ret,token); - return rval->s; - } + ioa_socket_handle s = NULL; + if (rtcp_map_valid(map)) { + ur_map_value_type value; + TURN_MUTEX_LOCK(&map->mutex); + int ret = ur_map_get(map->map, token, &value); + if (ret) { + rtcp_alloc_type* rval = (rtcp_alloc_type*) value; + if (rval) { + s = rval->s; + } + } + rtcp_map_del_savefd(map, token); + TURN_MUTEX_UNLOCK(&map->mutex); + } + return s; } static void rtcp_alloc_free(ur_map_value_type value) From 55c8e19424b3e7cc6be8e8f79e19b25d6dbfb339 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 22 Oct 2014 05:34:50 +0000 Subject: [PATCH 280/805] working on rtcp sockets --- src/apps/relay/ns_ioalib_engine_impl.c | 17 ++-- src/server/ns_turn_ioalib.h | 2 +- src/server/ns_turn_maps_rtcp.c | 103 +++++++++++++------------ src/server/ns_turn_maps_rtcp.h | 10 +-- src/server/ns_turn_server.c | 14 ++-- 5 files changed, 71 insertions(+), 75 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index d0ba4839..c64e361a 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -681,10 +681,10 @@ static int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read) return 1; } -int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_token, ioa_socket_handle *s) +int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_token, ioa_socket_handle *s, u08bits *realm) { if (e && in_reservation_token && s) { - *s = rtcp_map_get(e->map_rtcp, in_reservation_token); + *s = rtcp_map_get(e->map_rtcp, in_reservation_token, realm); if (*s) { return 0; } @@ -1823,12 +1823,15 @@ void set_ioa_socket_sub_session(ioa_socket_handle s, tcp_connection *tc) } int get_ioa_socket_address_family(ioa_socket_handle s) { - if(!s) { + + int first_time = 1; + beg: + if (!(s && (s->magic == SOCKET_MAGIC) && !(s->done))) { return AF_INET; - } else if(s->done) { - return s->family; - } else if(s->parent_s && (s != s->parent_s)) { - return get_ioa_socket_address_family(s->parent_s); + } else if(first_time && s->parent_s && (s != s->parent_s)) { + first_time = 0; + s = s->parent_s; + goto beg; } else { return s->family; } diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 3a29e8dd..29b9cb37 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -215,7 +215,7 @@ int create_relay_ioa_sockets(ioa_engine_handle e, ioa_socket_handle client_s, ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, ioa_addr *peer_addr, connect_cb cb, void *arg); -int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_token, ioa_socket_handle *s); +int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_token, ioa_socket_handle *s, u08bits *realm); int get_ioa_socket_address_family(ioa_socket_handle s); SOCKET_TYPE get_ioa_socket_type(ioa_socket_handle s); diff --git a/src/server/ns_turn_maps_rtcp.c b/src/server/ns_turn_maps_rtcp.c index 95266d41..34d7d75e 100644 --- a/src/server/ns_turn_maps_rtcp.c +++ b/src/server/ns_turn_maps_rtcp.c @@ -85,6 +85,54 @@ static int timeout_check(ur_map_key_type key, return 0; } +static void rtcp_alloc_free(ur_map_value_type value) +{ + rtcp_alloc_type *at = (rtcp_alloc_type *)value; + if (at) { + IOA_CLOSE_SOCKET(at->s); + turn_free(at,sizeof(rtcp_alloc_type)); + } +} + +static void rtcp_alloc_free_savefd(ur_map_value_type value) +{ + rtcp_alloc_type *at = (rtcp_alloc_type *) value; + if (at) { + turn_free(at,sizeof(rtcp_alloc_type)); + } +} + +static int foreachcb_free(ur_map_key_type key, ur_map_value_type value) { + UNUSED_ARG(key); + if(value) { + rtcp_alloc_free(value); + } + return 0; +} + +/** + * @ret: + * 1 - success + * 0 - not found + */ +static int rtcp_map_del(rtcp_map* map, rtcp_token_type token) { + if(!rtcp_map_valid(map)) return 0; + else { + TURN_MUTEX_LOCK(&map->mutex); + int ret = ur_map_del(map->map,token,rtcp_alloc_free); + TURN_MUTEX_UNLOCK(&map->mutex); + return ret; + } +} + +static int rtcp_map_del_savefd(rtcp_map* map, rtcp_token_type token) { + if(!rtcp_map_valid(map)) return 0; + else { + int ret = ur_map_del(map->map,token,rtcp_alloc_free_savefd); + return ret; + } +} + static void rtcp_map_timeout_handler(ioa_engine_handle e, void* arg) { UNUSED_ARG(e); @@ -166,7 +214,7 @@ int rtcp_map_put(rtcp_map* map, rtcp_token_type token, ioa_socket_handle s) { * >=0 - success * <0 - not found */ -ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token) { +ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token, u08bits *realm) { ioa_socket_handle s = NULL; if (rtcp_map_valid(map)) { ur_map_value_type value; @@ -176,61 +224,18 @@ ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token) { rtcp_alloc_type* rval = (rtcp_alloc_type*) value; if (rval) { s = rval->s; + if(!check_realm_hash(s,realm)) { + s = NULL; + } else { + rtcp_map_del_savefd(map, token); + } } } - rtcp_map_del_savefd(map, token); TURN_MUTEX_UNLOCK(&map->mutex); } return s; } -static void rtcp_alloc_free(ur_map_value_type value) -{ - rtcp_alloc_type *at = (rtcp_alloc_type *)value; - if (at) { - IOA_CLOSE_SOCKET(at->s); - turn_free(at,sizeof(rtcp_alloc_type)); - } -} - -static void rtcp_alloc_free_savefd(ur_map_value_type value) -{ - rtcp_alloc_type *at = (rtcp_alloc_type *) value; - if (at) { - turn_free(at,sizeof(rtcp_alloc_type)); - } -} - -static int foreachcb_free(ur_map_key_type key, ur_map_value_type value) { - UNUSED_ARG(key); - if(value) { - rtcp_alloc_free(value); - } - return 0; -} - -/** - * @ret: - * 1 - success - * 0 - not found - */ -int rtcp_map_del(rtcp_map* map, rtcp_token_type token) { - if(!rtcp_map_valid(map)) return 0; - else { - TURN_MUTEX_LOCK(&map->mutex); - int ret = ur_map_del(map->map,token,rtcp_alloc_free); - TURN_MUTEX_UNLOCK(&map->mutex); - return ret; - } -} -int rtcp_map_del_savefd(rtcp_map* map, rtcp_token_type token) { - if(!rtcp_map_valid(map)) return 0; - else { - int ret = ur_map_del(map->map,token,rtcp_alloc_free_savefd); - return ret; - } -} - void rtcp_map_free(rtcp_map** map) { if(map && rtcp_map_valid(*map)) { TURN_MUTEX_LOCK(&((*map)->mutex)); diff --git a/src/server/ns_turn_maps_rtcp.h b/src/server/ns_turn_maps_rtcp.h index 44222ba3..e8c2a0f9 100644 --- a/src/server/ns_turn_maps_rtcp.h +++ b/src/server/ns_turn_maps_rtcp.h @@ -61,15 +61,7 @@ int rtcp_map_put(rtcp_map* map, rtcp_token_type key, ioa_socket_handle s); * >=0 - success * <0 - not found */ -ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token); - -/** - * @ret: - * 1 - success - * 0 - not found - */ -int rtcp_map_del(rtcp_map* map, rtcp_token_type token); -int rtcp_map_del_savefd(rtcp_map* map, rtcp_token_type token); +ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token, u08bits *realm); /** * @ret: diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 502c6871..604efba6 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4261,7 +4261,7 @@ static int create_relay_connection(turn_turnserver* server, ioa_socket_handle s = NULL; - if ((get_ioa_socket_from_reservation(server->e, in_reservation_token,&s) < 0)|| + if ((get_ioa_socket_from_reservation(server->e, in_reservation_token,&s,(u08bits*)ss->realm_options.name) < 0)|| !s || ioa_socket_tobeclosed(s)) { @@ -4275,16 +4275,12 @@ static int create_relay_connection(turn_turnserver* server, newelem = get_relay_session_ss(ss,family); - IOA_CLOSE_SOCKET(newelem->s); + if(newelem->s != s) { - ns_bzero(newelem, sizeof(relay_endpoint_session)); - newelem->s = s; - - if(!check_realm_hash(newelem->s,(u08bits*)ss->realm_options.name)) { IOA_CLOSE_SOCKET(newelem->s); - *err_code = 508; - *reason = (const u08bits *)"Cannot find a valid reserved socket for this realm"; - return -1; + + ns_bzero(newelem, sizeof(relay_endpoint_session)); + newelem->s = s; } addr_debug_print(server->verbose, get_local_addr_from_ioa_socket(newelem->s), "Local relay addr (RTCP)"); From 0c11f9290b6fcc50dc9851252b5740aa4a9f41e8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 22 Oct 2014 05:52:38 +0000 Subject: [PATCH 281/805] cosmetics --- src/apps/relay/ns_ioalib_engine_impl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index c64e361a..b503f9b7 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1856,7 +1856,7 @@ void set_ioa_socket_app_type(ioa_socket_handle s, SOCKET_APP_TYPE sat) { if(s) s->sat = sat; } - + ioa_addr* get_local_addr_from_ioa_socket(ioa_socket_handle s) { if (s && (s->magic == SOCKET_MAGIC) && !(s->done)) { @@ -3677,7 +3677,7 @@ void* allocate_super_memory_region_func(super_memory_t *r, size_t size, const ch if(!region) { r->sm_chunk += 1; - r->super_memory = (char**)turn_realloc(r->super_memory,0,(r->sm_chunk+1) * sizeof(char*)); + r->super_memory = (char**)turn_realloc(r->super_memory,0, (r->sm_chunk+1) * sizeof(char*)); r->super_memory[r->sm_chunk] = (char*)turn_malloc(TURN_SM_SIZE); ns_bzero(r->super_memory[r->sm_chunk],TURN_SM_SIZE); r->sm_allocated = (size_t*)turn_realloc(r->sm_allocated,0,(r->sm_chunk+1) * sizeof(size_t*)); From 6889e5dc0fe6ed160aee2b798717a50b8aa0afc0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 24 Oct 2014 06:05:04 +0000 Subject: [PATCH 282/805] TCP fixes --- ChangeLog | 1 + src/apps/relay/netengine.c | 17 ++++------------- src/apps/relay/ns_ioalib_engine_impl.c | 12 ++++++------ src/apps/relay/turncli.c | 7 ++----- 4 files changed, 13 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 05c32ecf..526c68ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ Version 4.2.1.4 'Monza': - TCP/TLS tests extended. - relay RTCP sockets ports allocation fixed. - list of libraries cleaned. + - TCP bufferevent concurrency fixed. 10/05/2014 Oleg Moskalenko Version 4.2.1.2 'Monza': diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index a63bc3c7..4e057f54 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1005,11 +1005,8 @@ static void setup_listener(void) { struct bufferevent *pair[2]; - int opts = BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS; - opts |= BEV_OPT_THREADSAFE; - - bufferevent_pair_new(turn_params.listener.event_base, opts, pair); + bufferevent_pair_new(turn_params.listener.event_base, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE, pair); turn_params.listener.in_buf = pair[0]; turn_params.listener.out_buf = pair[1]; bufferevent_setcb(turn_params.listener.in_buf, listener_receive_message, NULL, NULL, &turn_params.listener); @@ -1548,7 +1545,6 @@ void run_listener_server(struct listener_server *ls) static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int to_set_rfc5780) { struct bufferevent *pair[2]; - int opts = BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS; if(e) { rs->event_base = e->event_base; @@ -1573,15 +1569,13 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int ioa_engine_set_rtcp_map(rs->ioa_eng, turn_params.listener.rtcpmap); } - opts |= BEV_OPT_THREADSAFE; - - bufferevent_pair_new(rs->event_base, opts, pair); + bufferevent_pair_new(rs->event_base, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE, pair); rs->in_buf = pair[0]; rs->out_buf = pair[1]; bufferevent_setcb(rs->in_buf, relay_receive_message, NULL, NULL, rs); bufferevent_enable(rs->in_buf, EV_READ); - bufferevent_pair_new(rs->event_base, opts, pair); + bufferevent_pair_new(rs->event_base, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE, pair); rs->auth_in_buf = pair[0]; rs->auth_out_buf = pair[1]; bufferevent_setcb(rs->auth_in_buf, relay_receive_auth_message, NULL, NULL, rs); @@ -1683,11 +1677,8 @@ static void* run_auth_server_thread(void *arg) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (auth thread): %s\n",event_base_get_method(turn_params.authserver.event_base)); struct bufferevent *pair[2]; - int opts = BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS; - opts |= BEV_OPT_THREADSAFE; - - bufferevent_pair_new(turn_params.authserver.event_base, opts, pair); + bufferevent_pair_new(turn_params.authserver.event_base, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE, pair); turn_params.authserver.in_buf = pair[0]; turn_params.authserver.out_buf = pair[1]; bufferevent_setcb(turn_params.authserver.in_buf, auth_server_receive_message, NULL, NULL, &turn_params.authserver); diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index b503f9b7..41d2274b 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1369,7 +1369,7 @@ ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, io ret->conn_bev = bufferevent_socket_new(ret->e->event_base, ret->fd, - BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE); debug_ptr_add(ret->conn_bev); bufferevent_setcb(ret->conn_bev, NULL, NULL, connect_eventcb, ret); @@ -2394,7 +2394,7 @@ static int socket_input_worker(ioa_socket_handle s) s->fd, s->ssl, BUFFEREVENT_SSL_ACCEPTING, - BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE); debug_ptr_add(s->bev); bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev, eventcb_bev, s); @@ -2410,7 +2410,7 @@ static int socket_input_worker(ioa_socket_handle s) } s->bev = bufferevent_socket_new(s->e->event_base, s->fd, - BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE); debug_ptr_add(s->bev); bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev, eventcb_bev, s); @@ -3235,7 +3235,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in } else { s->bev = bufferevent_socket_new(s->e->event_base, s->fd, - BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE); debug_ptr_add(s->bev); bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev, eventcb_bev, s); @@ -3260,14 +3260,14 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in s->fd, s->ssl, BUFFEREVENT_SSL_ACCEPTING, - BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE); debug_ptr_add(s->bev); } else { s->bev = bufferevent_openssl_socket_new(s->e->event_base, s->fd, s->ssl, BUFFEREVENT_SSL_OPEN, - BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE); debug_ptr_add(s->bev); } bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev, diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index f7ac8026..6012279a 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -1169,7 +1169,7 @@ static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd clisession->bev = bufferevent_socket_new(cliserver.event_base, fd, - BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS); + BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE); debug_ptr_add(clisession->bev); bufferevent_setcb(clisession->bev, cli_socket_input_handler_bev, NULL, cli_eventcb_bev, clisession); @@ -1201,11 +1201,8 @@ void setup_cli_thread(void) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (cli thread): %s\n",event_base_get_method(cliserver.event_base)); struct bufferevent *pair[2]; - int opts = BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS; - opts |= BEV_OPT_THREADSAFE; - - bufferevent_pair_new(cliserver.event_base, opts, pair); + bufferevent_pair_new(cliserver.event_base, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE, pair); cliserver.in_buf = pair[0]; cliserver.out_buf = pair[1]; bufferevent_setcb(cliserver.in_buf, cli_server_receive_message, NULL, NULL, &cliserver); From 016b2587b4fad245090311553b84f5e7843f21c3 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 24 Oct 2014 17:49:55 +0000 Subject: [PATCH 283/805] minor fix --- src/apps/relay/ns_ioalib_engine_impl.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 41d2274b..a8e85fec 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1726,10 +1726,7 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach) set_socket_ssl(ret,s->ssl); ret->fd = s->fd; - if(s->parent_s) - ret->family = s->parent_s->family; - else - ret->family = s->family; + ret->family = get_ioa_socket_address_family(s); ret->st = s->st; ret->sat = s->sat; From 4d700ef90a7ac433b939d17de9f42c77024e6bbc Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 24 Oct 2014 23:24:55 +0000 Subject: [PATCH 284/805] detached socket cleaning --- src/apps/relay/ns_ioalib_engine_impl.c | 47 +++++++++++--------------- src/apps/uclient/mainuclient.c | 1 + src/server/ns_turn_ioalib.h | 2 +- src/server/ns_turn_server.c | 6 ++-- 4 files changed, 24 insertions(+), 32 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index a8e85fec..b9d09079 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1661,7 +1661,7 @@ void close_ioa_socket(ioa_socket_handle s) } } -ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach) +ioa_socket_handle detach_ioa_socket(ioa_socket_handle s) { ioa_socket_handle ret = NULL; @@ -1693,13 +1693,29 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach) evutil_socket_t udp_fd = -1; - if(s->parent_s && full_detach) { + if(s->parent_s) { udp_fd = socket(s->local_addr.ss.sa_family, SOCK_DGRAM, 0); if (udp_fd < 0) { perror("socket"); TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"%s: Cannot allocate new socket\n",__FUNCTION__); return ret; } + if(sock_bind_to_device(udp_fd, (unsigned char*)(s->e->relay_ifname))<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind udp server socket to device %s\n",(char*)(s->e->relay_ifname)); + } + + if(addr_bind(udp_fd,&(s->local_addr),1)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind new detached udp server socket to local addr\n"); + close(udp_fd); + return ret; + } + + int connect_err=0; + if(addr_connect(udp_fd, &(s->remote_addr), &connect_err)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot connect new detached udp server socket to remote addr\n"); + close(udp_fd); + return ret; + } } detach_socket_net_data(s); @@ -1737,39 +1753,14 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach) addr_cpy(&(ret->remote_addr),&(s->remote_addr)); STRCPY(ret->orig_ctx_type, s->orig_ctx_type); - - ioa_socket_handle parent_s = s->parent_s; - ur_addr_map *sockets_container = s->sockets_container; delete_socket_from_map(s); delete_socket_from_parent(s); - if(udp_fd<0) { - - add_socket_to_parent(parent_s, ret); - add_socket_to_map(ret,sockets_container); - - } else { + if(udp_fd>=0) { ret->fd = udp_fd; - if(sock_bind_to_device(udp_fd, (unsigned char*)(s->e->relay_ifname))<0) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind udp server socket to device %s\n",(char*)(s->e->relay_ifname)); - } - - if(addr_bind(udp_fd,&(s->local_addr),1)<0) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind new detached udp server socket to local addr\n"); - IOA_CLOSE_SOCKET(ret); - return ret; - } - - int connect_err=0; - if(addr_connect(udp_fd, &(s->remote_addr), &connect_err)<0) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot connect new detached udp server socket to remote addr\n"); - IOA_CLOSE_SOCKET(ret); - return ret; - } - set_socket_options(ret); } diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 646831dc..4c2c4a3e 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -365,6 +365,7 @@ int main(int argc, char **argv) case 'P': passive_tcp = 1; /* implies 'T': */ + /* no break */ case 'T': relay_transport = STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE; break; diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 29b9cb37..8fff04c3 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -235,7 +235,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, ioa_network_buffer_handle nbh, int ttl, int tos); void close_ioa_socket(ioa_socket_handle s); #define IOA_CLOSE_SOCKET(S) do { if(S) { close_ioa_socket(S); S = NULL; } } while(0) -ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach); +ioa_socket_handle detach_ioa_socket(ioa_socket_handle s); void detach_socket_net_data(ioa_socket_handle s); int set_df_on_ioa_socket(ioa_socket_handle s, int value); void set_do_not_use_df(ioa_socket_handle s); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 604efba6..b622b842 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1525,7 +1525,7 @@ static int handle_turn_refresh(turn_turnserver *server, if(tsid != server->id) { if(server->send_socket_to_relay) { - ioa_socket_handle new_s = detach_ioa_socket(ss->client_socket,1); + ioa_socket_handle new_s = detach_ioa_socket(ss->client_socket); if(new_s) { if(server->send_socket_to_relay(tsid, mid, tid, new_s, message_integrity, RMT_MOBILE_SOCKET, in_buffer, can_resume)<0) { @@ -1616,7 +1616,7 @@ static int handle_turn_refresh(turn_turnserver *server, //Transfer socket: - ioa_socket_handle s = detach_ioa_socket(ss->client_socket,0); + ioa_socket_handle s = detach_ioa_socket(ss->client_socket); ss->to_be_closed = 1; @@ -2310,7 +2310,7 @@ static int handle_turn_connection_bind(turn_turnserver *server, turnserver_id sid = (id & 0xFF000000)>>24; ioa_socket_handle s = ss->client_socket; if(s && !ioa_socket_tobeclosed(s)) { - ioa_socket_handle new_s = detach_ioa_socket(s,1); + ioa_socket_handle new_s = detach_ioa_socket(s); if(new_s) { if(server->send_socket_to_relay(sid, id, tid, new_s, message_integrity, RMT_CB_SOCKET, in_buffer, can_resume)<0) { *err_code = 400; From f65711493c2bf2f58becb27d32bc2baac10b9616 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 25 Oct 2014 07:05:06 +0000 Subject: [PATCH 285/805] deadlock fixed --- ChangeLog | 1 - src/apps/relay/netengine.c | 8 ++++---- src/apps/relay/ns_ioalib_engine_impl.c | 12 ++++++------ src/apps/relay/turncli.c | 4 ++-- src/ns_turn_defs.h | 4 ++++ 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 526c68ad..05c32ecf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,7 +4,6 @@ Version 4.2.1.4 'Monza': - TCP/TLS tests extended. - relay RTCP sockets ports allocation fixed. - list of libraries cleaned. - - TCP bufferevent concurrency fixed. 10/05/2014 Oleg Moskalenko Version 4.2.1.2 'Monza': diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 4e057f54..e8c44d9b 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1006,7 +1006,7 @@ static void setup_listener(void) { struct bufferevent *pair[2]; - bufferevent_pair_new(turn_params.listener.event_base, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE, pair); + bufferevent_pair_new(turn_params.listener.event_base, TURN_BUFFEREVENTS_OPTIONS, pair); turn_params.listener.in_buf = pair[0]; turn_params.listener.out_buf = pair[1]; bufferevent_setcb(turn_params.listener.in_buf, listener_receive_message, NULL, NULL, &turn_params.listener); @@ -1569,13 +1569,13 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int ioa_engine_set_rtcp_map(rs->ioa_eng, turn_params.listener.rtcpmap); } - bufferevent_pair_new(rs->event_base, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE, pair); + bufferevent_pair_new(rs->event_base, TURN_BUFFEREVENTS_OPTIONS, pair); rs->in_buf = pair[0]; rs->out_buf = pair[1]; bufferevent_setcb(rs->in_buf, relay_receive_message, NULL, NULL, rs); bufferevent_enable(rs->in_buf, EV_READ); - bufferevent_pair_new(rs->event_base, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE, pair); + bufferevent_pair_new(rs->event_base, TURN_BUFFEREVENTS_OPTIONS, pair); rs->auth_in_buf = pair[0]; rs->auth_out_buf = pair[1]; bufferevent_setcb(rs->auth_in_buf, relay_receive_auth_message, NULL, NULL, rs); @@ -1678,7 +1678,7 @@ static void* run_auth_server_thread(void *arg) struct bufferevent *pair[2]; - bufferevent_pair_new(turn_params.authserver.event_base, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE, pair); + bufferevent_pair_new(turn_params.authserver.event_base, TURN_BUFFEREVENTS_OPTIONS, pair); turn_params.authserver.in_buf = pair[0]; turn_params.authserver.out_buf = pair[1]; bufferevent_setcb(turn_params.authserver.in_buf, auth_server_receive_message, NULL, NULL, &turn_params.authserver); diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index b9d09079..e66df80f 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1369,7 +1369,7 @@ ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, io ret->conn_bev = bufferevent_socket_new(ret->e->event_base, ret->fd, - BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE); + TURN_BUFFEREVENTS_OPTIONS); debug_ptr_add(ret->conn_bev); bufferevent_setcb(ret->conn_bev, NULL, NULL, connect_eventcb, ret); @@ -2382,7 +2382,7 @@ static int socket_input_worker(ioa_socket_handle s) s->fd, s->ssl, BUFFEREVENT_SSL_ACCEPTING, - BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE); + TURN_BUFFEREVENTS_OPTIONS); debug_ptr_add(s->bev); bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev, eventcb_bev, s); @@ -2398,7 +2398,7 @@ static int socket_input_worker(ioa_socket_handle s) } s->bev = bufferevent_socket_new(s->e->event_base, s->fd, - BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE); + TURN_BUFFEREVENTS_OPTIONS); debug_ptr_add(s->bev); bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev, eventcb_bev, s); @@ -3223,7 +3223,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in } else { s->bev = bufferevent_socket_new(s->e->event_base, s->fd, - BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE); + TURN_BUFFEREVENTS_OPTIONS); debug_ptr_add(s->bev); bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev, eventcb_bev, s); @@ -3248,14 +3248,14 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in s->fd, s->ssl, BUFFEREVENT_SSL_ACCEPTING, - BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE); + TURN_BUFFEREVENTS_OPTIONS); debug_ptr_add(s->bev); } else { s->bev = bufferevent_openssl_socket_new(s->e->event_base, s->fd, s->ssl, BUFFEREVENT_SSL_OPEN, - BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE); + TURN_BUFFEREVENTS_OPTIONS); debug_ptr_add(s->bev); } bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev, diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index 6012279a..0e1f45fc 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -1169,7 +1169,7 @@ static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd clisession->bev = bufferevent_socket_new(cliserver.event_base, fd, - BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE); + TURN_BUFFEREVENTS_OPTIONS); debug_ptr_add(clisession->bev); bufferevent_setcb(clisession->bev, cli_socket_input_handler_bev, NULL, cli_eventcb_bev, clisession); @@ -1202,7 +1202,7 @@ void setup_cli_thread(void) struct bufferevent *pair[2]; - bufferevent_pair_new(cliserver.event_base, BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE, pair); + bufferevent_pair_new(cliserver.event_base, TURN_BUFFEREVENTS_OPTIONS, pair); cliserver.in_buf = pair[0]; cliserver.out_buf = pair[1]; bufferevent_setcb(cliserver.in_buf, cli_server_receive_message, NULL, NULL, &cliserver); diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 514359f6..9c493cac 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -200,6 +200,10 @@ typedef u32bits turn_time_t; }\ } } while(0) +//////////////// Bufferevents ///////////////////// + +#define TURN_BUFFEREVENTS_OPTIONS (BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE | BEV_OPT_UNLOCK_CALLBACKS) + //////////////// KERNEL-LEVEL CHANNEL HANDLERS ///////// #if !defined(TURN_CHANNEL_HANDLER_KERNEL) From 061f49560b6c5855f2a5d1700a4f871193bd1adc Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 26 Oct 2014 04:31:21 +0000 Subject: [PATCH 286/805] ssl renegotiation callback fixed --- ChangeLog | 2 +- src/apps/relay/ns_ioalib_engine_impl.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 05c32ecf..5ce8b345 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,9 @@ 10/16/2014 Oleg Moskalenko Version 4.2.1.4 'Monza': - - Code cleaning. - TCP/TLS tests extended. - relay RTCP sockets ports allocation fixed. - list of libraries cleaned. + - SSL renegotiation callback fixed. 10/05/2014 Oleg Moskalenko Version 4.2.1.2 'Monza': diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index e66df80f..aa825d2a 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1739,7 +1739,9 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s) ret->realm_hash = s->realm_hash; - set_socket_ssl(ret,s->ssl); + SSL* ssl = s->ssl; + set_socket_ssl(s,NULL); + set_socket_ssl(ret,ssl); ret->fd = s->fd; ret->family = get_ioa_socket_address_family(s); @@ -1770,7 +1772,6 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s) ret->current_tos = s->current_tos; ret->default_tos = s->default_tos; - set_socket_ssl(s,NULL); s->fd = -1; } From 5b300733dcbf3419008d6b3f28b2980b9493d12d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 26 Oct 2014 07:45:28 +0000 Subject: [PATCH 287/805] working on per-realm white/black lists --- src/apps/relay/dbdrivers/dbd_mongo.c | 2 +- src/apps/relay/dbdrivers/dbd_mysql.c | 2 +- src/apps/relay/dbdrivers/dbd_pgsql.c | 2 +- src/apps/relay/dbdrivers/dbd_redis.c | 2 +- src/apps/relay/mainrelay.c | 6 +++--- src/apps/relay/turncli.c | 13 +++++++++--- src/apps/relay/userdb.c | 30 ++++++++++------------------ src/apps/relay/userdb.h | 2 +- src/server/ns_turn_ioalib.h | 11 ++++++++-- src/server/ns_turn_server.c | 30 ++++++++++++++++++---------- 10 files changed, 57 insertions(+), 43 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index e8478b2b..37f66d17 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -1001,7 +1001,7 @@ static int mongo_get_ip_list(const char *kind, ip_range_list_t * list) { while(mongoc_cursor_next(cursor, &item)) { if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "ip_range") && BSON_ITER_HOLDS_UTF8(&iter)) { value = bson_iter_utf8(&iter, &length); - add_ip_list_range(value, list); + add_ip_list_range(value, NULL, list); } } mongoc_cursor_destroy(cursor); diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 6f3c07ee..7b4a4da0 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -913,7 +913,7 @@ static int mysql_get_ip_list(const char *kind, ip_range_list_t * list) { char kval[TURN_LONG_STRING_SIZE]; ns_bcopy(row[0],kval,sz); kval[sz]=0; - add_ip_list_range(kval,list); + add_ip_list_range(kval,NULL,list); } } } diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index 0a8b317f..ab3b5a9c 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -658,7 +658,7 @@ static int pgsql_get_ip_list(const char *kind, ip_range_list_t * list) { for(i=0;itype != REDIS_REPLY_NIL) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type); } else { - add_ip_list_range(rget->str,list); + add_ip_list_range(rget->str,NULL,list); } turnFreeRedisReply(rget); } diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 11dd9dc0..70600f36 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -77,7 +77,7 @@ DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,1, { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,NULL,NULL,NULL }, -{NULL, NULL, 0},{NULL, NULL, 0}, +{NULL, 0},{NULL, 0}, NEV_UNKNOWN, { "Unknown", "UDP listening socket per session", "UDP thread per network endpoint", "UDP thread per CPU core" }, //////////////// Relay servers ////////////////////////////////// @@ -1230,10 +1230,10 @@ static void set_option(int c, char *value) add_tls_alternate_server(value); break; case ALLOWED_PEER_IPS: - if (add_ip_list_range(value, &turn_params.ip_whitelist) == 0) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "White listing: %s\n", value); + if (add_ip_list_range(value, NULL, &turn_params.ip_whitelist) == 0) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "White listing: %s\n", value); break; case DENIED_PEER_IPS: - if (add_ip_list_range(value, &turn_params.ip_blacklist) == 0) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Black listing: %s\n", value); + if (add_ip_list_range(value, NULL, &turn_params.ip_blacklist) == 0) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Black listing: %s\n", value); break; case CIPHER_LIST_OPT: STRCPY(turn_params.cipher_list,value); diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index 0e1f45fc..7fb60d8c 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -312,7 +312,7 @@ static void cli_print_str_array(struct cli_session* cs, char **value, size_t sz, static void cli_print_ip_range_list(struct cli_session* cs, ip_range_list_t *value, const char* name, int changeable) { - if(cs && cs->ts && name && value && value->ranges_number && value->ranges) { + if(cs && cs->ts && name && value && value->ranges_number && value->rs) { const char *sc=""; if(changeable==1) sc=" (*)"; @@ -320,8 +320,15 @@ static void cli_print_ip_range_list(struct cli_session* cs, ip_range_list_t *val sc=" (**)"; size_t i; for(i=0;iranges_number;++i) { - if(value->ranges[i]) - myprintf(cs," %s: %s%s\n",name,value->ranges[i],sc); + if(value->rs[i].realm[0]) { + if(cs->realm[0] && strcmp(cs->realm,value->rs[i].realm)) { + continue; + } else { + myprintf(cs," common %s: %s (%s)%s\n",name,value->rs[i].str,value->rs[i].realm,sc); + } + } else { + myprintf(cs," common %s: %s%s\n",name,value->rs[i].str,sc); + } } } } diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 7505da77..c2513f16 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -1393,17 +1393,8 @@ static ip_range_list_t* get_ip_list(const char *kind) static void ip_list_free(ip_range_list_t *l) { if(l) { - size_t i; - for(i=0;iranges_number;++i) { - if(l->ranges && l->ranges[i]) - turn_free(l->ranges[i],0); - if(l->encaddrsranges && l->encaddrsranges[i]) - turn_free(l->encaddrsranges[i],0); - } - if(l->ranges) - turn_free(l->ranges,0); - if(l->encaddrsranges) - turn_free(l->encaddrsranges,0); + if(l->rs) + turn_free(l->rs,l->ranges_number * sizeof(ip_range_t)); turn_free(l,sizeof(ip_range_list_t)); } } @@ -1432,7 +1423,7 @@ void update_white_and_black_lists(void) /////////////// add ACL record /////////////////// -int add_ip_list_range(const char * range0, ip_range_list_t * list) +int add_ip_list_range(const char * range0, const char * realm, ip_range_list_t * list) { char *range = turn_strdup(range0); @@ -1465,13 +1456,14 @@ int add_ip_list_range(const char * range0, ip_range_list_t * list) *separator = '-'; ++(list->ranges_number); - list->ranges = (char**) turn_realloc(list->ranges, 0, sizeof(char*) * list->ranges_number); - list->ranges[list->ranges_number - 1] = range; - list->encaddrsranges = (ioa_addr_range**) turn_realloc(list->encaddrsranges, 0, sizeof(ioa_addr_range*) * list->ranges_number); - - list->encaddrsranges[list->ranges_number - 1] = (ioa_addr_range*) turn_malloc(sizeof(ioa_addr_range)); - - ioa_addr_range_set(list->encaddrsranges[list->ranges_number - 1], &min, &max); + list->rs = (ip_range_t*) turn_realloc(list->rs, 0, sizeof(ip_range_t) * list->ranges_number); + STRCPY(list->rs[list->ranges_number - 1].str,range); + if(realm) + STRCPY(list->rs[list->ranges_number - 1].realm,realm); + else + list->rs[list->ranges_number - 1].realm[0]=0; + turn_free(range,0); + ioa_addr_range_set(&(list->rs[list->ranges_number - 1].enc), &min, &max); return 0; } diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index 6e5b96fb..2e05dda3 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -208,7 +208,7 @@ 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_ip_list_range(const char* range, ip_range_list_t * list); +int add_ip_list_range(const char* range, const char* realm, ip_range_list_t * list); ///////////// Redis ////////////////////// diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 8fff04c3..79fb3c48 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -137,9 +137,16 @@ typedef struct _realm_options_t realm_options_t; //////// IP White/black listing /////////// +struct _ip_range { + char str[257]; + char realm[513]; + ioa_addr_range enc; +}; + +typedef struct _ip_range ip_range_t; + struct _ip_range_list { - char **ranges; - ioa_addr_range **encaddrsranges; + ip_range_t *rs; size_t ranges_number; }; diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index b622b842..99ad1dfd 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -250,8 +250,10 @@ static int send_turn_message_to(turn_turnserver *server, ioa_network_buffer_hand /////////////////// Peer addr check ///////////////////////////// -static int good_peer_addr(turn_turnserver *server, ioa_addr *peer_addr) +static int good_peer_addr(turn_turnserver *server, const char* realm, ioa_addr *peer_addr) { +#define CHECK_REALM(r) if((r)[0] && realm && realm[0] && strcmp((r),realm)) continue + if(server && peer_addr) { if(*(server->no_multicast_peers) && ioa_addr_is_multicast(peer_addr)) return 0; @@ -264,7 +266,8 @@ static int good_peer_addr(turn_turnserver *server, ioa_addr *peer_addr) if(server->ip_whitelist) { // White listing of addr ranges for (i = server->ip_whitelist->ranges_number - 1; i >= 0; --i) { - if (ioa_addr_in_range(server->ip_whitelist->encaddrsranges[i], peer_addr)) + CHECK_REALM(server->ip_whitelist->rs[i].realm); + if (ioa_addr_in_range(&(server->ip_whitelist->rs[i].enc), peer_addr)) return 1; } } @@ -276,7 +279,8 @@ static int good_peer_addr(turn_turnserver *server, ioa_addr *peer_addr) if(wl) { // White listing of addr ranges for (i = wl->ranges_number - 1; i >= 0; --i) { - if (ioa_addr_in_range(wl->encaddrsranges[i], peer_addr)) { + CHECK_REALM(wl->rs[i].realm); + if (ioa_addr_in_range(&(wl->rs[i].enc), peer_addr)) { ioa_unlock_whitelist(server->e); return 1; } @@ -289,10 +293,11 @@ static int good_peer_addr(turn_turnserver *server, ioa_addr *peer_addr) if(server->ip_blacklist) { // Black listing of addr ranges for (i = server->ip_blacklist->ranges_number - 1; i >= 0; --i) { - if (ioa_addr_in_range(server->ip_blacklist->encaddrsranges[i], peer_addr)) { + CHECK_REALM(server->ip_blacklist->rs[i].realm); + if (ioa_addr_in_range(&(server->ip_blacklist->rs[i].enc), peer_addr)) { char saddr[129]; addr_to_string_no_port(peer_addr,(u08bits*)saddr); - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "A peer IP %s denied in the range: %s\n",saddr,server->ip_blacklist->ranges[i]); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "A peer IP %s denied in the range: %s\n",saddr,server->ip_blacklist->rs[i].str); return 0; } } @@ -305,11 +310,12 @@ static int good_peer_addr(turn_turnserver *server, ioa_addr *peer_addr) if(bl) { // Black listing of addr ranges for (i = bl->ranges_number - 1; i >= 0; --i) { - if (ioa_addr_in_range(bl->encaddrsranges[i], peer_addr)) { + CHECK_REALM(bl->rs[i].realm); + if (ioa_addr_in_range(&(bl->rs[i].enc), peer_addr)) { ioa_unlock_blacklist(server->e); char saddr[129]; addr_to_string_no_port(peer_addr,(u08bits*)saddr); - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "A peer IP %s denied in the range: %s\n",saddr,bl->ranges[i]); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "A peer IP %s denied in the range: %s\n",saddr,bl->rs[i].str); return 0; } } @@ -320,6 +326,8 @@ static int good_peer_addr(turn_turnserver *server, ioa_addr *peer_addr) } } +#undef CHECK_REALM + return 1; } @@ -2076,7 +2084,7 @@ static void tcp_peer_accept_connection(ioa_socket_handle s, void *arg) return; } - if(!good_peer_addr(server, peer_addr)) { + if(!good_peer_addr(server, ss->realm_options.name, peer_addr)) { u08bits saddr[256]; addr_to_string(peer_addr, saddr); TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: an attempt to connect from a peer with forbidden address: %s\n", __FUNCTION__,saddr); @@ -2226,7 +2234,7 @@ static int handle_turn_connect(turn_turnserver *server, *reason = (const u08bits *)"Where is Peer Address ?"; } else { - if(!good_peer_addr(server,&peer_addr)) { + if(!good_peer_addr(server,ss->realm_options.name,&peer_addr)) { *err_code = 403; *reason = (const u08bits *) "Forbidden IP"; } else { @@ -2588,7 +2596,7 @@ static int handle_turn_channel_bind(turn_turnserver *server, *err_code = 400; *reason = (const u08bits *)"You cannot use the same peer with different channel number"; } else { - if(!good_peer_addr(server,&peer_addr)) { + if(!good_peer_addr(server,ss->realm_options.name,&peer_addr)) { *err_code = 403; *reason = (const u08bits *) "Forbidden IP"; } else { @@ -3015,7 +3023,7 @@ static int handle_turn_create_permission(turn_turnserver *server, if(!get_relay_socket(a,peer_addr.ss.sa_family)) { *err_code = 443; *reason = (const u08bits *)"Peer Address Family Mismatch"; - } else if(!good_peer_addr(server, &peer_addr)) { + } else if(!good_peer_addr(server, ss->realm_options.name, &peer_addr)) { *err_code = 403; *reason = (const u08bits *) "Forbidden IP"; } else { From 13b8ac9e74a215fa8071ca870836d06aba1a4ac1 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 27 Oct 2014 01:22:33 +0000 Subject: [PATCH 288/805] working on per-realm white/black lists --- ChangeLog | 6 ++-- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 6 ++-- src/apps/relay/dbdrivers/dbd_mysql.c | 21 +++++++++++-- src/apps/relay/dbdrivers/dbd_pgsql.c | 41 +++++++++++++++++--------- src/apps/relay/dbdrivers/dbd_redis.c | 44 +++++++++++++++++++--------- src/ns_turn_defs.h | 2 +- turndb/schema.sql | 12 ++++---- turndb/schema.userdb.redis | 19 ++++++++---- turndb/testredisdbsetup.sh | 5 ++++ turndb/testsqldbsetup.sql | 4 +++ 11 files changed, 114 insertions(+), 48 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5ce8b345..d49ebf08 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ -10/16/2014 Oleg Moskalenko -Version 4.2.1.4 'Monza': +10/26/2014 Oleg Moskalenko +Version 4.2.2.1 'Monza': + - black- and white- IP lists are divided per realm + (the DB schema changed); - TCP/TLS tests extended. - relay RTCP sockets ports allocation fixed. - list of libraries cleaned. diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 8cfb0989..ea201c65 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.2.1.4 +TURNVERSION=4.2.2.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 2e44efe4..a5394229 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.2.1.4 +Version: 4.2.2.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,8 +294,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Thu Oct 16 2014 Oleg Moskalenko - - Sync to 4.2.1.4 +* Sun Oct 26 2014 Oleg Moskalenko + - Sync to 4.2.2.1 * Sun Oct 05 2014 Oleg Moskalenko - Sync to 4.2.1.2 * Thu Aug 14 2014 Oleg Moskalenko diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 7b4a4da0..cd5e65f5 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -896,11 +896,22 @@ static int mysql_get_ip_list(const char *kind, ip_range_list_t * list) { MYSQL * myc = get_mydb_connection(); if(myc) { char statement[TURN_LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"select ip_range from %s_peer_ip",kind); + snprintf(statement,sizeof(statement),"select ip_range,realm from %s_peer_ip",kind); int res = mysql_query(myc, statement); + + if(res) { + static int wrong_table_reported = 0; + if(!wrong_table_reported) { + wrong_table_reported = 1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information; probably, the tables 'allowed_peer_ip' and/or 'denied_peer_ip' have to be upgraded to include the realm column.\n"); + } + snprintf(statement, sizeof(statement), "select ip_range,'' from %s_peer_ip", kind); + res = mysql_query(myc, statement); + } + if(res == 0) { MYSQL_RES *mres = mysql_store_result(myc); - if(mres && mysql_field_count(myc)==1) { + if(mres && mysql_field_count(myc)==2) { for(;;) { MYSQL_ROW row = mysql_fetch_row(mres); if(!row) { @@ -913,7 +924,11 @@ static int mysql_get_ip_list(const char *kind, ip_range_list_t * list) { char kval[TURN_LONG_STRING_SIZE]; ns_bcopy(row[0],kval,sz); kval[sz]=0; - add_ip_list_range(kval,NULL,list); + sz = lengths[1]; + char rval[TURN_LONG_STRING_SIZE]; + ns_bcopy(row[1],rval,sz); + rval[sz]=0; + add_ip_list_range(kval,rval,list); } } } diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index ab3b5a9c..21e6ff98 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -645,30 +645,43 @@ static void pgsql_auth_ping(void * rch) { } } -static int pgsql_get_ip_list(const char *kind, ip_range_list_t * list) { - int ret = -1; + +static int pgsql_get_ip_list(const char *kind, ip_range_list_t * list) +{ + int ret = -1; PGconn * pqc = get_pqdb_connection(); - if(pqc) { + if (pqc) { char statement[TURN_LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"select ip_range from %s_peer_ip",kind); + snprintf(statement, sizeof(statement), "select ip_range,realm from %s_peer_ip", kind); PGresult *res = PQexec(pqc, statement); - if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) { - int i = 0; - for(i=0;ielements; ++i) { - add_to_secrets_list(&keys,reply->element[i]->str); + add_to_secrets_list(&keys, reply->element[i]->str); } } - for(isz=0;isztype == 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 { - add_ip_list_range(rget->str,NULL,list); + char *ptr = ((char*)keys.secrets[isz])+header_len; + char *sep = strstr(ptr, "/"); + if (sep) { + *sep = 0; + realm = ptr; + } + add_ip_list_range(rget->str, realm, list); + if(sep) { + *sep='/'; + } } turnFreeRedisReply(rget); } @@ -1139,10 +1155,10 @@ static int redis_get_ip_list(const char *kind, ip_range_list_t * list) { clean_secrets_list(&keys); turnFreeRedisReply(reply); - ret = 0; + ret = 0; } } - return ret; + return ret; } static void redis_reread_realms(secrets_list_t * realms_list) { diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 9c493cac..63820556 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.2.1.4" +#define TURN_SERVER_VERSION "4.2.2.1" #define TURN_SERVER_VERSION_NAME "Monza" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" diff --git a/turndb/schema.sql b/turndb/schema.sql index cdbb48de..9c452a0e 100644 --- a/turndb/schema.sql +++ b/turndb/schema.sql @@ -1,6 +1,6 @@ CREATE TABLE turnusers_lt ( - realm varchar(512), + realm varchar(512) default '', name varchar(512), hmackey char(128), PRIMARY KEY (realm,name) @@ -12,19 +12,21 @@ CREATE TABLE turnusers_st ( ); CREATE TABLE turn_secret ( - realm varchar(512), + 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 (ip_range) + primary key (realm,ip_range) ); CREATE TABLE denied_peer_ip ( + realm varchar(512) default '', ip_range varchar(256), - primary key (ip_range) + primary key (realm,ip_range) ); CREATE TABLE turn_origin_to_realm ( @@ -34,7 +36,7 @@ CREATE TABLE turn_origin_to_realm ( ); CREATE TABLE turn_realm_option ( - realm varchar(512), + realm varchar(512) default '', opt varchar(32), value varchar(128), primary key (realm,opt) diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis index 371645e1..aaaadbfd 100644 --- a/turndb/schema.userdb.redis +++ b/turndb/schema.userdb.redis @@ -28,13 +28,17 @@ issue command "keys turn/realm/north.gov/secret/*" it it will try to use the obtained keys in arbitrary order. 4) The "white" and "black" peer IP ranges are stored as keys of the -following form: "turn/allowed-peer-ip/" or -"turn/denied-peer-ip/" +following form: +"turn/allowed-peer-ip/" or +"turn/allowed-peer-ip//" or +"turn/denied-peer-ip/" or +"turn/denied-peer-ip//". The meaning of the keys is the same as the meaning of allowed-peer-ip and -denied-peer-ip turnserver command-line option. The only difference is that -the option values are "static" (they remain the same for the lifetime of -the turnserver process) but the database records can be dynamically changed +denied-peer-ip turnserver command-line option (with the addition of the realm option). +The only difference is that the turnserver option values are "static" +(they remain the same for the lifetime of the turnserver process) but +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 @@ -143,7 +147,12 @@ set turn/origin/https://bligh.edu:443 crinna.org set turn/denied-peer-ip/123456 "172.17.13.133-172.17.14.56" set turn/denied-peer-ip/234567 "123::45" +set turn/denied-peer-ip/north.gov/1234567 "172.17.17.133-172.17.19.56" +set turn/denied-peer-ip/crinna.org/2345678 "123::77" + set turn/allowed-peer-ip/345678 "172.17.13.200" +set turn/allowed-peer-ip/north.gov/345679 "172.17.13.201" +set turn/allowed-peer-ip/crinna.org/3456710 "172.17.13.202" 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' diff --git a/turndb/testredisdbsetup.sh b/turndb/testredisdbsetup.sh index e939f202..0197c3b7 100755 --- a/turndb/testredisdbsetup.sh +++ b/turndb/testredisdbsetup.sh @@ -45,7 +45,12 @@ set turn/origin/https://bligh.edu:443 crinna.org set turn/denied-peer-ip/123456 "172.17.13.133-172.17.14.56" set turn/denied-peer-ip/234567 "123::45" +set turn/denied-peer-ip/north.gov/1234567 "172.17.17.133-172.17.19.56" +set turn/denied-peer-ip/crinna.org/2345678 "123::77" + set turn/allowed-peer-ip/345678 "172.17.13.200" +set turn/allowed-peer-ip/north.gov/345679 "172.17.13.201" +set turn/allowed-peer-ip/crinna.org/3456710 "172.17.13.202" 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' diff --git a/turndb/testsqldbsetup.sql b/turndb/testsqldbsetup.sql index 19e92eba..58d5eca0 100644 --- a/turndb/testsqldbsetup.sql +++ b/turndb/testsqldbsetup.sql @@ -23,9 +23,13 @@ insert into turn_realm_option (realm,opt,value) values('north.gov','user-quota', insert into turn_realm_option (realm,opt,value) values('crinna.org','user-quota','8000'); insert into allowed_peer_ip (ip_range) values('172.17.13.200'); +insert into allowed_peer_ip (realm,ip_range) values('north.gov','172.17.13.201'); +insert into allowed_peer_ip (realm,ip_range) values('crinna.org','172.17.13.202'); insert into denied_peer_ip (ip_range) values('172.17.13.133-172.17.14.56'); insert into denied_peer_ip (ip_range) values('123::45'); +insert into denied_peer_ip (realm,ip_range) values('north.gov','172.17.17.133-172.17.19.56'); +insert into denied_peer_ip (realm,ip_range) values('crinna.org','123::77'); insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('north','Y2FybGVvbg==',0,0,'SHA-256','AES-256-CBC','','HMAC-SHA-256-128',''); insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('oldempire','YXVsY3Vz',0,0,'SHA-256','AEAD-AES-256-GCM','','',''); From 1d7940399763308398a4c9ceef32c6558d13b069 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 27 Oct 2014 05:26:11 +0000 Subject: [PATCH 289/805] per-realm white/black lists added to mongo stuff --- src/apps/relay/dbdrivers/dbd_mongo.c | 112 +++++++++++++++++---------- turndb/testmongosetup.sh | 19 +++-- 2 files changed, 84 insertions(+), 47 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index 37f66d17..cb4d6ad1 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -969,48 +969,80 @@ static void mongo_auth_ping(void * rch) { UNUSED_ARG(rch); // NOOP } + +static int mongo_read_realms_ip_lists(const char *kind, ip_range_list_t * list) +{ + int ret = 0; + + char field_name[129]; + sprintf(field_name, "%s_peer_ip", kind); + + mongoc_collection_t * collection = mongo_get_collection("realm"); + + if (!collection) + return ret; + + bson_t query; + bson_init(&query); + + bson_t fields; + bson_init(&fields); + BSON_APPEND_INT32(&fields, "realm", 1); + BSON_APPEND_INT32(&fields, field_name, 1); + + mongoc_cursor_t * cursor; + cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, + &query, &fields, NULL); + + if (!cursor) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Error querying MongoDB collection 'realm'\n"); + ret = -1; + } else { + const bson_t * item; + uint32_t length; + bson_iter_t iter; + char realm[513]; + + while (mongoc_cursor_next(cursor, &item)) { + + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "realm") + && BSON_ITER_HOLDS_UTF8(&iter)) { + + STRCPY(realm,bson_iter_utf8(&iter, &length)); + + if (bson_iter_init(&iter, item) && bson_iter_find(&iter, + field_name) && BSON_ITER_HOLDS_ARRAY(&iter)) { + const uint8_t *docbuf = NULL; + uint32_t doclen = 0; + bson_t ip_range_array; + bson_iter_t ip_range_iter; + + bson_iter_array(&iter, &doclen, &docbuf); + bson_init_static(&ip_range_array, docbuf, doclen); + + if (bson_iter_init(&ip_range_iter, &ip_range_array)) { + while (bson_iter_next(&ip_range_iter)) { + if (BSON_ITER_HOLDS_UTF8(&ip_range_iter)) { + const char* ip_range = bson_iter_utf8(&ip_range_iter, &length); + add_ip_list_range(ip_range, realm, list); + } + } + } + } + } + } + mongoc_cursor_destroy(cursor); + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + bson_destroy(&fields); + + return ret; +} static int mongo_get_ip_list(const char *kind, ip_range_list_t * list) { - char * collection_name = (char *)turn_malloc(strlen(kind) + 9); - sprintf(collection_name, "%s_peer_ip", kind); - mongoc_collection_t * collection = mongo_get_collection(collection_name); - turn_free(collection_name, strlen(kind) + 9); - - if(!collection) - return -1; - - bson_t query; - bson_init(&query); - - bson_t fields; - bson_init(&fields); - BSON_APPEND_INT32(&fields, "ip_range", 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; - const char * value; - while(mongoc_cursor_next(cursor, &item)) { - if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "ip_range") && BSON_ITER_HOLDS_UTF8(&iter)) { - value = bson_iter_utf8(&iter, &length); - add_ip_list_range(value, NULL, list); - } - } - mongoc_cursor_destroy(cursor); - ret = 0; - } - mongoc_collection_destroy(collection); - bson_destroy(&query); - bson_destroy(&fields); - return ret; + return mongo_read_realms_ip_lists(kind, list); } diff --git a/turndb/testmongosetup.sh b/turndb/testmongosetup.sh index 93fcdcdd..30538188 100755 --- a/turndb/testmongosetup.sh +++ b/turndb/testmongosetup.sh @@ -4,6 +4,12 @@ mongo $* < Date: Mon, 27 Oct 2014 06:27:00 +0000 Subject: [PATCH 290/805] white/black list telnet info fixed --- src/apps/relay/turncli.c | 19 +++++++++++++++---- src/apps/relay/userdb.c | 12 ++++++------ src/apps/relay/userdb.h | 2 ++ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index 7fb60d8c..2c67aa62 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -324,10 +324,10 @@ static void cli_print_ip_range_list(struct cli_session* cs, ip_range_list_t *val if(cs->realm[0] && strcmp(cs->realm,value->rs[i].realm)) { continue; } else { - myprintf(cs," common %s: %s (%s)%s\n",name,value->rs[i].str,value->rs[i].realm,sc); + myprintf(cs," %s: %s (%s)%s\n",name,value->rs[i].str,value->rs[i].realm,sc); } } else { - myprintf(cs," common %s: %s%s\n",name,value->rs[i].str,sc); + myprintf(cs," %s: %s%s\n",name,value->rs[i].str,sc); } } } @@ -760,8 +760,19 @@ static void cli_print_configuration(struct cli_session* cs) cli_print_uint(cs,(unsigned long)turn_params.min_port,"min-port",0); cli_print_uint(cs,(unsigned long)turn_params.max_port,"max-port",0); - cli_print_ip_range_list(cs,&turn_params.ip_whitelist,"Whitelist IP",0); - cli_print_ip_range_list(cs,&turn_params.ip_blacklist,"Blacklist IP",0); + cli_print_ip_range_list(cs,&turn_params.ip_whitelist,"Whitelist IP (static)",0); + { + ip_range_list_t* l = get_ip_list("allowed"); + cli_print_ip_range_list(cs,l,"Whitelist IP (dynamic)",0); + ip_list_free(l); + } + + cli_print_ip_range_list(cs,&turn_params.ip_blacklist,"Blacklist IP (static)",0); + { + ip_range_list_t* l = get_ip_list("denied"); + cli_print_ip_range_list(cs,l,"Blacklist IP (dynamic)",0); + ip_list_free(l); + } cli_print_flag(cs,turn_params.no_multicast_peers,"no-multicast-peers",1); cli_print_flag(cs,turn_params.no_loopback_peers,"no-loopback-peers",1); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index c2513f16..bb7e7801 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -1377,20 +1377,20 @@ const ip_range_list_t* ioa_get_blacklist(ioa_engine_handle e) return ipblacklist; } -static ip_range_list_t* get_ip_list(const char *kind) +ip_range_list_t* get_ip_list(const char *kind) { - ip_range_list_t *ret = (ip_range_list_t*)turn_malloc(sizeof(ip_range_list_t)); + ip_range_list_t *ret = (ip_range_list_t*) turn_malloc(sizeof(ip_range_list_t)); ns_bzero(ret,sizeof(ip_range_list_t)); - turn_dbdriver_t * dbd = get_dbdriver(); - if (dbd && dbd->get_ip_list) { - (*dbd->get_ip_list)(kind, ret); + turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->get_ip_list) { + (*dbd->get_ip_list)(kind, ret); } return ret; } -static void ip_list_free(ip_range_list_t *l) +void ip_list_free(ip_range_list_t *l) { if(l) { if(l->rs) diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index 2e05dda3..988103a5 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -209,6 +209,8 @@ 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_ip_list_range(const char* range, const char* realm, ip_range_list_t * list); +ip_range_list_t* get_ip_list(const char *kind); +void ip_list_free(ip_range_list_t *l); ///////////// Redis ////////////////////// From 835c02048db341add9a9bfc27e7fd1e0fc5cae57 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 27 Oct 2014 07:17:53 +0000 Subject: [PATCH 291/805] TODO updated --- TODO | 2 -- 1 file changed, 2 deletions(-) diff --git a/TODO b/TODO index c5d31573..05e9ab79 100644 --- a/TODO +++ b/TODO @@ -11,8 +11,6 @@ Cygwin is supported. A "real" MS-Windows port would involve a usable GUI. -3) Debian: update control to 3.9.6 - ================================================================== ### II. DOCS ### From 0da9105371b950a00b2c522a03730bf21c57b4f3 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 27 Oct 2014 17:36:47 +0000 Subject: [PATCH 292/805] textual fixes --- ChangeLog | 6 +++--- INSTALL | 12 +++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index d49ebf08..f8126f1e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,10 @@ 10/26/2014 Oleg Moskalenko Version 4.2.2.1 'Monza': - - black- and white- IP lists are divided per realm + - Black- and white- IP lists are divided per realm (the DB schema changed); - TCP/TLS tests extended. - - relay RTCP sockets ports allocation fixed. - - list of libraries cleaned. + - Relay RTCP sockets ports allocation fixed. + - List of libraries cleaned. - SSL renegotiation callback fixed. 10/05/2014 Oleg Moskalenko diff --git a/INSTALL b/INSTALL index d158a1c9..f8d6a9ad 100644 --- a/INSTALL +++ b/INSTALL @@ -700,7 +700,7 @@ The schema description: # Table for long-term credentials mechanism authorization: # CREATE TABLE turnusers_lt ( - realm varchar(512), + realm varchar(512) default '', name varchar(512), hmackey char(128), PRIMARY KEY (realm,name) @@ -727,7 +727,7 @@ CREATE TABLE turnusers_st ( # mechanism: # CREATE TABLE turn_secret ( - realm varchar(512), + realm varchar(512) default '', value varchar(512), primary key (realm,value) ); @@ -735,15 +735,17 @@ CREATE TABLE turn_secret ( # Table holding "white" allowed peer IP ranges. # CREATE TABLE allowed_peer_ip ( + realm varchar(512) default '', ip_range varchar(256), - primary key (ip_range) + primary key (realm,ip_range) ); # Table holding "black" denied peer IP ranges. # CREATE TABLE denied_peer_ip ( + realm varchar(512) default '', ip_range varchar(256), - primary key (ip_range) + primary key (realm,ip_range) ); # Table to match origin to realm. @@ -763,7 +765,7 @@ CREATE TABLE turn_origin_to_realm ( # Values for them are integers (in text form). # CREATE TABLE turn_realm_option ( - realm varchar(512), + realm varchar(512) default '', opt varchar(32), value varchar(128), primary key (realm,opt) From 9e0677e8c0b5a779803ea83f5a97f02e6a2b8030 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 28 Oct 2014 06:36:37 +0000 Subject: [PATCH 293/805] changelog fix --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f8126f1e..09e96b14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ 10/26/2014 Oleg Moskalenko Version 4.2.2.1 'Monza': - Black- and white- IP lists are divided per realm - (the DB schema changed); + (the DB schema for those two tables changed); - TCP/TLS tests extended. - Relay RTCP sockets ports allocation fixed. - List of libraries cleaned. From 48349d91b54a2be08d6fddf83b723d5d870ca16d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 28 Oct 2014 08:28:40 +0000 Subject: [PATCH 294/805] TODO updated --- TODO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO b/TODO index 05e9ab79..61237ca1 100644 --- a/TODO +++ b/TODO @@ -105,7 +105,7 @@ ================================================================== -Nope +1) Redis database structure cleaning. ================================================================== From 10045bd74239b798a80d628eea42a82b077454cf Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 29 Oct 2014 05:39:42 +0000 Subject: [PATCH 295/805] working on redis db reorganization. --- ChangeLog | 3 +- INSTALL | 50 ++++----- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +- src/apps/relay/dbdrivers/dbd_redis.c | 158 +++++++++------------------ src/ns_turn_defs.h | 2 +- turndb/schema.userdb.redis | 21 ++-- turndb/testredisdbsetup.sh | 4 +- 8 files changed, 92 insertions(+), 152 deletions(-) diff --git a/ChangeLog b/ChangeLog index 09e96b14..9d309f98 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,8 @@ 10/26/2014 Oleg Moskalenko -Version 4.2.2.1 'Monza': +Version 4.2.2.2 'Monza': - Black- and white- IP lists are divided per realm (the DB schema for those two tables changed); + - Updated Redis database schema. - TCP/TLS tests extended. - Relay RTCP sockets ports allocation fixed. - List of libraries cleaned. diff --git a/INSTALL b/INSTALL index f8d6a9ad..81ca3e9f 100644 --- a/INSTALL +++ b/INSTALL @@ -844,7 +844,7 @@ Of course, the administrators can play with the connection string as they want. When starting the turnserver, the psql-userdb parameter will be, for example: -turnserver ... --psql-userdb="host=localhost dbname=turn user=turn password=turn connect_timeout=30" +turnserver ... --psql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" Or, for 9.x PostgreSQL versions: turnserver ... --psql-userdb=postgresql://username:password@/databasename ... @@ -858,20 +858,20 @@ Fill in users, for example: Shared secret for the TURN REST API: - $ bin/turnadmin -s logen -e "host=localhost dbname=turn user=turn password=turn" + $ bin/turnadmin -s logen -e "host=localhost dbname=coturn user=turn password=turn" Long-term credentials mechanism: - $ bin/turnadmin -a -e "host=localhost dbname=turn user=turn password=turn" -u gorst -r north.gov -p hero - $ bin/turnadmin -a -e "host=localhost dbname=turn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + $ bin/turnadmin -a -e "host=localhost dbname=coturn user=turn password=turn" -u gorst -r north.gov -p hero + $ bin/turnadmin -a -e "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic Long-term credentials mechanism with SHA256 extention: - $ bin/turnadmin -a -e "host=localhost dbname=turn user=turn password=turn" -u bethod -r north.gov -p king-of-north --sha256 + $ 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: - $ bin/turnadmin -A -e "host=localhost dbname=turn user=turn password=turn" -u gorst -r north.gov -p hero - $ bin/turnadmin -A -e "host=localhost dbname=turn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + $ bin/turnadmin -A -e "host=localhost dbname=coturn user=turn password=turn" -u gorst -r north.gov -p hero + $ bin/turnadmin -A -e "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic XV. MySQL (MariaDB) setup @@ -913,20 +913,20 @@ the root account. Shared secret for the TURN REST API: - $ bin/turnadmin -s logen -M "host=localhost dbname=turn user=turn password=turn" + $ bin/turnadmin -s logen -M "host=localhost dbname=coturn user=turn password=turn" Long-term credentials mechanism: - $ bin/turnadmin -a -M "host=localhost dbname=turn user=turn password=turn" -u gorst -r north.gov -p hero - $ bin/turnadmin -a -M "host=localhost dbname=turn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + $ bin/turnadmin -a -M "host=localhost dbname=coturn user=turn password=turn" -u gorst -r north.gov -p hero + $ bin/turnadmin -a -M "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic Long-term credentials mechanism with SHA256 extention: - $ bin/turnadmin -a -M "host=localhost dbname=turn user=turn password=turn" -u bethod -r north.gov -p king-of-north --sha256 + $ 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: - $ bin/turnadmin -A -M "host=localhost dbname=turn user=turn password=turn" -u gorst -r north.gov -p hero - $ bin/turnadmin -A -M "host=localhost dbname=turn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + $ bin/turnadmin -A -M "host=localhost dbname=coturn user=turn password=turn" -u gorst -r north.gov -p hero + $ bin/turnadmin -A -M "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic 7) Now we can use mysql in the turnserver. @@ -944,11 +944,11 @@ The format of the MySQL connection string is: So, an example of the MySQL database parameter in the TURN server command line would be: ---mysql-userdb="host=localhost dbname=turn user=turn password=turn connect_timeout=30" +--mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" Or in the turnserver.conf file: -mysql-userdb="host=localhost dbname=turn user=turn password=turn connect_timeout=30" +mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" If you have to use a secure MySQL connection (SSL) then you have to use also the optional connection string parameters for the secure communications: @@ -977,11 +977,11 @@ http://hergert.me/docs/mongo-c-driver/mongoc_uri.html: So, an example of the MongoDB database parameter in the TURN server command line would be: ---mongo-userdb="mongodb://localhost:27017/turndb" +--mongo-userdb="mongodb://localhost:27017/coturn" Or in the turnserver.conf file: -mongo-userdb="mongodb://localhost:27017/turndb" +mongo-userdb="mongodb://localhost:27017/coturn" The meanings of the MongoDB keys are the same as for the other databases, see the explanations for the Postgres, for example. @@ -1012,11 +1012,11 @@ connection string is: So, an example of the Redis database parameter in the TURN server command line would be: ---redis-userdb="ip=127.0.0.1 dbname=0 password=turn connect_timeout=30" +--redis-userdb="ip=127.0.0.1 dbname=2 password=turn connect_timeout=30" Or in the turnserver.conf file: -redis-userdb="ip=127.0.0.1 dbname=0 password=turn connect_timeout=30" +redis-userdb="ip=127.0.0.1 dbname=2 password=turn connect_timeout=30" Redis can be also used for the TURN allocation status check and for status and traffic notifications. @@ -1042,20 +1042,20 @@ Redis TURN admin commands: Shared secret for the TURN REST API: - $ bin/turnadmin -s logen -N "host=localhost dbname=0 user=turn password=turn" + $ bin/turnadmin -s logen -N "host=localhost dbname=2 user=turn password=turn" Long-term credentials mechanism: - $ bin/turnadmin -a -N "host=localhost dbname=0 user=turn password=turn" -u gorst -r north.gov -p hero - $ bin/turnadmin -a -N "host=localhost dbname=0 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + $ bin/turnadmin -a -N "host=localhost dbname=2 user=turn password=turn" -u gorst -r north.gov -p hero + $ bin/turnadmin -a -N "host=localhost dbname=2 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic Long-term credentials mechanism with SHA256 extention: - $ bin/turnadmin -a -N "host=localhost dbname=0 user=turn password=turn" -u bethod -r north.gov -p king-of-north --sha256 + $ 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: - $ bin/turnadmin -A -N "host=localhost dbname=0 user=turn password=turn" -u gorst -r north.gov -p hero - $ bin/turnadmin -A -N "host=localhost dbname=0 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + $ bin/turnadmin -A -N "host=localhost dbname=2 user=turn password=turn" -u gorst -r north.gov -p hero + $ bin/turnadmin -A -N "host=localhost dbname=2 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic See the file testredisdbsetup.sh for the data structure examples. diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index ea201c65..c4ea5977 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.2.2.1 +TURNVERSION=4.2.2.2 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index a5394229..561da6eb 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.2.2.1 +Version: 4.2.2.2 Release: 0%{dist} Summary: Coturn TURN Server @@ -295,7 +295,7 @@ fi %changelog * Sun Oct 26 2014 Oleg Moskalenko - - Sync to 4.2.2.1 + - Sync to 4.2.2.2 * Sun Oct 05 2014 Oleg Moskalenko - Sync to 4.2.1.2 * Thu Aug 14 2014 Oleg Moskalenko diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index bfa0c763..043ed228 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -396,18 +396,13 @@ static int set_redis_realm_opt(char *realm, const char* key, unsigned long *valu /////////////////////////////////////////////////////////////////////////////////////////////////////////// -static int redis_get_auth_secrets(secrets_list_t *sl, u08bits *realm) { - int ret = -1; +static int redis_get_auth_secrets(secrets_list_t *sl, u08bits *realm) +{ + int ret = -1; redisContext *rc = get_redis_connection(); - if(rc) { - redisReply *reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/secret/*", (char*)realm); - if(reply) { - - secrets_list_t keys; - size_t isz = 0; - char s[257]; - - init_secrets_list(&keys); + if (rc) { + redisReply *reply = (redisReply*) redisCommand(rc, "smembers turn/realm/%s/secret", (char*) realm); + if (reply) { if (reply->type == REDIS_REPLY_ERROR) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str); @@ -417,34 +412,16 @@ static int redis_get_auth_secrets(secrets_list_t *sl, u08bits *realm) { } else { size_t i; for (i = 0; i < reply->elements; ++i) { - add_to_secrets_list(&keys,reply->element[i]->str); + add_to_secrets_list(sl, reply->element[i]->str); } } - for(isz=0;isztype == 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 { - add_to_secrets_list(sl,rget->str); - } - turnFreeRedisReply(rget); - } - } - - clean_secrets_list(&keys); - ret = 0; turnFreeRedisReply(reply); } } - return ret; + return ret; } static int redis_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) { @@ -780,18 +757,20 @@ static int redis_list_oauth_keys(void) { return ret; } -static int redis_show_secret(u08bits *realm) { - int ret = -1; + +static int redis_show_secret(u08bits *realm) +{ + int ret = -1; donot_print_connection_success = 1; redisContext *rc = get_redis_connection(); - if(rc) { + if (rc) { redisReply *reply = NULL; - if(realm && realm[0]) { - reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/secret/*",(char*)realm); + if (realm && realm[0]) { + reply = (redisReply*) redisCommand(rc, "keys turn/realm/%s/secret", (char*) realm); } else { - reply = (redisReply*)redisCommand(rc, "keys turn/realm/*/secret/*"); + reply = (redisReply*) redisCommand(rc, "keys turn/realm/*/secret"); } - if(reply) { + if (reply) { secrets_list_t keys; size_t isz = 0; char s[257]; @@ -806,21 +785,26 @@ static int redis_show_secret(u08bits *realm) { } else { size_t i; for (i = 0; i < reply->elements; ++i) { - add_to_secrets_list(&keys,reply->element[i]->str); + add_to_secrets_list(&keys, reply->element[i]->str); } } - for(isz=0;isztype == REDIS_REPLY_ERROR) + for (isz = 0; isz < keys.sz; ++isz) { + snprintf(s, sizeof(s), "smembers %s", keys.secrets[isz]); + 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) { + } else if (rget->type == REDIS_REPLY_STRING) { + printf("%s\n", rget->str); + } else if (rget->type != REDIS_REPLY_ARRAY) { if (rget->type != REDIS_REPLY_NIL) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type); } else { - printf("%s\n",rget->str); + size_t i; + for (i = 0; i < rget->elements; ++i) { + printf("%s\n", rget->element[i]->str); + } } } turnFreeRedisReply(rget); @@ -829,88 +813,44 @@ static int redis_show_secret(u08bits *realm) { clean_secrets_list(&keys); turnFreeRedisReply(reply); - ret = 0; + ret = 0; } } - return ret; + return ret; } -static int redis_del_secret(u08bits *secret, u08bits *realm) { - int ret = -1; + +static int redis_del_secret(u08bits *secret, u08bits *realm) +{ + int ret = -1; donot_print_connection_success = 1; redisContext *rc = get_redis_connection(); - if(rc) { - redisReply *reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/secret/*", (char*)realm); - if(reply) { - secrets_list_t keys; - size_t isz = 0; - char s[TURN_LONG_STRING_SIZE]; - - init_secrets_list(&keys); - - 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); - } - } - - for(isz=0;isztype == 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(!strcmp((char*)secret,rget->str)) { - snprintf(s,sizeof(s),"del %s", keys.secrets[isz]); - turnFreeRedisReply(redisCommand(rc, s)); - } - } - turnFreeRedisReply(rget); - } - } - } - - turnFreeRedisReply(redisCommand(rc, "save")); - - clean_secrets_list(&keys); - - turnFreeRedisReply(reply); - ret = 0; - } + if (rc) { + turnFreeRedisReply(redisCommand(rc, "srem turn/realm/%s/secret %s", (char*) realm, (char*) secret)); + turnFreeRedisReply(redisCommand(rc, "save")); + ret = 0; } - return ret; + return ret; } -static int redis_set_secret(u08bits *secret, u08bits *realm) { - int ret = -1; + +static int redis_set_secret(u08bits *secret, u08bits *realm) +{ + int ret = -1; donot_print_connection_success = 1; redisContext *rc = get_redis_connection(); - if(rc) { + if (rc) { char s[TURN_LONG_STRING_SIZE]; redis_del_secret(secret, realm); - snprintf(s,sizeof(s),"set turn/realm/%s/secret/%lu %s", (char*)realm, (unsigned long)turn_time(), secret); + snprintf(s, sizeof(s), "sadd turn/realm/%s/secret %s", (char*) realm, secret); turnFreeRedisReply(redisCommand(rc, s)); turnFreeRedisReply(redisCommand(rc, "save")); - ret = 0; + ret = 0; } - return ret; + return ret; } static int redis_add_origin(u08bits *origin, u08bits *realm) { diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 63820556..fc28026b 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.2.2.1" +#define TURN_SERVER_VERSION "4.2.2.2" #define TURN_SERVER_VERSION_NAME "Monza" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis index aaaadbfd..03365c42 100644 --- a/turndb/schema.userdb.redis +++ b/turndb/schema.userdb.redis @@ -18,14 +18,13 @@ 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 -may be used (same as in SQL schema). The key will be -"turn/realm//secret/" and the value will be -"". For example, if we have secrets "hero1", "hero2" and "hero3", -then we will have keys "turn/realm/north.gov/secret/123", -"turn/realm/north.gov/secret/234", "turn/realm/north.gov/secret/345" -and their values will be "hero1", "hero2", "hero3". The turnserver will -issue command "keys turn/realm/north.gov/secret/*" it it will try to use the -obtained keys in arbitrary order. +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//secret" and the value(s) will be the secret(s). +For example, if we have secrets "hero1", "hero2" and "hero3", +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 keys of the following form: @@ -97,7 +96,7 @@ This example sets user database for: with default realm "north.gov"; * long-term credentials with open passwords and with default realm "north.gov"; - * TURN REST API with shared secret "logen"; + * 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 @@ -126,8 +125,8 @@ 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" -set turn/realm/north.gov/secret/1368426581 "logen" -set turn/realm/crinna.org/secret/777888999 "north" +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" diff --git a/turndb/testredisdbsetup.sh b/turndb/testredisdbsetup.sh index 0197c3b7..ce449116 100755 --- a/turndb/testredisdbsetup.sh +++ b/turndb/testredisdbsetup.sh @@ -21,8 +21,8 @@ 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" -set turn/realm/north.gov/secret/1368426581 "logen" -set turn/realm/crinna.org/secret/777888999 "north" +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" From 0c0b04753972115bb90dc3d716e735f13594d121 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 29 Oct 2014 06:10:59 +0000 Subject: [PATCH 296/805] redis db refactoring completed --- src/apps/relay/dbdrivers/dbd_redis.c | 40 +++++++++++++++++----------- turndb/schema.userdb.redis | 22 ++++++--------- turndb/testredisdbsetup.sh | 12 +++------ 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index 043ed228..10feb342 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -1041,11 +1041,10 @@ static int redis_get_ip_list(const char *kind, ip_range_list_t * list) int ret = -1; redisContext *rc = get_redis_connection(); if (rc) { - char header[TURN_LONG_STRING_SIZE]; char statement[TURN_LONG_STRING_SIZE]; - snprintf(header, sizeof(header), "turn/%s-peer-ip/", kind); + const char* header = "turn/realm/"; size_t header_len = strlen(header); - snprintf(statement, sizeof(statement), "keys %s*", header); + snprintf(statement, sizeof(statement), "keys %s*/%s-peer-ip", header,kind); redisReply *reply = (redisReply*) redisCommand(rc, statement); if (reply) { secrets_list_t keys; @@ -1067,29 +1066,40 @@ static int redis_get_ip_list(const char *kind, ip_range_list_t * list) } for (isz = 0; isz < keys.sz; ++isz) { + char *realm = NULL; - snprintf(s, sizeof(s), "get %s", keys.secrets[isz]); + + snprintf(s, sizeof(s), "smembers %s", keys.secrets[isz]); + redisReply *rget = (redisReply *) redisCommand(rc, s); + + char *ptr = ((char*)keys.secrets[isz])+header_len; + char *sep = strstr(ptr, "/"); + if (sep) { + *sep = 0; + realm = ptr; + } + if (rget) { - if (rget->type == REDIS_REPLY_ERROR) + 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) { + } else if (rget->type == REDIS_REPLY_STRING) { + add_ip_list_range(rget->str, realm, list); + } else if (rget->type != REDIS_REPLY_ARRAY) { if (rget->type != REDIS_REPLY_NIL) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type); } else { - char *ptr = ((char*)keys.secrets[isz])+header_len; - char *sep = strstr(ptr, "/"); - if (sep) { - *sep = 0; - realm = ptr; - } - add_ip_list_range(rget->str, realm, list); - if(sep) { - *sep='/'; + size_t i; + for (i = 0; i < rget->elements; ++i) { + add_ip_list_range(rget->element[i]->str, realm, list); } } turnFreeRedisReply(rget); } + + if(sep) { + *sep='/'; + } } clean_secrets_list(&keys); diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis index 03365c42..585c2986 100644 --- a/turndb/schema.userdb.redis +++ b/turndb/schema.userdb.redis @@ -26,12 +26,10 @@ 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 keys of the -following form: -"turn/allowed-peer-ip/" or -"turn/allowed-peer-ip//" or -"turn/denied-peer-ip/" or -"turn/denied-peer-ip//". +4) The "white" and "black" peer IP ranges are stored as unordered sets +of the following names: +"turn/realm//allowed-peer-ip" and +"turn/realm//denied-peer-ip". The meaning of the keys is the same as the meaning of allowed-peer-ip and denied-peer-ip turnserver command-line option (with the addition of the realm option). @@ -143,15 +141,11 @@ set turn/realm/crinna.org/user-quota 8000 set turn/origin/http://crinna.org:80 crinna.org set turn/origin/https://bligh.edu:443 crinna.org -set turn/denied-peer-ip/123456 "172.17.13.133-172.17.14.56" -set turn/denied-peer-ip/234567 "123::45" +sadd turn/realm/north.gov/allowed-peer-ip "172.17.13.200" "172.17.13.201" +sadd turn/realm/crinna.org/allowed-peer-ip "172.17.13.202" -set turn/denied-peer-ip/north.gov/1234567 "172.17.17.133-172.17.19.56" -set turn/denied-peer-ip/crinna.org/2345678 "123::77" - -set turn/allowed-peer-ip/345678 "172.17.13.200" -set turn/allowed-peer-ip/north.gov/345679 "172.17.13.201" -set turn/allowed-peer-ip/crinna.org/3456710 "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' diff --git a/turndb/testredisdbsetup.sh b/turndb/testredisdbsetup.sh index ce449116..fbc96622 100755 --- a/turndb/testredisdbsetup.sh +++ b/turndb/testredisdbsetup.sh @@ -42,15 +42,11 @@ set turn/realm/crinna.org/user-quota 8000 set turn/origin/http://crinna.org:80 crinna.org set turn/origin/https://bligh.edu:443 crinna.org -set turn/denied-peer-ip/123456 "172.17.13.133-172.17.14.56" -set turn/denied-peer-ip/234567 "123::45" +sadd turn/realm/north.gov/allowed-peer-ip "172.17.13.200" "172.17.13.201" +sadd turn/realm/crinna.org/allowed-peer-ip "172.17.13.202" -set turn/denied-peer-ip/north.gov/1234567 "172.17.17.133-172.17.19.56" -set turn/denied-peer-ip/crinna.org/2345678 "123::77" - -set turn/allowed-peer-ip/345678 "172.17.13.200" -set turn/allowed-peer-ip/north.gov/345679 "172.17.13.201" -set turn/allowed-peer-ip/crinna.org/3456710 "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' From f96c40671bec46d1702906c92672c86e137b062b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 29 Oct 2014 06:17:18 +0000 Subject: [PATCH 297/805] TODO updated --- TODO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO b/TODO index 61237ca1..9f427caf 100644 --- a/TODO +++ b/TODO @@ -105,7 +105,7 @@ ================================================================== -1) Redis database structure cleaning. +nope ================================================================== From 106913f863866bfa56ce1fcf4930a0b3e059f963 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 30 Oct 2014 06:25:32 +0000 Subject: [PATCH 298/805] UFW debian file added --- debian/etc/ufw/applications.d/turnserver | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 debian/etc/ufw/applications.d/turnserver diff --git a/debian/etc/ufw/applications.d/turnserver b/debian/etc/ufw/applications.d/turnserver new file mode 100644 index 00000000..4513de3f --- /dev/null +++ b/debian/etc/ufw/applications.d/turnserver @@ -0,0 +1,4 @@ +[Turnserver] +title=Coturn Turnserver +description=Free open source implementation of TURN and STUN Server +ports=3478,3479,5349,5350,49152:65535/tcp|3478,3479,5349,5350,49152:65535/udp From f32216a0f3d45e3d10adfa288d58e77c4f8a80dd Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 30 Oct 2014 06:27:40 +0000 Subject: [PATCH 299/805] Changelog updated --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 9d309f98..5ff78954 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ Version 4.2.2.2 'Monza': - Black- and white- IP lists are divided per realm (the DB schema for those two tables changed); - Updated Redis database schema. + - Debian UFW file added (Issue 1 fixed). - TCP/TLS tests extended. - Relay RTCP sockets ports allocation fixed. - List of libraries cleaned. From 9f3d3338f4c18b65db0f208a03f03507c4b8eb92 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 30 Oct 2014 07:45:50 +0000 Subject: [PATCH 300/805] TODO updated --- TODO | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TODO b/TODO index 9f427caf..3364da85 100644 --- a/TODO +++ b/TODO @@ -11,6 +11,8 @@ Cygwin is supported. A "real" MS-Windows port would involve a usable GUI. +3) Move UFW stuff from the main tarball to the debian repository + ================================================================== ### II. DOCS ### From 3a9c23cf5c824f24792562f54283063a6460aba0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 31 Oct 2014 04:17:19 +0000 Subject: [PATCH 301/805] ufw file moved to debian repository --- debian/etc/ufw/applications.d/turnserver | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 debian/etc/ufw/applications.d/turnserver diff --git a/debian/etc/ufw/applications.d/turnserver b/debian/etc/ufw/applications.d/turnserver deleted file mode 100644 index 4513de3f..00000000 --- a/debian/etc/ufw/applications.d/turnserver +++ /dev/null @@ -1,4 +0,0 @@ -[Turnserver] -title=Coturn Turnserver -description=Free open source implementation of TURN and STUN Server -ports=3478,3479,5349,5350,49152:65535/tcp|3478,3479,5349,5350,49152:65535/udp From 52d4420b47c80175dc1ee3b47f84a1d070fb8031 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 31 Oct 2014 04:19:26 +0000 Subject: [PATCH 302/805] TODO updated --- TODO | 2 -- 1 file changed, 2 deletions(-) diff --git a/TODO b/TODO index 3364da85..9f427caf 100644 --- a/TODO +++ b/TODO @@ -11,8 +11,6 @@ Cygwin is supported. A "real" MS-Windows port would involve a usable GUI. -3) Move UFW stuff from the main tarball to the debian repository - ================================================================== ### II. DOCS ### From a854b94504bd0047f44d01ca9edc937312c21515 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 31 Oct 2014 05:27:09 +0000 Subject: [PATCH 303/805] typo fixed --- INSTALL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL b/INSTALL index 81ca3e9f..b4140dc0 100644 --- a/INSTALL +++ b/INSTALL @@ -774,7 +774,7 @@ CREATE TABLE turn_realm_option ( # oAuth key storage table. # CREATE TABLE oauth_key ( - kid varchar(128), /* + kid varchar(128), ikm_key varchar(256) default '', timestamp bigint default 0, lifetime integer default 0, From 202b9d6841735fde65f8ac691de9f092aff97532 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 3 Nov 2014 09:02:29 +0000 Subject: [PATCH 304/805] debug addition --- src/apps/uclient/startuclient.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index c60da2cd..6942d606 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -133,8 +133,8 @@ static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr) } break; } else { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot connect\n", - __FUNCTION__); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot connect: rc=%d, ctx=%d\n", + __FUNCTION__,rc,ctxtype); switch (SSL_get_error(ssl, rc)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: @@ -143,8 +143,7 @@ static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr) default: { char buf[1025]; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s (%d)\n", - ERR_error_string(ERR_get_error(), buf), SSL_get_error( - ssl, rc)); + ERR_error_string(ERR_get_error(), buf), SSL_get_error(ssl, rc)); exit(-1); } }; From 5ebdc93adcfbd0d931432a5abbdc385c122004c4 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 7 Nov 2014 07:47:30 +0000 Subject: [PATCH 305/805] client fixes --- src/apps/uclient/mainuclient.c | 1 - src/apps/uclient/startuclient.c | 32 +++++++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 4c2c4a3e..b69548f0 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -146,7 +146,6 @@ static char Usage[] = " -k Private key file (for secure connections only).\n" " -E CA file for server certificate verification, \n" " if the server certificate to be verified.\n" - " -F Cipher suite for TLS/DTLS. Default value is DEFAULT.\n" " -p TURN server port (Default: 3478 unsecure, 5349 secure).\n" " -n Number of messages to send (Default: 5).\n" " -d Local interface device (optional).\n" diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 6942d606..a68542f8 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -76,11 +76,12 @@ static int get_allocate_address_family(ioa_addr *relay_addr) { ///////////////////////////////////////// -static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr) +static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr, int *try_again) { int ctxtype = (int)(((unsigned long)random())%root_tls_ctx_num); + SSL *ssl; - SSL *ssl = SSL_NEW(root_tls_ctx[ctxtype]); + ssl = SSL_NEW(root_tls_ctx[ctxtype]); if(use_tcp) { SSL_set_fd(ssl, fd); @@ -144,6 +145,12 @@ static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr) char buf[1025]; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s (%d)\n", ERR_error_string(ERR_get_error(), buf), SSL_get_error(ssl, rc)); + if(ctxtype>0) { + if(try_again) { + *try_again = 1; + return NULL; + } + } exit(-1); } }; @@ -258,8 +265,13 @@ static int clnet_connect(uint16_t clnet_remote_port, const char *remote_address, } if (use_secure) { - clnet_info->ssl = tls_connect(clnet_info->fd, &remote_addr); + int try_again = 0; + clnet_info->ssl = tls_connect(clnet_info->fd, &remote_addr,&try_again); if (!clnet_info->ssl) { + if(try_again) { + close(clnet_fd); + goto start_socket; + } TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot SSL connect to remote addr\n", __FUNCTION__); exit(-1); } @@ -1521,7 +1533,11 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a void tcp_data_connect(app_ur_session *elem, u32bits cid) { - int clnet_fd = socket(elem->pinfo.remote_addr.ss.sa_family, SOCK_STREAM, 0); + int clnet_fd; + + again: + + clnet_fd = socket(elem->pinfo.remote_addr.ss.sa_family, SOCK_STREAM, 0); if (clnet_fd < 0) { perror("socket"); exit(-1); @@ -1593,8 +1609,14 @@ void tcp_data_connect(app_ur_session *elem, u32bits cid) } if(use_secure) { - elem->pinfo.tcp_conn[i]->tcp_data_ssl = tls_connect(elem->pinfo.tcp_conn[i]->tcp_data_fd, &(elem->pinfo.remote_addr)); + int try_again = 0; + elem->pinfo.tcp_conn[i]->tcp_data_ssl = tls_connect(elem->pinfo.tcp_conn[i]->tcp_data_fd, &(elem->pinfo.remote_addr),&try_again); if(!(elem->pinfo.tcp_conn[i]->tcp_data_ssl)) { + if(try_again) { + close(clnet_fd); + --elem->pinfo.tcp_conn_number; + goto again; + } TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot SSL connect to remote addr\n", __FUNCTION__); exit(-1); From 3c1c8420593281e59ae2b0b563077c330a78d390 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 7 Nov 2014 08:05:56 +0000 Subject: [PATCH 306/805] version bump --- ChangeLog | 4 ++++ TODO | 2 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/ns_turn_defs.h | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5ff78954..cded1cce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +11/07/2014 Oleg Moskalenko +Version 4.2.2.3 'Monza': + - TLS connection procedure improved in uclient test program. + 10/26/2014 Oleg Moskalenko Version 4.2.2.2 'Monza': - Black- and white- IP lists are divided per realm diff --git a/TODO b/TODO index 9f427caf..9b79ded5 100644 --- a/TODO +++ b/TODO @@ -105,7 +105,7 @@ ================================================================== -nope +1) uclient program upgrade to a full solution. ================================================================== diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index c4ea5977..2f445ae9 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.2.2.2 +TURNVERSION=4.2.2.3 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 561da6eb..ff1aca14 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.2.2.2 +Version: 4.2.2.3 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,6 +294,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Thu Nov 07 2014 Oleg Moskalenko + - Sync to 4.2.2.3 * Sun Oct 26 2014 Oleg Moskalenko - Sync to 4.2.2.2 * Sun Oct 05 2014 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index fc28026b..e755654f 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.2.2.2" +#define TURN_SERVER_VERSION "4.2.2.3" #define TURN_SERVER_VERSION_NAME "Monza" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 8f169e62bfe94921a0c97eb005481de216ba1dca Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 9 Nov 2014 08:10:39 +0000 Subject: [PATCH 307/805] working on uclient --- src/apps/uclient/startuclient.c | 213 ++++++++++++++------------------ src/apps/uclient/uclient.c | 108 +++++++++++++++- src/apps/uclient/uclient.h | 2 +- 3 files changed, 199 insertions(+), 124 deletions(-) diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index a68542f8..6b0b9c14 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -328,15 +328,15 @@ static int clnet_allocate(int verbose, app_ur_conn_info *clnet_info, ioa_addr *relay_addr, int af, - char *turn_addr, u16bits *turn_port, - stun_tid *in_tid, - stun_tid *out_tid) { + char *turn_addr, u16bits *turn_port) { int af_cycle = 0; int reopen_socket = 0; int allocate_finished; + stun_buffer request_message, response_message; + beg_allocate: allocate_finished=0; @@ -355,15 +355,14 @@ static int clnet_allocate(int verbose, reopen_socket = 0; } - stun_buffer message; - if(!in_tid && current_reservation_token) { + if(current_reservation_token) { af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT; } int af4 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4); int af6 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6); - if(!no_rtcp && !in_tid) { + if(!no_rtcp) { if (!never_allocate_rtcp && allocate_rtcp) { af4 = 0; af6 = 0; @@ -371,42 +370,34 @@ static int clnet_allocate(int verbose, } if(!dos) - stun_set_allocate_request(&message, UCLIENT_SESSION_LIFETIME, af4, af6, relay_transport, mobility); + stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME, af4, af6, relay_transport, mobility); else - stun_set_allocate_request(&message, UCLIENT_SESSION_LIFETIME/3, af4, af6, relay_transport, mobility); + stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME/3, af4, af6, relay_transport, mobility); if(bps) - stun_attr_add_bandwidth_str(message.buf, (size_t*)(&(message.len)), bps); - - if(in_tid) { - stun_tid_message_cpy(message.buf, in_tid); - } + stun_attr_add_bandwidth_str(request_message.buf, (size_t*)(&(request_message.len)), bps); if(dont_fragment) - stun_attr_add(&message, STUN_ATTRIBUTE_DONT_FRAGMENT, NULL, 0); - if(!no_rtcp && !in_tid) { + stun_attr_add(&request_message, STUN_ATTRIBUTE_DONT_FRAGMENT, NULL, 0); + if(!no_rtcp) { if (!never_allocate_rtcp && allocate_rtcp) { uint64_t reservation_token = ioa_ntoh64(current_reservation_token); - stun_attr_add(&message, STUN_ATTRIBUTE_RESERVATION_TOKEN, + stun_attr_add(&request_message, STUN_ATTRIBUTE_RESERVATION_TOKEN, (char*) (&reservation_token), 8); } else { - stun_attr_add_even_port(&message, 1); + stun_attr_add_even_port(&request_message, 1); } } - add_origin(&message); + add_origin(&request_message); - if(add_integrity(clnet_info, &message)<0) return -1; + if(add_integrity(clnet_info, &request_message)<0) return -1; - stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); - - if(out_tid) { - stun_tid_from_message_str(message.buf, (size_t)message.len, out_tid); - } + stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len)); while (!allocate_sent) { - int len = send_buffer(clnet_info, &message,0,0); + int len = send_buffer(clnet_info, &request_message,0,0); if (len > 0) { if (verbose) { @@ -426,25 +417,24 @@ static int clnet_allocate(int verbose, ////////allocate response==>> { int allocate_received = 0; - stun_buffer message; while (!allocate_received) { - int len = recv_buffer(clnet_info, &message, 1, 0); + int len = recv_buffer(clnet_info, &response_message, 1, NULL, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "allocate response received: \n"); } - message.len = len; + response_message.len = len; int err_code = 0; u08bits err_msg[129]; - if (stun_is_success_response(&message)) { + if (stun_is_success_response(&response_message)) { allocate_received = 1; allocate_finished = 1; if(clnet_info->nonce[0] || use_short_term) { - if(check_integrity(clnet_info, &message)<0) + if(check_integrity(clnet_info, &response_message)<0) return -1; } @@ -454,13 +444,13 @@ static int clnet_allocate(int verbose, { int found = 0; - stun_attr_ref sar = stun_attr_get_first(&message); + stun_attr_ref sar = stun_attr_get_first(&response_message); while (sar) { int attr_type = stun_attr_get_type(sar); if(attr_type == STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS) { - if (stun_attr_get_addr(&message, sar, relay_addr, NULL) < 0) { + if (stun_attr_get_addr(&response_message, sar, relay_addr, NULL) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: !!!: relay addr cannot be received (1)\n", __FUNCTION__); @@ -491,7 +481,7 @@ static int clnet_allocate(int verbose, } } - sar = stun_attr_get_next(&message,sar); + sar = stun_attr_get_next(&response_message,sar); } if(!found) { @@ -503,16 +493,16 @@ static int clnet_allocate(int verbose, } stun_attr_ref rt_sar = stun_attr_get_first_by_type( - &message, STUN_ATTRIBUTE_RESERVATION_TOKEN); + &response_message, STUN_ATTRIBUTE_RESERVATION_TOKEN); uint64_t rtv = stun_attr_get_reservation_token_value(rt_sar); current_reservation_token = rtv; if (verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: rtv=%llu\n", __FUNCTION__, (long long unsigned int)rtv); - read_mobility_ticket(clnet_info, &message); + read_mobility_ticket(clnet_info, &response_message); - } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, + } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { @@ -521,7 +511,7 @@ static int clnet_allocate(int verbose, recalculate_restapi_hmac(); } goto beg_allocate; - } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { + } 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; @@ -533,12 +523,12 @@ static int clnet_allocate(int verbose, if(err_code == 300) { if(clnet_info->nonce[0] || use_short_term) { - if(check_integrity(clnet_info, &message)<0) + if(check_integrity(clnet_info, &response_message)<0) return -1; } ioa_addr alternate_server; - if(stun_attr_get_first_addr(&message, STUN_ATTRIBUTE_ALTERNATE_SERVER, &alternate_server, NULL)==-1) { + if(stun_attr_get_first_addr(&response_message, STUN_ATTRIBUTE_ALTERNATE_SERVER, &alternate_server, NULL)==-1) { //error } else if(turn_addr && turn_port){ addr_to_string_no_port(&alternate_server, (u08bits*)turn_addr); @@ -582,9 +572,7 @@ static int clnet_allocate(int verbose, exit(-1); } - if(!in_tid) { - allocate_rtcp = !allocate_rtcp; - } + allocate_rtcp = !allocate_rtcp; if (1) { @@ -643,24 +631,23 @@ static int clnet_allocate(int verbose, { int refresh_sent = 0; - stun_buffer message; - stun_init_request(STUN_METHOD_REFRESH, &message); + stun_init_request(STUN_METHOD_REFRESH, &request_message); uint32_t lt = htonl(UCLIENT_SESSION_LIFETIME); - stun_attr_add(&message, STUN_ATTRIBUTE_LIFETIME, (const char*) <, 4); + stun_attr_add(&request_message, STUN_ATTRIBUTE_LIFETIME, (const char*) <, 4); if(clnet_info->s_mobile_id[0]) { - stun_attr_add(&message, STUN_ATTRIBUTE_MOBILITY_TICKET, (const char*)clnet_info->s_mobile_id, strlen(clnet_info->s_mobile_id)); + stun_attr_add(&request_message, STUN_ATTRIBUTE_MOBILITY_TICKET, (const char*)clnet_info->s_mobile_id, strlen(clnet_info->s_mobile_id)); } - add_origin(&message); + add_origin(&request_message); - if(add_integrity(clnet_info, &message)<0) return -1; + if(add_integrity(clnet_info, &request_message)<0) return -1; - stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); + stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len)); while (!refresh_sent) { - int len = send_buffer(clnet_info, &message, 0,0); + int len = send_buffer(clnet_info, &request_message, 0,0); if (len > 0) { if (verbose) { @@ -670,7 +657,7 @@ static int clnet_allocate(int verbose, if(clnet_info->s_mobile_id[0]) { usleep(10000); - send_buffer(clnet_info, &message, 0,0); + send_buffer(clnet_info, &request_message, 0,0); } } else { perror("send"); @@ -684,13 +671,12 @@ static int clnet_allocate(int verbose, ////////refresh response==>> { int refresh_received = 0; - stun_buffer message; while (!refresh_received) { - int len = recv_buffer(clnet_info, &message, 1, 0); + int len = recv_buffer(clnet_info, &response_message, 1, 0, &request_message); if(clnet_info->s_mobile_id[0]) { - len = recv_buffer(clnet_info, &message, 1, 0); + len = recv_buffer(clnet_info, &response_message, 1, 0, &request_message); } if (len > 0) { @@ -698,16 +684,16 @@ static int clnet_allocate(int verbose, TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "refresh response received: \n"); } - message.len = len; + response_message.len = len; int err_code = 0; u08bits err_msg[129]; - if (stun_is_success_response(&message)) { - read_mobility_ticket(clnet_info, &message); + if (stun_is_success_response(&response_message)) { + read_mobility_ticket(clnet_info, &response_message); refresh_received = 1; if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); } - } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, + } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { @@ -716,7 +702,7 @@ static int clnet_allocate(int verbose, recalculate_restapi_hmac(); } goto beg_refresh; - } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { + } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { refresh_received = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "error %d (%s)\n", err_code,(char*)err_msg); @@ -740,28 +726,28 @@ static int clnet_allocate(int verbose, static int turn_channel_bind(int verbose, uint16_t *chn, app_ur_conn_info *clnet_info, ioa_addr *peer_addr) { + stun_buffer request_message, response_message; + beg_bind: { int cb_sent = 0; - stun_buffer message; - if(negative_test) { - *chn = stun_set_channel_bind_request(&message, peer_addr, (u16bits)random()); + *chn = stun_set_channel_bind_request(&request_message, peer_addr, (u16bits)random()); } else { - *chn = stun_set_channel_bind_request(&message, peer_addr, *chn); + *chn = stun_set_channel_bind_request(&request_message, peer_addr, *chn); } - add_origin(&message); + add_origin(&request_message); - if(add_integrity(clnet_info, &message)<0) return -1; + if(add_integrity(clnet_info, &request_message)<0) return -1; - stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); + stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len)); while (!cb_sent) { - int len = send_buffer(clnet_info, &message, 0,0); + int len = send_buffer(clnet_info, &request_message, 0,0); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "channel bind sent\n"); @@ -782,10 +768,9 @@ static int turn_channel_bind(int verbose, uint16_t *chn, { int cb_received = 0; - stun_buffer message; while (!cb_received) { - int len = recv_buffer(clnet_info, &message, 1, 0); + int len = recv_buffer(clnet_info, &response_message, 1, NULL, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, @@ -793,12 +778,12 @@ static int turn_channel_bind(int verbose, uint16_t *chn, } int err_code = 0; u08bits err_msg[129]; - if (stun_is_success_response(&message)) { + if (stun_is_success_response(&response_message)) { cb_received = 1; if(clnet_info->nonce[0] || use_short_term) { - if(check_integrity(clnet_info, &message)<0) + if(check_integrity(clnet_info, &response_message)<0) return -1; } @@ -806,7 +791,7 @@ static int turn_channel_bind(int verbose, uint16_t *chn, TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success: 0x%x\n", (int) (*chn)); } - } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, + } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { @@ -815,7 +800,7 @@ static int turn_channel_bind(int verbose, uint16_t *chn, recalculate_restapi_hmac(); } goto beg_bind; - } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { + } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { cb_received = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "channel bind: error %d (%s)\n", err_code,(char*)err_msg); @@ -847,30 +832,30 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, addr_to_string(peer_addr,(u08bits*)saddr); } + stun_buffer request_message, response_message; + beg_cp: { int cp_sent = 0; - stun_buffer message; - - stun_init_request(STUN_METHOD_CREATE_PERMISSION, &message); + stun_init_request(STUN_METHOD_CREATE_PERMISSION, &request_message); { int addrindex; for(addrindex=0;addrindex 0) { if (verbose) { @@ -892,10 +877,9 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, { int cp_received = 0; - stun_buffer message; while (!cp_received) { - int len = recv_buffer(clnet_info, &message, 1, 0); + int len = recv_buffer(clnet_info, &response_message, 1, NULL, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, @@ -903,19 +887,19 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, } int err_code = 0; u08bits err_msg[129]; - if (stun_is_success_response(&message)) { + if (stun_is_success_response(&response_message)) { cp_received = 1; if(clnet_info->nonce[0] || use_short_term) { - if(check_integrity(clnet_info, &message)<0) + if(check_integrity(clnet_info, &response_message)<0) return -1; } if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); } - } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, + } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { @@ -924,7 +908,7 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, recalculate_restapi_hmac(); } goto beg_cp; - } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { + } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { cp_received = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "create permission error %d (%s)\n", err_code,(char*)err_msg); @@ -971,9 +955,7 @@ int start_connection(uint16_t clnet_remote_port0, char remote_address[1025]; STRCPY(remote_address,remote_address0); - stun_tid tid; - - clnet_allocate(verbose, clnet_info_probe, &relay_addr, default_address_family, remote_address, &clnet_remote_port,NULL,NULL); + clnet_allocate(verbose, clnet_info_probe, &relay_addr, default_address_family, remote_address, &clnet_remote_port); /* Real: */ @@ -993,20 +975,15 @@ int start_connection(uint16_t clnet_remote_port0, } int af = default_address_family ? default_address_family : get_allocate_address_family(&peer_addr); - if (clnet_allocate(verbose, clnet_info, &relay_addr, af, NULL,NULL,NULL,&tid) < 0) { + if (clnet_allocate(verbose, clnet_info, &relay_addr, af, NULL,NULL) < 0) { exit(-1); } - //strcpy((char*)g_uname,"qqq"); - //if (clnet_allocate(verbose, clnet_info, &relay_addr, af, NULL,NULL,&tid,NULL) < 0) { - // exit(-1); - //} - if(rare_event()) return 0; if(!no_rtcp) { af = default_address_family ? default_address_family : get_allocate_address_family(&peer_addr_rtcp); - if (clnet_allocate(verbose, clnet_info_rtcp, &relay_addr_rtcp, af,NULL,NULL,NULL,NULL) < 0) { + if (clnet_allocate(verbose, clnet_info_rtcp, &relay_addr_rtcp, af,NULL,NULL) < 0) { exit(-1); } if(rare_event()) return 0; @@ -1193,7 +1170,7 @@ int start_c2c_connection(uint16_t clnet_remote_port0, char remote_address[1025]; STRCPY(remote_address,remote_address0); - clnet_allocate(verbose, clnet_info_probe, &relay_addr1, default_address_family, remote_address, &clnet_remote_port,NULL,NULL); + clnet_allocate(verbose, clnet_info_probe, &relay_addr1, default_address_family, remote_address, &clnet_remote_port); if(rare_event()) return 0; @@ -1226,7 +1203,7 @@ int start_c2c_connection(uint16_t clnet_remote_port0, if(!no_rtcp) { - if (clnet_allocate(verbose, clnet_info1, &relay_addr1, default_address_family,NULL,NULL,NULL,NULL) + if (clnet_allocate(verbose, clnet_info1, &relay_addr1, default_address_family,NULL,NULL) < 0) { exit(-1); } @@ -1234,13 +1211,13 @@ int start_c2c_connection(uint16_t clnet_remote_port0, if(rare_event()) return 0; if (clnet_allocate(verbose, clnet_info1_rtcp, - &relay_addr1_rtcp, default_address_family,NULL,NULL,NULL,NULL) < 0) { + &relay_addr1_rtcp, default_address_family,NULL,NULL) < 0) { exit(-1); } if(rare_event()) return 0; - if (clnet_allocate(verbose, clnet_info2, &relay_addr2, default_address_family,NULL,NULL,NULL,NULL) + if (clnet_allocate(verbose, clnet_info2, &relay_addr2, default_address_family,NULL,NULL) < 0) { exit(-1); } @@ -1248,20 +1225,20 @@ int start_c2c_connection(uint16_t clnet_remote_port0, if(rare_event()) return 0; if (clnet_allocate(verbose, clnet_info2_rtcp, - &relay_addr2_rtcp, default_address_family,NULL,NULL,NULL,NULL) < 0) { + &relay_addr2_rtcp, default_address_family,NULL,NULL) < 0) { exit(-1); } if(rare_event()) return 0; } else { - if (clnet_allocate(verbose, clnet_info1, &relay_addr1, default_address_family,NULL,NULL,NULL,NULL) + if (clnet_allocate(verbose, clnet_info1, &relay_addr1, default_address_family,NULL,NULL) < 0) { exit(-1); } if(rare_event()) return 0; if(!(clnet_info2->is_peer)) { - if (clnet_allocate(verbose, clnet_info2, &relay_addr2, default_address_family,NULL,NULL,NULL,NULL) < 0) { + if (clnet_allocate(verbose, clnet_info2, &relay_addr2, default_address_family,NULL,NULL) < 0) { exit(-1); } if(rare_event()) return 0; @@ -1432,27 +1409,28 @@ int turn_tcp_connect(int verbose, app_ur_conn_info *clnet_info, ioa_addr *peer_a static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, app_tcp_conn_info *atc, int errorOK) { + stun_buffer request_message, response_message; + beg_cb: { int cb_sent = 0; - stun_buffer message; u32bits cid = atc->cid; - stun_init_request(STUN_METHOD_CONNECTION_BIND, &message); + stun_init_request(STUN_METHOD_CONNECTION_BIND, &request_message); - stun_attr_add(&message, STUN_ATTRIBUTE_CONNECTION_ID, (const s08bits*)&cid,4); + stun_attr_add(&request_message, STUN_ATTRIBUTE_CONNECTION_ID, (const s08bits*)&cid,4); - add_origin(&message); + add_origin(&request_message); - if(add_integrity(clnet_info, &message)<0) return -1; + if(add_integrity(clnet_info, &request_message)<0) return -1; - stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); + stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len)); while (!cb_sent) { - int len = send_buffer(clnet_info, &message, 1, atc); + int len = send_buffer(clnet_info, &request_message, 1, atc); if (len > 0) { if (verbose) { @@ -1476,10 +1454,9 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a { int cb_received = 0; - stun_buffer message; while (!cb_received) { - int len = recv_buffer(clnet_info, &message, 1, atc); + int len = recv_buffer(clnet_info, &response_message, 1, atc, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, @@ -1487,21 +1464,21 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a } int err_code = 0; u08bits err_msg[129]; - if (stun_is_success_response(&message)) { + if (stun_is_success_response(&response_message)) { if(clnet_info->nonce[0] || use_short_term) { - if(check_integrity(clnet_info, &message)<0) + if(check_integrity(clnet_info, &response_message)<0) return -1; } - if(stun_get_method(&message)!=STUN_METHOD_CONNECTION_BIND) + if(stun_get_method(&response_message)!=STUN_METHOD_CONNECTION_BIND) continue; cb_received = 1; if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); } atc->tcp_data_bound = 1; - } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, + } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { @@ -1510,7 +1487,7 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a recalculate_restapi_hmac(); } goto beg_cb; - } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { + } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { cb_received = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "connection bind error %d (%s)\n", err_code,(char*)err_msg); diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index d7aa0db5..6b3010f7 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -302,11 +302,18 @@ int send_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int data_con return ret; } -int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, - app_tcp_conn_info *atc) { +int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, app_tcp_conn_info *atc, stun_buffer* request_message) { int rc = 0; + stun_tid tid; + u16bits method = 0; + + if(request_message) { + stun_tid_from_message(request_message, &tid); + method = stun_get_method(request_message); + } + ioa_socket_raw fd = clnet_info->fd; if (atc) fd = atc->tcp_data_fd; @@ -315,6 +322,8 @@ int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, if (atc) ssl = atc->tcp_data_ssl; + recv_again: + if (!use_secure && !use_tcp && fd >= 0) { /* Plain UDP */ @@ -331,9 +340,9 @@ int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, message->len = rc; - } else if (use_secure && ssl && !(clnet_info->broken)) { + } else if (use_secure && !use_tcp && ssl && !(clnet_info->broken)) { - /* TLS/DTLS */ + /* DTLS */ int message_received = 0; int cycle = 0; @@ -400,6 +409,74 @@ int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, } } + } else if (use_secure && use_tcp && ssl && !(clnet_info->broken)) { + + /* TLS*/ + + int message_received = 0; + int cycle = 0; + while (!message_received && cycle++ < 100) { + + if (SSL_get_shutdown(ssl)) + return -1; + rc = 0; + do { + rc = SSL_read(ssl, message->buf, sizeof(message->buf) - 1); + if (rc < 0 && errno == EAGAIN && sync) + continue; + } while (rc < 0 && (errno == EINTR)); + + if (rc > 0) { + + if (clnet_verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "response received: size=%d\n", rc); + } + message->len = rc; + message_received = 1; + + } else { + + int sslerr = SSL_get_error(ssl, rc); + + switch (sslerr) { + case SSL_ERROR_NONE: + /* Try again ? */ + break; + case SSL_ERROR_WANT_WRITE: + /* Just try again later */ + break; + case SSL_ERROR_WANT_READ: + /* continue with reading */ + break; + case SSL_ERROR_ZERO_RETURN: + /* Try again */ + break; + case SSL_ERROR_SYSCALL: + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "Socket read error 111.999: \n"); + if (handle_socket_error()) + break; + case SSL_ERROR_SSL: { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SSL write error: \n"); + char buf[1024]; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s (%d)\n", + ERR_error_string(ERR_get_error(), buf), + SSL_get_error(ssl, rc)); + } + default: + clnet_info->broken = 1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "Unexpected error while reading: rc=%d, sslerr=%d\n", + rc, sslerr); + return -1; + } + + if (!sync) + break; + } + } + } else if (!use_secure && use_tcp && fd >= 0) { /* Plain TCP */ @@ -465,6 +542,27 @@ int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, } } + if(rc>0) { + if(request_message) { + + stun_tid recv_tid; + u16bits recv_method = 0; + + stun_tid_from_message(message, &recv_tid); + recv_method = stun_get_method(message); + + if(method != recv_method) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Received wrong response method: 0x%x, expected 0x%x; trying again...\n",(unsigned int)recv_method,(unsigned int)method); + goto recv_again; + } + + if(memcmp(tid.tsx_id,recv_tid.tsx_id,STUN_TID_SIZE)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Received wrong response tid; trying again...\n"); + goto recv_again; + } + } + } + return rc; } @@ -488,7 +586,7 @@ static int client_read(app_ur_session *elem, int is_tcp_data, app_tcp_conn_info TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "before read ...\n"); } - rc = recv_buffer(clnet_info, &(elem->in_buffer), 0, atc); + rc = recv_buffer(clnet_info, &(elem->in_buffer), 0, atc, NULL); if (clnet_verbose && verbose_packets) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "read %d bytes\n", (int) rc); diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index ea3958a1..d053afc9 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -99,7 +99,7 @@ void start_mclient(const char *remote_address, int port, int messagenumber, int mclient); int send_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int data_connection, app_tcp_conn_info *atc); -int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, app_tcp_conn_info *atc); +int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, app_tcp_conn_info *atc, stun_buffer* request_message); void client_input_handler(evutil_socket_t fd, short what, void* arg); From 61947e8dbd8dbeaf60c48965ac71df76a6052940 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 9 Nov 2014 09:22:24 +0000 Subject: [PATCH 308/805] Re-transmission implemented in the uclient. --- src/apps/uclient/startuclient.c | 12 +++---- src/apps/uclient/uclient.c | 64 ++++++++++++++++++++++++++++----- src/apps/uclient/uclient.h | 2 +- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 6b0b9c14..afe0b660 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -419,7 +419,7 @@ static int clnet_allocate(int verbose, int allocate_received = 0; while (!allocate_received) { - int len = recv_buffer(clnet_info, &response_message, 1, NULL, &request_message); + int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); if (len > 0) { if (verbose) { @@ -673,10 +673,10 @@ static int clnet_allocate(int verbose, int refresh_received = 0; while (!refresh_received) { - int len = recv_buffer(clnet_info, &response_message, 1, 0, &request_message); + int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); if(clnet_info->s_mobile_id[0]) { - len = recv_buffer(clnet_info, &response_message, 1, 0, &request_message); + len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); } if (len > 0) { @@ -770,7 +770,7 @@ static int turn_channel_bind(int verbose, uint16_t *chn, int cb_received = 0; while (!cb_received) { - int len = recv_buffer(clnet_info, &response_message, 1, NULL, &request_message); + int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, @@ -879,7 +879,7 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, int cp_received = 0; while (!cp_received) { - int len = recv_buffer(clnet_info, &response_message, 1, NULL, &request_message); + int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, @@ -1456,7 +1456,7 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a int cb_received = 0; while (!cb_received) { - int len = recv_buffer(clnet_info, &response_message, 1, atc, &request_message); + int len = recv_buffer(clnet_info, &response_message, 1, 1, atc, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 6b3010f7..1ba65194 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -40,6 +40,8 @@ #include #include +#include + static int verbose_packets=0; static size_t current_clients_number = 0; @@ -69,6 +71,8 @@ static app_ur_session** elems = NULL; #define SLEEP_INTERVAL (234) +#define MAX_LISTENING_CYCLE_NUMBER (7) + int RTP_PACKET_INTERVAL = 20; static inline s64bits time_minus(u64bits t1, u64bits t2) { @@ -302,7 +306,33 @@ int send_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int data_con return ret; } -int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, app_tcp_conn_info *atc, stun_buffer* request_message) { +static int wait_fd(int fd, unsigned int cycle) { + + fd_set fds; + FD_ZERO(&fds); + FD_SET(fd,&fds); + + if(dos && cycle==0) + return 0; + + struct timeval timeout = {0,0}; + if(cycle == 0) + timeout.tv_usec = 500000; + else { + timeout.tv_sec = 1; + while(--cycle) timeout.tv_sec = timeout.tv_sec + timeout.tv_sec; + } + + int rc = 0; + + do { + rc = select(fd+1,&fds,NULL,NULL,&timeout); + } while((rc<0) && (errno == EINTR)); + + return rc; +} + +int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, int data_connection, app_tcp_conn_info *atc, stun_buffer* request_message) { int rc = 0; @@ -324,6 +354,22 @@ int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, ap recv_again: + if(!use_tcp && sync && request_message && (fd>=0)) { + + unsigned int cycle = 0; + while(cycle < MAX_LISTENING_CYCLE_NUMBER) { + int serc = wait_fd(fd,cycle); + if(serc>0) + break; + if(serc<0) { + return -1; + } + if(send_buffer(clnet_info, request_message, data_connection, atc)<=0) + return -1; + ++cycle; + } + } + if (!use_secure && !use_tcp && fd >= 0) { /* Plain UDP */ @@ -586,7 +632,7 @@ static int client_read(app_ur_session *elem, int is_tcp_data, app_tcp_conn_info TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "before read ...\n"); } - rc = recv_buffer(clnet_info, &(elem->in_buffer), 0, atc, NULL); + rc = recv_buffer(clnet_info, &(elem->in_buffer), 0, is_tcp_data, atc, NULL); if (clnet_verbose && verbose_packets) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "read %d bytes\n", (int) rc); @@ -890,13 +936,13 @@ void client_input_handler(evutil_socket_t fd, short what, void* arg) { if(elem->pinfo.tcp_conn) { int i = 0; for(i=0;i<(int)(elem->pinfo.tcp_conn_number);++i) { - if(elem->pinfo.tcp_conn[i]) { - if((fd==elem->pinfo.tcp_conn[i]->tcp_data_fd) && (elem->pinfo.tcp_conn[i]->tcp_data_bound)) { - is_tcp_data = 1; - atc = elem->pinfo.tcp_conn[i]; - break; - } - } + if(elem->pinfo.tcp_conn[i]) { + if((fd==elem->pinfo.tcp_conn[i]->tcp_data_fd) && (elem->pinfo.tcp_conn[i]->tcp_data_bound)) { + is_tcp_data = 1; + atc = elem->pinfo.tcp_conn[i]; + break; + } + } } } int rc = client_read(elem, is_tcp_data, atc); diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index d053afc9..43ff021d 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -99,7 +99,7 @@ void start_mclient(const char *remote_address, int port, int messagenumber, int mclient); int send_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int data_connection, app_tcp_conn_info *atc); -int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, app_tcp_conn_info *atc, stun_buffer* request_message); +int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, int data_connection, app_tcp_conn_info *atc, stun_buffer* request_message); void client_input_handler(evutil_socket_t fd, short what, void* arg); From 9ee8788e16a5f438b847959ff8e2a49445ac4fd8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 9 Nov 2014 09:25:25 +0000 Subject: [PATCH 309/805] docs updated --- ChangeLog | 1 + README.turnutils | 7 ------- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 4 ++-- man/man1/turnutils.1 | 9 +-------- 5 files changed, 5 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index cded1cce..4fdd7157 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 11/07/2014 Oleg Moskalenko Version 4.2.2.3 'Monza': + - Request re-transmission implemented in uclient test program. - TLS connection procedure improved in uclient test program. 10/26/2014 Oleg Moskalenko diff --git a/README.turnutils b/README.turnutils index 618800b4..106983e6 100644 --- a/README.turnutils +++ b/README.turnutils @@ -8,13 +8,6 @@ for testing and for setting up the TURN server. The compiled binary image of this program is located in bin/ sub-directory. -WARNING: the turnutils_uclient program is a primitive client application. -It does not implement the re-transmission pattern that is necessary for -a correct TURN client implementation. In TURN, the retransmission burden -is lying almost entirely on the client application. We provide the messaging -functionality in the client library, but the client must implement -the correct Networking IO processing in the client program code. - 2. turnutils_peer: a simple stateless UDP-only "echo" server, to be used as the final server in relay pattern ("peer"). For every incoming UDP packet, it simply echoes it back. diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index e47caf77..41688d14 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "28 September 2014" "" "" +.TH TURN 1 "09 November 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index cd6d82f7..2f921a98 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "28 September 2014" "" "" +.TH TURN 1 "09 November 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -277,7 +277,7 @@ it does not make much sense with the short\-term mechanism. .TP .B \fB\-\-oauth\fP -Support oAuth authentication. +Support oAuth authentication, as in the third\-party TURN specs document. .TP .B \fB\-\-dh566\fP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index ec39407f..260ca5f7 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "28 September 2014" "" "" +.TH TURN 1 "09 November 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -11,13 +11,6 @@ for testing and for setting up the TURN server. (this program is provided for the testing purposes only !) The compiled binary image of this program is located in bin/ sub\-directory. -.PP -WARNING: the \fIturnutils_uclient\fP program is a primitive client application. -It does not implement the re\-transmission pattern that is necessary for -a correct TURN client implementation. In TURN, the retransmission burden -is lying almost entirely on the client application. We provide the messaging -functionality in the client library, but the client must implement -the correct Networking IO processing in the client program code. .TP .B 2. From 1ab7628cc1e8fcaae1cdda8b59eaabb06a3f9a0b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 9 Nov 2014 10:30:26 +0000 Subject: [PATCH 310/805] cosmetics --- TODO | 2 +- src/apps/uclient/mainuclient.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/TODO b/TODO index 9b79ded5..182c3a20 100644 --- a/TODO +++ b/TODO @@ -105,7 +105,7 @@ ================================================================== -1) uclient program upgrade to a full solution. +none ================================================================== diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index b69548f0..164fdaa6 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -187,7 +187,7 @@ void recalculate_restapi_hmac(void) { g_upwd[pwd_length] = 0; } } - free(pwd); + turn_free(pwd,strlen(pwd)+1); } } } From 40ec5fae5bb440c46a9a57c9ecfbef4f8d9f5ab2 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 9 Nov 2014 23:44:32 +0000 Subject: [PATCH 311/805] working on uclient --- ChangeLog | 2 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +-- src/apps/uclient/uclient.c | 62 ++++++++++++++++++++++++++------------ src/ns_turn_defs.h | 2 +- 5 files changed, 48 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4fdd7157..e436ef3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ 11/07/2014 Oleg Moskalenko -Version 4.2.2.3 'Monza': +Version 4.2.3.1 'Monza': - Request re-transmission implemented in uclient test program. - TLS connection procedure improved in uclient test program. diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 2f445ae9..d44c2d13 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.2.2.3 +TURNVERSION=4.2.3.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index ff1aca14..5cea7dba 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.2.2.3 +Version: 4.2.3.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -295,7 +295,7 @@ fi %changelog * Thu Nov 07 2014 Oleg Moskalenko - - Sync to 4.2.2.3 + - Sync to 4.2.3.1 * Sun Oct 26 2014 Oleg Moskalenko - Sync to 4.2.2.2 * Sun Oct 05 2014 Oleg Moskalenko diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 1ba65194..7403b880 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -308,28 +308,52 @@ int send_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int data_con static int wait_fd(int fd, unsigned int cycle) { - fd_set fds; - FD_ZERO(&fds); - FD_SET(fd,&fds); + if(fd>=(int)FD_SETSIZE) { + return 1; + } else { + fd_set fds; + FD_ZERO(&fds); + FD_SET(fd,&fds); - if(dos && cycle==0) - return 0; + if(dos && cycle==0) + return 0; - struct timeval timeout = {0,0}; - if(cycle == 0) - timeout.tv_usec = 500000; - else { - timeout.tv_sec = 1; - while(--cycle) timeout.tv_sec = timeout.tv_sec + timeout.tv_sec; + struct timeval start_time; + struct timeval ctime; + gettimeofday(&start_time,NULL); + + ctime.tv_sec = start_time.tv_sec; + ctime.tv_usec = start_time.tv_usec; + + int rc = 0; + + do { + struct timeval timeout = {0,0}; + if(cycle == 0) { + timeout.tv_usec = 500000; + } else { + + timeout.tv_sec = 1; + while(--cycle) timeout.tv_sec = timeout.tv_sec + timeout.tv_sec; + + if(ctime.tv_sec > start_time.tv_sec) { + if(ctime.tv_sec >= start_time.tv_sec + timeout.tv_sec) { + break; + } else { + timeout.tv_sec -= (ctime.tv_sec - start_time.tv_sec); + } + } + } + rc = select(fd+1,&fds,NULL,NULL,&timeout); + if((rc<0) && (errno == EINTR)) { + gettimeofday(&ctime,NULL); + } else { + break; + } + } while(1); + + return rc; } - - int rc = 0; - - do { - rc = select(fd+1,&fds,NULL,NULL,&timeout); - } while((rc<0) && (errno == EINTR)); - - return rc; } int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, int data_connection, app_tcp_conn_info *atc, stun_buffer* request_message) { diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index e755654f..482b856c 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.2.2.3" +#define TURN_SERVER_VERSION "4.2.3.1" #define TURN_SERVER_VERSION_NAME "Monza" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 0e208b06eb76fc2ff02fc88e28f89272b983d200 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 11 Nov 2014 07:01:14 +0000 Subject: [PATCH 312/805] working on uclient TLS --- src/apps/uclient/startuclient.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index afe0b660..3e9fe952 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -43,6 +43,7 @@ #define MAX_CONNECT_EFFORTS (77) #define DTLS_MAX_CONNECT_TIMEOUT (30) +#define MAX_TLS_CYCLES (32) #define EXTRA_CREATE_PERMS (25) static uint64_t current_reservation_token = 0; @@ -76,7 +77,7 @@ static int get_allocate_address_family(ioa_addr *relay_addr) { ///////////////////////////////////////// -static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr, int *try_again) +static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr, int *try_again, int connect_cycle) { int ctxtype = (int)(((unsigned long)random())%root_tls_ctx_num); SSL *ssl; @@ -122,6 +123,7 @@ static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr, int *try_again do { rc = SSL_connect(ssl); } while (rc < 0 && errno == EINTR); + int orig_errno = errno; if (rc > 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: client session connected with cipher %s, method=%s\n",__FUNCTION__, SSL_get_cipher(ssl),turn_get_ssl_method(ssl,NULL)); @@ -136,6 +138,7 @@ static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr, int *try_again } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot connect: rc=%d, ctx=%d\n", __FUNCTION__,rc,ctxtype); + switch (SSL_get_error(ssl, rc)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: @@ -143,10 +146,11 @@ static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr, int *try_again continue; default: { char buf[1025]; - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s (%d)\n", - ERR_error_string(ERR_get_error(), buf), SSL_get_error(ssl, rc)); - if(ctxtype>0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "errno=%d, err=%d, %s (%d)\n",orig_errno, + (int)ERR_get_error(), ERR_error_string(ERR_get_error(), buf), (int)SSL_get_error(ssl, rc)); + if((orig_errno == ECONNRESET) && (connect_cyclessl = tls_connect(clnet_info->fd, &remote_addr,&try_again); + clnet_info->ssl = tls_connect(clnet_info->fd, &remote_addr,&try_again,connect_cycle++); if (!clnet_info->ssl) { if(try_again) { - close(clnet_fd); goto start_socket; } TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot SSL connect to remote addr\n", __FUNCTION__); @@ -1511,6 +1515,7 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a void tcp_data_connect(app_ur_session *elem, u32bits cid) { int clnet_fd; + int connect_cycle = 0; again: @@ -1587,10 +1592,9 @@ void tcp_data_connect(app_ur_session *elem, u32bits cid) if(use_secure) { int try_again = 0; - elem->pinfo.tcp_conn[i]->tcp_data_ssl = tls_connect(elem->pinfo.tcp_conn[i]->tcp_data_fd, &(elem->pinfo.remote_addr),&try_again); + elem->pinfo.tcp_conn[i]->tcp_data_ssl = tls_connect(elem->pinfo.tcp_conn[i]->tcp_data_fd, &(elem->pinfo.remote_addr),&try_again, connect_cycle++); if(!(elem->pinfo.tcp_conn[i]->tcp_data_ssl)) { if(try_again) { - close(clnet_fd); --elem->pinfo.tcp_conn_number; goto again; } From 380cc7580f4bcbdbeeb899e0e641ffae9ca3f416 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 11 Nov 2014 07:21:47 +0000 Subject: [PATCH 313/805] working on TLS uclient --- src/apps/uclient/startuclient.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 3e9fe952..6c0d366d 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -148,7 +148,7 @@ static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr, int *try_again char buf[1025]; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "errno=%d, err=%d, %s (%d)\n",orig_errno, (int)ERR_get_error(), ERR_error_string(ERR_get_error(), buf), (int)SSL_get_error(ssl, rc)); - if((orig_errno == ECONNRESET) && (connect_cycle Date: Tue, 11 Nov 2014 07:32:36 +0000 Subject: [PATCH 314/805] version bump --- ChangeLog | 4 ++++ rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/ns_turn_defs.h | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index e436ef3c..0e9c1177 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +11/10/2014 Oleg Moskalenko +Version 4.2.3.2 'Monza': + - TLS connection procedure improved in uclient test program. + 11/07/2014 Oleg Moskalenko Version 4.2.3.1 'Monza': - Request re-transmission implemented in uclient test program. diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index d44c2d13..4ba01efa 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.2.3.1 +TURNVERSION=4.2.3.2 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 5cea7dba..b207071c 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.2.3.1 +Version: 4.2.3.2 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,6 +294,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Mon Nov 10 2014 Oleg Moskalenko + - Sync to 4.2.3.2 * Thu Nov 07 2014 Oleg Moskalenko - Sync to 4.2.3.1 * Sun Oct 26 2014 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 482b856c..2fb58322 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.2.3.1" +#define TURN_SERVER_VERSION "4.2.3.2" #define TURN_SERVER_VERSION_NAME "Monza" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 293ff99458d7e8d91a798e12cee1404c75077586 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 12 Nov 2014 07:24:23 +0000 Subject: [PATCH 315/805] centos updated to 6.6 --- rpm/CentOS6.pre.build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpm/CentOS6.pre.build.sh b/rpm/CentOS6.pre.build.sh index 2bb9306d..5d25b9e9 100755 --- a/rpm/CentOS6.pre.build.sh +++ b/rpm/CentOS6.pre.build.sh @@ -82,7 +82,7 @@ cd ${CPWD} # Platform file -echo "CentOS6.5" > ${BUILDDIR}/platform +echo "CentOS6.6" > ${BUILDDIR}/platform cp ${CPWD}/epel.install.sh ${BUILDDIR}/install.sh From 39d9fa98e2a7bfd15a5775fcc3f100ff579d42bc Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 14 Nov 2014 07:47:17 +0000 Subject: [PATCH 316/805] TODO fixed --- TODO | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/TODO b/TODO index 182c3a20..7bd197cd 100644 --- a/TODO +++ b/TODO @@ -47,7 +47,7 @@ ================================================================== -1) Per-realm black/white lists. +Nope ================================================================== @@ -63,8 +63,6 @@ 4) DTLS 1.2 (when available). -5) TURN Proxy ? http://tools.ietf.org/html/draft-schwartz-rtcweb-return-00 - ================================================================== ### VII. MISC FEATURES ### From ef7f08735980220e2afcbd710aa8a8b9a8128d56 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 15 Nov 2014 07:30:26 +0000 Subject: [PATCH 317/805] TODO updated --- TODO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO b/TODO index 7bd197cd..3ed9ee5b 100644 --- a/TODO +++ b/TODO @@ -103,7 +103,7 @@ Nope ================================================================== -none +1) SQLite support. ================================================================== From b9ef9f4c61c8e51cf0101229d931c9e1b962f975 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 16 Nov 2014 07:52:46 +0000 Subject: [PATCH 318/805] working on sqlite support --- ChangeLog | 4 +- INSTALL | 17 +- Makefile.in | 8 +- README.turnadmin | 18 +- README.turnserver | 34 +- README.turnutils | 4 +- STATUS | 2 + configure | 53 ++ examples/etc/turnserver.conf | 11 +- examples/etc/turnuserdb.conf | 23 - examples/var/db/turndb | Bin 0 -> 20480 bytes man/man1/turnadmin.1 | 22 +- man/man1/turnserver.1 | 37 +- man/man1/turnutils.1 | 6 +- postinstall.txt | 10 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 9 +- src/apps/relay/dbdrivers/dbd_sqlite.c | 818 ++++++++++++++++++++++++++ src/apps/relay/dbdrivers/dbd_sqlite.h | 49 ++ src/apps/relay/dbdrivers/dbdriver.c | 4 + src/apps/relay/mainrelay.c | 51 +- src/apps/relay/netengine.c | 1 - src/apps/relay/turncli.c | 4 +- src/apps/relay/userdb.c | 275 ++------- src/apps/relay/userdb.h | 5 +- src/ns_turn_defs.h | 4 +- 26 files changed, 1064 insertions(+), 407 deletions(-) delete mode 100644 examples/etc/turnuserdb.conf create mode 100644 examples/var/db/turndb create mode 100644 src/apps/relay/dbdrivers/dbd_sqlite.c create mode 100644 src/apps/relay/dbdrivers/dbd_sqlite.h diff --git a/ChangeLog b/ChangeLog index 0e9c1177..e9416b58 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,8 @@ 11/10/2014 Oleg Moskalenko -Version 4.2.3.2 'Monza': +Version 4.3.1.1 'Tolomei': - TLS connection procedure improved in uclient test program. + - Flat-file user database is no longer supported. + - SQLite supported as the default user database (TODO). 11/07/2014 Oleg Moskalenko Version 4.2.3.1 'Monza': diff --git a/INSTALL b/INSTALL index b4140dc0..85d314d7 100644 --- a/INSTALL +++ b/INSTALL @@ -211,7 +211,7 @@ If you do not want to use the rpath linking option, or you OS or compiler do not allows that, then after the installation, you may have to adjust the system-wide shared library search path by using "ldconfig -n " (Linux), "ldconfig -m " (BSD) or "crle -u -l " -(Solaris). Your system must be able to find the libevent2, openssl and +(Solaris). Your system must be able to find the sqlite, libevent2, openssl and (optionally) PostgreSQL and/or MySQL (MariaDB) and/or MongoDB and/or Redis shared libraries, either with the help of the system-wide library search configuration or by using LD_LIBRARY_PATH. "make install" will make a @@ -274,8 +274,9 @@ The code is compatible with C++ compiler, and a C++ compiler VII. WHICH EXTRA LIBRARIES AND UTILITIES YOU NEED In addition to common *NIX OS services and libraries, to compile this code, -OpenSSL (version 1.0.0a or better recommended) and libevent2 (version 2.0.5 -or better) are required, the PostgreSQL C client development setup is +OpenSSL (version 1.0.0a or better recommended), sqlite C development library, +and libevent2 (version 2.0.5 or better) are required, +the PostgreSQL C client development setup is optional, the MySQL (MariaDB) C client development setup is optional, the MongoDB C Driver and the Hiredis development files for Redis database access are optional. For fully functional build, the extra set of libraries must be installed @@ -283,9 +284,10 @@ in full version (the development headers and the libraries to link with). For runtime, only runtime setup is required. If the build is modified for static linking, then even runtime installation is not needed. -OpenSSL, libevent2, PostgreSQL, MySQL (or MariaDB) and Hiredis +OpenSSL, SQLite, libevent2, PostgreSQL, MySQL (or MariaDB) and Hiredis libraries can be downloaded from their web sites: - http://www.openssl.org (required); + - http://www.sqlite.org (required); - http://www.libevent.org (required); - http://www.postgresql.org (optional); - http://www.mysql.org (or http://mariadb.org) (optional); @@ -315,6 +317,8 @@ installation: $ cd /usr/ports/security/openssl/ $ sudo make install clean + $ cd /usr/ports/databases/sqlite3/ + $ sudo make install clean $ cd /usr/ports/devel/libevent2/ $ sudo make install clean $ cd /usr/ports/databases/postgresql84-client/ (or any other version) @@ -327,6 +331,7 @@ installation: **) Linux Ubuntu 11.10+, Debian Wheezy, Mint 14+: $ sudo apt-get install libssl-dev + $ sudo apt-get install sqlite3-dev $ sudo apt-get install libevent-dev $ sudo apt-get install libpq-dev $ sudo apt-get install mysql-client @@ -338,6 +343,8 @@ installation: ***) Fedora: $ sudo yum install openssl-devel + $ sudo yum install sqlite + $ sudo yum install sqlite-devel $ sudo yum install libevent $ sudo yum install libevent-devel $ sudo yum install postgresql-devel @@ -446,6 +453,8 @@ If you have a system with older libevent, then you have to install the new libevent2 from their web site. It was tested with older *NIXes (like FreeBSD 6.x) and it works just fine. +NOTE: SQLite must be of version 3.x. + NOTE: For extra security features (DTLS and SHA256) support, OpenSSL version 1.0.0a or newer is recommended. Older versions do not support DTLS, reliably, in some cases. For example, the Debian 'Squeeze' Linux supplies 0.9.8 version diff --git a/Makefile.in b/Makefile.in index 7a90ea22..e4f31284 100755 --- a/Makefile.in +++ b/Makefile.in @@ -27,8 +27,8 @@ IMPL_DEPS = ${COMMON_DEPS} ${IMPL_HEADERS} ${IMPL_MODS} HIREDIS_HEADERS = src/apps/common/hiredis_libevent2.h HIREDIS_MODS = src/apps/common/hiredis_libevent2.c -USERDB_HEADERS = src/apps/relay/dbdrivers/dbdriver.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_pgsql.c src/apps/relay/dbdrivers/dbd_mysql.c src/apps/relay/dbdrivers/dbd_mongo.c src/apps/relay/dbdrivers/dbd_redis.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} @@ -142,7 +142,7 @@ install: all ${MAKE_DEPS} ${INSTALL_DATA} turndb/schema.stats.redis ${DESTDIR}${DOCSDIR} ${INSTALL_DATA} turndb/schema.stats.redis ${DESTDIR}${SCHEMADIR} ${INSTALL_DATA} examples/etc/turnserver.conf ${DESTDIR}${CONFDIR}/turnserver.conf.default - ${INSTALL_DATA} examples/etc/turnuserdb.conf ${DESTDIR}${CONFDIR}/turnuserdb.conf.default + ${INSTALL_DATA} examples/var/db/turdb ${DESTDIR}/var/db/turndb ${INSTALL_DIR} examples/etc ${DESTDIR}${EXAMPLESDIR} ${INSTALL_DIR} examples/scripts ${DESTDIR}${EXAMPLESDIR} ${RMCMD} ${DESTDIR}${EXAMPLESDIR}/scripts/rfc5769.sh @@ -169,7 +169,7 @@ deinstall: ${MAKE_DEPS} ${RMCMD} ${DESTDIR}${LIBDIR}/libturnclient.a ${RMCMD} ${DESTDIR}${EXAMPLESDIR}/ ${RMCMD} ${DESTDIR}${CONFDIR}/turnserver.conf.default - ${RMCMD} ${DESTDIR}${CONFDIR}/turnuserdb.conf.default + ${RMCMD} ${DESTDIR}/var/db/turndb ${RMCMD} ${DESTDIR}${TURNINCLUDEDIR} uninstall: deinstall diff --git a/README.turnadmin b/README.turnadmin index bd0bc514..a2f6b27d 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -77,17 +77,11 @@ Commands: -g, --set-realm-option Set realm params: max-bps, total-quota, user-quota. -G, --list-realm-options List realm params. - -NOTE: if you are using the flat file for the user database, then you will have -to use a text editor to set or show the shared secrets. - -NOTE: the origin functionality is not supported with flat user db file, -a "real" database must be used. Options with required values: --b, --userdb File-based user database file name (default - turnuserdb.conf). - See the --userdb option in the turnserver section. +-b, --db, --userdb SQLite user database file name (default - /var/db/turndb). + See the same option in the turnserver section. -e, --psql-userdb PostgreSQL user database connection string. See the --psql-userdb option in the turnserver section. -M, --mysql-userdb MySQL user database connection string. @@ -112,11 +106,11 @@ Generate a key: $ turnadmin -k -u -r -p -Add/update a user in the userdb file or in the database: +Add/update a user in the in the database: $ turnadmin -a [-b | -e | -M | -N ] -u -r -p -Delete a user from the userdb file or from the database: +Delete a user from the database: $ turnadmin -d [-b | -e | -M | -N ] -u -r @@ -176,12 +170,10 @@ to see the man page. /etc/turnserver.conf -/etc/turnuserdb.conf +/var/db/turndb /usr/local/etc/turnserver.conf -/usr/local/etc/turnuserdb.conf - ===================================== DIRECTORIES diff --git a/README.turnserver b/README.turnserver index 31812e4e..b82b1745 100644 --- a/README.turnserver +++ b/README.turnserver @@ -81,11 +81,7 @@ Config file settings: User database settings: --b, --userdb User database file name (default - turnuserdb.conf), - for long-term credentials mechanism only. - This user file database is being dynamically checked while the - turnserver is working, and the user accounts can be changed - dynamically by editing the database. +-b, --db, --userdb SQLite user database file name (default - /var/db/turndb). -e, --psql-userdb User database connection string for PostgreSQL. This database can be used for long-term and short-term @@ -161,11 +157,9 @@ Flags: fingerprints to the messages in this session, regardless of the per-server setting. --a, --lt-cred-mech Use long-term credentials mechanism (this one you need for WebRTC usage). - This option can be used with either flat file user database or - PostgreSQL DB or MySQL DB or MongoDB or Redis for user keys storage. --A, --st-cred-mech Use the short-term credentials mechanism. This option requires - a PostgreSQL or MySQL or MongoDB or Redis DB for short term passwords storage. +-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 @@ -568,16 +562,14 @@ for that you have a number of options: a) command-line options (-u). - b) userdb config file. - - c) a database table (PostgreSQL or MySQL or MongoDB). You will have to set keys with - turnadmin utility (see docs and wiki for turnadmin). You cannot use open passwords - in the database. + b) a database table (SQLite or PostgreSQL or MySQL or MongoDB). You will have to + set keys with turnadmin utility (see docs and wiki for turnadmin). + You cannot use open passwords in the database. - d) Redis key/value pair(s), if Redis is used. You key use either keys or + c) Redis key/value pair(s), if Redis is used. You key use either keys or open passwords with Redis; see turndb/testredisdbsetup.sh file. - e) You also can use the TURN REST API. You will need shared secret(s) set + d) You also can use the TURN REST API. You will need shared secret(s) set either through the command line option, or through the config file, or through the database table or Redis key/value pairs. @@ -724,9 +716,7 @@ For the user database, the turnserver has the following options: Obviously, only a few users can be set that way, and their credentials are fixed for the turnserver process lifetime. -2) Users can be set in turnusers.conf flat file DB. The turnserver process periodically -re-reads this file, so the user accounts may be changed while the turnserver is running. -But still a relatively small (up to a hundred ?) number of users can be handled that way. +2) Users can be stored in SQlite DB. The default SQLite database file is /var/db/turndb. 3) Users can be stored in PostgreSQL database, if the turnserver was compiled with PostgreSQL support. Each time turnserver checks user credentials, it reads the database (asynchronously, @@ -851,12 +841,10 @@ FILES /etc/turnserver.conf -/etc/turnuserdb.conf +/var/db/turndb /usr/local/etc/turnserver.conf -/usr/local/etc/turnuserdb.conf - ================================= DIRECTORIES diff --git a/README.turnutils b/README.turnutils index 106983e6..61757a28 100644 --- a/README.turnutils +++ b/README.turnutils @@ -251,12 +251,10 @@ FILES /etc/turnserver.conf -/etc/turnuserdb.conf +/var/db/turndb /usr/local/etc/turnserver.conf -/usr/local/etc/turnuserdb.conf - ================================= DIRECTORIES diff --git a/STATUS b/STATUS index d5cd76e0..d908316a 100644 --- a/STATUS +++ b/STATUS @@ -106,6 +106,8 @@ compatibility. 45) Secure MySQL connection implemented. 46) Third-party security mechanism (through oAuth) implemented. + +47) SQLite support added as default database. Things to be implemented in future (the development roadmap) are described in the TODO file. diff --git a/configure b/configure index bc315886..bf3e8e4e 100755 --- a/configure +++ b/configure @@ -19,6 +19,8 @@ cleanup() { rm -rf ${MONGO_TMPCPROGB} rm -rf ${D_TMPCPROGC} rm -rf ${D_TMPCPROGB} + rm -rf ${SQL_TMPCPROGC} + rm -rf ${SQL_TMPCPROGO} rm -rf ${E_TMPCPROGC} rm -rf ${E_TMPCPROGO} rm -rf ${HR_TMPCPROGC} @@ -38,6 +40,19 @@ testlibraw() { fi } +testsqlite_comp() { + SQLITE_LIBS=-lsqlite3 + ${CC} -c ${SQL_TMPCPROGC} -o ${SQL_TMPCPROGO} ${OSCFLAGS} 2>>/dev/null + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "SQLite development is not installed properly" + return 0 + else + DBLIBS="${DBLIBS} ${SQLITE_LIBS}" + return 1 + fi +} + testlibevent2_comp() { ${CC} -c ${E_TMPCPROGC} -o ${E_TMPCPROGO} ${OSCFLAGS} 2>>/dev/null ER=$? @@ -683,6 +698,18 @@ int main(int argc, char** argv) { } ! +SQL_TMPCPROG=__test__ccomp__sqlite__$$ +SQL_TMPCPROGC=${TMPDIR}/${SQL_TMPCPROG}.c +SQL_TMPCPROGO=${TMPDIR}/${SQL_TMPCPROG}.o + +cat > ${SQL_TMPCPROGC} < +#include +int main(int argc, char** argv) { + return (int)(argv[argc][0]); +} +! + HR_TMPCPROG=__test__ccomp__hiredis__$$ HR_TMPCPROGC=${TMPDIR}/${HR_TMPCPROG}.c HR_TMPCPROGB=${TMPDIR}/${HR_TMPCPROG} @@ -932,6 +959,32 @@ else TURN_NO_GCM="-DTURN_NO_GCM" fi +########################### +# Test SQLite setup +########################### + +testlib sqlite3 +ER=$? +if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "SQLite library found." +else + ${ECHO_CMD} "ERROR: SQLite3 development library cannot be found." + cleanup + exit +fi + +testsqlite_comp +ER=$? +if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "SQLite development found." +else + ${ECHO_CMD} "ERROR: SQLite development libraries are not installed properly in required location." + ${ECHO_CMD} "See the INSTALL file." + ${ECHO_CMD} "Abort." + cleanup + exit +fi + ########################### # Test Libevent2 setup ########################### diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 0d1aef0b..0e583685 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -248,16 +248,11 @@ #user=ninefingers:youhavetoberealistic # -# 'Dynamic' user accounts database file name. -# Only users for long-term mechanism can be stored in a flat file, -# short-term mechanism will not work with option, the short-term -# mechanism required PostgreSQL or MySQL or MongoDB or Redis database. -# 'Dynamic' long-term user accounts are dynamically checked by the turnserver process, -# so that they can be changed while the turnserver is running. +# SQLite database file name. # -# Default file name is turnuserdb.conf. +# Default file name is /var/db/turndb # -#userdb=/usr/local/etc/turnuserdb.conf +#userdb=/var/db/turndb # PostgreSQL database connection string in the case that we are using PostgreSQL # as the user database. diff --git a/examples/etc/turnuserdb.conf b/examples/etc/turnuserdb.conf deleted file mode 100644 index 340fd008..00000000 --- a/examples/etc/turnuserdb.conf +++ /dev/null @@ -1,23 +0,0 @@ -#This file can be used as user accounts storage for long-term credentials mechanism. -# -#username1:key1 -#username2:key2 -# OR: -#username1:password1 -#username2:password2 -# -# Keys must be generated by turnadmin utility. The key value depends -# on user name, realm, and password: -# -# Example: -# $ turnadmin -k -u ninefingers -r north.gov -p youhavetoberealistic -# Output: 0xbc807ee29df3c9ffa736523fb2c4e8ee -# ('0x' in the beginning of the key is what differentiates the key from -# password. If it has 0x then it is a key, otherwise it is a password). -# -# The corresponding user account entry in the userdb file will be: -# -#ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee -# Or, equivalently (less secure): -#ninefingers:youhavetoberealistic -# diff --git a/examples/var/db/turndb b/examples/var/db/turndb new file mode 100644 index 0000000000000000000000000000000000000000..45de984f9f0db6ab8e026b6297aeafb044ea24cc GIT binary patch literal 20480 zcmeI2?`zXQ7{_zTmaNt3`~eXJcQU3e+nAkJ1re-LR5sDgi429~wqDoJw5dtz+$+gI zeCt2ppX6Kr0AKnC_{KNhrCFM!>l_tBC{Ll={mk=xKhIqrw!4?>Ylh2k-LhNM#W$r1 z2_fkL#*!pW@$W_cJ^YCJ#9@X1Mv?Nc;*_-XR1SCVs|tbqc1z1P}lM*&vV?ZbY+sHrxU)fB+CkfdJ(H6d;2MAdpc4kpD9p7;p;+ zq(A`je+rPn1Q5t50m%Ou4Gg#i1X3UX`9B57U;+qalmO)aj0OhW0s<)zfc&2VWH12) zGD-mQe?|iXZUKQ52#EZzNk1j&C;E!M%dh1x%DnP61;eSE@NOVYpPxqub1vOBncKD7 zU5D8YG2LicezZ}oY*z7R<>6WtM|*G~kNL-D)NJAR)ZS@OyHGBz6mgB!Y1ee|_3MlN zkTz|x*oa*|nHl z?)k*YJa^ov=Z-t+ouAb7xjE!DL)VGJc5LQ*9u(C9$Ab>;ckTr7c~8x5GC;YGZM3Mp zk41!nF!+zV2Q*H3wuPicC& zjJ&P>rnYQj*Ju;hBL0RIuP>5lI}=lS)Ci%sH!1f1;j4b|Es)#_y?J~KJU*@JZ_2}@ z9c4Dy<_UMtdZlSiUtUHB=lU{zKZwtKp+7Kj6eYX{vQDvOaTI8LID2%KPG_$89-nJ0+9blfCf{5z?cw# z{68jv1Q|eJ1Okx%M}P)XfWVj#5cyw`FG=zx`Hk{zOhkcHv%}Laal9S7 zd69FC7IR$M>fmj0w&;evH~6ubY1Ek*fO!YoWp=Ey(X7=;gE|dT@3wbB6Sr?AEKrB= u3nSFr{o9b^9rZ~Z|CE4LXlGDu?7jl$#SimJGpb&l9Tv0@Fe!z_3x5EY9Hxo@ literal 0 HcmV?d00001 diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 41688d14..f58dcbbc 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "09 November 2014" "" "" +.TH TURN 1 "15 November 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage @@ -126,20 +126,14 @@ Set realm params: max\-bps, total\-quota, user\-quota. .B \fB\-G\fP, \fB\-\-list\-realm\-options\fP List realm params. -.PP -NOTE: if you are using the flat file for the user database, then you will have -to use a text editor to set or show the shared secrets. -.PP -NOTE: the origin functionality is not supported with flat user db file, -a "real" database must be used. .TP .B Options with required values: .TP .B -\fB\-b\fP, \fB\-\-userdb\fP -File\-based user database file name (default \- turnuserdb.conf). -See the \fB\-\-userdb\fP option in the \fIturnserver\fP section. +\fB\-b\fP, \fB\-\-db\fP, \fB\-\-userdb\fP +SQLite user database file name (default \- /var/db/turndb). +See the same option in the \fIturnserver\fP section. .TP .B \fB\-e\fP, \fB\-\-psql\-userdb\fP @@ -204,11 +198,11 @@ Generate a key: .PP $ \fIturnadmin\fP \fB\-k\fP \fB\-u\fP \fB\-r\fP \fB\-p\fP .PP -Add/update a user in the userdb file or in the database: +Add/update a user in the in the database: .PP $ \fIturnadmin\fP \fB\-a\fP [\fB\-b\fP | \fB\-e\fP | \fB\-M\fP | \fB\-N\fP ] \fB\-u\fP \fB\-r\fP \fB\-p\fP .PP -Delete a user from the userdb file or from the database: +Delete a user from the database: .PP $ \fIturnadmin\fP \fB\-d\fP [\fB\-b\fP | \fB\-e\fP | \fB\-M\fP | \fB\-N\fP ] \fB\-u\fP \fB\-r\fP .PP @@ -267,12 +261,10 @@ to see the man page. /etc/turnserver.conf .PP -/etc/turnuserdb.conf +/var/db/turndb .PP /usr/local/etc/turnserver.conf .PP -/usr/local/etc/turnuserdb.conf -.PP ===================================== .SS DIRECTORIES diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 2f921a98..48391eec 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "09 November 2014" "" "" +.TH TURN 1 "15 November 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -131,12 +131,8 @@ installation directory /etc User database settings: .TP .B -\fB\-b\fP, \fB\-\-userdb\fP -User database file name (default \- turnuserdb.conf), -for long\-term credentials mechanism only. -This user file database is being dynamically checked while the -\fIturnserver\fP is working, and the user accounts can be changed -dynamically by editing the database. +\fB\-b\fP, \fB\-\-db\fP, \fB\-\-userdb\fP +SQLite user database file name (default \- /var/db/turndb). .TP .B \fB\-e\fP, \fB\-\-psql\-userdb\fP @@ -239,14 +235,11 @@ per\-server setting. .TP .B \fB\-a\fP, \fB\-\-lt\-cred\-mech\fP -Use long\-term credentials mechanism (this one you need for WebRTC usage). -This option can be used with either flat file user database or -PostgreSQL DB or MySQL DB or MongoDB or Redis for user keys storage. +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. This option requires -a PostgreSQL or MySQL or MongoDB or Redis DB for short term passwords storage. +Use the short\-term credentials mechanism. .TP .B \fB\-z\fP, \fB\-\-no\-auth\fP @@ -807,16 +800,14 @@ for that you have a number of \fIoptions\fP: .fam C a) command\-line options (\-u). - b) userdb config file. + b) a database table (SQLite or PostgreSQL or MySQL or MongoDB). You will have to + set keys with turnadmin utility (see docs and wiki for turnadmin). + You cannot use open passwords in the database. - c) a database table (PostgreSQL or MySQL or MongoDB). You will have to set keys with - turnadmin utility (see docs and wiki for turnadmin). You cannot use open passwords - in the database. - - d) Redis key/value pair(s), if Redis is used. You key use either keys or + c) Redis key/value pair(s), if Redis is used. You key use either keys or open passwords with Redis; see turndb/testredisdbsetup.sh file. - e) You also can use the TURN REST API. You will need shared secret(s) set + d) You also can use the TURN REST API. You will need shared secret(s) set either through the command line option, or through the config file, or through the database table or Redis key/value pairs. @@ -980,9 +971,7 @@ Users can be set in the command line, with multiple \fB\-u\fP or \fB\-\-user\fP Obviously, only a few users can be set that way, and their credentials are fixed for the \fIturnserver\fP process lifetime. .IP 2) 4 -Users can be set in turnusers.conf flat file DB. The \fIturnserver\fP process periodically -re\-reads this file, so the user accounts may be changed while the \fIturnserver\fP is running. -But still a relatively small (up to a hundred ?) number of users can be handled that way. +Users can be stored in SQlite DB. The default SQLite database file is /var/db/turndb. .IP 3) 4 Users can be stored in PostgreSQL database, if the \fIturnserver\fP was compiled with PostgreSQL support. Each time \fIturnserver\fP checks user credentials, it reads the database (asynchronously, @@ -1107,12 +1096,10 @@ it would affect the performance. /etc/turnserver.conf .PP -/etc/turnuserdb.conf +/var/db/turndb .PP /usr/local/etc/turnserver.conf .PP -/usr/local/etc/turnuserdb.conf -.PP ================================= .SH DIRECTORIES diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 260ca5f7..af881a18 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "09 November 2014" "" "" +.TH TURN 1 "15 November 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -374,12 +374,10 @@ to see the man page. /etc/turnserver.conf .PP -/etc/turnuserdb.conf +/var/db/turndb .PP /usr/local/etc/turnserver.conf .PP -/usr/local/etc/turnuserdb.conf -.PP ================================= .SH DIRECTORIES diff --git a/postinstall.txt b/postinstall.txt index b6546c1a..4f06f447 100644 --- a/postinstall.txt +++ b/postinstall.txt @@ -9,13 +9,15 @@ service, you have to: Use /usr/local/etc/turnserver.conf.default as an example. b) For user accounts settings, if using the turnserver - with authentication: create and edit /etc/turnuserdb.conf - file, or set up PostgreSQL or MySQL or MongoDB or Redis database for user accounts. - Use /usr/local/etc/turnuserdb.conf.default as example for flat file DB, - or use /usr/local/share/turnserver/schema.sql as SQL database schema, + with authentication: set up SQLite or PostgreSQL or MySQL or MongoDB or + Redis database for user accounts. + Use /usr/local/share/turnserver/schema.sql as SQL database schema, or use /usr/local/share/turnserver/schema.userdb.redis as Redis database schema description and/or /usr/local/share/turnserver/schema.stats.redis as Redis status & statistics database schema description. + + The installation process automatically creates /var/db/turndb SQlite database file, + with empty tables. c) add whatever is necessary to enable start-up daemon for the /usr/local/bin/turnserver. diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 4ba01efa..093eed71 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.2.3.2 +TURNVERSION=4.3.1.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index b207071c..49f119e4 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.2.3.2 +Version: 4.3.1.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -112,8 +112,6 @@ DESTDIR=$RPM_BUILD_ROOT make install mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig install -m644 rpm/turnserver.sysconfig \ $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig/turnserver -mv $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/turnuserdb.conf.default \ - $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/turnuserdb.conf %if 0%{?el6} cat $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/turnserver.conf.default | \ sed s/#syslog/syslog/g | \ @@ -169,12 +167,12 @@ fi %defattr(-,root,root) %{_bindir}/turnserver %{_bindir}/turnadmin +%{_localstatedir}/db/turndb %{_mandir}/man1/coturn.1.gz %{_mandir}/man1/turnserver.1.gz %{_mandir}/man1/turnadmin.1.gz %dir %attr(-,turnserver,turnserver) %{_sysconfdir}/%{name} %config(noreplace) %attr(0644,turnserver,turnserver) %{_sysconfdir}/%{name}/turnserver.conf -%config(noreplace) %attr(0644,turnserver,turnserver) %{_sysconfdir}/%{name}/turnuserdb.conf %config(noreplace) %{_sysconfdir}/sysconfig/turnserver %if 0%{?el6} %config %{_sysconfdir}/rc.d/init.d/turnserver @@ -203,7 +201,6 @@ fi %{_datadir}/%{name}/etc/turn_server_cert.pem %{_datadir}/%{name}/etc/turn_server_pkey.pem %{_datadir}/%{name}/etc/turnserver.conf -%{_datadir}/%{name}/etc/turnuserdb.conf %dir %{_datadir}/%{name}/scripts %{_datadir}/%{name}/scripts/peer.sh %{_datadir}/%{name}/scripts/readme.txt @@ -295,7 +292,7 @@ fi %changelog * Mon Nov 10 2014 Oleg Moskalenko - - Sync to 4.2.3.2 + - Sync to 4.3.1.1 * Thu Nov 07 2014 Oleg Moskalenko - Sync to 4.2.3.1 * Sun Oct 26 2014 Oleg Moskalenko diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c new file mode 100644 index 00000000..6a53df59 --- /dev/null +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -0,0 +1,818 @@ +/* + * Copyright (C) 2011, 2012, 2013 Citrix Systems + * Copyright (C) 2014 Vivocha S.p.A. + * + * 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. + */ + +#include "../mainrelay.h" +#include "dbd_sqlite.h" + +#include + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#if 0 + +static int donot_print_connection_success = 0; + +static PGconn *get_pqdb_connection(void) { + persistent_users_db_t *pud = get_persistent_users_db(); + + PGconn *pqdbconnection = (PGconn*)(pud->connection); + if(pqdbconnection) { + ConnStatusType status = PQstatus(pqdbconnection); + if(status != CONNECTION_OK) { + PQfinish(pqdbconnection); + pqdbconnection = NULL; + } + } + if(!pqdbconnection) { + char *errmsg=NULL; + PQconninfoOption *co = PQconninfoParse(pud->userdb, &errmsg); + if(!co) { + if(errmsg) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg); + turn_free(errmsg,strlen(errmsg)+1); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, unknown connection string format error\n",pud->userdb); + } + } else { + PQconninfoFree(co); + if(errmsg) + turn_free(errmsg,strlen(errmsg)+1); + pqdbconnection = PQconnectdb(pud->userdb); + if(!pqdbconnection) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb); + } else { + ConnStatusType status = PQstatus(pqdbconnection); + if(status != CONNECTION_OK) { + PQfinish(pqdbconnection); + pqdbconnection = NULL; + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb); + } else if(!donot_print_connection_success){ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "PostgreSQL DB connection success: %s\n",pud->userdb); + } + } + } + pud->connection = pqdbconnection; + } + return pqdbconnection; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static int pgsql_get_auth_secrets(secrets_list_t *sl, u08bits *realm) { + int ret = -1; + PGconn * pqc = get_pqdb_connection(); + if(pqc) { + char statement[TURN_LONG_STRING_SIZE]; + snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm); + 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; + for(i=0;iikm_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); + ret = 0; + } + + if(res) { + PQclear(res); + } + } + + return ret; +} + +static int pgsql_list_oauth_keys(void) { + + oauth_key_data_raw key_; + oauth_key_data_raw *key=&key_; + + int ret = -1; + + char statement[TURN_LONG_STRING_SIZE]; + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key,kid from oauth_key order by kid"); + + PGconn * pqc = get_pqdb_connection(); + if(pqc) { + 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; + for(i=0;iikm_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)); + + 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; + } + } + + if(res) { + PQclear(res); + } + } + + return ret; +} + +static int pgsql_set_user_key(u08bits *usname, u08bits *realm, const char *key) { + int ret = -1; + char statement[TURN_LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if(pqc) { + snprintf(statement,sizeof(statement),"insert into turnusers_lt (realm,name,hmackey) values('%s','%s','%s')",realm,usname,key); + + PGresult *res = PQexec(pqc, statement); + if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { + if(res) { + PQclear(res); + } + 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)); + } else { + ret = 0; + } + } + if(res) { + PQclear(res); + } + } + return ret; +} + +static int pgsql_set_oauth_key(oauth_key_data_raw *key) { + + int ret = -1; + char statement[TURN_LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if(pqc) { + snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s','%s','%s')", + 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); + + PGresult *res = PQexec(pqc, statement); + if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { + if(res) { + PQclear(res); + } + snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, hkdf_hash_func = '%s', as_rs_alg='%s',as_rs_key='%s',auth_alg='%s',auth_key='%s' where kid='%s'",key->ikm_key,(unsigned 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,key->kid); + res = PQexec(pqc, statement); + if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating oauth_key information: %s\n",PQerrorMessage(pqc)); + } 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) { + 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); + } + PGresult *res = PQexec(pqc, statement); + if(res) { + PQclear(res); + ret = 0; + } + } + return ret; +} + +static int pgsql_del_oauth_key(const u08bits *kid) { + + int ret = -1; + char statement[TURN_LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if(pqc) { + snprintf(statement,sizeof(statement),"delete from oauth_key where kid = '%s'",(const char*)kid); + + PGresult *res = PQexec(pqc, statement); + if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting oauth_key information: %s\n",PQerrorMessage(pqc)); + } else { + ret = 0; + } + if(res) { + PQclear(res); + } + } + return ret; +} + +static int pgsql_list_users(int is_st, 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),"select name,'' from turnusers_st order by name"); + } else if(realm && 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"); + } + 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; + for(i=0;i> %s\n",oval,rval); + } + } + } + ret = 0; + } + if(res) { + PQclear(res); + } + } + return ret; +} + +static int pgsql_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) { + int ret = -1; + char statement[TURN_LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if(pqc) { + { + snprintf(statement,sizeof(statement),"delete from turn_realm_option where realm='%s' and opt='%s'",realm,opt); + PGresult *res = PQexec(pqc, statement); + if(res) { + PQclear(res); + } + } + if(value>0) { + snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%lu')",realm,opt,(unsigned long)value); + PGresult *res = PQexec(pqc, statement); + if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting realm option information: %s\n",PQerrorMessage(pqc)); + } else { + ret = 0; + } + if(res) { + PQclear(res); + } + } + } + return ret; +} + +static int pgsql_list_realm_options(u08bits *realm) { + int ret = -1; + donot_print_connection_success = 1; + char statement[TURN_LONG_STRING_SIZE]; + PGconn *pqc = get_pqdb_connection(); + if(pqc) { + if(realm && realm[0]) { + snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option where realm='%s' order by realm,opt",realm); + } else { + snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option order by realm,opt"); + } + 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; + for(i=0;isz; + unlock_realms(); + + for (i = 0; isecrets[i]; + + realm_params_t* rp = get_realm(realm); + + lock_realms(); + rp->options.perf_options.max_bps = turn_params.max_bps; + unlock_realms(); + + lock_realms(); + rp->options.perf_options.total_quota = turn_params.total_quota; + unlock_realms(); + + lock_realms(); + rp->options.perf_options.user_quota = turn_params.user_quota; + unlock_realms(); + + } + } + + snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option"); + PGresult *res = PQexec(pqc, statement); + + if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) { + + int i = 0; + for(i=0;ioptions.perf_options.max_bps = (band_limit_t)atol(vval); + else if(!strcmp(oval,"total-quota")) + rp->options.perf_options.total_quota = (vint)atoi(vval); + else if(!strcmp(oval,"user-quota")) + rp->options.perf_options.user_quota = (vint)atoi(vval); + else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", oval); + } + } + } + } + + if(res) { + PQclear(res); + } + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static 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_del_secret, + &pgsql_set_secret, + &pgsql_add_origin, + &pgsql_del_origin, + &pgsql_list_origins, + &pgsql_set_realm_option_one, + &pgsql_list_realm_options, + &pgsql_auth_ping, + &pgsql_get_ip_list, + &pgsql_reread_realms, + &pgsql_set_oauth_key, + &pgsql_get_oauth_key, + &pgsql_del_oauth_key, + &pgsql_list_oauth_keys +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif + +turn_dbdriver_t * get_sqlite_dbdriver(void) { + //TODO + return NULL; +} diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.h b/src/apps/relay/dbdrivers/dbd_sqlite.h new file mode 100644 index 00000000..c1e95487 --- /dev/null +++ b/src/apps/relay/dbdrivers/dbd_sqlite.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011, 2012, 2013 Citrix Systems + * Copyright (C) 2014 Vivocha S.p.A. + * + * 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 __DBD_SQLITE__ +#define __DBD_SQLITE__ + +#include "dbdriver.h" + +#ifdef __cplusplus +extern "C" { +#endif + +turn_dbdriver_t * get_sqlite_dbdriver(void); + +#ifdef __cplusplus +} +#endif + +#endif +/// __DBD_SQLITE__/// + diff --git a/src/apps/relay/dbdrivers/dbdriver.c b/src/apps/relay/dbdrivers/dbdriver.c index abf797fd..ecae7039 100644 --- a/src/apps/relay/dbdrivers/dbdriver.c +++ b/src/apps/relay/dbdrivers/dbdriver.c @@ -34,6 +34,7 @@ #include "apputils.h" #include "dbdriver.h" +#include "dbd_sqlite.h" #include "dbd_pgsql.h" #include "dbd_mysql.h" #include "dbd_mongo.h" @@ -62,6 +63,9 @@ persistent_users_db_t * get_persistent_users_db(void) { turn_dbdriver_t * get_dbdriver() { if (!_driver) { switch(turn_params.default_users_db.userdb_type) { + case TURN_USERDB_TYPE_SQLITE: + _driver = get_sqlite_dbdriver(); + break; #if !defined(TURN_NO_PQ) case TURN_USERDB_TYPE_PQ: _driver = get_pgsql_dbdriver(); diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 70600f36..f294a932 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -95,7 +95,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_FILE, {"\0",NULL}, {0,NULL,NULL, {NULL,0}} } +{ TURN_USERDB_TYPE_SQLITE, {"\0",NULL}, {0,NULL,NULL, {NULL,0}} } }; @@ -386,17 +386,14 @@ static char Usage[] = "Usage: turnserver [options]\n" " -V, --Verbose Extra verbose mode, very annoying (for debug purposes only).\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. This option can be used with either\n" -" flat file user database or PostgreSQL DB or MySQL DB for user keys storage.\n" -" -A, --st-cred-mech Use the short-term credential mechanism. This option requires\n" -" a PostgreSQL or MySQL DB for short term passwords storage.\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 account, in form 'username:password', for long-term credentials.\n" " Cannot be used with TURN REST API or with short-term credentials.\n" " -r, --realm The default realm to be used for the users when no explicit\n" -" origin/realm relationship was found in the database, or if the TURN\n" -" server is not using any database (just the commands-line settings\n" -" and the userdb file). Must be used with long-term credentials \n" +" origin/realm relationship was found in the database.\n" +" Must be used with long-term credentials \n" " mechanism or with TURN REST API.\n" " --check-origin-consistency The flag that sets the origin consistency check:\n" " across the session, all requests must have the same\n" @@ -415,7 +412,7 @@ static char Usage[] = "Usage: turnserver [options]\n" " Total bytes-per-second bandwidth the TURN server is allowed to allocate\n" " for the sessions, combined (input and output network streams are treated separately).\n" " -c Configuration file name (default - turnserver.conf).\n" -" -b, --userdb User database file name (default - turnuserdb.conf) for long-term credentials only.\n" +" -b, , --db, --userdb SQLite database file name (default - "DEFAULT_USERDB_FILE").\n" #if !defined(TURN_NO_PQ) " -e, --psql-userdb, --sql-userdb 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" @@ -569,7 +566,7 @@ static char Usage[] = "Usage: turnserver [options]\n" "\n"; static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" - "Commands:\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" @@ -577,7 +574,6 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" " -D, --delete-st delete a short-term mechanism user\n" " -l, --list list all long-term mechanism users\n" " -L, --list-st list all short-term mechanism users\n" -#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS) " -s, --set-secret= Add shared secret for TURN RESP API\n" " -S, --show-secret Show stored shared secrets for TURN REST API\n" " -X, --delete-secret= Delete a shared secret\n" @@ -587,9 +583,8 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" " -I, --list-origins List origin-to-realm relations.\n" " -g, --set-realm-option Set realm params: max-bps, total-quota, user-quota.\n" " -G, --list-realm-options List realm params.\n" -#endif - "Options with mandatory values:\n" - " -b, --userdb User database file, if flat DB file is used.\n" + "\nOptions with mandatory values:\n\n" + " -b, --db, --userdb SQLite database file, default value is "DEFAULT_USERDB_FILE".\n" #if !defined(TURN_NO_PQ) " -e, --psql-userdb, --sql-userdb PostgreSQL user database connection string, if PostgreSQL DB is used.\n" #endif @@ -720,6 +715,7 @@ static const struct myoption long_options[] = { { "no-auth", optional_argument, NULL, 'z' }, { "user", required_argument, NULL, 'u' }, { "userdb", required_argument, NULL, 'b' }, + { "db", required_argument, NULL, 'b' }, #if !defined(TURN_NO_PQ) { "psql-userdb", required_argument, NULL, 'e' }, { "sql-userdb", required_argument, NULL, 'e' }, @@ -808,15 +804,14 @@ static const struct myoption admin_long_options[] = { { "delete", no_argument, NULL, 'd' }, { "list", no_argument, NULL, 'l' }, { "list-st", no_argument, NULL, 'L' }, -#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS) { "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 }, -#endif { "add-st", no_argument, NULL, 'A' }, { "delete-st", no_argument, NULL, 'D' }, { "userdb", required_argument, NULL, 'b' }, + { "db", required_argument, NULL, 'b' }, #if !defined(TURN_NO_PQ) { "psql-userdb", required_argument, NULL, 'e' }, { "sql-userdb", required_argument, NULL, 'e' }, @@ -834,7 +829,6 @@ static const struct myoption admin_long_options[] = { { "realm", required_argument, NULL, 'r' }, { "password", required_argument, NULL, 'p' }, { "sha256", no_argument, NULL, 'H' }, -#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS) { "add-origin", no_argument, NULL, 'O' }, { "del-origin", no_argument, NULL, 'R' }, { "list-origins", required_argument, NULL, 'I' }, @@ -844,7 +838,6 @@ static const struct myoption admin_long_options[] = { { "user-quota", required_argument, NULL, ADMIN_USER_QUOTA_OPT }, { "total-quota", required_argument, NULL, ADMIN_TOTAL_QUOTA_OPT }, { "max-bps", required_argument, NULL, ADMIN_MAX_BPS_OPT }, -#endif { "help", no_argument, NULL, 'h' }, { NULL, no_argument, NULL, 0 } }; @@ -1113,7 +1106,7 @@ static void set_option(int c, char *value) break; case 'b': STRCPY(turn_params.default_users_db.persistent_users_db.userdb, value); - turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_FILE; + turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_SQLITE; break; #if !defined(TURN_NO_PQ) case 'e': @@ -1461,7 +1454,6 @@ static int adminmain(int argc, char **argv) ct = TA_LIST_USERS; is_st = 1; break; -#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS) case 's': ct = TA_SET_SECRET; STRCPY(secret,optarg); @@ -1477,10 +1469,9 @@ static int adminmain(int argc, char **argv) case DEL_ALL_AUTH_SECRETS_OPT: ct = TA_DEL_SECRET; break; -#endif case 'b': STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg); - turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_FILE; + turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_SQLITE; break; #if !defined(TURN_NO_PQ) case 'e': @@ -1544,12 +1535,7 @@ static int adminmain(int argc, char **argv) } } - if(is_st && (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_FILE)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "ERROR: you have to use a PostgreSQL or MySQL database with short-term credentials\n"); - exit(-1); - } - - if(!strlen(turn_params.default_users_db.persistent_users_db.userdb) && (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_FILE)) + if(!strlen(turn_params.default_users_db.persistent_users_db.userdb) && (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_SQLITE)) STRCPY(turn_params.default_users_db.persistent_users_db.userdb,DEFAULT_USERDB_FILE); if(ct == TA_COMMAND_UNKNOWN) { @@ -1601,6 +1587,8 @@ static void print_features(unsigned long mfn) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "AEAD supported\n"); #endif + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SQLite supported\n"); + #if !defined(TURN_NO_HIREDIS) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis supported\n"); #else @@ -1851,10 +1839,9 @@ int main(int argc, char **argv) TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "\nCONFIG: WARNING: --server-relay: NON-STANDARD AND DANGEROUS OPTION.\n"); } - if(!strlen(turn_params.default_users_db.persistent_users_db.userdb) && (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_FILE)) + if(!strlen(turn_params.default_users_db.persistent_users_db.userdb) && (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_SQLITE)) STRCPY(turn_params.default_users_db.persistent_users_db.userdb,DEFAULT_USERDB_FILE); - read_userdb_file(0); update_white_and_black_lists(); argc -= optind; @@ -1891,9 +1878,7 @@ int main(int argc, char **argv) } if(use_lt_credentials) { - if(!turn_params.default_users_db.ram_db.users_number && (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_FILE) && !turn_params.use_auth_secret_with_timestamp) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "\nCONFIGURATION ALERT: you did not specify any user account, (-u option) \n but you did specified a long-term credentials mechanism option (-a option).\n The TURN Server will be inaccessible.\n Check your configuration.\n"); - } else if(!get_realm(NULL)->options.name[0]) { + if(!get_realm(NULL)->options.name[0]) { TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "\nCONFIGURATION ALERT: you did specify the long-term credentials usage\n but you did not specify the default realm option (-r option).\n Check your configuration.\n"); } } diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index e8c44d9b..86ae4471 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1696,7 +1696,6 @@ static void* run_auth_server_thread(void *arg) while(run_auth_server_flag) { reread_realms(); run_events(eb,NULL); - read_userdb_file(0); update_white_and_black_lists(); auth_ping(authserver->rch); #if defined(DB_TEST) diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index 2c67aa62..cf129080 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -781,8 +781,8 @@ static void cli_print_configuration(struct cli_session* cs) if(turn_params.default_users_db.persistent_users_db.userdb[0]) { switch(turn_params.default_users_db.userdb_type) { - case TURN_USERDB_TYPE_FILE: - cli_print_str(cs,"file","DB type",0); + case TURN_USERDB_TYPE_SQLITE: + cli_print_str(cs,"SQLite","DB type",0); break; #if !defined(TURN_NO_PQ) case TURN_USERDB_TYPE_PQ: diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index bb7e7801..816a99a0 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -736,83 +736,6 @@ void release_allocation_quota(u08bits *user, int oauth, u08bits *realm) ////////////////////////////////// -void read_userdb_file(int to_print) -{ - static char *full_path_to_userdb_file = NULL; - static int first_read = 1; - static turn_time_t mtime = 0; - - if(turn_params.default_users_db.userdb_type != TURN_USERDB_TYPE_FILE) - return; - if(turn_params.use_auth_secret_with_timestamp) - return; - - FILE *f = NULL; - - persistent_users_db_t *pud = get_persistent_users_db(); - - if(full_path_to_userdb_file) { - struct stat sb; - if(stat(full_path_to_userdb_file,&sb)<0) { - perror("File statistics"); - } else { - turn_time_t newmtime = (turn_time_t)(sb.st_mtime); - if(mtime == newmtime) - return; - mtime = newmtime; - - } - } - - if (!full_path_to_userdb_file) - full_path_to_userdb_file = find_config_file(pud->userdb, first_read); - - if (full_path_to_userdb_file) - f = fopen(full_path_to_userdb_file, "r"); - - if (f) { - - char sbuf[TURN_LONG_STRING_SIZE]; - - ur_string_map_lock(turn_params.default_users_db.ram_db.dynamic_accounts); - - ur_string_map_clean(turn_params.default_users_db.ram_db.dynamic_accounts); - - for (;;) { - char *s = fgets(sbuf, sizeof(sbuf) - 1, f); - if (!s) - break; - s = skip_blanks(s); - if (s[0] == '#') - continue; - if (!s[0]) - continue; - size_t slen = strlen(s); - while (slen && (s[slen - 1] == 10 || s[slen - 1] == 13)) - s[--slen] = 0; - if (slen) { - if(to_print) { - char* sc=strstr(s,":"); - if(sc) - sc[0]=0; - printf("%s\n",s); - } else { - add_user_account(s,1); - } - } - } - - ur_string_map_unlock(turn_params.default_users_db.ram_db.dynamic_accounts); - - fclose(f); - - } else if (first_read) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: Cannot find userdb file: %s: going without flat file user database.\n", pud->userdb); - } - - first_read = 0; -} - int add_user_account(char *user, int dynamic) { /* Realm is either default or empty for users taken from file or command-line */ @@ -872,11 +795,9 @@ static int list_users(int is_st, u08bits *realm) turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->list_users) { (*dbd->list_users)(is_st, realm); - } else if(!is_st) { - read_userdb_file(1); - } + } - return 0; + return 0; } static int show_secret(u08bits *realm) @@ -989,217 +910,107 @@ 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, int is_st, perf_options_t *po) +{ hmackey_t key; - char skey[sizeof(hmackey_t)*2+1]; + char skey[sizeof(hmackey_t) * 2 + 1]; st_password_t passwd; - if(ct == TA_LIST_USERS) { + if (ct == TA_LIST_USERS) { return list_users(is_st, realm); } - if(ct == TA_LIST_ORIGINS) { + if (ct == TA_LIST_ORIGINS) { return list_origins(realm); } - if(ct == TA_SHOW_SECRET) { + if (ct == TA_SHOW_SECRET) { return show_secret(realm); } - if(ct == TA_SET_SECRET) { + if (ct == TA_SET_SECRET) { return set_secret(secret, realm); } - if(ct == TA_DEL_SECRET) { + if (ct == TA_DEL_SECRET) { return del_secret(secret, realm); } - if(ct == TA_ADD_ORIGIN) { + if (ct == TA_ADD_ORIGIN) { must_set_admin_origin(origin); must_set_admin_realm(realm); - return add_origin(origin,realm); + return add_origin(origin, realm); } - if(ct == TA_DEL_ORIGIN) { + if (ct == TA_DEL_ORIGIN) { must_set_admin_origin(origin); return del_origin(origin); } - if(ct == TA_SET_REALM_OPTION) { + if (ct == TA_SET_REALM_OPTION) { must_set_admin_realm(realm); - if(!(po && (po->max_bps!=((band_limit_t)-1) || po->total_quota>=0 || po->user_quota>=0))) { + if (!(po && (po->max_bps != ((band_limit_t) -1) || po->total_quota >= 0 || po->user_quota >= 0))) { fprintf(stderr, "The operation cannot be completed: a realm option must be set.\n"); exit(-1); } - return set_realm_option(realm,po); + return set_realm_option(realm, po); } - if(ct == TA_LIST_REALM_OPTIONS) { + if (ct == TA_LIST_REALM_OPTIONS) { return list_realm_options(realm); } must_set_admin_user(user); - if(ct != TA_DELETE_USER) { + if (ct != TA_DELETE_USER) { must_set_admin_pwd(pwd); - if(is_st) { - strncpy((char*)passwd,(char*)pwd,sizeof(st_password_t)); + 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); - int maxsz = (int)(sz*2)+1; - char *s=skey; - for(i=0;(i2);i++) { - snprintf(s,(size_t)(sz*2),"%02x",(unsigned int)key[i]); - maxsz-=2; - s+=2; + int maxsz = (int) (sz * 2) + 1; + char *s = skey; + for (i = 0; (i < sz) && (maxsz > 2); i++) { + snprintf(s, (size_t) (sz * 2), "%02x", (unsigned int) key[i]); + maxsz -= 2; + s += 2; } - skey[sz*2]=0; + skey[sz * 2] = 0; } } - turn_dbdriver_t * dbd = get_dbdriver(); + turn_dbdriver_t * dbd = get_dbdriver(); - if(ct == TA_PRINT_KEY) { + if (ct == TA_PRINT_KEY) { - if(!is_st) { - printf("0x%s\n",skey); + if (!is_st) { + printf("0x%s\n", skey); } - } else if(dbd) { + } else if (dbd) { - if(!is_st) { + if (!is_st) { must_set_admin_realm(realm); } - - if (ct == TA_DELETE_USER) { - if (dbd->del_user) - (*dbd->del_user)(user, is_st, realm); - } else if (ct == TA_UPDATE_USER) { - if (is_st) { - if (dbd->set_user_pwd) - (*dbd->set_user_pwd)(user, passwd); - } else { - if (dbd->set_user_key) - (*dbd->set_user_key)(user, realm, skey); - } - } - - } else if(!is_st) { - persistent_users_db_t *pud = get_persistent_users_db(); - char *full_path_to_userdb_file = find_config_file(pud->userdb, 1); - FILE *f = full_path_to_userdb_file ? fopen(full_path_to_userdb_file,"r") : NULL; - int found = 0; - char us[TURN_LONG_STRING_SIZE]; - size_t i = 0; - char **content = NULL; - size_t csz = 0; - - STRCPY(us, (char*) user); - strncpy(us + strlen(us), ":", sizeof(us)-1-strlen(us)); - us[sizeof(us)-1]=0; - - if (!f) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "File %s not found, will be created.\n",pud->userdb); - } else { - - char sarg[TURN_LONG_STRING_SIZE]; - char sbuf[TURN_LONG_STRING_SIZE]; - - for (;;) { - char *s0 = fgets(sbuf, sizeof(sbuf) - 1, f); - if (!s0) - break; - - size_t slen = strlen(s0); - while (slen && (s0[slen - 1] == 10 || s0[slen - 1] == 13)) - s0[--slen] = 0; - - char *s = skip_blanks(s0); - - if (s[0] == '#') - goto add_and_cont; - if (!s[0]) - goto add_and_cont; - - STRCPY(sarg, s); - if (strstr(sarg, us) == sarg) { - if (ct == TA_DELETE_USER) - continue; - - if (found) - continue; - found = 1; - STRCPY(us, (char*) user); - strncpy(us + strlen(us), ":0x", sizeof(us)-1-strlen(us)); - us[sizeof(us)-1]=0; - size_t sz = get_hmackey_size(turn_params.shatype); - for (i = 0; i < sz; i++) { - snprintf( - us + strlen(us), - sizeof(us)-strlen(us), - "%02x", - (unsigned int) key[i]); - } - - s0 = us; - } - - add_and_cont: - content = (char**)turn_realloc(content, 0, sizeof(char*) * (++csz)); - content[csz - 1] = turn_strdup(s0); + if (ct == TA_DELETE_USER) { + if (dbd->del_user) + (*dbd->del_user)(user, is_st, realm); + } else if (ct == TA_UPDATE_USER) { + if (is_st) { + if (dbd->set_user_pwd) + (*dbd->set_user_pwd)(user, passwd); + } else { + if (dbd->set_user_key) + (*dbd->set_user_key)(user, realm, skey); } - - fclose(f); } - if(!found && (ct == TA_UPDATE_USER)) { - STRCPY(us,(char*)user); - strncpy(us+strlen(us),":0x",sizeof(us)-1-strlen(us)); - us[sizeof(us)-1]=0; - size_t sz = get_hmackey_size(turn_params.shatype); - for(i=0;iuserdb); - - size_t dirsz = strlen(full_path_to_userdb_file)+21; - char *dir = (char*)turn_malloc(dirsz+1); - strncpy(dir,full_path_to_userdb_file,dirsz); - dir[dirsz]=0; - size_t dlen = strlen(dir); - while(dlen) { - if(dir[dlen-1]=='/') - break; - dir[--dlen]=0; - } - strncpy(dir+strlen(dir),".tmp_userdb",dirsz-strlen(dir)); - - f = fopen(dir,"w"); - if(!f) { - perror("file open"); - exit(-1); - } - - for(i=0;i Date: Sun, 16 Nov 2014 07:56:51 +0000 Subject: [PATCH 319/805] preset sqlite db --- examples/var/db/turndb | Bin 20480 -> 20480 bytes postinstall.txt | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/var/db/turndb b/examples/var/db/turndb index 45de984f9f0db6ab8e026b6297aeafb044ea24cc..a71001bb82de43fe30558f6a3c98b511a0e16f1b 100644 GIT binary patch delta 1909 zcmah}O>Em_7`FX=;=f8ggzgWiJyj~JcENF+#4L@AlXh$e zvI+^fOae4*M<#>>XxgDv)3gbs!2vGN13%Ix*Z~P?OlU})xbitkW3R1*Pxkk|&-*^l z^SypAUSls_W8W9p><5!`YoWZyF5N9yHxiNtDF+xOp!43UJ!^sC>wb=@t zM%4=?H(2qcvyH$#>o=<9g65VC)6xxD)on+yG`m!(7>cXdWlzyP9YhooRnFD?FkEXG zwyAm+4J#GR@N}&tmkha;*OE=oQ|)p^bL~pSF*QS1wMt2K3!de9 zBMie3Tw!npU*ab`q@P=3}hx-g3f2 zfhZ){tJ=(rX}$ntihFoRsx)b*sGZl15e~edM3{m;MFkaig4z?Qg(#J(Be=}qXG-8Q zuG3HYY^BIssPCHgPC?ToFOp1gufDx3=&Iobwnu|IO!#6#d6II(TC26%oH=^5RQId3yjNbEDbPjK-&Go>_ea;H%8g{EhK2-*=lP&s_EuK?&|5ye z)LhnWae_1>$3z)tMvjdMOPHA$ST+lK++dzKL5Yov0SFLWUQ{l Date: Sun, 16 Nov 2014 19:05:12 +0000 Subject: [PATCH 320/805] /var/db changed to /var --- Makefile.in | 2 -- README.turnadmin | 4 ++-- README.turnserver | 6 +++--- README.turnutils | 2 +- examples/etc/turnserver.conf | 4 ++-- man/man1/turnadmin.1 | 6 +++--- man/man1/turnserver.1 | 8 ++++---- man/man1/turnutils.1 | 4 ++-- postinstall.txt | 3 --- rpm/turnserver.spec | 1 - src/apps/relay/userdb.h | 2 +- 11 files changed, 18 insertions(+), 24 deletions(-) diff --git a/Makefile.in b/Makefile.in index e4f31284..ea5ea7b0 100755 --- a/Makefile.in +++ b/Makefile.in @@ -142,7 +142,6 @@ install: all ${MAKE_DEPS} ${INSTALL_DATA} turndb/schema.stats.redis ${DESTDIR}${DOCSDIR} ${INSTALL_DATA} turndb/schema.stats.redis ${DESTDIR}${SCHEMADIR} ${INSTALL_DATA} examples/etc/turnserver.conf ${DESTDIR}${CONFDIR}/turnserver.conf.default - ${INSTALL_DATA} examples/var/db/turdb ${DESTDIR}/var/db/turndb ${INSTALL_DIR} examples/etc ${DESTDIR}${EXAMPLESDIR} ${INSTALL_DIR} examples/scripts ${DESTDIR}${EXAMPLESDIR} ${RMCMD} ${DESTDIR}${EXAMPLESDIR}/scripts/rfc5769.sh @@ -169,7 +168,6 @@ deinstall: ${MAKE_DEPS} ${RMCMD} ${DESTDIR}${LIBDIR}/libturnclient.a ${RMCMD} ${DESTDIR}${EXAMPLESDIR}/ ${RMCMD} ${DESTDIR}${CONFDIR}/turnserver.conf.default - ${RMCMD} ${DESTDIR}/var/db/turndb ${RMCMD} ${DESTDIR}${TURNINCLUDEDIR} uninstall: deinstall diff --git a/README.turnadmin b/README.turnadmin index a2f6b27d..269dfbbb 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -80,7 +80,7 @@ Commands: Options with required values: --b, --db, --userdb SQLite user database file name (default - /var/db/turndb). +-b, --db, --userdb SQLite user database file name (default - /var/turndb). See the same option in the turnserver section. -e, --psql-userdb PostgreSQL user database connection string. See the --psql-userdb option in the turnserver section. @@ -170,7 +170,7 @@ to see the man page. /etc/turnserver.conf -/var/db/turndb +/var/turndb /usr/local/etc/turnserver.conf diff --git a/README.turnserver b/README.turnserver index b82b1745..d35658bc 100644 --- a/README.turnserver +++ b/README.turnserver @@ -81,7 +81,7 @@ Config file settings: User database settings: --b, --db, --userdb SQLite user database file name (default - /var/db/turndb). +-b, --db, --userdb SQLite user database file name (default - /var/turndb). -e, --psql-userdb User database connection string for PostgreSQL. This database can be used for long-term and short-term @@ -716,7 +716,7 @@ For the user database, the turnserver has the following options: Obviously, only a few users can be set that way, and their credentials are fixed for the turnserver process lifetime. -2) Users can be stored in SQlite DB. The default SQLite database file is /var/db/turndb. +2) Users can be stored in SQlite DB. The default SQLite database file is /var/turndb. 3) Users can be stored in PostgreSQL database, if the turnserver was compiled with PostgreSQL support. Each time turnserver checks user credentials, it reads the database (asynchronously, @@ -841,7 +841,7 @@ FILES /etc/turnserver.conf -/var/db/turndb +/var/turndb /usr/local/etc/turnserver.conf diff --git a/README.turnutils b/README.turnutils index 61757a28..42f9359a 100644 --- a/README.turnutils +++ b/README.turnutils @@ -251,7 +251,7 @@ FILES /etc/turnserver.conf -/var/db/turndb +/var/turndb /usr/local/etc/turnserver.conf diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 0e583685..bfef53b7 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -250,9 +250,9 @@ # SQLite database file name. # -# Default file name is /var/db/turndb +# Default file name is /var/turndb # -#userdb=/var/db/turndb +#userdb=/var/turndb # PostgreSQL database connection string in the case that we are using PostgreSQL # as the user database. diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index f58dcbbc..d92301b9 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "15 November 2014" "" "" +.TH TURN 1 "16 November 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage @@ -132,7 +132,7 @@ Options with required values: .TP .B \fB\-b\fP, \fB\-\-db\fP, \fB\-\-userdb\fP -SQLite user database file name (default \- /var/db/turndb). +SQLite user database file name (default \- /var/turndb). See the same option in the \fIturnserver\fP section. .TP .B @@ -261,7 +261,7 @@ to see the man page. /etc/turnserver.conf .PP -/var/db/turndb +/var/turndb .PP /usr/local/etc/turnserver.conf .PP diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 48391eec..1833f4a6 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "15 November 2014" "" "" +.TH TURN 1 "16 November 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -132,7 +132,7 @@ User database settings: .TP .B \fB\-b\fP, \fB\-\-db\fP, \fB\-\-userdb\fP -SQLite user database file name (default \- /var/db/turndb). +SQLite user database file name (default \- /var/turndb). .TP .B \fB\-e\fP, \fB\-\-psql\-userdb\fP @@ -971,7 +971,7 @@ Users can be set in the command line, with multiple \fB\-u\fP or \fB\-\-user\fP Obviously, only a few users can be set that way, and their credentials are fixed for the \fIturnserver\fP process lifetime. .IP 2) 4 -Users can be stored in SQlite DB. The default SQLite database file is /var/db/turndb. +Users can be stored in SQlite DB. The default SQLite database file is /var/turndb. .IP 3) 4 Users can be stored in PostgreSQL database, if the \fIturnserver\fP was compiled with PostgreSQL support. Each time \fIturnserver\fP checks user credentials, it reads the database (asynchronously, @@ -1096,7 +1096,7 @@ it would affect the performance. /etc/turnserver.conf .PP -/var/db/turndb +/var/turndb .PP /usr/local/etc/turnserver.conf .PP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index af881a18..8b405f1e 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "15 November 2014" "" "" +.TH TURN 1 "16 November 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -374,7 +374,7 @@ to see the man page. /etc/turnserver.conf .PP -/var/db/turndb +/var/turndb .PP /usr/local/etc/turnserver.conf .PP diff --git a/postinstall.txt b/postinstall.txt index d178d399..27a427b8 100644 --- a/postinstall.txt +++ b/postinstall.txt @@ -16,9 +16,6 @@ service, you have to: database schema description and/or /usr/local/share/turnserver/schema.stats.redis as Redis status & statistics database schema description. - The installation process automatically creates /var/db/turndb SQlite database file, - with pre-set example data tables. - c) add whatever is necessary to enable start-up daemon for the /usr/local/bin/turnserver. 2) If you do not want the turnserver to be a system service, diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 49f119e4..ae1218de 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -167,7 +167,6 @@ fi %defattr(-,root,root) %{_bindir}/turnserver %{_bindir}/turnadmin -%{_localstatedir}/db/turndb %{_mandir}/man1/coturn.1.gz %{_mandir}/man1/turnserver.1.gz %{_mandir}/man1/turnadmin.1.gz diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index ebd2a17b..17f3c56f 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -48,7 +48,7 @@ extern "C" { //////////// Defines ////////////////////////////// -#define DEFAULT_USERDB_FILE "/var/db/turndb" +#define DEFAULT_USERDB_FILE ("/var/turndb") #define AUTH_SECRET_SIZE (512) From 805a3463b0d751c330921f5244f42249f464ce45 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 16 Nov 2014 19:17:27 +0000 Subject: [PATCH 321/805] sqlite added to rpm --- rpm/CentOS6.pre.build.sh | 2 +- rpm/CentOS7.pre.build.sh | 2 +- rpm/Fedora.pre.build.sh | 2 +- rpm/build.instructions.txt | 8 ++++++-- rpm/turnserver.spec | 4 ++-- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/rpm/CentOS6.pre.build.sh b/rpm/CentOS6.pre.build.sh index 5d25b9e9..bbbd39fc 100755 --- a/rpm/CentOS6.pre.build.sh +++ b/rpm/CentOS6.pre.build.sh @@ -18,7 +18,7 @@ LIBEVENT_SPEC_FILE=libevent.spec # Common packs -PACKS="mysql-devel" +PACKS="mysql-devel sqlite sqlite-devel" sudo yum -y install ${PACKS} ER=$? if ! [ ${ER} -eq 0 ] ; then diff --git a/rpm/CentOS7.pre.build.sh b/rpm/CentOS7.pre.build.sh index 82996859..45faeba3 100755 --- a/rpm/CentOS7.pre.build.sh +++ b/rpm/CentOS7.pre.build.sh @@ -12,7 +12,7 @@ EPELRPM=epel-release-6-8.noarch.rpm # Common packs -PACKS="libevent-devel mariadb-devel" +PACKS="libevent-devel mariadb-devel sqlite sqlite-devel" sudo yum -y install ${PACKS} ER=$? if ! [ ${ER} -eq 0 ] ; then diff --git a/rpm/Fedora.pre.build.sh b/rpm/Fedora.pre.build.sh index a5e8bc87..6e4f0249 100755 --- a/rpm/Fedora.pre.build.sh +++ b/rpm/Fedora.pre.build.sh @@ -6,7 +6,7 @@ CPWD=`pwd` . ./common.pre.build.sh -PACKS="libevent-devel mariadb-devel" +PACKS="libevent-devel mariadb-devel sqlite sqlite-devel" sudo yum -y install ${PACKS} ER=$? if ! [ ${ER} -eq 0 ] ; then diff --git a/rpm/build.instructions.txt b/rpm/build.instructions.txt index 4bfbfaa2..8f5050bf 100644 --- a/rpm/build.instructions.txt +++ b/rpm/build.instructions.txt @@ -18,8 +18,12 @@ To build the TURN server: 1) Install libevent and libevent-devel rpms 2) Install EPEL (http://fedoraproject.org/wiki/EPEL) - needed for hiredis - 3) Install the dependencies for building the TURN server: gcc, make, redhat-rpm-config, openssl-devel, libevent-devel >= 2.0.0, - mysql-devel, postgresql-devel, hiredis-devel + 3) Install the dependencies for building the TURN server: + gcc, make, redhat-rpm-config, + openssl-devel, + libevent-devel >= 2.0.0, + sqlite, sqlite-devel, + mysql-devel (or mariadb-devel), postgresql-devel, hiredis-devel 4) $ mkdir ~/rpmbuild 5) $ mkdir ~/rpmbuild/SOURCES 6) Export the TURN server from SVN, "svn export http://coturn.googlecode.com/svn/trunk/ turnserver-2.6.7.0" diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index ae1218de..128476d4 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -8,10 +8,10 @@ License: BSD URL: https://code.google.com/p/coturn/ Source0: http://turnserver.open-sys.org/downloads/v%{version}/%{name}-%{version}.tar.gz -BuildRequires: gcc, make, redhat-rpm-config +BuildRequires: gcc, make, redhat-rpm-config, sqlite-devel BuildRequires: openssl-devel, libevent-devel >= 2.0.0, postgresql-devel BuildRequires: hiredis-devel -Requires: openssl, libevent >= 2.0.0, mysql-libs, postgresql-libs +Requires: openssl, sqlite, libevent >= 2.0.0, mysql-libs, postgresql-libs Requires: hiredis, perl-DBI, perl-libwww-perl Requires: telnet %if 0%{?el6} From ef149fb30dae64f1e9690bd5367eb5074810b97f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 17 Nov 2014 01:33:31 +0000 Subject: [PATCH 322/805] default turndb changed to ~/turndb --- README.turnadmin | 4 ++-- README.turnserver | 6 +++--- README.turnutils | 2 +- examples/etc/turnserver.conf | 4 ++-- man/man1/turnadmin.1 | 4 ++-- man/man1/turnserver.1 | 6 +++--- man/man1/turnutils.1 | 2 +- src/apps/relay/dbdrivers/dbd_sqlite.c | 20 ++++++++++++++++++++ src/apps/relay/mainrelay.c | 4 ++-- src/apps/relay/userdb.h | 2 +- 10 files changed, 37 insertions(+), 17 deletions(-) diff --git a/README.turnadmin b/README.turnadmin index 269dfbbb..22d1f70f 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -80,7 +80,7 @@ Commands: Options with required values: --b, --db, --userdb SQLite user database file name (default - /var/turndb). +-b, --db, --userdb SQLite user database file name (default - ~/turndb). See the same option in the turnserver section. -e, --psql-userdb PostgreSQL user database connection string. See the --psql-userdb option in the turnserver section. @@ -170,7 +170,7 @@ to see the man page. /etc/turnserver.conf -/var/turndb +~/turndb /usr/local/etc/turnserver.conf diff --git a/README.turnserver b/README.turnserver index d35658bc..a2199b28 100644 --- a/README.turnserver +++ b/README.turnserver @@ -81,7 +81,7 @@ Config file settings: User database settings: --b, --db, --userdb SQLite user database file name (default - /var/turndb). +-b, --db, --userdb SQLite user database file name (default - ~/turndb). -e, --psql-userdb User database connection string for PostgreSQL. This database can be used for long-term and short-term @@ -716,7 +716,7 @@ For the user database, the turnserver has the following options: Obviously, only a few users can be set that way, and their credentials are fixed for the turnserver process lifetime. -2) Users can be stored in SQlite DB. The default SQLite database file is /var/turndb. +2) Users can be stored in SQLite DB. The default SQLite database file is ~/turndb. 3) Users can be stored in PostgreSQL database, if the turnserver was compiled with PostgreSQL support. Each time turnserver checks user credentials, it reads the database (asynchronously, @@ -841,7 +841,7 @@ FILES /etc/turnserver.conf -/var/turndb +~/turndb /usr/local/etc/turnserver.conf diff --git a/README.turnutils b/README.turnutils index 42f9359a..8beaf824 100644 --- a/README.turnutils +++ b/README.turnutils @@ -251,7 +251,7 @@ FILES /etc/turnserver.conf -/var/turndb +~/turndb /usr/local/etc/turnserver.conf diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index bfef53b7..e853f500 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -250,9 +250,9 @@ # SQLite database file name. # -# Default file name is /var/turndb +# Default file name is ~/turndb (turndb in the process' home directory). # -#userdb=/var/turndb +#userdb=~/turndb # PostgreSQL database connection string in the case that we are using PostgreSQL # as the user database. diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index d92301b9..dd0cf25d 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -132,7 +132,7 @@ Options with required values: .TP .B \fB\-b\fP, \fB\-\-db\fP, \fB\-\-userdb\fP -SQLite user database file name (default \- /var/turndb). +SQLite user database file name (default \- ~/turndb). See the same option in the \fIturnserver\fP section. .TP .B @@ -261,7 +261,7 @@ to see the man page. /etc/turnserver.conf .PP -/var/turndb +~/turndb .PP /usr/local/etc/turnserver.conf .PP diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 1833f4a6..bad4a5df 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -132,7 +132,7 @@ User database settings: .TP .B \fB\-b\fP, \fB\-\-db\fP, \fB\-\-userdb\fP -SQLite user database file name (default \- /var/turndb). +SQLite user database file name (default \- ~/turndb). .TP .B \fB\-e\fP, \fB\-\-psql\-userdb\fP @@ -971,7 +971,7 @@ Users can be set in the command line, with multiple \fB\-u\fP or \fB\-\-user\fP Obviously, only a few users can be set that way, and their credentials are fixed for the \fIturnserver\fP process lifetime. .IP 2) 4 -Users can be stored in SQlite DB. The default SQLite database file is /var/turndb. +Users can be stored in SQLite DB. The default SQLite database file is ~/turndb. .IP 3) 4 Users can be stored in PostgreSQL database, if the \fIturnserver\fP was compiled with PostgreSQL support. Each time \fIturnserver\fP checks user credentials, it reads the database (asynchronously, @@ -1096,7 +1096,7 @@ it would affect the performance. /etc/turnserver.conf .PP -/var/turndb +~/turndb .PP /usr/local/etc/turnserver.conf .PP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 8b405f1e..6df707ae 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -374,7 +374,7 @@ to see the man page. /etc/turnserver.conf .PP -/var/turndb +~/turndb .PP /usr/local/etc/turnserver.conf .PP diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 6a53df59..fa4b6cb0 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -36,6 +36,26 @@ /////////////////////////////////////////////////////////////////////////////////////////////////////////// +static int sqlite_init_multithreaded(void) { + + sqlite3_shutdown(); + + if (sqlite3_threadsafe() > 0) { + int retCode = sqlite3_config(SQLITE_CONFIG_SERIALIZED); + if (retCode == SQLITE_OK) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Can now use sqlite on multiple threads, using the same connection\n"); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "setting sqlite thread safe mode to serialized failed!!! return code: %d\n", retCode); + return -1; + } + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Your SQLite database is not compiled to be threadsafe.\n"); + return -1; + } + + return 0; +} + #if 0 static int donot_print_connection_success = 0; diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index f294a932..77aca642 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -412,7 +412,7 @@ static char Usage[] = "Usage: turnserver [options]\n" " Total bytes-per-second bandwidth the TURN server is allowed to allocate\n" " for the sessions, combined (input and output network streams are treated separately).\n" " -c Configuration file name (default - turnserver.conf).\n" -" -b, , --db, --userdb SQLite database file name (default - "DEFAULT_USERDB_FILE").\n" +" -b, , --db, --userdb SQLite database file name (default - ~/turndb).\n" #if !defined(TURN_NO_PQ) " -e, --psql-userdb, --sql-userdb 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" @@ -584,7 +584,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" " -g, --set-realm-option Set realm params: max-bps, total-quota, user-quota.\n" " -G, --list-realm-options List realm params.\n" "\nOptions with mandatory values:\n\n" - " -b, --db, --userdb SQLite database file, default value is "DEFAULT_USERDB_FILE".\n" + " -b, --db, --userdb SQLite database file, default value is ~/turndb.\n" #if !defined(TURN_NO_PQ) " -e, --psql-userdb, --sql-userdb PostgreSQL user database connection string, if PostgreSQL DB is used.\n" #endif diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index 17f3c56f..dc4890fc 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -48,7 +48,7 @@ extern "C" { //////////// Defines ////////////////////////////// -#define DEFAULT_USERDB_FILE ("/var/turndb") +#define DEFAULT_USERDB_FILE ("~/turndb") #define AUTH_SECRET_SIZE (512) From b25a32f10c5769d882336b63ffd7a449ee20767e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 17 Nov 2014 09:38:53 +0000 Subject: [PATCH 323/805] sqlite support, draft implementation --- .../secure_relay_with_db_sqlite.sh | 35 + .../secure_relay_secret_with_db_mongo.sh | 37 + .../secure_relay_secret_with_db_sqlite.sh | 37 + rpm/turnserver.spec | 3 + src/apps/relay/dbdrivers/dbd_sqlite.c | 1268 +++++++++-------- src/apps/uclient/mainuclient.c | 6 +- 6 files changed, 796 insertions(+), 590 deletions(-) create mode 100755 examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh create mode 100755 examples/scripts/restapi/secure_relay_secret_with_db_mongo.sh create mode 100755 examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh new file mode 100755 index 00000000..c160af38 --- /dev/null +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure mode with SQLite database for users +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) "-r north.gov" means "use authentication realm north.gov" +# 6) --db= +# means that local database will be used. +# 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 +# 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 --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 $@ + diff --git a/examples/scripts/restapi/secure_relay_secret_with_db_mongo.sh b/examples/scripts/restapi/secure_relay_secret_with_db_mongo.sh new file mode 100755 index 00000000..fdc41ec8 --- /dev/null +++ b/examples/scripts/restapi/secure_relay_secret_with_db_mongo.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure 'dynamic' 'secret' mode (see TURNServerRESTAPI.pdf) +# with MongoDB database for users information +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) --use-auth-secret means that we are using 'secret' authentication mode. +# Absense of --static-auth-secret value means that we will be taking the secret value +# from the database ('dynamic' mode). +# 6) --realm=north.gov sets realm value as "north.gov". +# 7) --mongo-userdb="mongodb://localhost/coturn" +# means that local MongoDB database "coturn" will be used. +# 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 +# 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 -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 $@ diff --git a/examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh b/examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh new file mode 100755 index 00000000..c4fa65e1 --- /dev/null +++ b/examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure 'dynamic' 'secret' mode (see TURNServerRESTAPI.pdf) +# with SQLite database for users information +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) --use-auth-secret means that we are using 'secret' authentication mode. +# Absense of --static-auth-secret value means that we will be taking the secret value +# from the database ('dynamic' mode). +# 6) --realm=north.gov sets realm value as "north.gov". +# 7) --db= +# means that local SQLite database will be used. +# 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 +# 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 -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 $@ diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 128476d4..026b8d1e 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -235,11 +235,14 @@ fi %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_psql.sh %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_redis.sh +%{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh %dir %{_datadir}/%{name}/scripts/restapi %{_datadir}/%{name}/scripts/restapi/secure_relay_secret.sh %{_datadir}/%{name}/scripts/restapi/secure_relay_secret_with_db_mysql.sh %{_datadir}/%{name}/scripts/restapi/secure_relay_secret_with_db_psql.sh %{_datadir}/%{name}/scripts/restapi/secure_relay_secret_with_db_redis.sh +%{_datadir}/%{name}/scripts/restapi/secure_relay_secret_with_db_mongo.sh +%{_datadir}/%{name}/scripts/restapi/secure_relay_secret_with_db_sqlite.sh %{_datadir}/%{name}/scripts/restapi/secure_udp_client_with_secret.sh %{_datadir}/%{name}/scripts/restapi/shared_secret_maintainer.pl %dir %{_datadir}/%{name}/scripts/selfloadbalance diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index fa4b6cb0..08d0d0be 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -34,6 +34,10 @@ #include +#include +#include +#include + /////////////////////////////////////////////////////////////////////////////////////////////////////////// static int sqlite_init_multithreaded(void) { @@ -56,181 +60,227 @@ static int sqlite_init_multithreaded(void) { return 0; } -#if 0 - static int donot_print_connection_success = 0; -static PGconn *get_pqdb_connection(void) { - persistent_users_db_t *pud = get_persistent_users_db(); - - PGconn *pqdbconnection = (PGconn*)(pud->connection); - if(pqdbconnection) { - ConnStatusType status = PQstatus(pqdbconnection); - if(status != CONNECTION_OK) { - PQfinish(pqdbconnection); - pqdbconnection = NULL; - } - } - if(!pqdbconnection) { - char *errmsg=NULL; - PQconninfoOption *co = PQconninfoParse(pud->userdb, &errmsg); - if(!co) { - if(errmsg) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg); - turn_free(errmsg,strlen(errmsg)+1); +static void fix_user_directory(char *dir0) { + char *dir = dir0; + while(*dir == ' ') ++dir; + if(*dir == '~') { + char *home=getenv("HOME"); + if(!home) { + struct passwd *pwd = getpwuid(getuid()); + if(!pwd) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot figure out the user's HOME directory (1)\n"); } else { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, unknown connection string format error\n",pud->userdb); - } - } else { - PQconninfoFree(co); - if(errmsg) - turn_free(errmsg,strlen(errmsg)+1); - pqdbconnection = PQconnectdb(pud->userdb); - if(!pqdbconnection) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb); - } else { - ConnStatusType status = PQstatus(pqdbconnection); - if(status != CONNECTION_OK) { - PQfinish(pqdbconnection); - pqdbconnection = NULL; - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb); - } else if(!donot_print_connection_success){ - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "PostgreSQL DB connection success: %s\n",pud->userdb); + home = pwd->pw_dir; + if(!home) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot figure out the user's HOME directory\n"); + return; } } } - pud->connection = pqdbconnection; + size_t szh = strlen(home); + size_t sz = strlen(dir0)+1+szh; + char* dir_fixed = (char*)turn_malloc(sz); + strncpy(dir_fixed,home,szh); + strncpy(dir_fixed+szh,dir+1,(sz-szh-1)); + strncpy(dir0,dir_fixed,sz); + turn_free(dir_fixed,sz); } - return pqdbconnection; +} + +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 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))", + NULL + }; + + int i = 0; + while(statements[i]) { + sqlite3_stmt *statement = NULL; + int rc = 0; + if ((rc = sqlite3_prepare(sqliteconnection, statements[i], -1, &statement, 0)) == SQLITE_OK) { + sqlite3_step(statement); + } + sqlite3_finalize(statement); + ++i; + } +} + +static sqlite3 * get_sqlite_connection(void) { + + persistent_users_db_t *pud = get_persistent_users_db(); + + sqlite3 *sqliteconnection = (sqlite3 *)(pud->connection); + if(!sqliteconnection) { + fix_user_directory(pud->userdb); + sqlite_init_multithreaded(); + int rc = sqlite3_open(pud->userdb, &sqliteconnection); + if(!sqliteconnection || (rc != SQLITE_OK)) { + const char* errmsg = sqlite3_errmsg(sqliteconnection); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open SQLite DB connection: <%s>, runtime error: %s\n",pud->userdb,errmsg); + } else if(!donot_print_connection_success){ + init_sqlite_database(sqliteconnection); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SQLite DB connection success: %s\n",pud->userdb); + } + pud->connection = sqliteconnection; + } + return sqliteconnection; } /////////////////////////////////////////////////////////////////////////////////////////////////////////// -static int pgsql_get_auth_secrets(secrets_list_t *sl, u08bits *realm) { - int ret = -1; - PGconn * pqc = get_pqdb_connection(); - if(pqc) { +static int sqlite_get_auth_secrets(secrets_list_t *sl, u08bits *realm) +{ + int ret = -1; + sqlite3 *sqliteconnection = get_sqlite_connection(); + if (sqliteconnection) { char statement[TURN_LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm); - PGresult *res = PQexec(pqc, statement); + sqlite3_stmt *st = NULL; + int rc = 0; + snprintf(statement, sizeof(statement) - 1, "select value from turn_secret where realm='%s'", realm); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { - 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; - for(i=0;i 0) { + + int res = sqlite3_step(st); + if (res == SQLITE_ROW) { + + int type = sqlite3_column_type(st, 0); + if (type != SQLITE_NULL) + add_to_secrets_list(sl, (const char*) sqlite3_column_text(st, 0)); + + } 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; } } - ret = 0; - } - - if(res) { - PQclear(res); - } - } - return ret; -} - -static int pgsql_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) { - int ret = -1; - PGconn * pqc = get_pqdb_connection(); - if(pqc) { - char statement[TURN_LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"select hmackey from turnusers_lt where name='%s' and realm='%s'",usname,realm); - 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); - int len = PQgetlength(res,0,0); - if(kval) { + const char* errmsg = sqlite3_errmsg(sqliteconnection); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); + } + sqlite3_finalize(st); + } + return ret; +} + +static int sqlite_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) +{ + int ret = -1; + 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 hmackey from turnusers_lt where name='%s' and realm='%s'", usname, realm); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { + int res = sqlite3_step(st); + if (res == SQLITE_ROW) { + char *kval = turn_strdup((const char*) sqlite3_column_text(st, 0)); size_t sz = get_hmackey_size(turn_params.shatype); - if(((size_t)lenikm_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); + ret = 0; + } } else { - STRCPY((char*)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); - ret = 0; + const char* errmsg = sqlite3_errmsg(sqliteconnection); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } - if(res) { - PQclear(res); - } + sqlite3_finalize(st); } return ret; } -static int pgsql_list_oauth_keys(void) { +static int sqlite_list_oauth_keys(void) { oauth_key_data_raw key_; oauth_key_data_raw *key=&key_; @@ -238,505 +288,543 @@ static int pgsql_list_oauth_keys(void) { int ret = -1; char statement[TURN_LONG_STRING_SIZE]; + sqlite3_stmt *st = NULL; + int rc = 0; snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key,kid from oauth_key order by kid"); - PGconn * pqc = get_pqdb_connection(); - if(pqc) { - PGresult *res = PQexec(pqc, statement); + sqlite3 *sqliteconnection = get_sqlite_connection(); + if(sqliteconnection) { - 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; - for(i=0;iikm_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)); + ret = 0; + while (1) { + int res = sqlite3_step(st); + if (res == SQLITE_ROW) { - 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", + STRCPY((char*)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)); + + 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; + } 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); } - if(res) { - PQclear(res); - } + sqlite3_finalize(st); } return ret; } - -static int pgsql_set_user_key(u08bits *usname, u08bits *realm, const char *key) { - int ret = -1; + +static int sqlite_set_user_key(u08bits *usname, u08bits *realm, const char *key) +{ + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; - PGconn *pqc = get_pqdb_connection(); - if(pqc) { - snprintf(statement,sizeof(statement),"insert into turnusers_lt (realm,name,hmackey) values('%s','%s','%s')",realm,usname,key); + sqlite3_stmt *st = NULL; + int rc = 0; + sqlite3 *sqliteconnection = get_sqlite_connection(); + if (sqliteconnection) { - PGresult *res = PQexec(pqc, statement); - if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { - if(res) { - PQclear(res); - } - 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)); - } else { - ret = 0; - } - } - if(res) { - PQclear(res); - } - } - return ret; -} + snprintf(statement, sizeof(statement), "insert or replace into turnusers_lt (realm,name,hmackey) values('%s','%s','%s')", realm, usname, key); -static int pgsql_set_oauth_key(oauth_key_data_raw *key) { - - int ret = -1; - char statement[TURN_LONG_STRING_SIZE]; - PGconn *pqc = get_pqdb_connection(); - if(pqc) { - snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s','%s','%s')", - 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); - - PGresult *res = PQexec(pqc, statement); - if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { - if(res) { - PQclear(res); - } - snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, hkdf_hash_func = '%s', as_rs_alg='%s',as_rs_key='%s',auth_alg='%s',auth_key='%s' where kid='%s'",key->ikm_key,(unsigned 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,key->kid); - res = PQexec(pqc, statement); - if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating oauth_key information: %s\n",PQerrorMessage(pqc)); - } 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) { - 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); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { + sqlite3_step(st); + ret = 0; } else { - 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); - ret = 0; + const char* errmsg = sqlite3_errmsg(sqliteconnection); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } + sqlite3_finalize(st); } - return ret; + return ret; } -static int pgsql_del_oauth_key(const u08bits *kid) { +static int sqlite_set_oauth_key(oauth_key_data_raw *key) +{ - int ret = -1; - char statement[TURN_LONG_STRING_SIZE]; - PGconn *pqc = get_pqdb_connection(); - if(pqc) { - snprintf(statement,sizeof(statement),"delete from oauth_key where kid = '%s'",(const char*)kid); - - PGresult *res = PQexec(pqc, statement); - if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting oauth_key information: %s\n",PQerrorMessage(pqc)); - } else { - ret = 0; - } - if(res) { - PQclear(res); - } - } - return ret; -} - -static int pgsql_list_users(int is_st, u08bits *realm) { - int ret = -1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; - 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]) { - snprintf(statement,sizeof(statement),"select name,realm from turnusers_lt where realm='%s' order by name",realm); + sqlite3_stmt *st = NULL; + int rc = 0; + sqlite3 *sqliteconnection = get_sqlite_connection(); + if (sqliteconnection) { + snprintf( + statement, + sizeof(statement), + "insert or replace into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s','%s','%s')", + 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 ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { + sqlite3_step(st); + ret = 0; } else { - snprintf(statement,sizeof(statement),"select name,realm from turnusers_lt order by name"); + const char* errmsg = sqlite3_errmsg(sqliteconnection); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } - 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)); + sqlite3_finalize(st); + } + return ret; +} + +static int sqlite_set_user_pwd(u08bits *usname, st_password_t pwd) +{ + int ret = -1; + char statement[TURN_LONG_STRING_SIZE]; + sqlite3_stmt *st = NULL; + int rc = 0; + sqlite3 *sqliteconnection = get_sqlite_connection(); + if (sqliteconnection) { + snprintf(statement, sizeof(statement), "insert or replace into turnusers_st values('%s','%s')", usname, pwd); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { + sqlite3_step(st); + ret = 0; } else { - int i = 0; - for(i=0;i> %s\n",oval,rval); - } - } - } - ret = 0; - } - if(res) { - PQclear(res); - } - } - return ret; -} - -static int pgsql_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) { - int ret = -1; - char statement[TURN_LONG_STRING_SIZE]; - PGconn *pqc = get_pqdb_connection(); - if(pqc) { - { - snprintf(statement,sizeof(statement),"delete from turn_realm_option where realm='%s' and opt='%s'",realm,opt); - PGresult *res = PQexec(pqc, statement); - if(res) { - PQclear(res); - } - } - if(value>0) { - snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%lu')",realm,opt,(unsigned long)value); - PGresult *res = PQexec(pqc, statement); - if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting realm option information: %s\n",PQerrorMessage(pqc)); - } else { - ret = 0; - } - if(res) { - PQclear(res); - } - } - } - return ret; -} - -static int pgsql_list_realm_options(u08bits *realm) { - int ret = -1; - donot_print_connection_success = 1; - char statement[TURN_LONG_STRING_SIZE]; - PGconn *pqc = get_pqdb_connection(); - if(pqc) { - if(realm && realm[0]) { - snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option where realm='%s' order by realm,opt",realm); - } else { - snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option order by realm,opt"); - } - 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; - for(i=0;i> %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; } } - ret = 0; + } else { + const char* errmsg = sqlite3_errmsg(sqliteconnection); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } - - if (res) { - PQclear(res); + sqlite3_finalize(st); + } + return ret; +} + +static int sqlite_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) +{ + int ret = -1; + char statement[TURN_LONG_STRING_SIZE]; + sqlite3_stmt *st = NULL; + int rc = 0; + sqlite3 *sqliteconnection = get_sqlite_connection(); + if(sqliteconnection) { + if(value>0) { + snprintf(statement,sizeof(statement),"insert or replace into turn_realm_option (realm,opt,value) values('%s','%s','%lu')",realm,opt,(unsigned long)value); + 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); } } return ret; } -static void pgsql_reread_realms(secrets_list_t * realms_list) { - PGconn * pqc = get_pqdb_connection(); - if(pqc) { - char statement[TURN_LONG_STRING_SIZE]; +static int sqlite_list_realm_options(u08bits *realm) +{ + int ret = -1; + 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) { + if (realm && realm[0]) { + snprintf(statement, sizeof(statement), "select realm,opt,value from turn_realm_option where realm='%s' order by realm,opt", realm); + } else { + snprintf(statement, sizeof(statement), "select realm,opt,value from turn_realm_option order by realm,opt"); + } + 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* rval = (const char*) sqlite3_column_text(st, 0); + const char* oval = (const char*) sqlite3_column_text(st, 1); + const char* vval = (const char*) sqlite3_column_text(st, 2); + + printf("%s[%s]=%s\n",oval,rval,vval); + + } 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); + } + return ret; +} + +static void sqlite_auth_ping(void * rch) +{ + UNUSED_ARG(rch); +} + +static int sqlite_get_ip_list(const char *kind, ip_range_list_t * list) +{ + int ret = -1; + 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 ip_range,realm from %s_peer_ip", kind); + 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); + + add_ip_list_range(kval, rval, list); + + } 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); + } + return ret; +} + +static void sqlite_reread_realms(secrets_list_t * realms_list) +{ + 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 origin,realm from turn_origin_to_realm"); - PGresult *res = PQexec(pqc, statement); - - if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) { + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { ur_string_map *o_to_realm_new = ur_string_map_create(turn_free_simple); - int i = 0; - for(i=0;ioptions.perf_options.max_bps = (band_limit_t)atol(vval); @@ -790,13 +878,22 @@ static void pgsql_reread_realms(secrets_list_t * realms_list) { else { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", oval); } + + turn_free(rval,strlen(rval)+1); + + } 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); + break; } } + } else { + const char* errmsg = sqlite3_errmsg(sqliteconnection); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } - - if(res) { - PQclear(res); - } + sqlite3_finalize(st); } } } @@ -804,35 +901,32 @@ static void pgsql_reread_realms(secrets_list_t * realms_list) { /////////////////////////////////////////////////////////////////////////////////////////////////////////// static 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_del_secret, - &pgsql_set_secret, - &pgsql_add_origin, - &pgsql_del_origin, - &pgsql_list_origins, - &pgsql_set_realm_option_one, - &pgsql_list_realm_options, - &pgsql_auth_ping, - &pgsql_get_ip_list, - &pgsql_reread_realms, - &pgsql_set_oauth_key, - &pgsql_get_oauth_key, - &pgsql_del_oauth_key, - &pgsql_list_oauth_keys + &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_del_secret, + &sqlite_set_secret, + &sqlite_add_origin, + &sqlite_del_origin, + &sqlite_list_origins, + &sqlite_set_realm_option_one, + &sqlite_list_realm_options, + &sqlite_auth_ping, + &sqlite_get_ip_list, + &sqlite_reread_realms, + &sqlite_set_oauth_key, + &sqlite_get_oauth_key, + &sqlite_del_oauth_key, + &sqlite_list_oauth_keys }; /////////////////////////////////////////////////////////////////////////////////////////////////////////// -#endif - turn_dbdriver_t * get_sqlite_dbdriver(void) { - //TODO - return NULL; + return &driver; } diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 164fdaa6..ca7201ba 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -137,9 +137,9 @@ static char Usage[] = " -I Do not set permissions on TURN relay endpoints\n" " (for testing the non-standard server relay functionality).\n" " -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" + " -B Random disconnect after a few initial packets.\n" + " -Z Dual allocation.\n" + " -J Use oAuth with default test key kid='north'.\n" "Options:\n" " -l Message length (Default: 100 Bytes).\n" " -i Certificate file (for secure connections only, optional).\n" From 8a258ff5252808cdbd2d0df6c050067c76071b21 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 17 Nov 2014 16:32:21 +0000 Subject: [PATCH 324/805] status updated --- ChangeLog | 2 +- TODO | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index e9416b58..f9846da9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,7 +2,7 @@ Version 4.3.1.1 'Tolomei': - TLS connection procedure improved in uclient test program. - Flat-file user database is no longer supported. - - SQLite supported as the default user database (TODO). + - SQLite supported as the default user database. 11/07/2014 Oleg Moskalenko Version 4.2.3.1 'Monza': diff --git a/TODO b/TODO index 3ed9ee5b..92375d2a 100644 --- a/TODO +++ b/TODO @@ -103,7 +103,7 @@ Nope ================================================================== -1) SQLite support. +nope ================================================================== From 46392bf738f6cd1c475f7bd71cf7f03b8754fcab Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 18 Nov 2014 05:54:46 +0000 Subject: [PATCH 325/805] short-term credentials script changed to use sqlite --- .../shorttermsecure/secure_relay_short_term_mech.sh | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh b/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh index e7cfeb56..4cbfb0ed 100755 --- a/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh +++ b/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh @@ -4,8 +4,7 @@ # secure mode with short-term security mechanism - see option -A # that means "use short-term credential mechanism". # -# The short-term credentials mechanism must be used with PostgreSQL or -# MySQL database only, the flat file userdb cannot be used. +# The user credentials are stored in the database. # # We listen on available interfaces here, and we use the "external" IPs # for relay endpoints allocation. @@ -16,9 +15,7 @@ # 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) --mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" -# means that local MySQL database "coturn" will be used, with database user "turn" and -# database user password "turn", and connection timeout 30 seconds. +# 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. @@ -34,4 +31,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 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --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 -E 127.0.0.1 -E ::1 --cipher-list=ALL:SSLv2 $@ +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 $@ From 21723a221b9dc8d88c1a637f1658240351cb138e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 18 Nov 2014 06:19:15 +0000 Subject: [PATCH 326/805] INSTALL updated --- INSTALL | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/INSTALL b/INSTALL index 85d314d7..b80372ee 100644 --- a/INSTALL +++ b/INSTALL @@ -328,10 +328,10 @@ installation: $ cd /usr/ports/databases/hiredis/ $ sudo make install clean - **) Linux Ubuntu 11.10+, Debian Wheezy, Mint 14+: + **) Linux Ubuntu, Debian, Mint: $ sudo apt-get install libssl-dev - $ sudo apt-get install sqlite3-dev + $ sudo apt-get install sqlite3-dev (or libsqlite3-dev) $ sudo apt-get install libevent-dev $ sudo apt-get install libpq-dev $ sudo apt-get install mysql-client From cf93f38218d2e575a451eb083224fbba9b962017 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 18 Nov 2014 06:25:16 +0000 Subject: [PATCH 327/805] a log message removed --- src/apps/relay/dbdrivers/dbd_sqlite.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 08d0d0be..367332f7 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -46,9 +46,7 @@ static int sqlite_init_multithreaded(void) { if (sqlite3_threadsafe() > 0) { int retCode = sqlite3_config(SQLITE_CONFIG_SERIALIZED); - if (retCode == SQLITE_OK) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Can now use sqlite on multiple threads, using the same connection\n"); - } else { + if (retCode != SQLITE_OK) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "setting sqlite thread safe mode to serialized failed!!! return code: %d\n", retCode); return -1; } From 9c8743e002d73b317b878d516bddd5e5a590936e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 18 Nov 2014 07:57:19 +0000 Subject: [PATCH 328/805] INSTALL updated --- INSTALL | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/INSTALL b/INSTALL index b80372ee..21596eed 100644 --- a/INSTALL +++ b/INSTALL @@ -331,7 +331,8 @@ installation: **) Linux Ubuntu, Debian, Mint: $ sudo apt-get install libssl-dev - $ sudo apt-get install sqlite3-dev (or libsqlite3-dev) + $ sudo apt-get install libsqlite3 (or sqlite3) + $ sudo apt-get install libsqlite3-dev (or sqlite3-dev) $ sudo apt-get install libevent-dev $ sudo apt-get install libpq-dev $ sudo apt-get install mysql-client From 924fa29c5e8206f710de337d88c6e17b56b40d95 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 19 Nov 2014 18:41:24 +0000 Subject: [PATCH 329/805] make SQLite optional --- README.turnadmin | 4 +- README.turnserver | 6 +-- README.turnutils | 2 +- configure | 53 +++++++++++++-------------- examples/etc/turnserver.conf | 4 +- man/man1/turnadmin.1 | 6 +-- man/man1/turnserver.1 | 8 ++-- man/man1/turnutils.1 | 4 +- src/apps/relay/dbdrivers/dbd_sqlite.c | 15 +++++++- src/apps/relay/dbdrivers/dbdriver.c | 53 +++++++++++++++------------ src/apps/relay/mainrelay.c | 21 +++++++++-- src/apps/relay/turncli.c | 2 + src/apps/relay/userdb.h | 7 +++- 13 files changed, 111 insertions(+), 74 deletions(-) diff --git a/README.turnadmin b/README.turnadmin index 22d1f70f..a2f6b27d 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -80,7 +80,7 @@ Commands: Options with required values: --b, --db, --userdb SQLite user database file name (default - ~/turndb). +-b, --db, --userdb SQLite user database file name (default - /var/db/turndb). See the same option in the turnserver section. -e, --psql-userdb PostgreSQL user database connection string. See the --psql-userdb option in the turnserver section. @@ -170,7 +170,7 @@ to see the man page. /etc/turnserver.conf -~/turndb +/var/db/turndb /usr/local/etc/turnserver.conf diff --git a/README.turnserver b/README.turnserver index a2199b28..867cfd5b 100644 --- a/README.turnserver +++ b/README.turnserver @@ -81,7 +81,7 @@ Config file settings: User database settings: --b, --db, --userdb SQLite user database file name (default - ~/turndb). +-b, --db, --userdb SQLite user database file name (default - /var/db/turndb). -e, --psql-userdb User database connection string for PostgreSQL. This database can be used for long-term and short-term @@ -716,7 +716,7 @@ For the user database, the turnserver has the following options: Obviously, only a few users can be set that way, and their credentials are fixed for the turnserver process lifetime. -2) Users can be stored in SQLite DB. The default SQLite database file is ~/turndb. +2) Users can be stored in SQLite DB. The default SQLite database file is /var/db/turndb. 3) Users can be stored in PostgreSQL database, if the turnserver was compiled with PostgreSQL support. Each time turnserver checks user credentials, it reads the database (asynchronously, @@ -841,7 +841,7 @@ FILES /etc/turnserver.conf -~/turndb +/var/db/turndb /usr/local/etc/turnserver.conf diff --git a/README.turnutils b/README.turnutils index 8beaf824..61757a28 100644 --- a/README.turnutils +++ b/README.turnutils @@ -251,7 +251,7 @@ FILES /etc/turnserver.conf -~/turndb +/var/db/turndb /usr/local/etc/turnserver.conf diff --git a/configure b/configure index bf3e8e4e..c722a509 100755 --- a/configure +++ b/configure @@ -959,32 +959,6 @@ else TURN_NO_GCM="-DTURN_NO_GCM" fi -########################### -# Test SQLite setup -########################### - -testlib sqlite3 -ER=$? -if ! [ ${ER} -eq 0 ] ; then - ${ECHO_CMD} "SQLite library found." -else - ${ECHO_CMD} "ERROR: SQLite3 development library cannot be found." - cleanup - exit -fi - -testsqlite_comp -ER=$? -if ! [ ${ER} -eq 0 ] ; then - ${ECHO_CMD} "SQLite development found." -else - ${ECHO_CMD} "ERROR: SQLite development libraries are not installed properly in required location." - ${ECHO_CMD} "See the INSTALL file." - ${ECHO_CMD} "Abort." - cleanup - exit -fi - ########################### # Test Libevent2 setup ########################### @@ -1055,6 +1029,31 @@ else exit fi +########################### +# Test SQLite setup +########################### + +if [ -z "${TURN_NO_SQLITE}" ] ; then + + testlib sqlite3 + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "SQLite library found." + else + ${ECHO_CMD} "SQLite3 development library cannot be found." + TURN_NO_SQLITE="-DTURN_NO_SQLITE" + fi + + testsqlite_comp + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "SQLite development found." + else + ${ECHO_CMD} "SQLite development libraries are not installed properly in required location." + TURN_NO_SQLITE="-DTURN_NO_SQLITE" + fi +fi + ########################### # Test PostgreSQL ########################### @@ -1178,7 +1177,7 @@ ${ECHO_CMD} "LDFLAGS += ${OSLIBS}" >> Makefile ${ECHO_CMD} "DBLIBS += ${DBLIBS}" >> Makefile ${ECHO_CMD} "CFLAGS += ${OSCFLAGS}" >> Makefile ${ECHO_CMD} "CPPFLAGS = ${CPPFLAGS}" >> Makefile -${ECHO_CMD} "DBCFLAGS += ${DBCFLAGS} ${TURN_NO_PQ} ${TURN_NO_MYSQL} ${TURN_NO_MONGO} ${TURN_NO_HIREDIS}" >> Makefile +${ECHO_CMD} "DBCFLAGS += ${DBCFLAGS} ${TURN_NO_PQ} ${TURN_NO_MYSQL} ${TURN_NO_SQLITE} ${TURN_NO_MONGO} ${TURN_NO_HIREDIS}" >> Makefile ${ECHO_CMD} "#" >> Makefile ${ECHO_CMD} "PORTNAME = ${PORTNAME}" >> Makefile ${ECHO_CMD} "PREFIX = ${PREFIX}" >> Makefile diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index e853f500..3e6cd203 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -250,9 +250,9 @@ # SQLite database file name. # -# Default file name is ~/turndb (turndb in the process' home directory). +# Default file name is /var/db/turndb (turndb in the process' home directory). # -#userdb=~/turndb +#userdb=/var/db/turndb # PostgreSQL database connection string in the case that we are using PostgreSQL # as the user database. diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index dd0cf25d..85470c69 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "16 November 2014" "" "" +.TH TURN 1 "19 November 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage @@ -132,7 +132,7 @@ Options with required values: .TP .B \fB\-b\fP, \fB\-\-db\fP, \fB\-\-userdb\fP -SQLite user database file name (default \- ~/turndb). +SQLite user database file name (default \- /var/db/turndb). See the same option in the \fIturnserver\fP section. .TP .B @@ -261,7 +261,7 @@ to see the man page. /etc/turnserver.conf .PP -~/turndb +/var/db/turndb .PP /usr/local/etc/turnserver.conf .PP diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index bad4a5df..5cdc166c 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "16 November 2014" "" "" +.TH TURN 1 "19 November 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -132,7 +132,7 @@ User database settings: .TP .B \fB\-b\fP, \fB\-\-db\fP, \fB\-\-userdb\fP -SQLite user database file name (default \- ~/turndb). +SQLite user database file name (default \- /var/db/turndb). .TP .B \fB\-e\fP, \fB\-\-psql\-userdb\fP @@ -971,7 +971,7 @@ Users can be set in the command line, with multiple \fB\-u\fP or \fB\-\-user\fP Obviously, only a few users can be set that way, and their credentials are fixed for the \fIturnserver\fP process lifetime. .IP 2) 4 -Users can be stored in SQLite DB. The default SQLite database file is ~/turndb. +Users can be stored in SQLite DB. The default SQLite database file is /var/db/turndb. .IP 3) 4 Users can be stored in PostgreSQL database, if the \fIturnserver\fP was compiled with PostgreSQL support. Each time \fIturnserver\fP checks user credentials, it reads the database (asynchronously, @@ -1096,7 +1096,7 @@ it would affect the performance. /etc/turnserver.conf .PP -~/turndb +/var/db/turndb .PP /usr/local/etc/turnserver.conf .PP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 6df707ae..b2a60223 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "16 November 2014" "" "" +.TH TURN 1 "19 November 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -374,7 +374,7 @@ to see the man page. /etc/turnserver.conf .PP -~/turndb +/var/db/turndb .PP /usr/local/etc/turnserver.conf .PP diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 367332f7..0bb60956 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -32,6 +32,8 @@ #include "../mainrelay.h" #include "dbd_sqlite.h" +#if !defined(TURN_NO_SQLITE) + #include #include @@ -124,7 +126,12 @@ static sqlite3 * get_sqlite_connection(void) { int rc = sqlite3_open(pud->userdb, &sqliteconnection); if(!sqliteconnection || (rc != SQLITE_OK)) { const char* errmsg = sqlite3_errmsg(sqliteconnection); - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open SQLite DB connection: <%s>, runtime error: %s\n",pud->userdb,errmsg); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open SQLite DB connection: <%s>, runtime error:\n %s\n (If your intention is to use a database for the TURN server, then\n check the TURN server process / file / DB directory permissions and\n re-start the TURN server)\n",pud->userdb,errmsg); + if(sqliteconnection) { + sqlite3_close(sqliteconnection); + sqliteconnection=NULL; + } + turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_UNKNOWN; } else if(!donot_print_connection_success){ init_sqlite_database(sqliteconnection); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SQLite DB connection success: %s\n",pud->userdb); @@ -923,8 +930,12 @@ static turn_dbdriver_t driver = { &sqlite_list_oauth_keys }; -/////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////// turn_dbdriver_t * get_sqlite_dbdriver(void) { return &driver; } + +////////////////////////////////////////////////// + +#endif diff --git a/src/apps/relay/dbdrivers/dbdriver.c b/src/apps/relay/dbdrivers/dbdriver.c index ecae7039..f51ac72a 100644 --- a/src/apps/relay/dbdrivers/dbdriver.c +++ b/src/apps/relay/dbdrivers/dbdriver.c @@ -60,36 +60,43 @@ persistent_users_db_t * get_persistent_users_db(void) { return &(turn_params.default_users_db.persistent_users_db); } -turn_dbdriver_t * get_dbdriver() { - if (!_driver) { - switch(turn_params.default_users_db.userdb_type) { - case TURN_USERDB_TYPE_SQLITE: - _driver = get_sqlite_dbdriver(); - break; +turn_dbdriver_t * get_dbdriver() +{ + + if (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_UNKNOWN) + return NULL; + + if (!_driver) { + switch (turn_params.default_users_db.userdb_type){ +#if !defined(TURN_NO_SQLITE) + case TURN_USERDB_TYPE_SQLITE: + _driver = get_sqlite_dbdriver(); + break; +#endif #if !defined(TURN_NO_PQ) - case TURN_USERDB_TYPE_PQ: - _driver = get_pgsql_dbdriver(); - break; + case TURN_USERDB_TYPE_PQ: + _driver = get_pgsql_dbdriver(); + break; #endif #if !defined(TURN_NO_MYSQL) - case TURN_USERDB_TYPE_MYSQL: - _driver = get_mysql_dbdriver(); - break; + case TURN_USERDB_TYPE_MYSQL: + _driver = get_mysql_dbdriver(); + break; #endif #if !defined(TURN_NO_MONGO) - case TURN_USERDB_TYPE_MONGO: - _driver = get_mongo_dbdriver(); - break; + case TURN_USERDB_TYPE_MONGO: + _driver = get_mongo_dbdriver(); + break; #endif #if !defined(TURN_NO_HIREDIS) - case TURN_USERDB_TYPE_REDIS: - _driver = get_redis_dbdriver(); - break; + case TURN_USERDB_TYPE_REDIS: + _driver = get_redis_dbdriver(); + break; #endif - default: - break; - } - } - return _driver; + default: + break; + } + } + return _driver; } diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 77aca642..f92fa8f4 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -412,7 +412,9 @@ static char Usage[] = "Usage: turnserver [options]\n" " Total bytes-per-second bandwidth the TURN server is allowed to allocate\n" " for the sessions, combined (input and output network streams are treated separately).\n" " -c Configuration file name (default - turnserver.conf).\n" -" -b, , --db, --userdb SQLite database file name (default - ~/turndb).\n" +#if !defined(TURN_NO_SQLITE) +" -b, , --db, --userdb SQLite database file name (default - /var/db/turndb).\n" +#endif #if !defined(TURN_NO_PQ) " -e, --psql-userdb, --sql-userdb 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" @@ -584,7 +586,9 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" " -g, --set-realm-option Set realm params: max-bps, total-quota, user-quota.\n" " -G, --list-realm-options List realm params.\n" "\nOptions with mandatory values:\n\n" - " -b, --db, --userdb SQLite database file, default value is ~/turndb.\n" +#if !defined(TURN_NO_SQLITE) + " -b, --db, --userdb SQLite database file, default value is /var/db/turndb.\n" +#endif #if !defined(TURN_NO_PQ) " -e, --psql-userdb, --sql-userdb PostgreSQL user database connection string, if PostgreSQL DB is used.\n" #endif @@ -600,7 +604,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" " -u, --user Username\n" " -r, --realm Realm for long-term mechanism only\n" " -p, --password Password\n" -#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS) +#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" #endif " -H, --sha256 Use SHA256 digest function to be used for the message integrity.\n" @@ -714,8 +718,10 @@ static const struct myoption long_options[] = { { "st-cred-mech", optional_argument, NULL, 'A' }, { "no-auth", optional_argument, NULL, 'z' }, { "user", required_argument, NULL, 'u' }, +#if !defined(TURN_NO_SQLITE) { "userdb", required_argument, NULL, 'b' }, { "db", required_argument, NULL, 'b' }, +#endif #if !defined(TURN_NO_PQ) { "psql-userdb", required_argument, NULL, 'e' }, { "sql-userdb", required_argument, NULL, 'e' }, @@ -810,8 +816,10 @@ static const struct myoption admin_long_options[] = { { "delete-all-secrets", no_argument, NULL, DEL_ALL_AUTH_SECRETS_OPT }, { "add-st", no_argument, NULL, 'A' }, { "delete-st", no_argument, NULL, 'D' }, +#if !defined(TURN_NO_SQLITE) { "userdb", required_argument, NULL, 'b' }, { "db", required_argument, NULL, 'b' }, +#endif #if !defined(TURN_NO_PQ) { "psql-userdb", required_argument, NULL, 'e' }, { "sql-userdb", required_argument, NULL, 'e' }, @@ -1104,10 +1112,12 @@ static void set_option(int c, char *value) case 'u': add_user_account(value,0); break; +#if !defined(TURN_NO_SQLITE) case 'b': STRCPY(turn_params.default_users_db.persistent_users_db.userdb, value); turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_SQLITE; break; +#endif #if !defined(TURN_NO_PQ) case 'e': STRCPY(turn_params.default_users_db.persistent_users_db.userdb, value); @@ -1469,10 +1479,12 @@ static int adminmain(int argc, char **argv) case DEL_ALL_AUTH_SECRETS_OPT: ct = TA_DEL_SECRET; break; +#if !defined(TURN_NO_SQLITE) case 'b': STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg); turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_SQLITE; break; +#endif #if !defined(TURN_NO_PQ) case 'e': STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg); @@ -1587,8 +1599,9 @@ static void print_features(unsigned long mfn) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "AEAD supported\n"); #endif +#if !defined(TURN_NO_SQLITE) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SQLite supported\n"); - +#endif #if !defined(TURN_NO_HIREDIS) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis supported\n"); #else diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index cf129080..4f86d916 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -781,9 +781,11 @@ static void cli_print_configuration(struct cli_session* cs) if(turn_params.default_users_db.persistent_users_db.userdb[0]) { switch(turn_params.default_users_db.userdb_type) { +#if !defined(TURN_NO_SQLITE) case TURN_USERDB_TYPE_SQLITE: cli_print_str(cs,"SQLite","DB type",0); break; +#endif #if !defined(TURN_NO_PQ) case TURN_USERDB_TYPE_PQ: cli_print_str(cs,"Postgres","DB type",0); diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index dc4890fc..faf4504f 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -48,7 +48,7 @@ extern "C" { //////////// Defines ////////////////////////////// -#define DEFAULT_USERDB_FILE ("~/turndb") +#define DEFAULT_USERDB_FILE ("/var/db/turndb") #define AUTH_SECRET_SIZE (512) @@ -100,7 +100,12 @@ struct auth_message { }; enum _TURN_USERDB_TYPE { +#if !defined(TURN_NO_SQLITE) + TURN_USERDB_TYPE_UNKNOWN=-1, TURN_USERDB_TYPE_SQLITE=0 +#else + TURN_USERDB_TYPE_UNKNOWN=0 +#endif #if !defined(TURN_NO_PQ) ,TURN_USERDB_TYPE_PQ #endif From a80a33b111c55d592bd89233b64fe91ee290d0d0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 19 Nov 2014 18:46:19 +0000 Subject: [PATCH 330/805] INSTALL updated --- INSTALL | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/INSTALL b/INSTALL index 21596eed..02da4e6d 100644 --- a/INSTALL +++ b/INSTALL @@ -225,26 +225,20 @@ V. PLATFORMS The TURN Server is using generic *NIX system APIs and is supposed to be usable on wide range of *NIX systems. -The following platforms have been used in the development: +The following platforms have been used in the development (i386 and x86_64): - - Linux Ubuntu 11.x and 12.x, i386 and x86_64 - - FreeBSD 6.x, i386 - - FreeBSD 8.x, i386 - - PC-BSD 9.x, x86_64 - - Solaris 11, x86_64 - - Linux CentOS / Red Hat Enterprise Edition 6.x-7.0, x86_64 (i386 & amd64) - - Linux Debian 'Squeeze', i386 - - Linux Mint 14.1 'Nadia', i386 - - Linux Mint 16 'Petra', i386 - - Linux Debian 'Wheezy', x86_64 + - Linux Ubuntu, Mint, Debian, + - FreeBSD, + - Solaris 11, + - Linux CentOS / Red Hat Enterprise Edition 6.x-7.0, x86_64 - Cygwin 1.7.20 - - NetBSD 6.0.1, i386 - - OpenBSD 5.3, i386 - - Amazon Linux, x86_64 - - Mac OS X Mountain Lion - - ArchLinux, x86_64 - - Fedora 19 and 20, x86_64 - - OpenSUSE 12.3, x86_64 + - NetBSD 6.0.1, + - OpenBSD 5.3, + - Amazon Linux, + - Mac OS X, + - ArchLinux, + - Fedora, + - OpenSUSE It must work on many other *NIXes, as well. The configure script and/or Makefile may need adjustments for other *NIXes not mentioned above. @@ -259,9 +253,9 @@ and for the performance reasons. The tested C compilers are: - - gcc 3.4.4 thru 4.8.1 + - gcc 3.4.4 thru 4.8.x - clang 3.0 or better - - Solaris Studio 12.3 C compiler, version 5.12 + - Solaris Studio 12 C and C++ compilers It may be compiled with others compilers, too. @@ -287,7 +281,7 @@ static linking, then even runtime installation is not needed. OpenSSL, SQLite, libevent2, PostgreSQL, MySQL (or MariaDB) and Hiredis libraries can be downloaded from their web sites: - http://www.openssl.org (required); - - http://www.sqlite.org (required); + - http://www.sqlite.org (optional); - http://www.libevent.org (required); - http://www.postgresql.org (optional); - http://www.mysql.org (or http://mariadb.org) (optional); From c7cf2af4014199333e9b16a7c075e143a921f2d0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 19 Nov 2014 18:52:26 +0000 Subject: [PATCH 331/805] optional SQLite support --- src/apps/relay/mainrelay.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index f92fa8f4..2266a5ae 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -95,7 +95,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_SQLITE, {"\0",NULL}, {0,NULL,NULL, {NULL,0}} } +{ 0, {"\0",NULL}, {0,NULL,NULL, {NULL,0}} } }; @@ -1547,8 +1547,10 @@ static int adminmain(int argc, char **argv) } } +#if !defined(TURN_NO_SQLITE) if(!strlen(turn_params.default_users_db.persistent_users_db.userdb) && (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_SQLITE)) STRCPY(turn_params.default_users_db.persistent_users_db.userdb,DEFAULT_USERDB_FILE); +#endif if(ct == TA_COMMAND_UNKNOWN) { fprintf(stderr,"\n%s\n", AdminUsage); @@ -1601,7 +1603,10 @@ static void print_features(unsigned long mfn) #if !defined(TURN_NO_SQLITE) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SQLite supported\n"); +#else + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SQLite is not supported\n"); #endif + #if !defined(TURN_NO_HIREDIS) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis supported\n"); #else @@ -1852,8 +1857,10 @@ int main(int argc, char **argv) TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "\nCONFIG: WARNING: --server-relay: NON-STANDARD AND DANGEROUS OPTION.\n"); } +#if !defined(TURN_NO_SQLITE) if(!strlen(turn_params.default_users_db.persistent_users_db.userdb) && (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_SQLITE)) STRCPY(turn_params.default_users_db.persistent_users_db.userdb,DEFAULT_USERDB_FILE); +#endif update_white_and_black_lists(); From 221f014a6c6fea0f236fbdf3336d38852a7afe51 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 20 Nov 2014 02:56:53 +0000 Subject: [PATCH 332/805] working on sqlite install --- Makefile.in | 3 ++ README.turnadmin | 4 +- README.turnserver | 6 +-- README.turnutils | 2 +- configure | 46 +++++++++++++++---- examples/etc/turnserver.conf | 4 +- .../secure_relay_with_db_sqlite.sh | 2 +- .../secure_relay_secret_with_db_sqlite.sh | 2 +- .../secure_relay_short_term_mech.sh | 4 +- man/man1/turnadmin.1 | 4 +- man/man1/turnserver.1 | 6 +-- man/man1/turnutils.1 | 2 +- src/apps/relay/mainrelay.c | 6 +-- src/apps/relay/userdb.h | 2 +- 14 files changed, 61 insertions(+), 32 deletions(-) diff --git a/Makefile.in b/Makefile.in index ea5ea7b0..60868365 100755 --- a/Makefile.in +++ b/Makefile.in @@ -104,6 +104,7 @@ distclean: clean install: all ${MAKE_DEPS} ${MKDIR} ${DESTDIR}${PREFIX} ${MKDIR} ${DESTDIR}${BINDIR} + ${MKDIR} ${DESTDIR}${LOCALSTATEDIR} ${MKDIR} ${DESTDIR}${MANPREFIX}/man/man1 ${MKDIR} ${DESTDIR}${CONFDIR} ${MKDIR} ${DESTDIR}${LIBDIR} @@ -147,10 +148,12 @@ install: all ${MAKE_DEPS} ${RMCMD} ${DESTDIR}${EXAMPLESDIR}/scripts/rfc5769.sh ${INSTALL_DIR} include/turn/client ${DESTDIR}${TURNINCLUDEDIR} ${INSTALL_DATA} include/turn/ns_turn_defs.h ${DESTDIR}${TURNINCLUDEDIR} + ${SQLITECMD} ${DESTDIR}${LOCALSTATEDIR}/turndb < turndb/schema.sql ${MORECMD} ${DESTDIR}${DOCSDIR}/postinstall.txt deinstall: ${MAKE_DEPS} ${PKILL_PROGRAM} turnserver || ${ECHO_CMD} OK + ${RMCMD} ${DESTDIR}${LOCALSTATEDIR}/turndb ${RMCMD} ${DESTDIR}${DOCSDIR} ${RMCMD} ${DESTDIR}${SCHEMADIR} ${RMCMD} ${DESTDIR}${BINDIR}/turnserver diff --git a/README.turnadmin b/README.turnadmin index a2f6b27d..269dfbbb 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -80,7 +80,7 @@ Commands: Options with required values: --b, --db, --userdb SQLite user database file name (default - /var/db/turndb). +-b, --db, --userdb SQLite user database file name (default - /var/turndb). See the same option in the turnserver section. -e, --psql-userdb PostgreSQL user database connection string. See the --psql-userdb option in the turnserver section. @@ -170,7 +170,7 @@ to see the man page. /etc/turnserver.conf -/var/db/turndb +/var/turndb /usr/local/etc/turnserver.conf diff --git a/README.turnserver b/README.turnserver index 867cfd5b..6bda58dd 100644 --- a/README.turnserver +++ b/README.turnserver @@ -81,7 +81,7 @@ Config file settings: User database settings: --b, --db, --userdb SQLite user database file name (default - /var/db/turndb). +-b, --db, --userdb SQLite user database file name (default - /var/turndb). -e, --psql-userdb User database connection string for PostgreSQL. This database can be used for long-term and short-term @@ -716,7 +716,7 @@ For the user database, the turnserver has the following options: Obviously, only a few users can be set that way, and their credentials are fixed for the turnserver process lifetime. -2) Users can be stored in SQLite DB. The default SQLite database file is /var/db/turndb. +2) Users can be stored in SQLite DB. The default SQLite database file is /var/turndb. 3) Users can be stored in PostgreSQL database, if the turnserver was compiled with PostgreSQL support. Each time turnserver checks user credentials, it reads the database (asynchronously, @@ -841,7 +841,7 @@ FILES /etc/turnserver.conf -/var/db/turndb +/var/turndb /usr/local/etc/turnserver.conf diff --git a/README.turnutils b/README.turnutils index 61757a28..42f9359a 100644 --- a/README.turnutils +++ b/README.turnutils @@ -251,7 +251,7 @@ FILES /etc/turnserver.conf -/var/db/turndb +/var/turndb /usr/local/etc/turnserver.conf diff --git a/configure b/configure index c722a509..b1ddc0d1 100755 --- a/configure +++ b/configure @@ -346,6 +346,11 @@ do -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) BINDIR=$ac_optarg ;; + -localstatedir | --localstatedir | --localstatedi | --localstated | --localstate | --localstat) + ac_prev=LOCALSTATEDIR ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* | --localstate=* | --localstat=*) + LOCALSTATEDIR=$ac_optarg ;; + -datadir | --datadir | --datadi | --datad | -schemadir | --schemadir) ac_prev=SCHEMADIR ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | -schemadir=* | --schemadir=*) @@ -432,9 +437,17 @@ fi if [ -z "${BINDIR}" ] ; then if [ -z "${bindir}" ] ; then - BINDIR=${PREFIX}/bin + BINDIR=${PREFIX}/bin else - BINDIR=${bindir} + BINDIR=${bindir} + fi +fi + +if [ -z "${LOCALSTATEDIR}" ] ; then + if [ -z "${localstatedir}" ] ; then + LOCALSTATEDIR=/var + else + LOCALSTATEDIR=${localstatedir} fi fi @@ -591,6 +604,14 @@ INSTALL_DIR="cp -rpf" MKBUILDDIR="mkdir -p" RMCMD="rm -rf" +type sqlite3 2>>/dev/null +ER=$? +if [ ${ER} -eq 0 ] ; then + SQLITECMD="sqlite3" +else + SQLITECMD="echo" +fi + ############################# # Adjustments for Solaris ############################# @@ -1043,14 +1064,16 @@ if [ -z "${TURN_NO_SQLITE}" ] ; then ${ECHO_CMD} "SQLite3 development library cannot be found." TURN_NO_SQLITE="-DTURN_NO_SQLITE" fi - - testsqlite_comp - ER=$? - if ! [ ${ER} -eq 0 ] ; then - ${ECHO_CMD} "SQLite development found." - else - ${ECHO_CMD} "SQLite development libraries are not installed properly in required location." - TURN_NO_SQLITE="-DTURN_NO_SQLITE" + + if [ -z "${TURN_NO_SQLITE}" ] ; then + testsqlite_comp + ER=$? + if ! [ ${ER} -eq 0 ] ; then + ${ECHO_CMD} "SQLite development found." + else + ${ECHO_CMD} "SQLite development libraries are not installed properly in required location." + TURN_NO_SQLITE="-DTURN_NO_SQLITE" + fi fi fi @@ -1184,6 +1207,8 @@ ${ECHO_CMD} "PREFIX = ${PREFIX}" >> Makefile ${ECHO_CMD} "prefix = ${PREFIX}" >> Makefile ${ECHO_CMD} "BINDIR = ${BINDIR}" >> Makefile ${ECHO_CMD} "bindir = ${BINDIR}" >> Makefile +${ECHO_CMD} "LOCALSTATEDIR = ${LOCALSTATEDIR}" >> Makefile +${ECHO_CMD} "localstatedir = ${LOCALSTATEDIR}" >> Makefile ${ECHO_CMD} "CONFDIR = ${CONFDIR}" >> Makefile ${ECHO_CMD} "confdir = ${CONFDIR}" >> Makefile ${ECHO_CMD} "MANPREFIX = ${MANPREFIX}" >> Makefile @@ -1203,6 +1228,7 @@ ${ECHO_CMD} "turnincludedir = ${TURNINCLUDEDIR}" >> Makefile ${ECHO_CMD} "#" >> Makefile ${ECHO_CMD} "ARCHIVERCMD = ${ARCHIVERCMD}" >> Makefile ${ECHO_CMD} "MKDIR = ${MKDIR}" >> Makefile +${ECHO_CMD} "SQLITECMD = ${SQLITECMD}" >> Makefile ${ECHO_CMD} "INSTALL_PROGRAM = ${INSTALL_PROGRAM}" >> Makefile ${ECHO_CMD} "PKILL_PROGRAM = ${PKILL_PROGRAM}" >> Makefile ${ECHO_CMD} "INSTALL_MAN = ${INSTALL_MAN}" >> Makefile diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 3e6cd203..90c0d60c 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -250,9 +250,9 @@ # SQLite database file name. # -# Default file name is /var/db/turndb (turndb in the process' home directory). +# Default file name is /var/turndb. # -#userdb=/var/db/turndb +#userdb=/var/turndb # PostgreSQL database connection string in the case that we are using PostgreSQL # as the user database. diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh index c160af38..a574cc00 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh @@ -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/turndb" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 --oauth $@ diff --git a/examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh b/examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh index c4fa65e1..f2a47720 100755 --- a/examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh +++ b/examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh @@ -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/turndb" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL:SSLv2 $@ diff --git a/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh b/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh index 4cbfb0ed..cd757393 100755 --- a/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh +++ b/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh @@ -15,7 +15,7 @@ # 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. +# 5) --db="var/turndb" means that SQLite database "var/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. @@ -31,4 +31,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 --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 $@ +PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver -v --syslog -A --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --db="var/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 $@ diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 85470c69..04a17b64 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -132,7 +132,7 @@ Options with required values: .TP .B \fB\-b\fP, \fB\-\-db\fP, \fB\-\-userdb\fP -SQLite user database file name (default \- /var/db/turndb). +SQLite user database file name (default \- /var/turndb). See the same option in the \fIturnserver\fP section. .TP .B @@ -261,7 +261,7 @@ to see the man page. /etc/turnserver.conf .PP -/var/db/turndb +/var/turndb .PP /usr/local/etc/turnserver.conf .PP diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 5cdc166c..39b3bf2b 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -132,7 +132,7 @@ User database settings: .TP .B \fB\-b\fP, \fB\-\-db\fP, \fB\-\-userdb\fP -SQLite user database file name (default \- /var/db/turndb). +SQLite user database file name (default \- /var/turndb). .TP .B \fB\-e\fP, \fB\-\-psql\-userdb\fP @@ -971,7 +971,7 @@ Users can be set in the command line, with multiple \fB\-u\fP or \fB\-\-user\fP Obviously, only a few users can be set that way, and their credentials are fixed for the \fIturnserver\fP process lifetime. .IP 2) 4 -Users can be stored in SQLite DB. The default SQLite database file is /var/db/turndb. +Users can be stored in SQLite DB. The default SQLite database file is /var/turndb. .IP 3) 4 Users can be stored in PostgreSQL database, if the \fIturnserver\fP was compiled with PostgreSQL support. Each time \fIturnserver\fP checks user credentials, it reads the database (asynchronously, @@ -1096,7 +1096,7 @@ it would affect the performance. /etc/turnserver.conf .PP -/var/db/turndb +/var/turndb .PP /usr/local/etc/turnserver.conf .PP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index b2a60223..979f6d58 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -374,7 +374,7 @@ to see the man page. /etc/turnserver.conf .PP -/var/db/turndb +/var/turndb .PP /usr/local/etc/turnserver.conf .PP diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 2266a5ae..79881b2f 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -95,7 +95,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 ////////////// -{ 0, {"\0",NULL}, {0,NULL,NULL, {NULL,0}} } +{ (TURN_USERDB_TYPE)0, {"\0",NULL}, {0,NULL,NULL, {NULL,0}} } }; @@ -413,7 +413,7 @@ static char Usage[] = "Usage: turnserver [options]\n" " for the sessions, combined (input and output network streams are treated separately).\n" " -c Configuration file name (default - turnserver.conf).\n" #if !defined(TURN_NO_SQLITE) -" -b, , --db, --userdb SQLite database file name (default - /var/db/turndb).\n" +" -b, , --db, --userdb SQLite database file name (default - /var/turndb).\n" #endif #if !defined(TURN_NO_PQ) " -e, --psql-userdb, --sql-userdb PostgreSQL database connection string, if used (default - empty, no PostreSQL DB used).\n" @@ -587,7 +587,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" " -G, --list-realm-options List realm params.\n" "\nOptions with mandatory values:\n\n" #if !defined(TURN_NO_SQLITE) - " -b, --db, --userdb SQLite database file, default value is /var/db/turndb.\n" + " -b, --db, --userdb SQLite database file, default value is /var/turndb.\n" #endif #if !defined(TURN_NO_PQ) " -e, --psql-userdb, --sql-userdb PostgreSQL user database connection string, if PostgreSQL DB is used.\n" diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index faf4504f..d25164a1 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -48,7 +48,7 @@ extern "C" { //////////// Defines ////////////////////////////// -#define DEFAULT_USERDB_FILE ("/var/db/turndb") +#define DEFAULT_USERDB_FILE ("/var/turndb") #define AUTH_SECRET_SIZE (512) From c14f9413926cca6d9125f5b2d818e12b4968fea4 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 20 Nov 2014 03:15:57 +0000 Subject: [PATCH 333/805] postinstall --- postinstall.txt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/postinstall.txt b/postinstall.txt index 27a427b8..ffd9f3ff 100644 --- a/postinstall.txt +++ b/postinstall.txt @@ -8,21 +8,25 @@ service, you have to: /usr/local/etc/turnserver.conf . Use /usr/local/etc/turnserver.conf.default as an example. - b) For user accounts settings, if using the turnserver - with authentication: set up SQLite or PostgreSQL or MySQL or MongoDB or - Redis database for user accounts. + b) For user accounts settings: set up SQLite or PostgreSQL or + MySQL or MongoDB or Redis database for user accounts. Use /usr/local/share/turnserver/schema.sql as SQL database schema, or use /usr/local/share/turnserver/schema.userdb.redis as Redis - database schema description and/or /usr/local/share/turnserver/schema.stats.redis + database schema description and/or + /usr/local/share/turnserver/schema.stats.redis as Redis status & statistics database schema description. + + If you are using SQLite, the default database location is in /var/turndb. - c) add whatever is necessary to enable start-up daemon for the /usr/local/bin/turnserver. + c) add whatever is necessary to enable start-up daemon for the + /usr/local/bin/turnserver. 2) If you do not want the turnserver to be a system service, then you can start/stop it "manually", using the "turnserver" executable with appropriate options (see the documentation). -3) To create database schema, use schema in file /usr/local/share/turnserver/schema.sql. +3) To create database schema, use schema in file +/usr/local/share/turnserver/schema.sql. 4) For additional information, run: From 68f28329fc29b87b73be20dc7c5dab9dc5604a82 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 20 Nov 2014 04:13:49 +0000 Subject: [PATCH 334/805] working on sqlite --- Makefile.in | 6 ++-- README.turnadmin | 6 ++-- README.turnserver | 9 +++-- README.turnutils | 3 +- configure | 12 +++++-- examples/etc/turnserver.conf | 4 +-- .../secure_relay_with_db_sqlite.sh | 2 +- .../secure_relay_secret_with_db_sqlite.sh | 2 +- .../secure_relay_short_term_mech.sh | 4 +-- man/man1/turnadmin.1 | 6 ++-- man/man1/turnserver.1 | 9 +++-- man/man1/turnutils.1 | 3 +- postinstall.txt | 3 +- sqlite/turndb | Bin 0 -> 20480 bytes src/apps/relay/mainrelay.c | 32 ++++++++++++++++-- src/apps/relay/userdb.h | 2 -- 16 files changed, 73 insertions(+), 30 deletions(-) create mode 100644 sqlite/turndb diff --git a/Makefile.in b/Makefile.in index 60868365..7233ec47 100755 --- a/Makefile.in +++ b/Makefile.in @@ -104,7 +104,7 @@ distclean: clean install: all ${MAKE_DEPS} ${MKDIR} ${DESTDIR}${PREFIX} ${MKDIR} ${DESTDIR}${BINDIR} - ${MKDIR} ${DESTDIR}${LOCALSTATEDIR} + ${MKDIR} ${DESTDIR}${LOCALSTATEDIR}/db ${MKDIR} ${DESTDIR}${MANPREFIX}/man/man1 ${MKDIR} ${DESTDIR}${CONFDIR} ${MKDIR} ${DESTDIR}${LIBDIR} @@ -148,12 +148,12 @@ install: all ${MAKE_DEPS} ${RMCMD} ${DESTDIR}${EXAMPLESDIR}/scripts/rfc5769.sh ${INSTALL_DIR} include/turn/client ${DESTDIR}${TURNINCLUDEDIR} ${INSTALL_DATA} include/turn/ns_turn_defs.h ${DESTDIR}${TURNINCLUDEDIR} - ${SQLITECMD} ${DESTDIR}${LOCALSTATEDIR}/turndb < turndb/schema.sql + ${SQLITECMD} ${DESTDIR}${LOCALSTATEDIR}/db/turndb < turndb/schema.sql ${MORECMD} ${DESTDIR}${DOCSDIR}/postinstall.txt deinstall: ${MAKE_DEPS} ${PKILL_PROGRAM} turnserver || ${ECHO_CMD} OK - ${RMCMD} ${DESTDIR}${LOCALSTATEDIR}/turndb + ${RMCMD} ${DESTDIR}${LOCALSTATEDIR}/db/turndb ${RMCMD} ${DESTDIR}${DOCSDIR} ${RMCMD} ${DESTDIR}${SCHEMADIR} ${RMCMD} ${DESTDIR}${BINDIR}/turnserver diff --git a/README.turnadmin b/README.turnadmin index 269dfbbb..97012343 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -80,7 +80,8 @@ Commands: Options with required values: --b, --db, --userdb SQLite user database file name (default - /var/turndb). +-b, --db, --userdb SQLite user database file name (default - /var/db/turndb or + /usr/local/var/db/turndb). See the same option in the turnserver section. -e, --psql-userdb PostgreSQL user database connection string. See the --psql-userdb option in the turnserver section. @@ -170,7 +171,8 @@ to see the man page. /etc/turnserver.conf -/var/turndb +/var/db/turndb +/usr/local/var/db/turndb /usr/local/etc/turnserver.conf diff --git a/README.turnserver b/README.turnserver index 6bda58dd..fc38c045 100644 --- a/README.turnserver +++ b/README.turnserver @@ -81,7 +81,8 @@ Config file settings: User database settings: --b, --db, --userdb SQLite user database file name (default - /var/turndb). +-b, --db, --userdb SQLite user database file name (default - /var/db/turndb or + /usr/local/var/db/turndb). -e, --psql-userdb User database connection string for PostgreSQL. This database can be used for long-term and short-term @@ -716,7 +717,8 @@ For the user database, the turnserver has the following options: Obviously, only a few users can be set that way, and their credentials are fixed for the turnserver process lifetime. -2) Users can be stored in SQLite DB. The default SQLite database file is /var/turndb. +2) Users can be stored in SQLite DB. The default SQLite database file is /var/db/turndb +or /usr/local/var/db/turndb. 3) Users can be stored in PostgreSQL database, if the turnserver was compiled with PostgreSQL support. Each time turnserver checks user credentials, it reads the database (asynchronously, @@ -841,7 +843,8 @@ FILES /etc/turnserver.conf -/var/turndb +/var/db/turndb +/usr/local/var/db/turndb /usr/local/etc/turnserver.conf diff --git a/README.turnutils b/README.turnutils index 42f9359a..7b93fe8e 100644 --- a/README.turnutils +++ b/README.turnutils @@ -251,7 +251,8 @@ FILES /etc/turnserver.conf -/var/turndb +/var/db/turndb +/usr/local/var/db/turndb /usr/local/etc/turnserver.conf diff --git a/configure b/configure index b1ddc0d1..953e3af9 100755 --- a/configure +++ b/configure @@ -445,7 +445,13 @@ fi if [ -z "${LOCALSTATEDIR}" ] ; then if [ -z "${localstatedir}" ] ; then - LOCALSTATEDIR=/var + + if [ "${PREFIX}" = "/usr" ] ; then + LOCALSTATEDIR=/var + else + LOCALSTATEDIR=${PREFIX}/var + fi + else LOCALSTATEDIR=${localstatedir} fi @@ -1176,7 +1182,7 @@ fi # So, what we have now: ############################### -OSCFLAGS="${OSCFLAGS} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX}" +OSCFLAGS="${OSCFLAGS} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX} -DTURNDB=${LOCALSTATEDIR}/db/turndb" if ! [ -z "${TURN_ACCEPT_RPATH}" ] ; then if [ -z "${TURN_DISABLE_RPATH}" ] ; then @@ -1185,7 +1191,7 @@ if ! [ -z "${TURN_ACCEPT_RPATH}" ] ; then fi fi -${ECHO_CMD} PREFIX="${PREFIX}" OSLIBS="${OSLIBS}" DBLIBS="${DBLIBS}" OSCFLAGS="${OSCFLAGS}" DBCFLAGS="${DBCFLAGS}" $@ +${ECHO_CMD} PREFIX="${PREFIX}" LOCALSTATEDIR="${LOCALSTATEDIR}" OSLIBS="${OSLIBS}" DBLIBS="${DBLIBS}" OSCFLAGS="${OSCFLAGS}" DBCFLAGS="${DBCFLAGS}" $@ ############################### # Make make: diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 90c0d60c..9067758f 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -250,9 +250,9 @@ # SQLite database file name. # -# Default file name is /var/turndb. +# Default file name is /var/db/turndb or /usr/local/var/db/turndb. # -#userdb=/var/turndb +#userdb=/var/db/turndb # PostgreSQL database connection string in the case that we are using PostgreSQL # as the user database. diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh index a574cc00..c160af38 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh @@ -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/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:SSLv2 --oauth $@ diff --git a/examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh b/examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh index f2a47720..c4fa65e1 100755 --- a/examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh +++ b/examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh @@ -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/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:SSLv2 $@ diff --git a/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh b/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh index cd757393..4cbfb0ed 100755 --- a/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh +++ b/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh @@ -15,7 +15,7 @@ # 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/turndb" means that SQLite database "var/turndb" will be used. +# 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. @@ -31,4 +31,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 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 --db="var/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 $@ +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 $@ diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 04a17b64..589a90df 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -132,7 +132,8 @@ Options with required values: .TP .B \fB\-b\fP, \fB\-\-db\fP, \fB\-\-userdb\fP -SQLite user database file name (default \- /var/turndb). +SQLite user database file name (default \- /var/db/turndb or +/usr/local/var/db/turndb). See the same option in the \fIturnserver\fP section. .TP .B @@ -261,7 +262,8 @@ to see the man page. /etc/turnserver.conf .PP -/var/turndb +/var/db/turndb +/usr/local/var/db/turndb .PP /usr/local/etc/turnserver.conf .PP diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 39b3bf2b..8095505d 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -132,7 +132,8 @@ User database settings: .TP .B \fB\-b\fP, \fB\-\-db\fP, \fB\-\-userdb\fP -SQLite user database file name (default \- /var/turndb). +SQLite user database file name (default \- /var/db/turndb or +/usr/local/var/db/turndb). .TP .B \fB\-e\fP, \fB\-\-psql\-userdb\fP @@ -971,7 +972,8 @@ Users can be set in the command line, with multiple \fB\-u\fP or \fB\-\-user\fP Obviously, only a few users can be set that way, and their credentials are fixed for the \fIturnserver\fP process lifetime. .IP 2) 4 -Users can be stored in SQLite DB. The default SQLite database file is /var/turndb. +Users can be stored in SQLite DB. The default SQLite database file is /var/db/turndb +or /usr/local/var/db/turndb. .IP 3) 4 Users can be stored in PostgreSQL database, if the \fIturnserver\fP was compiled with PostgreSQL support. Each time \fIturnserver\fP checks user credentials, it reads the database (asynchronously, @@ -1096,7 +1098,8 @@ it would affect the performance. /etc/turnserver.conf .PP -/var/turndb +/var/db/turndb +/usr/local/var/db/turndb .PP /usr/local/etc/turnserver.conf .PP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 979f6d58..1007c87e 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -374,7 +374,8 @@ to see the man page. /etc/turnserver.conf .PP -/var/turndb +/var/db/turndb +/usr/local/var/db/turndb .PP /usr/local/etc/turnserver.conf .PP diff --git a/postinstall.txt b/postinstall.txt index ffd9f3ff..0dbc55dc 100644 --- a/postinstall.txt +++ b/postinstall.txt @@ -16,7 +16,8 @@ service, you have to: /usr/local/share/turnserver/schema.stats.redis as Redis status & statistics database schema description. - If you are using SQLite, the default database location is in /var/turndb. + If you are using SQLite, the default database location is in + /var/db/turndb or in /usr/local/var/db/turndb. c) add whatever is necessary to enable start-up daemon for the /usr/local/bin/turnserver. diff --git a/sqlite/turndb b/sqlite/turndb new file mode 100644 index 0000000000000000000000000000000000000000..45de984f9f0db6ab8e026b6297aeafb044ea24cc GIT binary patch literal 20480 zcmeI2?`zXQ7{_zTmaNt3`~eXJcQU3e+nAkJ1re-LR5sDgi429~wqDoJw5dtz+$+gI zeCt2ppX6Kr0AKnC_{KNhrCFM!>l_tBC{Ll={mk=xKhIqrw!4?>Ylh2k-LhNM#W$r1 z2_fkL#*!pW@$W_cJ^YCJ#9@X1Mv?Nc;*_-XR1SCVs|tbqc1z1P}lM*&vV?ZbY+sHrxU)fB+CkfdJ(H6d;2MAdpc4kpD9p7;p;+ zq(A`je+rPn1Q5t50m%Ou4Gg#i1X3UX`9B57U;+qalmO)aj0OhW0s<)zfc&2VWH12) zGD-mQe?|iXZUKQ52#EZzNk1j&C;E!M%dh1x%DnP61;eSE@NOVYpPxqub1vOBncKD7 zU5D8YG2LicezZ}oY*z7R<>6WtM|*G~kNL-D)NJAR)ZS@OyHGBz6mgB!Y1ee|_3MlN zkTz|x*oa*|nHl z?)k*YJa^ov=Z-t+ouAb7xjE!DL)VGJc5LQ*9u(C9$Ab>;ckTr7c~8x5GC;YGZM3Mp zk41!nF!+zV2Q*H3wuPicC& zjJ&P>rnYQj*Ju;hBL0RIuP>5lI}=lS)Ci%sH!1f1;j4b|Es)#_y?J~KJU*@JZ_2}@ z9c4Dy<_UMtdZlSiUtUHB=lU{zKZwtKp+7Kj6eYX{vQDvOaTI8LID2%KPG_$89-nJ0+9blfCf{5z?cw# z{68jv1Q|eJ1Okx%M}P)XfWVj#5cyw`FG=zx`Hk{zOhkcHv%}Laal9S7 zd69FC7IR$M>fmj0w&;evH~6ubY1Ek*fO!YoWp=Ey(X7=;gE|dT@3wbB6Sr?AEKrB= u3nSFr{o9b^9rZ~Z|CE4LXlGDu?7jl$#SimJGpb&l9Tv0@Fe!z_3x5EY9Hxo@ literal 0 HcmV?d00001 diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 79881b2f..5b40bb52 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -36,6 +36,30 @@ static int use_lt_credentials = 0; static int use_st_credentials = 0; static int anon_credentials = 0; +////// TURNDB ////////////// + +#if defined(TURNDB) + +#if defined(Q) +#undef Q +#endif + +#define Q(x) #x + +#if defined(QUOTE) +#undef QUOTE +#endif + +#define QUOTE(x) Q(x) + +#define DEFAULT_USERDB_FILE QUOTE(TURNDB) + +#else + +#define DEFAULT_USERDB_FILE "/usr/local/var/db/turndb" + +#endif + //////TURN PARAMS STRUCTURE DEFINITION ////// #define DEFAULT_GENERAL_RELAY_SERVERS_NUMBER (1) @@ -413,7 +437,8 @@ static char Usage[] = "Usage: turnserver [options]\n" " for the sessions, combined (input and output network streams are treated separately).\n" " -c Configuration file name (default - turnserver.conf).\n" #if !defined(TURN_NO_SQLITE) -" -b, , --db, --userdb SQLite database file name (default - /var/turndb).\n" +" -b, , --db, --userdb SQLite database file name; default - /var/db/turndb or\n" +" /usr/local/var/db/turndb.\n" #endif #if !defined(TURN_NO_PQ) " -e, --psql-userdb, --sql-userdb PostgreSQL database connection string, if used (default - empty, no PostreSQL DB used).\n" @@ -587,7 +612,8 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" " -G, --list-realm-options List realm params.\n" "\nOptions with mandatory values:\n\n" #if !defined(TURN_NO_SQLITE) - " -b, --db, --userdb SQLite database file, default value is /var/turndb.\n" + " -b, --db, --userdb SQLite database file, default value is /var/db/turndb or\n" + " /usr/local/var/db/turndb.\n" #endif #if !defined(TURN_NO_PQ) " -e, --psql-userdb, --sql-userdb PostgreSQL user database connection string, if PostgreSQL DB is used.\n" @@ -1602,7 +1628,7 @@ static void print_features(unsigned long mfn) #endif #if !defined(TURN_NO_SQLITE) - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SQLite supported\n"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SQLite supported, default database location is %s\n",DEFAULT_USERDB_FILE); #else TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SQLite is not supported\n"); #endif diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index d25164a1..41d37915 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -48,8 +48,6 @@ extern "C" { //////////// Defines ////////////////////////////// -#define DEFAULT_USERDB_FILE ("/var/turndb") - #define AUTH_SECRET_SIZE (512) //////////// REALM ////////////// From 5044cad09187171c763c2ddae6f72246b98785e1 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 20 Nov 2014 06:40:44 +0000 Subject: [PATCH 335/805] rpm updated for sqlite --- rpm/turnserver.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 026b8d1e..5a9f058a 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -167,6 +167,7 @@ fi %defattr(-,root,root) %{_bindir}/turnserver %{_bindir}/turnadmin +%{_localstatedir}/db/turndb %{_mandir}/man1/coturn.1.gz %{_mandir}/man1/turnserver.1.gz %{_mandir}/man1/turnadmin.1.gz From 925532662dbc7aa5d564c19f684dc89fcc8454c3 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 20 Nov 2014 06:57:18 +0000 Subject: [PATCH 336/805] working on sqlite config --- configure | 54 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/configure b/configure index 953e3af9..d4607265 100755 --- a/configure +++ b/configure @@ -32,24 +32,24 @@ testlibraw() { ${CC} ${TMPCPROGC} -o ${TMPCPROGB} ${OSCFLAGS} ${OSLIBS} -${1} 2>>/dev/null ER=$? if ! [ ${ER} -eq 0 ] ; then - ${ECHO_CMD} "Do not use -${1}" - return 0 + ${ECHO_CMD} "Library option -${1} cannot be used" + return 0 else - OSLIBS="${OSLIBS} -${1}" - return 1 + OSLIBS="${OSLIBS} -${1}" + return 1 fi } testsqlite_comp() { - SQLITE_LIBS=-lsqlite3 + SQLITE_LIBS=-lsqlite3 ${CC} -c ${SQL_TMPCPROGC} -o ${SQL_TMPCPROGO} ${OSCFLAGS} 2>>/dev/null ER=$? if ! [ ${ER} -eq 0 ] ; then - ${ECHO_CMD} "SQLite development is not installed properly" - return 0 + ${ECHO_CMD} "SQLite development is not installed properly" + return 0 else - DBLIBS="${DBLIBS} ${SQLITE_LIBS}" - return 1 + DBLIBS="${DBLIBS} ${SQLITE_LIBS}" + return 1 fi } @@ -155,15 +155,15 @@ testlibmongoc() { ER=$? if ! [ ${ER} -eq 0 ] ; then ${ECHO_CMD} - ${ECHO_CMD} "MONGODB DEVELOPMENT LIBRARIES (libmongoc-1.0 and libbson-1.0) AND/OR HEADER (mongoc.h)" - ${ECHO_CMD} " ARE NOT INSTALLED PROPERLY ON THIS SYSTEM." - ${ECHO_CMD} " THAT'S OK BUT THE TURN SERVER IS BUILDING WITHOUT MONGODB SUPPORT." - ${ECHO_CMD} - return 0 + ${ECHO_CMD} "MONGODB DEVELOPMENT LIBRARIES (libmongoc-1.0 and libbson-1.0) AND/OR HEADER (mongoc.h)" + ${ECHO_CMD} " ARE NOT INSTALLED PROPERLY ON THIS SYSTEM." + ${ECHO_CMD} " THAT'S OK BUT THE TURN SERVER IS BUILDING WITHOUT MONGODB SUPPORT." + ${ECHO_CMD} + return 0 else - DBCFLAGS="${DBCFLAGS} ${MONGO_CFLAGS}" - DBLIBS="${DBLIBS} ${MONGO_LIBS}" - return 1 + DBCFLAGS="${DBCFLAGS} ${MONGO_CFLAGS}" + DBLIBS="${DBLIBS} ${MONGO_LIBS}" + return 1 fi } @@ -1072,14 +1072,22 @@ if [ -z "${TURN_NO_SQLITE}" ] ; then fi if [ -z "${TURN_NO_SQLITE}" ] ; then - testsqlite_comp - ER=$? - if ! [ ${ER} -eq 0 ] ; then + testsqlite_comp + ER=$? + if ! [ ${ER} -eq 0 ] ; then ${ECHO_CMD} "SQLite development found." - else + else ${ECHO_CMD} "SQLite development libraries are not installed properly in required location." TURN_NO_SQLITE="-DTURN_NO_SQLITE" - fi + fi + fi + + if ! [ -z "${TURN_NO_SQLITE}" ] ; then + ${ECHO_CMD} + ${ECHO_CMD} "SQLite DEVELOPMENT LIBRARY (libsqlite3) AND/OR HEADER (sqlite3.h)" + ${ECHO_CMD} " ARE NOT INSTALLED PROPERLY ON THIS SYSTEM." + ${ECHO_CMD} " THAT'S OK BUT THE TURN SERVER IS BUILDING WITHOUT SQLITE SUPPORT." + ${ECHO_CMD} fi fi @@ -1257,4 +1265,4 @@ cat Makefile.in >> Makefile cleanup - +${ECHO_CMD} "Makefile created: success." From a5f6b6b94073ce0b5a198b23cc131c6e21388861 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 20 Nov 2014 07:22:02 +0000 Subject: [PATCH 337/805] cosmetic change --- Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index 7233ec47..68cbcef0 100755 --- a/Makefile.in +++ b/Makefile.in @@ -169,7 +169,7 @@ deinstall: ${MAKE_DEPS} ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_peer.1 ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/coturn.1 ${RMCMD} ${DESTDIR}${LIBDIR}/libturnclient.a - ${RMCMD} ${DESTDIR}${EXAMPLESDIR}/ + ${RMCMD} ${DESTDIR}${EXAMPLESDIR} ${RMCMD} ${DESTDIR}${CONFDIR}/turnserver.conf.default ${RMCMD} ${DESTDIR}${TURNINCLUDEDIR} From 9b3d8b2504e6908c046e11cd091348c404990df1 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 20 Nov 2014 09:01:57 +0000 Subject: [PATCH 338/805] working on sqlite install --- sqlite/turndb | Bin 20480 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 sqlite/turndb diff --git a/sqlite/turndb b/sqlite/turndb deleted file mode 100644 index 45de984f9f0db6ab8e026b6297aeafb044ea24cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20480 zcmeI2?`zXQ7{_zTmaNt3`~eXJcQU3e+nAkJ1re-LR5sDgi429~wqDoJw5dtz+$+gI zeCt2ppX6Kr0AKnC_{KNhrCFM!>l_tBC{Ll={mk=xKhIqrw!4?>Ylh2k-LhNM#W$r1 z2_fkL#*!pW@$W_cJ^YCJ#9@X1Mv?Nc;*_-XR1SCVs|tbqc1z1P}lM*&vV?ZbY+sHrxU)fB+CkfdJ(H6d;2MAdpc4kpD9p7;p;+ zq(A`je+rPn1Q5t50m%Ou4Gg#i1X3UX`9B57U;+qalmO)aj0OhW0s<)zfc&2VWH12) zGD-mQe?|iXZUKQ52#EZzNk1j&C;E!M%dh1x%DnP61;eSE@NOVYpPxqub1vOBncKD7 zU5D8YG2LicezZ}oY*z7R<>6WtM|*G~kNL-D)NJAR)ZS@OyHGBz6mgB!Y1ee|_3MlN zkTz|x*oa*|nHl z?)k*YJa^ov=Z-t+ouAb7xjE!DL)VGJc5LQ*9u(C9$Ab>;ckTr7c~8x5GC;YGZM3Mp zk41!nF!+zV2Q*H3wuPicC& zjJ&P>rnYQj*Ju;hBL0RIuP>5lI}=lS)Ci%sH!1f1;j4b|Es)#_y?J~KJU*@JZ_2}@ z9c4Dy<_UMtdZlSiUtUHB=lU{zKZwtKp+7Kj6eYX{vQDvOaTI8LID2%KPG_$89-nJ0+9blfCf{5z?cw# z{68jv1Q|eJ1Okx%M}P)XfWVj#5cyw`FG=zx`Hk{zOhkcHv%}Laal9S7 zd69FC7IR$M>fmj0w&;evH~6ubY1Ek*fO!YoWp=Ey(X7=;gE|dT@3wbB6Sr?AEKrB= u3nSFr{o9b^9rZ~Z|CE4LXlGDu?7jl$#SimJGpb&l9Tv0@Fe!z_3x5EY9Hxo@ From 4a86c4fcd3724a1daa631adea046b7a3e383f903 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 20 Nov 2014 09:16:11 +0000 Subject: [PATCH 339/805] working on sqlite install --- Makefile.in | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Makefile.in b/Makefile.in index 68cbcef0..7f3e7184 100755 --- a/Makefile.in +++ b/Makefile.in @@ -34,7 +34,7 @@ SERVERAPP_HEADERS = src/apps/relay/userdb.h src/apps/relay/tls_listener.h src/ap 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_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 +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 all: ${TURN_BUILD_RESULTS} @@ -95,10 +95,18 @@ build/obj/ns_turn_msg.o: src/client/ns_turn_msg.c ${LUBCLIENTTURN_DEPS} ### Clean all: clean: - ${RMCMD} bin build lib obj *bak *~ */*~ */*/*~ */*/*/*~ *core */*core */*/*core include Makefile tmp + ${RMCMD} bin build lib obj *bak *~ */*~ */*/*~ */*/*/*~ *core */*core */*/*core include Makefile tmp sqlite distclean: clean +### SQLite empty database: +sqlite_empty_db : sqlite/turndb + +sqlite/turndb : turndb/schema.sql + ${MKDIR} sqlite + ${RMCMD} sqlite/turndb + ${SQLITECMD} sqlite/turndb < turndb/schema.sql + ### Install all: install: all ${MAKE_DEPS} @@ -142,13 +150,13 @@ install: all ${MAKE_DEPS} ${INSTALL_DATA} turndb/schema.userdb.redis ${DESTDIR}${SCHEMADIR} ${INSTALL_DATA} turndb/schema.stats.redis ${DESTDIR}${DOCSDIR} ${INSTALL_DATA} turndb/schema.stats.redis ${DESTDIR}${SCHEMADIR} + ${INSTALL_DATA} sqlite/turndb ${DESTDIR}${LOCALSTATEDIR}/db/turndb ${INSTALL_DATA} examples/etc/turnserver.conf ${DESTDIR}${CONFDIR}/turnserver.conf.default ${INSTALL_DIR} examples/etc ${DESTDIR}${EXAMPLESDIR} ${INSTALL_DIR} examples/scripts ${DESTDIR}${EXAMPLESDIR} ${RMCMD} ${DESTDIR}${EXAMPLESDIR}/scripts/rfc5769.sh ${INSTALL_DIR} include/turn/client ${DESTDIR}${TURNINCLUDEDIR} ${INSTALL_DATA} include/turn/ns_turn_defs.h ${DESTDIR}${TURNINCLUDEDIR} - ${SQLITECMD} ${DESTDIR}${LOCALSTATEDIR}/db/turndb < turndb/schema.sql ${MORECMD} ${DESTDIR}${DOCSDIR}/postinstall.txt deinstall: ${MAKE_DEPS} @@ -176,5 +184,3 @@ deinstall: ${MAKE_DEPS} uninstall: deinstall reinstall: deinstall install - - From cdcd831a73d492278ce050a164f6aa730ca0ef9a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 21 Nov 2014 00:42:24 +0000 Subject: [PATCH 340/805] rpm updated --- rpm/build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/rpm/build.sh b/rpm/build.sh index 745f6928..1edefe6f 100755 --- a/rpm/build.sh +++ b/rpm/build.sh @@ -63,6 +63,7 @@ cat <>turnserver-${TURNVERSION}/install.sh sudo yum -y install openssl sudo yum -y install telnet +sudo yum -y install sqlite for i in *.rpm ; do From 6758ca92314a122a3c670227cb8c3e6e8ea46c2c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 21 Nov 2014 00:47:16 +0000 Subject: [PATCH 341/805] rpm update --- configure | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/configure b/configure index d4607265..5a4d8510 100755 --- a/configure +++ b/configure @@ -613,9 +613,15 @@ RMCMD="rm -rf" type sqlite3 2>>/dev/null ER=$? if [ ${ER} -eq 0 ] ; then - SQLITECMD="sqlite3" + SQLITECMD="sqlite3" else + type sqlite 2>>/dev/null + ER=$? + if [ ${ER} -eq 0 ] ; then + SQLITECMD="sqlite" + else SQLITECMD="echo" + fi fi ############################# From 01e2364a7d1e2526df3fd8bb3c49919c7bc59ce7 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 21 Nov 2014 08:14:45 +0000 Subject: [PATCH 342/805] docs updated --- INSTALL | 62 ++++++++++++++++++------------------ README.turnadmin | 3 +- README.turnserver | 14 +++++--- README.turnutils | 1 + examples/etc/turnserver.conf | 4 --- examples/scripts/readme.txt | 4 +-- man/man1/turnadmin.1 | 3 +- man/man1/turnserver.1 | 16 ++++++---- man/man1/turnutils.1 | 3 +- 9 files changed, 59 insertions(+), 51 deletions(-) diff --git a/INSTALL b/INSTALL index 02da4e6d..46e6bd4f 100644 --- a/INSTALL +++ b/INSTALL @@ -211,10 +211,10 @@ If you do not want to use the rpath linking option, or you OS or compiler do not allows that, then after the installation, you may have to adjust the system-wide shared library search path by using "ldconfig -n " (Linux), "ldconfig -m " (BSD) or "crle -u -l " -(Solaris). Your system must be able to find the sqlite, libevent2, openssl and -(optionally) PostgreSQL and/or MySQL (MariaDB) and/or MongoDB and/or Redis -shared libraries, either with the help of the system-wide library search -configuration or by using LD_LIBRARY_PATH. "make install" will make a +(Solaris). Your system must be able to find the libevent2, openssl and +(optionally) SQLite and/or PostgreSQL and/or MySQL (MariaDB) and/or MongoDB +and/or Redis shared libraries, either with the help of the system-wide library +search configuration or by using LD_LIBRARY_PATH. "make install" will make a non-garantied effort to add automatically PREFIX/lib and /usr/local/lib to the libraries search path, but if you have some libraries in different non-default directories you will have to add them manually to the search @@ -268,21 +268,21 @@ The code is compatible with C++ compiler, and a C++ compiler VII. WHICH EXTRA LIBRARIES AND UTILITIES YOU NEED In addition to common *NIX OS services and libraries, to compile this code, -OpenSSL (version 1.0.0a or better recommended), sqlite C development library, -and libevent2 (version 2.0.5 or better) are required, -the PostgreSQL C client development setup is -optional, the MySQL (MariaDB) C client development setup is optional, the MongoDB -C Driver and the Hiredis development files for Redis database access are optional. -For fully functional build, the extra set of libraries must be installed -in full version (the development headers and the libraries to link with). -For runtime, only runtime setup is required. If the build is modified for +OpenSSL (version 1.0.0a or better recommended) and libevent2 (version 2.0.5 +or better) are required, SQLite C development library and header is optional, +the PostgreSQL C client development setup is optional, +the MySQL (MariaDB) C client development setup is optional, +the MongoDB C Driver and the Hiredis development files for Redis database +access are all optional. For development build, the development headers and +the libraries to link with, are to be installed. For the runtime, only the +runtime setup is required. If the build is modified for static linking, then even runtime installation is not needed. OpenSSL, SQLite, libevent2, PostgreSQL, MySQL (or MariaDB) and Hiredis libraries can be downloaded from their web sites: - http://www.openssl.org (required); - - http://www.sqlite.org (optional); - http://www.libevent.org (required); + - http://www.sqlite.org (optional); - http://www.postgresql.org (optional); - http://www.mysql.org (or http://mariadb.org) (optional); - https://github.com/mongodb/mongo-c-driver (optional); @@ -387,9 +387,8 @@ like this: Dynamic library paths: -You may also have to adjust the turn server start script, add PostgreSQL -and/or MySQL and/or MongoDB and/or Redis runtime library path to LD_LIBRARY_PATH. -Or you may find that it would be more convenient to adjust the +You may also have to adjust the turn server start script, add all the dynamic runtime +library paths to LD_LIBRARY_PATH. Or you may find that it would be more convenient to adjust the system-wide shared library search path by using commands: on Linux: @@ -410,22 +409,23 @@ On Mac OS X, you have three different choices for dynamic libraries handling: 2) Before the compilation, check the dynamic libraries and adjust their identification names, if necessary, to the absolute library path or to @rpath/. -For exmple, the MySQL dynamic library may need that adjustment. You will have to use +For example, the MySQL dynamic library may need that adjustment. You will have to use "adjust_name_tool" with -id option for that; OR -3) After the compilation, you can use the same tool, "adjust_name_tool", with option -change, -to adjust the library paths values in the binary, where necessary. All library paths must be -absolute paths or @rpath/... . +3) After the compilation, you can use the same tool, "adjust_name_tool", +with option -change, to adjust the library paths values in the binary, +where necessary. All library paths must be absolute paths or @rpath/... . See also the next section. -NOTE: See "PostgreSQL setup" and "MySQL setup" and "MongoDB setup" and -"Redis setup" sections below for more database setup information. +NOTE: See "SQLite setup" and "PostgreSQL setup" and "MySQL setup" and +"MongoDB setup" and "Redis setup" sections below for more database setup +information. -NOTE: If you do not install PostgreSQL or MySQL or MongoDB or Redis then you will -be limited to flat files for user database. It will work great for -smaller user databases (like 100 users) but for larger systems you -will need PostgreSQL or MySQL or MongoDB or Redis. +NOTE: If you do not install SQLite or PostgreSQL or MySQL or MongoDB or Redis, +then you will be limited to the command-line options for user database. +It will work great for development setup, but for real runtime systems you +will need SQLite or PostgreSQL or MySQL or MongoDB or Redis. NOTE: To run PostgreSQL or MySQL or MongoDB or Redis server on the same system, you will also have to install a corresponding PostgreSQL or MySQL or @@ -1026,11 +1026,11 @@ Redis can be also used for the TURN allocation status check and for status and traffic notifications. See the explanation in the turndb/schema.stats.redis file, and an example in -turndb/testredisdbsetup.sh file. One special thing about TURN Redis security setup -is that you can store open passwords for long-term credentials in Redis. -You cannot set open passwords for long-term credentials in MySQL and PostgreSQL - -with those DBs, you have to use the keys only. With Redis, you have a choice - -keys or open passwords. +turndb/testredisdbsetup.sh file. One special thing about TURN Redis security +setup is that you can store open passwords for long-term credentials in Redis. +You cannot set open passwords for long-term credentials in SQLite or MySQL or +PostgreSQL - with those DBs, you have to use the keys only. With Redis, you +have a choice - keys or open passwords. You also have to take care about Redis connection parameters, the timeout and the keepalive. The following settings must be in your Redis config file diff --git a/README.turnadmin b/README.turnadmin index 97012343..7113cf42 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -80,7 +80,7 @@ Commands: Options with required values: --b, --db, --userdb SQLite user database file name (default - /var/db/turndb or +-b, --db, --userdb SQLite user database file name (default - /var/db/turndb or /usr/local/var/db/turndb). See the same option in the turnserver section. -e, --psql-userdb PostgreSQL user database connection string. @@ -172,6 +172,7 @@ to see the man page. /etc/turnserver.conf /var/db/turndb + /usr/local/var/db/turndb /usr/local/etc/turnserver.conf diff --git a/README.turnserver b/README.turnserver index fc38c045..4d564295 100644 --- a/README.turnserver +++ b/README.turnserver @@ -486,15 +486,15 @@ Options with required values: --tls-alternate-server Option to set alternative server for TLS & DTLS services in form of :. If the port number is omitted, then the default port - number 5349 for the TLS/DTLS protocols will be used. See the previous option for the - functionality description. + number 5349 for the TLS/DTLS protocols will be used. See the + previous option for the functionality description. -O, --redis-statsdb Redis status and statistics database connection string, if used (default - empty, no Redis stats DB used). This database keeps allocations status information, and it can be also used for publishing and delivering traffic and allocation event notifications. This database option can be used independently of --redis-userdb option, - and actually Redis can be used for status/statistics and MySQL or MongoDB or PostgreSQL can - be used for the user database. + and actually Redis can be used for status/statistics and SQLite or MySQL or MongoDB or + PostgreSQL can be used for the user database. The connection string has the same parameters as redis-userdb connection string. --max-allocate-timeout Max time, in seconds, allowed for full allocation establishment. @@ -770,7 +770,10 @@ choose any for your convenience. You do not have to handle the database information "manually" - the turnadmin program can handle everything for you. For PostgreSQL and MySQL you will just have to create an empty database with schema.sql SQL script. With Redis, you do not have to do even that - just run turnadmin and -it will set the users for you (see the turnadmin manuals). +it will set the users for you (see the turnadmin manuals). If you are using SQLite, then the +turnserver or turnadmin will initialize the empty database, for you, when started. The +TURN server installation process creates an empty initialized SQLite database in the default +location (/var/db/turndb or /usr/local/var/db/turndb, depending on the system). ================================= @@ -844,6 +847,7 @@ FILES /etc/turnserver.conf /var/db/turndb + /usr/local/var/db/turndb /usr/local/etc/turnserver.conf diff --git a/README.turnutils b/README.turnutils index 7b93fe8e..865d8f92 100644 --- a/README.turnutils +++ b/README.turnutils @@ -252,6 +252,7 @@ FILES /etc/turnserver.conf /var/db/turndb + /usr/local/var/db/turndb /usr/local/etc/turnserver.conf diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 9067758f..559f9314 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -160,15 +160,11 @@ # Uncomment to use long-term credential mechanism. # By default no credentials mechanism is used (any user allowed). -# This option can be used with either flat file user database or -# PostgreSQL DB or MySQL DB or MongoDB or Redis DB for user keys storage. # #lt-cred-mech # Uncomment to use short-term credential mechanism. # By default no credentials mechanism is used (any user allowed). -# For short-term credential mechanism you have to use PostgreSQL or -# MySQL or MongoDB or Redis database for user password storage. # #st-cred-mech diff --git a/examples/scripts/readme.txt b/examples/scripts/readme.txt index 4514771a..f97308e5 100644 --- a/examples/scripts/readme.txt +++ b/examples/scripts/readme.txt @@ -11,8 +11,8 @@ 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" -directory. Of course, the database (PostgreSQL or MySQL) must be set for these scripts -to work correctly. +directory. Of course, the database (SQLite, PostgreSQL, MySQL, Redis or MongoDB) must +be set for these scripts to work correctly. 5) "restapi" shows how to use TURN REST API. diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 589a90df..964c84da 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "19 November 2014" "" "" +.TH TURN 1 "21 November 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage @@ -263,6 +263,7 @@ to see the man page. /etc/turnserver.conf .PP /var/db/turndb +.PP /usr/local/var/db/turndb .PP /usr/local/etc/turnserver.conf diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 8095505d..62391438 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "19 November 2014" "" "" +.TH TURN 1 "21 November 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -699,8 +699,8 @@ can emulate "weighting" of the servers. \fB\-\-tls\-alternate\-server\fP Option to set alternative server for TLS & DTLS services in form of :. If the port number is omitted, then the default port -number 5349 for the TLS/DTLS protocols will be used. See the previous option for the -functionality description. +number 5349 for the TLS/DTLS protocols will be used. See the +previous option for the functionality description. .TP .B \fB\-O\fP, \fB\-\-redis\-statsdb\fP @@ -708,8 +708,8 @@ Redis status and statistics database connection string, if used (default \- empt no Redis stats DB used). This database keeps allocations status information, and it can be also used for publishing and delivering traffic and allocation event notifications. This database option can be used independently of \fB\-\-redis\-userdb\fP option, -and actually Redis can be used for status/statistics and MySQL or MongoDB or PostgreSQL can -be used for the user database. +and actually Redis can be used for status/statistics and SQLite or MySQL or MongoDB or +PostgreSQL can be used for the user database. The connection string has the same parameters as redis\-userdb connection string. .TP .B @@ -1025,7 +1025,10 @@ choose any for your convenience. You do not have to handle the database information "manually" \- the \fIturnadmin\fP program can handle everything for you. For PostgreSQL and MySQL you will just have to create an empty database with schema.sql SQL script. With Redis, you do not have to do even that \- just run \fIturnadmin\fP and -it will set the users for you (see the \fIturnadmin\fP manuals). +it will set the users for you (see the \fIturnadmin\fP manuals). If you are using SQLite, then the +\fIturnserver\fP or \fIturnadmin\fP will initialize the empty database, for you, when started. The +TURN server installation process creates an empty initialized SQLite database in the default +location (/var/db/turndb or /usr/local/var/db/turndb, depending on the system). .PP ================================= .SH LIBRARIES @@ -1099,6 +1102,7 @@ it would affect the performance. /etc/turnserver.conf .PP /var/db/turndb +.PP /usr/local/var/db/turndb .PP /usr/local/etc/turnserver.conf diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 1007c87e..57d5b1ab 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "19 November 2014" "" "" +.TH TURN 1 "21 November 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -375,6 +375,7 @@ to see the man page. /etc/turnserver.conf .PP /var/db/turndb +.PP /usr/local/var/db/turndb .PP /usr/local/etc/turnserver.conf From 8c8cb297eb0257f9d13f709e5429df6477fa3e84 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 21 Nov 2014 08:16:54 +0000 Subject: [PATCH 343/805] rpm info updated --- rpm/turnserver.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 5a9f058a..f1902b96 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -54,7 +54,7 @@ Supported relay protocols: Supported user databases (for user repository, with passwords or keys, if authentication is required): -- Flat files +- SQLite - MySQL - PostgreSQL - Redis From fdb52a88b9d52b9ff41812303476d27c7332e589 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 22 Nov 2014 20:57:26 +0000 Subject: [PATCH 344/805] docs update --- INSTALL | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/INSTALL b/INSTALL index 46e6bd4f..006ec78d 100644 --- a/INSTALL +++ b/INSTALL @@ -294,8 +294,8 @@ locations - the configure script and the Makefile are assuming that they are installed in their default locations. If not, then you will have to modify those. -Most modern popular systems (FreeBSD / PC-BSD, Linux Ubuntu 11.10+, Debian Wheezy, -Linux Mint 14+, Amazon Linux, Fedora) have a simpler way of the third party tools +Most modern popular systems (FreeBSD / PC-BSD, Linux Ubuntu, Debian Wheezy, +Linux Mint, Amazon Linux, Fedora) have a simpler way of the third party tools installation: *) PC-BSD or FreeBSD (the FRESH ports database is assumed to be installed, with @@ -367,9 +367,8 @@ installation: perfectly installed without redis support - if you do not need it. - *****) Some OSes in Debian family (Debian Squeeze and - pre-11.10 Ubuntus) setups are similar to Debian Wheezy, - although some packages have different names. + *****) Older Debian family Linuxes are using some packages + with different names. ******) On some CentOS / RedHat 6.x systems you have to install libevent2 "manually", and optionally you have to download and From bc765e01dc646e2d467df88d1f54a6ef5e3c3cd0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 22 Nov 2014 21:55:00 +0000 Subject: [PATCH 345/805] INSTALL updated for sqlite --- INSTALL | 328 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 177 insertions(+), 151 deletions(-) diff --git a/INSTALL b/INSTALL index 006ec78d..e731f5bf 100644 --- a/INSTALL +++ b/INSTALL @@ -2,27 +2,12 @@ I. TURN Server as a standard OS package At the present time, several operation systems have this project pre-packaged: -1) FreeBSD (and PC-BSD) have this project as a "port", named "turnserver", -in /usr/ports/net/turnserver directory. Installation is very simple: +1) New Linuxes in Debian family have package "coturn": -# optional commands, to update the ports tree: - $ sudo portsnap fetch - $ sudo portsnap update +http://packages.qa.debian.org/r/coturn.html -# Build and install the TURN Server: - $ cd /usr/ports/net/turnserver - $ sudo make install clean - -2) Debian "jessie" (and the recent version of Ubuntu and Mint) -have the predecessor of this project packaged as "rfc5766-turn-server", see the link: - -http://packages.qa.debian.org/r/rfc5766-turn-server.html - -In the new Debian "jessie", and in the related Ubuntu and Mint, you will -be able to just select rfc5766-turn-server from the packages list and -install it through Synaptic or through the package manager. - -If you are using the Debian package from the project download site, then follow these instructions: +If you are using the Debian package from the project download site, +then follow these instructions: Unpack the archive: @@ -50,16 +35,12 @@ The turn*.conf config files are in /etc directory. The service start-up control scripts will be in /etc/init.d/coturn and in /etc/defaults/coturn files. -3) ArchLinux has this TURN server package: +2) ArchLinux has this TURN server package: https://aur.archlinux.org/packages/coturn/ -4) OpenSUSE has an older package, too: - -https://build.opensuse.org/package/show/home:ehauenstein/rfc5766-turn-server - -If you are using a pre-packaged TURN server then you can skip -to the section IX. +3) FreeBSD and OpenSUSE have the predecessor of this project packaged +(rfc5766-turn-server). II. DOWNLOAD @@ -81,17 +62,18 @@ First, you have to run the configure script: It will create a Makefile customized for your system. -By default, the generated Makefile will be set to install everything -in: +By default, the generated Makefile will install everything to: + - /usr on Solaris. - /usr/pkg on NetBSD. - /usr/local everywhere else. -The binaries will be copied in bin subdirectory of the installation -destination, config files copied to etc subdirectory. There will be +The binaries will be copied to the bin subdirectory of the installation +destination, config files copied to etc subdirectory. The default SQLite database +will be created in var/db/turndb. There will be also documents, examples and some other files, in separate directories. - You can change the root configured destination directory by +You can change the root configured destination directory by setting PREFIX variable in the configure command line. For example: @@ -102,8 +84,8 @@ Or: $ ./configure --prefix=/opt You can change the auxiliary configured destination sub-directories by -setting BINDIR, CONFDIR, MANPREFIX, EXAMPLESDIR, DOCSDIR, LIBDIR, SCHEMADIR -and TURNINCLUDEDIR variables in the +setting BINDIR, CONFDIR, MANPREFIX, EXAMPLESDIR, DOCSDIR, LIBDIR, SCHEMADIR, +LOCALSTATEDIR and TURNINCLUDEDIR variables in the configure command line. For example: $ PREFIX=/opt BINDIR=/opt/bin64 CONFDIR=/opt/conf ./configure @@ -120,7 +102,7 @@ configure command line. For example: See below a separate INSTALL section for more details. -The script configure is a proprietary script. It will create a Makefile +The script "configure" is a proprietary script. It will create a Makefile that you can use to build the project: $ make @@ -131,8 +113,10 @@ The make command without options will do the following: "utility" programs there. - create lib/ sub-directory and put the client library there. - create include/turn/ sub-directory and put include files there. + - create sqlite/turndb default empty database that will be copied to + var/db/ during the installation. -The programs can be either called directly, or a shell scripts can be used. +The TURN programs can be either called directly, or a shell scripts can be used. The script examples are located in examples/scripts directory. These scripts are just examples: you can run them successfully for the tests, but you will have to change the script parameters for your real environment. @@ -169,7 +153,7 @@ accordingly, the Makefile.in template file. IV. INSTALL This step is optional. You can run the turnserver from the original build -directory, successfully, without installing the TURN server into the system. +directory, successfully, without installing the TURN server into your system. You have to install the turnserver only if you want to integrate the turnserver in your system. @@ -186,10 +170,12 @@ This command will also: - copy the content of examples subdirectory into PREFIX/share/examples/turnserver/ directory; + - copy the generated default empty SQLite database from sqlite/turndb + to /var/db/turndb; - copy the content of include/turn subdirectory into PREFIX/include/turn/ directory; - copy the database schema file turndb/schema.sql into - PREFIX/share/turnserver/ + PREFIX/share/turnserver/ directory; - copy all docs into PREFIX/share/doc/turnserver/ directory. @@ -203,44 +189,37 @@ using DESTDIR variable, for example: In this example, the root installation directory will be /opt/usr. The "configure" script by default generates a Makefile with "rpath" option -set for the binaries linking (if your compiler allows that option). If that -is not desirable (like in some OS packaging procedures), then run the -"configure" script with --disable-rpath option. +set for the dynamic libraries linking (if your system and your compiler +allow that option). If that is not desirable (like in some OS packaging +procedures), then run the "configure" script with --disable-rpath option. -If you do not want to use the rpath linking option, or you OS or compiler -do not allows that, then after the installation, you may have to adjust the -system-wide shared library search path by using "ldconfig -n " -(Linux), "ldconfig -m " (BSD) or "crle -u -l " -(Solaris). Your system must be able to find the libevent2, openssl and -(optionally) SQLite and/or PostgreSQL and/or MySQL (MariaDB) and/or MongoDB -and/or Redis shared libraries, either with the help of the system-wide library -search configuration or by using LD_LIBRARY_PATH. "make install" will make a -non-garantied effort to add automatically PREFIX/lib and /usr/local/lib to -the libraries search path, but if you have some libraries in different -non-default directories you will have to add them manually to the search -path, or you will have to adjust LD_LIBRARY_PATH. +If you are not using the rpath linking option, then after the installation, +you may have to adjust the system-wide shared library search path with +"ldconfig -n " (Linux), "ldconfig -m " (BSD) or +"crle -u -l " (Solaris). Your system must be able to find the +libevent2, openssl and (optionally) SQLite and/or PostgreSQL and/or MySQL +(MariaDB) and/or MongoDB and/or Redis shared libraries, either with the +help of the system-wide library search configuration or by using +LD_LIBRARY_PATH. "make install" will make a non-guaranteed effort to add +automatically PREFIX/lib and /usr/local/lib to the libraries search path, +but if you have some libraries in different non-default directories then +you will have to add them manually to the search path, or you will have +to adjust LD_LIBRARY_PATH. V. PLATFORMS The TURN Server is using generic *NIX system APIs and is supposed to be usable on wide range of *NIX systems. -The following platforms have been used in the development (i386 and x86_64): +The following platforms are supported +(both i386 and x86_64 variants when applicable): - - Linux Ubuntu, Mint, Debian, - - FreeBSD, + - Linux, + - BSD family (Mac OS X, FreeBSD, NetBSD, OpenBSD), - Solaris 11, - - Linux CentOS / Red Hat Enterprise Edition 6.x-7.0, x86_64 - - Cygwin 1.7.20 - - NetBSD 6.0.1, - - OpenBSD 5.3, - - Amazon Linux, - - Mac OS X, - - ArchLinux, - - Fedora, - - OpenSUSE + - Cygwin -It must work on many other *NIXes, as well. The configure script and/or +It must work on other *NIXes, as well. The configure script and/or Makefile may need adjustments for other *NIXes not mentioned above. The code of the client messaging library can be compiled and used on @@ -255,9 +234,9 @@ The tested C compilers are: - gcc 3.4.4 thru 4.8.x - clang 3.0 or better - - Solaris Studio 12 C and C++ compilers + - Solaris Studio 12 C compiler -It may be compiled with others compilers, too. +It may be compiled with other compilers, too. The code is compatible with C++ compiler, and a C++ compiler (like g++) can be used for the compilation, too: @@ -294,11 +273,10 @@ locations - the configure script and the Makefile are assuming that they are installed in their default locations. If not, then you will have to modify those. -Most modern popular systems (FreeBSD / PC-BSD, Linux Ubuntu, Debian Wheezy, -Linux Mint, Amazon Linux, Fedora) have a simpler way of the third party tools -installation: +Most modern popular systems (FreeBSD, Linux Ubuntu/Debian/Mint, Amazon Linux, Fedora) +have a simpler way of the third party tools installation: - *) PC-BSD or FreeBSD (the FRESH ports database is assumed to be installed, with + *) FreeBSD (the FRESH ports database is assumed to be installed, with the turnserver port included): $ cd /usr/ports/net/turnserver @@ -354,10 +332,11 @@ installation: - you have to install gcc first: $ sudo yum install gcc - - mongo-c-driver packages are not available. MongoDB support - will not be compiled, unless you install it "manually" before - the TURN server compilation. Refer to https://github.com/mongodb/mongo-c-driver - for installation instructions of the driver. + - mongo-c-driver packages are not available "automatically". + MongoDB support will not be compiled, unless you install it "manually" + before the TURN server compilation. Refer to + https://github.com/mongodb/mongo-c-driver for installation instructions + of the driver. - hiredis packages are not available, so do not issue the hiredis installation commands. Redis support will not be @@ -503,9 +482,9 @@ by using $ ldconfig -m (BSD) $ crle -u -l (Solaris) -IX. TEST SCRIPT SETS +IX. TEST SCRIPTS -First of all, we can use test vectors from RFC 5769 to double-check that our +First of all, you can use the test vectors from RFC 5769 to double-check that the STUN/TURN message encoding algorithms work properly. Run the utility: $ cd examples @@ -588,9 +567,10 @@ secure_relay.sh as a guidance how to run the TURN server. X. OS X compilation notes OS X usually has an older version of openssl supplied, with some Apple -additions. The best option is to install a good fresh openssl development -library, free of Apple tweaks, from http://www.openssl.org. But the "native" -openssl will work, too. +additions. The the "native" openssl will work, within its limitations, +but the best option is to install a good fresh openssl development +library, from http://www.openssl.org. You will have +to handle the dynamic linking of the generated binaries. XI. MS Windows and Cygwin support @@ -626,77 +606,20 @@ HTML-formatted client library functions reference is located in docs/html subdirectory of the original archive tree. After the installation, it will be placed in PREFIX/share/doc/turnserver/html. -XIV. PostgreSQL setup +XIV. SQLite setup -The site http://www.postgresql.org site has excellent extensive documentation. -For a quick-start guide, you can take a look into this page: -http://www.freebsddiary.org/postgresql.php. That page is written for -FreeBSD users, but it has lots of generic information applicable to other -*NIXes, too. +The site http://www.sqlite.org site has excellent extensive documentation. -For the psql-userdb TURN server parameter, you can either set a PostgreSQL -connection string, or a PostgreSQL URI, see the link: - -For 8.4 PostgreSQL version: -http://www.postgresql.org/docs/8.4/static/libpq-connect.html - -For newer 9.x versions: -http://www.postgresql.org/docs/9.2/static/libpq-connect.html#LIBPQ-CONNSTRING. - -In the PostgreSQL connection string or URI, you can set the host, the -access port, the database name, the user, and the user password -(if the access is secured). Numerous other parameters can be set, -see the links above. The TURN server will blindly use that connection -string without any modifications. You are responsible for the right -connection string format. - -Below are the steps to setup the PostgreSQL database server from scratch: - -1) Install PostgreSQL server. - -2) Find and edit Postgres' pg_hba.conf file to set the access options -(see docs). On different systems, it may be located in different places. -Set the lines for local access as "trust" for now (you can change it later), -for TCP/IP access set the value as "md5". -To set TCP/IP access from any host, use "0.0.0.0/0" for IPv4, and "::/0" -for IPv6. - -3) Edit postgresql.conf file to allow TCP/IP access - uncomment and edit -the "listen_addresses" option (see docs). On different systems, this file -may be located in different places. - -4) Restart your system or restart the postgresql server, for example: - - $ sudo /etc/init.d/postgresql stop - $ sudo /etc/init.d/postgresql start - -5) Check /etc/passwd file to find out which user account is used for the -PostgreSQL admin access on your system (it may be "pgsql", or "postgres", -or "postgresql"). Let's assume that this is "postgres" account. - -6) Create a database for the TURN purposes, with name, say, "turn": - - $ createdb -U postgres turn - -7) Create a user for the TURN with name, say, "turn": - $ psql -U postgres turn - turn=# create user turn with password 'turn'; - turn=# - Ctrl-D - -8) Create the TURN users database schema. +The default SQLite database location for the TURN Server is +/usr/local/var/db/turndb or /var/db/turndb (depending on the platform). The database schema for the TURN server is very minimalistic and is located in project's turndb/schema.sql file, or in the system's PREFIX/share/turnserver/schema.sql file after the turnserver installation: -$ cat turndb/schema.sql | psql -U turn 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 -$ +If you would like to created a new fresh SQLite TURN database: + +$ sqlite3 < turndb/schema.sql The schema description: @@ -829,6 +752,109 @@ 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. +When starting the turnserver, the --db parameter will be, for example: + +turnserver ... --db="/var/db/turndb" + +You will have to use the program turnadmin to fill the +database, or you can do that manually with psql. + +Fill in users, for example: + + Shared secret for the TURN REST API: + + $ bin/turnadmin -s logen -b "/var/db/turndb" + + Long-term credentials mechanism: + + $ bin/turnadmin -a -b "/var/db/turndb" -u gorst -r north.gov -p hero + $ bin/turnadmin -a -b "/var/db/turndb" -u ninefingers -r north.gov -p youhavetoberealistic + + Long-term credentials mechanism with SHA256 extention: + $ bin/turnadmin -a -b "/var/db/turndb" -u bethod -r north.gov -p king-of-north --sha256 + + Short-term credentials mechanism: + + $ bin/turnadmin -A -b "/var/db/turndb" -u gorst -r north.gov -p hero + $ bin/turnadmin -A -b "/var/db/turndb" -u ninefingers -r north.gov -p youhavetoberealistic + +XV. PostgreSQL setup + +The site http://www.postgresql.org site has excellent extensive documentation. +For a quick-start guide, you can take a look into this page: +http://www.freebsddiary.org/postgresql.php. That page is written for +FreeBSD users, but it has lots of generic information applicable to other +*NIXes, too. + +For the psql-userdb TURN server parameter, you can either set a PostgreSQL +connection string, or a PostgreSQL URI, see the link: + +For 8.4 PostgreSQL version: +http://www.postgresql.org/docs/8.4/static/libpq-connect.html + +For newer 9.x versions: +http://www.postgresql.org/docs/9.2/static/libpq-connect.html#LIBPQ-CONNSTRING. + +In the PostgreSQL connection string or URI, you can set the host, the +access port, the database name, the user, and the user password +(if the access is secured). Numerous other parameters can be set, +see the links above. The TURN server will blindly use that connection +string without any modifications. You are responsible for the right +connection string format. + +Below are the steps to setup the PostgreSQL database server from scratch: + +1) Install PostgreSQL server. + +2) Find and edit Postgres' pg_hba.conf file to set the access options +(see docs). On different systems, it may be located in different places. +Set the lines for local access as "trust" for now (you can change it later), +for TCP/IP access set the value as "md5". +To set TCP/IP access from any host, use "0.0.0.0/0" for IPv4, and "::/0" +for IPv6. + +3) Edit postgresql.conf file to allow TCP/IP access - uncomment and edit +the "listen_addresses" option (see docs). On different systems, this file +may be located in different places. + +4) Restart your system or restart the postgresql server, for example: + + $ sudo /etc/init.d/postgresql stop + $ sudo /etc/init.d/postgresql start + +5) Check /etc/passwd file to find out which user account is used for the +PostgreSQL admin access on your system (it may be "pgsql", or "postgres", +or "postgresql"). Let's assume that this is "postgres" account. + +6) Create a database for the TURN purposes, with name, say, "turn": + + $ createdb -U postgres turn + +7) Create a user for the TURN with name, say, "turn": + $ psql -U postgres turn + turn=# create user turn with password 'turn'; + turn=# + Ctrl-D + +8) Create the TURN users database schema. + +The database schema for the TURN server is very minimalistic and is located +in project's turndb/schema.sql file, or in the system's +PREFIX/share/turnserver/schema.sql file after the turnserver installation: + +$ cat turndb/schema.sql | psql -U turn 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. + +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. + More examples of database schema creation: psql -h -U -d < turndb/schema.sql @@ -876,7 +902,7 @@ Fill in users, for example: $ bin/turnadmin -A -e "host=localhost dbname=coturn user=turn password=turn" -u gorst -r north.gov -p hero $ bin/turnadmin -A -e "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic -XV. MySQL (MariaDB) setup +XVI. MySQL (MariaDB) setup The MySQL setup is similar to PostgreSQL (same idea), and is well documented on their site http://www.mysql.org. The TURN Server database schema is the @@ -884,7 +910,7 @@ same as for PostgreSQL and you can find it in turndb/schema.sql file, or in the system's PREFIX/share/turnserver/schema.sql file after the turnserver installation. -The general setup idea is the same as for PostgreSQL case: +The general setup idea is the same as for PostgreSQL: 1) Check that the mysql server access is OK. Immediately after the MySQL server installation, it must be accessible, at the very minimum, at the localhost with @@ -959,7 +985,7 @@ ca, capath, cert, key, cipher (see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the command options description). -XVI. MongoDB setup +XVII. MongoDB setup The MongoDB setup is well documented on their site http://docs.mongodb.org/manual/. @@ -991,7 +1017,7 @@ explanations for the Postgres, for example. See the file testmongosetup.sh for the database structure examples. -XVII. Redis setup +XVIII. Redis setup The Redis setup is well documented on their site http://redis.io. The TURN Server Redis database schema description can be found @@ -1062,20 +1088,20 @@ Redis TURN admin commands: See the file testredisdbsetup.sh for the data structure examples. -XVIII. Performance tuning +XIX. Performance tuning This topic is covered in the wiki page: http://code.google.com/p/coturn/wiki/turn_performance_and_load_balance -XIX. TURN Server setup +XX. TURN Server setup 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. -XX. Management interface +XXI. 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 From a549c8b36f656e2b6307a51e603c3dc1fd98e52c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 22 Nov 2014 23:46:48 +0000 Subject: [PATCH 346/805] minor fixes --- ChangeLog | 4 ++-- INSTALL | 32 +++++++++++++-------------- src/apps/relay/dbdrivers/dbd_sqlite.c | 31 ++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index f9846da9..2e0febc0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,8 @@ 11/10/2014 Oleg Moskalenko Version 4.3.1.1 'Tolomei': - - TLS connection procedure improved in uclient test program. - - Flat-file user database is no longer supported. - SQLite supported as the default user database. + - Support of the flat-file user database removed. + - TLS connection procedure improved in uclient test program. 11/07/2014 Oleg Moskalenko Version 4.2.3.1 'Monza': diff --git a/INSTALL b/INSTALL index e731f5bf..a64ec59f 100644 --- a/INSTALL +++ b/INSTALL @@ -761,9 +761,9 @@ database, or you can do that manually with psql. Fill in users, for example: - Shared secret for the TURN REST API: + Shared secret for the TURN REST API (realm north.gov): - $ bin/turnadmin -s logen -b "/var/db/turndb" + $ bin/turnadmin -s logen -r north.gov -b "/var/db/turndb" Long-term credentials mechanism: @@ -775,8 +775,8 @@ Fill in users, for example: Short-term credentials mechanism: - $ bin/turnadmin -A -b "/var/db/turndb" -u gorst -r north.gov -p hero - $ bin/turnadmin -A -b "/var/db/turndb" -u ninefingers -r north.gov -p youhavetoberealistic + $ bin/turnadmin -A -b "/var/db/turndb" -u gorst -p hero + $ bin/turnadmin -A -b "/var/db/turndb" -u ninefingers -p youhavetoberealistic XV. PostgreSQL setup @@ -885,9 +885,9 @@ database, or you can do that manually with psql. Fill in users, for example: - Shared secret for the TURN REST API: + Shared secret for the TURN REST API (realm north.gov): - $ bin/turnadmin -s logen -e "host=localhost dbname=coturn user=turn password=turn" + $ bin/turnadmin -s logen -r north.gov -e "host=localhost dbname=coturn user=turn password=turn" Long-term credentials mechanism: @@ -899,8 +899,8 @@ Fill in users, for example: Short-term credentials mechanism: - $ bin/turnadmin -A -e "host=localhost dbname=coturn user=turn password=turn" -u gorst -r north.gov -p hero - $ bin/turnadmin -A -e "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + $ 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 XVI. MySQL (MariaDB) setup @@ -940,9 +940,9 @@ the root account. 6) Fill in users, for example: - Shared secret for the TURN REST API: + Shared secret for the TURN REST API (realm north.gov): - $ bin/turnadmin -s logen -M "host=localhost dbname=coturn user=turn password=turn" + $ bin/turnadmin -s logen -r north.gov -M "host=localhost dbname=coturn user=turn password=turn" Long-term credentials mechanism: @@ -954,8 +954,8 @@ the root account. Short-term credentials mechanism: - $ bin/turnadmin -A -M "host=localhost dbname=coturn user=turn password=turn" -u gorst -r north.gov -p hero - $ bin/turnadmin -A -M "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + $ 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 7) Now we can use mysql in the turnserver. @@ -1069,9 +1069,9 @@ tcp-keepalive 60 Redis TURN admin commands: - Shared secret for the TURN REST API: + Shared secret for the TURN REST API (realm north.gov): - $ bin/turnadmin -s logen -N "host=localhost dbname=2 user=turn password=turn" + $ bin/turnadmin -s logen -r north.gov -N "host=localhost dbname=2 user=turn password=turn" Long-term credentials mechanism: @@ -1083,8 +1083,8 @@ Redis TURN admin commands: Short-term credentials mechanism: - $ bin/turnadmin -A -N "host=localhost dbname=2 user=turn password=turn" -u gorst -r north.gov -p hero - $ bin/turnadmin -A -N "host=localhost dbname=2 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic + $ 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 See the file testredisdbsetup.sh for the data structure examples. diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 0bb60956..957c9d44 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -290,6 +290,8 @@ static int sqlite_list_oauth_keys(void) { oauth_key_data_raw key_; oauth_key_data_raw *key=&key_; + donot_print_connection_success=1; + int ret = -1; char statement[TURN_LONG_STRING_SIZE]; @@ -347,6 +349,9 @@ static int sqlite_set_user_key(u08bits *usname, u08bits *realm, const char *key) 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) { @@ -371,6 +376,9 @@ static int sqlite_set_oauth_key(oauth_key_data_raw *key) 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( @@ -398,6 +406,9 @@ static int sqlite_set_user_pwd(u08bits *usname, st_password_t pwd) 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), "insert or replace into turnusers_st values('%s','%s')", usname, pwd); @@ -419,6 +430,9 @@ static int sqlite_del_user(u08bits *usname, int is_st, u08bits *realm) 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) { @@ -444,6 +458,9 @@ static int sqlite_del_oauth_key(const u08bits *kid) 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 oauth_key where kid = '%s'", (const char*) kid); @@ -467,6 +484,9 @@ static int sqlite_list_users(int is_st, u08bits *realm) 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) { @@ -547,6 +567,7 @@ static int sqlite_del_secret(u08bits *secret, u08bits *realm) char statement[TURN_LONG_STRING_SIZE]; sqlite3_stmt *st = NULL; int rc = 0; + sqlite3 *sqliteconnection = get_sqlite_connection(); if (sqliteconnection) { if(!secret || (secret[0]==0)) @@ -573,6 +594,7 @@ static int sqlite_set_secret(u08bits *secret, u08bits *realm) char statement[TURN_LONG_STRING_SIZE]; sqlite3_stmt *st = NULL; int rc = 0; + sqlite3 *sqliteconnection = get_sqlite_connection(); if (sqliteconnection) { snprintf(statement,sizeof(statement),"insert or replace into turn_secret (realm,value) values('%s','%s')",realm,secret); @@ -594,6 +616,8 @@ static int sqlite_add_origin(u08bits *origin, u08bits *realm) 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),"insert or replace into turn_origin_to_realm (origin,realm) values('%s','%s')",origin,realm); @@ -615,6 +639,8 @@ static int sqlite_del_origin(u08bits *origin) 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 turn_origin_to_realm where origin='%s'",origin); @@ -637,6 +663,7 @@ static int sqlite_list_origins(u08bits *realm) char statement[TURN_LONG_STRING_SIZE]; sqlite3_stmt *st = NULL; int rc = 0; + sqlite3 *sqliteconnection = get_sqlite_connection(); if (sqliteconnection) { if (realm && realm[0]) { @@ -680,6 +707,8 @@ static int sqlite_set_realm_option_one(u08bits *realm, unsigned long value, cons 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(value>0) { @@ -704,6 +733,7 @@ static int sqlite_list_realm_options(u08bits *realm) char statement[TURN_LONG_STRING_SIZE]; sqlite3_stmt *st = NULL; int rc = 0; + sqlite3 *sqliteconnection = get_sqlite_connection(); if (sqliteconnection) { if (realm && realm[0]) { @@ -751,6 +781,7 @@ static void sqlite_auth_ping(void * rch) static int sqlite_get_ip_list(const char *kind, ip_range_list_t * list) { int ret = -1; + sqlite3 *sqliteconnection = get_sqlite_connection(); if (sqliteconnection) { char statement[TURN_LONG_STRING_SIZE]; From 2cbe97ebcc20be18771cd5916f730ee9629cb1ce Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 23 Nov 2014 06:15:11 +0000 Subject: [PATCH 347/805] installation of no-sqlite fixed --- Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index 7f3e7184..2f1b323f 100755 --- a/Makefile.in +++ b/Makefile.in @@ -150,7 +150,7 @@ install: all ${MAKE_DEPS} ${INSTALL_DATA} turndb/schema.userdb.redis ${DESTDIR}${SCHEMADIR} ${INSTALL_DATA} turndb/schema.stats.redis ${DESTDIR}${DOCSDIR} ${INSTALL_DATA} turndb/schema.stats.redis ${DESTDIR}${SCHEMADIR} - ${INSTALL_DATA} sqlite/turndb ${DESTDIR}${LOCALSTATEDIR}/db/turndb + if [ -f sqlite/turndb ] ; then ${INSTALL_DATA} sqlite/turndb ${DESTDIR}${LOCALSTATEDIR}/db/turndb; fi ${INSTALL_DATA} examples/etc/turnserver.conf ${DESTDIR}${CONFDIR}/turnserver.conf.default ${INSTALL_DIR} examples/etc ${DESTDIR}${EXAMPLESDIR} ${INSTALL_DIR} examples/scripts ${DESTDIR}${EXAMPLESDIR} From 10fdcf90057b6efc6474727a83f7a8df05c3e5e2 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 23 Nov 2014 06:42:09 +0000 Subject: [PATCH 348/805] install fixed --- Makefile.in | 2 +- configure | 61 ++++++++++++++++++++++++++++------------------------- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/Makefile.in b/Makefile.in index 2f1b323f..577dd192 100755 --- a/Makefile.in +++ b/Makefile.in @@ -105,7 +105,7 @@ sqlite_empty_db : sqlite/turndb sqlite/turndb : turndb/schema.sql ${MKDIR} sqlite ${RMCMD} sqlite/turndb - ${SQLITECMD} sqlite/turndb < turndb/schema.sql + ${SQLITE_CMD} sqlite/turndb < turndb/schema.sql ### Install all: diff --git a/configure b/configure index 5a4d8510..65b39918 100755 --- a/configure +++ b/configure @@ -32,11 +32,11 @@ testlibraw() { ${CC} ${TMPCPROGC} -o ${TMPCPROGB} ${OSCFLAGS} ${OSLIBS} -${1} 2>>/dev/null ER=$? if ! [ ${ER} -eq 0 ] ; then - ${ECHO_CMD} "Library option -${1} cannot be used" - return 0 + ${ECHO_CMD} "Library option -${1} cannot be used" + return 0 else - OSLIBS="${OSLIBS} -${1}" - return 1 + OSLIBS="${OSLIBS} -${1}" + return 1 fi } @@ -45,11 +45,11 @@ testsqlite_comp() { ${CC} -c ${SQL_TMPCPROGC} -o ${SQL_TMPCPROGO} ${OSCFLAGS} 2>>/dev/null ER=$? if ! [ ${ER} -eq 0 ] ; then - ${ECHO_CMD} "SQLite development is not installed properly" - return 0 + ${ECHO_CMD} "SQLite development is not installed properly" + return 0 else - DBLIBS="${DBLIBS} ${SQLITE_LIBS}" - return 1 + DBLIBS="${DBLIBS} ${SQLITE_LIBS}" + return 1 fi } @@ -70,16 +70,16 @@ testhiredis() { ${CC} ${HR_TMPCPROGC} -o ${HR_TMPCPROGB} ${OSCFLAGS} ${DBLIBS} ${HIREDISCFLAGS} ${HIREDISLIBS} 2>>/dev/null ER=$? if ! [ ${ER} -eq 0 ] ; then - ${ECHO_CMD} - ${ECHO_CMD} "HIREDIS DEVELOPMENT LIBRARY (libhiredis.*) AND/OR HEADERS (hiredis/*.h)" - ${ECHO_CMD} " ARE NOT INSTALLED PROPERLY ON THIS SYSTEM." - ${ECHO_CMD} " THAT'S OK BUT THE TURN SERVER IS BUILDING WITHOUT REDIS SUPPORT." - ${ECHO_CMD} - return 0 + ${ECHO_CMD} + ${ECHO_CMD} "HIREDIS DEVELOPMENT LIBRARY (libhiredis.*) AND/OR HEADERS (hiredis/*.h)" + ${ECHO_CMD} " ARE NOT INSTALLED PROPERLY ON THIS SYSTEM." + ${ECHO_CMD} " THAT'S OK BUT THE TURN SERVER IS BUILDING WITHOUT REDIS SUPPORT." + ${ECHO_CMD} + return 0 else - DBCFLAGS="${DBCFLAGS} ${HIREDISCFLAGS}" - DBLIBS="${DBLIBS} ${HIREDISLIBS}" - return 1 + DBCFLAGS="${DBCFLAGS} ${HIREDISCFLAGS}" + DBLIBS="${DBLIBS} ${HIREDISLIBS}" + return 1 fi } @@ -155,15 +155,15 @@ testlibmongoc() { ER=$? if ! [ ${ER} -eq 0 ] ; then ${ECHO_CMD} - ${ECHO_CMD} "MONGODB DEVELOPMENT LIBRARIES (libmongoc-1.0 and libbson-1.0) AND/OR HEADER (mongoc.h)" - ${ECHO_CMD} " ARE NOT INSTALLED PROPERLY ON THIS SYSTEM." - ${ECHO_CMD} " THAT'S OK BUT THE TURN SERVER IS BUILDING WITHOUT MONGODB SUPPORT." - ${ECHO_CMD} - return 0 + ${ECHO_CMD} "MONGODB DEVELOPMENT LIBRARIES (libmongoc-1.0 and libbson-1.0) AND/OR HEADER (mongoc.h)" + ${ECHO_CMD} " ARE NOT INSTALLED PROPERLY ON THIS SYSTEM." + ${ECHO_CMD} " THAT'S OK BUT THE TURN SERVER IS BUILDING WITHOUT MONGODB SUPPORT." + ${ECHO_CMD} + return 0 else - DBCFLAGS="${DBCFLAGS} ${MONGO_CFLAGS}" - DBLIBS="${DBLIBS} ${MONGO_LIBS}" - return 1 + DBCFLAGS="${DBCFLAGS} ${MONGO_CFLAGS}" + DBLIBS="${DBLIBS} ${MONGO_LIBS}" + return 1 fi } @@ -613,14 +613,14 @@ RMCMD="rm -rf" type sqlite3 2>>/dev/null ER=$? if [ ${ER} -eq 0 ] ; then - SQLITECMD="sqlite3" + SQLITE_CMD="sqlite3" else type sqlite 2>>/dev/null ER=$? if [ ${ER} -eq 0 ] ; then - SQLITECMD="sqlite" + SQLITE_CMD="sqlite" else - SQLITECMD="echo" + SQLITE_CMD=${ECHO_CMD} fi fi @@ -1095,6 +1095,9 @@ if [ -z "${TURN_NO_SQLITE}" ] ; then ${ECHO_CMD} " THAT'S OK BUT THE TURN SERVER IS BUILDING WITHOUT SQLITE SUPPORT." ${ECHO_CMD} fi +else + TURN_NO_SQLITE="-DTURN_NO_SQLITE" + SQLITE_CMD=${ECHO_CMD} fi ########################### @@ -1248,7 +1251,7 @@ ${ECHO_CMD} "turnincludedir = ${TURNINCLUDEDIR}" >> Makefile ${ECHO_CMD} "#" >> Makefile ${ECHO_CMD} "ARCHIVERCMD = ${ARCHIVERCMD}" >> Makefile ${ECHO_CMD} "MKDIR = ${MKDIR}" >> Makefile -${ECHO_CMD} "SQLITECMD = ${SQLITECMD}" >> Makefile +${ECHO_CMD} "SQLITE_CMD = ${SQLITE_CMD}" >> Makefile ${ECHO_CMD} "INSTALL_PROGRAM = ${INSTALL_PROGRAM}" >> Makefile ${ECHO_CMD} "PKILL_PROGRAM = ${PKILL_PROGRAM}" >> Makefile ${ECHO_CMD} "INSTALL_MAN = ${INSTALL_MAN}" >> Makefile From dafedda0b951a458504c8979a6c3c17c90a41e83 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 23 Nov 2014 21:24:04 +0000 Subject: [PATCH 349/805] tunable TURNDBDIR --- INSTALL | 4 ++-- Makefile.in | 8 ++++---- README.turnadmin | 4 +++- README.turnserver | 8 +++++--- README.turnutils | 2 ++ configure | 13 ++++++++++++- examples/etc/turnserver.conf | 3 ++- man/man1/turnadmin.1 | 6 ++++-- man/man1/turnserver.1 | 10 ++++++---- man/man1/turnutils.1 | 4 +++- postinstall.txt | 2 +- src/apps/relay/mainrelay.c | 4 ++-- 12 files changed, 46 insertions(+), 22 deletions(-) diff --git a/INSTALL b/INSTALL index a64ec59f..5b9d0d08 100644 --- a/INSTALL +++ b/INSTALL @@ -85,7 +85,7 @@ Or: You can change the auxiliary configured destination sub-directories by setting BINDIR, CONFDIR, MANPREFIX, EXAMPLESDIR, DOCSDIR, LIBDIR, SCHEMADIR, -LOCALSTATEDIR and TURNINCLUDEDIR variables in the +LOCALSTATEDIR, TURNDBDIR and TURNINCLUDEDIR variables in the configure command line. For example: $ PREFIX=/opt BINDIR=/opt/bin64 CONFDIR=/opt/conf ./configure @@ -171,7 +171,7 @@ This command will also: - copy the content of examples subdirectory into PREFIX/share/examples/turnserver/ directory; - copy the generated default empty SQLite database from sqlite/turndb - to /var/db/turndb; + to /usr/local/var/db or to /var/db/turndb; - copy the content of include/turn subdirectory into PREFIX/include/turn/ directory; - copy the database schema file turndb/schema.sql into diff --git a/Makefile.in b/Makefile.in index 577dd192..0426fe1d 100755 --- a/Makefile.in +++ b/Makefile.in @@ -106,13 +106,13 @@ sqlite/turndb : turndb/schema.sql ${MKDIR} sqlite ${RMCMD} sqlite/turndb ${SQLITE_CMD} sqlite/turndb < turndb/schema.sql - + ### Install all: install: all ${MAKE_DEPS} ${MKDIR} ${DESTDIR}${PREFIX} ${MKDIR} ${DESTDIR}${BINDIR} - ${MKDIR} ${DESTDIR}${LOCALSTATEDIR}/db + ${MKDIR} ${DESTDIR}${TURNDBDIR} ${MKDIR} ${DESTDIR}${MANPREFIX}/man/man1 ${MKDIR} ${DESTDIR}${CONFDIR} ${MKDIR} ${DESTDIR}${LIBDIR} @@ -150,7 +150,7 @@ install: all ${MAKE_DEPS} ${INSTALL_DATA} turndb/schema.userdb.redis ${DESTDIR}${SCHEMADIR} ${INSTALL_DATA} turndb/schema.stats.redis ${DESTDIR}${DOCSDIR} ${INSTALL_DATA} turndb/schema.stats.redis ${DESTDIR}${SCHEMADIR} - if [ -f sqlite/turndb ] ; then ${INSTALL_DATA} sqlite/turndb ${DESTDIR}${LOCALSTATEDIR}/db/turndb; fi + if [ -f sqlite/turndb ] ; then ${INSTALL_DATA} sqlite/turndb ${DESTDIR}${TURNDBDIR}/turndb; fi ${INSTALL_DATA} examples/etc/turnserver.conf ${DESTDIR}${CONFDIR}/turnserver.conf.default ${INSTALL_DIR} examples/etc ${DESTDIR}${EXAMPLESDIR} ${INSTALL_DIR} examples/scripts ${DESTDIR}${EXAMPLESDIR} @@ -161,7 +161,7 @@ install: all ${MAKE_DEPS} deinstall: ${MAKE_DEPS} ${PKILL_PROGRAM} turnserver || ${ECHO_CMD} OK - ${RMCMD} ${DESTDIR}${LOCALSTATEDIR}/db/turndb + ${RMCMD} ${DESTDIR}${TURNDBDIR}/turndb ${RMCMD} ${DESTDIR}${DOCSDIR} ${RMCMD} ${DESTDIR}${SCHEMADIR} ${RMCMD} ${DESTDIR}${BINDIR}/turnserver diff --git a/README.turnadmin b/README.turnadmin index 7113cf42..589e531a 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -81,7 +81,7 @@ Commands: Options with required values: -b, --db, --userdb SQLite user database file name (default - /var/db/turndb or - /usr/local/var/db/turndb). + /usr/local/var/db/turndb or /var/lib/turn/turndb). See the same option in the turnserver section. -e, --psql-userdb PostgreSQL user database connection string. See the --psql-userdb option in the turnserver section. @@ -175,6 +175,8 @@ to see the man page. /usr/local/var/db/turndb +/var/lib/turn/turndb + /usr/local/etc/turnserver.conf ===================================== diff --git a/README.turnserver b/README.turnserver index 4d564295..ce6cdd12 100644 --- a/README.turnserver +++ b/README.turnserver @@ -82,7 +82,7 @@ Config file settings: User database settings: -b, --db, --userdb SQLite user database file name (default - /var/db/turndb or - /usr/local/var/db/turndb). + /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 @@ -718,7 +718,7 @@ Obviously, only a few users can be set that way, and their credentials are fixed for the turnserver process lifetime. 2) Users can be stored in SQLite DB. The default SQLite database file is /var/db/turndb -or /usr/local/var/db/turndb. +or /usr/local/var/db/turndb or /var/lib/turn/turndb. 3) Users can be stored in PostgreSQL database, if the turnserver was compiled with PostgreSQL support. Each time turnserver checks user credentials, it reads the database (asynchronously, @@ -773,7 +773,7 @@ with schema.sql SQL script. With Redis, you do not have to do even that - just r it will set the users for you (see the turnadmin manuals). If you are using SQLite, then the turnserver or turnadmin will initialize the empty database, for you, when started. The TURN server installation process creates an empty initialized SQLite database in the default -location (/var/db/turndb or /usr/local/var/db/turndb, depending on the system). +location (/var/db/turndb or /usr/local/var/db/turndb or /var/lib/turn/turndb, depending on the system). ================================= @@ -850,6 +850,8 @@ FILES /usr/local/var/db/turndb +/var/lib/turn/turndb + /usr/local/etc/turnserver.conf ================================= diff --git a/README.turnutils b/README.turnutils index 865d8f92..dc57ad40 100644 --- a/README.turnutils +++ b/README.turnutils @@ -255,6 +255,8 @@ FILES /usr/local/var/db/turndb +/var/lib/turn/turndb + /usr/local/etc/turnserver.conf ================================= diff --git a/configure b/configure index 65b39918..23d95c5a 100755 --- a/configure +++ b/configure @@ -351,6 +351,11 @@ do -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* | --localstate=* | --localstat=*) LOCALSTATEDIR=$ac_optarg ;; + -turndbdir | --turndbdir | --turndbdi | --turndbd | --turndb | --turnd) + ac_prev=TURNDBDIR ;; + -turndbdir=* | --turndbdir=* | --turndbdi=* | --turndbd=* | --turndb=* | --turnd=*) + TURNDBDIR=$ac_optarg ;; + -datadir | --datadir | --datadi | --datad | -schemadir | --schemadir) ac_prev=SCHEMADIR ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | -schemadir=* | --schemadir=*) @@ -1100,6 +1105,10 @@ else SQLITE_CMD=${ECHO_CMD} fi +if [ -z "${TURNDBDIR}" ] ; then + TURNDBDIR=${LOCALSTATEDIR}/db +fi + ########################### # Test PostgreSQL ########################### @@ -1199,7 +1208,7 @@ fi # So, what we have now: ############################### -OSCFLAGS="${OSCFLAGS} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX} -DTURNDB=${LOCALSTATEDIR}/db/turndb" +OSCFLAGS="${OSCFLAGS} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX} -DTURNDB=${TURNDBDIR}/turndb" if ! [ -z "${TURN_ACCEPT_RPATH}" ] ; then if [ -z "${TURN_DISABLE_RPATH}" ] ; then @@ -1232,6 +1241,8 @@ ${ECHO_CMD} "BINDIR = ${BINDIR}" >> Makefile ${ECHO_CMD} "bindir = ${BINDIR}" >> Makefile ${ECHO_CMD} "LOCALSTATEDIR = ${LOCALSTATEDIR}" >> Makefile ${ECHO_CMD} "localstatedir = ${LOCALSTATEDIR}" >> Makefile +${ECHO_CMD} "TURNDBDIR = ${TURNDBDIR}" >> Makefile +${ECHO_CMD} "turndbdir = ${TURNDBDIR}" >> Makefile ${ECHO_CMD} "CONFDIR = ${CONFDIR}" >> Makefile ${ECHO_CMD} "confdir = ${CONFDIR}" >> Makefile ${ECHO_CMD} "MANPREFIX = ${MANPREFIX}" >> Makefile diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 559f9314..4e1b8c45 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -246,7 +246,8 @@ # SQLite database file name. # -# Default file name is /var/db/turndb or /usr/local/var/db/turndb. +# Default file name is /var/db/turndb or /usr/local/var/db/turndb or +# /var/lib/turn/turndb. # #userdb=/var/db/turndb diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 964c84da..462f111d 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "21 November 2014" "" "" +.TH TURN 1 "23 November 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage @@ -133,7 +133,7 @@ Options with required values: .B \fB\-b\fP, \fB\-\-db\fP, \fB\-\-userdb\fP SQLite user database file name (default \- /var/db/turndb or -/usr/local/var/db/turndb). +/usr/local/var/db/turndb or /var/lib/turn/turndb). See the same option in the \fIturnserver\fP section. .TP .B @@ -266,6 +266,8 @@ to see the man page. .PP /usr/local/var/db/turndb .PP +/var/lib/turn/turndb +.PP /usr/local/etc/turnserver.conf .PP ===================================== diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 62391438..dff14c15 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "21 November 2014" "" "" +.TH TURN 1 "23 November 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -133,7 +133,7 @@ User database settings: .B \fB\-b\fP, \fB\-\-db\fP, \fB\-\-userdb\fP SQLite user database file name (default \- /var/db/turndb or -/usr/local/var/db/turndb). +/usr/local/var/db/turndb or /var/lib/turn/turndb). .TP .B \fB\-e\fP, \fB\-\-psql\-userdb\fP @@ -973,7 +973,7 @@ Obviously, only a few users can be set that way, and their credentials are fixed for the \fIturnserver\fP process lifetime. .IP 2) 4 Users can be stored in SQLite DB. The default SQLite database file is /var/db/turndb -or /usr/local/var/db/turndb. +or /usr/local/var/db/turndb or /var/lib/turn/turndb. .IP 3) 4 Users can be stored in PostgreSQL database, if the \fIturnserver\fP was compiled with PostgreSQL support. Each time \fIturnserver\fP checks user credentials, it reads the database (asynchronously, @@ -1028,7 +1028,7 @@ with schema.sql SQL script. With Redis, you do not have to do even that \- just it will set the users for you (see the \fIturnadmin\fP manuals). If you are using SQLite, then the \fIturnserver\fP or \fIturnadmin\fP will initialize the empty database, for you, when started. The TURN server installation process creates an empty initialized SQLite database in the default -location (/var/db/turndb or /usr/local/var/db/turndb, depending on the system). +location (/var/db/turndb or /usr/local/var/db/turndb or /var/lib/turn/turndb, depending on the system). .PP ================================= .SH LIBRARIES @@ -1105,6 +1105,8 @@ it would affect the performance. .PP /usr/local/var/db/turndb .PP +/var/lib/turn/turndb +.PP /usr/local/etc/turnserver.conf .PP ================================= diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 57d5b1ab..ac7083e0 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "21 November 2014" "" "" +.TH TURN 1 "23 November 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -378,6 +378,8 @@ to see the man page. .PP /usr/local/var/db/turndb .PP +/var/lib/turn/turndb +.PP /usr/local/etc/turnserver.conf .PP ================================= diff --git a/postinstall.txt b/postinstall.txt index 0dbc55dc..471dda4f 100644 --- a/postinstall.txt +++ b/postinstall.txt @@ -17,7 +17,7 @@ service, you have to: as Redis status & statistics database schema description. If you are using SQLite, the default database location is in - /var/db/turndb or in /usr/local/var/db/turndb. + /var/db/turndb or in /usr/local/var/db/turndb or in /var/lib/turn/turndb. c) add whatever is necessary to enable start-up daemon for the /usr/local/bin/turnserver. diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 5b40bb52..129cc389 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -438,7 +438,7 @@ static char Usage[] = "Usage: turnserver [options]\n" " -c Configuration file name (default - turnserver.conf).\n" #if !defined(TURN_NO_SQLITE) " -b, , --db, --userdb SQLite database file name; default - /var/db/turndb or\n" -" /usr/local/var/db/turndb.\n" +" /usr/local/var/db/turndb or /var/lib/turn/turndb.\n" #endif #if !defined(TURN_NO_PQ) " -e, --psql-userdb, --sql-userdb PostgreSQL database connection string, if used (default - empty, no PostreSQL DB used).\n" @@ -613,7 +613,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" "\nOptions with mandatory values:\n\n" #if !defined(TURN_NO_SQLITE) " -b, --db, --userdb SQLite database file, default value is /var/db/turndb or\n" - " /usr/local/var/db/turndb.\n" + " /usr/local/var/db/turndb or /var/lib/turn/turndb.\n" #endif #if !defined(TURN_NO_PQ) " -e, --psql-userdb, --sql-userdb PostgreSQL user database connection string, if PostgreSQL DB is used.\n" From fe673e62cab6e796d50cf3dac9f6ed61ef4673a9 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 23 Nov 2014 21:32:20 +0000 Subject: [PATCH 350/805] version up to 4.3.1.2 --- ChangeLog | 6 +++++- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 6 ++++-- src/ns_turn_defs.h | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2e0febc0..67b75fee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ -11/10/2014 Oleg Moskalenko +11/23/2014 Oleg Moskalenko +Version 4.3.1.2 'Tolomei': + - Debian package fixes. + +11/22/2014 Oleg Moskalenko Version 4.3.1.1 'Tolomei': - SQLite supported as the default user database. - Support of the flat-file user database removed. diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 093eed71..ffc7e827 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.3.1.1 +TURNVERSION=4.3.1.2 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index f1902b96..0a05c68c 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.3.1.1 +Version: 4.3.1.2 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,7 +294,9 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Mon Nov 10 2014 Oleg Moskalenko +* Mon Nov 23 2014 Oleg Moskalenko + - Sync to 4.3.1.2 +* Mon Nov 22 2014 Oleg Moskalenko - Sync to 4.3.1.1 * Thu Nov 07 2014 Oleg Moskalenko - Sync to 4.2.3.1 diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 6f0d3ca2..4c3d2a23 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.3.1.1" +#define TURN_SERVER_VERSION "4.3.1.2" #define TURN_SERVER_VERSION_NAME "Tolomei" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 6bd501ac9d9ce133c720255f5a539d48a170e9a5 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 30 Nov 2014 03:29:18 +0000 Subject: [PATCH 351/805] peer_input_handler fixes --- ChangeLog | 4 ++++ rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/apps/relay/mainrelay.c | 32 ++++++++++++++++++++------------ src/ns_turn_defs.h | 2 +- src/server/ns_turn_server.c | 25 ++++++++++++++----------- 6 files changed, 43 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 67b75fee..50ecdf5c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +11/29/2014 Oleg Moskalenko +Version 4.3.1.3 'Tolomei': + - Reliability fixes (Issue 141 from rfc5766-turn-server). + 11/23/2014 Oleg Moskalenko Version 4.3.1.2 'Tolomei': - Debian package fixes. diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index ffc7e827..e4c19573 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.3.1.2 +TURNVERSION=4.3.1.3 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 0a05c68c..6b76d9e6 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.3.1.2 +Version: 4.3.1.3 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,6 +294,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Sat Nov 29 2014 Oleg Moskalenko + - Sync to 4.3.1.3 * Mon Nov 23 2014 Oleg Moskalenko - Sync to 4.3.1.2 * Mon Nov 22 2014 Oleg Moskalenko diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 129cc389..9327da13 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -2063,15 +2063,17 @@ int main(int argc, char **argv) #if defined(OPENSSL_THREADS) -static pthread_mutex_t* mutex_buf = NULL; +static pthread_mutex_t** mutex_buf = NULL; static void locking_function(int mode, int n, const char *file, int line) { UNUSED_ARG(file); UNUSED_ARG(line); - if (mode & CRYPTO_LOCK) - pthread_mutex_lock(&mutex_buf[n]); - else - pthread_mutex_unlock(&mutex_buf[n]); + if(mutex_buf && (n < CRYPTO_num_locks()) && mutex_buf[n]) { + if (mode & CRYPTO_LOCK) + pthread_mutex_lock(mutex_buf[n]); + else + pthread_mutex_unlock(mutex_buf[n]); + } } #if OPENSSL_VERSION_NUMBER >= 0x10000000L @@ -2094,12 +2096,13 @@ static int THREAD_setup(void) { int i; - mutex_buf = (pthread_mutex_t*) turn_malloc(CRYPTO_num_locks() - * sizeof(pthread_mutex_t)); + mutex_buf = (pthread_mutex_t**) turn_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t*)); if (!mutex_buf) return 0; - for (i = 0; i < CRYPTO_num_locks(); i++) - pthread_mutex_init(&mutex_buf[i], NULL); + for (i = 0; i < CRYPTO_num_locks(); i++) { + mutex_buf[i] = (pthread_mutex_t*) turn_malloc(sizeof(pthread_mutex_t)); + pthread_mutex_init(mutex_buf[i], NULL); + } #if OPENSSL_VERSION_NUMBER >= 0x10000000L CRYPTO_THREADID_set_callback(id_function); @@ -2130,9 +2133,14 @@ int THREAD_cleanup(void) { #endif CRYPTO_set_locking_callback(NULL); - for (i = 0; i < CRYPTO_num_locks(); i++) - pthread_mutex_destroy(&mutex_buf[i]); - turn_free(mutex_buf,sizeof(pthread_mutex_t)); + for (i = 0; i < CRYPTO_num_locks(); i++) { + if(mutex_buf[i]) { + pthread_mutex_destroy(mutex_buf[i]); + turn_free(mutex_buf[i],sizeof(pthread_mutex_t)); + mutex_buf[i] = NULL; + } + } + turn_free(mutex_buf,CRYPTO_num_locks() * sizeof(pthread_mutex_t*)); mutex_buf = NULL; #endif diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 4c3d2a23..bb136d3f 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.3.1.2" +#define TURN_SERVER_VERSION "4.3.1.3" #define TURN_SERVER_VERSION_NAME "Tolomei" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 99ad1dfd..b8968a9c 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4623,24 +4623,23 @@ int open_client_connection_session(turn_turnserver* server, static void peer_input_handler(ioa_socket_handle s, int event_type, ioa_net_data *in_buffer, void *arg, int can_resume) { - if (!(event_type & IOA_EV_READ) || !arg) - return; + if (!(event_type & IOA_EV_READ) || !arg) return; - if(in_buffer->recv_ttl==0) - return; + if(in_buffer->recv_ttl==0) return; - UNUSED_ARG(s); UNUSED_ARG(can_resume); + if(ioa_socket_tobeclosed(s)) return; + ts_ur_super_session* ss = (ts_ur_super_session*) arg; - if(!ss || !s) return; + if(!ss) return; + + if(ss->to_be_closed) return; turn_turnserver *server = (turn_turnserver*) (ss->server); - if (!server) { - return; - } + if (!server) return; relay_endpoint_session* elem = get_relay_session_ss(ss, get_ioa_socket_address_family(s)); if (elem->s == NULL) { @@ -4654,8 +4653,6 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, if (ilen >= 0) { - size_t len = (size_t)(ilen); - allocation* a = get_allocation_ss(ss); if (is_allocation_valid(a)) { @@ -4672,6 +4669,9 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, } if (chnum) { + + size_t len = (size_t)(ilen); + nbh = in_buffer->nbh; ioa_network_buffer_add_offset_size(nbh, @@ -4693,6 +4693,9 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, (int) (chnum)); } } else { + + size_t len = 0; + nbh = ioa_network_buffer_allocate(server->e); stun_init_indication_str(STUN_METHOD_DATA, ioa_network_buffer_data(nbh), &len); stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_DATA, From e8d39a8e776e609bcc2706417a5e3ef8aad11da3 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 30 Nov 2014 18:11:29 +0000 Subject: [PATCH 352/805] working on 141 --- src/server/ns_turn_server.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index b8968a9c..bdca6c8b 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4629,7 +4629,7 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, UNUSED_ARG(can_resume); - if(ioa_socket_tobeclosed(s)) return; + if(!s || ioa_socket_tobeclosed(s)) return; ts_ur_super_session* ss = (ts_ur_super_session*) arg; @@ -4637,6 +4637,8 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, if(ss->to_be_closed) return; + if(!(ss->client_socket) || ioa_socket_tobeclosed(ss->client_socket)) return; + turn_turnserver *server = (turn_turnserver*) (ss->server); if (!server) return; From 69d524a3801973c6dae2c9d0b89c36c2a7740762 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 1 Dec 2014 08:12:31 +0000 Subject: [PATCH 353/805] minor fix --- src/apps/relay/mainrelay.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 9327da13..99e134a5 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -2063,6 +2063,8 @@ int main(int argc, char **argv) #if defined(OPENSSL_THREADS) +static char some_buffer[65536]; + static pthread_mutex_t** mutex_buf = NULL; static void locking_function(int mode, int n, const char *file, int line) { @@ -2096,6 +2098,8 @@ static int THREAD_setup(void) { int i; + some_buffer[0] = 0; + mutex_buf = (pthread_mutex_t**) turn_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t*)); if (!mutex_buf) return 0; From df7b770ebb0d02f5f5c8ebe59090047f031d0013 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 1 Dec 2014 17:54:38 +0000 Subject: [PATCH 354/805] minor fixes --- src/apps/relay/dbdrivers/dbd_sqlite.c | 2 +- src/apps/relay/mainrelay.c | 30 ++++++++++++--------------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 957c9d44..0646bfaa 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -126,7 +126,7 @@ static sqlite3 * get_sqlite_connection(void) { int rc = sqlite3_open(pud->userdb, &sqliteconnection); if(!sqliteconnection || (rc != SQLITE_OK)) { const char* errmsg = sqlite3_errmsg(sqliteconnection); - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open SQLite DB connection: <%s>, runtime error:\n %s\n (If your intention is to use a database for the TURN server, then\n check the TURN server process / file / DB directory permissions and\n re-start the TURN server)\n",pud->userdb,errmsg); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open SQLite DB connection: <%s>, runtime error:\n %s\n (If your intention is to use an SQLite database for the TURN server, then\n check and fix, if necessary, the effective permissions of the TURN server\n process and of the DB directory and then re-start the TURN server)\n",pud->userdb,errmsg); if(sqliteconnection) { sqlite3_close(sqliteconnection); sqliteconnection=NULL; diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 99e134a5..c309351c 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -2065,16 +2065,18 @@ int main(int argc, char **argv) static char some_buffer[65536]; -static pthread_mutex_t** mutex_buf = NULL; +//array larger than anything that OpenSSL may need: +static pthread_mutex_t mutex_buf[256]; +static int mutex_buf_initialized = 0; static void locking_function(int mode, int n, const char *file, int line) { UNUSED_ARG(file); UNUSED_ARG(line); - if(mutex_buf && (n < CRYPTO_num_locks()) && mutex_buf[n]) { + if(mutex_buf_initialized && (n < CRYPTO_num_locks())) { if (mode & CRYPTO_LOCK) - pthread_mutex_lock(mutex_buf[n]); + pthread_mutex_lock(&(mutex_buf[n])); else - pthread_mutex_unlock(mutex_buf[n]); + pthread_mutex_unlock(&(mutex_buf[n])); } } @@ -2100,14 +2102,12 @@ static int THREAD_setup(void) { some_buffer[0] = 0; - mutex_buf = (pthread_mutex_t**) turn_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t*)); - if (!mutex_buf) - return 0; for (i = 0; i < CRYPTO_num_locks(); i++) { - mutex_buf[i] = (pthread_mutex_t*) turn_malloc(sizeof(pthread_mutex_t)); - pthread_mutex_init(mutex_buf[i], NULL); + pthread_mutex_init(&(mutex_buf[i]), NULL); } + mutex_buf_initialized = 1; + #if OPENSSL_VERSION_NUMBER >= 0x10000000L CRYPTO_THREADID_set_callback(id_function); #else @@ -2127,7 +2127,7 @@ int THREAD_cleanup(void) { int i; - if (!mutex_buf) + if (!mutex_buf_initialized) return 0; #if OPENSSL_VERSION_NUMBER >= 0x10000000L @@ -2138,14 +2138,10 @@ int THREAD_cleanup(void) { CRYPTO_set_locking_callback(NULL); for (i = 0; i < CRYPTO_num_locks(); i++) { - if(mutex_buf[i]) { - pthread_mutex_destroy(mutex_buf[i]); - turn_free(mutex_buf[i],sizeof(pthread_mutex_t)); - mutex_buf[i] = NULL; - } + pthread_mutex_destroy(&(mutex_buf[i])); } - turn_free(mutex_buf,CRYPTO_num_locks() * sizeof(pthread_mutex_t*)); - mutex_buf = NULL; + + mutex_buf_initialized = 0; #endif From f8c08b4a58769d39c4f21948a2b5c52396af938c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 2 Dec 2014 06:06:57 +0000 Subject: [PATCH 355/805] HTTP/HTTPS requests fixed --- ChangeLog | 1 + src/server/ns_turn_server.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 50ecdf5c..a940d095 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 11/29/2014 Oleg Moskalenko Version 4.3.1.3 'Tolomei': - Reliability fixes (Issue 141 from rfc5766-turn-server). + - HTTP/HTTPS echo fixed. 11/23/2014 Oleg Moskalenko Version 4.3.1.2 'Tolomei': diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index bdca6c8b..d77107d8 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4540,9 +4540,12 @@ 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))) - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTP request: %s\n", __FUNCTION__, (char*)ioa_network_buffer_data(in_buffer->nbh)); + if(is_http_get((char*)ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh))) { + const char *proto = "HTTP"; + if(st==TLS_SOCKET) proto = "HTTPS"; + 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(server,ss); + } } } From f9ac2c4460cd4391832a36807ccb8a10e00639aa Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 2 Dec 2014 06:47:39 +0000 Subject: [PATCH 356/805] https connections handling --- src/apps/relay/ns_ioalib_engine_impl.c | 123 ++++++++++++++----------- src/server/ns_turn_ioalib.h | 4 + src/server/ns_turn_server.c | 35 ++++++- 3 files changed, 105 insertions(+), 57 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index aa825d2a..8990a000 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -108,66 +108,67 @@ static int bufferevent_enabled(struct bufferevent *bufev, short flags) return (bufferevent_get_enabled(bufev) & flags); } -static int is_socket_writeable(ioa_socket_handle s, size_t sz, const char *msg, int option) +static int is_socket_writeable(ioa_socket_handle s, size_t sz, const char *msg, int option) { - UNUSED_ARG(sz); - UNUSED_ARG(msg); - UNUSED_ARG(option); + UNUSED_ARG(sz); + UNUSED_ARG(msg); + UNUSED_ARG(option); - if(!s) - return 0; + if (!s) + return 0; - if(!(s->done) && !(s->broken) && !(s->tobeclosed)) { + if (!(s->done) && !(s->broken) && !(s->tobeclosed)) { - switch(s->st) { - - case TCP_SOCKET: - case TLS_SOCKET: - if(s->bev) { + switch (s->st){ - struct evbuffer *evb = bufferevent_get_output(s->bev); - - if(evb) { - size_t bufsz = evbuffer_get_length(evb); - size_t newsz = bufsz + sz; - - switch(s->sat) { - case TCP_CLIENT_DATA_SOCKET: - case TCP_RELAY_DATA_SOCKET: - - switch(option) { - case 0: - case 1: - if(newsz >= BUFFEREVENT_MAX_TCP_TO_TCP_WRITE) { - return 0; - } - break; - case 3: - case 4: - if(newsz >= BUFFEREVENT_MAX_TCP_TO_TCP_WRITE) { - return 0; - } - break; - default: - return 1; - }; - break; - default: - if(option == 2) { - if(newsz >= BUFFEREVENT_MAX_UDP_TO_TCP_WRITE) { - return 0; - } - } - }; + case TCP_SOCKET: + case TLS_SOCKET: + if (s->bev) { + + struct evbuffer *evb = bufferevent_get_output(s->bev); + + if (evb) { + size_t bufsz = evbuffer_get_length(evb); + size_t newsz = bufsz + sz; + + switch (s->sat){ + case TCP_CLIENT_DATA_SOCKET: + case TCP_RELAY_DATA_SOCKET: + + switch (option){ + case 0: + case 1: + if (newsz >= BUFFEREVENT_MAX_TCP_TO_TCP_WRITE) { + return 0; + } + break; + case 3: + case 4: + if (newsz >= BUFFEREVENT_MAX_TCP_TO_TCP_WRITE) { + return 0; + } + break; + default: + return 1; + } + ; + break; + default: + if (option == 2) { + if (newsz >= BUFFEREVENT_MAX_UDP_TO_TCP_WRITE) { + return 0; + } + } + }; + } + } + break; + default: + ; + }; } - } - break; - default: - ; - }; - } - return 1; + return 1; } static void log_socket_event(ioa_socket_handle s, const char *msg, int error) { @@ -3448,6 +3449,22 @@ void ioa_network_buffer_delete(ioa_engine_handle e, ioa_network_buffer_handle nb /////////// REPORTING STATUS ///////////////////// +const char* get_ioa_socket_cipher(ioa_socket_handle s) +{ + if(s && s->ssl) { + return SSL_get_cipher(s->ssl); + } + return "no SSL"; +} + +const char* get_ioa_socket_ssl_method(ioa_socket_handle s) +{ + if(s && s->ssl) { + return turn_get_ssl_method(s->ssl, s->orig_ctx_type); + } + return "no SSL"; +} + void turn_report_allocation_set(void *a, turn_time_t lifetime, int refresh) { if(a) { diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 79fb3c48..fb703971 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -96,6 +96,8 @@ typedef enum _SOCKET_TYPE SOCKET_TYPE; enum _SOCKET_APP_TYPE { UNKNOWN_APP_SOCKET, CLIENT_SOCKET, + HTTP_CLIENT_SOCKET, + HTTPS_CLIENT_SOCKET, RELAY_SOCKET, RELAY_RTCP_SOCKET, TCP_CLIENT_DATA_SOCKET, @@ -225,6 +227,8 @@ ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, i int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_token, ioa_socket_handle *s, u08bits *realm); int get_ioa_socket_address_family(ioa_socket_handle s); +const char* get_ioa_socket_cipher(ioa_socket_handle s); +const char* get_ioa_socket_ssl_method(ioa_socket_handle s); SOCKET_TYPE get_ioa_socket_type(ioa_socket_handle s); SOCKET_APP_TYPE get_ioa_socket_app_type(ioa_socket_handle s); const char* get_ioa_socket_tls_method(ioa_socket_handle s); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index d77107d8..d50a70c4 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4161,8 +4161,11 @@ static void client_to_be_allocated_timeout_handler(ioa_engine_handle e, int to_close = 0; ioa_socket_handle s = ss->client_socket; + if(!s || ioa_socket_tobeclosed(s)) { to_close = 1; + } else if(get_ioa_socket_app_type(s) == HTTPS_CLIENT_SOCKET) { + ; } else { ioa_socket_handle rs4 = ss->alloc.relay_sessions[ALLOC_IPV4_INDEX].s; ioa_socket_handle rs6 = ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].s; @@ -4415,6 +4418,12 @@ static void write_http_echo(turn_turnserver *server, ts_ur_super_session *ss) } } +static void handle_https(turn_turnserver *server, ts_ur_super_session *ss, ioa_network_buffer_handle nbh) { + //TODO + UNUSED_ARG(nbh); + write_http_echo(server,ss); +} + static int read_client_connection(turn_turnserver *server, ts_ur_super_session *ss, ioa_net_data *in_buffer, int can_resume, int count_usage) { @@ -4451,9 +4460,20 @@ static int read_client_connection(turn_turnserver *server, size_t blen = ioa_network_buffer_get_size(in_buffer->nbh); size_t orig_blen = blen; SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket); + SOCKET_APP_TYPE sat = get_ioa_socket_app_type(ss->client_socket); int is_padding_mandatory = ((st == TCP_SOCKET)||(st==TLS_SOCKET)||(st==TENTATIVE_TCP_SOCKET)); - if (stun_is_channel_message_str(ioa_network_buffer_data(in_buffer->nbh), + 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(server,ss); + + } 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(server,ss,in_buffer->nbh); + + } else if (stun_is_channel_message_str(ioa_network_buffer_data(in_buffer->nbh), &blen, &chnum, is_padding_mandatory)) { @@ -4542,9 +4562,16 @@ static int read_client_connection(turn_turnserver *server, 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))) { const char *proto = "HTTP"; - if(st==TLS_SOCKET) proto = "HTTPS"; - 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(server,ss); + 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(server,ss,in_buffer->nbh); + } 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(server,ss); + } } } } From d2922f53fccf09cf0834ce47727ec00af070851c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 2 Dec 2014 08:02:05 +0000 Subject: [PATCH 357/805] separate http-related code module --- Makefile.in | 2 +- src/apps/relay/http_server.c | 58 ++++++++++++++++++++++++++++++++++++ src/server/ns_turn_ioalib.h | 5 ++++ src/server/ns_turn_server.c | 32 +++----------------- 4 files changed, 68 insertions(+), 29 deletions(-) create mode 100644 src/apps/relay/http_server.c diff --git a/Makefile.in b/Makefile.in index 0426fe1d..bae43e13 100755 --- a/Makefile.in +++ b/Makefile.in @@ -21,7 +21,7 @@ COMMON_MODS = src/apps/common/apputils.c src/apps/common/ns_turn_utils.c src/app COMMON_DEPS = ${LIBCLIENTTURN_DEPS} ${COMMON_MODS} ${COMMON_HEADERS} IMPL_HEADERS = src/apps/relay/ns_ioalib_impl.h src/apps/relay/ns_sm.h src/apps/relay/turn_ports.h -IMPL_MODS = src/apps/relay/ns_ioalib_engine_impl.c src/apps/relay/turn_ports.c +IMPL_MODS = src/apps/relay/ns_ioalib_engine_impl.c src/apps/relay/turn_ports.c src/apps/relay/http_server.c IMPL_DEPS = ${COMMON_DEPS} ${IMPL_HEADERS} ${IMPL_MODS} HIREDIS_HEADERS = src/apps/common/hiredis_libevent2.h diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c new file mode 100644 index 00000000..bcb78d3c --- /dev/null +++ b/src/apps/relay/http_server.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2011, 2012, 2013 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. + */ + +#include "ns_ioalib_impl.h" + +void write_http_echo(ts_ur_super_session *ss) +{ + if(ss && ss->client_socket && !(ss->to_be_closed)) { + turn_turnserver *server = (turn_turnserver *)ss->server; + if(server) { + ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(server->e); + size_t len_http = ioa_network_buffer_get_size(nbh_http); + u08bits *data = ioa_network_buffer_data(nbh_http); + char data_http[1025]; + char content_http[1025]; + const char* title = "TURN Server"; + snprintf(content_http,sizeof(content_http)-1,"\r\n\r\n \r\n %s\r\n \r\n \r\n %s\r\n \r\n\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); + len_http = strlen(data_http); + ns_bcopy(data_http,data,len_http); + ioa_network_buffer_set_size(nbh_http,len_http); + send_data_from_ioa_socket_nbh(ss->client_socket, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE); + } + } +} + +void handle_https(ts_ur_super_session *ss, ioa_network_buffer_handle nbh) { + //TODO + UNUSED_ARG(nbh); + write_http_echo(ss); +} diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index fb703971..4b28cfcd 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -276,6 +276,11 @@ void get_realm_options_by_name(char *realm, realm_options_t* ro); int get_canonic_origin(const char* o, char *co, int sz); int get_default_protocol_port(const char* scheme, size_t slen); +///////////// HTTP //////////////////// + +void write_http_echo(ts_ur_super_session *ss); +void handle_https(ts_ur_super_session *ss, ioa_network_buffer_handle nbh); + /////////////////////////////////////// #ifdef __cplusplus diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index d50a70c4..1f85113c 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4400,30 +4400,6 @@ static int refresh_relay_connection(turn_turnserver* server, } } -static void write_http_echo(turn_turnserver *server, ts_ur_super_session *ss) -{ - if(server && ss && ss->client_socket && !(ss->to_be_closed)) { - ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(server->e); - size_t len_http = ioa_network_buffer_get_size(nbh_http); - u08bits *data = ioa_network_buffer_data(nbh_http); - char data_http[1025]; - char content_http[1025]; - const char* title = "TURN Server"; - snprintf(content_http,sizeof(content_http)-1,"\r\n\r\n \r\n %s\r\n \r\n \r\n %s\r\n \r\n\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); - len_http = strlen(data_http); - ns_bcopy(data_http,data,len_http); - ioa_network_buffer_set_size(nbh_http,len_http); - send_data_from_ioa_socket_nbh(ss->client_socket, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE); - } -} - -static void handle_https(turn_turnserver *server, ts_ur_super_session *ss, ioa_network_buffer_handle nbh) { - //TODO - UNUSED_ARG(nbh); - write_http_echo(server,ss); -} - static int read_client_connection(turn_turnserver *server, ts_ur_super_session *ss, ioa_net_data *in_buffer, int can_resume, int count_usage) { @@ -4466,12 +4442,12 @@ 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(server,ss); + write_http_echo(ss); } 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(server,ss,in_buffer->nbh); + handle_https(ss,in_buffer->nbh); } else if (stun_is_channel_message_str(ioa_network_buffer_data(in_buffer->nbh), &blen, @@ -4566,11 +4542,11 @@ static int read_client_connection(turn_turnserver *server, 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(server,ss,in_buffer->nbh); + handle_https(ss,in_buffer->nbh); } 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(server,ss); + write_http_echo(ss); } } } From 849e67269e3bba1bf92940c512b7f93fbfda7664 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 2 Dec 2014 08:27:21 +0000 Subject: [PATCH 358/805] http code cleaning --- src/apps/relay/http_server.c | 16 ++++++++-------- src/server/ns_turn_ioalib.h | 4 ++-- src/server/ns_turn_server.c | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index bcb78d3c..56f23dc7 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -30,12 +30,12 @@ #include "ns_ioalib_impl.h" -void write_http_echo(ts_ur_super_session *ss) +void write_http_echo(ioa_socket_handle s) { - if(ss && ss->client_socket && !(ss->to_be_closed)) { - turn_turnserver *server = (turn_turnserver *)ss->server; - if(server) { - ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(server->e); + if(s && !ioa_socket_tobeclosed(s)) { + SOCKET_APP_TYPE sat = get_ioa_socket_app_type(s); + if((sat == HTTP_CLIENT_SOCKET) || (sat == HTTPS_CLIENT_SOCKET)) { + ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(s->e); size_t len_http = ioa_network_buffer_get_size(nbh_http); u08bits *data = ioa_network_buffer_data(nbh_http); char data_http[1025]; @@ -46,13 +46,13 @@ void write_http_echo(ts_ur_super_session *ss) len_http = strlen(data_http); ns_bcopy(data_http,data,len_http); ioa_network_buffer_set_size(nbh_http,len_http); - send_data_from_ioa_socket_nbh(ss->client_socket, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE); + send_data_from_ioa_socket_nbh(s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE); } } } -void handle_https(ts_ur_super_session *ss, ioa_network_buffer_handle nbh) { +void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { //TODO UNUSED_ARG(nbh); - write_http_echo(ss); + write_http_echo(s); } diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 4b28cfcd..7afb6ae3 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -278,8 +278,8 @@ int get_default_protocol_port(const char* scheme, size_t slen); ///////////// HTTP //////////////////// -void write_http_echo(ts_ur_super_session *ss); -void handle_https(ts_ur_super_session *ss, ioa_network_buffer_handle nbh); +void write_http_echo(ioa_socket_handle s); +void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh); /////////////////////////////////////// diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 1f85113c..949334ba 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4442,12 +4442,12 @@ 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); + write_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,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, @@ -4542,11 +4542,11 @@ static int read_client_connection(turn_turnserver *server, 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,in_buffer->nbh); + handle_https(ss->client_socket,in_buffer->nbh); } 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); + write_http_echo(ss->client_socket); } } } From ff7fadd0d542c170623063dc15d04efdceaf2e5c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 3 Dec 2014 07:08:17 +0000 Subject: [PATCH 359/805] relay mapping fixed --- ChangeLog | 1 + src/apps/relay/mainrelay.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index a940d095..ea3f77aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,7 @@ Version 4.3.1.3 'Tolomei': - Reliability fixes (Issue 141 from rfc5766-turn-server). - HTTP/HTTPS echo fixed. + - external address mapping fixes for Amazon EC2. 11/23/2014 Oleg Moskalenko Version 4.3.1.2 'Tolomei': diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index c309351c..dfa6048a 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1993,6 +1993,23 @@ int main(int argc, char **argv) } } + if(turn_params.external_ip && turn_params.relay_addrs) { + size_t ir = 0; + for(ir = 0; ir < turn_params.relays_number; ++ir) { + if(turn_params.relay_addrs[ir]) { + const char* sra = (const char*)turn_params.relay_addrs[ir]; + if((strstr(sra,"127.0.0.1") != sra)&&(strstr(sra,"::1")!=sra)) { + ioa_addr ra; + if(make_ioa_addr((const u08bits*)sra,0,&ra)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"-X : Wrong address format: %s\n",sra); + } else if(ra.ss.sa_family == turn_params.external_ip->ss.sa_family) { + ioa_addr_add_mapping(turn_params.external_ip,&ra); + } + } + } + } + } + if(turn_params.turn_daemon) { #if !defined(TURN_HAS_DAEMON) pid_t pid = fork(); From 57fb77c4e46aa1b0f5d320afdf13c630eed9aa35 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 5 Dec 2014 07:53:55 +0000 Subject: [PATCH 360/805] minor fix --- src/server/ns_turn_server.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 949334ba..cef17b66 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4548,6 +4548,7 @@ static int read_client_connection(turn_turnserver *server, 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); } + return 0; } } } From 5050bea60063a48d4d39ed2ad739f4f53a62dceb Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 7 Dec 2014 13:42:05 +0000 Subject: [PATCH 361/805] docs fixes --- ChangeLog | 3 ++- README.turnserver | 11 ++++++----- examples/etc/turnserver.conf | 18 ++++++++++++------ man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 13 +++++++------ man/man1/turnutils.1 | 2 +- src/apps/relay/mainrelay.c | 3 ++- 7 files changed, 31 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index ea3f77aa..0bd06874 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,7 +2,8 @@ Version 4.3.1.3 'Tolomei': - Reliability fixes (Issue 141 from rfc5766-turn-server). - HTTP/HTTPS echo fixed. - - external address mapping fixes for Amazon EC2. + - External address mapping fixes for Amazon EC2. + - Minor docs improvements. 11/23/2014 Oleg Moskalenko Version 4.3.1.2 'Tolomei': diff --git a/README.turnserver b/README.turnserver index ce6cdd12..31c2b5de 100644 --- a/README.turnserver +++ b/README.turnserver @@ -356,13 +356,14 @@ Options with required values: is behind A NAT. By default, this value is empty, and no address mapping is used. --m, --relay-threads Number of relay threads to handle the established connections +-m, --relay-threads Number of the relay threads to handle the established connections (in addition to authentication thread and the listener thread). - If set to 0 then application runs relay process in a single thread, + If explicitly set to 0 then application runs relay process in a single thread, in the same thread with the listener process (the authentication thread will - still be a separate thread). In older systems (before Linux kernel 3.9), - the number of UDP threads is always one threads per network listening endpoint - - unless "-m 0" or "-m 1" is set. + still be a separate thread). If not set, then a default optimal algorithm + will be employed (OS-dependent). In the older Linux systems + (before Linux kernel 3.9), the number of UDP threads is always one threads + per network listening endpoint - unless "-m 0" or "-m 1" is set. --min-port Lower bound of the UDP port range for relay endpoints allocation. diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 4e1b8c45..5d35de87 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -125,15 +125,21 @@ #external-ip=60.70.80.92/172.17.19.102 -# Number of relay threads to handle the established connections +# Number of the relay threads to handle the established connections # (in addition to authentication thread and the listener thread). -# If set to 0 then application runs relay process in a single thread, -# in the same thread with the listener process (the authentication thread will -# still be a separate thread). +# If explicitly set to 0 then application runs relay process in a +# single thread, in the same thread with the listener process +# (the authentication thread will still be a separate thread). +# +# If this parameter is not set, then the default OS-dependent +# thread pattern algorithm will be employed. Usually the default +# algorithm is the most optimal, so you have to change this option +# only if you want to make some fine tweaks. # # In the older systems (Linux kernel before 3.9), -# the number of UDP threads is always one thread per network listening endpoint - -# including the auxiliary endpoints - unless 0 (zero) or 1 (one) value is set. +# the number of UDP threads is always one thread per network listening +# endpoint - including the auxiliary endpoints - unless 0 (zero) or +# 1 (one) value is set. # #relay-threads=0 diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 462f111d..d460331c 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "23 November 2014" "" "" +.TH TURN 1 "06 December 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index dff14c15..b12d631a 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "23 November 2014" "" "" +.TH TURN 1 "06 December 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -527,13 +527,14 @@ By default, this value is empty, and no address mapping is used. .TP .B \fB\-m\fP, \fB\-\-relay\-threads\fP -Number of relay threads to handle the established connections +Number of the relay threads to handle the established connections (in addition to authentication thread and the listener thread). -If set to 0 then application runs relay process in a single thread, +If explicitly set to 0 then application runs relay process in a single thread, in the same thread with the listener process (the authentication thread will -still be a separate thread). In older systems (before Linux kernel 3.9), -the number of UDP threads is always one threads per network listening endpoint \- -unless "\fB\-m\fP 0" or "\fB\-m\fP 1" is set. +still be a separate thread). If not set, then a default optimal algorithm +will be employed (OS\-dependent). In the older Linux systems +(before Linux kernel 3.9), the number of UDP threads is always one threads +per network listening endpoint \- unless "\fB\-m\fP 0" or "\fB\-m\fP 1" is set. .TP .B \fB\-\-min\-port\fP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index ac7083e0..ecd87d77 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "23 November 2014" "" "" +.TH TURN 1 "06 December 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index dfa6048a..5abf1bd8 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -398,7 +398,8 @@ static char Usage[] = "Usage: turnserver [options]\n" " --no-multicast-peers Disallow peers on well-known broadcast addresses (224.0.0.0 and above, and FFXX:*).\n" " -m, --relay-threads Number of relay threads to handle the established connections\n" " (in addition to authentication thread and the listener thread).\n" -" If set to 0 then application runs in single-threaded mode.\n" +" If explicitly set to 0 then application runs in single-threaded mode.\n" +" If not set then a default OS-dependent optimal algorithm will be employed.\n" " The default thread number is the number of CPUs.\n" " In older systems (pre-Linux 3.9) the number of UDP relay threads always equals\n" " the number of listening endpoints (unless -m 0 is set).\n" From b3bdfd24a8e7a5fb9514efa81f4ce9dbfa070933 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 7 Dec 2014 20:47:41 +0000 Subject: [PATCH 362/805] issue 141 --- src/client/ns_turn_msg.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index c2106aea..bff048b6 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -101,13 +101,11 @@ long turn_random(void) return ret; } -void turn_random32_size(u32bits *ar, size_t sz) +static void turn_random_tid_size(u32bits *ar) { - if(!RAND_bytes((unsigned char *)ar, sz<<2)) { - size_t i; - for(i=0;itsx_id); - turn_random32_size(w,3); + turn_random_tid_size(w); } } From a67a2b40b855411bcf4e56aeaadb984f49d11386 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 7 Dec 2014 20:49:04 +0000 Subject: [PATCH 363/805] issue 141 --- src/client/ns_turn_msg.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 09e29d01..52bdfadd 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -194,7 +194,6 @@ size_t get_hmackey_size(SHATYPE shatype); #define TURN_RANDOM_SIZE (sizeof(long)) long turn_random(void); -void turn_random32_size(u32bits *ar, size_t sz); int stun_produce_integrity_key_str(u08bits *uname, u08bits *realm, u08bits *upwd, hmackey_t key, SHATYPE shatype); int stun_calculate_hmac(const u08bits *buf, size_t len, const u08bits *key, size_t sz, u08bits *hmac, unsigned int *hmac_len, SHATYPE shatype); From 212a5fd6ec0100716d63b7cc824766bceca7ecd9 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 7 Dec 2014 21:07:42 +0000 Subject: [PATCH 364/805] issue 141 --- src/client/ns_turn_msg.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index bff048b6..7f7c1172 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -101,11 +101,14 @@ long turn_random(void) return ret; } -static void turn_random_tid_size(u32bits *ar) +static void turn_random_tid_size(void *id) { - size_t i; - for(i=0;i<3;++i) { - ar[i] = (u32bits)random(); + u32bits *ar=(u32bits*)id; + if(!RAND_pseudo_bytes((unsigned char *)ar,12)) { + size_t i; + for(i=0;i<3;++i) { + ar[i] = (u32bits)random(); + } } } @@ -952,8 +955,7 @@ void stun_tid_message_cpy(u08bits* buf, const stun_tid* id) { void stun_tid_generate(stun_tid* id) { if(id) { - u32bits *w=(u32bits*)(id->tsx_id); - turn_random_tid_size(w); + turn_random_tid_size(id->tsx_id); } } From b1aaef347aaee09410a791955474ef012d9d0483 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 9 Dec 2014 07:10:46 +0000 Subject: [PATCH 365/805] TODO updated --- TODO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO b/TODO index 92375d2a..05e71fc6 100644 --- a/TODO +++ b/TODO @@ -47,7 +47,7 @@ ================================================================== -Nope +1) EC curve new features in OpenSSL 1.0.2 ================================================================== From 786105a9b4bcf21ed111da753f5b4813903f3182 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 9 Dec 2014 09:29:27 +0000 Subject: [PATCH 366/805] DTLS v1.2 supported. --- ChangeLog | 4 ++ STATUS | 2 + TODO | 2 - rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +- src/apps/common/apputils.c | 8 +++ src/apps/relay/dtls_listener.c | 67 +++++++++++++++++++++++--- src/apps/relay/mainrelay.c | 14 ++++-- src/apps/relay/mainrelay.h | 3 ++ src/apps/relay/netengine.c | 18 +++++-- src/apps/relay/ns_ioalib_engine_impl.c | 9 +++- src/apps/relay/ns_ioalib_impl.h | 9 +++- src/apps/uclient/mainuclient.c | 5 ++ src/apps/uclient/startuclient.c | 2 + src/ns_turn_defs.h | 2 +- 15 files changed, 131 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0bd06874..041d5560 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +12/09/2014 Oleg Moskalenko +Version 4.3.2.1 'Tolomei': + - DTLS v1.2 supported (for OpenSSL 1.0.2+); + 11/29/2014 Oleg Moskalenko Version 4.3.1.3 'Tolomei': - Reliability fixes (Issue 141 from rfc5766-turn-server). diff --git a/STATUS b/STATUS index d908316a..3585fe1d 100644 --- a/STATUS +++ b/STATUS @@ -108,6 +108,8 @@ compatibility. 46) Third-party security mechanism (through oAuth) implemented. 47) SQLite support added as default database. + +48) DTLS1.2 supported. Things to be implemented in future (the development roadmap) are described in the TODO file. diff --git a/TODO b/TODO index 05e71fc6..6bd108ae 100644 --- a/TODO +++ b/TODO @@ -61,8 +61,6 @@ 3) Redirect draft. -4) DTLS 1.2 (when available). - ================================================================== ### VII. MISC FEATURES ### diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index e4c19573..67acef40 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.3.1.3 +TURNVERSION=4.3.2.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 6b76d9e6..995ba866 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.3.1.3 +Version: 4.3.2.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,6 +294,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Tue Dec 09 2014 Oleg Moskalenko + - Sync to 4.3.2.1 * Sat Nov 29 2014 Oleg Moskalenko - Sync to 4.3.1.3 * Mon Nov 23 2014 Oleg Moskalenko diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c index e76e3910..12cf7abf 100644 --- a/src/apps/common/apputils.c +++ b/src/apps/common/apputils.c @@ -864,6 +864,14 @@ static const char* turn_get_method(const SSL_METHOD *method, const char* mdefaul return "DTLSv1.0"; } else if(method == DTLSv1_client_method()) { return "DTLSv1.0"; + +#if defined(SSL_OP_NO_DTLSv1_2) + } else if(method == DTLSv1_2_server_method()) { + return "DTLSv1.2"; + } else if(method == DTLSv1_2_client_method()) { + return "DTLSv1.2"; +#endif + #endif } else { if(mdefault) diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index f6847ec3..2280298a 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -59,6 +59,9 @@ struct dtls_listener_relay_server_info { turn_turnserver *ts; int verbose; SSL_CTX *dtls_ctx; +#if defined(SSL_OP_NO_DTLSv1_2) + SSL_CTX *dtls_ctx_v1_2; +#endif struct event *udp_listen_ev; ioa_socket_handle udp_listen_s; ur_addr_map *children_ss; /* map of socket children on remote addr */ @@ -79,27 +82,28 @@ int is_dtls_handshake_message(const unsigned char* buf, int len); int is_dtls_data_message(const unsigned char* buf, int len); int is_dtls_alert_message(const unsigned char* buf, int len); int is_dtls_cipher_change_message(const unsigned char* buf, int len); +int get_dtls_version(const unsigned char* buf, int len); int is_dtls_message(const unsigned char* buf, int len); int is_dtls_handshake_message(const unsigned char* buf, int len) { - return (buf && len>3 && buf[0]==0x16 && buf[1]==0xfe && buf[2]==0xff); + return (buf && len>3 && buf[0]==0x16 && buf[1]==0xfe && ((buf[2]==0xff)||(buf[2]==0xfd))); } int is_dtls_data_message(const unsigned char* buf, int len) { - return (buf && len>3 && buf[0]==0x17 && buf[1]==0xfe && buf[2]==0xff); + return (buf && len>3 && buf[0]==0x17 && buf[1]==0xfe && ((buf[2]==0xff)||(buf[2]==0xfd))); } int is_dtls_alert_message(const unsigned char* buf, int len) { - return (buf && len>3 && buf[0]==0x15 && buf[1]==0xfe && buf[2]==0xff); + return (buf && len>3 && buf[0]==0x15 && buf[1]==0xfe && ((buf[2]==0xff)||(buf[2]==0xfd))); } int is_dtls_cipher_change_message(const unsigned char* buf, int len) { - return (buf && len>3 && buf[0]==0x14 && buf[1]==0xfe && buf[2]==0xff); + return (buf && len>3 && buf[0]==0x14 && buf[1]==0xfe && ((buf[2]==0xff)||(buf[2]==0xfd))); } int is_dtls_message(const unsigned char* buf, int len) { - if(buf && (len>3) && (buf[1])==0xfe && (buf[2]==0xff)) { + if(buf && (len>3) && (buf[1])==0xfe && ((buf[2]==0xff)||(buf[2]==0xfd))) { switch (buf[0]) { case 0x14: case 0x15: @@ -113,6 +117,13 @@ int is_dtls_message(const unsigned char* buf, int len) { return 0; } +/* 0 - 1.0, 1 - 1.2 */ +int get_dtls_version(const unsigned char* buf, int len) { + if(buf && (len>3) && (buf[2] == 0xfd)) + return 1; + return 0; +} + ///////////// utils ///////////////////// #if !defined(TURN_NO_DTLS) @@ -266,7 +277,18 @@ static ioa_socket_handle dtls_server_input_handler(dtls_listener_relay_server_ty timeout.tv_usec = 0; BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); - connecting_ssl = SSL_NEW(server->dtls_ctx); +#if defined(SSL_OP_NO_DTLSv1_2) + if(get_dtls_version(ioa_network_buffer_data(nbh), + (int)ioa_network_buffer_get_size(nbh)) == 1) { + connecting_ssl = SSL_NEW(server->dtls_ctx_v1_2); + } else { + connecting_ssl = SSL_NEW(server->dtls_ctx); + } +#else + { + connecting_ssl = SSL_NEW(server->dtls_ctx); + } +#endif SSL_set_accept_state(connecting_ssl); @@ -536,7 +558,18 @@ static int create_new_connected_udp_socket( timeout.tv_usec = 0; BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); - connecting_ssl = SSL_NEW(server->dtls_ctx); +#if defined(SSL_OP_NO_DTLSv1_2) + if(get_dtls_version(ioa_network_buffer_data(server->sm.m.sm.nd.nbh), + (int)ioa_network_buffer_get_size(server->sm.m.sm.nd.nbh)) == 1) { + connecting_ssl = SSL_NEW(server->dtls_ctx_v1_2); + } else { + connecting_ssl = SSL_NEW(server->dtls_ctx); + } +#else + { + connecting_ssl = SSL_NEW(server->dtls_ctx); + } +#endif SSL_set_accept_state(connecting_ssl); @@ -865,6 +898,9 @@ static int init_server(dtls_listener_relay_server_type* server, if(!server) return -1; server->dtls_ctx = e->dtls_ctx; +#if defined(SSL_OP_NO_DTLSv1_2) + server->dtls_ctx_v1_2 = e->dtls_ctx_v1_2; +#endif server->ts = ts; server->connect_cb = send_socket; @@ -896,6 +932,23 @@ static int init_server(dtls_listener_relay_server_type* server, #endif } +#if defined(SSL_OP_NO_DTLSv1_2) + if(server->dtls_ctx_v1_2) { + + #if defined(REQUEST_CLIENT_CERT) + /* If client has to authenticate, then */ + SSL_CTX_set_verify(server->dtls_ctx_v1_2, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, dtls_verify_callback); + #endif + + SSL_CTX_set_read_ahead(server->dtls_ctx_v1_2, 1); + + #if !defined(TURN_NO_DTLS) + SSL_CTX_set_cookie_generate_cb(server->dtls_ctx_v1_2, generate_cookie); + SSL_CTX_set_cookie_verify_cb(server->dtls_ctx_v1_2, verify_cookie); + #endif + } +#endif + return create_server_socket(server, report_creation); } diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 5abf1bd8..df316501 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -65,17 +65,17 @@ static int anon_credentials = 0; #define DEFAULT_GENERAL_RELAY_SERVERS_NUMBER (1) turn_params_t turn_params = { - NULL, NULL, - #if defined(SSL_TXT_TLSV1_1) NULL, #if defined(SSL_TXT_TLSV1_2) NULL, #endif #endif - NULL, +#if defined(SSL_OP_NO_DTLSv1_2) +NULL, +#endif DH_1066, "", DEFAULT_EC_CURVE_NAME, "", "turn_server_cert.pem","turn_server_pkey.pem", "", "", @@ -2546,7 +2546,15 @@ static void openssl_setup(void) 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 defined(SSL_OP_NO_DTLSv1_2) + 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); +#endif + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS cipher suite: %s\n",turn_params.cipher_list); + #endif } } diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index 0b684c95..06fbee72 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -188,6 +188,9 @@ typedef struct _turn_params_ { #endif SSL_CTX *dtls_ctx; +#if defined(SSL_OP_NO_DTLSv1_2) + SSL_CTX *dtls_ctx_v1_2; +#endif DH_KEY_SIZE dh_key_size; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 86ae4471..ca7073d2 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -947,7 +947,11 @@ static ioa_engine_handle create_new_listener_engine(void) turn_params.tls_ctx_v1_2, #endif #endif - turn_params.dtls_ctx); + turn_params.dtls_ctx +#if defined(SSL_OP_NO_DTLSv1_2) + ,turn_params.dtls_ctx_v1_2 +#endif + ); ioa_engine_set_rtcp_map(e, turn_params.listener.rtcpmap); return e; } @@ -997,7 +1001,11 @@ static void setup_listener(void) turn_params.tls_ctx_v1_2, #endif #endif - turn_params.dtls_ctx); + turn_params.dtls_ctx +#if defined(SSL_OP_NO_DTLSv1_2) + ,turn_params.dtls_ctx_v1_2 +#endif + ); turn_params.listener.rtcpmap = rtcp_map_create(turn_params.listener.ioa_eng); @@ -1565,7 +1573,11 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int turn_params.tls_ctx_v1_2, #endif #endif - turn_params.dtls_ctx); + turn_params.dtls_ctx +#if defined(SSL_OP_NO_DTLSv1_2) + ,turn_params.dtls_ctx_v1_2 +#endif + ); ioa_engine_set_rtcp_map(rs->ioa_eng, turn_params.listener.rtcpmap); } diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 8990a000..7385881c 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -440,7 +440,11 @@ void set_ssl_ctx(ioa_engine_handle e, SSL_CTX *tls_ctx_v1_2, #endif #endif - SSL_CTX *dtls_ctx) + SSL_CTX *dtls_ctx +#if defined(SSL_OP_NO_DTLSv1_2) + ,SSL_CTX *dtls_ctx_v1_2 +#endif +) { e->tls_ctx_ssl23 = tls_ctx_ssl23; e->tls_ctx_v1_0 = tls_ctx_v1_0; @@ -451,6 +455,9 @@ void set_ssl_ctx(ioa_engine_handle e, #endif #endif e->dtls_ctx = dtls_ctx; +#if defined(SSL_OP_NO_DTLSv1_2) + e->dtls_ctx_v1_2 = dtls_ctx_v1_2; +#endif } void ioa_engine_set_rtcp_map(ioa_engine_handle e, rtcp_map *rtcpmap) diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 998860a7..dbffaed5 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -150,6 +150,9 @@ struct _ioa_engine #endif #endif SSL_CTX *dtls_ctx; +#if defined(SSL_OP_NO_DTLSv1_2) + SSL_CTX *dtls_ctx_v1_2; +#endif turn_time_t jiffie; /* bandwidth check interval */ ioa_timer_handle timer_ev; s08bits cmsg[TURN_CMSG_SZ+1]; @@ -258,7 +261,11 @@ void set_ssl_ctx(ioa_engine_handle e, SSL_CTX *tls_ctx_v1_2, #endif #endif - SSL_CTX *dtls_ctx); + SSL_CTX *dtls_ctx +#if defined(SSL_OP_NO_DTLSv1_2) + ,SSL_CTX *dtls_ctx_v1_2 +#endif +); void ioa_engine_set_rtcp_map(ioa_engine_handle e, rtcp_map *rtcpmap); diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index ca7201ba..dbe41fdf 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -538,6 +538,11 @@ int main(int argc, char **argv) root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; +#if defined(SSL_OP_NO_DTLSv1_2) + root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_2_client_method()); + SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); + root_tls_ctx_num++; +#endif #endif } diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 6c0d366d..791d704a 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -79,7 +79,9 @@ static int get_allocate_address_family(ioa_addr *relay_addr) { static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr, int *try_again, int connect_cycle) { + int ctxtype = (int)(((unsigned long)random())%root_tls_ctx_num); + SSL *ssl; ssl = SSL_NEW(root_tls_ctx[ctxtype]); diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index bb136d3f..3a259ce2 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.3.1.3" +#define TURN_SERVER_VERSION "4.3.2.1" #define TURN_SERVER_VERSION_NAME "Tolomei" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 06389df97c297fab3689606d9d72aeefb057ab54 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 10 Dec 2014 09:01:15 +0000 Subject: [PATCH 367/805] ALPN support added --- ChangeLog | 3 +- README.turnserver | 19 +++++++-- TODO | 4 +- examples/etc/turnserver.conf | 2 +- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 16 ++++++-- man/man1/turnutils.1 | 2 +- src/apps/relay/mainrelay.c | 73 ++++++++++++++++++++++++++++++++- src/apps/uclient/startuclient.c | 9 ++++ src/ns_turn_defs.h | 10 ++++- 10 files changed, 122 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 041d5560..6dfb8b5c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 12/09/2014 Oleg Moskalenko Version 4.3.2.1 'Tolomei': - - DTLS v1.2 supported (for OpenSSL 1.0.2+); + - DTLS v1.2 supported (when compiled with OpenSSL 1.0.2+ ); + - STUN/TURN ALPN supported (when compiled with OpenSSL 1.0.2+ ); 11/29/2014 Oleg Moskalenko Version 4.3.1.3 'Tolomei': diff --git a/README.turnserver b/README.turnserver index 31c2b5de..06fe32d0 100644 --- a/README.turnserver +++ b/README.turnserver @@ -195,11 +195,11 @@ Flags: --no-sslv3 Do not allow SSLv3 protocol. ---no-tlsv1 Do not allow TLSv1 protocol. +--no-tlsv1 Do not allow TLSv1/DTLSv1 protocol. --no-tlsv1_1 Do not allow TLSv1.1 protocol. ---no-tlsv1_2 Do not allow TLSv1.2 protocol. +--no-tlsv1_2 Do not allow TLSv1.2/DTLSv1.2 protocol. --no-udp Do not start UDP client listeners. @@ -775,7 +775,18 @@ it will set the users for you (see the turnadmin manuals). If you are using SQLi turnserver or turnadmin will initialize the empty database, for you, when started. The TURN server installation process creates an empty initialized SQLite database in the default location (/var/db/turndb or /usr/local/var/db/turndb or /var/lib/turn/turndb, depending on the system). - + +================================= + +ALPN + +The server supports ALPNs "stun.turn" and "stun.nat-discovery", when +compiled with OpenSSL 1.0.2 or newer. If the server receives a TLS/DTLS +ClientHello message that contains one or both of those ALPNs, then the +server chooses the first stun.* label and sends it back (in the ServerHello) +in the ALPN extention field. If no stun.* label is found, then the server +does not include the ALPN information into the ServerHello. + ================================= LIBRARIES @@ -786,7 +797,7 @@ The C++ wrapper for the messaging functionality is located in TurnMsgLib.h heade An example of C++ code can be found in stunclient.c file. ================================= - + DOCS After installation, run the command: diff --git a/TODO b/TODO index 6bd108ae..49ef28c2 100644 --- a/TODO +++ b/TODO @@ -57,9 +57,7 @@ 1) For extra difficult NAT/FWs, consider implementing Websockets. -2) ALPN with TLS and DTLS (when OpenSSL 1.0.2 is available). - -3) Redirect draft. +2) Redirect draft. ================================================================== diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 5d35de87..efd96225 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -620,7 +620,7 @@ # #ne=[1|2|3] -# Do not allow an SSL/TLS version of protocol +# Do not allow an SSL/TLS/DTLS version of protocol # #no-sslv2 #no-sslv3 diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index d460331c..6b1d34f0 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "06 December 2014" "" "" +.TH TURN 1 "10 December 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index b12d631a..5882842a 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "06 December 2014" "" "" +.TH TURN 1 "10 December 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -291,7 +291,7 @@ Do not allow SSLv3 protocol. .TP .B \fB\-\-no\-tlsv1\fP -Do not allow TLSv1 protocol. +Do not allow TLSv1/DTLSv1 protocol. .TP .B \fB\-\-no\-tlsv1_1\fP @@ -299,7 +299,7 @@ Do not allow TLSv1.1 protocol. .TP .B \fB\-\-no\-tlsv1_2\fP -Do not allow TLSv1.2 protocol. +Do not allow TLSv1.2/DTLSv1.2 protocol. .TP .B \fB\-\-no\-udp\fP @@ -1032,6 +1032,16 @@ TURN server installation process creates an empty initialized SQLite database in location (/var/db/turndb or /usr/local/var/db/turndb or /var/lib/turn/turndb, depending on the system). .PP ================================= +.SH ALPN + +The server supports ALPNs "stun.turn" and "stun.nat\-discovery", when +compiled with OpenSSL 1.0.2 or newer. If the server receives a TLS/DTLS +ClientHello message that contains one or both of those ALPNs, then the +server chooses the first stun.* label and sends it back (in the ServerHello) +in the ALPN extention field. If no stun.* label is found, then the server +does not include the ALPN information into the ServerHello. +.PP +================================= .SH LIBRARIES In the lib/ sub\-directory the build process will create TURN client messaging library. diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index ecd87d77..61851d7c 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "06 December 2014" "" "" +.TH TURN 1 "10 December 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index df316501..bc4ff64e 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -515,9 +515,9 @@ static char Usage[] = "Usage: turnserver [options]\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 protocol.\n" +" --no-tlsv1 Do not allow TLSv1/DTLSv1 protocol.\n" " --no-tlsv1_1 Do not allow TLSv1.1 protocol.\n" -" --no-tlsv1_2 Do not allow TLSv1.2 protocol.\n" +" --no-tlsv1_2 Do not allow TLSv1.2/DTLSv1.2 protocol.\n" " --no-udp Do not start UDP client listeners.\n" " --no-tcp Do not start TCP client listeners.\n" " --no-tls Do not start TLS client listeners.\n" @@ -2339,8 +2339,59 @@ static int pem_password_func(char *buf, int size, int rwflag, void *password) return (strlen(buf)); } +#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION + +static int ServerALPNCallback(SSL *s, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg) { + + UNUSED_ARG(s); + UNUSED_ARG(arg); + + unsigned char sa_len = (unsigned char)strlen(STUN_ALPN); + unsigned char ta_len = (unsigned char)strlen(TURN_ALPN); + unsigned char ha_len = (unsigned char)strlen(HTTP_ALPN); + + int found_http = 0; + + const unsigned char *ptr = in; + while(ptr < (in+inlen)) { + unsigned char current_len = *ptr; + if(ptr+1+current_len > in+inlen) + break; + if((current_len == sa_len) && (memcmp(ptr+1,STUN_ALPN,sa_len)==0)) { + *out = ptr+1; + *outlen = sa_len; + return SSL_TLSEXT_ERR_OK; + } + if((current_len == ta_len) && (memcmp(ptr+1,TURN_ALPN,ta_len)==0)) { + *out = ptr+1; + *outlen = ta_len; + return SSL_TLSEXT_ERR_OK; + } + if((current_len == ha_len) && (memcmp(ptr+1,HTTP_ALPN,ha_len)==0)) { + found_http = 1; + } + ptr += 1 + current_len; + } + + if(found_http) + return SSL_TLSEXT_ERR_NOACK; + + return SSL_TLSEXT_ERR_NOACK; //??? +} + +#endif + static void set_ctx(SSL_CTX* ctx, const char *protocol) { +#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION + SSL_CTX_set_alpn_select_cb(ctx, ServerALPNCallback, NULL); +#endif + SSL_CTX_set_default_passwd_cb_userdata(ctx, turn_params.tls_password); SSL_CTX_set_default_passwd_cb(ctx, pem_password_func); @@ -2437,6 +2488,14 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) dh = get_dh1066(); } + /* + if(!dh) { + dh = DH_new(); + DH_generate_parameters_ex(dh, 32, DH_GENERATOR_2, 0); + DH_generate_key(dh); + } + */ + if(!dh) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot allocate DH suite\n",__FUNCTION__); } else { @@ -2469,6 +2528,16 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) op |= SSL_OP_NO_TLSv1_2; #endif +#if defined(SSL_OP_NO_DTLSv1) + if(turn_params.no_tlsv1) + op |= SSL_OP_NO_DTLSv1; +#endif + +#if defined(SSL_OP_NO_DTLSv1_2) + if(turn_params.no_tlsv1_2) + op |= SSL_OP_NO_DTLSv1_2; +#endif + #if defined(SSL_OP_CIPHER_SERVER_PREFERENCE) op |= SSL_OP_CIPHER_SERVER_PREFERENCE; #endif diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 791d704a..40dcd7fa 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -50,6 +50,11 @@ static uint64_t current_reservation_token = 0; static int allocate_rtcp = 0; static const int never_allocate_rtcp = 0; +#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION +static const unsigned char kALPNProtos[] = "\x09stun.turn\x12stun.nat-discovery"; +static const size_t kALPNProtosLen = sizeof(kALPNProtos) - 1; +#endif + ///////////////////////////////////////// int rare_event(void) @@ -86,6 +91,10 @@ static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr, int *try_again ssl = SSL_NEW(root_tls_ctx[ctxtype]); +#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION + SSL_set_alpn_protos(ssl, kALPNProtos, kALPNProtosLen); +#endif + if(use_tcp) { SSL_set_fd(ssl, fd); } else { diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 3a259ce2..8ad2eaed 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -60,8 +60,6 @@ extern "C" { #endif -/////////////////////////////////////////// - /* NS types: */ #define s08bits char @@ -218,6 +216,14 @@ typedef u32bits turn_time_t; #define DELETE_TURN_CHANNEL_KERNEL(handler) #endif +/* ALPN */ + +#define OPENSSL_FIRST_ALPN_VERSION (0x10002003L) + +#define STUN_ALPN "stun.nat-discovery" +#define TURN_ALPN "stun.turn" +#define HTTP_ALPN "http/1.1" + //////////////////////////////////////////////////////// #ifdef __cplusplus From c810a2332eba585a8215a7d09bb5b9c7434e5a79 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 10 Dec 2014 16:55:21 +0000 Subject: [PATCH 368/805] tls code cleaning --- src/apps/common/apputils.c | 23 +++++++++++++---------- src/apps/relay/dtls_listener.c | 1 - src/apps/relay/ns_ioalib_engine_impl.c | 15 +++------------ src/apps/relay/ns_ioalib_impl.h | 1 - 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c index 12cf7abf..0a0c9eec 100644 --- a/src/apps/common/apputils.c +++ b/src/apps/common/apputils.c @@ -861,13 +861,13 @@ static const char* turn_get_method(const SSL_METHOD *method, const char* mdefaul #endif #if !defined(TURN_NO_DTLS) } else if(method == DTLSv1_server_method()) { - return "DTLSv1.0"; + return "DTLSv1.0"; } else if(method == DTLSv1_client_method()) { return "DTLSv1.0"; #if defined(SSL_OP_NO_DTLSv1_2) } else if(method == DTLSv1_2_server_method()) { - return "DTLSv1.2"; + return "DTLSv1.2"; } else if(method == DTLSv1_2_client_method()) { return "DTLSv1.2"; #endif @@ -880,20 +880,23 @@ static const char* turn_get_method(const SSL_METHOD *method, const char* mdefaul } } } - } const char* turn_get_ssl_method(SSL *ssl, const char* mdefault) { - if(!ssl) - return mdefault; - else { + const char* ret = "unknown"; + if(!ssl) { + ret = mdefault; + } else { const SSL_METHOD *method = SSL_get_ssl_method(ssl); - if(!method) - return mdefault; - else - return turn_get_method(method, mdefault); + if(!method) { + ret = mdefault; + } else { + ret = turn_get_method(method, mdefault); + } } + + return ret; } //////////// EVENT BASE /////////////// diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index 2280298a..2f022243 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -599,7 +599,6 @@ static int create_new_connected_udp_socket( server->sm.m.sm.nd.nbh = NULL; ret->st = DTLS_SOCKET; - STRCPY(ret->orig_ctx_type,"DTLSv1.0"); } #endif diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 7385881c..1ae54d0f 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1561,8 +1561,6 @@ ioa_socket_handle create_ioa_socket_from_ssl(ioa_engine_handle e, ioa_socket_han if(ret) { set_socket_ssl(ret,ssl); - if(st == DTLS_SOCKET) - STRCPY(ret->orig_ctx_type,"DTLSv1.0"); } return ret; @@ -1761,8 +1759,6 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s) addr_cpy(&(ret->local_addr),&(s->local_addr)); ret->connected = s->connected; addr_cpy(&(ret->remote_addr),&(s->remote_addr)); - - STRCPY(ret->orig_ctx_type, s->orig_ctx_type); delete_socket_from_map(s); delete_socket_from_parent(s); @@ -2359,7 +2355,6 @@ static int socket_input_worker(ioa_socket_handle s) case TURN_TLS_v1_2: if(s->e->tls_ctx_v1_2) { set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_2)); - STRCPY(s->orig_ctx_type,"TLSv1.2"); } break; #endif @@ -2367,20 +2362,17 @@ static int socket_input_worker(ioa_socket_handle s) case TURN_TLS_v1_1: if(s->e->tls_ctx_v1_1) { set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_1)); - STRCPY(s->orig_ctx_type,"TLSv1.1"); } break; #endif case TURN_TLS_v1_0: if(s->e->tls_ctx_v1_0) { set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_0)); - STRCPY(s->orig_ctx_type,"TLSv1.0"); } break; default: if(s->e->tls_ctx_ssl23) { set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_ssl23)); - STRCPY(s->orig_ctx_type,"SSLv23"); } else { s->tobeclosed = 1; return 0; @@ -3252,7 +3244,6 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in if(!(s->ssl)) { //??? how we can get to this point ??? set_socket_ssl(s,SSL_NEW(e->tls_ctx_ssl23)); - STRCPY(s->orig_ctx_type,"SSLv23"); s->bev = bufferevent_openssl_socket_new(s->e->event_base, s->fd, s->ssl, @@ -3467,7 +3458,7 @@ const char* get_ioa_socket_cipher(ioa_socket_handle s) const char* get_ioa_socket_ssl_method(ioa_socket_handle s) { if(s && s->ssl) { - return turn_get_ssl_method(s->ssl, s->orig_ctx_type); + return turn_get_ssl_method(s->ssl, "UNKNOWN"); } return "no SSL"; } @@ -3485,8 +3476,8 @@ void turn_report_allocation_set(void *a, turn_time_t lifetime, int refresh) ioa_engine_handle e = turn_server_get_engine(server); if(e && e->verbose && ss->client_socket) { if(ss->client_socket->ssl) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: %s, realm=<%s>, username=<%s>, lifetime=%lu, cipher=%s, method=%s (%s)\n", (unsigned long long)ss->id, status, (char*)ss->realm_options.name, (char*)ss->username, (unsigned long)lifetime, SSL_get_cipher(ss->client_socket->ssl), - turn_get_ssl_method(ss->client_socket->ssl, ss->client_socket->orig_ctx_type),ss->client_socket->orig_ctx_type); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: %s, realm=<%s>, username=<%s>, lifetime=%lu, cipher=%s, method=%s\n", (unsigned long long)ss->id, status, (char*)ss->realm_options.name, (char*)ss->username, (unsigned long)lifetime, SSL_get_cipher(ss->client_socket->ssl), + turn_get_ssl_method(ss->client_socket->ssl, "UNKNOWN")); } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: %s, realm=<%s>, username=<%s>, lifetime=%lu\n", (unsigned long long)ss->id, status, (char*)ss->realm_options.name, (char*)ss->username, (unsigned long)lifetime); } diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index dbffaed5..c17fffd8 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -183,7 +183,6 @@ struct _ioa_socket SSL* ssl; u32bits ssl_renegs; int in_write; - char orig_ctx_type[16]; int bound; int local_addr_known; ioa_addr local_addr; From 65dc4832086ba62b5118b2c7aa914688599ab583 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 11 Dec 2014 08:19:29 +0000 Subject: [PATCH 369/805] tls code cleaning --- src/apps/common/apputils.c | 15 ++++---- src/apps/common/apputils.h | 53 +++++++++++++++++++++++++- src/apps/relay/dtls_listener.c | 22 ++++++----- src/apps/relay/mainrelay.c | 42 ++++++++++---------- src/apps/relay/mainrelay.h | 8 ++-- src/apps/relay/netengine.c | 24 +++++++----- src/apps/relay/ns_ioalib_engine_impl.c | 37 ++++++++++-------- src/apps/relay/ns_ioalib_impl.h | 16 +++++--- src/apps/uclient/mainuclient.c | 8 ++-- src/apps/uclient/startuclient.c | 6 +-- src/ns_turn_defs.h | 8 ---- 11 files changed, 151 insertions(+), 88 deletions(-) diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c index 0a0c9eec..aa4a4f39 100644 --- a/src/apps/common/apputils.c +++ b/src/apps/common/apputils.c @@ -349,7 +349,7 @@ int set_socket_df(evutil_socket_t fd, int family, int value) static int get_mtu_from_ssl(SSL* ssl) { int ret = SOSO_MTU; -#if !defined(TURN_NO_DTLS) +#if DTLSv1_SUPPORTED if(ssl) ret = BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); #else @@ -395,7 +395,7 @@ int decrease_mtu(SSL* ssl, int mtu, int verbose) if (verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "1. mtu to use: %d\n", mtu); -#if !defined(TURN_NO_DTLS) +#if DTLSv1_SUPPORTED SSL_set_mtu(ssl,mtu); BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_SET_MTU, mtu, NULL); #endif @@ -416,7 +416,7 @@ int set_mtu_df(SSL* ssl, evutil_socket_t fd, int family, int mtu, int df_value, set_query_mtu(ssl); if(verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"3. mtu to use: %d\n",mtu); -#if !defined(TURN_NO_DTLS) +#if DTLSv1_SUPPORTED SSL_set_mtu(ssl,mtu); @@ -847,25 +847,26 @@ static const char* turn_get_method(const SSL_METHOD *method, const char* mdefaul return "TLSv1.0"; } else if(method == TLSv1_client_method()) { return "TLSv1.0"; -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED } else if(method == TLSv1_1_server_method()) { return "TLSv1.1"; } else if(method == TLSv1_1_client_method()) { return "TLSv1.1"; -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED } else if(method == TLSv1_2_server_method()) { return "TLSv1.2"; } else if(method == TLSv1_2_client_method()) { return "TLSv1.2"; #endif #endif -#if !defined(TURN_NO_DTLS) +#if DTLSv1_SUPPORTED + } else if(method == DTLSv1_server_method()) { return "DTLSv1.0"; } else if(method == DTLSv1_client_method()) { return "DTLSv1.0"; -#if defined(SSL_OP_NO_DTLSv1_2) +#if DTLSv1_2_SUPPORTED } else if(method == DTLSv1_2_server_method()) { return "DTLSv1.2"; } else if(method == DTLSv1_2_client_method()) { diff --git a/src/apps/common/apputils.h b/src/apps/common/apputils.h index 0868d6e9..37d24001 100644 --- a/src/apps/common/apputils.h +++ b/src/apps/common/apputils.h @@ -53,15 +53,64 @@ extern "C" { extern int IS_TURN_SERVER; +/* ALPN */ + +#define OPENSSL_FIRST_ALPN_VERSION (0x10002003L) + +#define STUN_ALPN "stun.nat-discovery" +#define TURN_ALPN "stun.turn" +#define HTTP_ALPN "http/1.1" + +#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION +#define ALPN_SUPPORTED 1 +#else +#define ALPN_SUPPORTED 0 +#endif + +/* TLS */ + +#if defined(TURN_NO_TLS) +#define TLS_SUPPORTED 0 +#define TLSv1_1_SUPPORTED 0 +#define TLSv1_2_SUPPORTED 0 +#else +#define TLS_SUPPORTED 1 +#if defined(SSL_TXT_TLSV1_1) +#define TLSv1_1_SUPPORTED 1 +#else +#define TLSv1_1_SUPPORTED 0 +#endif + +#if defined(SSL_TXT_TLSV1_2) +#define TLSv1_2_SUPPORTED 1 +#else +#define TLSv1_2_SUPPORTED 0 +#endif +#endif + +#define OPENSSL_FIRST_DTLSv1_2_VERSION (0x10002003L) + +#if defined(TURN_NO_DTLS) +#define DTLSv1_SUPPORTED 0 +#define DTLSv1_2_SUPPORTED 0 +#else +#define DTLSv1_SUPPORTED 1 +#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_DTLSv1_2_VERSION +#define DTLSv1_2_SUPPORTED 1 +#else +#define DTLSv1_2_SUPPORTED 0 +#endif +#endif + /////////// SSL ////////////////////////// enum _TURN_TLS_TYPE { TURN_TLS_NO=0, TURN_TLS_SSL23, TURN_TLS_v1_0, -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED TURN_TLS_v1_1, -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED TURN_TLS_v1_2, #endif #endif diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index 2f022243..f45e4bbf 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -58,9 +58,11 @@ struct dtls_listener_relay_server_info { ioa_engine_handle e; turn_turnserver *ts; int verbose; +#if DTLSv1_SUPPORTED SSL_CTX *dtls_ctx; -#if defined(SSL_OP_NO_DTLSv1_2) +#if DTLSv1_2_SUPPORTED SSL_CTX *dtls_ctx_v1_2; +#endif #endif struct event *udp_listen_ev; ioa_socket_handle udp_listen_s; @@ -126,7 +128,7 @@ int get_dtls_version(const unsigned char* buf, int len) { ///////////// utils ///////////////////// -#if !defined(TURN_NO_DTLS) +#if DTLSv1_SUPPORTED static void calculate_cookie(SSL* ssl, unsigned char *cookie_secret, unsigned int cookie_length) { long rv=(long)ssl; @@ -277,7 +279,7 @@ static ioa_socket_handle dtls_server_input_handler(dtls_listener_relay_server_ty timeout.tv_usec = 0; BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); -#if defined(SSL_OP_NO_DTLSv1_2) +#if DTLSv1_2_SUPPORTED if(get_dtls_version(ioa_network_buffer_data(nbh), (int)ioa_network_buffer_get_size(nbh)) == 1) { connecting_ssl = SSL_NEW(server->dtls_ctx_v1_2); @@ -426,7 +428,7 @@ static int handle_udp_packet(dtls_listener_relay_server_type *server, chs = NULL; -#if !defined(TURN_NO_DTLS) +#if DTLSv1_SUPPORTED if (!turn_params.no_dtls && is_dtls_handshake_message(ioa_network_buffer_data(sm->m.sm.nd.nbh), (int)ioa_network_buffer_get_size(sm->m.sm.nd.nbh))) { @@ -535,7 +537,7 @@ static int create_new_connected_udp_socket( ret->current_tos = s->current_tos; ret->default_tos = s->default_tos; -#if !defined(TURN_NO_DTLS) +#if DTLSv1_SUPPORTED if (!turn_params.no_dtls && is_dtls_handshake_message( ioa_network_buffer_data(server->sm.m.sm.nd.nbh), @@ -558,7 +560,7 @@ static int create_new_connected_udp_socket( timeout.tv_usec = 0; BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); -#if defined(SSL_OP_NO_DTLSv1_2) +#if DTLSv1_2_SUPPORTED if(get_dtls_version(ioa_network_buffer_data(server->sm.m.sm.nd.nbh), (int)ioa_network_buffer_get_size(server->sm.m.sm.nd.nbh)) == 1) { connecting_ssl = SSL_NEW(server->dtls_ctx_v1_2); @@ -897,7 +899,7 @@ static int init_server(dtls_listener_relay_server_type* server, if(!server) return -1; server->dtls_ctx = e->dtls_ctx; -#if defined(SSL_OP_NO_DTLSv1_2) +#if DTLSv1_2_SUPPORTED server->dtls_ctx_v1_2 = e->dtls_ctx_v1_2; #endif server->ts = ts; @@ -925,13 +927,13 @@ static int init_server(dtls_listener_relay_server_type* server, SSL_CTX_set_read_ahead(server->dtls_ctx, 1); -#if !defined(TURN_NO_DTLS) +#if DTLSv1_SUPPORTED SSL_CTX_set_cookie_generate_cb(server->dtls_ctx, generate_cookie); SSL_CTX_set_cookie_verify_cb(server->dtls_ctx, verify_cookie); #endif } -#if defined(SSL_OP_NO_DTLSv1_2) +#if DTLSv1_2_SUPPORTED if(server->dtls_ctx_v1_2) { #if defined(REQUEST_CLIENT_CERT) @@ -941,7 +943,7 @@ static int init_server(dtls_listener_relay_server_type* server, SSL_CTX_set_read_ahead(server->dtls_ctx_v1_2, 1); - #if !defined(TURN_NO_DTLS) + #if DTLSv1_SUPPORTED SSL_CTX_set_cookie_generate_cb(server->dtls_ctx_v1_2, generate_cookie); SSL_CTX_set_cookie_verify_cb(server->dtls_ctx_v1_2, verify_cookie); #endif diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index bc4ff64e..ac95e8ee 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -66,27 +66,29 @@ static int anon_credentials = 0; turn_params_t turn_params = { NULL, NULL, -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED NULL, -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED NULL, #endif #endif +#if DTLSv1_SUPPORTED NULL, -#if defined(SSL_OP_NO_DTLSv1_2) +#endif +#if DTLSv1_2_SUPPORTED NULL, #endif DH_1066, "", DEFAULT_EC_CURVE_NAME, "", "turn_server_cert.pem","turn_server_pkey.pem", "", "", 0,0,0,0,0, -#if defined(TURN_NO_TLS) +#if !TLS_SUPPORTED 1, #else 0, #endif -#if defined(TURN_NO_DTLS) +#if !DTLSv1_SUPPORTED 1, #else 0, @@ -1219,14 +1221,14 @@ static void set_option(int c, char *value) turn_params.no_tcp_relay = get_bool_value(value); break; case NO_TLS_OPT: -#if defined(TURN_NO_TLS) +#if !TLS_SUPPORTED turn_params.no_tls = 1; #else turn_params.no_tls = get_bool_value(value); #endif break; case NO_DTLS_OPT: -#if !defined(TURN_NO_DTLS) +#if DTLSv1_SUPPORTED turn_params.no_dtls = get_bool_value(value); #else turn_params.no_dtls = 1; @@ -1610,13 +1612,13 @@ static void print_features(unsigned long mfn) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\n\n==== Show him the instruments, Practical Frost: ====\n\n"); -#if defined(TURN_NO_TLS) +#if !TLS_SUPPORTED TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS is not supported\n"); #else TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS supported\n"); #endif -#if defined(TURN_NO_DTLS) +#if !DTLSv1_SUPPORTED TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS is not supported\n"); #else TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS supported\n"); @@ -1796,11 +1798,11 @@ int main(int argc, char **argv) optind = 0; -#if defined(TURN_NO_TLS) +#if !TLS_SUPPORTED turn_params.no_tls = 1; #endif -#if defined(TURN_NO_DTLS) +#if !DTLSv1_SUPPORTED turn_params.no_dtls = 1; #endif @@ -2339,7 +2341,7 @@ static int pem_password_func(char *buf, int size, int rwflag, void *password) return (strlen(buf)); } -#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION +#if ALPN_SUPPORTED static int ServerALPNCallback(SSL *s, const unsigned char **out, @@ -2388,7 +2390,7 @@ static int ServerALPNCallback(SSL *s, static void set_ctx(SSL_CTX* ctx, const char *protocol) { -#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION +#if ALPN_SUPPORTED SSL_CTX_set_alpn_select_cb(ctx, ServerALPNCallback, NULL); #endif @@ -2528,12 +2530,12 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) op |= SSL_OP_NO_TLSv1_2; #endif -#if defined(SSL_OP_NO_DTLSv1) +#if defined(SSL_OP_NO_DTLSv1) && DTLSv1_SUPPORTED if(turn_params.no_tlsv1) op |= SSL_OP_NO_DTLSv1; #endif -#if defined(SSL_OP_NO_DTLSv1_2) +#if defined(SSL_OP_NO_DTLSv1_2) && DTLSv1_2_SUPPORTED if(turn_params.no_tlsv1_2) op |= SSL_OP_NO_DTLSv1_2; #endif @@ -2560,7 +2562,7 @@ static void openssl_setup(void) SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); -#if defined(TURN_NO_TLS) +#if !TLS_SUPPORTED if(!turn_params.no_tls) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "WARNING: TLS is not supported\n"); turn_params.no_tls = 1; @@ -2590,12 +2592,12 @@ static void openssl_setup(void) turn_params.tls_ctx_v1_0 = SSL_CTX_new(TLSv1_server_method()); set_ctx(turn_params.tls_ctx_v1_0,"TLS1.0"); } -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED if(!turn_params.no_tlsv1_1) { turn_params.tls_ctx_v1_1 = SSL_CTX_new(TLSv1_1_server_method()); set_ctx(turn_params.tls_ctx_v1_1,"TLS1.1"); } -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED if(!turn_params.no_tlsv1_2) { turn_params.tls_ctx_v1_2 = SSL_CTX_new(TLSv1_2_server_method()); set_ctx(turn_params.tls_ctx_v1_2,"TLS1.2"); @@ -2606,7 +2608,7 @@ static void openssl_setup(void) } if(!turn_params.no_dtls) { -#if defined(TURN_NO_DTLS) +#if !DTLSv1_SUPPORTED TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "ERROR: DTLS is not supported.\n"); #else if(OPENSSL_VERSION_NUMBER < 0x10000000L) { @@ -2616,7 +2618,7 @@ static void openssl_setup(void) set_ctx(turn_params.dtls_ctx,"DTLS"); SSL_CTX_set_read_ahead(turn_params.dtls_ctx, 1); -#if defined(SSL_OP_NO_DTLSv1_2) +#if DTLSv1_2_SUPPORTED 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); diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index 06fbee72..edf4e823 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -180,15 +180,17 @@ typedef struct _turn_params_ { SSL_CTX *tls_ctx_v1_0; -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED SSL_CTX *tls_ctx_v1_1; -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED SSL_CTX *tls_ctx_v1_2; #endif #endif +#if DTLSv1_SUPPORTED SSL_CTX *dtls_ctx; -#if defined(SSL_OP_NO_DTLSv1_2) +#endif +#if DTLSv1_2_SUPPORTED SSL_CTX *dtls_ctx_v1_2; #endif diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index ca7073d2..02880373 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -941,14 +941,16 @@ static ioa_engine_handle create_new_listener_engine(void) #endif ); set_ssl_ctx(e, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0, -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED turn_params.tls_ctx_v1_1, -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED turn_params.tls_ctx_v1_2, #endif #endif +#if DTLSv1_SUPPORTED turn_params.dtls_ctx -#if defined(SSL_OP_NO_DTLSv1_2) +#endif +#if DTLSv1_2_SUPPORTED ,turn_params.dtls_ctx_v1_2 #endif ); @@ -995,14 +997,16 @@ static void setup_listener(void) exit(-1); set_ssl_ctx(turn_params.listener.ioa_eng, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0, -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED turn_params.tls_ctx_v1_1, -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED turn_params.tls_ctx_v1_2, #endif #endif +#if DTLSv1_SUPPORTED turn_params.dtls_ctx -#if defined(SSL_OP_NO_DTLSv1_2) +#endif +#if DTLSv1_2_SUPPORTED ,turn_params.dtls_ctx_v1_2 #endif ); @@ -1567,14 +1571,16 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int #endif ); set_ssl_ctx(rs->ioa_eng, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0, -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED turn_params.tls_ctx_v1_1, -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED turn_params.tls_ctx_v1_2, #endif #endif +#if DTLSv1_SUPPORTED turn_params.dtls_ctx -#if defined(SSL_OP_NO_DTLSv1_2) +#endif +#if DTLSv1_2_SUPPORTED ,turn_params.dtls_ctx_v1_2 #endif ); diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 1ae54d0f..5fcc8b86 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -38,7 +38,7 @@ #include "ns_ioalib_impl.h" -#if !defined(TURN_NO_TLS) +#if TLS_SUPPORTED #include #endif @@ -434,28 +434,32 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm, void set_ssl_ctx(ioa_engine_handle e, SSL_CTX *tls_ctx_ssl23, SSL_CTX *tls_ctx_v1_0, -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED SSL_CTX *tls_ctx_v1_1, -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED SSL_CTX *tls_ctx_v1_2, #endif #endif +#if DTLSv1_SUPPORTED SSL_CTX *dtls_ctx -#if defined(SSL_OP_NO_DTLSv1_2) +#endif +#if DTLSv1_2_SUPPORTED ,SSL_CTX *dtls_ctx_v1_2 #endif ) { e->tls_ctx_ssl23 = tls_ctx_ssl23; e->tls_ctx_v1_0 = tls_ctx_v1_0; -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED e->tls_ctx_v1_1 = tls_ctx_v1_1; -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED e->tls_ctx_v1_2 = tls_ctx_v1_2; #endif #endif +#if DTLSv1_SUPPORTED e->dtls_ctx = dtls_ctx; -#if defined(SSL_OP_NO_DTLSv1_2) +#endif +#if DTLSv1_2_SUPPORTED e->dtls_ctx_v1_2 = dtls_ctx_v1_2; #endif } @@ -2242,7 +2246,8 @@ int udp_recvfrom(evutil_socket_t fd, ioa_addr* orig_addr, const ioa_addr *like_a return len; } -#if !defined(TURN_NO_TLS) +#if TLS_SUPPORTED + static TURN_TLS_TYPE check_tentative_tls(ioa_socket_raw fd) { TURN_TLS_TYPE ret = TURN_TLS_NO; @@ -2321,7 +2326,7 @@ static int socket_input_worker(ioa_socket_handle s) } if(s->st == TLS_SOCKET) { -#if !defined(TURN_NO_TLS) +#if TLS_SUPPORTED SSL *ctx = bufferevent_openssl_get_ssl(s->bev); if(!ctx || SSL_get_shutdown(ctx)) { s->tobeclosed = 1; @@ -2340,7 +2345,7 @@ static int socket_input_worker(ioa_socket_handle s) if(s->st == TENTATIVE_TCP_SOCKET) { EVENT_DEL(s->read_event); -#if !defined(TURN_NO_TLS) +#if TLS_SUPPORTED TURN_TLS_TYPE tls_type = check_tentative_tls(s->fd); if(tls_type) { s->st = TLS_SOCKET; @@ -2351,14 +2356,14 @@ 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); } switch(tls_type) { -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED case TURN_TLS_v1_2: if(s->e->tls_ctx_v1_2) { set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_2)); } break; #endif -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED case TURN_TLS_v1_1: if(s->e->tls_ctx_v1_1) { set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_1)); @@ -2391,7 +2396,7 @@ static int socket_input_worker(ioa_socket_handle s) bufferevent_enable(s->bev, EV_READ|EV_WRITE); /* Start reading. */ } } else -#endif //TURN_NO_TLS +#endif //TLS_SUPPORTED { s->st = TCP_SOCKET; if(s->bev) { @@ -2443,7 +2448,7 @@ static int socket_input_worker(ioa_socket_handle s) s->broken = 1; log_socket_event(s, "socket read failed, to be closed",1); } else if(s->st == TLS_SOCKET) { -#if !defined(TURN_NO_TLS) +#if TLS_SUPPORTED SSL *ctx = bufferevent_openssl_get_ssl(s->bev); if(!ctx || SSL_get_shutdown(ctx)) { ret = -1; @@ -3083,7 +3088,7 @@ int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, if (s->connected && s->bev) { if (s->st == TLS_SOCKET) { -#if !defined(TURN_NO_TLS) +#if TLS_SUPPORTED SSL *ctx = bufferevent_openssl_get_ssl(s->bev); if (!ctx || SSL_get_shutdown(ctx)) { s->tobeclosed = 1; @@ -3240,7 +3245,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in return -1; } } else { -#if !defined(TURN_NO_TLS) +#if TLS_SUPPORTED if(!(s->ssl)) { //??? how we can get to this point ??? set_socket_ssl(s,SSL_NEW(e->tls_ctx_ssl23)); diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index c17fffd8..989cefbb 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -143,14 +143,16 @@ struct _ioa_engine stun_buffer_list bufs; SSL_CTX *tls_ctx_ssl23; SSL_CTX *tls_ctx_v1_0; -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED SSL_CTX *tls_ctx_v1_1; -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED SSL_CTX *tls_ctx_v1_2; #endif #endif +#if DTLSv1_SUPPORTED SSL_CTX *dtls_ctx; -#if defined(SSL_OP_NO_DTLSv1_2) +#endif +#if DTLSv1_2_SUPPORTED SSL_CTX *dtls_ctx_v1_2; #endif turn_time_t jiffie; /* bandwidth check interval */ @@ -254,14 +256,16 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm, void set_ssl_ctx(ioa_engine_handle e, SSL_CTX *tls_ctx_ssl23, SSL_CTX *tls_ctx_v1_0, -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED SSL_CTX *tls_ctx_v1_1, -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED SSL_CTX *tls_ctx_v1_2, #endif #endif +#if DTLSv1_SUPPORTED SSL_CTX *dtls_ctx -#if defined(SSL_OP_NO_DTLSv1_2) +#endif +#if DTLSv1_2_SUPPORTED ,SSL_CTX *dtls_ctx_v1_2 #endif ); diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index dbe41fdf..ecd3f546 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -517,18 +517,18 @@ int main(int argc, char **argv) root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; -#if defined(SSL_TXT_TLSV1_1) +#if TLSv1_1_SUPPORTED root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_1_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; -#if defined(SSL_TXT_TLSV1_2) +#if TLSv1_2_SUPPORTED root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_2_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; #endif #endif } else { -#if defined(TURN_NO_DTLS) +#if !DTLSv1_SUPPORTED fprintf(stderr,"ERROR: DTLS is not supported.\n"); exit(-1); #else @@ -538,7 +538,7 @@ int main(int argc, char **argv) root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; -#if defined(SSL_OP_NO_DTLSv1_2) +#if DTLSv1_2_SUPPORTED root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_2_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 40dcd7fa..cfed67f2 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -50,7 +50,7 @@ static uint64_t current_reservation_token = 0; static int allocate_rtcp = 0; static const int never_allocate_rtcp = 0; -#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION +#if ALPN_SUPPORTED static const unsigned char kALPNProtos[] = "\x09stun.turn\x12stun.nat-discovery"; static const size_t kALPNProtosLen = sizeof(kALPNProtos) - 1; #endif @@ -91,14 +91,14 @@ static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr, int *try_again ssl = SSL_NEW(root_tls_ctx[ctxtype]); -#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION +#if ALPN_SUPPORTED SSL_set_alpn_protos(ssl, kALPNProtos, kALPNProtosLen); #endif if(use_tcp) { SSL_set_fd(ssl, fd); } else { -#if defined(TURN_NO_DTLS) +#if !DTLSv1_SUPPORTED UNUSED_ARG(remote_addr); fprintf(stderr,"ERROR: DTLS is not supported.\n"); exit(-1); diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 8ad2eaed..6443a109 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -216,14 +216,6 @@ typedef u32bits turn_time_t; #define DELETE_TURN_CHANNEL_KERNEL(handler) #endif -/* ALPN */ - -#define OPENSSL_FIRST_ALPN_VERSION (0x10002003L) - -#define STUN_ALPN "stun.nat-discovery" -#define TURN_ALPN "stun.turn" -#define HTTP_ALPN "http/1.1" - //////////////////////////////////////////////////////// #ifdef __cplusplus From cd35ab46afe1fed644225d74ef2d8c12ac75837d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 11 Dec 2014 09:02:49 +0000 Subject: [PATCH 370/805] tls code cleaning --- src/apps/relay/dtls_listener.c | 7 ++++-- src/apps/relay/netengine.c | 30 +++++++++++++------------- src/apps/relay/ns_ioalib_engine_impl.c | 8 +++---- src/apps/relay/ns_ioalib_impl.h | 8 +++---- 4 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index f45e4bbf..9119535a 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -898,7 +898,10 @@ static int init_server(dtls_listener_relay_server_type* server, if(!server) return -1; +#if DTLSv1_SUPPORTED server->dtls_ctx = e->dtls_ctx; +#endif + #if DTLSv1_2_SUPPORTED server->dtls_ctx_v1_2 = e->dtls_ctx_v1_2; #endif @@ -918,6 +921,7 @@ static int init_server(dtls_listener_relay_server_type* server, server->e = e; +#if DTLSv1_SUPPORTED if(server->dtls_ctx) { #if defined(REQUEST_CLIENT_CERT) @@ -927,11 +931,10 @@ static int init_server(dtls_listener_relay_server_type* server, SSL_CTX_set_read_ahead(server->dtls_ctx, 1); -#if DTLSv1_SUPPORTED SSL_CTX_set_cookie_generate_cb(server->dtls_ctx, generate_cookie); SSL_CTX_set_cookie_verify_cb(server->dtls_ctx, verify_cookie); -#endif } +#endif #if DTLSv1_2_SUPPORTED if(server->dtls_ctx_v1_2) { diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 02880373..633984b0 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -940,18 +940,18 @@ static ioa_engine_handle create_new_listener_engine(void) ,turn_params.redis_statsdb #endif ); - set_ssl_ctx(e, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0, + set_ssl_ctx(e, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0 #if TLSv1_1_SUPPORTED - turn_params.tls_ctx_v1_1, + ,turn_params.tls_ctx_v1_1 #if TLSv1_2_SUPPORTED - turn_params.tls_ctx_v1_2, + ,turn_params.tls_ctx_v1_2 #endif #endif #if DTLSv1_SUPPORTED - turn_params.dtls_ctx + ,turn_params.dtls_ctx #endif #if DTLSv1_2_SUPPORTED - ,turn_params.dtls_ctx_v1_2 + ,turn_params.dtls_ctx_v1_2 #endif ); ioa_engine_set_rtcp_map(e, turn_params.listener.rtcpmap); @@ -996,18 +996,18 @@ static void setup_listener(void) if(!turn_params.listener.ioa_eng) exit(-1); - set_ssl_ctx(turn_params.listener.ioa_eng, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0, + set_ssl_ctx(turn_params.listener.ioa_eng, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0 #if TLSv1_1_SUPPORTED - turn_params.tls_ctx_v1_1, + ,turn_params.tls_ctx_v1_1 #if TLSv1_2_SUPPORTED - turn_params.tls_ctx_v1_2, + ,turn_params.tls_ctx_v1_2 #endif #endif #if DTLSv1_SUPPORTED - turn_params.dtls_ctx + ,turn_params.dtls_ctx #endif #if DTLSv1_2_SUPPORTED - ,turn_params.dtls_ctx_v1_2 + ,turn_params.dtls_ctx_v1_2 #endif ); @@ -1570,18 +1570,18 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int ,turn_params.redis_statsdb #endif ); - set_ssl_ctx(rs->ioa_eng, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0, + set_ssl_ctx(rs->ioa_eng, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0 #if TLSv1_1_SUPPORTED - turn_params.tls_ctx_v1_1, + ,turn_params.tls_ctx_v1_1 #if TLSv1_2_SUPPORTED - turn_params.tls_ctx_v1_2, + ,turn_params.tls_ctx_v1_2 #endif #endif #if DTLSv1_SUPPORTED - turn_params.dtls_ctx + ,turn_params.dtls_ctx #endif #if DTLSv1_2_SUPPORTED - ,turn_params.dtls_ctx_v1_2 + ,turn_params.dtls_ctx_v1_2 #endif ); ioa_engine_set_rtcp_map(rs->ioa_eng, turn_params.listener.rtcpmap); diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 5fcc8b86..3feb6b6e 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -433,15 +433,15 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm, void set_ssl_ctx(ioa_engine_handle e, SSL_CTX *tls_ctx_ssl23, - SSL_CTX *tls_ctx_v1_0, + SSL_CTX *tls_ctx_v1_0 #if TLSv1_1_SUPPORTED - SSL_CTX *tls_ctx_v1_1, + ,SSL_CTX *tls_ctx_v1_1 #if TLSv1_2_SUPPORTED - SSL_CTX *tls_ctx_v1_2, + ,SSL_CTX *tls_ctx_v1_2 #endif #endif #if DTLSv1_SUPPORTED - SSL_CTX *dtls_ctx + ,SSL_CTX *dtls_ctx #endif #if DTLSv1_2_SUPPORTED ,SSL_CTX *dtls_ctx_v1_2 diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 989cefbb..5e82e0d9 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -255,15 +255,15 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm, void set_ssl_ctx(ioa_engine_handle e, SSL_CTX *tls_ctx_ssl23, - SSL_CTX *tls_ctx_v1_0, + SSL_CTX *tls_ctx_v1_0 #if TLSv1_1_SUPPORTED - SSL_CTX *tls_ctx_v1_1, + ,SSL_CTX *tls_ctx_v1_1 #if TLSv1_2_SUPPORTED - SSL_CTX *tls_ctx_v1_2, + ,SSL_CTX *tls_ctx_v1_2 #endif #endif #if DTLSv1_SUPPORTED - SSL_CTX *dtls_ctx + ,SSL_CTX *dtls_ctx #endif #if DTLSv1_2_SUPPORTED ,SSL_CTX *dtls_ctx_v1_2 From 08e3980b2492b353502c565b8c025f5731565d80 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 12 Dec 2014 01:59:25 +0000 Subject: [PATCH 371/805] INSTALL updated --- INSTALL | 87 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/INSTALL b/INSTALL index 5b9d0d08..6b6cdc23 100644 --- a/INSTALL +++ b/INSTALL @@ -150,7 +150,49 @@ NOTE: On most modern systems, the build will produce dynamically linked executables. If you want statically linked executables, you have to modify, accordingly, the Makefile.in template file. -IV. INSTALL +IV. OPENSSL + +If you are using the OpenSSL that is coming with your system, and you are +OK with it, then you do not have to read this chapter. If your system has +an outdated OpenSSL version, or if you need some very fresh OpenSSL features +that are not present in the current usual stable version, then you may have +to compile (and run) your TURN server with a different OpenSSL version. + +For example, if you need ALPN feature, or DTLS1.2, and your system comes with +OpenSSL 1.0.1, you will not be able to use those features unless you install +OpenSSL 1.0.2 and compile and run the TURN server with the newer version. + +The problem is, it is usually not safe to replace the system's OpenSSL with +a different version. Some systems are "bound" to its "native" OpenSSL +installations, and their behavior may become unpredictable with the newer +versions. + +So you want to preserve your system's OpenSSL but you want to compile and to +run the TURN server with newer OpenSSL version. There are different ways to +do that. We are suggesting the following: + + 1) Download the OpenSSL version from openssl.org. + 2) Let's assume that we want to install the "custom" OpenSSL into /opt. + Configure and build OpenSSL as: + $ ./config --prefix=/opt + $ make + $ make install + Those commands will install OpenSSL into /opt, with static libraries (no + dynamic libraries). + 3) Build the TURN server: + $ ./configure --prefix=/opt + $ make + Those commands will build the TURN server binaries, statically linked + against the newer OpenSSL. + 4) Then you can run the TURN server without setting the dynamic + libraries paths - because it has been linked statically against the newer + OpenSSL libraries. + +One potential problem is that libevent2 is using the OpenSSL, too. So, ideally, +to be 100% safe of all potential discrepancies in the runtime, we'd suggesting +rebuilding libevent2 with the newer OpenSSL, too. + +V. INSTALL This step is optional. You can run the turnserver from the original build directory, successfully, without installing the TURN server into your system. @@ -206,7 +248,7 @@ but if you have some libraries in different non-default directories then you will have to add them manually to the search path, or you will have to adjust LD_LIBRARY_PATH. -V. PLATFORMS +VI. PLATFORMS The TURN Server is using generic *NIX system APIs and is supposed to be usable on wide range of *NIX systems. @@ -244,7 +286,7 @@ The code is compatible with C++ compiler, and a C++ compiler $ CC=g++ ./configure $ make -VII. WHICH EXTRA LIBRARIES AND UTILITIES YOU NEED +VIII. WHICH EXTRA LIBRARIES AND UTILITIES YOU NEED In addition to common *NIX OS services and libraries, to compile this code, OpenSSL (version 1.0.0a or better recommended) and libevent2 (version 2.0.5 @@ -443,7 +485,7 @@ that will set the installation prefix to /usr (without "--prefix=/usr" by default it would be installed to /usr/local). This is necessary if you want to overwrite your existing older OpenSSL installation. -VIII. BUILDING WITH NON-DEFAULT PREFIX DIRECTORY +IX. BUILDING WITH NON-DEFAULT PREFIX DIRECTORY Say, you have an older system with old openssl and old libevent library and you do not want to change that, but you still want @@ -482,7 +524,7 @@ by using $ ldconfig -m (BSD) $ crle -u -l (Solaris) -IX. TEST SCRIPTS +X. TEST SCRIPTS First of all, you can use the test vectors from RFC 5769 to double-check that the STUN/TURN message encoding algorithms work properly. Run the utility: @@ -564,15 +606,16 @@ and the peer. Check the README.* files and the comments in the scripts relay.sh and secure_relay.sh as a guidance how to run the TURN server. -X. OS X compilation notes +XI. OS X compilation notes OS X usually has an older version of openssl supplied, with some Apple additions. The the "native" openssl will work, within its limitations, but the best option is to install a good fresh openssl development library, from http://www.openssl.org. You will have -to handle the dynamic linking of the generated binaries. +to handle the dynamic linking of the generated binaries, or use the +static linking (see the section OPENSSL). -XI. MS Windows and Cygwin support +XII. MS Windows and Cygwin support Currently, this project cannot be compiled under MS Windows. @@ -585,7 +628,7 @@ libevent2 runtime and libevent-devel packages. "Manual" libevent2 compilation and installation in Cygwin is not recommended and does not garantee a good outcome. -XII. CLIENT API LIBRARY. +XIII. CLIENT API LIBRARY. The compilation process will create lib/ sub-directory with libturnclient.a library. The header files for this library are located in include/turn/client/ @@ -594,7 +637,7 @@ TurnMsgLib.h header. An example of C++ code can be found in stunclient.c file. This file is compiled as a C++ program if C++ compiler is used, and as a C program if C compiler is used. -XIII. DOCS +XIV. DOCS After installation, the man page turnserver(1) must be available. The man page is located in man/man1 subdirectory. If you want to see the man page without @@ -606,7 +649,7 @@ HTML-formatted client library functions reference is located in docs/html subdirectory of the original archive tree. After the installation, it will be placed in PREFIX/share/doc/turnserver/html. -XIV. SQLite setup +XV. SQLite setup The site http://www.sqlite.org site has excellent extensive documentation. @@ -778,7 +821,7 @@ Fill in users, for example: $ bin/turnadmin -A -b "/var/db/turndb" -u gorst -p hero $ bin/turnadmin -A -b "/var/db/turndb" -u ninefingers -p youhavetoberealistic -XV. PostgreSQL setup +XVI. PostgreSQL setup The site http://www.postgresql.org site has excellent extensive documentation. For a quick-start guide, you can take a look into this page: @@ -902,7 +945,7 @@ Fill in users, for example: $ 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 -XVI. MySQL (MariaDB) setup +XVII. MySQL (MariaDB) setup The MySQL setup is similar to PostgreSQL (same idea), and is well documented on their site http://www.mysql.org. The TURN Server database schema is the @@ -985,7 +1028,7 @@ ca, capath, cert, key, cipher (see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the command options description). -XVII. MongoDB setup +XVIII. MongoDB setup The MongoDB setup is well documented on their site http://docs.mongodb.org/manual/. @@ -1017,7 +1060,7 @@ explanations for the Postgres, for example. See the file testmongosetup.sh for the database structure examples. -XVIII. Redis setup +XIX. Redis setup The Redis setup is well documented on their site http://redis.io. The TURN Server Redis database schema description can be found @@ -1088,20 +1131,20 @@ Redis TURN admin commands: See the file testredisdbsetup.sh for the data structure examples. -XIX. Performance tuning +XX. Performance tuning This topic is covered in the wiki page: http://code.google.com/p/coturn/wiki/turn_performance_and_load_balance -XX. TURN Server setup +XXI. TURN Server setup 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. -XXI. Management interface +XXII. 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 @@ -1117,3 +1160,11 @@ or ::1). The CLI may have a password configured, but that password is 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. + +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). +If the ALPN functionality is needed, then OpenSSL version 1.0.2 or +newer has to be used. See OPENSSL section for the OpenSSL upgrade hints. + \ No newline at end of file From c4cd2cabe2a73d98c6367b6e7763eed5d628f319 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 12 Dec 2014 09:17:28 +0000 Subject: [PATCH 372/805] STATUS updated --- STATUS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/STATUS b/STATUS index 3585fe1d..d137195a 100644 --- a/STATUS +++ b/STATUS @@ -110,6 +110,8 @@ compatibility. 47) SQLite support added as default database. 48) DTLS1.2 supported. + +49) ALPN stun.turn and stun.nat-discovery supported. Things to be implemented in future (the development roadmap) are described in the TODO file. From 94c3c57456f09112555000a39654fb096158c9e7 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 12 Dec 2014 10:23:18 +0000 Subject: [PATCH 373/805] DTLS code cleaning --- configure | 48 ---------------------- src/apps/common/apputils.c | 9 ++--- src/apps/common/apputils.h | 56 +++++++++++++++----------- src/apps/relay/dtls_listener.c | 19 +++++---- src/apps/relay/mainrelay.c | 21 +++++----- src/apps/relay/mainrelay.h | 4 +- src/apps/relay/netengine.c | 6 +-- src/apps/relay/ns_ioalib_engine_impl.c | 4 +- src/apps/relay/ns_ioalib_impl.h | 4 +- src/apps/uclient/mainuclient.c | 2 +- src/apps/uclient/startuclient.c | 2 +- 11 files changed, 65 insertions(+), 110 deletions(-) diff --git a/configure b/configure index 23d95c5a..4cd9b101 100755 --- a/configure +++ b/configure @@ -7,8 +7,6 @@ cleanup() { rm -rf ${TMPCPROGB} rm -rf ${TH_TMPCPROGC} rm -rf ${TH_TMPCPROGB} - rm -rf ${DTLS_TMPCPROGC} - rm -rf ${DTLS_TMPCPROGB} rm -rf ${GCM_TMPCPROGC} rm -rf ${GCM_TMPCPROGB} rm -rf ${PQ_TMPCPROGC} @@ -239,21 +237,6 @@ pthread_testbarriers() { fi } -dtls_testlib() { - - if [ -z "${TURN_NO_DTLS}" ] ; then - ${CC} ${DTLS_TMPCPROGC} -o ${DTLS_TMPCPROGB} ${OSCFLAGS} ${OSLIBS} 2>>/dev/null - ER=$? - if [ ${ER} -eq 0 ] ; then - return 1 - else - return 0 - fi - else - return 0 - fi -} - gcm_testlib() { if [ -z "${TURN_NO_GCM}" ] ; then @@ -686,19 +669,6 @@ int main(int argc, char** argv) { ! -DTLS_TMPCPROG=__test__ccomp__dtls__$$ -DTLS_TMPCPROGC=${TMPDIR}/${DTLS_TMPCPROG}.c -DTLS_TMPCPROGB=${TMPDIR}/${DTLS_TMPCPROG} - -cat > ${DTLS_TMPCPROGC} < -#include -#include -int main(int argc, char** argv) { - return (((int)(BIO_CTRL_DGRAM_QUERY_MTU)) + argc + (int)(argv[argc][0]) + DTLSv1_listen(NULL,NULL)); -} -! - GCM_TMPCPROG=__test__ccomp__gcm__$$ GCM_TMPCPROGC=${TMPDIR}/${GCM_TMPCPROG}.c GCM_TMPCPROGB=${TMPDIR}/${GCM_TMPCPROG} @@ -961,24 +931,6 @@ else exit fi -########################### -# Can we use DTLS ? -########################### - -if [ -z ${TURN_NO_DTLS} ] ; then - -dtls_testlib -ER=$? -if [ ${ER} -eq 0 ] ; then - ${ECHO_CMD} "WARNING: Cannot find DTLS support." - ${ECHO_CMD} "Turning DTLS off." - TURN_NO_DTLS="-DTURN_NO_DTLS" -fi - -else - TURN_NO_DTLS="-DTURN_NO_DTLS" -fi - ########################### # Can we use GCM cipher ? ########################### diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c index aa4a4f39..6d89d926 100644 --- a/src/apps/common/apputils.c +++ b/src/apps/common/apputils.c @@ -349,7 +349,7 @@ int set_socket_df(evutil_socket_t fd, int family, int value) static int get_mtu_from_ssl(SSL* ssl) { int ret = SOSO_MTU; -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED if(ssl) ret = BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); #else @@ -395,7 +395,7 @@ int decrease_mtu(SSL* ssl, int mtu, int verbose) if (verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "1. mtu to use: %d\n", mtu); -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED SSL_set_mtu(ssl,mtu); BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_SET_MTU, mtu, NULL); #endif @@ -416,7 +416,7 @@ int set_mtu_df(SSL* ssl, evutil_socket_t fd, int family, int mtu, int df_value, set_query_mtu(ssl); if(verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"3. mtu to use: %d\n",mtu); -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED SSL_set_mtu(ssl,mtu); @@ -859,7 +859,7 @@ static const char* turn_get_method(const SSL_METHOD *method, const char* mdefaul return "TLSv1.2"; #endif #endif -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED } else if(method == DTLSv1_server_method()) { return "DTLSv1.0"; @@ -872,7 +872,6 @@ static const char* turn_get_method(const SSL_METHOD *method, const char* mdefaul } else if(method == DTLSv1_2_client_method()) { return "DTLSv1.2"; #endif - #endif } else { if(mdefault) diff --git a/src/apps/common/apputils.h b/src/apps/common/apputils.h index 37d24001..c61c77a9 100644 --- a/src/apps/common/apputils.h +++ b/src/apps/common/apputils.h @@ -70,36 +70,44 @@ extern int IS_TURN_SERVER; /* TLS */ #if defined(TURN_NO_TLS) -#define TLS_SUPPORTED 0 -#define TLSv1_1_SUPPORTED 0 -#define TLSv1_2_SUPPORTED 0 + + #define TLS_SUPPORTED 0 + #define TLSv1_1_SUPPORTED 0 + #define TLSv1_2_SUPPORTED 0 + #else -#define TLS_SUPPORTED 1 -#if defined(SSL_TXT_TLSV1_1) -#define TLSv1_1_SUPPORTED 1 -#else -#define TLSv1_1_SUPPORTED 0 + + #define TLS_SUPPORTED 1 + + #if defined(SSL_OP_NO_TLSv1_1) + #define TLSv1_1_SUPPORTED 1 + #else + #define TLSv1_1_SUPPORTED 0 + #endif + + #if defined(SSL_OP_NO_TLSv1_2) + #define TLSv1_2_SUPPORTED 1 + #else + #define TLSv1_2_SUPPORTED 0 + #endif + #endif -#if defined(SSL_TXT_TLSV1_2) -#define TLSv1_2_SUPPORTED 1 -#else -#define TLSv1_2_SUPPORTED 0 -#endif -#endif +#if defined(TURN_NO_DTLS) || !defined(DTLS_CTRL_LISTEN) -#define OPENSSL_FIRST_DTLSv1_2_VERSION (0x10002003L) + #define DTLS_SUPPORTED 0 + #define DTLSv1_2_SUPPORTED 0 -#if defined(TURN_NO_DTLS) -#define DTLSv1_SUPPORTED 0 -#define DTLSv1_2_SUPPORTED 0 #else -#define DTLSv1_SUPPORTED 1 -#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_DTLSv1_2_VERSION -#define DTLSv1_2_SUPPORTED 1 -#else -#define DTLSv1_2_SUPPORTED 0 -#endif + + #define DTLS_SUPPORTED 1 + +#if defined(SSL_OP_NO_DTLSv1_2) + #define DTLSv1_2_SUPPORTED 1 + #else + #define DTLSv1_2_SUPPORTED 0 + #endif + #endif /////////// SSL ////////////////////////// diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index 9119535a..f4428411 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -58,7 +58,7 @@ struct dtls_listener_relay_server_info { ioa_engine_handle e; turn_turnserver *ts; int verbose; -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED SSL_CTX *dtls_ctx; #if DTLSv1_2_SUPPORTED SSL_CTX *dtls_ctx_v1_2; @@ -128,7 +128,7 @@ int get_dtls_version(const unsigned char* buf, int len) { ///////////// utils ///////////////////// -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED static void calculate_cookie(SSL* ssl, unsigned char *cookie_secret, unsigned int cookie_length) { long rv=(long)ssl; @@ -428,7 +428,7 @@ static int handle_udp_packet(dtls_listener_relay_server_type *server, chs = NULL; -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED if (!turn_params.no_dtls && is_dtls_handshake_message(ioa_network_buffer_data(sm->m.sm.nd.nbh), (int)ioa_network_buffer_get_size(sm->m.sm.nd.nbh))) { @@ -537,7 +537,7 @@ static int create_new_connected_udp_socket( ret->current_tos = s->current_tos; ret->default_tos = s->default_tos; -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED if (!turn_params.no_dtls && is_dtls_handshake_message( ioa_network_buffer_data(server->sm.m.sm.nd.nbh), @@ -898,13 +898,14 @@ static int init_server(dtls_listener_relay_server_type* server, if(!server) return -1; -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED server->dtls_ctx = e->dtls_ctx; -#endif #if DTLSv1_2_SUPPORTED server->dtls_ctx_v1_2 = e->dtls_ctx_v1_2; #endif +#endif + server->ts = ts; server->connect_cb = send_socket; @@ -921,7 +922,7 @@ static int init_server(dtls_listener_relay_server_type* server, server->e = e; -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED if(server->dtls_ctx) { #if defined(REQUEST_CLIENT_CERT) @@ -934,7 +935,6 @@ static int init_server(dtls_listener_relay_server_type* server, SSL_CTX_set_cookie_generate_cb(server->dtls_ctx, generate_cookie); SSL_CTX_set_cookie_verify_cb(server->dtls_ctx, verify_cookie); } -#endif #if DTLSv1_2_SUPPORTED if(server->dtls_ctx_v1_2) { @@ -946,11 +946,10 @@ static int init_server(dtls_listener_relay_server_type* server, SSL_CTX_set_read_ahead(server->dtls_ctx_v1_2, 1); - #if DTLSv1_SUPPORTED SSL_CTX_set_cookie_generate_cb(server->dtls_ctx_v1_2, generate_cookie); SSL_CTX_set_cookie_verify_cb(server->dtls_ctx_v1_2, verify_cookie); - #endif } +#endif #endif return create_server_socket(server, report_creation); diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index ac95e8ee..7e556dbd 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -72,7 +72,7 @@ NULL, NULL, NULL, #endif #endif -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED NULL, #endif #if DTLSv1_2_SUPPORTED @@ -88,7 +88,7 @@ DH_1066, "", DEFAULT_EC_CURVE_NAME, "", 0, #endif -#if !DTLSv1_SUPPORTED +#if !DTLS_SUPPORTED 1, #else 0, @@ -1228,7 +1228,7 @@ static void set_option(int c, char *value) #endif break; case NO_DTLS_OPT: -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED turn_params.no_dtls = get_bool_value(value); #else turn_params.no_dtls = 1; @@ -1618,7 +1618,7 @@ static void print_features(unsigned long mfn) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS supported\n"); #endif -#if !DTLSv1_SUPPORTED +#if !DTLS_SUPPORTED TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS is not supported\n"); #else TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS supported\n"); @@ -1666,11 +1666,7 @@ static void print_features(unsigned long mfn) TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "OpenSSL multithreading is not supported (?!)\n"); #endif -#if OPENSSL_VERSION_NUMBER >= 0x10000000L - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL compile-time version 0x%llx: fresh enough\n",(unsigned long long)OPENSSL_VERSION_NUMBER); -#else - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL compile-time version 0x%llx version: antique\n",(unsigned long long)OPENSSL_VERSION_NUMBER); -#endif + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL compile-time version: %s\n",OPENSSL_VERSION_TEXT); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Default Net Engine version: %d (%s)\n\n=====================================================\n\n", (int)turn_params.net_engine_version, turn_params.net_engine_version_txt[(int)turn_params.net_engine_version]); @@ -1802,7 +1798,7 @@ int main(int argc, char **argv) turn_params.no_tls = 1; #endif -#if !DTLSv1_SUPPORTED +#if !DTLS_SUPPORTED turn_params.no_dtls = 1; #endif @@ -2525,12 +2521,13 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) if(turn_params.no_tlsv1_1) op |= SSL_OP_NO_TLSv1_1; #endif + #if defined(SSL_OP_NO_TLSv1_2) if(turn_params.no_tlsv1_2) op |= SSL_OP_NO_TLSv1_2; #endif -#if defined(SSL_OP_NO_DTLSv1) && DTLSv1_SUPPORTED +#if defined(SSL_OP_NO_DTLSv1) && DTLS_SUPPORTED if(turn_params.no_tlsv1) op |= SSL_OP_NO_DTLSv1; #endif @@ -2608,7 +2605,7 @@ static void openssl_setup(void) } if(!turn_params.no_dtls) { -#if !DTLSv1_SUPPORTED +#if !DTLS_SUPPORTED TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "ERROR: DTLS is not supported.\n"); #else if(OPENSSL_VERSION_NUMBER < 0x10000000L) { diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index edf4e823..b1e7ea42 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -187,11 +187,11 @@ typedef struct _turn_params_ { #endif #endif -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED SSL_CTX *dtls_ctx; -#endif #if DTLSv1_2_SUPPORTED SSL_CTX *dtls_ctx_v1_2; +#endif #endif DH_KEY_SIZE dh_key_size; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 633984b0..081cd77b 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -947,7 +947,7 @@ static ioa_engine_handle create_new_listener_engine(void) ,turn_params.tls_ctx_v1_2 #endif #endif -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED ,turn_params.dtls_ctx #endif #if DTLSv1_2_SUPPORTED @@ -1003,7 +1003,7 @@ static void setup_listener(void) ,turn_params.tls_ctx_v1_2 #endif #endif -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED ,turn_params.dtls_ctx #endif #if DTLSv1_2_SUPPORTED @@ -1577,7 +1577,7 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int ,turn_params.tls_ctx_v1_2 #endif #endif -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED ,turn_params.dtls_ctx #endif #if DTLSv1_2_SUPPORTED diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 3feb6b6e..f8c71bcc 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -440,7 +440,7 @@ void set_ssl_ctx(ioa_engine_handle e, ,SSL_CTX *tls_ctx_v1_2 #endif #endif -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED ,SSL_CTX *dtls_ctx #endif #if DTLSv1_2_SUPPORTED @@ -456,7 +456,7 @@ void set_ssl_ctx(ioa_engine_handle e, e->tls_ctx_v1_2 = tls_ctx_v1_2; #endif #endif -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED e->dtls_ctx = dtls_ctx; #endif #if DTLSv1_2_SUPPORTED diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 5e82e0d9..27390dc1 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -149,7 +149,7 @@ struct _ioa_engine SSL_CTX *tls_ctx_v1_2; #endif #endif -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED SSL_CTX *dtls_ctx; #endif #if DTLSv1_2_SUPPORTED @@ -262,7 +262,7 @@ void set_ssl_ctx(ioa_engine_handle e, ,SSL_CTX *tls_ctx_v1_2 #endif #endif -#if DTLSv1_SUPPORTED +#if DTLS_SUPPORTED ,SSL_CTX *dtls_ctx #endif #if DTLSv1_2_SUPPORTED diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index ecd3f546..7adc7983 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -528,7 +528,7 @@ int main(int argc, char **argv) #endif #endif } else { -#if !DTLSv1_SUPPORTED +#if !DTLS_SUPPORTED fprintf(stderr,"ERROR: DTLS is not supported.\n"); exit(-1); #else diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index cfed67f2..823434b7 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -98,7 +98,7 @@ static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr, int *try_again if(use_tcp) { SSL_set_fd(ssl, fd); } else { -#if !DTLSv1_SUPPORTED +#if !DTLS_SUPPORTED UNUSED_ARG(remote_addr); fprintf(stderr,"ERROR: DTLS is not supported.\n"); exit(-1); From e4d22777feede79423b6b89a4ece16ae1a8a981d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 12 Dec 2014 10:32:29 +0000 Subject: [PATCH 374/805] cleaning --- src/apps/relay/mainrelay.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 7e556dbd..84f53bb4 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1660,12 +1660,6 @@ static void print_features(unsigned long mfn) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MongoDB is not supported\n"); #endif -#if defined(OPENSSL_THREADS) - //TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL multithreading supported\n"); -#else - TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "OpenSSL multithreading is not supported (?!)\n"); -#endif - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL compile-time version: %s\n",OPENSSL_VERSION_TEXT); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Default Net Engine version: %d (%s)\n\n=====================================================\n\n", (int)turn_params.net_engine_version, turn_params.net_engine_version_txt[(int)turn_params.net_engine_version]); From c88240468febcc5163a00d13b12b1a3d5e1bcb00 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 14 Dec 2014 05:56:33 +0000 Subject: [PATCH 375/805] changelog update --- ChangeLog | 5 +++-- rpm/turnserver.spec | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6dfb8b5c..87f6fcba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,8 @@ -12/09/2014 Oleg Moskalenko +12/13/2014 Oleg Moskalenko Version 4.3.2.1 'Tolomei': - - DTLS v1.2 supported (when compiled with OpenSSL 1.0.2+ ); - STUN/TURN ALPN supported (when compiled with OpenSSL 1.0.2+ ); + - DTLS v1.2 supported (when compiled with OpenSSL 1.0.2+ ); + - TLS/DTLS code cleaning. 11/29/2014 Oleg Moskalenko Version 4.3.1.3 'Tolomei': diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 995ba866..462bad42 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -294,7 +294,7 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Tue Dec 09 2014 Oleg Moskalenko +* Sat Dec 13 2014 Oleg Moskalenko - Sync to 4.3.2.1 * Sat Nov 29 2014 Oleg Moskalenko - Sync to 4.3.1.3 From 4dfa8248a12957f92b28d1eb2893294e84770ed2 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 14 Dec 2014 07:26:38 +0000 Subject: [PATCH 376/805] iauto ecdh curve parameters; docs. --- ChangeLog | 1 + README.turnserver | 7 +++++-- examples/etc/turnserver.conf | 7 +++++-- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 9 ++++++--- man/man1/turnutils.1 | 2 +- src/apps/common/apputils.h | 6 ++++++ src/apps/relay/mainrelay.c | 31 +++++++++++++++++++++++-------- 8 files changed, 48 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 87f6fcba..791b8e6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,7 @@ Version 4.3.2.1 'Tolomei': - STUN/TURN ALPN supported (when compiled with OpenSSL 1.0.2+ ); - DTLS v1.2 supported (when compiled with OpenSSL 1.0.2+ ); + - Auto optimal ECDH parameters (when compiled with OpenSSL 1.0.2+ ); - TLS/DTLS code cleaning. 11/29/2014 Oleg Moskalenko diff --git a/README.turnserver b/README.turnserver index 06fe32d0..79de0d56 100644 --- a/README.turnserver +++ b/README.turnserver @@ -444,8 +444,11 @@ Options with required values: Forces TURN server to verify the client SSL certificates. By default, no CA is set and no client certificate check is performed. ---ec-curve-name Curve name for EC ciphers, if supported by OpenSSL library (TLS and DTLS). - The default value is prime256v1. +--ec-curve-name Curve name for EC ciphers, if supported by OpenSSL + library (TLS and DTLS). The default value is prime256v1, + if pre-OpenSSL 1.0.2 is used. With OpenSSL 1.0.2+, + an optimal curve will be automatically calculated, if not defined + by this option. --dh-file Use custom DH TLS key, stored in PEM format in the file. Flags --dh566 and --dh2066 are ignored when the DH key is taken from a file. diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index efd96225..6e3c2f95 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -418,8 +418,11 @@ # Example: #CA-file=/etc/ssh/id_rsa.cert -# Curve name for EC ciphers, if supported by OpenSSL library (TLS and DTLS). -# The default value is prime256v1. +# Curve name for EC ciphers, if supported by OpenSSL +# library (TLS and DTLS). The default value is prime256v1, +# if pre-OpenSSL 1.0.2 is used. With OpenSSL 1.0.2+, +# an optimal curve will be automatically calculated, if not defined +# by this option. # #ec-curve-name=prime256v1 diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 6b1d34f0..36e92cfb 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "10 December 2014" "" "" +.TH TURN 1 "13 December 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 5882842a..e60e14d8 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "10 December 2014" "" "" +.TH TURN 1 "13 December 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -649,8 +649,11 @@ By default, no CA is set and no client certificate check is performed. .TP .B \fB\-\-ec\-curve\-name\fP -Curve name for EC ciphers, if supported by OpenSSL library (TLS and DTLS). -The default value is prime256v1. +Curve name for EC ciphers, if supported by OpenSSL +library (TLS and DTLS). The default value is prime256v1, +if pre\-OpenSSL 1.0.2 is used. With OpenSSL 1.0.2+, +an optimal curve will be automatically calculated, if not defined +by this option. .TP .B \fB\-\-dh\-file\fP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 61851d7c..b75d33d3 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "10 December 2014" "" "" +.TH TURN 1 "13 December 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/src/apps/common/apputils.h b/src/apps/common/apputils.h index c61c77a9..adb38b69 100644 --- a/src/apps/common/apputils.h +++ b/src/apps/common/apputils.h @@ -110,6 +110,12 @@ extern int IS_TURN_SERVER; #endif +#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION +#define SSL_SESSION_ECDH_AUTO_SUPPORTED 1 +#else +#define SSL_SESSION_ECDH_AUTO_SUPPORTED 0 +#endif + /////////// SSL ////////////////////////// enum _TURN_TLS_TYPE { diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 84f53bb4..a4090e33 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -509,8 +509,11 @@ static char Usage[] = "Usage: turnserver [options]\n" " --CA-file CA file in OpenSSL format.\n" " Forces TURN server to verify the client SSL certificates.\n" " By default, no CA is set and no client certificate check is performed.\n" -" --ec-curve-name Curve name for EC ciphers, if supported by OpenSSL library\n" -" (TLS and DTLS). The default value is prime256v1.\n" +" --ec-curve-name Curve name for EC ciphers, if supported by OpenSSL\n" +" library (TLS and DTLS). The default value is prime256v1,\n" +" if pre-OpenSSL 1.0.2 is used. With OpenSSL 1.0.2+,\n" +" an optimal curve will be automatically calculated, if not defined\n" +" by this option.\n" " --dh566 Use 566 bits predefined DH TLS key. Default size of the predefined key is 1066.\n" " --dh2066 Use 2066 bits predefined DH TLS key. Default size of the predefined key is 1066.\n" " --dh-file Use custom DH TLS key, stored in PEM format in the file.\n" @@ -2435,23 +2438,35 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) #if !defined(OPENSSL_NO_EC) && defined(OPENSSL_EC_NAMED_CURVE) { //Elliptic curve algorithms: int nid = NID_X9_62_prime256v1; + int set_tmp_curve = !SSL_SESSION_ECDH_AUTO_SUPPORTED; if (turn_params.ec_curve_name[0]) { nid = OBJ_sn2nid(turn_params.ec_curve_name); if (nid == 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"unknown curve name (%s), using NID_X9_62_prime256v1\n",turn_params.ec_curve_name); nid = NID_X9_62_prime256v1; + } else { + set_tmp_curve = 1; } } - EC_KEY *ecdh = EC_KEY_new_by_curve_name(nid); - if (!ecdh) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + if(set_tmp_curve) { + EC_KEY *ecdh = EC_KEY_new_by_curve_name(nid); + if (!ecdh) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: allocate EC suite\n",__FUNCTION__); - } else { - SSL_CTX_set_tmp_ecdh(ctx, ecdh); - EC_KEY_free(ecdh); + set_tmp_curve = 0; + } else { + SSL_CTX_set_tmp_ecdh(ctx, ecdh); + EC_KEY_free(ecdh); + } } + +#if SSL_SESSION_ECDH_AUTO_SUPPORTED + if(!set_tmp_curve) { + SSL_CTX_set_ecdh_auto(ctx,1); + } +#endif } #endif From 1bf9508011513d75af37e535429e32e853e5a22c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 14 Dec 2014 08:26:48 +0000 Subject: [PATCH 377/805] ecdh auto fixes --- src/apps/relay/mainrelay.c | 51 +++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index a4090e33..382941fb 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -79,7 +79,7 @@ NULL, NULL, #endif -DH_1066, "", DEFAULT_EC_CURVE_NAME, "", +DH_1066, "", "", "", "turn_server_cert.pem","turn_server_pkey.pem", "", "", 0,0,0,0,0, #if !TLS_SUPPORTED @@ -2437,33 +2437,44 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) #if !defined(OPENSSL_NO_EC) && defined(OPENSSL_EC_NAMED_CURVE) { //Elliptic curve algorithms: - int nid = NID_X9_62_prime256v1; - int set_tmp_curve = !SSL_SESSION_ECDH_AUTO_SUPPORTED; + int nid = 0; + int set_auto_curve = 0; - if (turn_params.ec_curve_name[0]) { - nid = OBJ_sn2nid(turn_params.ec_curve_name); - if (nid == 0) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"unknown curve name (%s), using NID_X9_62_prime256v1\n",turn_params.ec_curve_name); - nid = NID_X9_62_prime256v1; - } else { - set_tmp_curve = 1; - } + const char* curve_name = turn_params.ec_curve_name; + + if (!(curve_name[0])) { +#if !SSL_SESSION_ECDH_AUTO_SUPPORTED + curve_name = DEFAULT_EC_CURVE_NAME; +#endif + set_auto_curve = 1; } - if(set_tmp_curve) { - EC_KEY *ecdh = EC_KEY_new_by_curve_name(nid); - if (!ecdh) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + if(curve_name[0]) { + { + nid = OBJ_sn2nid(curve_name); + if (nid == 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"unknown curve name: %s\n",curve_name); + curve_name = DEFAULT_EC_CURVE_NAME; + nid = OBJ_sn2nid(curve_name); + set_auto_curve = 1; + } + } + + { + EC_KEY *ecdh = EC_KEY_new_by_curve_name(nid); + if (!ecdh) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: allocate EC suite\n",__FUNCTION__); - set_tmp_curve = 0; - } else { - SSL_CTX_set_tmp_ecdh(ctx, ecdh); - EC_KEY_free(ecdh); + set_auto_curve = 1; + } else { + SSL_CTX_set_tmp_ecdh(ctx, ecdh); + EC_KEY_free(ecdh); + } } } #if SSL_SESSION_ECDH_AUTO_SUPPORTED - if(!set_tmp_curve) { + if(set_auto_curve) { SSL_CTX_set_ecdh_auto(ctx,1); } #endif From 6c845ced0e4852a1cd2f628bf44bd56394ed7476 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 14 Dec 2014 08:30:32 +0000 Subject: [PATCH 378/805] warning fixed --- src/apps/relay/mainrelay.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 382941fb..3133dc30 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -2473,11 +2473,12 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) } } -#if SSL_SESSION_ECDH_AUTO_SUPPORTED if(set_auto_curve) { +#if SSL_SESSION_ECDH_AUTO_SUPPORTED SSL_CTX_set_ecdh_auto(ctx,1); - } #endif + set_auto_curve = 0; + } } #endif From a0ddb8524579c2e05f7829daaab4eac81d853bc7 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 15 Dec 2014 02:49:37 +0000 Subject: [PATCH 379/805] ALPN fixes --- src/apps/relay/mainrelay.c | 4 ++-- src/apps/uclient/startuclient.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 3133dc30..61768132 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -2357,12 +2357,12 @@ static int ServerALPNCallback(SSL *s, unsigned char current_len = *ptr; if(ptr+1+current_len > in+inlen) break; - if((current_len == sa_len) && (memcmp(ptr+1,STUN_ALPN,sa_len)==0)) { + if((!turn_params.no_stun) && (current_len == sa_len) && (memcmp(ptr+1,STUN_ALPN,sa_len)==0)) { *out = ptr+1; *outlen = sa_len; return SSL_TLSEXT_ERR_OK; } - if((current_len == ta_len) && (memcmp(ptr+1,TURN_ALPN,ta_len)==0)) { + if((!turn_params.stun_only) && (current_len == ta_len) && (memcmp(ptr+1,TURN_ALPN,ta_len)==0)) { *out = ptr+1; *outlen = ta_len; return SSL_TLSEXT_ERR_OK; diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 823434b7..38ab87b5 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -51,7 +51,7 @@ static int allocate_rtcp = 0; static const int never_allocate_rtcp = 0; #if ALPN_SUPPORTED -static const unsigned char kALPNProtos[] = "\x09stun.turn\x12stun.nat-discovery"; +static const unsigned char kALPNProtos[] = "\x08http/1.1\x09stun.turn\x12stun.nat-discovery"; static const size_t kALPNProtosLen = sizeof(kALPNProtos) - 1; #endif From ec0472bfdebfdcf7190b233452c97f1d6ca8b5c9 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 15 Dec 2014 03:53:15 +0000 Subject: [PATCH 380/805] Redis read message queu bug fixed; --- ChangeLog | 1 + src/apps/common/hiredis_libevent2.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 791b8e6b..b3ca86d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 12/13/2014 Oleg Moskalenko Version 4.3.2.1 'Tolomei': + - Redis read message queue bug fixed; - STUN/TURN ALPN supported (when compiled with OpenSSL 1.0.2+ ); - DTLS v1.2 supported (when compiled with OpenSSL 1.0.2+ ); - Auto optimal ECDH parameters (when compiled with OpenSSL 1.0.2+ ); diff --git a/src/apps/common/hiredis_libevent2.c b/src/apps/common/hiredis_libevent2.c index 24ca2fa0..c27fba35 100644 --- a/src/apps/common/hiredis_libevent2.c +++ b/src/apps/common/hiredis_libevent2.c @@ -267,7 +267,7 @@ redis_context_handle redisLibeventAttach(struct event_base *base, char *ip0, int /* Initialize and install read/write events */ e->rev = event_new(e->base,e->context->c.fd, - EV_READ,redisLibeventReadEvent, + EV_READ|EV_PERSIST,redisLibeventReadEvent, e); e->wev = event_new(e->base,e->context->c.fd, From b0c6428aefdbf995ce373f247328c9e1a3bba6e8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 15 Dec 2014 05:52:33 +0000 Subject: [PATCH 381/805] typo fixed --- ChangeLog | 6 +++--- INSTALL | 10 +++++----- README.turnserver | 2 +- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 4 ++-- man/man1/turnutils.1 | 2 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 6 +++--- src/ns_turn_defs.h | 2 +- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index b3ca86d7..8b07655c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ -12/13/2014 Oleg Moskalenko -Version 4.3.2.1 'Tolomei': +12/14/2014 Oleg Moskalenko +Version 4.3.2.2 'Tolomei': - Redis read message queue bug fixed; - STUN/TURN ALPN supported (when compiled with OpenSSL 1.0.2+ ); - DTLS v1.2 supported (when compiled with OpenSSL 1.0.2+ ); @@ -565,7 +565,7 @@ Version 1.8.5.4 'Black Dow': 05/31/2013 Oleg Moskalenko Version 1.8.5.3 'Black Dow': - - REST API extra script example and docs extention. + - REST API extra script example and docs extension. 05/26/2013 Oleg Moskalenko Version 1.8.5.1 'Black Dow': diff --git a/INSTALL b/INSTALL index 6b6cdc23..dccc7f77 100644 --- a/INSTALL +++ b/INSTALL @@ -813,7 +813,7 @@ Fill in users, for example: $ bin/turnadmin -a -b "/var/db/turndb" -u gorst -r north.gov -p hero $ bin/turnadmin -a -b "/var/db/turndb" -u ninefingers -r north.gov -p youhavetoberealistic - Long-term credentials mechanism with SHA256 extention: + 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: @@ -937,7 +937,7 @@ Fill in users, for example: $ bin/turnadmin -a -e "host=localhost dbname=coturn user=turn password=turn" -u gorst -r north.gov -p hero $ bin/turnadmin -a -e "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic - Long-term credentials mechanism with SHA256 extention: + 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: @@ -992,7 +992,7 @@ the root account. $ bin/turnadmin -a -M "host=localhost dbname=coturn user=turn password=turn" -u gorst -r north.gov -p hero $ bin/turnadmin -a -M "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic - Long-term credentials mechanism with SHA256 extention: + 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: @@ -1035,7 +1035,7 @@ The MongoDB setup is well documented on their site http://docs.mongodb.org/manua Note: if your system has a "standard" plain vanilla UNIX "make" utility (that is not a GNU make) then you will have to use the GNU make to compile the Mongo driver, because the Mongo compilation process was written with -the "proprietary" GNU extentions. For example, in FreeBSD in will have to use +the "proprietary" GNU extensions. For example, in FreeBSD in will have to use "gmake" command. If the TURN server was compiled with MongoDB support (mongo-c-driver is the C client @@ -1121,7 +1121,7 @@ Redis TURN admin commands: $ bin/turnadmin -a -N "host=localhost dbname=2 user=turn password=turn" -u gorst -r north.gov -p hero $ bin/turnadmin -a -N "host=localhost dbname=2 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic - Long-term credentials mechanism with SHA256 extention: + 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: diff --git a/README.turnserver b/README.turnserver index 79de0d56..0c686290 100644 --- a/README.turnserver +++ b/README.turnserver @@ -787,7 +787,7 @@ The server supports ALPNs "stun.turn" and "stun.nat-discovery", when compiled with OpenSSL 1.0.2 or newer. If the server receives a TLS/DTLS ClientHello message that contains one or both of those ALPNs, then the server chooses the first stun.* label and sends it back (in the ServerHello) -in the ALPN extention field. If no stun.* label is found, then the server +in the ALPN extension field. If no stun.* label is found, then the server does not include the ALPN information into the ServerHello. ================================= diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 36e92cfb..d14cdfa9 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "13 December 2014" "" "" +.TH TURN 1 "14 December 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index e60e14d8..2146995d 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "13 December 2014" "" "" +.TH TURN 1 "14 December 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -1041,7 +1041,7 @@ The server supports ALPNs "stun.turn" and "stun.nat\-discovery", when compiled with OpenSSL 1.0.2 or newer. If the server receives a TLS/DTLS ClientHello message that contains one or both of those ALPNs, then the server chooses the first stun.* label and sends it back (in the ServerHello) -in the ALPN extention field. If no stun.* label is found, then the server +in the ALPN extension field. If no stun.* label is found, then the server does not include the ALPN information into the ServerHello. .PP ================================= diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index b75d33d3..867fc9ca 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "13 December 2014" "" "" +.TH TURN 1 "14 December 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 67acef40..096912ff 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.3.2.1 +TURNVERSION=4.3.2.2 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 462bad42..3b26a4be 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.3.2.1 +Version: 4.3.2.2 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,8 +294,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Sat Dec 13 2014 Oleg Moskalenko - - Sync to 4.3.2.1 +* Sun Dec 14 2014 Oleg Moskalenko + - Sync to 4.3.2.2 * Sat Nov 29 2014 Oleg Moskalenko - Sync to 4.3.1.3 * Mon Nov 23 2014 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 6443a109..bceccf5d 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.3.2.1" +#define TURN_SERVER_VERSION "4.3.2.2" #define TURN_SERVER_VERSION_NAME "Tolomei" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 6b291a823858f6236cbfb47f25548857118398e8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 20 Dec 2014 08:51:44 +0000 Subject: [PATCH 382/805] multi-threaded DB connections. --- src/apps/relay/dbdrivers/dbd_mongo.c | 12 ++++++---- src/apps/relay/dbdrivers/dbd_mongo.h | 2 +- src/apps/relay/dbdrivers/dbd_mysql.c | 14 +++++++---- src/apps/relay/dbdrivers/dbd_mysql.h | 2 +- src/apps/relay/dbdrivers/dbd_pgsql.c | 15 ++++++++---- src/apps/relay/dbdrivers/dbd_pgsql.h | 2 +- src/apps/relay/dbdrivers/dbd_redis.c | 18 +++++++------- src/apps/relay/dbdrivers/dbd_redis.h | 2 +- src/apps/relay/dbdrivers/dbd_sqlite.c | 16 +++++++++---- src/apps/relay/dbdrivers/dbd_sqlite.h | 2 +- src/apps/relay/dbdrivers/dbdriver.c | 19 +++++++++++---- src/apps/relay/dbdrivers/dbdriver.h | 7 +++++- src/apps/relay/mainrelay.c | 2 +- src/apps/relay/userdb.c | 34 +++++++++++++-------------- src/apps/relay/userdb.h | 3 --- 15 files changed, 90 insertions(+), 60 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index cb4d6ad1..f5d4f998 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -82,7 +82,7 @@ static MONGO * get_mongodb_connection(void) { persistent_users_db_t * pud = get_persistent_users_db(); - MONGO * mydbconnection = (MONGO *) (pud->connection); + MONGO * mydbconnection = (MONGO *) pthread_getspecific(connection_key); if (!mydbconnection) { mongoc_init(); @@ -111,7 +111,9 @@ static MONGO * get_mongodb_connection(void) { mydbconnection->uri); if (!mydbconnection->database) mydbconnection->database = MONGO_DEFAULT_DB; - pud->connection = mydbconnection; + if(mydbconnection) { + (void) pthread_setspecific(connection_key, mydbconnection); + } TURN_LOG_FUNC( TURN_LOG_LEVEL_INFO, "Opened MongoDB URI <%s>\n", @@ -1172,7 +1174,7 @@ static void mongo_reread_realms(secrets_list_t * realms_list) { /////////////////////////////////////////////////////////////////////////////////////////////////////////// -static turn_dbdriver_t driver = { +static const turn_dbdriver_t driver = { &mongo_get_auth_secrets, &mongo_get_user_key, &mongo_get_user_pwd, @@ -1197,7 +1199,7 @@ static turn_dbdriver_t driver = { &mongo_list_oauth_keys }; -turn_dbdriver_t * get_mongo_dbdriver(void) { +const turn_dbdriver_t * get_mongo_dbdriver(void) { return &driver; } @@ -1205,7 +1207,7 @@ turn_dbdriver_t * get_mongo_dbdriver(void) { #else -turn_dbdriver_t * get_mongo_dbdriver(void) { +const turn_dbdriver_t * get_mongo_dbdriver(void) { return NULL; } diff --git a/src/apps/relay/dbdrivers/dbd_mongo.h b/src/apps/relay/dbdrivers/dbd_mongo.h index 66ed0a07..862881b4 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.h +++ b/src/apps/relay/dbdrivers/dbd_mongo.h @@ -38,7 +38,7 @@ extern "C" { #endif -turn_dbdriver_t * get_mongo_dbdriver(void); +const turn_dbdriver_t * get_mongo_dbdriver(void); #ifdef __cplusplus } diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index cd5e65f5..25bd46db 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -189,14 +189,16 @@ static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) { } static MYSQL *get_mydb_connection(void) { + persistent_users_db_t *pud = get_persistent_users_db(); - MYSQL *mydbconnection = (MYSQL*)(pud->connection); + MYSQL *mydbconnection = (MYSQL*)pthread_getspecific(connection_key); if(mydbconnection) { if(mysql_ping(mydbconnection)) { mysql_close(mydbconnection); mydbconnection=NULL; + (void) pthread_setspecific(connection_key, mydbconnection); } } @@ -242,7 +244,9 @@ static MYSQL *get_mydb_connection(void) { } MyconninfoFree(co); } - pud->connection = mydbconnection; + if(mydbconnection) { + (void) pthread_setspecific(connection_key, mydbconnection); + } } return mydbconnection; } @@ -1063,7 +1067,7 @@ static void mysql_reread_realms(secrets_list_t * realms_list) { /////////////////////////////////////////////////////////////////////////////////////////////////////////// -static turn_dbdriver_t driver = { +static const turn_dbdriver_t driver = { &mysql_get_auth_secrets, &mysql_get_user_key, &mysql_get_user_pwd, @@ -1088,7 +1092,7 @@ static turn_dbdriver_t driver = { &mysql_list_oauth_keys }; -turn_dbdriver_t * get_mysql_dbdriver(void) { +const turn_dbdriver_t * get_mysql_dbdriver(void) { return &driver; } @@ -1096,7 +1100,7 @@ turn_dbdriver_t * get_mysql_dbdriver(void) { #else -turn_dbdriver_t * get_mysql_dbdriver(void) { +const turn_dbdriver_t * get_mysql_dbdriver(void) { return NULL; } diff --git a/src/apps/relay/dbdrivers/dbd_mysql.h b/src/apps/relay/dbdrivers/dbd_mysql.h index 91b15906..b7ba5b89 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.h +++ b/src/apps/relay/dbdrivers/dbd_mysql.h @@ -38,7 +38,7 @@ extern "C" { #endif -turn_dbdriver_t * get_mysql_dbdriver(void); +const turn_dbdriver_t * get_mysql_dbdriver(void); #ifdef __cplusplus } diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index 21e6ff98..52e9bd96 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -40,14 +40,16 @@ static int donot_print_connection_success = 0; static PGconn *get_pqdb_connection(void) { + persistent_users_db_t *pud = get_persistent_users_db(); - PGconn *pqdbconnection = (PGconn*)(pud->connection); + PGconn *pqdbconnection = (PGconn*)pthread_getspecific(connection_key); if(pqdbconnection) { ConnStatusType status = PQstatus(pqdbconnection); if(status != CONNECTION_OK) { PQfinish(pqdbconnection); pqdbconnection = NULL; + (void) pthread_setspecific(connection_key, pqdbconnection); } } if(!pqdbconnection) { @@ -78,7 +80,10 @@ static PGconn *get_pqdb_connection(void) { } } } - pud->connection = pqdbconnection; + + if(pqdbconnection) { + (void) pthread_setspecific(connection_key, pqdbconnection); + } } return pqdbconnection; } @@ -782,7 +787,7 @@ static void pgsql_reread_realms(secrets_list_t * realms_list) { /////////////////////////////////////////////////////////////////////////////////////////////////////////// -static turn_dbdriver_t driver = { +static const turn_dbdriver_t driver = { &pgsql_get_auth_secrets, &pgsql_get_user_key, &pgsql_get_user_pwd, @@ -807,7 +812,7 @@ static turn_dbdriver_t driver = { &pgsql_list_oauth_keys }; -turn_dbdriver_t * get_pgsql_dbdriver(void) { +const turn_dbdriver_t * get_pgsql_dbdriver(void) { return &driver; } @@ -815,7 +820,7 @@ turn_dbdriver_t * get_pgsql_dbdriver(void) { #else -turn_dbdriver_t * get_pgsql_dbdriver(void) { +const turn_dbdriver_t * get_pgsql_dbdriver(void) { return NULL; } diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.h b/src/apps/relay/dbdrivers/dbd_pgsql.h index 7c36e66e..4ebea436 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.h +++ b/src/apps/relay/dbdrivers/dbd_pgsql.h @@ -38,7 +38,7 @@ extern "C" { #endif -turn_dbdriver_t * get_pgsql_dbdriver(void); +const turn_dbdriver_t * get_pgsql_dbdriver(void); #ifdef __cplusplus } diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index 10feb342..2f5b04ca 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -264,14 +264,14 @@ redis_context_handle get_redis_async_connection(struct event_base *base, const c static redisContext *get_redis_connection(void) { persistent_users_db_t *pud = get_persistent_users_db(); - redisContext *redisconnection = (redisContext*)(pud->connection); + redisContext *redisconnection = (redisContext*)pthread_getspecific(connection_key); if(redisconnection) { if(redisconnection->err) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Cannot connect to redis, err=%d, flags=0x%lx\n", __FUNCTION__,(int)redisconnection->err,(unsigned long)redisconnection->flags); redisFree(redisconnection); - pud->connection = NULL; redisconnection = NULL; + (void) pthread_setspecific(connection_key, redisconnection); } } @@ -351,11 +351,9 @@ static redisContext *get_redis_connection(void) { RyconninfoFree(co); } - pud->connection = redisconnection; - - pud = get_persistent_users_db(); - - redisconnection = (redisContext*)(pud->connection); + if(redisconnection) { + (void) pthread_setspecific(connection_key, redisconnection); + } } return redisconnection; @@ -1205,7 +1203,7 @@ static void redis_reread_realms(secrets_list_t * realms_list) { /////////////////////////////////////////////////////////////////////////////////////////////////////////// -static turn_dbdriver_t driver = { +static const turn_dbdriver_t driver = { &redis_get_auth_secrets, &redis_get_user_key, &redis_get_user_pwd, @@ -1230,7 +1228,7 @@ static turn_dbdriver_t driver = { &redis_list_oauth_keys }; -turn_dbdriver_t * get_redis_dbdriver(void) { +const turn_dbdriver_t * get_redis_dbdriver(void) { return &driver; } @@ -1238,7 +1236,7 @@ turn_dbdriver_t * get_redis_dbdriver(void) { #else -turn_dbdriver_t * get_redis_dbdriver(void) { +const turn_dbdriver_t * get_redis_dbdriver(void) { return NULL; } diff --git a/src/apps/relay/dbdrivers/dbd_redis.h b/src/apps/relay/dbdrivers/dbd_redis.h index 6ba27b9f..85cc2ab8 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.h +++ b/src/apps/relay/dbdrivers/dbd_redis.h @@ -38,7 +38,7 @@ extern "C" { #endif -turn_dbdriver_t * get_redis_dbdriver(void); +const turn_dbdriver_t * get_redis_dbdriver(void); #ifdef __cplusplus } diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 0646bfaa..57d3e0b6 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -119,7 +119,7 @@ static sqlite3 * get_sqlite_connection(void) { persistent_users_db_t *pud = get_persistent_users_db(); - sqlite3 *sqliteconnection = (sqlite3 *)(pud->connection); + sqlite3 *sqliteconnection = (sqlite3 *)pthread_getspecific(connection_key); if(!sqliteconnection) { fix_user_directory(pud->userdb); sqlite_init_multithreaded(); @@ -136,7 +136,9 @@ static sqlite3 * get_sqlite_connection(void) { init_sqlite_database(sqliteconnection); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SQLite DB connection success: %s\n",pud->userdb); } - pud->connection = sqliteconnection; + if(sqliteconnection) { + (void) pthread_setspecific(connection_key, sqliteconnection); + } } return sqliteconnection; } @@ -936,7 +938,7 @@ static void sqlite_reread_realms(secrets_list_t * realms_list) /////////////////////////////////////////////////////////////////////////////////////////////////////////// -static turn_dbdriver_t driver = { +static const turn_dbdriver_t driver = { &sqlite_get_auth_secrets, &sqlite_get_user_key, &sqlite_get_user_pwd, @@ -963,10 +965,16 @@ static turn_dbdriver_t driver = { ////////////////////////////////////////////////// -turn_dbdriver_t * get_sqlite_dbdriver(void) { +const turn_dbdriver_t * get_sqlite_dbdriver(void) { return &driver; } ////////////////////////////////////////////////// +#else + +const turn_dbdriver_t * get_sqlite_dbdriver(void) { + return NULL; +} + #endif diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.h b/src/apps/relay/dbdrivers/dbd_sqlite.h index c1e95487..69d4269f 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.h +++ b/src/apps/relay/dbdrivers/dbd_sqlite.h @@ -38,7 +38,7 @@ extern "C" { #endif -turn_dbdriver_t * get_sqlite_dbdriver(void); +const turn_dbdriver_t * get_sqlite_dbdriver(void); #ifdef __cplusplus } diff --git a/src/apps/relay/dbdrivers/dbdriver.c b/src/apps/relay/dbdrivers/dbdriver.c index f51ac72a..987666e3 100644 --- a/src/apps/relay/dbdrivers/dbdriver.c +++ b/src/apps/relay/dbdrivers/dbdriver.c @@ -40,7 +40,14 @@ #include "dbd_mongo.h" #include "dbd_redis.h" -static turn_dbdriver_t * _driver; +static void make_connection_key(void) +{ + (void) pthread_key_create(&connection_key, NULL); +} + + +pthread_key_t connection_key; +pthread_once_t connection_key_once = PTHREAD_ONCE_INIT; int convert_string_key_to_binary(char* keysource, hmackey_t key, size_t sz) { char is[3]; @@ -60,13 +67,17 @@ persistent_users_db_t * get_persistent_users_db(void) { return &(turn_params.default_users_db.persistent_users_db); } -turn_dbdriver_t * get_dbdriver() +const turn_dbdriver_t * get_dbdriver() { - if (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_UNKNOWN) return NULL; - if (!_driver) { + (void) pthread_once(&connection_key_once, make_connection_key); + + static const turn_dbdriver_t * _driver = NULL; + + if (_driver == NULL) { + switch (turn_params.default_users_db.userdb_type){ #if !defined(TURN_NO_SQLITE) case TURN_USERDB_TYPE_SQLITE: diff --git a/src/apps/relay/dbdrivers/dbdriver.h b/src/apps/relay/dbdrivers/dbdriver.h index 29e8ef20..5118313d 100644 --- a/src/apps/relay/dbdrivers/dbdriver.h +++ b/src/apps/relay/dbdrivers/dbdriver.h @@ -36,12 +36,17 @@ #include "ns_turn_msg_defs_new.h" +#include + #ifdef __cplusplus extern "C" { #endif //////////////////////////////////////////// +extern pthread_key_t connection_key; +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); @@ -71,7 +76,7 @@ typedef struct _turn_dbdriver_t { int convert_string_key_to_binary(char* keysource, hmackey_t key, size_t sz); persistent_users_db_t * get_persistent_users_db(void); -turn_dbdriver_t * get_dbdriver(void); +const turn_dbdriver_t * get_dbdriver(void); //////////////////////////////////////////// diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 61768132..f2906778 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -121,7 +121,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",NULL}, {0,NULL,NULL, {NULL,0}} } +{ (TURN_USERDB_TYPE)0, {"\0"}, {0,NULL,NULL, {NULL,0}} } }; diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 816a99a0..4d599634 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -302,7 +302,7 @@ void add_to_secrets_list(secrets_list_t *sl, const char* elem) static int get_auth_secrets(secrets_list_t *sl, u08bits *realm) { int ret = -1; - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); clean_secrets_list(sl); @@ -419,7 +419,7 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u if(len>0 && value) { - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->get_oauth_key) { @@ -635,7 +635,7 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u return 0; } - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->get_user_key) { ret = (*(dbd->get_user_key))(usname, realm, key); } @@ -650,7 +650,7 @@ int get_user_pwd(u08bits *usname, st_password_t pwd) { int ret = -1; - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->get_user_pwd) { ret = (*dbd->get_user_pwd)(usname, pwd); } @@ -792,7 +792,7 @@ int add_user_account(char *user, int dynamic) static int list_users(int is_st, u08bits *realm) { - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->list_users) { (*dbd->list_users)(is_st, realm); } @@ -804,7 +804,7 @@ static int show_secret(u08bits *realm) { must_set_admin_realm(realm); - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->show_secret) { (*dbd->show_secret)(realm); } @@ -816,7 +816,7 @@ static int del_secret(u08bits *secret, u08bits *realm) { must_set_admin_realm(realm); - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->del_secret) { (*dbd->del_secret)(secret, realm); } @@ -833,7 +833,7 @@ static int set_secret(u08bits *secret, u08bits *realm) { del_secret(secret, realm); - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->set_secret) { (*dbd->set_secret)(secret, realm); } @@ -847,7 +847,7 @@ static int add_origin(u08bits *origin0, u08bits *realm) get_canonic_origin((const char *)origin0, (char *)origin, sizeof(origin)-1); - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->add_origin) { (*dbd->add_origin)(origin, realm); } @@ -861,7 +861,7 @@ static int del_origin(u08bits *origin0) get_canonic_origin((const char *)origin0, (char *)origin, sizeof(origin)-1); - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->del_origin) { (*dbd->del_origin)(origin); } @@ -871,7 +871,7 @@ static int del_origin(u08bits *origin0) static int list_origins(u08bits *realm) { - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->list_origins) { (*dbd->list_origins)(realm); } @@ -884,7 +884,7 @@ static int set_realm_option_one(u08bits *realm, unsigned long value, const char* if(value == (unsigned long)-1) return 0; - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->set_realm_option_one) { (*dbd->set_realm_option_one)(realm, value, opt); } @@ -902,7 +902,7 @@ static int set_realm_option(u08bits *realm, perf_options_t *po) static int list_realm_options(u08bits *realm) { - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->list_realm_options) { (*dbd->list_realm_options)(realm); } @@ -984,7 +984,7 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b } } - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (ct == TA_PRINT_KEY) { @@ -1020,7 +1020,7 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b void auth_ping(redis_context_handle rch) { - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->auth_ping) { (*dbd->auth_ping)(rch); } @@ -1193,7 +1193,7 @@ ip_range_list_t* get_ip_list(const char *kind) ip_range_list_t *ret = (ip_range_list_t*) turn_malloc(sizeof(ip_range_list_t)); ns_bzero(ret,sizeof(ip_range_list_t)); - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->get_ip_list) { (*dbd->get_ip_list)(kind, ret); } @@ -1292,7 +1292,7 @@ void reread_realms(void) ur_string_map_unlock(realms); } - turn_dbdriver_t * dbd = get_dbdriver(); + const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->reread_realms) { (*dbd->reread_realms)(&realms_list); } diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index 41d37915..1d66a710 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -158,10 +158,7 @@ typedef struct _ram_users_db_t { } ram_users_db_t; typedef struct _persistent_users_db_t { - char userdb[TURN_LONG_STRING_SIZE]; - void *connection; - } persistent_users_db_t; typedef struct _default_users_db_t From 87cd2366c77c238d18f7e1558403c10f285e966a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 20 Dec 2014 22:21:00 +0000 Subject: [PATCH 383/805] auth server code cleaning --- src/apps/relay/dbdrivers/dbd_redis.c | 1 + src/apps/relay/mainrelay.c | 3 -- src/apps/relay/mainrelay.h | 11 ------- src/apps/relay/netengine.c | 49 ++++++++++++++++++---------- src/apps/relay/userdb.c | 12 +++---- 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index 2f5b04ca..c72c939a 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -161,6 +161,7 @@ static Ryconninfo *RyconninfoParse(const char *userdb, char **errmsg) { } redis_context_handle get_redis_async_connection(struct event_base *base, const char* connection_string, int delete_keys) { + redis_context_handle ret = NULL; char *errmsg = NULL; diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index f2906778..c9b060ad 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -110,7 +110,6 @@ NEV_UNKNOWN, LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,0,"", 0,NULL,0,NULL,DEFAULT_GENERAL_RELAY_SERVERS_NUMBER,0, ////////////// Auth server ///////////////////////////////////// -{NULL,NULL,NULL,0,NULL}, "","",0, /////////////// AUX SERVERS //////////////// {NULL,0,{0,NULL}},0, @@ -1884,8 +1883,6 @@ int main(int argc, char **argv) STRCPY(turn_params.default_users_db.persistent_users_db.userdb,DEFAULT_USERDB_FILE); #endif - update_white_and_black_lists(); - argc -= optind; argv += optind; diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index b1e7ea42..b5062b48 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -160,16 +160,6 @@ enum _NET_ENG_VERSION { typedef enum _NET_ENG_VERSION NET_ENG_VERSION; -////////////// Auth Server Types //////////////// - -struct auth_server { - struct event_base* event_base; - struct bufferevent *in_buf; - struct bufferevent *out_buf; - pthread_t thr; - redis_context_handle rch; -}; - /////////// PARAMS ////////////////////////////////// typedef struct _turn_params_ { @@ -275,7 +265,6 @@ typedef struct _turn_params_ { ////////////// Auth server //////////////// - struct auth_server authserver; char oauth_server_name[1025]; char domain[1025]; int oauth; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 081cd77b..762b16b4 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -37,6 +37,18 @@ static unsigned int barrier_count = 0; static pthread_barrier_t barrier; #endif +////////////// Auth Server //////////////// + +struct auth_server { + struct event_base* event_base; + struct bufferevent *in_buf; + struct bufferevent *out_buf; + pthread_t thr; + redis_context_handle rch; +}; + +static struct auth_server authserver = {NULL,NULL,NULL,0,NULL}; + ////////////////////////////////////////////// #define get_real_general_relay_servers_number() (turn_params.general_relay_servers_number > 1 ? turn_params.general_relay_servers_number : 1) @@ -356,7 +368,7 @@ static int handle_relay_message(relay_server_handle rs, struct message_to_relay void send_auth_message_to_auth_server(struct auth_message *am) { - struct evbuffer *output = bufferevent_get_output(turn_params.authserver.out_buf); + struct evbuffer *output = bufferevent_get_output(authserver.out_buf); if(evbuffer_add(output,am,sizeof(struct auth_message))<0) { fprintf(stderr,"%s: Weird buffer error\n",__FUNCTION__); } @@ -1689,33 +1701,34 @@ static void* run_auth_server_thread(void *arg) { ignore_sigpipe(); - ns_bzero(&turn_params.authserver,sizeof(struct auth_server)); + struct auth_server *as = (struct auth_server*)arg; - turn_params.authserver.event_base = turn_event_base_new(); - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (auth thread): %s\n",event_base_get_method(turn_params.authserver.event_base)); + ns_bzero(as,sizeof(struct auth_server)); + + as->event_base = turn_event_base_new(); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (auth thread): %s\n",event_base_get_method(as->event_base)); struct bufferevent *pair[2]; - bufferevent_pair_new(turn_params.authserver.event_base, TURN_BUFFEREVENTS_OPTIONS, pair); - turn_params.authserver.in_buf = pair[0]; - turn_params.authserver.out_buf = pair[1]; - bufferevent_setcb(turn_params.authserver.in_buf, auth_server_receive_message, NULL, NULL, &turn_params.authserver); - bufferevent_enable(turn_params.authserver.in_buf, EV_READ); + bufferevent_pair_new(as->event_base, TURN_BUFFEREVENTS_OPTIONS, pair); + as->in_buf = pair[0]; + as->out_buf = pair[1]; + bufferevent_setcb(as->in_buf, auth_server_receive_message, NULL, NULL, as); + bufferevent_enable(as->in_buf, EV_READ); #if !defined(TURN_NO_HIREDIS) - turn_params.authserver.rch = get_redis_async_connection(turn_params.authserver.event_base, turn_params.redis_statsdb, 1); + as->rch = get_redis_async_connection(as->event_base, turn_params.redis_statsdb, 1); #endif - struct auth_server *authserver = &turn_params.authserver; - struct event_base *eb = authserver->event_base; + struct event_base *eb = as->event_base; barrier_wait(); while(run_auth_server_flag) { reread_realms(); - run_events(eb,NULL); update_white_and_black_lists(); - auth_ping(authserver->rch); + auth_ping(as->rch); + run_events(eb,NULL); #if defined(DB_TEST) run_db_test(); #endif @@ -1724,13 +1737,13 @@ static void* run_auth_server_thread(void *arg) return arg; } -static void setup_auth_server(void) +static void setup_auth_server(struct auth_server *as) { - if(pthread_create(&(turn_params.authserver.thr), NULL, run_auth_server_thread, NULL)<0) { + if(pthread_create(&(as->thr), NULL, run_auth_server_thread, as)<0) { perror("Cannot create auth thread\n"); exit(-1); } - pthread_detach(turn_params.authserver.thr); + pthread_detach(as->thr); } static void* run_cli_server_thread(void *arg) @@ -1815,7 +1828,7 @@ void setup_server(void) } } - setup_auth_server(); + setup_auth_server(&authserver); if(use_cli) setup_cli_server(); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 4d599634..aae0e411 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -650,12 +650,12 @@ 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); - } + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->get_user_pwd) { + ret = (*dbd->get_user_pwd)(usname, pwd); + } - return ret; + 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) @@ -1023,7 +1023,7 @@ void auth_ping(redis_context_handle rch) const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->auth_ping) { (*dbd->auth_ping)(rch); - } + } } ///////////////// TEST ///////////////// From c3da54c292f59f8a9f3c5ed325067c44ec02bac3 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 21 Dec 2014 03:16:02 +0000 Subject: [PATCH 384/805] multiple auth threads --- src/apps/relay/dbdrivers/dbd_mysql.c | 2 +- src/apps/relay/dbdrivers/dbd_pgsql.c | 2 +- src/apps/relay/dbdrivers/dbd_redis.c | 3 +- src/apps/relay/dbdrivers/dbd_sqlite.c | 1 + src/apps/relay/mainrelay.c | 17 ++--- src/apps/relay/mainrelay.h | 6 ++ src/apps/relay/netengine.c | 92 +++++++++++++++++++-------- src/apps/relay/userdb.c | 40 ++++++------ 8 files changed, 106 insertions(+), 57 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 25bd46db..37b705b1 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -240,6 +240,7 @@ static MYSQL *get_mydb_connection(void) { mydbconnection=NULL; } else if(!donot_print_connection_success) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MySQL DB connection success: %s\n",pud->userdb); + donot_print_connection_success = 1; } } MyconninfoFree(co); @@ -876,7 +877,6 @@ static int mysql_list_realm_options(u08bits *realm) { static void mysql_auth_ping(void * rch) { UNUSED_ARG(rch); - donot_print_connection_success = 1; MYSQL * myc = get_mydb_connection(); if(myc) { char statement[TURN_LONG_STRING_SIZE]; diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index 52e9bd96..c35a3f85 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -77,6 +77,7 @@ static PGconn *get_pqdb_connection(void) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb); } else if(!donot_print_connection_success){ TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "PostgreSQL DB connection success: %s\n",pud->userdb); + donot_print_connection_success = 1; } } } @@ -633,7 +634,6 @@ static int pgsql_list_realm_options(u08bits *realm) { static void pgsql_auth_ping(void * rch) { UNUSED_ARG(rch); - donot_print_connection_success = 1; PGconn * pqc = get_pqdb_connection(); if(pqc) { char statement[TURN_LONG_STRING_SIZE]; diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index c72c939a..eb54c940 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -254,6 +254,7 @@ redis_context_handle get_redis_async_connection(struct event_base *base, const c TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB connection\n"); } else if (is_redis_asyncconn_good(ret) && !donot_print_connection_success) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis DB async connection to be used: %s\n", connection_string); + donot_print_connection_success = 1; } RyconninfoFree(co); } @@ -348,6 +349,7 @@ static redisContext *get_redis_connection(void) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB connection\n"); } else if (!donot_print_connection_success) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis DB sync connection success: %s\n", pud->userdb); + donot_print_connection_success = 1; } RyconninfoFree(co); @@ -1024,7 +1026,6 @@ static int redis_list_realm_options(u08bits *realm) { } static void redis_auth_ping(void * rch) { - donot_print_connection_success = 1; redisContext *rc = get_redis_connection(); if(rc) { turnFreeRedisReply(redisCommand(rc, "keys turn/origin/*")); diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 57d3e0b6..9667621a 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -135,6 +135,7 @@ static sqlite3 * get_sqlite_connection(void) { } else if(!donot_print_connection_success){ 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(sqliteconnection) { (void) pthread_setspecific(connection_key, sqliteconnection); diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index c9b060ad..43a739e5 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -120,8 +120,9 @@ 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, {NULL,0}} }, +///////////// CPUs ////////////////// +DEFAULT_CPUS_NUMBER }; //////////////// OpenSSL Init ////////////////////// @@ -1801,14 +1802,14 @@ int main(int argc, char **argv) #if defined(_SC_NPROCESSORS_ONLN) { - long cpus = (long)sysconf(_SC_NPROCESSORS_CONF); + turn_params.cpus = (long)sysconf(_SC_NPROCESSORS_CONF); - if(cpus<1) - cpus = 1; - else if(cpus>MAX_NUMBER_OF_GENERAL_RELAY_SERVERS) - cpus = MAX_NUMBER_OF_GENERAL_RELAY_SERVERS; + if(turn_params.cpusMAX_NUMBER_OF_GENERAL_RELAY_SERVERS) + turn_params.cpus = MAX_NUMBER_OF_GENERAL_RELAY_SERVERS; - turn_params.general_relay_servers_number = (turnserver_id)cpus; + turn_params.general_relay_servers_number = (turnserver_id)turn_params.cpus; } #endif diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index b5062b48..be020acb 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -100,6 +100,8 @@ extern "C" { #define TURNSERVER_ID_BOUNDARY_BETWEEN_TCP_AND_UDP MAX_NUMBER_OF_GENERAL_RELAY_SERVERS #define TURNSERVER_ID_BOUNDARY_BETWEEN_UDP_AND_TCP TURNSERVER_ID_BOUNDARY_BETWEEN_TCP_AND_UDP +#define DEFAULT_CPUS_NUMBER (2) + /////////// TYPES /////////////////////////////////// enum _DH_KEY_SIZE { @@ -304,6 +306,10 @@ typedef struct _turn_params_ { default_users_db_t default_users_db; +/////// CPUs ////////////// + + unsigned long cpus; + } turn_params_t; extern turn_params_t turn_params; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 762b16b4..49bafc4e 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -39,7 +39,10 @@ static pthread_barrier_t barrier; ////////////// Auth Server //////////////// +typedef unsigned char authserver_id; + struct auth_server { + authserver_id id; struct event_base* event_base; struct bufferevent *in_buf; struct bufferevent *out_buf; @@ -47,7 +50,9 @@ struct auth_server { redis_context_handle rch; }; -static struct auth_server authserver = {NULL,NULL,NULL,0,NULL}; +#define MIN_AUTHSERVER_NUMBER (3) +static authserver_id authserver_number = MIN_AUTHSERVER_NUMBER; +static struct auth_server authserver[256]; ////////////////////////////////////////////// @@ -366,9 +371,20 @@ static void allocate_relay_addrs_ports(void) { static int handle_relay_message(relay_server_handle rs, struct message_to_relay *sm); +static pthread_mutex_t auth_message_counter_mutex = PTHREAD_MUTEX_INITIALIZER; +static authserver_id auth_message_counter = 1; + void send_auth_message_to_auth_server(struct auth_message *am) { - struct evbuffer *output = bufferevent_get_output(authserver.out_buf); + pthread_mutex_lock(&auth_message_counter_mutex); + if(auth_message_counter>=authserver_number) auth_message_counter = 1; + else if(auth_message_counter<1) auth_message_counter = 1; + authserver_id sn = auth_message_counter++; + pthread_mutex_unlock(&auth_message_counter_mutex); + + printf("%s: 111.111: %d\n",__FUNCTION__,(int)sn); + + struct evbuffer *output = bufferevent_get_output(authserver[sn].out_buf); if(evbuffer_add(output,am,sizeof(struct auth_message))<0) { fprintf(stderr,"%s: Weird buffer error\n",__FUNCTION__); } @@ -1703,35 +1719,48 @@ static void* run_auth_server_thread(void *arg) struct auth_server *as = (struct auth_server*)arg; - ns_bzero(as,sizeof(struct auth_server)); + authserver_id id = as->id; - as->event_base = turn_event_base_new(); - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (auth thread): %s\n",event_base_get_method(as->event_base)); + if(id == 0) { - struct bufferevent *pair[2]; + barrier_wait(); - bufferevent_pair_new(as->event_base, TURN_BUFFEREVENTS_OPTIONS, pair); - as->in_buf = pair[0]; - as->out_buf = pair[1]; - bufferevent_setcb(as->in_buf, auth_server_receive_message, NULL, NULL, as); - bufferevent_enable(as->in_buf, EV_READ); + while(run_auth_server_flag) { + reread_realms(); + update_white_and_black_lists(); +#if defined(DB_TEST) + run_db_test(); +#endif + sleep(5); + } + + } else { + + ns_bzero(as,sizeof(struct auth_server)); + + as->id = id; + + as->event_base = turn_event_base_new(); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (auth thread): %s\n",event_base_get_method(as->event_base)); + + struct bufferevent *pair[2]; + + bufferevent_pair_new(as->event_base, TURN_BUFFEREVENTS_OPTIONS, pair); + as->in_buf = pair[0]; + as->out_buf = pair[1]; + bufferevent_setcb(as->in_buf, auth_server_receive_message, NULL, NULL, as); + bufferevent_enable(as->in_buf, EV_READ); #if !defined(TURN_NO_HIREDIS) - as->rch = get_redis_async_connection(as->event_base, turn_params.redis_statsdb, 1); + as->rch = get_redis_async_connection(as->event_base, turn_params.redis_statsdb, 1); #endif - struct event_base *eb = as->event_base; + barrier_wait(); - barrier_wait(); - - while(run_auth_server_flag) { - reread_realms(); - update_white_and_black_lists(); - auth_ping(as->rch); - run_events(eb,NULL); -#if defined(DB_TEST) - run_db_test(); -#endif + while(run_auth_server_flag) { + auth_ping(as->rch); + run_events(as->event_base,NULL); + } } return arg; @@ -1781,11 +1810,15 @@ void setup_server(void) pthread_mutex_init(&mutex_bps, NULL); + authserver_number = 1 + (authserver_id)(turn_params.cpus / 2); + + if(authserver_number < MIN_AUTHSERVER_NUMBER) authserver_number = MIN_AUTHSERVER_NUMBER; + #if !defined(TURN_NO_THREAD_BARRIERS) - /* relay threads plus auth thread plus main listener thread */ + /* relay threads plus auth threads plus main listener thread */ /* udp address listener thread(s) will start later */ - barrier_count = turn_params.general_relay_servers_number+2; + barrier_count = turn_params.general_relay_servers_number+authserver_number+1; if(use_cli) { barrier_count += 1; @@ -1828,7 +1861,14 @@ void setup_server(void) } } - setup_auth_server(&authserver); + { + authserver_id sn = 0; + for(sn = 0; sn < authserver_number;++sn) { + authserver[sn].id = sn; + setup_auth_server(&(authserver[sn])); + } + } + if(use_cli) setup_cli_server(); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index aae0e411..21783953 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -108,37 +108,37 @@ void create_default_realm() o_to_realm = ur_string_map_create(turn_free_simple); default_realm_params_ptr = &_default_realm_params; realms = ur_string_map_create(NULL); - ur_string_map_lock(realms); + lock_realms(); default_realm_params_ptr->status.alloc_counters = ur_string_map_create(NULL); - ur_string_map_unlock(realms); + unlock_realms(); } void get_default_realm_options(realm_options_t* ro) { if(ro) { - ur_string_map_lock(realms); + lock_realms(); ns_bcopy(&(default_realm_params_ptr->options),ro,sizeof(realm_options_t)); - ur_string_map_unlock(realms); + unlock_realms(); } } void set_default_realm_name(char *realm) { - ur_string_map_lock(realms); + lock_realms(); ur_string_map_value_type value = (ur_string_map_value_type)default_realm_params_ptr; STRCPY(default_realm_params_ptr->options.name,realm); ur_string_map_put(realms, (ur_string_map_key_type)default_realm_params_ptr->options.name, value); add_to_secrets_list(&realms_list, realm); - ur_string_map_unlock(realms); + unlock_realms(); } realm_params_t* get_realm(char* name) { if(name && name[0]) { - ur_string_map_lock(realms); + lock_realms(); ur_string_map_value_type value = 0; ur_string_map_key_type key = (ur_string_map_key_type)name; if (ur_string_map_get(realms, key, &value)) { - ur_string_map_unlock(realms); + unlock_realms(); return (realm_params_t*)value; } else { realm_params_t *ret = (realm_params_t*)turn_malloc(sizeof(realm_params_t)); @@ -148,7 +148,7 @@ realm_params_t* get_realm(char* name) ur_string_map_put(realms, key, value); ret->status.alloc_counters = ur_string_map_create(NULL); add_to_secrets_list(&realms_list, name); - ur_string_map_unlock(realms); + unlock_realms(); return ret; } } @@ -158,9 +158,9 @@ realm_params_t* get_realm(char* name) int get_realm_data(char* name, realm_params_t* rp) { - ur_string_map_lock(realms); + lock_realms(); ns_bcopy(get_realm(name),rp,sizeof(realm_params_t)); - ur_string_map_unlock(realms); + unlock_realms(); return 0; } @@ -193,20 +193,20 @@ void get_realm_options_by_name(char *realm, realm_options_t* ro) int change_total_quota(char *realm, int value) { int ret = value; - ur_string_map_lock(realms); + lock_realms(); realm_params_t* rp = get_realm(realm); rp->options.perf_options.total_quota = value; - ur_string_map_unlock(realms); + unlock_realms(); return ret; } int change_user_quota(char *realm, int value) { int ret = value; - ur_string_map_lock(realms); + lock_realms(); realm_params_t* rp = get_realm(realm); rp->options.perf_options.user_quota = value; - ur_string_map_unlock(realms); + unlock_realms(); return ret; } @@ -1285,16 +1285,16 @@ void reread_realms(void) { { realm_params_t* defrp = get_realm(NULL); - ur_string_map_lock(realms); + lock_realms(); defrp->options.perf_options.max_bps = turn_params.max_bps; defrp->options.perf_options.total_quota = turn_params.total_quota; defrp->options.perf_options.user_quota = turn_params.user_quota; - ur_string_map_unlock(realms); + unlock_realms(); } - const turn_dbdriver_t * dbd = get_dbdriver(); - if (dbd && dbd->reread_realms) { - (*dbd->reread_realms)(&realms_list); + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->reread_realms) { + (*dbd->reread_realms)(&realms_list); } } From 73f1d2cdb5c0840c4e71bf9caef077ed3b860cfd Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 21 Dec 2014 03:24:00 +0000 Subject: [PATCH 385/805] debug messages removed --- src/apps/relay/netengine.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 49bafc4e..48a930d2 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -382,8 +382,6 @@ void send_auth_message_to_auth_server(struct auth_message *am) authserver_id sn = auth_message_counter++; pthread_mutex_unlock(&auth_message_counter_mutex); - printf("%s: 111.111: %d\n",__FUNCTION__,(int)sn); - struct evbuffer *output = bufferevent_get_output(authserver[sn].out_buf); if(evbuffer_add(output,am,sizeof(struct auth_message))<0) { fprintf(stderr,"%s: Weird buffer error\n",__FUNCTION__); From 9ceb66fc9df849bb1cb9f0a86aeeb7a4f02cf5e5 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 21 Dec 2014 03:36:00 +0000 Subject: [PATCH 386/805] version bumped up --- ChangeLog | 5 +++++ rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/ns_turn_defs.h | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8b07655c..0e8697ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +12/20/2014 Oleg Moskalenko +Version 4.3.3.2 'Tolomei': + - multiple authentication threads; + - database code cleaned; + 12/14/2014 Oleg Moskalenko Version 4.3.2.2 'Tolomei': - Redis read message queue bug fixed; diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 096912ff..8519d74a 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.3.2.2 +TURNVERSION=4.3.3.2 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 3b26a4be..0bb9f188 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.3.2.2 +Version: 4.3.3.2 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,6 +294,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Sat Dec 20 2014 Oleg Moskalenko + - Sync to 4.3.3.2 * Sun Dec 14 2014 Oleg Moskalenko - Sync to 4.3.2.2 * Sat Nov 29 2014 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index bceccf5d..8d3ded1a 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.3.2.2" +#define TURN_SERVER_VERSION "4.3.3.2" #define TURN_SERVER_VERSION_NAME "Tolomei" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From ae71f2b7fd00ab011f2c5c73d1b85299ab9e1208 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 21 Dec 2014 07:21:46 +0000 Subject: [PATCH 387/805] sqlite multithreading --- src/apps/relay/dbdrivers/dbd_sqlite.c | 169 +++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 4 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 9667621a..ff2d6647 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -40,17 +40,73 @@ #include #include -/////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include + +////////////////////////////////////////////////// + +static pthread_mutex_t rc_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t rc_cond = PTHREAD_COND_INITIALIZER; + +static int read_threads = 0; +static int write_level = 0; +static pthread_t write_thread = 0; + +static void sqlite_lock(int write) +{ + pthread_t pths = pthread_self(); + + int can_move = 0; + while (!can_move) { + pthread_mutex_lock(&rc_mutex); + if (write) { + if (((write_thread == 0) && (read_threads < 1)) || (write_thread == pths)) { + can_move = 1; + ++write_level; + write_thread = pths; + } + } else { + if ((!write_thread) || (write_thread == pths)) { + can_move = 1; + ++read_threads; + } + } + if (!can_move) { + pthread_cond_wait(&rc_cond, &rc_mutex); + } + pthread_mutex_unlock(&rc_mutex); + } +} + +void sqlite_unlock(int write) +{ + pthread_mutex_lock(&rc_mutex); + if (write) { + if (!(--write_level)) { + write_thread = 0; + pthread_cond_broadcast(&rc_cond); + } + } else { + if (!(--read_threads)) { + pthread_cond_broadcast(&rc_cond); + } + } + pthread_mutex_unlock(&rc_mutex); +} + +////////////////////////////////////////////////// static int sqlite_init_multithreaded(void) { sqlite3_shutdown(); if (sqlite3_threadsafe() > 0) { - int retCode = sqlite3_config(SQLITE_CONFIG_SERIALIZED); + int retCode = sqlite3_config(SQLITE_CONFIG_MULTITHREAD); if (retCode != SQLITE_OK) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "setting sqlite thread safe mode to serialized failed!!! return code: %d\n", retCode); - return -1; + retCode = sqlite3_config(SQLITE_CONFIG_SERIALIZED); + if (retCode != SQLITE_OK) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "setting sqlite thread safe mode to serialized failed!!! return code: %d\n", retCode); + return -1; + } } } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Your SQLite database is not compiled to be threadsafe.\n"); @@ -155,6 +211,9 @@ static int sqlite_get_auth_secrets(secrets_list_t *sl, u08bits *realm) sqlite3_stmt *st = NULL; int rc = 0; snprintf(statement, sizeof(statement) - 1, "select value from turn_secret where realm='%s'", realm); + + sqlite_lock(0); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { int ctotal = sqlite3_column_count(st); @@ -183,6 +242,8 @@ static int sqlite_get_auth_secrets(secrets_list_t *sl, u08bits *realm) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(0); } return ret; } @@ -196,6 +257,9 @@ static int sqlite_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) sqlite3_stmt *st = NULL; int rc = 0; snprintf(statement, sizeof(statement), "select hmackey from turnusers_lt where name='%s' and realm='%s'", usname, realm); + + sqlite_lock(0); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { int res = sqlite3_step(st); if (res == SQLITE_ROW) { @@ -214,6 +278,8 @@ static int sqlite_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) } sqlite3_finalize(st); + + sqlite_unlock(0); } return ret; } @@ -228,6 +294,9 @@ static int sqlite_get_user_pwd(u08bits *usname, st_password_t pwd) 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) { @@ -245,6 +314,8 @@ static int sqlite_get_user_pwd(u08bits *usname, st_password_t pwd) } sqlite3_finalize(st); + + sqlite_unlock(0); } return ret; } @@ -261,6 +332,8 @@ static int sqlite_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { 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); @@ -283,6 +356,8 @@ static int sqlite_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { } sqlite3_finalize(st); + + sqlite_unlock(0); } return ret; @@ -305,6 +380,8 @@ static int sqlite_list_oauth_keys(void) { sqlite3 *sqliteconnection = get_sqlite_connection(); if(sqliteconnection) { + sqlite_lock(0); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { ret = 0; @@ -341,6 +418,8 @@ static int sqlite_list_oauth_keys(void) { } sqlite3_finalize(st); + + sqlite_unlock(0); } return ret; @@ -358,6 +437,8 @@ static int sqlite_set_user_key(u08bits *usname, u08bits *realm, const char *key) sqlite3 *sqliteconnection = get_sqlite_connection(); if (sqliteconnection) { + sqlite_lock(1); + snprintf(statement, sizeof(statement), "insert or replace into turnusers_lt (realm,name,hmackey) values('%s','%s','%s')", realm, usname, key); if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { @@ -368,6 +449,8 @@ static int sqlite_set_user_key(u08bits *usname, u08bits *realm, const char *key) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(1); } return ret; } @@ -391,6 +474,8 @@ static int sqlite_set_oauth_key(oauth_key_data_raw *key) 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); + sqlite_lock(1); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { sqlite3_step(st); ret = 0; @@ -399,6 +484,8 @@ static int sqlite_set_oauth_key(oauth_key_data_raw *key) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(1); } return ret; } @@ -415,6 +502,9 @@ 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; @@ -423,6 +513,8 @@ static int sqlite_set_user_pwd(u08bits *usname, st_password_t pwd) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(1); } return ret; } @@ -443,6 +535,9 @@ static int sqlite_del_user(u08bits *usname, int is_st, u08bits *realm) } else { snprintf(statement, sizeof(statement), "delete from turnusers_lt where name='%s' and realm='%s'", usname, realm); } + + sqlite_lock(1); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { sqlite3_step(st); ret = 0; @@ -451,6 +546,8 @@ static int sqlite_del_user(u08bits *usname, int is_st, u08bits *realm) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(1); } return ret; } @@ -466,8 +563,11 @@ static int sqlite_del_oauth_key(const u08bits *kid) sqlite3 *sqliteconnection = get_sqlite_connection(); if (sqliteconnection) { + snprintf(statement, sizeof(statement), "delete from oauth_key where kid = '%s'", (const char*) kid); + sqlite_lock(1); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { sqlite3_step(st); ret = 0; @@ -476,6 +576,8 @@ static int sqlite_del_oauth_key(const u08bits *kid) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(1); } return ret; } @@ -499,6 +601,9 @@ static int sqlite_list_users(int is_st, u08bits *realm) } else { snprintf(statement, sizeof(statement), "select name,realm from turnusers_lt order by name"); } + + sqlite_lock(0); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { ret = 0; @@ -529,6 +634,8 @@ static int sqlite_list_users(int is_st, u08bits *realm) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(0); } return ret; } @@ -545,6 +652,9 @@ static int sqlite_show_secret(u08bits *realm) 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) { @@ -559,6 +669,8 @@ static int sqlite_show_secret(u08bits *realm) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(0); } return ret; } @@ -578,6 +690,8 @@ static int sqlite_del_secret(u08bits *secret, u08bits *realm) else snprintf(statement,sizeof(statement),"delete from turn_secret where value='%s' and realm='%s'",secret,realm); + sqlite_lock(1); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { sqlite3_step(st); ret = 0; @@ -586,6 +700,8 @@ static int sqlite_del_secret(u08bits *secret, u08bits *realm) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(1); } return ret; } @@ -600,7 +716,11 @@ static int sqlite_set_secret(u08bits *secret, u08bits *realm) sqlite3 *sqliteconnection = get_sqlite_connection(); if (sqliteconnection) { + snprintf(statement,sizeof(statement),"insert or replace into turn_secret (realm,value) values('%s','%s')",realm,secret); + + sqlite_lock(1); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { sqlite3_step(st); ret = 0; @@ -609,6 +729,8 @@ static int sqlite_set_secret(u08bits *secret, u08bits *realm) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(1); } return ret; } @@ -624,6 +746,9 @@ static int sqlite_add_origin(u08bits *origin, u08bits *realm) sqlite3 *sqliteconnection = get_sqlite_connection(); if(sqliteconnection) { snprintf(statement,sizeof(statement),"insert or replace into turn_origin_to_realm (origin,realm) values('%s','%s')",origin,realm); + + sqlite_lock(1); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { sqlite3_step(st); ret = 0; @@ -632,6 +757,8 @@ static int sqlite_add_origin(u08bits *origin, u08bits *realm) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(1); } return ret; } @@ -647,6 +774,9 @@ static int sqlite_del_origin(u08bits *origin) sqlite3 *sqliteconnection = get_sqlite_connection(); if(sqliteconnection) { snprintf(statement,sizeof(statement),"delete from turn_origin_to_realm where origin='%s'",origin); + + sqlite_lock(1); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { sqlite3_step(st); ret = 0; @@ -655,6 +785,8 @@ static int sqlite_del_origin(u08bits *origin) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(1); } return ret; } @@ -674,6 +806,9 @@ static int sqlite_list_origins(u08bits *realm) } else { snprintf(statement, sizeof(statement), "select origin,realm from turn_origin_to_realm order by origin,realm"); } + + sqlite_lock(0); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { ret = 0; @@ -700,6 +835,8 @@ static int sqlite_list_origins(u08bits *realm) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(0); } return ret; } @@ -716,6 +853,9 @@ static int sqlite_set_realm_option_one(u08bits *realm, unsigned long value, cons if(sqliteconnection) { if(value>0) { snprintf(statement,sizeof(statement),"insert or replace into turn_realm_option (realm,opt,value) values('%s','%s','%lu')",realm,opt,(unsigned long)value); + + sqlite_lock(1); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { sqlite3_step(st); ret = 0; @@ -724,6 +864,8 @@ static int sqlite_set_realm_option_one(u08bits *realm, unsigned long value, cons TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(1); } } return ret; @@ -744,6 +886,9 @@ static int sqlite_list_realm_options(u08bits *realm) } else { snprintf(statement, sizeof(statement), "select realm,opt,value from turn_realm_option order by realm,opt"); } + + sqlite_lock(0); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { ret = 0; @@ -772,6 +917,8 @@ static int sqlite_list_realm_options(u08bits *realm) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(0); } return ret; } @@ -791,6 +938,9 @@ static int sqlite_get_ip_list(const char *kind, ip_range_list_t * list) sqlite3_stmt *st = NULL; int rc = 0; snprintf(statement, sizeof(statement), "select ip_range,realm from %s_peer_ip", kind); + + sqlite_lock(0); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { ret = 0; @@ -818,6 +968,8 @@ static int sqlite_get_ip_list(const char *kind, ip_range_list_t * list) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(0); } return ret; } @@ -831,6 +983,9 @@ static void sqlite_reread_realms(secrets_list_t * realms_list) int rc = 0; { snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm"); + + sqlite_lock(0); + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { ur_string_map *o_to_realm_new = ur_string_map_create(turn_free_simple); @@ -864,6 +1019,8 @@ static void sqlite_reread_realms(secrets_list_t * realms_list) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(0); } { @@ -896,6 +1053,8 @@ static void sqlite_reread_realms(secrets_list_t * realms_list) } } + sqlite_lock(0); + snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option"); if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { @@ -933,6 +1092,8 @@ static void sqlite_reread_realms(secrets_list_t * realms_list) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving SQLite DB information: %s\n", errmsg); } sqlite3_finalize(st); + + sqlite_unlock(0); } } } From 626a6b69d7d8827dfacc4c9eaf605e40a4c4158e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 21 Dec 2014 10:48:53 +0000 Subject: [PATCH 388/805] minor fixes --- src/apps/relay/dbdrivers/dbd_sqlite.c | 2 +- src/apps/relay/mainrelay.c | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index ff2d6647..dff544d8 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -77,7 +77,7 @@ static void sqlite_lock(int write) } } -void sqlite_unlock(int write) +static void sqlite_unlock(int write) { pthread_mutex_lock(&rc_mutex); if (write) { diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 43a739e5..26629557 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -2334,14 +2334,14 @@ static int pem_password_func(char *buf, int size, int rwflag, void *password) #if ALPN_SUPPORTED -static int ServerALPNCallback(SSL *s, +static int ServerALPNCallback(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { - UNUSED_ARG(s); + UNUSED_ARG(ssl); UNUSED_ARG(arg); unsigned char sa_len = (unsigned char)strlen(STUN_ALPN); @@ -2358,21 +2358,26 @@ static int ServerALPNCallback(SSL *s, if((!turn_params.no_stun) && (current_len == sa_len) && (memcmp(ptr+1,STUN_ALPN,sa_len)==0)) { *out = ptr+1; *outlen = sa_len; + SSL_set_app_data(ssl,STUN_ALPN); return SSL_TLSEXT_ERR_OK; } if((!turn_params.stun_only) && (current_len == ta_len) && (memcmp(ptr+1,TURN_ALPN,ta_len)==0)) { *out = ptr+1; *outlen = ta_len; + SSL_set_app_data(ssl,TURN_ALPN); return SSL_TLSEXT_ERR_OK; } if((current_len == ha_len) && (memcmp(ptr+1,HTTP_ALPN,ha_len)==0)) { + *out = ptr+1; + *outlen = ta_len; + SSL_set_app_data(ssl,HTTP_ALPN); found_http = 1; } ptr += 1 + current_len; } if(found_http) - return SSL_TLSEXT_ERR_NOACK; + return SSL_TLSEXT_ERR_OK; return SSL_TLSEXT_ERR_NOACK; //??? } From 294e0bfc1d264e91081d4caebf53b38d28826c58 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 21 Dec 2014 18:28:46 +0000 Subject: [PATCH 389/805] auth thread fix --- src/apps/relay/netengine.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 48a930d2..5edaa0a7 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1721,6 +1721,9 @@ static void* run_auth_server_thread(void *arg) if(id == 0) { + reread_realms(); + update_white_and_black_lists(); + barrier_wait(); while(run_auth_server_flag) { From c2021f2c8734096c8db8476c72a7c6770534f34b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 24 Dec 2014 05:24:09 +0000 Subject: [PATCH 390/805] minor fix --- src/apps/relay/netengine.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 5edaa0a7..7bd1d602 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1727,12 +1727,12 @@ static void* run_auth_server_thread(void *arg) barrier_wait(); while(run_auth_server_flag) { - reread_realms(); - update_white_and_black_lists(); #if defined(DB_TEST) run_db_test(); #endif sleep(5); + reread_realms(); + update_white_and_black_lists(); } } else { From d08bc700c985ea27ee9908cc791d8110086f6b77 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 24 Dec 2014 08:08:36 +0000 Subject: [PATCH 391/805] version number fixed --- ChangeLog | 4 ++-- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 6 +++--- src/ns_turn_defs.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0e8697ff..60c00cd8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ -12/20/2014 Oleg Moskalenko -Version 4.3.3.2 'Tolomei': +12/24/2014 Oleg Moskalenko +Version 4.3.3.1 'Tolomei': - multiple authentication threads; - database code cleaned; diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 8519d74a..ffff3cb7 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.3.3.2 +TURNVERSION=4.3.3.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 0bb9f188..f83d4c98 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.3.3.2 +Version: 4.3.3.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,8 +294,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Sat Dec 20 2014 Oleg Moskalenko - - Sync to 4.3.3.2 +* Wed Dec 24 2014 Oleg Moskalenko + - Sync to 4.3.3.1 * Sun Dec 14 2014 Oleg Moskalenko - Sync to 4.3.2.2 * Sat Nov 29 2014 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 8d3ded1a..5f591681 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.3.3.2" +#define TURN_SERVER_VERSION "4.3.3.1" #define TURN_SERVER_VERSION_NAME "Tolomei" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 83a51829418be33884456f5a3071c0351e3693b7 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 1 Jan 2015 03:22:26 +0000 Subject: [PATCH 392/805] working on https server --- README.turnadmin | 2 +- README.turnserver | 2 +- README.turnutils | 2 +- src/apps/relay/http_server.c | 6 +- src/apps/relay/netengine.c | 1 + src/apps/relay/turncli.c | 104 +++++++++++++++++++++++++++++++++-- src/apps/relay/turncli.h | 5 ++ src/server/ns_turn_ioalib.h | 3 +- src/server/ns_turn_server.c | 16 ++++-- src/server/ns_turn_server.h | 3 + 10 files changed, 124 insertions(+), 20 deletions(-) diff --git a/README.turnadmin b/README.turnadmin index 589e531a..3070d6c9 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -233,7 +233,7 @@ to see the man page. Po-sheng Lin - Peter Dunkley + Peter Dunkley Mutsutoshi Yoshimoto diff --git a/README.turnserver b/README.turnserver index 0c686290..e3cebab8 100644 --- a/README.turnserver +++ b/README.turnserver @@ -941,7 +941,7 @@ https://groups.google.com/forum/?fromgroups=#!forum/turn-server-project-rfc5766- Po-sheng Lin - Peter Dunkley + Peter Dunkley Mutsutoshi Yoshimoto diff --git a/README.turnutils b/README.turnutils index dc57ad40..13142195 100644 --- a/README.turnutils +++ b/README.turnutils @@ -329,7 +329,7 @@ SEE ALSO Po-sheng Lin - Peter Dunkley + Peter Dunkley Mutsutoshi Yoshimoto diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index 56f23dc7..a0643d7a 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -30,7 +30,7 @@ #include "ns_ioalib_impl.h" -void write_http_echo(ioa_socket_handle s) +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); @@ -51,8 +51,6 @@ 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(ioa_socket_handle s) { write_http_echo(s); } diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 7bd1d602..e74d7866 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1649,6 +1649,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); diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index 4f86d916..eef8212a 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -1218,15 +1218,38 @@ static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd void setup_cli_thread(void) { cliserver.event_base = turn_event_base_new(); + super_memory_t* sm = new_super_memory_region(); + cliserver.e = create_ioa_engine(sm, cliserver.event_base, turn_params.listener.tp, turn_params.relay_ifname, turn_params.relays_number, turn_params.relay_addrs, + turn_params.default_relays, turn_params.verbose + #if !defined(TURN_NO_HIREDIS) + ,turn_params.redis_statsdb + #endif + ); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (cli thread): %s\n",event_base_get_method(cliserver.event_base)); - struct bufferevent *pair[2]; + { + struct bufferevent *pair[2]; - bufferevent_pair_new(cliserver.event_base, TURN_BUFFEREVENTS_OPTIONS, pair); - cliserver.in_buf = pair[0]; - cliserver.out_buf = pair[1]; - bufferevent_setcb(cliserver.in_buf, cli_server_receive_message, NULL, NULL, &cliserver); - bufferevent_enable(cliserver.in_buf, EV_READ); + bufferevent_pair_new(cliserver.event_base, TURN_BUFFEREVENTS_OPTIONS, pair); + + cliserver.in_buf = pair[0]; + cliserver.out_buf = pair[1]; + + bufferevent_setcb(cliserver.in_buf, cli_server_receive_message, NULL, NULL, &cliserver); + bufferevent_enable(cliserver.in_buf, EV_READ); + } + + { + struct bufferevent *pair[2]; + + bufferevent_pair_new(cliserver.event_base, TURN_BUFFEREVENTS_OPTIONS, pair); + + cliserver.https_in_buf = pair[0]; + cliserver.https_out_buf = pair[1]; + + bufferevent_setcb(cliserver.https_in_buf, https_cli_server_receive_message, NULL, NULL, &cliserver); + bufferevent_enable(cliserver.https_in_buf, EV_READ); + } if(!cli_addr_set) { if(make_ioa_addr((const u08bits*)CLI_DEFAULT_IP,0,&cli_addr)<0) { @@ -1330,4 +1353,73 @@ int send_turn_session_info(struct turn_session_info* tsi) return ret; } +/////////// HTTPS ///////////// + +static void write_https_echo(ioa_socket_handle s) +{ + if(s && !ioa_socket_tobeclosed(s)) { + SOCKET_APP_TYPE sat = get_ioa_socket_app_type(s); + if(sat == HTTPS_CLIENT_SOCKET) { + ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(s->e); + size_t len_http = ioa_network_buffer_get_size(nbh_http); + u08bits *data = ioa_network_buffer_data(nbh_http); + char data_http[1025]; + char content_http[1025]; + const char* title = "HTTPS TURN Server"; + snprintf(content_http,sizeof(content_http)-1,"\r\n\r\n \r\n %s\r\n \r\n \r\n %s\r\n \r\n\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); + len_http = strlen(data_http); + ns_bcopy(data_http,data,len_http); + ioa_network_buffer_set_size(nbh_http,len_http); + send_data_from_ioa_socket_nbh(s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE); + } + } +} + +static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { + //TODO + UNUSED_ARG(nbh); + write_https_echo(s); +} + +static void https_input_handler(ioa_socket_handle s, int event_type, ioa_net_data *data, void *arg, int can_resume) { + + UNUSED_ARG(arg); + UNUSED_ARG(s); + UNUSED_ARG(event_type); + UNUSED_ARG(can_resume); + + handle_https(s,data->nbh); + + ioa_network_buffer_delete(cliserver.e, data->nbh); + data->nbh = NULL; +} + +void https_cli_server_receive_message(struct bufferevent *bev, void *ptr) +{ + UNUSED_ARG(ptr); + + ioa_socket_handle s= NULL; + int n = 0; + struct evbuffer *input = bufferevent_get_input(bev); + + while ((n = evbuffer_remove(input, &s, sizeof(s))) > 0) { + if (n != sizeof(s)) { + fprintf(stderr,"%s: Weird HTTPS CLI buffer error: size=%d\n",__FUNCTION__,n); + continue; + } + + register_callback_on_ioa_socket(cliserver.e, s, IOA_EV_READ, https_input_handler, NULL, 0); + + handle_https(s,NULL); + } +} + +void send_https_socket(ioa_socket_handle s) { + struct evbuffer *output = bufferevent_get_output(cliserver.https_out_buf); + if(output) { + evbuffer_add(output,&s,sizeof(s)); + } +} + /////////////////////////////// diff --git a/src/apps/relay/turncli.h b/src/apps/relay/turncli.h index 6a432441..aef0e0c0 100644 --- a/src/apps/relay/turncli.h +++ b/src/apps/relay/turncli.h @@ -54,10 +54,13 @@ extern "C" { struct cli_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; }; @@ -86,8 +89,10 @@ extern int cli_max_output_sessions; void setup_cli_thread(void); void cli_server_receive_message(struct bufferevent *bev, void *ptr); +void https_cli_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); //////////////////////////////////////////// diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 7afb6ae3..c0e5797d 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -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(ioa_socket_handle s); /////////////////////////////////////// diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index cef17b66..b8cc9720 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4442,12 +4442,11 @@ 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); + handle_http(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, @@ -4542,11 +4541,16 @@ static int read_client_connection(turn_turnserver *server, 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) { + ioa_socket_handle new_s = detach_ioa_socket(ss->client_socket); + if(new_s) { + server->send_https_socket(new_s); + } + } } 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); + handle_http(ss->client_socket); } return 0; } @@ -4802,6 +4806,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 +4832,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; diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index 3506e617..75380802 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -96,6 +96,7 @@ typedef int (*check_new_allocation_quota_cb)(u08bits *username, int oauth, u08bi 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); From 520c629b343fa14996238830be71432030767b43 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 1 Jan 2015 05:22:16 +0000 Subject: [PATCH 393/805] working on https --- src/apps/relay/turncli.c | 11 ++++++++++- src/server/ns_turn_server.c | 9 +++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index eef8212a..c88b509d 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -1377,8 +1377,17 @@ static void write_https_echo(ioa_socket_handle s) } static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { + //TODO - UNUSED_ARG(nbh); + + if(turn_params.verbose) { + if(nbh) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection input: %s\n", __FUNCTION__, (char*)ioa_network_buffer_data(nbh)); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection initial input\n", __FUNCTION__); + } + } + write_https_echo(s); } diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index b8cc9720..abf2909e 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4441,7 +4441,10 @@ 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)); + 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(ss->client_socket); } else if(sat == HTTPS_CLIENT_SOCKET) { @@ -4549,7 +4552,9 @@ static int read_client_connection(turn_turnserver *server, } } 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)); + 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(ss->client_socket); } return 0; From adcd1f428a33e95a09af7f2c05f7661693bc567d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 1 Jan 2015 06:06:43 +0000 Subject: [PATCH 394/805] working on https --- src/apps/relay/netengine.c | 1 - src/apps/relay/turncli.c | 86 +------------------------------------ src/apps/relay/turncli.h | 4 -- src/server/ns_turn_server.c | 18 +------- src/server/ns_turn_server.h | 3 -- 5 files changed, 3 insertions(+), 109 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index e74d7866..7bd1d602 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1649,7 +1649,6 @@ 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); diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index c88b509d..e4fe656e 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -1239,18 +1239,6 @@ void setup_cli_thread(void) bufferevent_enable(cliserver.in_buf, EV_READ); } - { - struct bufferevent *pair[2]; - - bufferevent_pair_new(cliserver.event_base, TURN_BUFFEREVENTS_OPTIONS, pair); - - cliserver.https_in_buf = pair[0]; - cliserver.https_out_buf = pair[1]; - - bufferevent_setcb(cliserver.https_in_buf, https_cli_server_receive_message, NULL, NULL, &cliserver); - bufferevent_enable(cliserver.https_in_buf, EV_READ); - } - if(!cli_addr_set) { if(make_ioa_addr((const u08bits*)CLI_DEFAULT_IP,0,&cli_addr)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot set cli address %s\n",CLI_DEFAULT_IP); @@ -1355,80 +1343,8 @@ int send_turn_session_info(struct turn_session_info* tsi) /////////// HTTPS ///////////// -static void write_https_echo(ioa_socket_handle s) -{ - if(s && !ioa_socket_tobeclosed(s)) { - SOCKET_APP_TYPE sat = get_ioa_socket_app_type(s); - if(sat == HTTPS_CLIENT_SOCKET) { - ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(s->e); - size_t len_http = ioa_network_buffer_get_size(nbh_http); - u08bits *data = ioa_network_buffer_data(nbh_http); - char data_http[1025]; - char content_http[1025]; - const char* title = "HTTPS TURN Server"; - snprintf(content_http,sizeof(content_http)-1,"\r\n\r\n \r\n %s\r\n \r\n \r\n %s\r\n \r\n\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); - len_http = strlen(data_http); - ns_bcopy(data_http,data,len_http); - ioa_network_buffer_set_size(nbh_http,len_http); - send_data_from_ioa_socket_nbh(s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE); - } - } -} +//https://github.com/ppelleti/https-example -static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { - //TODO - - if(turn_params.verbose) { - if(nbh) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection input: %s\n", __FUNCTION__, (char*)ioa_network_buffer_data(nbh)); - } else { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection initial input\n", __FUNCTION__); - } - } - - write_https_echo(s); -} - -static void https_input_handler(ioa_socket_handle s, int event_type, ioa_net_data *data, void *arg, int can_resume) { - - UNUSED_ARG(arg); - UNUSED_ARG(s); - UNUSED_ARG(event_type); - UNUSED_ARG(can_resume); - - handle_https(s,data->nbh); - - ioa_network_buffer_delete(cliserver.e, data->nbh); - data->nbh = NULL; -} - -void https_cli_server_receive_message(struct bufferevent *bev, void *ptr) -{ - UNUSED_ARG(ptr); - - ioa_socket_handle s= NULL; - int n = 0; - struct evbuffer *input = bufferevent_get_input(bev); - - while ((n = evbuffer_remove(input, &s, sizeof(s))) > 0) { - if (n != sizeof(s)) { - fprintf(stderr,"%s: Weird HTTPS CLI buffer error: size=%d\n",__FUNCTION__,n); - continue; - } - - register_callback_on_ioa_socket(cliserver.e, s, IOA_EV_READ, https_input_handler, NULL, 0); - - handle_https(s,NULL); - } -} - -void send_https_socket(ioa_socket_handle s) { - struct evbuffer *output = bufferevent_get_output(cliserver.https_out_buf); - if(output) { - evbuffer_add(output,&s,sizeof(s)); - } -} /////////////////////////////// diff --git a/src/apps/relay/turncli.h b/src/apps/relay/turncli.h index aef0e0c0..8c4490c6 100644 --- a/src/apps/relay/turncli.h +++ b/src/apps/relay/turncli.h @@ -59,8 +59,6 @@ struct cli_server { 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; }; @@ -89,10 +87,8 @@ extern int cli_max_output_sessions; void setup_cli_thread(void); void cli_server_receive_message(struct bufferevent *bev, void *ptr); -void https_cli_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); //////////////////////////////////////////// diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index abf2909e..0823c324 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4164,8 +4164,6 @@ static void client_to_be_allocated_timeout_handler(ioa_engine_handle e, if(!s || ioa_socket_tobeclosed(s)) { to_close = 1; - } else if(get_ioa_socket_app_type(s) == HTTPS_CLIENT_SOCKET) { - ; } else { ioa_socket_handle rs4 = ss->alloc.relay_sessions[ALLOC_IPV4_INDEX].s; ioa_socket_handle rs6 = ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].s; @@ -4439,7 +4437,7 @@ static int read_client_connection(turn_turnserver *server, SOCKET_APP_TYPE sat = get_ioa_socket_app_type(ss->client_socket); int is_padding_mandatory = ((st == TCP_SOCKET)||(st==TLS_SOCKET)||(st==TENTATIVE_TCP_SOCKET)); - if(sat == HTTP_CLIENT_SOCKET) { + if((sat == HTTP_CLIENT_SOCKET)||(sat == HTTPS_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)); @@ -4447,10 +4445,6 @@ static int read_client_connection(turn_turnserver *server, handle_http(ss->client_socket); - } else if(sat == HTTPS_CLIENT_SOCKET) { - - //??? - } else if (stun_is_channel_message_str(ioa_network_buffer_data(in_buffer->nbh), &blen, &chnum, @@ -4544,19 +4538,13 @@ static int read_client_connection(turn_turnserver *server, 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)); - if(server->send_https_socket) { - ioa_socket_handle new_s = detach_ioa_socket(ss->client_socket); - if(new_s) { - server->send_https_socket(new_s); - } - } } else { set_ioa_socket_app_type(ss->client_socket,HTTP_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(ss->client_socket); } + handle_http(ss->client_socket); return 0; } } @@ -4811,7 +4799,6 @@ 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) { @@ -4837,7 +4824,6 @@ 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; diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index 75380802..3506e617 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -96,7 +96,6 @@ typedef int (*check_new_allocation_quota_cb)(u08bits *username, int oauth, u08bi 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); @@ -132,7 +131,6 @@ 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; @@ -201,7 +199,6 @@ 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); From 79094f06346991e1439d005dc22bd985ed5f2bfd Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 1 Jan 2015 19:37:12 +0000 Subject: [PATCH 395/805] working on https --- ChangeLog | 4 ++++ rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/apps/relay/mainrelay.c | 4 +++- src/apps/relay/mainrelay.h | 10 ++++++++++ src/apps/relay/turncli.c | 36 +++++++++++++++++++++++++++++------- src/apps/relay/turncli.h | 5 ++++- src/ns_turn_defs.h | 2 +- 8 files changed, 55 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 60c00cd8..da5dcfff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +1/1/2015 Oleg Moskalenko +Version 4.3.4.1 'Tolomei': + - https admin server; + 12/24/2014 Oleg Moskalenko Version 4.3.3.1 'Tolomei': - multiple authentication threads; diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index ffff3cb7..514e69ef 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.3.3.1 +TURNVERSION=4.3.4.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index f83d4c98..923228ec 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.3.3.1 +Version: 4.3.4.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,6 +294,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Thu Jan 24 2015 Oleg Moskalenko + - Sync to 4.3.4.1 * Wed Dec 24 2014 Oleg Moskalenko - Sync to 4.3.3.1 * Sun Dec 14 2014 Oleg Moskalenko diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 26629557..ad00ebaf 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -122,7 +122,9 @@ LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,0,"", ///////////// Users DB ////////////// { (TURN_USERDB_TYPE)0, {"\0"}, {0,NULL,NULL, {NULL,0}} }, ///////////// CPUs ////////////////// -DEFAULT_CPUS_NUMBER +DEFAULT_CPUS_NUMBER, +///////////// HTTPS Admin Server //// +1,DEFAULT_HTTPS_ADMIN_PORT,DEFAULT_HTTPS_ADMIN_ADDR,"123" }; //////////////// OpenSSL Init ////////////////////// diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index be020acb..bdffed94 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -102,6 +102,9 @@ extern "C" { #define DEFAULT_CPUS_NUMBER (2) +#define DEFAULT_HTTPS_ADMIN_PORT (4433) +#define DEFAULT_HTTPS_ADMIN_ADDR ("0.0.0.0") + /////////// TYPES /////////////////////////////////// enum _DH_KEY_SIZE { @@ -310,6 +313,13 @@ typedef struct _turn_params_ { unsigned long cpus; +/////// HTTPS Admin server ////// + + int use_https_admin_server; + int https_admin_server_port; + char https_admin_server_addr[129]; + char https_admin_server_pwd[129]; + } turn_params_t; extern turn_params_t turn_params; diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index e4fe656e..9eb3e512 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -1217,16 +1217,38 @@ static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd void setup_cli_thread(void) { + ns_bzero(&cliserver,sizeof(cliserver)); cliserver.event_base = turn_event_base_new(); - super_memory_t* sm = new_super_memory_region(); - cliserver.e = create_ioa_engine(sm, cliserver.event_base, turn_params.listener.tp, turn_params.relay_ifname, turn_params.relays_number, turn_params.relay_addrs, - turn_params.default_relays, turn_params.verbose - #if !defined(TURN_NO_HIREDIS) - ,turn_params.redis_statsdb - #endif - ); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (cli thread): %s\n",event_base_get_method(cliserver.event_base)); + if (turn_params.use_https_admin_server + && turn_params.https_admin_server_pwd[0]) { + +#if TLSv1_2_SUPPORTED + if (turn_params.tls_ctx_v1_2) { + cliserver.ctx = turn_params.tls_ctx_v1_2; + } +#endif + +#if TLSv1_1_SUPPORTED + if (!cliserver.ctx && turn_params.tls_ctx_v1_1) { + cliserver.ctx = turn_params.tls_ctx_v1_1; + } +#endif + + if (!cliserver.ctx && turn_params.tls_ctx_v1_0) { + cliserver.ctx = turn_params.tls_ctx_v1_0; + } + + if (!cliserver.ctx && turn_params.tls_ctx_ssl23) { + cliserver.ctx = turn_params.tls_ctx_ssl23; + } + } + + if(!cliserver.ctx) { + turn_params.use_https_admin_server = 0; + } + { struct bufferevent *pair[2]; diff --git a/src/apps/relay/turncli.h b/src/apps/relay/turncli.h index 8c4490c6..8ca61b1c 100644 --- a/src/apps/relay/turncli.h +++ b/src/apps/relay/turncli.h @@ -38,6 +38,7 @@ #include #include +#include #include "ns_turn_utils.h" #include "ns_turn_maps.h" @@ -54,13 +55,15 @@ extern "C" { struct cli_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; ur_map *sessions; pthread_t thr; + //// HTTPS interface //// + SSL_CTX *ctx; + struct evhttp *https; }; /////////////////////////////////////////// diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 5f591681..4e641751 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.3.3.1" +#define TURN_SERVER_VERSION "4.3.4.1" #define TURN_SERVER_VERSION_NAME "Tolomei" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From f10d40d3303d792be4a73a6ae3e5830d8dcfbe6a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 2 Jan 2015 06:26:09 +0000 Subject: [PATCH 396/805] working on https --- src/apps/relay/mainrelay.c | 4 +- src/apps/relay/mainrelay.h | 10 --- src/apps/relay/netengine.c | 1 + src/apps/relay/turncli.c | 122 +++++++++++++++++++++++++++--------- src/apps/relay/turncli.h | 9 +-- src/server/ns_turn_server.c | 18 +++++- src/server/ns_turn_server.h | 3 + 7 files changed, 118 insertions(+), 49 deletions(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index ad00ebaf..26629557 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -122,9 +122,7 @@ LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,0,"", ///////////// Users DB ////////////// { (TURN_USERDB_TYPE)0, {"\0"}, {0,NULL,NULL, {NULL,0}} }, ///////////// CPUs ////////////////// -DEFAULT_CPUS_NUMBER, -///////////// HTTPS Admin Server //// -1,DEFAULT_HTTPS_ADMIN_PORT,DEFAULT_HTTPS_ADMIN_ADDR,"123" +DEFAULT_CPUS_NUMBER }; //////////////// OpenSSL Init ////////////////////// diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index bdffed94..be020acb 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -102,9 +102,6 @@ extern "C" { #define DEFAULT_CPUS_NUMBER (2) -#define DEFAULT_HTTPS_ADMIN_PORT (4433) -#define DEFAULT_HTTPS_ADMIN_ADDR ("0.0.0.0") - /////////// TYPES /////////////////////////////////// enum _DH_KEY_SIZE { @@ -313,13 +310,6 @@ typedef struct _turn_params_ { unsigned long cpus; -/////// HTTPS Admin server ////// - - int use_https_admin_server; - int https_admin_server_port; - char https_admin_server_addr[129]; - char https_admin_server_pwd[129]; - } turn_params_t; extern turn_params_t turn_params; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 7bd1d602..e74d7866 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1649,6 +1649,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); diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index 9eb3e512..c88b509d 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -1217,38 +1217,16 @@ static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd void setup_cli_thread(void) { - ns_bzero(&cliserver,sizeof(cliserver)); cliserver.event_base = turn_event_base_new(); + super_memory_t* sm = new_super_memory_region(); + cliserver.e = create_ioa_engine(sm, cliserver.event_base, turn_params.listener.tp, turn_params.relay_ifname, turn_params.relays_number, turn_params.relay_addrs, + turn_params.default_relays, turn_params.verbose + #if !defined(TURN_NO_HIREDIS) + ,turn_params.redis_statsdb + #endif + ); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (cli thread): %s\n",event_base_get_method(cliserver.event_base)); - if (turn_params.use_https_admin_server - && turn_params.https_admin_server_pwd[0]) { - -#if TLSv1_2_SUPPORTED - if (turn_params.tls_ctx_v1_2) { - cliserver.ctx = turn_params.tls_ctx_v1_2; - } -#endif - -#if TLSv1_1_SUPPORTED - if (!cliserver.ctx && turn_params.tls_ctx_v1_1) { - cliserver.ctx = turn_params.tls_ctx_v1_1; - } -#endif - - if (!cliserver.ctx && turn_params.tls_ctx_v1_0) { - cliserver.ctx = turn_params.tls_ctx_v1_0; - } - - if (!cliserver.ctx && turn_params.tls_ctx_ssl23) { - cliserver.ctx = turn_params.tls_ctx_ssl23; - } - } - - if(!cliserver.ctx) { - turn_params.use_https_admin_server = 0; - } - { struct bufferevent *pair[2]; @@ -1261,6 +1239,18 @@ void setup_cli_thread(void) bufferevent_enable(cliserver.in_buf, EV_READ); } + { + struct bufferevent *pair[2]; + + bufferevent_pair_new(cliserver.event_base, TURN_BUFFEREVENTS_OPTIONS, pair); + + cliserver.https_in_buf = pair[0]; + cliserver.https_out_buf = pair[1]; + + bufferevent_setcb(cliserver.https_in_buf, https_cli_server_receive_message, NULL, NULL, &cliserver); + bufferevent_enable(cliserver.https_in_buf, EV_READ); + } + if(!cli_addr_set) { if(make_ioa_addr((const u08bits*)CLI_DEFAULT_IP,0,&cli_addr)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot set cli address %s\n",CLI_DEFAULT_IP); @@ -1365,8 +1355,80 @@ int send_turn_session_info(struct turn_session_info* tsi) /////////// HTTPS ///////////// -//https://github.com/ppelleti/https-example +static void write_https_echo(ioa_socket_handle s) +{ + if(s && !ioa_socket_tobeclosed(s)) { + SOCKET_APP_TYPE sat = get_ioa_socket_app_type(s); + if(sat == HTTPS_CLIENT_SOCKET) { + ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(s->e); + size_t len_http = ioa_network_buffer_get_size(nbh_http); + u08bits *data = ioa_network_buffer_data(nbh_http); + char data_http[1025]; + char content_http[1025]; + const char* title = "HTTPS TURN Server"; + snprintf(content_http,sizeof(content_http)-1,"\r\n\r\n \r\n %s\r\n \r\n \r\n %s\r\n \r\n\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); + len_http = strlen(data_http); + ns_bcopy(data_http,data,len_http); + ioa_network_buffer_set_size(nbh_http,len_http); + send_data_from_ioa_socket_nbh(s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE); + } + } +} +static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { + //TODO + + if(turn_params.verbose) { + if(nbh) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection input: %s\n", __FUNCTION__, (char*)ioa_network_buffer_data(nbh)); + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection initial input\n", __FUNCTION__); + } + } + + write_https_echo(s); +} + +static void https_input_handler(ioa_socket_handle s, int event_type, ioa_net_data *data, void *arg, int can_resume) { + + UNUSED_ARG(arg); + UNUSED_ARG(s); + UNUSED_ARG(event_type); + UNUSED_ARG(can_resume); + + handle_https(s,data->nbh); + + ioa_network_buffer_delete(cliserver.e, data->nbh); + data->nbh = NULL; +} + +void https_cli_server_receive_message(struct bufferevent *bev, void *ptr) +{ + UNUSED_ARG(ptr); + + ioa_socket_handle s= NULL; + int n = 0; + struct evbuffer *input = bufferevent_get_input(bev); + + while ((n = evbuffer_remove(input, &s, sizeof(s))) > 0) { + if (n != sizeof(s)) { + fprintf(stderr,"%s: Weird HTTPS CLI buffer error: size=%d\n",__FUNCTION__,n); + continue; + } + + register_callback_on_ioa_socket(cliserver.e, s, IOA_EV_READ, https_input_handler, NULL, 0); + + handle_https(s,NULL); + } +} + +void send_https_socket(ioa_socket_handle s) { + struct evbuffer *output = bufferevent_get_output(cliserver.https_out_buf); + if(output) { + evbuffer_add(output,&s,sizeof(s)); + } +} /////////////////////////////// diff --git a/src/apps/relay/turncli.h b/src/apps/relay/turncli.h index 8ca61b1c..aef0e0c0 100644 --- a/src/apps/relay/turncli.h +++ b/src/apps/relay/turncli.h @@ -38,7 +38,6 @@ #include #include -#include #include "ns_turn_utils.h" #include "ns_turn_maps.h" @@ -55,15 +54,15 @@ extern "C" { struct cli_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; - //// HTTPS interface //// - SSL_CTX *ctx; - struct evhttp *https; }; /////////////////////////////////////////// @@ -90,8 +89,10 @@ extern int cli_max_output_sessions; void setup_cli_thread(void); void cli_server_receive_message(struct bufferevent *bev, void *ptr); +void https_cli_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); //////////////////////////////////////////// diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 0823c324..abf2909e 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4164,6 +4164,8 @@ static void client_to_be_allocated_timeout_handler(ioa_engine_handle e, if(!s || ioa_socket_tobeclosed(s)) { to_close = 1; + } else if(get_ioa_socket_app_type(s) == HTTPS_CLIENT_SOCKET) { + ; } else { ioa_socket_handle rs4 = ss->alloc.relay_sessions[ALLOC_IPV4_INDEX].s; ioa_socket_handle rs6 = ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].s; @@ -4437,7 +4439,7 @@ static int read_client_connection(turn_turnserver *server, SOCKET_APP_TYPE sat = get_ioa_socket_app_type(ss->client_socket); int is_padding_mandatory = ((st == TCP_SOCKET)||(st==TLS_SOCKET)||(st==TENTATIVE_TCP_SOCKET)); - if((sat == HTTP_CLIENT_SOCKET)||(sat == HTTPS_CLIENT_SOCKET)) { + if(sat == HTTP_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)); @@ -4445,6 +4447,10 @@ static int read_client_connection(turn_turnserver *server, handle_http(ss->client_socket); + } else if(sat == HTTPS_CLIENT_SOCKET) { + + //??? + } else if (stun_is_channel_message_str(ioa_network_buffer_data(in_buffer->nbh), &blen, &chnum, @@ -4538,13 +4544,19 @@ static int read_client_connection(turn_turnserver *server, 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)); + if(server->send_https_socket) { + ioa_socket_handle new_s = detach_ioa_socket(ss->client_socket); + if(new_s) { + server->send_https_socket(new_s); + } + } } else { set_ioa_socket_app_type(ss->client_socket,HTTP_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(ss->client_socket); } - handle_http(ss->client_socket); return 0; } } @@ -4799,6 +4811,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) { @@ -4824,6 +4837,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; diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index 3506e617..75380802 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -96,6 +96,7 @@ typedef int (*check_new_allocation_quota_cb)(u08bits *username, int oauth, u08bi 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); From d36d3e5336a96eeb69351210e33f994fc0d037cc Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 2 Jan 2015 07:32:25 +0000 Subject: [PATCH 397/805] working on https --- src/apps/relay/ns_ioalib_engine_impl.c | 15 +++++++++++++++ src/server/ns_turn_server.c | 3 +++ 2 files changed, 18 insertions(+) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index f8c71bcc..1d9111ca 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -2599,6 +2599,13 @@ 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->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_type(s)); + IOA_CLOSE_SOCKET(s); + return; + } + switch (s->sat){ case TCP_CLIENT_DATA_SOCKET: case TCP_RELAY_DATA_SOCKET: @@ -2772,6 +2779,14 @@ static void eventcb_bev(struct bufferevent *bev, short events, void *arg) s->tobeclosed = 1; + 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_type(s),sraddr); + IOA_CLOSE_SOCKET(s); + return; + } + switch (s->sat){ case TCP_CLIENT_DATA_SOCKET: case TCP_RELAY_DATA_SOCKET: diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index abf2909e..605b6605 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4545,10 +4545,13 @@ static int read_client_connection(turn_turnserver *server, 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)); 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_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_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); From 04f119e2e130666a452e9f8e20f56fdc25e94c6b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 4 Jan 2015 02:59:06 +0000 Subject: [PATCH 398/805] man pages updated --- man/man1/turnadmin.1 | 4 ++-- man/man1/turnserver.1 | 4 ++-- man/man1/turnutils.1 | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index d14cdfa9..ed57c9db 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "14 December 2014" "" "" +.TH TURN 1 "03 January 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage @@ -322,7 +322,7 @@ Vladimir Tsanev .PP Po\-sheng Lin .PP -Peter Dunkley +Peter Dunkley .PP Mutsutoshi Yoshimoto .PP diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 2146995d..7dfd83fd 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "14 December 2014" "" "" +.TH TURN 1 "03 January 2015" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -1191,7 +1191,7 @@ Vladimir Tsanev .PP Po\-sheng Lin .PP -Peter Dunkley +Peter Dunkley .PP Mutsutoshi Yoshimoto .PP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 867fc9ca..f5c4124e 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "14 December 2014" "" "" +.TH TURN 1 "03 January 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -449,7 +449,7 @@ Vladimir Tsanev .PP Po\-sheng Lin .PP -Peter Dunkley +Peter Dunkley .PP Mutsutoshi Yoshimoto .PP From 71112a7144af58dca5f3ebc0d58c7e6475f7d2ee Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 4 Jan 2015 03:04:29 +0000 Subject: [PATCH 399/805] working on https --- src/apps/relay/turncli.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turncli.c index c88b509d..c84b6631 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turncli.c @@ -1355,31 +1355,26 @@ int send_turn_session_info(struct turn_session_info* tsi) /////////// HTTPS ///////////// -static void write_https_echo(ioa_socket_handle s) +static void write_https_default_page(ioa_socket_handle s) { if(s && !ioa_socket_tobeclosed(s)) { - SOCKET_APP_TYPE sat = get_ioa_socket_app_type(s); - if(sat == HTTPS_CLIENT_SOCKET) { - ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(s->e); - size_t len_http = ioa_network_buffer_get_size(nbh_http); - u08bits *data = ioa_network_buffer_data(nbh_http); - char data_http[1025]; - char content_http[1025]; - const char* title = "HTTPS TURN Server"; - snprintf(content_http,sizeof(content_http)-1,"\r\n\r\n \r\n %s\r\n \r\n \r\n %s\r\n \r\n\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); - len_http = strlen(data_http); - ns_bcopy(data_http,data,len_http); - ioa_network_buffer_set_size(nbh_http,len_http); - send_data_from_ioa_socket_nbh(s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE); - } + ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(s->e); + size_t len_http = ioa_network_buffer_get_size(nbh_http); + u08bits *data = ioa_network_buffer_data(nbh_http); + char data_http[1025]; + char content_http[1025]; + const char* title = "HTTPS TURN Server"; + snprintf(content_http,sizeof(content_http)-1,"\r\n\r\n \r\n %s\r\n \r\n \r\n %s\r\n \r\n\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); + len_http = strlen(data_http); + ns_bcopy(data_http,data,len_http); + ioa_network_buffer_set_size(nbh_http,len_http); + send_data_from_ioa_socket_nbh(s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE); } } static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { - //TODO - if(turn_params.verbose) { if(nbh) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection input: %s\n", __FUNCTION__, (char*)ioa_network_buffer_data(nbh)); @@ -1388,7 +1383,11 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { } } - write_https_echo(s); + if(nbh) { + //TODO + } + + write_https_default_page(s); } static void https_input_handler(ioa_socket_handle s, int event_type, ioa_net_data *data, void *arg, int can_resume) { @@ -1420,7 +1419,7 @@ void https_cli_server_receive_message(struct bufferevent *bev, void *ptr) register_callback_on_ioa_socket(cliserver.e, s, IOA_EV_READ, https_input_handler, NULL, 0); - handle_https(s,NULL); + write_https_default_page(s); } } From e8394a8f011562bf30dec38b538f06ee5786273a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 4 Jan 2015 03:09:35 +0000 Subject: [PATCH 400/805] working on https --- Makefile.in | 4 ++-- src/apps/relay/mainrelay.h | 2 +- src/apps/relay/{turncli.c => turn_admin_server.c} | 2 +- src/apps/relay/{turncli.h => turn_admin_server.h} | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) rename src/apps/relay/{turncli.c => turn_admin_server.c} (99%) rename src/apps/relay/{turncli.h => turn_admin_server.h} (97%) diff --git a/Makefile.in b/Makefile.in index bae43e13..7b99032b 100755 --- a/Makefile.in +++ b/Makefile.in @@ -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 diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index be020acb..b57c27ac 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -70,7 +70,7 @@ #include "ns_turn_khash.h" #include "userdb.h" -#include "turncli.h" +#include "turn_admin_server.h" #include "tls_listener.h" #include "dtls_listener.h" diff --git a/src/apps/relay/turncli.c b/src/apps/relay/turn_admin_server.c similarity index 99% rename from src/apps/relay/turncli.c rename to src/apps/relay/turn_admin_server.c index c84b6631..894adda4 100644 --- a/src/apps/relay/turncli.c +++ b/src/apps/relay/turn_admin_server.c @@ -64,7 +64,7 @@ #include "apputils.h" -#include "turncli.h" +#include "turn_admin_server.h" /////////////////////////////// diff --git a/src/apps/relay/turncli.h b/src/apps/relay/turn_admin_server.h similarity index 97% rename from src/apps/relay/turncli.h rename to src/apps/relay/turn_admin_server.h index aef0e0c0..05c8d262 100644 --- a/src/apps/relay/turncli.h +++ b/src/apps/relay/turn_admin_server.h @@ -28,8 +28,8 @@ * SUCH DAMAGE. */ -#ifndef __TURNCLI__ -#define __TURNCLI__ +#ifndef __TURN_ADMIN_SERVER__ +#define __TURN_ADMIN_SERVER__ #include #include @@ -101,5 +101,5 @@ void send_https_socket(ioa_socket_handle s); #endif #endif -/// __TURNCLI__/// +/// __TURN_ADMIN_SERVER__/// From 8d5ccfa445c99f7e317f292220cb14e799af35a0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 4 Jan 2015 03:23:37 +0000 Subject: [PATCH 401/805] working on https --- src/apps/relay/http_server.c | 4 +-- src/apps/relay/http_server.h | 57 ++++++++++++++++++++++++++++++ src/apps/relay/mainrelay.c | 4 ++- src/apps/relay/mainrelay.h | 4 +++ src/apps/relay/turn_admin_server.c | 16 ++++++--- src/server/ns_turn_ioalib.h | 2 +- src/server/ns_turn_server.c | 4 +-- 7 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 src/apps/relay/http_server.h diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index a0643d7a..8e08e4d2 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2012, 2013 Citrix Systems + * Copyright (C) 2011, 2012, 2013, 2014 Citrix Systems * * All rights reserved. * @@ -51,6 +51,6 @@ static void write_http_echo(ioa_socket_handle s) } } -void handle_http(ioa_socket_handle s) { +void handle_http_echo(ioa_socket_handle s) { write_http_echo(s); } diff --git a/src/apps/relay/http_server.h b/src/apps/relay/http_server.h new file mode 100644 index 00000000..0bfb7714 --- /dev/null +++ b/src/apps/relay/http_server.h @@ -0,0 +1,57 @@ +/* + * 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 +#include + +#include "ns_turn_utils.h" +#include "ns_turn_server.h" +#include "apputils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////// + +void handle_http_echo(ioa_socket_handle s); + +//////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif +/// __TURN_HTTP_SERVER__/// + diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 26629557..a87ed205 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -122,7 +122,9 @@ LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,0,"", ///////////// Users DB ////////////// { (TURN_USERDB_TYPE)0, {"\0"}, {0,NULL,NULL, {NULL,0}} }, ///////////// CPUs ////////////////// -DEFAULT_CPUS_NUMBER +DEFAULT_CPUS_NUMBER, +///////////// HTTPS ADMIN SERVER //// +"123" }; //////////////// OpenSSL Init ////////////////////// diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index b57c27ac..c981ad5e 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -310,6 +310,10 @@ typedef struct _turn_params_ { unsigned long cpus; +/////// HTTPS SERVER ///// + + char https_admin_pwd[129]; + } turn_params_t; extern turn_params_t turn_params; diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 894adda4..fb5d32a5 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -66,6 +66,8 @@ #include "turn_admin_server.h" +#include "http_server.h" + /////////////////////////////// struct cli_server cliserver; @@ -1358,6 +1360,7 @@ int send_turn_session_info(struct turn_session_info* tsi) static void write_https_default_page(ioa_socket_handle s) { if(s && !ioa_socket_tobeclosed(s)) { + //TODO ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(s->e); size_t len_http = ioa_network_buffer_get_size(nbh_http); u08bits *data = ioa_network_buffer_data(nbh_http); @@ -1383,11 +1386,14 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { } } - if(nbh) { - //TODO + if(!turn_params.https_admin_pwd[0]) { + handle_http_echo(s); + } else { + if(nbh) { + //TODO + } + write_https_default_page(s); } - - write_https_default_page(s); } static void https_input_handler(ioa_socket_handle s, int event_type, ioa_net_data *data, void *arg, int can_resume) { @@ -1419,7 +1425,7 @@ void https_cli_server_receive_message(struct bufferevent *bev, void *ptr) register_callback_on_ioa_socket(cliserver.e, s, IOA_EV_READ, https_input_handler, NULL, 0); - write_https_default_page(s); + handle_https(s,NULL); } } diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index c0e5797d..5abc1d51 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -278,7 +278,7 @@ int get_default_protocol_port(const char* scheme, size_t slen); ///////////// HTTP //////////////////// -void handle_http(ioa_socket_handle s); +void handle_http_echo(ioa_socket_handle s); /////////////////////////////////////// diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 605b6605..1e8316db 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4445,7 +4445,7 @@ static int read_client_connection(turn_turnserver *server, TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTP connection input: %s\n", __FUNCTION__, (char*)ioa_network_buffer_data(in_buffer->nbh)); } - handle_http(ss->client_socket); + handle_http_echo(ss->client_socket); } else if(sat == HTTPS_CLIENT_SOCKET) { @@ -4558,7 +4558,7 @@ static int read_client_connection(turn_turnserver *server, 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(ss->client_socket); + handle_http_echo(ss->client_socket); } return 0; } From 0aee63f61eee251e56a1426d2721e1dac0180fab Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 4 Jan 2015 09:09:52 +0000 Subject: [PATCH 402/805] working on https --- src/apps/relay/http_server.c | 205 +++++++++++++++++++++++++ src/apps/relay/http_server.h | 27 +++- src/apps/relay/ns_ioalib_engine_impl.c | 4 +- src/apps/relay/turn_admin_server.c | 8 +- src/client/ns_turn_msg.c | 4 +- src/server/ns_turn_server.c | 4 +- 6 files changed, 242 insertions(+), 10 deletions(-) diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index 8e08e4d2..6bcbeabb 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -30,6 +30,26 @@ #include "ns_ioalib_impl.h" +#include "http_server.h" + +#include +#include + +////////////////////////////////////// + +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)) { @@ -54,3 +74,188 @@ static void write_http_echo(ioa_socket_handle s) void handle_http_echo(ioa_socket_handle s) { write_http_echo(s); } + +/////////////////////////////////////////////// + +static struct headers_list * post_parse(char *data, size_t data_len) +{ + char *post_data = 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); + value = value ? value : ""; + value = evhttp_decode_uri(value); + char *p = value; + while (*p != '\0') { + 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; + } + } + 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,"POST ") == request) { + ret->rtype = HRT_POST; + ret = parse_http_request_1(ret,request+5,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;in;++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;in;++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;in;++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 *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); + } + } + return ret; +} + +void free_http_request(struct http_request *request) { + if(request) { + 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); + } +} + +/////////////////////////////////////////////// diff --git a/src/apps/relay/http_server.h b/src/apps/relay/http_server.h index 0bfb7714..20aeba19 100644 --- a/src/apps/relay/http_server.h +++ b/src/apps/relay/http_server.h @@ -31,17 +31,38 @@ #ifndef __TURN_HTTP_SERVER__ #define __TURN_HTTP_SERVER__ -#include -#include - #include "ns_turn_utils.h" #include "ns_turn_server.h" #include "apputils.h" +#include +#include + #ifdef __cplusplus extern "C" { #endif +///////// HTTP REQUEST ////////// + +enum _HTTP_REQUEST_TYPE { + HRT_UNKNOWN=0, + HRT_GET, + HRT_POST +}; + +typedef enum _HTTP_REQUEST_TYPE HTTP_REQUEST_TYPE; + +struct http_headers; + +struct http_request { + HTTP_REQUEST_TYPE rtype; + 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); +void free_http_request(struct http_request *request); + //////////////////////////////////////////// void handle_http_echo(ioa_socket_handle s); diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 1d9111ca..bbf5279f 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -2601,7 +2601,7 @@ void close_ioa_socket_after_processing_if_necessary(ioa_socket_handle s) if (s && ioa_socket_tobeclosed(s)) { 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_type(s)); + 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; } @@ -2782,7 +2782,7 @@ static void eventcb_bev(struct bufferevent *bev, short events, void *arg) 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_type(s),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; } diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index fb5d32a5..735d0ea5 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1390,7 +1390,13 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { handle_http_echo(s); } else { if(nbh) { - //TODO + struct http_request* hr = parse_http_request((char*)ioa_network_buffer_data(nbh)); + if(!hr) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: wrong HTTPS request (I cannot parse it)\n", __FUNCTION__); + } else { + //TODO + free_http_request(hr); + } } write_https_default_page(s); } diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 7f7c1172..02b2f442 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -646,9 +646,9 @@ static inline const char* findstr(const char *hay, size_t slen, const char *need static inline int is_http_get_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"); + const char *sp=findstr(s+4,blen-4," HTTP/"); 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"); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 1e8316db..3e75e8cf 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4545,10 +4545,10 @@ static int read_client_connection(turn_turnserver *server, 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)); 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_type(ss->client_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_type(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; From 385bb2fe9be41ee044261fbabb72631b4fc890b6 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 4 Jan 2015 21:02:19 +0000 Subject: [PATCH 403/805] working on https --- src/apps/relay/mainrelay.c | 4 +--- src/apps/relay/mainrelay.h | 4 ---- src/apps/relay/ns_ioalib_impl.h | 4 ++++ src/apps/relay/turn_admin_server.c | 11 ++++++----- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index a87ed205..26629557 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -122,9 +122,7 @@ LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,0,"", ///////////// Users DB ////////////// { (TURN_USERDB_TYPE)0, {"\0"}, {0,NULL,NULL, {NULL,0}} }, ///////////// CPUs ////////////////// -DEFAULT_CPUS_NUMBER, -///////////// HTTPS ADMIN SERVER //// -"123" +DEFAULT_CPUS_NUMBER }; //////////////// OpenSSL Init ////////////////////// diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index c981ad5e..b57c27ac 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -310,10 +310,6 @@ typedef struct _turn_params_ { unsigned long cpus; -/////// HTTPS SERVER ///// - - char https_admin_pwd[129]; - } turn_params_t; extern turn_params_t turn_params; diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 27390dc1..277724df 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -223,6 +223,10 @@ struct _ioa_socket accept_cb acb; void *acbarg; /* <<== RFC 6062 */ + //Admin server: + int as_ok; + char as_login[17]; + char as_realm[STUN_MAX_REALM_SIZE + 1]; }; typedef struct _timer_event diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 735d0ea5..7976994f 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1357,7 +1357,7 @@ int send_turn_session_info(struct turn_session_info* tsi) /////////// HTTPS ///////////// -static void write_https_default_page(ioa_socket_handle s) +static void write_https_logon_page(ioa_socket_handle s) { if(s && !ioa_socket_tobeclosed(s)) { //TODO @@ -1386,19 +1386,20 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { } } - if(!turn_params.https_admin_pwd[0]) { - handle_http_echo(s); - } else { + if(s->as_ok) { if(nbh) { struct http_request* hr = parse_http_request((char*)ioa_network_buffer_data(nbh)); if(!hr) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: wrong HTTPS request (I cannot parse it)\n", __FUNCTION__); } else { //TODO + write_https_logon_page(s); + s->as_ok = 1; free_http_request(hr); } } - write_https_default_page(s); + } else { + write_https_logon_page(s); } } From bd8c39c3b7582d9966c3c737a18bbccd62c86374 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 5 Jan 2015 06:40:28 +0000 Subject: [PATCH 404/805] working on https --- src/apps/relay/http_server.c | 77 ++++++++++++++++++++++++++ src/apps/relay/http_server.h | 16 +++++- src/apps/relay/ns_ioalib_engine_impl.c | 45 +++++++++++++++ src/apps/relay/ns_ioalib_impl.h | 6 +- src/apps/relay/turn_admin_server.c | 48 +++++++++++----- src/apps/relay/turn_admin_server.h | 2 +- src/client/ns_turn_msg.c | 41 +++++++++----- src/client/ns_turn_msg.h | 2 +- src/server/ns_turn_server.c | 2 +- 9 files changed, 205 insertions(+), 34 deletions(-) diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index 6bcbeabb..b8c990e0 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -138,6 +138,11 @@ static struct http_request* parse_http_request_1(struct http_request* ret, char* 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) { @@ -174,6 +179,12 @@ struct http_request* parse_http_request(char* request) { } 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; @@ -241,6 +252,10 @@ const char *get_http_header_value(const struct http_request *request, const char 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); @@ -258,4 +273,66 @@ void free_http_request(struct http_request *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); +} + +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); + } +} + /////////////////////////////////////////////// diff --git a/src/apps/relay/http_server.h b/src/apps/relay/http_server.h index 20aeba19..ef400326 100644 --- a/src/apps/relay/http_server.h +++ b/src/apps/relay/http_server.h @@ -47,7 +47,9 @@ extern "C" { enum _HTTP_REQUEST_TYPE { HRT_UNKNOWN=0, HRT_GET, - HRT_POST + HRT_POST, + HRT_PUT, + HRT_DELETE }; typedef enum _HTTP_REQUEST_TYPE HTTP_REQUEST_TYPE; @@ -56,6 +58,7 @@ struct http_headers; struct http_request { HTTP_REQUEST_TYPE rtype; + char *path; struct http_headers *headers; }; @@ -65,6 +68,17 @@ void free_http_request(struct http_request *request); //////////////////////////////////////////// +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); +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); //////////////////////////////////////////// diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index bbf5279f..233306a8 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -3191,6 +3191,51 @@ 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 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) { diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 277724df..4bc505e4 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -66,6 +66,8 @@ extern "C" { #define MAX_BUFFER_QUEUE_SIZE_PER_ENGINE (64) #define MAX_SOCKET_BUFFER_BACKLOG (16) +#define ADMIN_USER_MAX_LENGTH (32) + #define BUFFEREVENT_HIGH_WATERMARK (128<<10) #define BUFFEREVENT_MAX_UDP_TO_TCP_WRITE (64<<9) #define BUFFEREVENT_MAX_TCP_TO_TCP_WRITE (192<<10) @@ -225,7 +227,7 @@ struct _ioa_socket /* <<== RFC 6062 */ //Admin server: int as_ok; - char as_login[17]; + char as_login[ADMIN_USER_MAX_LENGTH + 1]; char as_realm[STUN_MAX_REALM_SIZE + 1]; }; @@ -301,6 +303,8 @@ 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); + ///////////////////////// SUPER MEMORY //////// #define allocate_super_memory_engine(e,size) allocate_super_memory_engine_func(e, size, __FILE__, __FUNCTION__, __LINE__) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 7976994f..c8c7a336 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1249,7 +1249,7 @@ void setup_cli_thread(void) cliserver.https_in_buf = pair[0]; cliserver.https_out_buf = pair[1]; - bufferevent_setcb(cliserver.https_in_buf, https_cli_server_receive_message, NULL, NULL, &cliserver); + bufferevent_setcb(cliserver.https_in_buf, https_admin_server_receive_message, NULL, NULL, &cliserver); bufferevent_enable(cliserver.https_in_buf, EV_READ); } @@ -1360,19 +1360,35 @@ int send_turn_session_info(struct turn_session_info* tsi) static void write_https_logon_page(ioa_socket_handle s) { if(s && !ioa_socket_tobeclosed(s)) { - //TODO - ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(s->e); - size_t len_http = ioa_network_buffer_get_size(nbh_http); - u08bits *data = ioa_network_buffer_data(nbh_http); - char data_http[1025]; - char content_http[1025]; - const char* title = "HTTPS TURN Server"; - snprintf(content_http,sizeof(content_http)-1,"\r\n\r\n \r\n %s\r\n \r\n \r\n %s\r\n \r\n\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); - len_http = strlen(data_http); - ns_bcopy(data_http,data,len_http); - ioa_network_buffer_set_size(nbh_http,len_http); - send_data_from_ioa_socket_nbh(s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE); + + struct str_buffer* sb = str_buffer_new(); + + const char* title = "TURN Server (https admin connection)"; + + str_buffer_append(sb,"\r\n\r\n \r\n "); + str_buffer_append(sb,title); + str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,title); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
Admin user information: user name:

password:


\r\n"); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"\r\n \r\n\r\n"); + + struct str_buffer* sb_http = str_buffer_new(); + + str_buffer_append(sb_http,"HTTP/1.1 200 OK\r\nServer: "); + str_buffer_append(sb_http,TURN_SOFTWARE); + str_buffer_append(sb_http,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + str_buffer_append_sz(sb_http,str_buffer_get_str_len(sb)); + str_buffer_append(sb_http,"\r\n\r\n"); + str_buffer_append(sb_http,str_buffer_get_str(sb)); + + str_buffer_free(sb); + + send_data_from_ioa_socket_tcp(s, str_buffer_get_str(sb_http), str_buffer_get_str_len(sb_http)); + + str_buffer_free(sb_http); } } @@ -1393,6 +1409,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: wrong HTTPS request (I cannot parse it)\n", __FUNCTION__); } else { //TODO + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS request, path %s\n", __FUNCTION__,hr->path); write_https_logon_page(s); s->as_ok = 1; free_http_request(hr); @@ -1400,6 +1417,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { } } else { write_https_logon_page(s); + s->as_ok = 1; } } @@ -1416,7 +1434,7 @@ static void https_input_handler(ioa_socket_handle s, int event_type, ioa_net_dat data->nbh = NULL; } -void https_cli_server_receive_message(struct bufferevent *bev, void *ptr) +void https_admin_server_receive_message(struct bufferevent *bev, void *ptr) { UNUSED_ARG(ptr); diff --git a/src/apps/relay/turn_admin_server.h b/src/apps/relay/turn_admin_server.h index 05c8d262..37c63298 100644 --- a/src/apps/relay/turn_admin_server.h +++ b/src/apps/relay/turn_admin_server.h @@ -89,7 +89,7 @@ extern int cli_max_output_sessions; void setup_cli_thread(void); void cli_server_receive_message(struct bufferevent *bev, void *ptr); -void https_cli_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); diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 02b2f442..1f2c1be4 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -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(*head)==tolower(*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=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 += 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; diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 52bdfadd..88d2e3d2 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -207,7 +207,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); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 3e75e8cf..cf660f59 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4538,7 +4538,7 @@ 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"; if(st==TLS_SOCKET) { proto = "HTTPS"; From 44475566bb3968aa8167b449c3e452397cc0b9ba Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 6 Jan 2015 06:27:08 +0000 Subject: [PATCH 405/805] working on https --- src/apps/relay/http_server.c | 1 + src/apps/relay/turn_admin_server.c | 121 ++++++++++++++++++++++++----- 2 files changed, 104 insertions(+), 18 deletions(-) diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index b8c990e0..d731abca 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -79,6 +79,7 @@ void handle_http_echo(ioa_socket_handle s) { static struct headers_list * post_parse(char *data, size_t data_len) { + while((*data=='\r')||(*data=='\n')) ++data; char *post_data = calloc(data_len + 1, sizeof(char)); memcpy(post_data, data, data_len); char *fmarker = NULL; diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index c8c7a336..f730cf18 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1357,6 +1357,24 @@ int send_turn_session_info(struct turn_session_info* tsi) /////////// HTTPS ///////////// +enum _AS_FORM { + AS_FORM_UNKNOWN, + AS_FORM_LOGON +}; + +typedef enum _AS_FORM AS_FORM; + +#define HR_USERNAME "uname" +#define HR_PASSWORD "pwd" + +#define AS_FORM_NAME_LOGON "logon" + +static AS_FORM get_form(const char* path) { + while(*path=='/') ++path; + if(!strcmp(path,AS_FORM_NAME_LOGON)) return AS_FORM_LOGON; + return AS_FORM_UNKNOWN; +} + static void write_https_logon_page(ioa_socket_handle s) { if(s && !ioa_socket_tobeclosed(s)) { @@ -1370,8 +1388,14 @@ static void write_https_logon_page(ioa_socket_handle s) str_buffer_append(sb,"\r\n \r\n \r\n "); str_buffer_append(sb,title); str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,"
Admin user information: user name:

password:


\r\n"); + str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,"
Admin user information: user name:

password:


\r\n"); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,"\r\n \r\n\r\n"); @@ -1392,32 +1416,93 @@ static void write_https_logon_page(ioa_socket_handle s) } } +static void write_https_default_page(ioa_socket_handle s) +{ + if(s && !ioa_socket_tobeclosed(s)) { + + if(!(s->as_ok)) { + write_https_logon_page(s); + } else { + + struct str_buffer* sb = str_buffer_new(); + + const char* title = "TURN Server (https admin connection)"; + + str_buffer_append(sb,"\r\n\r\n \r\n "); + str_buffer_append(sb,title); + str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,title); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"\r\n \r\n\r\n"); + + struct str_buffer* sb_http = str_buffer_new(); + + str_buffer_append(sb_http,"HTTP/1.1 200 OK\r\nServer: "); + str_buffer_append(sb_http,TURN_SOFTWARE); + str_buffer_append(sb_http,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + str_buffer_append_sz(sb_http,str_buffer_get_str_len(sb)); + str_buffer_append(sb_http,"\r\n\r\n"); + str_buffer_append(sb_http,str_buffer_get_str(sb)); + + str_buffer_free(sb); + + send_data_from_ioa_socket_tcp(s, str_buffer_get_str(sb_http), str_buffer_get_str_len(sb_http)); + + str_buffer_free(sb_http); + } + } +} + +static void handle_logon_request(ioa_socket_handle s, struct http_request* hr) +{ + if(s && hr) { + if(hr->rtype != HRT_POST) { + write_https_default_page(s); + } else { + const char *uname = get_http_header_value(hr, HR_USERNAME); + const char *pwd = get_http_header_value(hr, HR_PASSWORD); + //TODO + if(uname && pwd) { + s->as_ok = 1; + write_https_default_page(s); + } else { + write_https_logon_page(s); + } + } + } +} + static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { if(turn_params.verbose) { if(nbh) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection input: %s\n", __FUNCTION__, (char*)ioa_network_buffer_data(nbh)); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection input: %.40s\n", __FUNCTION__, (char*)ioa_network_buffer_data(nbh)); } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection initial input\n", __FUNCTION__); } } - if(s->as_ok) { - if(nbh) { - struct http_request* hr = parse_http_request((char*)ioa_network_buffer_data(nbh)); - if(!hr) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: wrong HTTPS request (I cannot parse it)\n", __FUNCTION__); - } else { - //TODO - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS request, path %s\n", __FUNCTION__,hr->path); - write_https_logon_page(s); - s->as_ok = 1; - free_http_request(hr); - } - } - } else { + if(!nbh) { write_https_logon_page(s); - s->as_ok = 1; + } else { + struct http_request* hr = parse_http_request((char*)ioa_network_buffer_data(nbh)); + if(!hr) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: wrong HTTPS request (I cannot parse it)\n", __FUNCTION__); + } else { + //TODO + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS request, path %s\n", __FUNCTION__,hr->path); + + AS_FORM form = get_form(hr->path); + + switch(form) { + case AS_FORM_LOGON: + handle_logon_request(s,hr); + break; + default: + write_https_default_page(s); + }; + free_http_request(hr); + } } } From f17ce4fe830dac0f3a2c17f2b12e1cc98c1d02ac Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 7 Jan 2015 07:57:56 +0000 Subject: [PATCH 406/805] new turn_admin table --- INSTALL | 31 +++++++++++++++++--------- examples/var/db/turndb | Bin 20480 -> 22528 bytes src/apps/relay/dbdrivers/dbd_redis.c | 4 ++-- src/apps/relay/dbdrivers/dbd_sqlite.c | 23 ++++++++++--------- src/apps/relay/userdb.h | 4 ---- src/client/ns_turn_msg.h | 3 +-- src/client/ns_turn_msg_defs.h | 3 ++- turndb/schema.mongo.sh | 1 + turndb/schema.sql | 25 +++++++++++++-------- turndb/schema.userdb.redis | 13 ++++++++++- turndb/testmongosetup.sh | 3 +++ turndb/testredisdbsetup.sh | 3 +++ turndb/testsqldbsetup.sql | 3 +++ 13 files changed, 77 insertions(+), 39 deletions(-) diff --git a/INSTALL b/INSTALL index dccc7f77..5435dbd6 100644 --- a/INSTALL +++ b/INSTALL @@ -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) @@ -688,7 +688,7 @@ or 64 characters (HEX representation of 32 bytes) for SHA256. # CREATE TABLE turnusers_st ( name varchar(512) PRIMARY KEY, - password varchar(512) + password varchar(127) ); # Table holding shared secrets for secret-based authorization @@ -696,15 +696,15 @@ CREATE TABLE turnusers_st ( # 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 +712,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 +723,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 +734,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 +753,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: @@ -791,6 +791,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 ( + uname varchar(32), + realm varchar(127), + password varchar(127), + primary key (uname) +); + 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. diff --git a/examples/var/db/turndb b/examples/var/db/turndb index a71001bb82de43fe30558f6a3c98b511a0e16f1b..d122bb1c172b0f8cd214a4358a8a22c3406e6fc8 100644 GIT binary patch delta 352 zcmZozz}T>Xae}m<76Su=7!bn%_e33IMy-tr3%v!IL>O2Z0~nYjn4+1_G6pc--`Hr! zSl`Ga$S$s^$k>=%l9-f}nwXNCnHOJLoLYoni8=?lI)=C^gg83+xGEsT6*Nlo5_3}( z$`Xr`GZKq5jEyvP6pB(4b8_KAhDPQUll=@OrQlA9H$+$p@*K-%3BMPNJiI_A6Z0ho=7-FeHVcXzW47XDViD&RO-igx ztjbMH&y;0kk(HM%&Q2`K$;?a7%P%U)&`ZxR%gE19$w@6P<^t<~#lZZE`O9WOj~mPr V1K7kknZ+5w1~73m%W}f>0ss(5W>^3K delta 58 zcmZqJz}T>Wae}mn$3z`tM&*qO3%z-PLd;AO3``PC(adKzHgYj-mhgMQ F2mmS{3lIPR diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index eb54c940..030fbf13 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -533,8 +533,8 @@ static int redis_get_user_pwd(u08bits *usname, st_password_t pwd) { 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; + strncpy((char*)pwd,rget->str,STUN_MAX_PWD_SIZE); + pwd[STUN_MAX_PWD_SIZE]=0; ret = 0; } turnFreeRedisReply(rget); diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index dff544d8..3339be74 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -148,14 +148,15 @@ 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 turnusers_st (name varchar(512) PRIMARY KEY, password varchar(127))", + "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 +189,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); diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index 1d66a710..71dbbfe2 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -46,10 +46,6 @@ extern "C" { #endif -//////////// Defines ////////////////////////////// - -#define AUTH_SECRET_SIZE (512) - //////////// REALM ////////////// struct _realm_status_t; diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 88d2e3d2..2b24231d 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -66,8 +66,7 @@ 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 st_password_t[STUN_MAX_PWD_SIZE+1]; typedef unsigned int band_limit_t; /////////////////////////////////// diff --git a/src/client/ns_turn_msg_defs.h b/src/client/ns_turn_msg_defs.h index cde11dd6..5e22c251 100644 --- a/src/client/ns_turn_msg_defs.h +++ b/src/client/ns_turn_msg_defs.h @@ -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) diff --git a/turndb/schema.mongo.sh b/turndb/schema.mongo.sh index 867dbb66..0edec9b0 100755 --- a/turndb/schema.mongo.sh +++ b/turndb/schema.mongo.sh @@ -9,6 +9,7 @@ db.turnusers_st.ensureIndex({ name: 1 }, { unique: 1 }); db.turn_secret.ensureIndex({ realm: 1 }, { unique: 1 }); db.realm.ensureIndex({ realm: 1 }, { unique: 1 }); db.oauth_key.ensureIndex({ kid: 1 }, {unique: 1 }); +db.admin_user.ensureIndex({ uname: 1 }, {unique: 1 }); exit diff --git a/turndb/schema.sql b/turndb/schema.sql index 9c452a0e..5a2396bb 100644 --- a/turndb/schema.sql +++ b/turndb/schema.sql @@ -1,6 +1,6 @@ CREATE TABLE turnusers_lt ( - realm varchar(512) default '', + realm varchar(127) default '', name varchar(512), hmackey char(128), PRIMARY KEY (realm,name) @@ -8,35 +8,35 @@ CREATE TABLE turnusers_lt ( CREATE TABLE turnusers_st ( name varchar(512) PRIMARY KEY, - password varchar(512) + password varchar(127) ); 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 +54,10 @@ CREATE TABLE oauth_key ( auth_key varchar(256) default '', primary key (kid) ); + +CREATE TABLE admin_user ( + uname varchar(32), + realm varchar(127), + password varchar(127), + primary key (uname) +); diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis index 585c2986..fbc550c9 100644 --- a/turndb/schema.userdb.redis +++ b/turndb/schema.userdb.redis @@ -72,6 +72,12 @@ 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. + +6) admin users (over https interface) are maintained as keys of form: +"turn/realm//admin_user//password" with the password +values (for the per-relam admin users), or as keys of form: +"turn/admin_user//password" with password values - for the global +admin users. II. Extra realms data in the database @@ -104,7 +110,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: @@ -131,6 +139,9 @@ 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/admin_user/skarling/password "hoodless" +set turn/admin_user/bayaz/password "magi" + set turn/realm/north.gov/max-bps 500000 set turn/realm/north.gov/total-quota 12000 set turn/realm/north.gov/user-quota 10000 diff --git a/turndb/testmongosetup.sh b/turndb/testmongosetup.sh index 30538188..0d3f1078 100755 --- a/turndb/testmongosetup.sh +++ b/turndb/testmongosetup.sh @@ -23,6 +23,9 @@ db.turnusers_st.insert({ name: 'stranger-come-knocking', password: 'civilization db.turn_secret.insert({ realm: 'north.gov', value: 'logen' }); db.turn_secret.insert({ realm: 'crinna.org', value: 'north' }); +db.admin_user.insert({ uname: 'skarling', realm: 'north.gov', password: 'hoodless' }); +db.admin_user.insert({ uname: 'bayaz', realm: '', password: 'magi' }); + db.realm.insert({ realm: 'north.gov', options: { diff --git a/turndb/testredisdbsetup.sh b/turndb/testredisdbsetup.sh index fbc96622..5e2fb685 100755 --- a/turndb/testredisdbsetup.sh +++ b/turndb/testredisdbsetup.sh @@ -32,6 +32,9 @@ 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/admin_user/skarling/password "hoodless" +set turn/admin_user/bayaz/password "magi" + set turn/realm/north.gov/max-bps 500000 set turn/realm/north.gov/total-quota 12000 set turn/realm/north.gov/user-quota 10000 diff --git a/turndb/testsqldbsetup.sql b/turndb/testsqldbsetup.sql index 58d5eca0..e9aef977 100644 --- a/turndb/testsqldbsetup.sql +++ b/turndb/testsqldbsetup.sql @@ -12,6 +12,9 @@ insert into turnusers_st (name, password) values('stranger-come-knocking','civil insert into turn_secret (realm,value) values('north.gov','logen'); insert into turn_secret (realm,value) values('crinna.org','north'); +insert into admin_user (uname, realm, password) values('skarling','north.gov','hoodless'); +insert into admin_user (uname, 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'); From 6b54e11dcbe85dac1147463c2318cefeacf2a310 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 7 Jan 2015 08:19:11 +0000 Subject: [PATCH 407/805] working on admin users --- README.turnadmin | 2 +- man/man1/turnadmin.1 | 4 ++-- man/man1/turnserver.1 | 2 +- man/man1/turnutils.1 | 2 +- src/apps/relay/mainrelay.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.turnadmin b/README.turnadmin index 3070d6c9..bbe3f3f8 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -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). diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index ed57c9db..0d2e3edd 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "03 January 2015" "" "" +.TH TURN 1 "07 January 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage @@ -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 diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 7dfd83fd..44c5670f 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "03 January 2015" "" "" +.TH TURN 1 "07 January 2015" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index f5c4124e..3c989acf 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "03 January 2015" "" "" +.TH TURN 1 "07 January 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 26629557..886b10e7 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -634,7 +634,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" From 5cd0d33c311ba926716495134502e64770ad160c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 10 Jan 2015 08:25:29 +0000 Subject: [PATCH 408/805] 1) working on https; 2) SSLv2 support removed. --- ChangeLog | 1 + INSTALL | 4 +- README.turnserver | 2 +- configure | 2 +- examples/etc/turnserver.conf | 2 +- .../scripts/longtermsecure/secure_relay.sh | 4 +- .../longtermsecure/secure_relay_cert.sh | 4 +- .../secure_relay_with_db_mongo.sh | 4 +- .../secure_relay_with_db_mysql.sh | 4 +- .../secure_relay_with_db_mysql_ssl.sh | 4 +- .../secure_relay_with_db_psql.sh | 6 +- .../secure_relay_with_db_redis.sh | 4 +- .../secure_relay_with_db_sqlite.sh | 4 +- examples/scripts/mobile/mobile_relay.sh | 4 +- .../scripts/restapi/secure_relay_secret.sh | 4 +- .../secure_relay_secret_with_db_mongo.sh | 4 +- .../secure_relay_secret_with_db_mysql.sh | 4 +- .../secure_relay_secret_with_db_psql.sh | 4 +- .../secure_relay_secret_with_db_redis.sh | 4 +- .../secure_relay_secret_with_db_sqlite.sh | 4 +- .../scripts/selfloadbalance/secure_relay.sh | 4 +- .../secure_relay_short_term_mech.sh | 4 +- examples/var/db/turndb | Bin 22528 -> 22528 bytes man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 4 +- man/man1/turnutils.1 | 2 +- rpm/turnserver.spec | 3 +- src/apps/relay/dbdrivers/dbd_mongo.c | 174 +++++++++++++++++- src/apps/relay/dbdrivers/dbd_mysql.c | 160 ++++++++++++++-- src/apps/relay/dbdrivers/dbd_pgsql.c | 126 ++++++++++++- src/apps/relay/dbdrivers/dbd_redis.c | 133 ++++++++++++- src/apps/relay/dbdrivers/dbd_sqlite.c | 167 ++++++++++++++++- src/apps/relay/dbdrivers/dbdriver.h | 8 +- src/apps/relay/mainrelay.h | 2 + src/apps/relay/netengine.c | 4 +- src/apps/relay/ns_ioalib_engine_impl.c | 2 + src/apps/relay/userdb.c | 10 +- src/apps/relay/userdb.h | 4 +- src/apps/uclient/mainuclient.c | 2 +- src/apps/uclient/uclient.c | 4 +- src/apps/uclient/uclient.h | 2 +- src/client/ns_turn_msg.c | 12 +- src/client/ns_turn_msg.h | 8 +- src/server/ns_turn_server.c | 4 +- src/server/ns_turn_server.h | 2 +- src/server/ns_turn_session.h | 2 +- turndb/schema.mongo.sh | 2 +- turndb/schema.sql | 4 +- turndb/schema.userdb.redis | 9 +- turndb/testmongosetup.sh | 4 +- turndb/testredisdbsetup.sh | 7 +- turndb/testsqldbsetup.sql | 4 +- 52 files changed, 826 insertions(+), 122 deletions(-) diff --git a/ChangeLog b/ChangeLog index da5dcfff..cc7eb311 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 1/1/2015 Oleg Moskalenko Version 4.3.4.1 'Tolomei': - https admin server; + - SSLv2 support removed; 12/24/2014 Oleg Moskalenko Version 4.3.3.1 'Tolomei': diff --git a/INSTALL b/INSTALL index 5435dbd6..988a458c 100644 --- a/INSTALL +++ b/INSTALL @@ -796,10 +796,10 @@ The oauth_key table fields meanings are: # remote https access to the admin functions. # CREATE TABLE admin_user ( - uname varchar(32), + name varchar(32), realm varchar(127), password varchar(127), - primary key (uname) + primary key (name) ); You can use turnadmin program to manage the database - you can either use diff --git a/README.turnserver b/README.turnserver index e3cebab8..5add8ab8 100644 --- a/README.turnserver +++ b/README.turnserver @@ -300,7 +300,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; diff --git a/configure b/configure index 4cd9b101..e7b89250 100755 --- a/configure +++ b/configure @@ -1160,7 +1160,7 @@ fi # So, what we have now: ############################### -OSCFLAGS="${OSCFLAGS} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX} -DTURNDB=${TURNDBDIR}/turndb" +OSCFLAGS="-DOPENSSL_NO_SSL2 ${OSCFLAGS} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX} -DTURNDB=${TURNDBDIR}/turndb" if ! [ -z "${TURN_ACCEPT_RPATH}" ] ; then if [ -z "${TURN_DISABLE_RPATH}" ] ; then diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 6e3c2f95..2ba9d673 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -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 diff --git a/examples/scripts/longtermsecure/secure_relay.sh b/examples/scripts/longtermsecure/secure_relay.sh index d390265b..4fd53c88 100755 --- a/examples/scripts/longtermsecure/secure_relay.sh +++ b/examples/scripts/longtermsecure/secure_relay.sh @@ -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 $@ diff --git a/examples/scripts/longtermsecure/secure_relay_cert.sh b/examples/scripts/longtermsecure/secure_relay_cert.sh index 9df3b4d7..ee63572c 100755 --- a/examples/scripts/longtermsecure/secure_relay_cert.sh +++ b/examples/scripts/longtermsecure/secure_relay_cert.sh @@ -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" $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh index fd793c72..42452008 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh @@ -20,7 +20,7 @@ # 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 +# 10) --cipher-list=ALL means that we support all OpenSSL ciphers # 11) --oauth - accept oAuth security dialog # Other parameters (config file name, etc) are default. @@ -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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh index 198f7c6e..fa86b507 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh @@ -21,7 +21,7 @@ # 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 +# 10) --cipher-list=ALL means that we support all OpenSSL ciphers # 11) --oauth - accept oAuth security dialog # Other parameters (config file name, etc) are default. @@ -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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh index 773020a4..2ad97f7b 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh @@ -22,7 +22,7 @@ # 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 +# 10) --cipher-list=ALL means that we support all OpenSSL ciphers # 11) --oauth - accept oAuth security dialog # Other parameters (config file name, etc) are default. @@ -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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh index 86949285..927bdf18 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh @@ -21,7 +21,7 @@ # 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 +# 10) --cipher-list=ALL means that we support all OpenSSL ciphers # 11) --oauth - accept oAuth security dialog # Other parameters (config file name, etc) are default. @@ -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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh index 6a18c40c..db7db638 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh @@ -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 # 12) --oauth - accept oAuth security dialog # Other parameters (config file name, etc) are default. @@ -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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh index c160af38..1bc1c775 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh @@ -20,7 +20,7 @@ # 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 +# 10) --cipher-list=ALL means that we support all OpenSSL ciphers # 11) --oauth - accept oAuth security dialog # Other parameters (config file name, etc) are default. @@ -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 $@ diff --git a/examples/scripts/mobile/mobile_relay.sh b/examples/scripts/mobile/mobile_relay.sh index b7ff83c1..cab92af6 100755 --- a/examples/scripts/mobile/mobile_relay.sh +++ b/examples/scripts/mobile/mobile_relay.sh @@ -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 $@ diff --git a/examples/scripts/restapi/secure_relay_secret.sh b/examples/scripts/restapi/secure_relay_secret.sh index 539742c4..719b293c 100755 --- a/examples/scripts/restapi/secure_relay_secret.sh +++ b/examples/scripts/restapi/secure_relay_secret.sh @@ -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 $@ diff --git a/examples/scripts/restapi/secure_relay_secret_with_db_mongo.sh b/examples/scripts/restapi/secure_relay_secret_with_db_mongo.sh index fdc41ec8..fd2f1725 100755 --- a/examples/scripts/restapi/secure_relay_secret_with_db_mongo.sh +++ b/examples/scripts/restapi/secure_relay_secret_with_db_mongo.sh @@ -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 $@ diff --git a/examples/scripts/restapi/secure_relay_secret_with_db_mysql.sh b/examples/scripts/restapi/secure_relay_secret_with_db_mysql.sh index eeab4d20..b3d8bd28 100755 --- a/examples/scripts/restapi/secure_relay_secret_with_db_mysql.sh +++ b/examples/scripts/restapi/secure_relay_secret_with_db_mysql.sh @@ -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 $@ diff --git a/examples/scripts/restapi/secure_relay_secret_with_db_psql.sh b/examples/scripts/restapi/secure_relay_secret_with_db_psql.sh index c0637c0a..2dfa44d7 100755 --- a/examples/scripts/restapi/secure_relay_secret_with_db_psql.sh +++ b/examples/scripts/restapi/secure_relay_secret_with_db_psql.sh @@ -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 $@ diff --git a/examples/scripts/restapi/secure_relay_secret_with_db_redis.sh b/examples/scripts/restapi/secure_relay_secret_with_db_redis.sh index 0b64d566..ab335e02 100755 --- a/examples/scripts/restapi/secure_relay_secret_with_db_redis.sh +++ b/examples/scripts/restapi/secure_relay_secret_with_db_redis.sh @@ -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 $@ diff --git a/examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh b/examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh index c4fa65e1..3753f28c 100755 --- a/examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh +++ b/examples/scripts/restapi/secure_relay_secret_with_db_sqlite.sh @@ -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 $@ diff --git a/examples/scripts/selfloadbalance/secure_relay.sh b/examples/scripts/selfloadbalance/secure_relay.sh index a537ada9..5fb97ff2 100755 --- a/examples/scripts/selfloadbalance/secure_relay.sh +++ b/examples/scripts/selfloadbalance/secure_relay.sh @@ -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 $@ diff --git a/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh b/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh index 4cbfb0ed..35453f6c 100755 --- a/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh +++ b/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh @@ -21,7 +21,7 @@ # 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. +# 10) --cipher-list=ALL means that we support all OpenSSL ciphers # 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/:/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 $@ +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 $@ diff --git a/examples/var/db/turndb b/examples/var/db/turndb index d122bb1c172b0f8cd214a4358a8a22c3406e6fc8..a51877861fa2c53e1e5710f63b605043bc58ed60 100644 GIT binary patch delta 122 zcmZqJz}T>Xae}m<9s>h|7!bn%??fGAM!k&*y1s#2d5O8H3T25!$r*`78pcMNI$TAm ti8;A&Awwf`pjbg-adCNmQ3|?nQD$ypQKdq5YNdh($Rtg!&G&qjxBy>*B5(iz delta 122 zcmZqJz}T>Xae}m<76Su=7!bn%_e33IMy-try1s#>d5O8H3T25!$r*`78pcMNItoRp si8;A&Awwf`pjbg-adCNmQ3|?nQD$ypQKdq5YNdh(*eK1-_k5MO0FIp_egFUf diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 0d2e3edd..b56c9e01 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "07 January 2015" "" "" +.TH TURN 1 "10 January 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 44c5670f..f655a51a 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "07 January 2015" "" "" +.TH TURN 1 "10 January 2015" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -453,7 +453,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 diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 3c989acf..1f37f85e 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "07 January 2015" "" "" +.TH TURN 1 "10 January 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 923228ec..5d816c69 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -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: diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index f5d4f998..612c7039 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -312,7 +312,7 @@ 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) { +static int mongo_get_user_pwd(u08bits *usname, password_t pwd) { mongoc_collection_t * collection = mongo_get_collection("turnusers_st"); if(!collection) @@ -425,7 +425,7 @@ 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) { +static int mongo_set_user_pwd(u08bits *usname, password_t pwd) { mongoc_collection_t * collection = mongo_get_collection("turnusers_st"); if(!collection) @@ -1172,7 +1172,169 @@ 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(void) +{ + 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; + 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); + } + if(realm && *realm) { + printf("%s[%s]\n", value, realm); + } else { + printf("%s\n", value); + } + } + } + } + mongoc_cursor_destroy(cursor); + ret = 0; + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + bson_destroy(&fields); + return ret; +} + +////////////////////////////////////////////////////////// static const turn_dbdriver_t driver = { &mongo_get_auth_secrets, @@ -1196,7 +1358,11 @@ static const turn_dbdriver_t driver = { &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) { diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 37b705b1..f3763710 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -339,7 +339,7 @@ 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) { +static int mysql_get_user_pwd(u08bits *usname, password_t pwd) { int ret = -1; @@ -514,21 +514,26 @@ 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; } @@ -553,7 +558,7 @@ static int mysql_set_oauth_key(oauth_key_data_raw *key) { return ret; } -static int mysql_set_user_pwd(u08bits *usname, st_password_t pwd) { +static int mysql_set_user_pwd(u08bits *usname, password_t pwd) { int ret = -1; char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); @@ -1065,7 +1070,126 @@ 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]; + 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]; + 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(void) +{ + int ret = -1; + char statement[TURN_LONG_STRING_SIZE]; + 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 { + for(;;) { + MYSQL_ROW row = mysql_fetch_row(mres); + if(!row) { + break; + } else { + if(row[0]) { + if(row[1] && row[1][0]) { + printf("%s[%s]\n",row[0],row[1]); + } else { + printf("%s\n",row[0]); + } + } + } + } + ret = 0; + } + + if(mres) + mysql_free_result(mres); + } + } + return ret; +} + +////////////////////////////////////////////////////// static const turn_dbdriver_t driver = { &mysql_get_auth_secrets, @@ -1089,7 +1213,11 @@ static const turn_dbdriver_t driver = { &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) { diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index c35a3f85..fb6e0f4a 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -153,7 +153,7 @@ 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) { +static int pgsql_get_user_pwd(u08bits *usname, 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); @@ -167,7 +167,7 @@ static int pgsql_get_user_pwd(u08bits *usname, st_password_t pwd) { } else { char *kval = PQgetvalue(res,0,0); if(kval) { - strncpy((char*)pwd,kval,sizeof(st_password_t)); + strncpy((char*)pwd,kval,sizeof(password_t)); ret = 0; } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong password data for user %s: NULL\n",usname); @@ -319,7 +319,7 @@ static int pgsql_set_oauth_key(oauth_key_data_raw *key) { return ret; } -static int pgsql_set_user_pwd(u08bits *usname, st_password_t pwd) { +static int pgsql_set_user_pwd(u08bits *usname, password_t pwd) { int ret = -1; char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); @@ -785,7 +785,119 @@ 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]; + 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]; + 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(void) +{ + int ret = -1; + char statement[TURN_LONG_STRING_SIZE]; + 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; + for(i=0;itype == 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; + 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; + 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(void) +{ + int ret = -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); + } + } + + for(isz=0;isz #include #include +#include +#include #include "ns_turn_utils.h" #include "ns_turn_khash.h" diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index e74d7866..f74fb71b 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -403,13 +403,13 @@ static void auth_server_receive_message(struct bufferevent *bev, void *ptr) } if(am.ct == TURN_CREDENTIALS_SHORT_TERM) { - st_password_t pwd; + 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)); + ns_bcopy(pwd,am.pwd,sizeof(password_t)); am.success = 1; } } else { diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 233306a8..8f9b5bd9 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -2268,8 +2268,10 @@ static TURN_TLS_TYPE check_tentative_tls(ioa_socket_raw fd) ret = (TURN_TLS_TYPE)(s[10]+1); } else if((s[2]==1)&&(s[3]==3)) { ret = TURN_TLS_SSL23; /* compatibility mode */ +#ifndef OPENSSL_NO_SSL2 } else if((s[2]==1)&&(s[3]==0)&&(s[4]==2)) { ret = TURN_TLS_SSL23; /* old mode */ +#endif } } diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 21783953..a2cf5190 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -496,7 +496,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 +549,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; @@ -646,7 +646,7 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u /* * Short-term mechanism password retrieval */ -int get_user_pwd(u08bits *usname, st_password_t pwd) +int get_user_pwd(u08bits *usname, password_t pwd) { int ret = -1; @@ -915,7 +915,7 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b hmackey_t key; char skey[sizeof(hmackey_t) * 2 + 1]; - st_password_t passwd; + password_t passwd; if (ct == TA_LIST_USERS) { return list_users(is_st, realm); @@ -968,7 +968,7 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b must_set_admin_pwd(pwd); if (is_st) { - strncpy((char*) passwd, (char*) pwd, sizeof(st_password_t)); + strncpy((char*) passwd, (char*) pwd, sizeof(password_t)); } else { stun_produce_integrity_key_str(user, realm, pwd, key, turn_params.shatype); size_t i = 0; diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index 71dbbfe2..4efd1457 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -86,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; @@ -187,7 +187,7 @@ 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); +int get_user_pwd(u08bits *uname, 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); diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 7adc7983..d19a95b1 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -63,7 +63,7 @@ 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; diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 7403b880..03bf401c 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1654,7 +1654,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 +1679,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); diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index 43ff021d..3d0267d6 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -61,7 +61,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; diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 1f2c1be4..061cbf65 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1465,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]; @@ -1504,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); } @@ -1518,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; @@ -1540,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]; @@ -1608,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; diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 2b24231d..8f8c7393 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -66,7 +66,7 @@ typedef u08bits hmackey_t[64]; /** * Short-term credentials password */ -typedef u08bits st_password_t[STUN_MAX_PWD_SIZE+1]; +typedef u08bits password_t[STUN_MAX_PWD_SIZE+1]; typedef unsigned int band_limit_t; /////////////////////////////////// @@ -179,12 +179,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); /* diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index cf660f59..a6e0e640 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3164,7 +3164,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 +3178,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); diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index 75380802..1a767391 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -90,7 +90,7 @@ typedef enum { struct _turn_turnserver; typedef struct _turn_turnserver turn_turnserver; -typedef void (*get_username_resume_cb)(int success, int oauth, int max_session_time, hmackey_t hmackey, 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); diff --git a/src/server/ns_turn_session.h b/src/server/ns_turn_session.h index c1a2c70e..c9d4b921 100644 --- a/src/server/ns_turn_session.h +++ b/src/server/ns_turn_session.h @@ -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; diff --git a/turndb/schema.mongo.sh b/turndb/schema.mongo.sh index 0edec9b0..32173f06 100755 --- a/turndb/schema.mongo.sh +++ b/turndb/schema.mongo.sh @@ -9,7 +9,7 @@ db.turnusers_st.ensureIndex({ name: 1 }, { unique: 1 }); db.turn_secret.ensureIndex({ realm: 1 }, { unique: 1 }); db.realm.ensureIndex({ realm: 1 }, { unique: 1 }); db.oauth_key.ensureIndex({ kid: 1 }, {unique: 1 }); -db.admin_user.ensureIndex({ uname: 1 }, {unique: 1 }); +db.admin_user.ensureIndex({ name: 1 }, {unique: 1 }); exit diff --git a/turndb/schema.sql b/turndb/schema.sql index 5a2396bb..00cd4dca 100644 --- a/turndb/schema.sql +++ b/turndb/schema.sql @@ -56,8 +56,8 @@ CREATE TABLE oauth_key ( ); CREATE TABLE admin_user ( - uname varchar(32), + name varchar(32), realm varchar(127), password varchar(127), - primary key (uname) + primary key (name) ); diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis index fbc550c9..a09d3237 100644 --- a/turndb/schema.userdb.redis +++ b/turndb/schema.userdb.redis @@ -139,9 +139,6 @@ 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/admin_user/skarling/password "hoodless" -set turn/admin_user/bayaz/password "magi" - set turn/realm/north.gov/max-bps 500000 set turn/realm/north.gov/total-quota 12000 set turn/realm/north.gov/user-quota 10000 @@ -158,7 +155,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 diff --git a/turndb/testmongosetup.sh b/turndb/testmongosetup.sh index 0d3f1078..60d36ed3 100755 --- a/turndb/testmongosetup.sh +++ b/turndb/testmongosetup.sh @@ -23,8 +23,8 @@ db.turnusers_st.insert({ name: 'stranger-come-knocking', password: 'civilization db.turn_secret.insert({ realm: 'north.gov', value: 'logen' }); db.turn_secret.insert({ realm: 'crinna.org', value: 'north' }); -db.admin_user.insert({ uname: 'skarling', realm: 'north.gov', password: 'hoodless' }); -db.admin_user.insert({ uname: 'bayaz', realm: '', password: 'magi' }); +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', diff --git a/turndb/testredisdbsetup.sh b/turndb/testredisdbsetup.sh index 5e2fb685..23307450 100755 --- a/turndb/testredisdbsetup.sh +++ b/turndb/testredisdbsetup.sh @@ -51,8 +51,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 diff --git a/turndb/testsqldbsetup.sql b/turndb/testsqldbsetup.sql index e9aef977..8e47399b 100644 --- a/turndb/testsqldbsetup.sql +++ b/turndb/testsqldbsetup.sql @@ -12,8 +12,8 @@ insert into turnusers_st (name, password) values('stranger-come-knocking','civil insert into turn_secret (realm,value) values('north.gov','logen'); insert into turn_secret (realm,value) values('crinna.org','north'); -insert into admin_user (uname, realm, password) values('skarling','north.gov','hoodless'); -insert into admin_user (uname, realm, password) values('bayaz','','magi'); +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'); From 2b356c2f166066c38f56743846c3614f15c0d4fa Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 10 Jan 2015 09:06:30 +0000 Subject: [PATCH 409/805] SSLv2 removal --- ChangeLog | 4 ++-- README.turnserver | 2 -- examples/etc/turnserver.conf | 1 - man/man1/turnserver.1 | 4 ---- src/apps/relay/mainrelay.c | 8 +++++--- src/apps/uclient/mainuclient.c | 2 +- src/apps/uclient/uclient.h | 2 ++ 7 files changed, 10 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index cc7eb311..0d5f99af 100644 --- a/ChangeLog +++ b/ChangeLog @@ -463,9 +463,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. diff --git a/README.turnserver b/README.turnserver index 5add8ab8..aab31884 100644 --- a/README.turnserver +++ b/README.turnserver @@ -191,8 +191,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. diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 2ba9d673..1f0908cf 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -625,7 +625,6 @@ # Do not allow an SSL/TLS/DTLS version of protocol # -#no-sslv2 #no-sslv3 #no-tlsv1 #no-tlsv1_1 diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index f655a51a..8b69332b 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -282,10 +282,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 diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 886b10e7..eb4c19d7 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -81,7 +81,8 @@ NULL, DH_1066, "", "", "", "turn_server_cert.pem","turn_server_pkey.pem", "", "", -0,0,0,0,0, +1, +0,0,0,0, #if !TLS_SUPPORTED 1, #else @@ -518,7 +519,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 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" @@ -908,7 +908,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); @@ -2531,9 +2531,11 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) { int op = 0; +#if !defined(OPENSSL_NO_SSL2) #if defined(SSL_OP_NO_SSLv2) if(turn_params.no_sslv2) op |= SSL_OP_NO_SSLv2; +#endif #endif if(turn_params.no_sslv3) op |= SSL_OP_NO_SSLv3; diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index d19a95b1..9f14237d 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -496,7 +496,7 @@ 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]) diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index 3d0267d6..dde2b887 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -36,6 +36,8 @@ #include "session.h" #include +#include +#include #ifdef __cplusplus extern "C" { From b3098cd71d4c95ef0a3403d90de007c6da43097f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 10 Jan 2015 23:29:08 +0000 Subject: [PATCH 410/805] ssl2 removed --- src/apps/common/apputils.c | 8 -------- src/apps/relay/mainrelay.c | 11 ++++------- src/apps/relay/mainrelay.h | 1 - src/apps/relay/ns_ioalib_engine_impl.c | 4 ---- src/apps/relay/turn_admin_server.c | 6 ------ src/apps/uclient/mainuclient.c | 5 ----- 6 files changed, 4 insertions(+), 31 deletions(-) diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c index 6d89d926..a8ec8ef3 100644 --- a/src/apps/common/apputils.c +++ b/src/apps/common/apputils.c @@ -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()) { diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index eb4c19d7..acdbcdc5 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -81,7 +81,6 @@ NULL, DH_1066, "", "", "", "turn_server_cert.pem","turn_server_pkey.pem", "", "", -1, 0,0,0,0, #if !TLS_SUPPORTED 1, @@ -705,7 +704,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, @@ -828,7 +827,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 }, @@ -2531,12 +2530,10 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) { int op = 0; -#if !defined(OPENSSL_NO_SSL2) #if defined(SSL_OP_NO_SSLv2) - if(turn_params.no_sslv2) - op |= SSL_OP_NO_SSLv2; -#endif + op |= SSL_OP_NO_SSLv2; #endif + if(turn_params.no_sslv3) op |= SSL_OP_NO_SSLv3; diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index 8047b4a3..b2f8033e 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -199,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; diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 8f9b5bd9..457fa4d7 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -2268,10 +2268,6 @@ static TURN_TLS_TYPE check_tentative_tls(ioa_socket_raw fd) ret = (TURN_TLS_TYPE)(s[10]+1); } else if((s[2]==1)&&(s[3]==3)) { ret = TURN_TLS_SSL23; /* compatibility mode */ -#ifndef OPENSSL_NO_SSL2 - } else if((s[2]==1)&&(s[3]==0)&&(s[4]==2)) { - ret = TURN_TLS_SSL23; /* old mode */ -#endif } } diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index f730cf18..62f09035 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -723,12 +723,6 @@ static void cli_print_configuration(struct cli_session* cs) cli_print_flag(cs,turn_params.no_dtls,"no-dtls",0); cli_print_flag(cs,turn_params.no_tls,"no-tls",0); -#ifndef OPENSSL_NO_SSL2 - cli_print_flag(cs,(!turn_params.no_sslv2 && !turn_params.no_tls),"SSLv2",0); -#else - cli_print_flag(cs,0,"SSLv2",0); -#endif - cli_print_flag(cs,(!turn_params.no_sslv3 && !turn_params.no_tls),"SSLv3",0); cli_print_flag(cs,(!turn_params.no_tlsv1 && !turn_params.no_tls),"TLSv1.0",0); cli_print_flag(cs,(!turn_params.no_tlsv1_1 && !turn_params.no_tls),"TLSv1.1",0); diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 9f14237d..369c3261 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -503,11 +503,6 @@ int main(int argc, char **argv) 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++; From f2a5909be97d379a652b3ef0c542a45a6b423b4b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 10 Jan 2015 23:32:41 +0000 Subject: [PATCH 411/805] ssl2 support removed --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index e7b89250..4cd9b101 100755 --- a/configure +++ b/configure @@ -1160,7 +1160,7 @@ fi # So, what we have now: ############################### -OSCFLAGS="-DOPENSSL_NO_SSL2 ${OSCFLAGS} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX} -DTURNDB=${TURNDBDIR}/turndb" +OSCFLAGS="${OSCFLAGS} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX} -DTURNDB=${TURNDBDIR}/turndb" if ! [ -z "${TURN_ACCEPT_RPATH}" ] ; then if [ -z "${TURN_DISABLE_RPATH}" ] ; then From 237b3baaa7a4478c8516d32e4bc2f27bc7d36842 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 11 Jan 2015 06:28:58 +0000 Subject: [PATCH 412/805] short-term credentials removed in the TURN server --- ChangeLog | 3 +- INSTALL | 25 ++--- README.turnadmin | 8 +- README.turnserver | 34 +++---- README.turnutils | 4 - examples/etc/turnserver.conf | 16 +-- .../secure_relay_short_term_mech.sh | 34 ------- ...ure_tcp_client_c2c_tcp_relay_short_term.sh | 31 ------ .../secure_udp_client_short_term.sh | 30 ------ examples/var/db/turndb | Bin 22528 -> 22528 bytes man/man1/turnadmin.1 | 14 +-- man/man1/turnserver.1 | 36 +++---- man/man1/turnutils.1 | 6 -- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 11 +- src/apps/relay/dbdrivers/dbd_mongo.c | 95 ++---------------- src/apps/relay/dbdrivers/dbd_mysql.c | 77 +------------- src/apps/relay/dbdrivers/dbd_pgsql.c | 70 +------------ src/apps/relay/dbdrivers/dbd_redis.c | 68 +------------ src/apps/relay/dbdrivers/dbd_sqlite.c | 82 +-------------- src/apps/relay/dbdrivers/dbdriver.h | 6 +- src/apps/relay/mainrelay.c | 63 ++++-------- src/apps/relay/netengine.c | 12 +-- src/apps/relay/turn_admin_server.c | 2 - src/apps/relay/userdb.c | 48 +++------ src/apps/relay/userdb.h | 3 +- src/apps/uclient/mainuclient.c | 19 ---- src/apps/uclient/startuclient.c | 15 +-- src/apps/uclient/uclient.c | 21 +--- src/apps/uclient/uclient.h | 1 - src/client/ns_turn_msg.h | 3 - src/ns_turn_defs.h | 4 +- src/server/ns_turn_server.c | 50 ++------- turndb/schema.mongo.sh | 1 - turndb/schema.sql | 5 - turndb/schema.userdb.redis | 25 ++--- turndb/testmongosetup.sh | 6 -- turndb/testredisdbsetup.sh | 11 -- turndb/testsqldbsetup.sql | 5 - 39 files changed, 136 insertions(+), 810 deletions(-) delete mode 100755 examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh delete mode 100755 examples/scripts/shorttermsecure/secure_tcp_client_c2c_tcp_relay_short_term.sh delete mode 100755 examples/scripts/shorttermsecure/secure_udp_client_short_term.sh diff --git a/ChangeLog b/ChangeLog index 0d5f99af..8d3425d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,8 @@ 1/1/2015 Oleg Moskalenko -Version 4.3.4.1 'Tolomei': +Version 4.4.1.1 'Carlot dan Eider': - https admin server; - SSLv2 support removed; + - The server-side short-term credentials mechanism support removed; 12/24/2014 Oleg Moskalenko Version 4.3.3.1 'Tolomei': diff --git a/INSTALL b/INSTALL index 988a458c..3e9873ff 100644 --- a/INSTALL +++ b/INSTALL @@ -684,13 +684,6 @@ 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(127) -); - # Table holding shared secrets for secret-based authorization # (REST API). It can only be used together with the long-term # mechanism: @@ -827,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 @@ -899,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. @@ -951,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 @@ -1006,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. @@ -1135,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. diff --git a/README.turnadmin b/README.turnadmin index bbe3f3f8..b10f2379 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -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= Add shared secret for TURN RESP API @@ -119,7 +119,7 @@ List all long-term users in MySQL database: $ turnadmin -l --mysql-userdb="" -r -List all short-term users in Redis database: +List all admin users in Redis database: $ turnadmin -L --redis-userdb="" diff --git a/README.turnserver b/README.turnserver index aab31884..85087bb4 100644 --- a/README.turnserver +++ b/README.turnserver @@ -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. @@ -380,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 @@ -558,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: @@ -731,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. @@ -742,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 diff --git a/README.turnutils b/README.turnutils index 13142195..c2c5e9dc 100644 --- a/README.turnutils +++ b/README.turnutils @@ -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). diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 1f0908cf..33235e01 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -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, @@ -223,8 +218,7 @@ #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): # diff --git a/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh b/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh deleted file mode 100755 index 35453f6c..00000000 --- a/examples/scripts/shorttermsecure/secure_relay_short_term_mech.sh +++ /dev/null @@ -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 means that we support all OpenSSL ciphers -# 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 $@ diff --git a/examples/scripts/shorttermsecure/secure_tcp_client_c2c_tcp_relay_short_term.sh b/examples/scripts/shorttermsecure/secure_tcp_client_c2c_tcp_relay_short_term.sh deleted file mode 100755 index a68a079b..00000000 --- a/examples/scripts/shorttermsecure/secure_tcp_client_c2c_tcp_relay_short_term.sh +++ /dev/null @@ -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 - diff --git a/examples/scripts/shorttermsecure/secure_udp_client_short_term.sh b/examples/scripts/shorttermsecure/secure_udp_client_short_term.sh deleted file mode 100755 index 792b4828..00000000 --- a/examples/scripts/shorttermsecure/secure_udp_client_short_term.sh +++ /dev/null @@ -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 diff --git a/examples/var/db/turndb b/examples/var/db/turndb index a51877861fa2c53e1e5710f63b605043bc58ed60..97183521c52978cec3404fbc0195f325c857cd98 100644 GIT binary patch delta 108 zcmZqJz}T>Xae}mXae}m<9s>h|7!bn%??fGAM!k&*3%CV%fnqGo(-@fVFrQ=I%RFr}BTpN1 zy($Z{rD}0WQDRcH(9>p4H3_Qp}c&*xkUw%`D9bwU?QbS)37UB@-XBGAELC zn?x8TM1kh9GrVG8c*QuE@fuS&(*$N!=9r0%S0=yGdE->i%r35~%Gl^wl9-f}T2fk+ zS6U2oXMAx9GMmLY$kj2#RUyRD$;VXzSw=x)a)7Rwwn9LVr>|pBq=L6=qz;z?5ELX9 qgTq6iEU_p#Be6)s)X+$iOVgZX@_b!2!Qzs5Lu6xEH&4(j&;$V6g@fJz diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index b56c9e01..a9e34f63 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -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= Add shared secret for TURN RESP API .TP @@ -211,7 +211,7 @@ List all long\-term users in MySQL database: .PP $ \fIturnadmin\fP \fB\-l\fP \fB\-\-mysql\-userdb\fP="" \fB\-r\fP .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="" .PP diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 8b69332b..5e66b223 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -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 @@ -555,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 @@ -792,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 @@ -984,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. @@ -995,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 diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 1f37f85e..c5cd42bb 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -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 diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 514e69ef..5121d85b 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.3.4.1 +TURNVERSION=4.4.1.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 5d816c69..95a884c9 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.3.4.1 +Version: 4.4.1.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -61,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) @@ -248,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 @@ -293,8 +288,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Thu Jan 24 2015 Oleg Moskalenko - - Sync to 4.3.4.1 +* Sat Jan 10 2015 Oleg Moskalenko + - Sync to 4.4.1.1 * Wed Dec 24 2014 Oleg Moskalenko - Sync to 4.3.3.1 * Sun Dec 14 2014 Oleg Moskalenko diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index 612c7039..d27211d5 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -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, 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, 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, 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,8 +424,8 @@ 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"; +static int mongo_list_users(u08bits *realm) { + const char * collection_name = "turnusers_lt"; mongoc_collection_t * collection = mongo_get_collection(collection_name); if(!collection) @@ -514,7 +437,7 @@ static int mongo_list_users(int is_st, u08bits *realm) { 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 +445,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); @@ -542,7 +465,7 @@ static int mongo_list_users(int is_st, u08bits *realm) { 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)) { + 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); } if(realm && *realm) { @@ -1339,9 +1262,7 @@ static int mongo_list_admin_users(void) 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, diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index f3763710..38e04a1c 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -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, 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) { @@ -558,36 +517,12 @@ static int mysql_set_oauth_key(oauth_key_data_raw *key) { return ret; } -static int mysql_set_user_pwd(u08bits *usname, password_t pwd) { +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) { - 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; - } - } - } - return ret; -} - -static int mysql_del_user(u08bits *usname, int is_st, 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)); @@ -614,14 +549,12 @@ static int mysql_del_oauth_key(const u08bits *kid) { return ret; } -static int mysql_list_users(int is_st, u08bits *realm) { +static int mysql_list_users(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),"select name,'' from turnusers_st order by name"); - } else if(realm && realm[0]) { + if(realm && 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"); @@ -1194,9 +1127,7 @@ static int mysql_list_admin_users(void) 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, diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index fb6e0f4a..24a3f7c6 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -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, 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(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) { @@ -318,43 +290,13 @@ static int pgsql_set_oauth_key(oauth_key_data_raw *key) { } return ret; } - -static int pgsql_set_user_pwd(u08bits *usname, 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,14 +327,12 @@ static int pgsql_del_oauth_key(const u08bits *kid) { return ret; } -static int pgsql_list_users(int is_st, u08bits *realm) { +static int pgsql_list_users(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),"select name,'' from turnusers_st order by name"); - } else if(realm && realm[0]) { + if(realm && 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"); @@ -902,9 +842,7 @@ static int pgsql_list_admin_users(void) 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, diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index d306eaf4..db1ddd85 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -519,30 +519,6 @@ static int redis_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { return ret; } -static int redis_get_user_pwd(u08bits *usname, 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,STUN_MAX_PWD_SIZE); - pwd[STUN_MAX_PWD_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(); @@ -572,28 +548,12 @@ static int redis_set_oauth_key(oauth_key_data_raw *key) { return ret; } -static int redis_set_user_pwd(u08bits *usname, 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); @@ -619,7 +579,7 @@ static int redis_del_oauth_key(const u08bits *kid) { return ret; } -static int redis_list_users(int is_st, u08bits *realm) { +static int redis_list_users(u08bits *realm) { int ret = -1; redisContext *rc = get_redis_connection(); if(rc) { @@ -630,8 +590,7 @@ 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 { @@ -660,23 +619,6 @@ static int redis_list_users(int is_st, u08bits *realm) { } 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) { @@ -1329,9 +1271,7 @@ static int redis_list_admin_users(void) 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, diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index f14c1cf3..3c755372 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -149,7 +149,6 @@ static void init_sqlite_database(sqlite3 *sqliteconnection) { const char * statements[] = { "CREATE TABLE turnusers_lt ( 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(127))", "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))", @@ -287,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, 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(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; @@ -493,7 +456,7 @@ static int sqlite_set_oauth_key(oauth_key_data_raw *key) return ret; } -static int sqlite_set_user_pwd(u08bits *usname, password_t pwd) +static int sqlite_del_user(u08bits *usname, u08bits *realm) { int ret = -1; char statement[TURN_LONG_STRING_SIZE]; @@ -504,40 +467,7 @@ static int sqlite_set_user_pwd(u08bits *usname, 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); @@ -586,7 +516,7 @@ 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) { int ret = -1; char statement[TURN_LONG_STRING_SIZE]; @@ -597,9 +527,7 @@ static int sqlite_list_users(int is_st, u08bits *realm) 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 && 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"); @@ -1259,9 +1187,7 @@ static int sqlite_list_admin_users(void) 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, diff --git a/src/apps/relay/dbdrivers/dbdriver.h b/src/apps/relay/dbdrivers/dbdriver.h index 0dc76c96..8de2cca7 100644 --- a/src/apps/relay/dbdrivers/dbdriver.h +++ b/src/apps/relay/dbdrivers/dbdriver.h @@ -50,11 +50,9 @@ 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, password_t pwd); int (*set_user_key)(u08bits *usname, u08bits *realm, const char *key); - int (*set_user_pwd)(u08bits *usname, password_t pwd); - int (*del_user)(u08bits *usname, int is_st, u08bits *realm); - int (*list_users)(int is_st, u08bits *realm); + int (*del_user)(u08bits *usname, u08bits *realm); + int (*list_users)(u08bits *realm); int (*show_secret)(u08bits *realm); int (*del_secret)(u08bits *secret, u08bits *realm); int (*set_secret)(u08bits *secret, u08bits *realm); diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index acdbcdc5..cdd2e761 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -33,7 +33,6 @@ ////// TEMPORARY data ////////// static int use_lt_credentials = 0; -static int use_st_credentials = 0; static int anon_credentials = 0; ////// TURNDB ////////////// @@ -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 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 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 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 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= dbname= user= \\\n password= port= connect_timeout=\".\n\n" @@ -466,12 +464,12 @@ static char Usage[] = "Usage: turnserver [options]\n" #endif #if !defined(TURN_NO_MONGO) " -J, --mongo-userdb 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 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= dbname= \\\n password= port= connect_timeout=\".\n\n" @@ -601,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= Add shared secret for TURN RESP API\n" " -S, --show-secret Show stored shared secrets for TURN REST API\n" " -X, --delete-secret= Delete a shared secret\n" @@ -746,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) @@ -840,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' }, @@ -1119,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; @@ -1430,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]=""; @@ -1482,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; @@ -1596,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); } static void print_features(unsigned long mfn) @@ -1895,17 +1884,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; @@ -1927,15 +1906,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; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index f74fb71b..30843744 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -402,17 +402,7 @@ static void auth_server_receive_message(struct bufferevent *bev, void *ptr) continue; } - if(am.ct == TURN_CREDENTIALS_SHORT_TERM) { - 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(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; diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 62f09035..0f9d4299 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -832,8 +832,6 @@ static void cli_print_configuration(struct cli_session* cs) cli_print_str(cs,cs->origin,"CLI session origin",0); if(turn_params.ct == TURN_CREDENTIALS_LONG_TERM) cli_print_flag(cs,1,"Long-term authorization mechanism",0); - else if(turn_params.ct == TURN_CREDENTIALS_SHORT_TERM) - cli_print_flag(cs,1,"Short-term authorization mechanism",0); else cli_print_flag(cs,1,"Anonymous credentials",0); cli_print_flag(cs,turn_params.use_auth_secret_with_timestamp,"TURN REST API support",0); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index a2cf5190..510a9e35 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -643,21 +643,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, 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; @@ -790,11 +775,11 @@ int add_user_account(char *user, int dynamic) ////////////////// Admin ///////////////////////// -static int list_users(int is_st, u08bits *realm) +static int list_users(u08bits *realm) { const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->list_users) { - (*dbd->list_users)(is_st, realm); + (*dbd->list_users)(realm); } return 0; @@ -910,15 +895,17 @@ 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) { hmackey_t key; char skey[sizeof(hmackey_t) * 2 + 1]; password_t passwd; + STRCPY(passwd,pwd); + if (ct == TA_LIST_USERS) { - return list_users(is_st, realm); + return list_users(realm); } if (ct == TA_LIST_ORIGINS) { @@ -967,9 +954,7 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b must_set_admin_pwd(pwd); - if (is_st) { - strncpy((char*) passwd, (char*) pwd, sizeof(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,27 +973,18 @@ 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) { - must_set_admin_realm(realm); - } + must_set_admin_realm(realm); if (ct == TA_DELETE_USER) { if (dbd->del_user) - (*dbd->del_user)(user, is_st, realm); + (*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); - } else { - if (dbd->set_user_key) - (*dbd->set_user_key)(user, realm, skey); - } + if (dbd->set_user_key) + (*dbd->set_user_key)(user, realm, skey); } } diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index 4efd1457..b1848776 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -187,7 +187,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, 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); @@ -201,7 +200,7 @@ 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 adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08bits *origin, TURNADMIN_COMMAND_TYPE ct, perf_options_t* po); int add_ip_list_range(const char* range, const char* realm, ip_range_list_t * list); ip_range_list_t* get_ip_list(const char *kind); diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 369c3261..e509b797 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -56,7 +56,6 @@ 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; @@ -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" @@ -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 */ diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 38ab87b5..54da33c6 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -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; } diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 03bf401c..46b2dc6f 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -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) { diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index dde2b887..e68de6ee 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -53,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; diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 8f8c7393..0d6d93ea 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -63,9 +63,6 @@ typedef enum { */ typedef u08bits hmackey_t[64]; -/** - * Short-term credentials password - */ typedef u08bits password_t[STUN_MAX_PWD_SIZE+1]; typedef unsigned int band_limit_t; diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 4e641751..014cc7d5 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,8 +31,8 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.3.4.1" -#define TURN_SERVER_VERSION_NAME "Tolomei" +#define TURN_SERVER_VERSION "4.4.1.1" +#define TURN_SERVER_VERSION_NAME "Carlot dan Eider" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" #if (defined(__unix__) || defined(unix)) && !defined(USG) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index a6e0e640..1bff8006 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -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: ; }; @@ -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){ @@ -4734,13 +4705,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); diff --git a/turndb/schema.mongo.sh b/turndb/schema.mongo.sh index 32173f06..63ae491c 100755 --- a/turndb/schema.mongo.sh +++ b/turndb/schema.mongo.sh @@ -5,7 +5,6 @@ mongo $* </secret" and the value(s) will be the secret(s). @@ -26,7 +21,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//allowed-peer-ip" and "turn/realm//denied-peer-ip". @@ -38,7 +33,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/". The kid structure fields are: ikm_key - (optional) base64-encoded key ("input keying material"); @@ -73,11 +68,9 @@ and they will be almost immediately "seen" by the turnserver process. calculated with ikm_key and hkdf_hash_func. The auth_key length is defined by auth_alg. -6) admin users (over https interface) are maintained as keys of form: -"turn/realm//admin_user//password" with the password -values (for the per-relam admin users), or as keys of form: -"turn/admin_user//password" with password values - for the global -admin users. +5) admin users (over https interface) are maintained as keys of form: +"turn/admin_user/ with hash members "password" and, +optionally, "realm". II. Extra realms data in the database @@ -101,7 +94,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 @@ -134,11 +126,6 @@ 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 diff --git a/turndb/testmongosetup.sh b/turndb/testmongosetup.sh index 60d36ed3..dba4757d 100755 --- a/turndb/testmongosetup.sh +++ b/turndb/testmongosetup.sh @@ -5,7 +5,6 @@ mongo $* < Date: Sun, 11 Jan 2015 06:36:42 +0000 Subject: [PATCH 413/805] name change --- ChangeLog | 2 +- src/ns_turn_defs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8d3425d3..ffd61d29 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ 1/1/2015 Oleg Moskalenko -Version 4.4.1.1 'Carlot dan Eider': +Version 4.4.1.1 'Ardee West': - https admin server; - SSLv2 support removed; - The server-side short-term credentials mechanism support removed; diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 014cc7d5..3cedbe84 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -32,7 +32,7 @@ #define __IOADEFS__ #define TURN_SERVER_VERSION "4.4.1.1" -#define TURN_SERVER_VERSION_NAME "Carlot dan Eider" +#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) From f562b9cfa715e501108afcc6ee3ec418dae6eba3 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 11 Jan 2015 09:50:52 +0000 Subject: [PATCH 414/805] admin user administration commands --- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/dbdrivers/dbd_mysql.c | 3 ++ src/apps/relay/dbdrivers/dbd_pgsql.c | 3 ++ src/apps/relay/dbdrivers/dbd_redis.c | 9 ++-- src/apps/relay/mainrelay.c | 7 ++- src/apps/relay/userdb.c | 63 +++++++++++++++------------ src/apps/relay/userdb.h | 5 +-- 7 files changed, 53 insertions(+), 37 deletions(-) diff --git a/examples/var/db/turndb b/examples/var/db/turndb index 97183521c52978cec3404fbc0195f325c857cd98..f06a31d409ebbf8537c5cdbcbaac4019f63153f7 100644 GIT binary patch delta 99 zcmZqJz}T>Xae_3X=|mZ4M$?T6Yy4T5H!^SB%*eBZSy+()9q>;+9_-4(e2e)OP{mnh hWdW!H4iL@BEY6seSeaPG#LXXae_3X{zMsPM*WQmYy3Ae@*HEHd@0xp$hgNW#>p(sn3PzVSjEK6EX!G( LomiBUnU@X#17Q(p diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 38e04a1c..ce118195 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -1045,6 +1045,7 @@ static int mysql_set_admin_user(const u08bits *usname, const u08bits *realm, con { 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); @@ -1068,6 +1069,7 @@ 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); @@ -1085,6 +1087,7 @@ static int mysql_list_admin_users(void) { 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"); diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index 24a3f7c6..a9a9cec6 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -765,6 +765,7 @@ static int pgsql_set_admin_user(const u08bits *usname, const u08bits *realm, con { 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); @@ -793,6 +794,7 @@ 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); @@ -809,6 +811,7 @@ static int pgsql_list_admin_users(void) { 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"); diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index db1ddd85..6a9d70ac 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -539,7 +539,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")); @@ -1187,13 +1187,14 @@ static int redis_get_admin_user(const u08bits *usname, u08bits *realm, password_ 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); + 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); + snprintf(statement,sizeof(statement),"hmset turn/admin_user/%s password %s",usname,pwd); } turnFreeRedisReply(redisCommand(rc, statement)); turnFreeRedisReply(redisCommand(rc, "save")); @@ -1204,6 +1205,7 @@ static int redis_set_admin_user(const u08bits *usname, const u08bits *realm, con 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]; @@ -1218,6 +1220,7 @@ static int redis_del_admin_user(const u08bits *usname) { static int redis_list_admin_users(void) { int ret = -1; + donot_print_connection_success = 1; redisContext *rc = get_redis_connection(); secrets_list_t keys; size_t isz = 0; diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index cdd2e761..1f0d7178 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -119,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 }; @@ -1129,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': @@ -1585,7 +1585,7 @@ static int adminmain(int argc, char **argv) exit(-1); } - return adminuser(user, realm, pwd, secret, origin, ct, &po); + return adminuser(user, realm, pwd, secret, origin, ct, &po, is_admin); } static void print_features(unsigned long mfn) @@ -1804,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); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 510a9e35..b17a0505 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -620,12 +620,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); @@ -721,7 +715,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) { @@ -755,11 +749,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); @@ -775,11 +765,19 @@ int add_user_account(char *user, int dynamic) ////////////////// Admin ///////////////////////// -static int list_users(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)(realm); + if (dbd) { + if(is_admin) { + if(dbd->list_admin_users) { + (*dbd->list_admin_users)(); + } + } else { + if(dbd->list_users) { + (*dbd->list_users)(realm); + } + } } return 0; @@ -895,17 +893,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, 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]; - password_t passwd; - - STRCPY(passwd,pwd); - if (ct == TA_LIST_USERS) { - return list_users(realm); + return list_users(realm, is_admin); } if (ct == TA_LIST_ORIGINS) { @@ -950,7 +944,7 @@ 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); @@ -977,14 +971,29 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b } else if (dbd) { - must_set_admin_realm(realm); + if(!is_admin) + must_set_admin_realm(realm); if (ct == TA_DELETE_USER) { - if (dbd->del_user) - (*dbd->del_user)(user, 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 (dbd->set_user_key) - (*dbd->set_user_key)(user, realm, skey); + 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); + } } } diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index b1848776..84b944c6 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -149,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; @@ -199,8 +198,8 @@ 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, 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); ip_range_list_t* get_ip_list(const char *kind); From c5f461eb99b7dd74d573d960abc8685075dfe8d1 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 12 Jan 2015 04:02:34 +0000 Subject: [PATCH 415/805] login implemented --- src/apps/relay/ns_ioalib_engine_impl.c | 13 +++++++ src/apps/relay/ns_ioalib_impl.h | 3 ++ src/apps/relay/turn_admin_server.c | 54 ++++++++++++++------------ 3 files changed, 45 insertions(+), 25 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 457fa4d7..d1f2d4e0 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -3234,6 +3234,19 @@ int send_data_from_ioa_socket_tcp(ioa_socket_handle s, const void *data, size_t return ret; } +int send_str_from_ioa_socket_tcp(ioa_socket_handle s, const void *data) +{ + return send_data_from_ioa_socket_tcp(s, data, strlen(data)); +} + +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) { diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 4bc505e4..aa4bc706 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -227,6 +227,7 @@ struct _ioa_socket /* <<== RFC 6062 */ //Admin server: int as_ok; + int as_private; char as_login[ADMIN_USER_MAX_LENGTH + 1]; char as_realm[STUN_MAX_REALM_SIZE + 1]; }; @@ -304,6 +305,8 @@ 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 //////// diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 0f9d4299..091847d1 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -68,6 +68,8 @@ #include "http_server.h" +#include "dbdrivers/dbdriver.h" + /////////////////////////////// struct cli_server cliserver; @@ -1408,7 +1410,7 @@ static void write_https_logon_page(ioa_socket_handle s) } } -static void write_https_default_page(ioa_socket_handle s) +static void write_https_initial_page(ioa_socket_handle s) { if(s && !ioa_socket_tobeclosed(s)) { @@ -1427,20 +1429,16 @@ static void write_https_default_page(ioa_socket_handle s) str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,"\r\n \r\n\r\n"); - struct str_buffer* sb_http = str_buffer_new(); + send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); + send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); + send_str_from_ioa_socket_tcp(s,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); - str_buffer_append(sb_http,"HTTP/1.1 200 OK\r\nServer: "); - str_buffer_append(sb_http,TURN_SOFTWARE); - str_buffer_append(sb_http,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); - str_buffer_append_sz(sb_http,str_buffer_get_str_len(sb)); - str_buffer_append(sb_http,"\r\n\r\n"); - str_buffer_append(sb_http,str_buffer_get_str(sb)); + send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); + + send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); + send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); str_buffer_free(sb); - - send_data_from_ioa_socket_tcp(s, str_buffer_get_str(sb_http), str_buffer_get_str_len(sb_http)); - - str_buffer_free(sb_http); } } } @@ -1448,17 +1446,20 @@ static void write_https_default_page(ioa_socket_handle s) static void handle_logon_request(ioa_socket_handle s, struct http_request* hr) { if(s && hr) { - if(hr->rtype != HRT_POST) { - write_https_default_page(s); - } else { - const char *uname = get_http_header_value(hr, HR_USERNAME); - const char *pwd = get_http_header_value(hr, HR_PASSWORD); - //TODO - if(uname && pwd) { - s->as_ok = 1; - write_https_default_page(s); - } else { - write_https_logon_page(s); + const char *uname = get_http_header_value(hr, HR_USERNAME); + const char *pwd = get_http_header_value(hr, HR_PASSWORD); + + if(!(s->as_ok) && uname && pwd) { + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->get_admin_user) { + + password_t password; + char realm[STUN_MAX_REALM_SIZE]="\0"; + if((*(dbd->get_admin_user))((const u08bits*)uname,(u08bits*)realm,password)>=0) { + if(!strcmp(pwd,(char*)password)) { + s->as_ok = 1; + } + } } } } @@ -1489,9 +1490,12 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { switch(form) { case AS_FORM_LOGON: handle_logon_request(s,hr); - break; default: - write_https_default_page(s); + if(s->as_ok) { + write_https_initial_page(s); + } else { + write_https_logon_page(s); + } }; free_http_request(hr); } From a2ca178ff7b49e164aa634f9fd84785e0a6b57bd Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 12 Jan 2015 08:31:58 +0000 Subject: [PATCH 416/805] working on https --- ChangeLog | 5 +- src/apps/relay/turn_admin_server.c | 430 +++++++++++++++++++++++++++-- 2 files changed, 414 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index ffd61d29..e19a758a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,9 @@ -1/1/2015 Oleg Moskalenko +1/12/2015 Oleg Moskalenko Version 4.4.1.1 'Ardee West': - https admin server; - SSLv2 support removed; - - The server-side short-term credentials mechanism support removed; + - The server-side short-term credentials mechanism support removed; + - OpenSSL 1.1.0 supported; 12/24/2014 Oleg Moskalenko Version 4.3.3.1 'Tolomei': diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 091847d1..1e2638a8 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1352,8 +1352,10 @@ int send_turn_session_info(struct turn_session_info* tsi) /////////// HTTPS ///////////// enum _AS_FORM { - AS_FORM_UNKNOWN, - AS_FORM_LOGON + AS_FORM_LOGON, + AS_FORM_PC, + AS_FORM_HOME, + AS_FORM_UNKNOWN }; typedef enum _AS_FORM AS_FORM; @@ -1361,11 +1363,32 @@ typedef enum _AS_FORM AS_FORM; #define HR_USERNAME "uname" #define HR_PASSWORD "pwd" -#define AS_FORM_NAME_LOGON "logon" +struct form_name { + AS_FORM form; + const char* name; +}; + +static struct form_name form_names[] = { + {AS_FORM_LOGON,"/logon"}, + {AS_FORM_PC,"/pc"}, + {AS_FORM_HOME,"/home"}, + {AS_FORM_UNKNOWN,NULL} +}; + +static const char* admin_title = "TURN Server (https admin connection)"; +static const char* home_link = "
home page
\r\n"; + +static ioa_socket_handle current_socket = NULL; static AS_FORM get_form(const char* path) { - while(*path=='/') ++path; - if(!strcmp(path,AS_FORM_NAME_LOGON)) return AS_FORM_LOGON; + if(path) { + size_t i = 0; + while(form_names[i].name) { + if(!strcmp(form_names[i].name,path)) + return form_names[i].form; + ++i; + } + } return AS_FORM_UNKNOWN; } @@ -1375,15 +1398,13 @@ static void write_https_logon_page(ioa_socket_handle s) struct str_buffer* sb = str_buffer_new(); - const char* title = "TURN Server (https admin connection)"; - str_buffer_append(sb,"\r\n\r\n \r\n "); - str_buffer_append(sb,title); + str_buffer_append(sb,admin_title); str_buffer_append(sb,"\r\n \r\n \r\n "); - str_buffer_append(sb,title); + str_buffer_append(sb,admin_title); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,"
Admin user information: user name:
\r\n\r\n \r\n "); + str_buffer_append(sb,admin_title); + str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,admin_title); + str_buffer_append(sb,"

\r\n"); + str_buffer_append(sb,"Print Config Parameters
\r\n"); + str_buffer_append(sb,"\r\n \r\n\r\n"); + + send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); + send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); + send_str_from_ioa_socket_tcp(s,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + + send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); + + send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); + send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); + + str_buffer_free(sb); + } + } +} + +static void sbprintf(struct str_buffer *sb, const char *format, ...) +{ + if(sb && format) { + va_list args; + va_start (args, format); + static char s[1025]="\0"; + vsnprintf(s,sizeof(s)-1,format, args); + str_buffer_append(sb,s); + va_end (args); + } +} + +static void https_print_flag(struct str_buffer* sb, int flag, const char* name, int changeable) +{ + if(sb && name) { + const char *sc=""; + if(changeable) + sc=" (*)"; + sbprintf(sb,"%s%s%s\r\n",name,get_flag(flag),sc); + } +} + +static void https_print_uint(struct str_buffer* sb, unsigned long value, const char* name, int changeable) +{ + if(sb && name) { + const char *sc=""; + if(changeable==1) + sc=" (*)"; + else if(changeable==2) + sc=" (**)"; + sbprintf(sb,"%s%lu%s\r\n",name,value,sc); + } +} + +static void https_print_str(struct str_buffer* sb, const char *value, const char* name, int changeable) +{ + if(sb && name && value) { + if((value[0] == 0) && name[0]) + value="empty"; + const char *sc=""; + if(changeable==1) + sc=" (*)"; + else if(changeable==2) + sc=" (**)"; + sbprintf(sb,"%s%s%s\r\n",name,value,sc); + } +} + +static void https_print_str_array(struct str_buffer* sb, char **value, size_t sz, const char* name, int changeable) +{ + if(sb && name && value && sz) { + const char *sc=""; + if(changeable==1) + sc=" (*)"; + else if(changeable==2) + sc=" (**)"; + size_t i; + for(i=0;i %s %s%s\r\n",name,value[i],sc); + } + } +} + +static void https_print_addr(struct str_buffer* sb, ioa_addr *value, int use_port, const char* name, int changeable) +{ + if(sb && name && value) { + const char *sc=""; + if(changeable==1) + sc=" (*)"; + else if(changeable==2) + sc=" (**)"; + char s[256]; + if(!use_port) + addr_to_string_no_port(value,(u08bits*)s); + else + addr_to_string(value,(u08bits*)s); + sbprintf(sb," %s %s%s\r\n",name,s,sc); + } +} + +static void https_print_addr_list(struct str_buffer* sb, turn_server_addrs_list_t *value, int use_port, const char* name, int changeable) +{ + if(sb && name && value && value->size && value->addrs) { + const char *sc=""; + if(changeable==1) + sc=" (*)"; + else if(changeable==2) + sc=" (**)"; + char s[256]; + size_t i; + for(i=0;isize;i++) { + if(!use_port) + addr_to_string_no_port(&(value->addrs[i]),(u08bits*)s); + else + addr_to_string(&(value->addrs[i]),(u08bits*)s); + sbprintf(sb," %s %s%s\r\n",name,s,sc); + } + } +} + +static void https_print_ip_range_list(struct str_buffer* sb, ip_range_list_t *value, const char* name, int changeable) +{ + if(sb && name && value && value->ranges_number && value->rs) { + const char *sc=""; + if(changeable==1) + sc=" (*)"; + else if(changeable==2) + sc=" (**)"; + size_t i; + for(i=0;iranges_number;++i) { + if(value->rs[i].realm[0]) { + if(current_socket->as_realm[0] && strcmp(current_socket->as_realm,value->rs[i].realm)) { + continue; + } else { + sbprintf(sb," %s %s (%s)%s\r\n",name,value->rs[i].str,value->rs[i].realm,sc); + } + } else { + sbprintf(sb," %s %s%s\r\n",name,value->rs[i].str,sc); + } + } + } +} + +static void write_pc_page(ioa_socket_handle s) +{ + if(s && !ioa_socket_tobeclosed(s)) { + + if(!(s->as_ok)) { + write_https_logon_page(s); + } else { + + struct str_buffer* sb = str_buffer_new(); str_buffer_append(sb,"\r\n\r\n \r\n "); - str_buffer_append(sb,title); + str_buffer_append(sb,admin_title); str_buffer_append(sb,"\r\n \r\n \r\n "); - str_buffer_append(sb,title); + str_buffer_append(sb,admin_title); str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,"\r\n \r\n\r\n"); + str_buffer_append(sb,home_link); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"Config Parameters:
\r\n"); + + { + https_print_flag(sb,turn_params.verbose,"verbose",0); + https_print_flag(sb,turn_params.turn_daemon,"daemon process",0); + https_print_flag(sb,turn_params.stale_nonce,"stale-nonce",1); + https_print_flag(sb,turn_params.stun_only,"stun-only",1); + https_print_flag(sb,turn_params.no_stun,"no-stun",1); + https_print_flag(sb,turn_params.secure_stun,"secure-stun",1); + https_print_flag(sb,turn_params.do_not_use_config_file,"do-not-use-config-file",0); + https_print_flag(sb,turn_params.rfc5780,"RFC5780 support",0); + https_print_uint(sb,(unsigned int)turn_params.net_engine_version,"net engine version",0); + https_print_str(sb,turn_params.net_engine_version_txt[(int)turn_params.net_engine_version],"net engine",0); + https_print_flag(sb,turn_params.fingerprint,"enforce fingerprints",0); + https_print_flag(sb,turn_params.mobility,"mobility",1); + https_print_flag(sb,turn_params.udp_self_balance,"udp-self-balance",0); + https_print_str(sb,turn_params.pidfile,"pidfile",0); + https_print_uint(sb,(unsigned long)getuid(),"process user ID",0); + https_print_uint(sb,(unsigned long)getgid(),"process group ID",0); + + { + char wd[1025]; + if(getcwd(wd,sizeof(wd)-1)) { + https_print_str(sb,wd,"process dir",0); + } + } + + https_print_str(sb,"","",0); + + if(turn_params.cipher_list[0]) + https_print_str(sb,turn_params.cipher_list,"cipher-list",0); + else + https_print_str(sb,DEFAULT_CIPHER_LIST,"cipher-list",0); + + https_print_str(sb,turn_params.ec_curve_name,"ec-curve-name",0); + { + if(turn_params.dh_key_size == DH_CUSTOM) + https_print_str(sb,turn_params.dh_file,"dh-file",0); + else { + unsigned int dh_key_length = 1066; + if(turn_params.dh_key_size == DH_566) + dh_key_length = 566; + else if(turn_params.dh_key_size == DH_2066) + dh_key_length = 2066; + https_print_uint(sb,(unsigned long)dh_key_length,"DH-key-length",0); + } + } + + https_print_str(sb,turn_params.ca_cert_file,"Certificate Authority file",0); + https_print_str(sb,turn_params.cert_file,"Certificate file",0); + https_print_str(sb,turn_params.pkey_file,"Private Key file",0); + + if(turn_params.shatype == SHATYPE_SHA256) + https_print_str(sb,"SHA256","SHA type",0); + else + https_print_str(sb,"SHA1","SHA type",0); + + https_print_str(sb,"","",0); + + https_print_str_array(sb,turn_params.listener.addrs,turn_params.listener.addrs_number,"Listener addr",0); + + if(turn_params.listener_ifname[0]) + https_print_str(sb,turn_params.listener_ifname,"listener-ifname",0); + + https_print_flag(sb,turn_params.no_udp,"no-udp",0); + https_print_flag(sb,turn_params.no_tcp,"no-tcp",0); + https_print_flag(sb,turn_params.no_dtls,"no-dtls",0); + https_print_flag(sb,turn_params.no_tls,"no-tls",0); + + https_print_flag(sb,(!turn_params.no_sslv3 && !turn_params.no_tls),"SSLv3",0); + https_print_flag(sb,(!turn_params.no_tlsv1 && !turn_params.no_tls),"TLSv1.0",0); + https_print_flag(sb,(!turn_params.no_tlsv1_1 && !turn_params.no_tls),"TLSv1.1",0); + https_print_flag(sb,(!turn_params.no_tlsv1_2 && !turn_params.no_tls),"TLSv1.2",0); + + https_print_uint(sb,(unsigned long)turn_params.listener_port,"listener-port",0); + https_print_uint(sb,(unsigned long)turn_params.tls_listener_port,"tls-listener-port",0); + https_print_uint(sb,(unsigned long)turn_params.alt_listener_port,"alt-listener-port",0); + https_print_uint(sb,(unsigned long)turn_params.alt_tls_listener_port,"alt-tls-listener-port",0); + + https_print_addr(sb,turn_params.external_ip,0,"External public IP",0); + + https_print_str(sb,"","",0); + + https_print_addr_list(sb,&turn_params.aux_servers_list,1,"Aux server",0); + https_print_addr_list(sb,&turn_params.alternate_servers_list,1,"Alternate server",0); + https_print_addr_list(sb,&turn_params.tls_alternate_servers_list,1,"TLS alternate server",0); + + https_print_str(sb,"","",0); + + https_print_str_array(sb,turn_params.relay_addrs,turn_params.relays_number,"Relay addr",0); + + if(turn_params.relay_ifname[0]) + https_print_str(sb,turn_params.relay_ifname,"relay-ifname",0); + + https_print_flag(sb,turn_params.server_relay,"server-relay",0); + + https_print_flag(sb,turn_params.no_udp_relay,"no-udp-relay",1); + https_print_flag(sb,turn_params.no_tcp_relay,"no-tcp-relay",1); + + https_print_uint(sb,(unsigned long)turn_params.min_port,"min-port",0); + https_print_uint(sb,(unsigned long)turn_params.max_port,"max-port",0); + + https_print_ip_range_list(sb,&turn_params.ip_whitelist,"Whitelist IP (static)",0); + { + ip_range_list_t* l = get_ip_list("allowed"); + https_print_ip_range_list(sb,l,"Whitelist IP (dynamic)",0); + ip_list_free(l); + } + + https_print_ip_range_list(sb,&turn_params.ip_blacklist,"Blacklist IP (static)",0); + { + ip_range_list_t* l = get_ip_list("denied"); + https_print_ip_range_list(sb,l,"Blacklist IP (dynamic)",0); + ip_list_free(l); + } + + https_print_flag(sb,turn_params.no_multicast_peers,"no-multicast-peers",1); + https_print_flag(sb,turn_params.no_loopback_peers,"no-loopback-peers",1); + + https_print_str(sb,"","",0); + + if(turn_params.default_users_db.persistent_users_db.userdb[0]) { + switch(turn_params.default_users_db.userdb_type) { +#if !defined(TURN_NO_SQLITE) + case TURN_USERDB_TYPE_SQLITE: + https_print_str(sb,"SQLite","DB type",0); + break; +#endif +#if !defined(TURN_NO_PQ) + case TURN_USERDB_TYPE_PQ: + https_print_str(sb,"Postgres","DB type",0); + break; +#endif +#if !defined(TURN_NO_MYSQL) + case TURN_USERDB_TYPE_MYSQL: + https_print_str(sb,"MySQL/MariaDB","DB type",0); + break; +#endif +#if !defined(TURN_NO_MONGO) + case TURN_USERDB_TYPE_MONGO: + https_print_str(sb,"MongoDB","DB type",0); + break; +#endif +#if !defined(TURN_NO_HIREDIS) + case TURN_USERDB_TYPE_REDIS: + https_print_str(sb,"redis","DB type",0); + break; +#endif + default: + https_print_str(sb,"unknown","DB type",0); + }; + https_print_str(sb,turn_params.default_users_db.persistent_users_db.userdb,"DB",0); + } else { + https_print_str(sb,"none","DB type",0); + https_print_str(sb,"none","DB",0); + } + +#if !defined(TURN_NO_HIREDIS) + if(turn_params.use_redis_statsdb && turn_params.redis_statsdb[0]) + https_print_str(sb,turn_params.redis_statsdb,"Redis Statistics DB",0); +#endif + + https_print_str(sb,"","",0); + + { + char * rn = get_realm(NULL)->options.name; + if(rn[0]) + https_print_str(sb,rn,"Default realm",0); + } + if(current_socket->as_realm[0]) + https_print_str(sb,current_socket->as_realm,"Admin session realm",0); + + if(turn_params.ct == TURN_CREDENTIALS_LONG_TERM) + https_print_flag(sb,1,"Long-term authorization mechanism",0); + else + https_print_flag(sb,1,"Anonymous credentials",0); + https_print_flag(sb,turn_params.use_auth_secret_with_timestamp,"TURN REST API support",0); + if(turn_params.use_auth_secret_with_timestamp && turn_params.rest_api_separator) + https_print_uint(sb,turn_params.rest_api_separator,"TURN REST API separator ASCII number",0); + + https_print_str(sb,"","",0); + + realm_params_t *rp = get_realm(NULL); + if(current_socket->as_realm[0]) { + rp = get_realm(current_socket->as_realm); + if(!rp) rp = get_realm(NULL); + } + + https_print_uint(sb,(unsigned long)rp->status.total_current_allocs,"total-current-allocs",0); + + https_print_str(sb,"","",0); + + https_print_uint(sb,(unsigned long)turn_params.total_quota,"Default total-quota",2); + https_print_uint(sb,(unsigned long)turn_params.user_quota,"Default user-quota",2); + https_print_uint(sb,(unsigned long)get_bps_capacity(),"Total server bps-capacity",2); + https_print_uint(sb,(unsigned long)get_bps_capacity_allocated(),"Allocated bps-capacity",0); + https_print_uint(sb,(unsigned long)get_max_bps(),"Default max-bps",2); + + https_print_str(sb,"","",0); + + https_print_uint(sb,(unsigned long)rp->options.perf_options.total_quota,"current realm total-quota",0); + https_print_uint(sb,(unsigned long)rp->options.perf_options.user_quota,"current realm user-quota",0); + https_print_uint(sb,(unsigned long)rp->options.perf_options.max_bps,"current realm max-bps",0); + } + + str_buffer_append(sb,"\r\n
\r\n\r\n"); send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); @@ -1465,7 +1849,9 @@ static void handle_logon_request(ioa_socket_handle s, struct http_request* hr) } } -static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { +static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) +{ + current_socket = s; if(turn_params.verbose) { if(nbh) { @@ -1482,17 +1868,21 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { if(!hr) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: wrong HTTPS request (I cannot parse it)\n", __FUNCTION__); } else { - //TODO TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS request, path %s\n", __FUNCTION__,hr->path); AS_FORM form = get_form(hr->path); switch(form) { + case AS_FORM_PC: + write_pc_page(s); + break; case AS_FORM_LOGON: - handle_logon_request(s,hr); + if(!(s->as_ok)) { + handle_logon_request(s,hr); + } default: if(s->as_ok) { - write_https_initial_page(s); + write_https_home_page(s); } else { write_https_logon_page(s); } @@ -1500,6 +1890,8 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { free_http_request(hr); } } + + current_socket = NULL; } static void https_input_handler(ioa_socket_handle s, int event_type, ioa_net_data *data, void *arg, int can_resume) { From d0c0359011a76e8225b0bb6409abb05e7332e61c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 13 Jan 2015 07:45:39 +0000 Subject: [PATCH 417/805] ssl fixes --- src/apps/relay/ns_ioalib_engine_impl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index d1f2d4e0..59104bf0 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -2263,7 +2263,7 @@ 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)) { From 345695219a09179de1f0ad321fa2aa6a222fe91b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 13 Jan 2015 08:09:28 +0000 Subject: [PATCH 418/805] dtls fixes --- src/apps/relay/mainrelay.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 1f0d7178..7dd1e65d 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -2606,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); From b34c21536535a0cf5d4578316d283aacc715507b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 13 Jan 2015 09:25:38 +0000 Subject: [PATCH 419/805] admin session realm --- src/apps/relay/ns_ioalib_impl.h | 1 - src/apps/relay/turn_admin_server.c | 64 +++++++++++++++++++++--------- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index aa4bc706..b6f67c04 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -227,7 +227,6 @@ struct _ioa_socket /* <<== RFC 6062 */ //Admin server: int as_ok; - int as_private; char as_login[ADMIN_USER_MAX_LENGTH + 1]; char as_realm[STUN_MAX_REALM_SIZE + 1]; }; diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 1e2638a8..9d042023 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1362,6 +1362,7 @@ typedef enum _AS_FORM AS_FORM; #define HR_USERNAME "uname" #define HR_PASSWORD "pwd" +#define HR_REALM "realm" struct form_name { AS_FORM form; @@ -1379,6 +1380,7 @@ static const char* admin_title = "TURN Server (https admin connection)"; static const char* home_link = "
home page
\r\n"; static ioa_socket_handle current_socket = NULL; +static char* current_realm = NULL; static AS_FORM get_form(const char* path) { if(path) { @@ -1446,9 +1448,22 @@ static void write_https_home_page(ioa_socket_handle s) str_buffer_append(sb,"\r\n \r\n \r\n "); str_buffer_append(sb,admin_title); str_buffer_append(sb,"

\r\n"); - str_buffer_append(sb,"Print Config Parameters
\r\n"); + + if(current_socket->as_realm[0]) { + str_buffer_append(sb,"Config Parameters
\r\n"); + } else { + str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,"
Current realm: name:

"); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"\r\n"); + } + str_buffer_append(sb,"\r\n \r\n\r\n"); send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); @@ -1577,7 +1592,7 @@ static void https_print_ip_range_list(struct str_buffer* sb, ip_range_list_t *va size_t i; for(i=0;iranges_number;++i) { if(value->rs[i].realm[0]) { - if(current_socket->as_realm[0] && strcmp(current_socket->as_realm,value->rs[i].realm)) { + if(current_realm && current_realm[0] && strcmp(current_realm,value->rs[i].realm)) { continue; } else { sbprintf(sb," %s %s (%s)%s\r\n",name,value->rs[i].str,value->rs[i].realm,sc); @@ -1775,8 +1790,6 @@ static void write_pc_page(ioa_socket_handle s) if(rn[0]) https_print_str(sb,rn,"Default realm",0); } - if(current_socket->as_realm[0]) - https_print_str(sb,current_socket->as_realm,"Admin session realm",0); if(turn_params.ct == TURN_CREDENTIALS_LONG_TERM) https_print_flag(sb,1,"Long-term authorization mechanism",0); @@ -1788,11 +1801,17 @@ static void write_pc_page(ioa_socket_handle s) https_print_str(sb,"","",0); - realm_params_t *rp = get_realm(NULL); - if(current_socket->as_realm[0]) { - rp = get_realm(current_socket->as_realm); - if(!rp) rp = get_realm(NULL); - } + realm_params_t *rp = get_realm(current_realm); + if(!rp) rp = get_realm(NULL); + + if(current_realm) + https_print_str(sb,current_realm,"current realm",0); + + https_print_uint(sb,(unsigned long)rp->options.perf_options.total_quota,"current realm total-quota",0); + https_print_uint(sb,(unsigned long)rp->options.perf_options.user_quota,"current realm user-quota",0); + https_print_uint(sb,(unsigned long)rp->options.perf_options.max_bps,"current realm max-bps",0); + + https_print_str(sb,"","",0); https_print_uint(sb,(unsigned long)rp->status.total_current_allocs,"total-current-allocs",0); @@ -1803,12 +1822,6 @@ static void write_pc_page(ioa_socket_handle s) https_print_uint(sb,(unsigned long)get_bps_capacity(),"Total server bps-capacity",2); https_print_uint(sb,(unsigned long)get_bps_capacity_allocated(),"Allocated bps-capacity",0); https_print_uint(sb,(unsigned long)get_max_bps(),"Default max-bps",2); - - https_print_str(sb,"","",0); - - https_print_uint(sb,(unsigned long)rp->options.perf_options.total_quota,"current realm total-quota",0); - https_print_uint(sb,(unsigned long)rp->options.perf_options.user_quota,"current realm user-quota",0); - https_print_uint(sb,(unsigned long)rp->options.perf_options.max_bps,"current realm max-bps",0); } str_buffer_append(sb,"\r\n \r\n\r\n"); @@ -1841,6 +1854,8 @@ static void handle_logon_request(ioa_socket_handle s, struct http_request* hr) char realm[STUN_MAX_REALM_SIZE]="\0"; if((*(dbd->get_admin_user))((const u08bits*)uname,(u08bits*)realm,password)>=0) { if(!strcmp(pwd,(char*)password)) { + STRCPY(s->as_login,uname); + STRCPY(s->as_realm,realm); s->as_ok = 1; } } @@ -1852,6 +1867,7 @@ static void handle_logon_request(ioa_socket_handle s, struct http_request* hr) static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { current_socket = s; + current_realm = s->as_realm; if(turn_params.verbose) { if(nbh) { @@ -1864,6 +1880,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) if(!nbh) { write_https_logon_page(s); } else { + ((char*)ioa_network_buffer_data(nbh))[ioa_network_buffer_get_size(nbh)] = 0; struct http_request* hr = parse_http_request((char*)ioa_network_buffer_data(nbh)); if(!hr) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: wrong HTTPS request (I cannot parse it)\n", __FUNCTION__); @@ -1873,9 +1890,19 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) AS_FORM form = get_form(hr->path); switch(form) { - case AS_FORM_PC: + case AS_FORM_PC: { + const char *realm0 = get_http_header_value(hr, HR_REALM); + if(!realm0 || !realm0[0]) + realm0=get_realm(NULL)->options.name; + if(current_socket->as_realm[0]) + realm0 = current_socket->as_realm; + char realm[STUN_MAX_REALM_SIZE + 1]; + STRCPY(realm,realm0); + current_realm = realm; write_pc_page(s); + current_realm = s->as_realm; break; + } case AS_FORM_LOGON: if(!(s->as_ok)) { handle_logon_request(s,hr); @@ -1892,6 +1919,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } current_socket = NULL; + current_realm = NULL; } static void https_input_handler(ioa_socket_handle s, int event_type, ioa_net_data *data, void *arg, int can_resume) { From d21c42a5253b5989b79db77e8ca0e555b1f9c8f8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 14 Jan 2015 09:23:16 +0000 Subject: [PATCH 420/805] parameters page --- src/apps/relay/ns_ioalib_impl.h | 1 + src/apps/relay/turn_admin_server.c | 306 ++++++++++++++++++----------- 2 files changed, 196 insertions(+), 111 deletions(-) diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index b6f67c04..04bd9c42 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -229,6 +229,7 @@ struct _ioa_socket 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]; }; typedef struct _timer_event diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 9d042023..6d651724 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1353,8 +1353,11 @@ int send_turn_session_info(struct turn_session_info* tsi) enum _AS_FORM { AS_FORM_LOGON, + AS_FORM_LOGOUT, AS_FORM_PC, AS_FORM_HOME, + AS_FORM_TOGGLE, + AS_FORM_UPDATE, AS_FORM_UNKNOWN }; @@ -1371,16 +1374,19 @@ struct form_name { static struct form_name form_names[] = { {AS_FORM_LOGON,"/logon"}, + {AS_FORM_LOGOUT,"/logout"}, {AS_FORM_PC,"/pc"}, {AS_FORM_HOME,"/home"}, + {AS_FORM_TOGGLE,"/toggle"}, + {AS_FORM_UPDATE,"/update"}, {AS_FORM_UNKNOWN,NULL} }; static const char* admin_title = "TURN Server (https admin connection)"; -static const char* home_link = "
home page
\r\n"; +static const char* home_link = "
home page
\r\n
Logout

\r\n"; +static const char* logout_link = "
Logout

\r\n"; static ioa_socket_handle current_socket = NULL; -static char* current_realm = NULL; static AS_FORM get_form(const char* path) { if(path) { @@ -1404,7 +1410,7 @@ static void write_https_logon_page(ioa_socket_handle s) str_buffer_append(sb,admin_title); str_buffer_append(sb,"\r\n \r\n \r\n "); str_buffer_append(sb,admin_title); - str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"

\r\n"); str_buffer_append(sb,"
\r\n"); @@ -1448,6 +1454,7 @@ static void write_https_home_page(ioa_socket_handle s) str_buffer_append(sb,"\r\n \r\n \r\n "); str_buffer_append(sb,admin_title); str_buffer_append(sb,"

\r\n"); + str_buffer_append(sb,logout_link); if(current_socket->as_realm[0]) { str_buffer_append(sb,"\r\n"); str_buffer_append(sb,"
Current realm: name:

"); + str_buffer_append(sb,"\" value=\""); + str_buffer_append(sb,current_socket->as_eff_realm); + str_buffer_append(sb,"\">
"); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,"\r\n"); } @@ -1495,80 +1504,71 @@ static void sbprintf(struct str_buffer *sb, const char *format, ...) static void https_print_flag(struct str_buffer* sb, int flag, const char* name, int changeable) { if(sb && name) { - const char *sc=""; - if(changeable) - sc=" (*)"; - sbprintf(sb,"%s%s%s\r\n",name,get_flag(flag),sc); - } -} - -static void https_print_uint(struct str_buffer* sb, unsigned long value, const char* name, int changeable) -{ - if(sb && name) { - const char *sc=""; - if(changeable==1) - sc=" (*)"; - else if(changeable==2) - sc=" (**)"; - sbprintf(sb,"%s%lu%s\r\n",name,value,sc); - } -} - -static void https_print_str(struct str_buffer* sb, const char *value, const char* name, int changeable) -{ - if(sb && name && value) { - if((value[0] == 0) && name[0]) - value="empty"; - const char *sc=""; - if(changeable==1) - sc=" (*)"; - else if(changeable==2) - sc=" (**)"; - sbprintf(sb,"%s%s%s\r\n",name,value,sc); - } -} - -static void https_print_str_array(struct str_buffer* sb, char **value, size_t sz, const char* name, int changeable) -{ - if(sb && name && value && sz) { - const char *sc=""; - if(changeable==1) - sc=" (*)"; - else if(changeable==2) - sc=" (**)"; - size_t i; - for(i=0;i %s %s%s\r\n",name,value[i],sc); + if(current_socket->as_realm[0]) + changeable = 0; + if(!changeable) { + sbprintf(sb,"%s%s\r\n",name,get_flag(flag)); + } else { + sbprintf(sb,"%s%s
toggle\r\n",name,get_flag(flag),name); } } } -static void https_print_addr(struct str_buffer* sb, ioa_addr *value, int use_port, const char* name, int changeable) +static void https_print_uint(struct str_buffer* sb, unsigned long value, const char* name, const char* param_name) +{ + if(sb && name) { + if(current_socket->as_realm[0]) + param_name = 0; + if(!param_name) { + sbprintf(sb,"%s%lu\r\n",name,value); + } else { + sbprintf(sb,"%s%lu
\r\n",name,value,param_name,param_name,value); + } + } +} + +static void https_print_str(struct str_buffer* sb, const char *value, const char* name, const char* param_name) +{ + if(sb && name && value) { + if(current_socket->as_realm[0]) + param_name = 0; + const char *v = value; + if((value[0] == 0) && name[0]) + v="empty"; + if(!param_name) { + sbprintf(sb,"%s%s\r\n",name,v); + } else { + sbprintf(sb,"%s%s
\r\n",name,v,param_name,param_name,value); + } + } +} + +static void https_print_str_array(struct str_buffer* sb, char **value, size_t sz, const char* name) +{ + if(sb && name && value && sz) { + size_t i; + for(i=0;i %s %s\r\n",name,value[i]); + } + } +} + +static void https_print_addr(struct str_buffer* sb, ioa_addr *value, int use_port, const char* name) { if(sb && name && value) { - const char *sc=""; - if(changeable==1) - sc=" (*)"; - else if(changeable==2) - sc=" (**)"; char s[256]; if(!use_port) addr_to_string_no_port(value,(u08bits*)s); else addr_to_string(value,(u08bits*)s); - sbprintf(sb," %s %s%s\r\n",name,s,sc); + sbprintf(sb," %s %s\r\n",name,s); } } -static void https_print_addr_list(struct str_buffer* sb, turn_server_addrs_list_t *value, int use_port, const char* name, int changeable) +static void https_print_addr_list(struct str_buffer* sb, turn_server_addrs_list_t *value, int use_port, const char* name) { if(sb && name && value && value->size && value->addrs) { - const char *sc=""; - if(changeable==1) - sc=" (*)"; - else if(changeable==2) - sc=" (**)"; char s[256]; size_t i; for(i=0;isize;i++) { @@ -1576,34 +1576,60 @@ static void https_print_addr_list(struct str_buffer* sb, turn_server_addrs_list_ addr_to_string_no_port(&(value->addrs[i]),(u08bits*)s); else addr_to_string(&(value->addrs[i]),(u08bits*)s); - sbprintf(sb," %s %s%s\r\n",name,s,sc); + sbprintf(sb," %s %s\r\n",name,s); } } } -static void https_print_ip_range_list(struct str_buffer* sb, ip_range_list_t *value, const char* name, int changeable) +static void https_print_ip_range_list(struct str_buffer* sb, ip_range_list_t *value, const char* name) { if(sb && name && value && value->ranges_number && value->rs) { - const char *sc=""; - if(changeable==1) - sc=" (*)"; - else if(changeable==2) - sc=" (**)"; size_t i; for(i=0;iranges_number;++i) { if(value->rs[i].realm[0]) { - if(current_realm && current_realm[0] && strcmp(current_realm,value->rs[i].realm)) { + if(current_socket->as_eff_realm[0] && strcmp(current_socket->as_eff_realm,value->rs[i].realm)) { continue; } else { - sbprintf(sb," %s %s (%s)%s\r\n",name,value->rs[i].str,value->rs[i].realm,sc); + sbprintf(sb," %s %s (%s)\r\n",name,value->rs[i].str,value->rs[i].realm); } } else { - sbprintf(sb," %s %s%s\r\n",name,value->rs[i].str,sc); + sbprintf(sb," %s %s\r\n",name,value->rs[i].str); } } } } +static void toggle_param(const char* pn) +{ + if(pn) { + int i=0; + while(tcmds[i].cmd && tcmds[i].data) { + if(strcmp(tcmds[i].cmd,pn) == 0) { + *(tcmds[i].data) = !(*(tcmds[i].data)); + return; + } + ++i; + } + } +} + +static void update_param(const char* pn, const char *value) +{ + if(pn) { + if(!value) + value = "0"; + if(strstr(pn,"total-quota")==pn) { + turn_params.total_quota = atoi(value); + } else if(strstr(pn,"user-quota")==pn) { + turn_params.user_quota = atoi(value); + } else if(strstr(pn,"max-bps")==pn) { + set_max_bps((band_limit_t)atol(value)); + } else if(strstr(pn,"bps-capacity")==pn) { + set_bps_capacity((band_limit_t)atol(value)); + } + } +} + static void write_pc_page(ioa_socket_handle s) { if(s && !ioa_socket_tobeclosed(s)) { @@ -1616,12 +1642,17 @@ static void write_pc_page(ioa_socket_handle s) str_buffer_append(sb,"\r\n\r\n \r\n "); str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,"\r\n \r\n \r\n "); str_buffer_append(sb,admin_title); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,home_link); str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,"Config Parameters:
\r\n"); + str_buffer_append(sb,"Config Parameters:
\r\n"); + str_buffer_append(sb,"\r\n"); { https_print_flag(sb,turn_params.verbose,"verbose",0); @@ -1680,7 +1711,7 @@ static void write_pc_page(ioa_socket_handle s) https_print_str(sb,"","",0); - https_print_str_array(sb,turn_params.listener.addrs,turn_params.listener.addrs_number,"Listener addr",0); + https_print_str_array(sb,turn_params.listener.addrs,turn_params.listener.addrs_number,"Listener addr"); if(turn_params.listener_ifname[0]) https_print_str(sb,turn_params.listener_ifname,"listener-ifname",0); @@ -1700,17 +1731,17 @@ static void write_pc_page(ioa_socket_handle s) https_print_uint(sb,(unsigned long)turn_params.alt_listener_port,"alt-listener-port",0); https_print_uint(sb,(unsigned long)turn_params.alt_tls_listener_port,"alt-tls-listener-port",0); - https_print_addr(sb,turn_params.external_ip,0,"External public IP",0); + https_print_addr(sb,turn_params.external_ip,0,"External public IP"); https_print_str(sb,"","",0); - https_print_addr_list(sb,&turn_params.aux_servers_list,1,"Aux server",0); - https_print_addr_list(sb,&turn_params.alternate_servers_list,1,"Alternate server",0); - https_print_addr_list(sb,&turn_params.tls_alternate_servers_list,1,"TLS alternate server",0); + https_print_addr_list(sb,&turn_params.aux_servers_list,1,"Aux server"); + https_print_addr_list(sb,&turn_params.alternate_servers_list,1,"Alternate server"); + https_print_addr_list(sb,&turn_params.tls_alternate_servers_list,1,"TLS alternate server"); https_print_str(sb,"","",0); - https_print_str_array(sb,turn_params.relay_addrs,turn_params.relays_number,"Relay addr",0); + https_print_str_array(sb,turn_params.relay_addrs,turn_params.relays_number,"Relay addr"); if(turn_params.relay_ifname[0]) https_print_str(sb,turn_params.relay_ifname,"relay-ifname",0); @@ -1723,17 +1754,17 @@ static void write_pc_page(ioa_socket_handle s) https_print_uint(sb,(unsigned long)turn_params.min_port,"min-port",0); https_print_uint(sb,(unsigned long)turn_params.max_port,"max-port",0); - https_print_ip_range_list(sb,&turn_params.ip_whitelist,"Whitelist IP (static)",0); + https_print_ip_range_list(sb,&turn_params.ip_whitelist,"Whitelist IP (static)"); { ip_range_list_t* l = get_ip_list("allowed"); - https_print_ip_range_list(sb,l,"Whitelist IP (dynamic)",0); + https_print_ip_range_list(sb,l,"Whitelist IP (dynamic)"); ip_list_free(l); } - https_print_ip_range_list(sb,&turn_params.ip_blacklist,"Blacklist IP (static)",0); + https_print_ip_range_list(sb,&turn_params.ip_blacklist,"Blacklist IP (static)"); { ip_range_list_t* l = get_ip_list("denied"); - https_print_ip_range_list(sb,l,"Blacklist IP (dynamic)",0); + https_print_ip_range_list(sb,l,"Blacklist IP (dynamic)"); ip_list_free(l); } @@ -1801,11 +1832,11 @@ static void write_pc_page(ioa_socket_handle s) https_print_str(sb,"","",0); - realm_params_t *rp = get_realm(current_realm); + realm_params_t *rp = get_realm(current_socket->as_eff_realm); if(!rp) rp = get_realm(NULL); - if(current_realm) - https_print_str(sb,current_realm,"current realm",0); + if(current_socket->as_eff_realm[0]) + https_print_str(sb,current_socket->as_eff_realm,"current realm",0); https_print_uint(sb,(unsigned long)rp->options.perf_options.total_quota,"current realm total-quota",0); https_print_uint(sb,(unsigned long)rp->options.perf_options.user_quota,"current realm user-quota",0); @@ -1817,11 +1848,11 @@ static void write_pc_page(ioa_socket_handle s) https_print_str(sb,"","",0); - https_print_uint(sb,(unsigned long)turn_params.total_quota,"Default total-quota",2); - https_print_uint(sb,(unsigned long)turn_params.user_quota,"Default user-quota",2); - https_print_uint(sb,(unsigned long)get_bps_capacity(),"Total server bps-capacity",2); + https_print_uint(sb,(unsigned long)turn_params.total_quota,"Default total-quota","total-quota"); + https_print_uint(sb,(unsigned long)turn_params.user_quota,"Default user-quota","user-quota"); + https_print_uint(sb,(unsigned long)get_bps_capacity(),"Total server bps-capacity","bps-capacity"); https_print_uint(sb,(unsigned long)get_bps_capacity_allocated(),"Allocated bps-capacity",0); - https_print_uint(sb,(unsigned long)get_max_bps(),"Default max-bps",2); + https_print_uint(sb,(unsigned long)get_max_bps(),"Default max-bps","max-bps"); } str_buffer_append(sb,"\r\n
ParameterCurrent Value"); + if(!(current_socket->as_realm[0])) { + str_buffer_append(sb,"New (ephemeral) Value"); + } + str_buffer_append(sb,"
\r\n\r\n"); @@ -1840,6 +1871,24 @@ static void write_pc_page(ioa_socket_handle s) } } +static void handle_toggle_request(ioa_socket_handle s, struct http_request* hr) +{ + if(s && hr) { + const char *param = get_http_header_value(hr, "parameter"); + toggle_param(param); + } +} + +static void handle_update_request(ioa_socket_handle s, struct http_request* hr) +{ + if(s && hr) { + const char *param = get_http_header_value(hr, "parameter"); + if(param) { + update_param(param,get_http_header_value(hr,param)); + } + } +} + static void handle_logon_request(ioa_socket_handle s, struct http_request* hr) { if(s && hr) { @@ -1856,6 +1905,7 @@ static void handle_logon_request(ioa_socket_handle s, struct http_request* hr) if(!strcmp(pwd,(char*)password)) { STRCPY(s->as_login,uname); STRCPY(s->as_realm,realm); + STRCPY(s->as_eff_realm,realm); s->as_ok = 1; } } @@ -1864,10 +1914,20 @@ static void handle_logon_request(ioa_socket_handle s, struct http_request* hr) } } +static void handle_logout_request(ioa_socket_handle s, struct http_request* hr) +{ + UNUSED_ARG(hr); + if(s) { + s->as_login[0] = 0; + s->as_ok = 0; + s->as_realm[0] = 0; + s->as_eff_realm[0] = 0; + } +} + static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) { current_socket = s; - current_realm = s->as_realm; if(turn_params.verbose) { if(nbh) { @@ -1891,35 +1951,59 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) switch(form) { case AS_FORM_PC: { - const char *realm0 = get_http_header_value(hr, HR_REALM); - if(!realm0 || !realm0[0]) - realm0=get_realm(NULL)->options.name; - if(current_socket->as_realm[0]) - realm0 = current_socket->as_realm; - char realm[STUN_MAX_REALM_SIZE + 1]; - STRCPY(realm,realm0); - current_realm = realm; - write_pc_page(s); - current_realm = s->as_realm; - break; - } - case AS_FORM_LOGON: - if(!(s->as_ok)) { - handle_logon_request(s,hr); - } - default: if(s->as_ok) { - write_https_home_page(s); + const char *realm0 = get_http_header_value(hr, HR_REALM); + if(!realm0 || !realm0[0]) + realm0=get_realm(NULL)->options.name; + if(current_socket->as_realm[0]) + realm0 = current_socket->as_realm; + STRCPY(current_socket->as_eff_realm,realm0); + write_pc_page(s); } else { write_https_logon_page(s); } + break; + } + case AS_FORM_TOGGLE: + if(s->as_ok) { + handle_toggle_request(s,hr); + write_pc_page(s); + } else { + write_https_logon_page(s); + } + break; + case AS_FORM_UPDATE: + if(s->as_ok) { + handle_update_request(s,hr); + write_pc_page(s); + } else { + write_https_logon_page(s); + } + break; + case AS_FORM_LOGON: + if(!(s->as_ok)) { + handle_logon_request(s,hr); + if(s->as_ok) { + write_https_home_page(s); + } else { + write_https_logon_page(s); + } + } else { + write_https_home_page(s); + } + break; + case AS_FORM_LOGOUT: + handle_logout_request(s,hr); + write_https_logon_page(s); + break; + default: + write_https_home_page(s); }; free_http_request(hr); } } current_socket = NULL; - current_realm = NULL; } static void https_input_handler(ioa_socket_handle s, int event_type, ioa_net_data *data, void *arg, int can_resume) { From 17de1a8e1209e950bf5a8708845d6ed58da307e3 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 14 Jan 2015 21:28:41 +0000 Subject: [PATCH 421/805] pc page --- src/apps/relay/turn_admin_server.c | 95 +++++++++++++++++------------- 1 file changed, 54 insertions(+), 41 deletions(-) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 6d651724..7b8122dc 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1388,6 +1388,10 @@ static const char* logout_link = "
Logout

\r\n static ioa_socket_handle current_socket = NULL; +static int is_superuser(void) { + return !(current_socket->as_realm[0]); +} + static AS_FORM get_form(const char* path) { if(path) { size_t i = 0; @@ -1456,7 +1460,7 @@ static void write_https_home_page(ioa_socket_handle s) str_buffer_append(sb,"

\r\n"); str_buffer_append(sb,logout_link); - if(current_socket->as_realm[0]) { + if(!is_superuser()) { str_buffer_append(sb,"Config Parameters
\r\n"); @@ -1501,15 +1505,15 @@ static void sbprintf(struct str_buffer *sb, const char *format, ...) } } -static void https_print_flag(struct str_buffer* sb, int flag, const char* name, int changeable) +static void https_print_flag(struct str_buffer* sb, int flag, const char* name, const char* param_name) { if(sb && name) { - if(current_socket->as_realm[0]) - changeable = 0; - if(!changeable) { + if(!is_superuser()) + param_name = 0; + if(!param_name) { sbprintf(sb,"%s%s\r\n",name,get_flag(flag)); } else { - sbprintf(sb,"%s%stoggle\r\n",name,get_flag(flag),name); + sbprintf(sb,"%s%stoggle\r\n",name,get_flag(flag),param_name); } } } @@ -1517,7 +1521,7 @@ static void https_print_flag(struct str_buffer* sb, int flag, const char* name, static void https_print_uint(struct str_buffer* sb, unsigned long value, const char* name, const char* param_name) { if(sb && name) { - if(current_socket->as_realm[0]) + if(!is_superuser()) param_name = 0; if(!param_name) { sbprintf(sb,"%s%lu\r\n",name,value); @@ -1530,7 +1534,7 @@ static void https_print_uint(struct str_buffer* sb, unsigned long value, const c static void https_print_str(struct str_buffer* sb, const char *value, const char* name, const char* param_name) { if(sb && name && value) { - if(current_socket->as_realm[0]) + if(!is_superuser()) param_name = 0; const char *v = value; if((value[0] == 0) && name[0]) @@ -1601,31 +1605,35 @@ static void https_print_ip_range_list(struct str_buffer* sb, ip_range_list_t *va static void toggle_param(const char* pn) { - if(pn) { - int i=0; - while(tcmds[i].cmd && tcmds[i].data) { - if(strcmp(tcmds[i].cmd,pn) == 0) { - *(tcmds[i].data) = !(*(tcmds[i].data)); - return; + if(is_superuser()) { + if(pn) { + int i=0; + while(tcmds[i].cmd && tcmds[i].data) { + if(strcmp(tcmds[i].cmd,pn) == 0) { + *(tcmds[i].data) = !(*(tcmds[i].data)); + return; + } + ++i; } - ++i; } } } static void update_param(const char* pn, const char *value) { - if(pn) { - if(!value) - value = "0"; - if(strstr(pn,"total-quota")==pn) { - turn_params.total_quota = atoi(value); - } else if(strstr(pn,"user-quota")==pn) { - turn_params.user_quota = atoi(value); - } else if(strstr(pn,"max-bps")==pn) { - set_max_bps((band_limit_t)atol(value)); - } else if(strstr(pn,"bps-capacity")==pn) { - set_bps_capacity((band_limit_t)atol(value)); + if(is_superuser()) { + if(pn) { + if(!value) + value = "0"; + if(strstr(pn,"total-quota")==pn) { + turn_params.total_quota = atoi(value); + } else if(strstr(pn,"user-quota")==pn) { + turn_params.user_quota = atoi(value); + } else if(strstr(pn,"max-bps")==pn) { + set_max_bps((band_limit_t)atol(value)); + } else if(strstr(pn,"bps-capacity")==pn) { + set_bps_capacity((band_limit_t)atol(value)); + } } } } @@ -1649,7 +1657,7 @@ static void write_pc_page(ioa_socket_handle s) str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,"Config Parameters:
\r\n"); str_buffer_append(sb,"\r\n"); @@ -1657,16 +1665,16 @@ static void write_pc_page(ioa_socket_handle s) { https_print_flag(sb,turn_params.verbose,"verbose",0); https_print_flag(sb,turn_params.turn_daemon,"daemon process",0); - https_print_flag(sb,turn_params.stale_nonce,"stale-nonce",1); - https_print_flag(sb,turn_params.stun_only,"stun-only",1); - https_print_flag(sb,turn_params.no_stun,"no-stun",1); - https_print_flag(sb,turn_params.secure_stun,"secure-stun",1); + https_print_flag(sb,turn_params.stale_nonce,"stale-nonce","stale-nonce"); + https_print_flag(sb,turn_params.stun_only,"stun-only","stun-only"); + https_print_flag(sb,turn_params.no_stun,"no-stun","no-stun"); + https_print_flag(sb,turn_params.secure_stun,"secure-stun","secure-stun"); https_print_flag(sb,turn_params.do_not_use_config_file,"do-not-use-config-file",0); https_print_flag(sb,turn_params.rfc5780,"RFC5780 support",0); https_print_uint(sb,(unsigned int)turn_params.net_engine_version,"net engine version",0); https_print_str(sb,turn_params.net_engine_version_txt[(int)turn_params.net_engine_version],"net engine",0); https_print_flag(sb,turn_params.fingerprint,"enforce fingerprints",0); - https_print_flag(sb,turn_params.mobility,"mobility",1); + https_print_flag(sb,turn_params.mobility,"mobility","mobility"); https_print_flag(sb,turn_params.udp_self_balance,"udp-self-balance",0); https_print_str(sb,turn_params.pidfile,"pidfile",0); https_print_uint(sb,(unsigned long)getuid(),"process user ID",0); @@ -1748,8 +1756,8 @@ static void write_pc_page(ioa_socket_handle s) https_print_flag(sb,turn_params.server_relay,"server-relay",0); - https_print_flag(sb,turn_params.no_udp_relay,"no-udp-relay",1); - https_print_flag(sb,turn_params.no_tcp_relay,"no-tcp-relay",1); + https_print_flag(sb,turn_params.no_udp_relay,"no-udp-relay","no-udp-relay"); + https_print_flag(sb,turn_params.no_tcp_relay,"no-tcp-relay","no-tcp-relay"); https_print_uint(sb,(unsigned long)turn_params.min_port,"min-port",0); https_print_uint(sb,(unsigned long)turn_params.max_port,"max-port",0); @@ -1768,8 +1776,8 @@ static void write_pc_page(ioa_socket_handle s) ip_list_free(l); } - https_print_flag(sb,turn_params.no_multicast_peers,"no-multicast-peers",1); - https_print_flag(sb,turn_params.no_loopback_peers,"no-loopback-peers",1); + https_print_flag(sb,turn_params.no_multicast_peers,"no-multicast-peers","no-multicast-peers"); + https_print_flag(sb,turn_params.no_loopback_peers,"no-loopback-peers","no-loopback-peers"); https_print_str(sb,"","",0); @@ -1803,20 +1811,25 @@ static void write_pc_page(ioa_socket_handle s) default: https_print_str(sb,"unknown","DB type",0); }; - https_print_str(sb,turn_params.default_users_db.persistent_users_db.userdb,"DB",0); + if(is_superuser()) { + https_print_str(sb,turn_params.default_users_db.persistent_users_db.userdb,"DB",0); + } } else { https_print_str(sb,"none","DB type",0); https_print_str(sb,"none","DB",0); } #if !defined(TURN_NO_HIREDIS) - if(turn_params.use_redis_statsdb && turn_params.redis_statsdb[0]) - https_print_str(sb,turn_params.redis_statsdb,"Redis Statistics DB",0); + if(is_superuser()) { + if(turn_params.use_redis_statsdb && turn_params.redis_statsdb[0]) { + https_print_str(sb,turn_params.redis_statsdb,"Redis Statistics DB",0); + } + } #endif https_print_str(sb,"","",0); - { + if(is_superuser()) { char * rn = get_realm(NULL)->options.name; if(rn[0]) https_print_str(sb,rn,"Default realm",0); @@ -1955,7 +1968,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) const char *realm0 = get_http_header_value(hr, HR_REALM); if(!realm0 || !realm0[0]) realm0=get_realm(NULL)->options.name; - if(current_socket->as_realm[0]) + if(!is_superuser()) realm0 = current_socket->as_realm; STRCPY(current_socket->as_eff_realm,realm0); write_pc_page(s); From 827b1db525af846c955d7532e55f74dc70c30fea Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 15 Jan 2015 05:44:06 +0000 Subject: [PATCH 422/805] connection establishment communication procedure improvements --- src/apps/relay/dtls_listener.c | 4 +++- src/apps/relay/netengine.c | 10 ++++++++-- src/apps/relay/ns_ioalib_engine_impl.c | 24 +++++++++++++++--------- src/server/ns_turn_server.c | 17 +++++++++++------ 4 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index f4428411..cddd0768 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -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; + } } } diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 30843744..7ae2d0ee 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -742,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); @@ -780,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); diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 59104bf0..f4dd6a1c 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -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; @@ -2401,11 +2402,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. */ } @@ -3298,14 +3299,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: diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 1bff8006..d8a84ef5 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4320,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) @@ -4555,8 +4556,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); } @@ -4582,8 +4585,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); From 3ff446b90ef78b01f9cedf6324ac140da7664aa2 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 15 Jan 2015 08:37:48 +0000 Subject: [PATCH 423/805] sessions page --- src/apps/relay/http_server.c | 7 + src/apps/relay/http_server.h | 1 + src/apps/relay/turn_admin_server.c | 214 +++++++++++++++++++++++++++-- 3 files changed, 207 insertions(+), 15 deletions(-) diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index d731abca..2d47d325 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -312,6 +312,13 @@ void str_buffer_append_sz(struct str_buffer* sb, size_t 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) { diff --git a/src/apps/relay/http_server.h b/src/apps/relay/http_server.h index ef400326..8bb3f26d 100644 --- a/src/apps/relay/http_server.h +++ b/src/apps/relay/http_server.h @@ -73,6 +73,7 @@ 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); diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 7b8122dc..f2150f15 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1358,6 +1358,7 @@ enum _AS_FORM { AS_FORM_HOME, AS_FORM_TOGGLE, AS_FORM_UPDATE, + AS_FORM_PS, AS_FORM_UNKNOWN }; @@ -1379,6 +1380,7 @@ static struct form_name form_names[] = { {AS_FORM_HOME,"/home"}, {AS_FORM_TOGGLE,"/toggle"}, {AS_FORM_UPDATE,"/update"}, + {AS_FORM_PS,"/ps"}, {AS_FORM_UNKNOWN,NULL} }; @@ -1460,22 +1462,31 @@ static void write_https_home_page(ioa_socket_handle s) str_buffer_append(sb,"

\r\n"); str_buffer_append(sb,logout_link); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
Actions:\r\n"); + + str_buffer_append(sb," Realm name: as_eff_realm); + str_buffer_append(sb,"\""); if(!is_superuser()) { - str_buffer_append(sb,"Config Parameters
\r\n"); - } else { - str_buffer_append(sb,"\r\n"); - str_buffer_append(sb,"
Current realm: name:
as_eff_realm); - str_buffer_append(sb,"\">
"); - str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,"\r\n"); + str_buffer_append(sb," disabled "); } + str_buffer_append(sb,">
"); + + str_buffer_append(sb,"
"); + + str_buffer_append(sb,"
"); + + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"\r\n"); str_buffer_append(sb,"\r\n \r\n\r\n"); @@ -1655,7 +1666,7 @@ static void write_pc_page(ioa_socket_handle s) str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,home_link); str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,"Config Parameters:
ParameterCurrent Value"); - if(!(current_socket->as_realm[0])) { + if(is_superuser()) { str_buffer_append(sb,"New (ephemeral) Value"); } str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"Configuration Parameters:
\r\n"); str_buffer_append(sb,""); + } + } + + csarg->counter += 1; + } + return 0; +} + +static void https_print_sessions(struct str_buffer* sb) +{ + struct https_ps_arg arg = {sb,0,0}; + + arg.ct = turn_time(); + + ur_map_foreach_arg(cliserver.sessions, (foreachcb_arg_type)https_print_session, &arg); +} + +static void write_ps_page(ioa_socket_handle s) +{ + if(s && !ioa_socket_tobeclosed(s)) { + + if(!(s->as_ok)) { + write_https_logon_page(s); + } else { + + struct str_buffer* sb = str_buffer_new(); + + str_buffer_append(sb,"\r\n\r\n \r\n "); + str_buffer_append(sb,admin_title); + str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,admin_title); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,home_link); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"TURN Sessions:
ParameterCurrent Value"); if(is_superuser()) { str_buffer_append(sb,"New (ephemeral) Value"); @@ -1884,6 +1895,165 @@ static void write_pc_page(ioa_socket_handle s) } } +struct https_ps_arg { + struct str_buffer* sb; + size_t counter; + turn_time_t ct; +}; + +static int https_print_session(ur_map_key_type key, ur_map_value_type value, void *arg) +{ + if(key && value && arg) { + struct https_ps_arg *csarg = (struct https_ps_arg*)arg; + struct str_buffer* sb = csarg->sb; + struct turn_session_info *tsi = (struct turn_session_info *)value; + + if(current_socket->as_eff_realm[0] && strcmp(current_socket->as_eff_realm,tsi->realm)) + return 0; + + if((unsigned long)csarg->counter<(unsigned long)cli_max_output_sessions) { + str_buffer_append(sb,"
"); + str_buffer_append_sz(sb,(size_t)(csarg->counter+1)); + str_buffer_append(sb,""); + str_buffer_append_sid(sb,tsi->id); + str_buffer_append(sb,""); + str_buffer_append(sb,(char*)tsi->username); + str_buffer_append(sb,""); + str_buffer_append(sb,tsi->realm); + str_buffer_append(sb,""); + str_buffer_append(sb,tsi->origin); + str_buffer_append(sb,""); + if(turn_time_before(csarg->ct, tsi->start_time)) { + str_buffer_append(sb,"undefined time\n"); + } else { + str_buffer_append_sz(sb,(size_t)(csarg->ct - tsi->start_time)); + } + str_buffer_append(sb,""); + if(turn_time_before(tsi->expiration_time,csarg->ct)) { + str_buffer_append(sb,"expired"); + } else { + str_buffer_append_sz(sb,(size_t)(tsi->expiration_time - csarg->ct)); + } + str_buffer_append(sb,""); + str_buffer_append(sb,pname(tsi->client_protocol)); + str_buffer_append(sb,""); + str_buffer_append(sb,pname(tsi->peer_protocol)); + str_buffer_append(sb,""); + { + if(!tsi->local_addr_data.saddr[0]) + addr_to_string(&(tsi->local_addr_data.addr),(u08bits*)tsi->local_addr_data.saddr); + if(!tsi->remote_addr_data.saddr[0]) + addr_to_string(&(tsi->remote_addr_data.addr),(u08bits*)tsi->remote_addr_data.saddr); + if(!tsi->relay_addr_data_ipv4.saddr[0]) + addr_to_string(&(tsi->relay_addr_data_ipv4.addr),(u08bits*)tsi->relay_addr_data_ipv4.saddr); + if(!tsi->relay_addr_data_ipv6.saddr[0]) + addr_to_string(&(tsi->relay_addr_data_ipv6.addr),(u08bits*)tsi->relay_addr_data_ipv6.saddr); + str_buffer_append(sb,tsi->remote_addr_data.saddr); + str_buffer_append(sb,""); + str_buffer_append(sb,tsi->local_addr_data.saddr); + str_buffer_append(sb,""); + str_buffer_append(sb,tsi->relay_addr_data_ipv4.saddr); + str_buffer_append(sb,""); + str_buffer_append(sb,tsi->relay_addr_data_ipv6.saddr); + str_buffer_append(sb,""); + str_buffer_append(sb,get_flag(tsi->enforce_fingerprints)); + str_buffer_append(sb,""); + str_buffer_append(sb,get_flag(tsi->is_mobile)); + str_buffer_append(sb,""); + str_buffer_append(sb,tsi->tls_method); + str_buffer_append(sb,""); + str_buffer_append(sb,tsi->tls_cipher); + str_buffer_append(sb,""); + str_buffer_append_sz(sb,(size_t)tsi->bps); + str_buffer_append(sb,""); + { + char str[1025]; + snprintf(str,sizeof(str)-1,"rp=%lu, rb=%lu, sp=%lu, sb=%lu\n",(unsigned long)(tsi->received_packets), (unsigned long)(tsi->received_bytes),(unsigned long)(tsi->sent_packets),(unsigned long)(tsi->sent_bytes)); + str_buffer_append(sb,str); + str_buffer_append(sb,""); + } + { + char str[1025]; + snprintf(str,sizeof(str)-1,"r=%lu, s=%lu, total=%lu (bytes per sec)\n",(unsigned long)(tsi->received_rate), (unsigned long)(tsi->sent_rate),(unsigned long)(tsi->total_rate)); + str_buffer_append(sb,str); + str_buffer_append(sb,""); + } + + if(tsi->main_peers_size) { + size_t i; + for(i=0;imain_peers_size;++i) { + if(!(tsi->main_peers_data[i].saddr[0])) + addr_to_string(&(tsi->main_peers_data[i].addr),(u08bits*)tsi->main_peers_data[i].saddr); + str_buffer_append(sb," "); + str_buffer_append(sb,tsi->main_peers_data[i].saddr); + str_buffer_append(sb," "); + } + if(tsi->extra_peers_size && tsi->extra_peers_data) { + for(i=0;iextra_peers_size;++i) { + if(!(tsi->extra_peers_data[i].saddr[0])) + addr_to_string(&(tsi->extra_peers_data[i].addr),(u08bits*)tsi->extra_peers_data[i].saddr); + str_buffer_append(sb," "); + str_buffer_append(sb,tsi->extra_peers_data[i].saddr); + str_buffer_append(sb," "); + } + } + } + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"\r\n"); + + https_print_sessions(sb); + + str_buffer_append(sb,"\r\n
NSession IDUserRealmOriginAge, secsExpires, secsClient protocolRelay protocolClient addrServer addrRelay addr (IPv4)Relay addr (IPv6)FingerprintsMobileTLS methodTLS cipherBPS (allocated)PacketsRatePeers
\r\n\r\n"); + + send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); + send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); + send_str_from_ioa_socket_tcp(s,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + + send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); + + send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); + send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); + + str_buffer_free(sb); + } + } +} + static void handle_toggle_request(ioa_socket_handle s, struct http_request* hr) { if(s && hr) { @@ -1977,6 +2147,20 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } break; } + case AS_FORM_PS: { + if(s->as_ok) { + const char *realm0 = get_http_header_value(hr, HR_REALM); + if(!realm0 || !realm0[0]) + realm0=get_realm(NULL)->options.name; + if(!is_superuser()) + realm0 = current_socket->as_realm; + STRCPY(current_socket->as_eff_realm,realm0); + write_ps_page(s); + } else { + write_https_logon_page(s); + } + break; + } case AS_FORM_TOGGLE: if(s->as_ok) { handle_toggle_request(s,hr); From 814cfcd36cf26135b4160bf69708637dc6e76d66 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 16 Jan 2015 06:50:25 +0000 Subject: [PATCH 424/805] realm fixes --- src/apps/relay/turn_admin_server.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index f2150f15..baff6631 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1394,6 +1394,12 @@ static int is_superuser(void) { return !(current_socket->as_realm[0]); } +static char* get_eff_realm(void) { + if(current_socket->as_realm[0]) + return current_socket->as_realm; + return current_socket->as_eff_realm; +} + static AS_FORM get_form(const char* path) { if(path) { size_t i = 0; @@ -1470,7 +1476,7 @@ static void write_https_home_page(ioa_socket_handle s) str_buffer_append(sb," Realm name: as_eff_realm); + str_buffer_append(sb,get_eff_realm()); str_buffer_append(sb,"\""); if(!is_superuser()) { str_buffer_append(sb," disabled "); @@ -1602,7 +1608,7 @@ static void https_print_ip_range_list(struct str_buffer* sb, ip_range_list_t *va size_t i; for(i=0;iranges_number;++i) { if(value->rs[i].realm[0]) { - if(current_socket->as_eff_realm[0] && strcmp(current_socket->as_eff_realm,value->rs[i].realm)) { + if(get_eff_realm()[0] && strcmp(get_eff_realm(),value->rs[i].realm)) { continue; } else { sbprintf(sb," %s %s (%s)\r\n",name,value->rs[i].str,value->rs[i].realm); @@ -1856,11 +1862,11 @@ static void write_pc_page(ioa_socket_handle s) https_print_str(sb,"","",0); - realm_params_t *rp = get_realm(current_socket->as_eff_realm); + realm_params_t *rp = get_realm(get_eff_realm()); if(!rp) rp = get_realm(NULL); - if(current_socket->as_eff_realm[0]) - https_print_str(sb,current_socket->as_eff_realm,"current realm",0); + if(get_eff_realm()[0]) + https_print_str(sb,get_eff_realm(),"current realm",0); https_print_uint(sb,(unsigned long)rp->options.perf_options.total_quota,"current realm total-quota",0); https_print_uint(sb,(unsigned long)rp->options.perf_options.user_quota,"current realm user-quota",0); @@ -1908,7 +1914,7 @@ static int https_print_session(ur_map_key_type key, ur_map_value_type value, voi struct str_buffer* sb = csarg->sb; struct turn_session_info *tsi = (struct turn_session_info *)value; - if(current_socket->as_eff_realm[0] && strcmp(current_socket->as_eff_realm,tsi->realm)) + if(get_eff_realm()[0] && strcmp(get_eff_realm(),tsi->realm)) return 0; if((unsigned long)csarg->counter<(unsigned long)cli_max_output_sessions) { @@ -2088,7 +2094,7 @@ static void handle_logon_request(ioa_socket_handle s, struct http_request* hr) if(!strcmp(pwd,(char*)password)) { STRCPY(s->as_login,uname); STRCPY(s->as_realm,realm); - STRCPY(s->as_eff_realm,realm); + s->as_eff_realm[0]=0; s->as_ok = 1; } } @@ -2136,8 +2142,8 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) case AS_FORM_PC: { if(s->as_ok) { const char *realm0 = get_http_header_value(hr, HR_REALM); - if(!realm0 || !realm0[0]) - realm0=get_realm(NULL)->options.name; + if(!realm0) + realm0=""; if(!is_superuser()) realm0 = current_socket->as_realm; STRCPY(current_socket->as_eff_realm,realm0); @@ -2150,8 +2156,8 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) case AS_FORM_PS: { if(s->as_ok) { const char *realm0 = get_http_header_value(hr, HR_REALM); - if(!realm0 || !realm0[0]) - realm0=get_realm(NULL)->options.name; + if(!realm0) + realm0=""; if(!is_superuser()) realm0 = current_socket->as_realm; STRCPY(current_socket->as_eff_realm,realm0); From 90216cf5d4929f4f47f90ce1e1bb2988e4d656d8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 16 Jan 2015 07:59:18 +0000 Subject: [PATCH 425/805] sessions filter --- src/apps/relay/turn_admin_server.c | 130 ++++++++++++++++++++++++++--- src/server/ns_turn_server.c | 1 + 2 files changed, 119 insertions(+), 12 deletions(-) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index baff6631..ae02a411 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1367,6 +1367,9 @@ typedef enum _AS_FORM AS_FORM; #define HR_USERNAME "uname" #define HR_PASSWORD "pwd" #define HR_REALM "realm" +#define HR_CLIENT_PROTOCOL "cprotocol" +#define HR_USER_PATTERN "puser" +#define HR_MAX_SESSIONS "maxsess" struct form_name { AS_FORM form; @@ -1384,7 +1387,8 @@ static struct form_name form_names[] = { {AS_FORM_UNKNOWN,NULL} }; -static const char* admin_title = "TURN Server (https admin connection)"; +#define admin_title "TURN Server (https admin connection)" +#define bold_admin_title ""admin_title"" static const char* home_link = "
home page
\r\n
Logout

\r\n"; static const char* logout_link = "
Logout

\r\n"; @@ -1421,7 +1425,7 @@ static void write_https_logon_page(ioa_socket_handle s) str_buffer_append(sb,"\r\n\r\n \r\n "); str_buffer_append(sb,admin_title); str_buffer_append(sb,"\r\n \r\n \r\n "); - str_buffer_append(sb,admin_title); + str_buffer_append(sb,bold_admin_title); str_buffer_append(sb,"

\r\n"); str_buffer_append(sb,"
\r\n\r\n \r\n "); str_buffer_append(sb,admin_title); str_buffer_append(sb,"\r\n \r\n \r\n "); - str_buffer_append(sb,admin_title); + str_buffer_append(sb,bold_admin_title); str_buffer_append(sb,"

\r\n"); str_buffer_append(sb,logout_link); @@ -1489,6 +1493,10 @@ static void write_https_home_page(ioa_socket_handle s) str_buffer_append(sb,"
"); str_buffer_append(sb,"
\r\n"); @@ -1668,7 +1676,7 @@ static void write_pc_page(ioa_socket_handle s) str_buffer_append(sb,"\r\n\r\n \r\n "); str_buffer_append(sb,admin_title); str_buffer_append(sb,"\r\n \r\n \r\n "); - str_buffer_append(sb,admin_title); + str_buffer_append(sb,bold_admin_title); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,home_link); str_buffer_append(sb,"
\r\n"); @@ -1905,6 +1913,9 @@ struct https_ps_arg { struct str_buffer* sb; size_t counter; turn_time_t ct; + const char* client_protocol; + const char* user_pattern; + size_t max_sessions; }; static int https_print_session(ur_map_key_type key, ur_map_value_type value, void *arg) @@ -1917,7 +1928,36 @@ static int https_print_session(ur_map_key_type key, ur_map_value_type value, voi if(get_eff_realm()[0] && strcmp(get_eff_realm(),tsi->realm)) return 0; - if((unsigned long)csarg->counter<(unsigned long)cli_max_output_sessions) { + { + if(csarg->user_pattern[0]) { + if(!strstr((char*)tsi->username,csarg->user_pattern)) { + return 0; + } + } + } + + { + const char *pn=csarg->client_protocol; + if(pn[0]) { + if(!strcmp(pn,"TLS") || !strcmp(pn,"tls") || !strcmp(pn,"Tls")) { + if(tsi->client_protocol != TLS_SOCKET) + return 0; + } else if(!strcmp(pn,"DTLS") || !strcmp(pn,"dtls") || !strcmp(pn,"Dtls")) { + if(tsi->client_protocol != DTLS_SOCKET) + return 0; + } else if(!strcmp(pn,"TCP") || !strcmp(pn,"tcp") || !strcmp(pn,"Tcp")) { + if(tsi->client_protocol != TCP_SOCKET) + return 0; + } else if(!strcmp(pn,"UDP") || !strcmp(pn,"udp") || !strcmp(pn,"Udp")) { + if(tsi->client_protocol != UDP_SOCKET) + return 0; + } else { + return 0; + } + } + } + + if((unsigned long)csarg->counter<(unsigned long)csarg->max_sessions) { str_buffer_append(sb,""); str_buffer_append_sz(sb,(size_t)(csarg->counter+1)); str_buffer_append(sb,""); @@ -2013,16 +2053,18 @@ static int https_print_session(ur_map_key_type key, ur_map_value_type value, voi return 0; } -static void https_print_sessions(struct str_buffer* sb) +static size_t https_print_sessions(struct str_buffer* sb, const char* client_protocol, const char* user_pattern, size_t max_sessions) { - struct https_ps_arg arg = {sb,0,0}; + struct https_ps_arg arg = {sb,0,0,client_protocol,user_pattern,max_sessions}; arg.ct = turn_time(); ur_map_foreach_arg(cliserver.sessions, (foreachcb_arg_type)https_print_session, &arg); + + return arg.counter; } -static void write_ps_page(ioa_socket_handle s) +static void write_ps_page(ioa_socket_handle s, const char* client_protocol, const char* user_pattern, size_t max_sessions) { if(s && !ioa_socket_tobeclosed(s)) { @@ -2035,16 +2077,64 @@ static void write_ps_page(ioa_socket_handle s) str_buffer_append(sb,"\r\n\r\n \r\n "); str_buffer_append(sb,admin_title); str_buffer_append(sb,"\r\n \r\n \r\n "); - str_buffer_append(sb,admin_title); + str_buffer_append(sb,bold_admin_title); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,home_link); str_buffer_append(sb,"
\r\n"); + + str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,"
Filter:\r\n"); + + str_buffer_append(sb,"
Realm name: "); + + str_buffer_append(sb," Client protocol: "); + + str_buffer_append(sb," User name contains:

"); + + str_buffer_append(sb," Max number of output sessions in the page:
"); + + str_buffer_append(sb,"
"); + + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,"TURN Sessions:
\r\n"); str_buffer_append(sb,"\r\n"); - https_print_sessions(sb); + size_t total_sz = https_print_sessions(sb,client_protocol,user_pattern,max_sessions); - str_buffer_append(sb,"\r\n
NSession IDUserRealmOriginAge, secsExpires, secsClient protocolRelay protocolClient addrServer addrRelay addr (IPv4)Relay addr (IPv6)FingerprintsMobileTLS methodTLS cipherBPS (allocated)PacketsRatePeers
\r\n\r\n"); + str_buffer_append(sb,"\r\n\r\n"); + + str_buffer_append(sb,"
Total sessions = "); + str_buffer_append_sz(sb,total_sz); + str_buffer_append(sb,"
\r\n"); + + str_buffer_append(sb,"\r\n\r\n"); send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); @@ -2161,7 +2251,23 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) if(!is_superuser()) realm0 = current_socket->as_realm; STRCPY(current_socket->as_eff_realm,realm0); - write_ps_page(s); + + const char* client_protocol = get_http_header_value(hr, HR_CLIENT_PROTOCOL); + if(!client_protocol) client_protocol=""; + + const char* user_pattern = get_http_header_value(hr, HR_USER_PATTERN); + if(!user_pattern) user_pattern=""; + + size_t max_sessions = cli_max_output_sessions; + const char* s_max_sessions = get_http_header_value(hr, HR_MAX_SESSIONS); + if(s_max_sessions) { + max_sessions=strtoul(s_max_sessions,NULL,10); + if(!max_sessions) max_sessions = cli_max_output_sessions; + } + + if(!max_sessions) max_sessions = DEFAULT_CLI_MAX_OUTPUT_SESSIONS; + + write_ps_page(s,client_protocol,user_pattern,max_sessions); } else { write_https_logon_page(s); } diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index d8a84ef5..6b9d8f8a 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -4512,6 +4512,7 @@ static int read_client_connection(turn_turnserver *server, if((st == TCP_SOCKET)||(st==TLS_SOCKET)||(st==TENTATIVE_TCP_SOCKET)) { 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); From f27c293b2d10ba7062461ca150dc78f6e496748d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 16 Jan 2015 09:13:36 +0000 Subject: [PATCH 426/805] cancel session --- src/apps/relay/turn_admin_server.c | 46 +++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index ae02a411..46664421 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1370,6 +1370,7 @@ typedef enum _AS_FORM AS_FORM; #define HR_CLIENT_PROTOCOL "cprotocol" #define HR_USER_PATTERN "puser" #define HR_MAX_SESSIONS "maxsess" +#define HR_CANCEL_SESSION "cs" struct form_name { AS_FORM form; @@ -1398,6 +1399,16 @@ static int is_superuser(void) { return !(current_socket->as_realm[0]); } +static void https_cancel_session(const char* ssid) +{ + printf("%s: 111.111: %s\n",__FUNCTION__,ssid); + if(ssid && *ssid) { + turnsession_id sid = (turnsession_id)strtoull(ssid,NULL,10); + printf("%s: 111.222: %llu\n",__FUNCTION__,(unsigned long long)sid); + send_session_cancellation_to_relay(sid); + } +} + static char* get_eff_realm(void) { if(current_socket->as_realm[0]) return current_socket->as_realm; @@ -1916,6 +1927,7 @@ struct https_ps_arg { const char* client_protocol; const char* user_pattern; size_t max_sessions; + turnsession_id cs; }; static int https_print_session(ur_map_key_type key, ur_map_value_type value, void *arg) @@ -1928,14 +1940,16 @@ static int https_print_session(ur_map_key_type key, ur_map_value_type value, voi if(get_eff_realm()[0] && strcmp(get_eff_realm(),tsi->realm)) return 0; - { - if(csarg->user_pattern[0]) { - if(!strstr((char*)tsi->username,csarg->user_pattern)) { - return 0; - } + if(csarg->user_pattern[0]) { + if(!strstr((char*)tsi->username,csarg->user_pattern)) { + return 0; } } + if(csarg->cs == tsi->id) { + return 0; + } + { const char *pn=csarg->client_protocol; if(pn[0]) { @@ -1962,6 +1976,11 @@ static int https_print_session(ur_map_key_type key, ur_map_value_type value, voi str_buffer_append_sz(sb,(size_t)(csarg->counter+1)); str_buffer_append(sb,""); str_buffer_append_sid(sb,tsi->id); + str_buffer_append(sb,"
cancel"); str_buffer_append(sb,""); str_buffer_append(sb,(char*)tsi->username); str_buffer_append(sb,""); @@ -2053,9 +2072,9 @@ static int https_print_session(ur_map_key_type key, ur_map_value_type value, voi return 0; } -static size_t https_print_sessions(struct str_buffer* sb, const char* client_protocol, const char* user_pattern, size_t max_sessions) +static size_t https_print_sessions(struct str_buffer* sb, const char* client_protocol, const char* user_pattern, size_t max_sessions, turnsession_id cs) { - struct https_ps_arg arg = {sb,0,0,client_protocol,user_pattern,max_sessions}; + struct https_ps_arg arg = {sb,0,0,client_protocol,user_pattern,max_sessions,cs}; arg.ct = turn_time(); @@ -2064,7 +2083,7 @@ static size_t https_print_sessions(struct str_buffer* sb, const char* client_pro return arg.counter; } -static void write_ps_page(ioa_socket_handle s, const char* client_protocol, const char* user_pattern, size_t max_sessions) +static void write_ps_page(ioa_socket_handle s, const char* client_protocol, const char* user_pattern, size_t max_sessions, turnsession_id cs) { if(s && !ioa_socket_tobeclosed(s)) { @@ -2126,7 +2145,7 @@ static void write_ps_page(ioa_socket_handle s, const char* client_protocol, cons str_buffer_append(sb,"TURN Sessions:
\r\n"); str_buffer_append(sb,"\r\n"); - size_t total_sz = https_print_sessions(sb,client_protocol,user_pattern,max_sessions); + size_t total_sz = https_print_sessions(sb,client_protocol,user_pattern,max_sessions,cs); str_buffer_append(sb,"\r\n
NSession IDUserRealmOriginAge, secsExpires, secsClient protocolRelay protocolClient addrServer addrRelay addr (IPv4)Relay addr (IPv6)FingerprintsMobileTLS methodTLS cipherBPS (allocated)PacketsRatePeers
\r\n"); @@ -2258,6 +2277,13 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) const char* user_pattern = get_http_header_value(hr, HR_USER_PATTERN); if(!user_pattern) user_pattern=""; + turnsession_id csid=0; + const char* ssid = get_http_header_value(hr, HR_CANCEL_SESSION); + if(ssid) { + https_cancel_session(ssid); + csid = (turnsession_id)strtoull(ssid,NULL,10); + } + size_t max_sessions = cli_max_output_sessions; const char* s_max_sessions = get_http_header_value(hr, HR_MAX_SESSIONS); if(s_max_sessions) { @@ -2267,7 +2293,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) if(!max_sessions) max_sessions = DEFAULT_CLI_MAX_OUTPUT_SESSIONS; - write_ps_page(s,client_protocol,user_pattern,max_sessions); + write_ps_page(s,client_protocol,user_pattern,max_sessions,csid); } else { write_https_logon_page(s); } From cf34bc2e7ab5d1f3b421e816583f3de0bbc3a903 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 17 Jan 2015 00:51:11 +0000 Subject: [PATCH 427/805] cosmetics --- src/apps/relay/turn_admin_server.c | 68 ++++++++++++++++++------------ 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 46664421..83c11fee 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1606,7 +1606,7 @@ static void https_print_addr(struct str_buffer* sb, ioa_addr *value, int use_por } } -static void https_print_addr_list(struct str_buffer* sb, turn_server_addrs_list_t *value, int use_port, const char* name) +static size_t https_print_addr_list(struct str_buffer* sb, turn_server_addrs_list_t *value, int use_port, const char* name) { if(sb && name && value && value->size && value->addrs) { char s[256]; @@ -1618,7 +1618,9 @@ static void https_print_addr_list(struct str_buffer* sb, turn_server_addrs_list_ addr_to_string(&(value->addrs[i]),(u08bits*)s); sbprintf(sb," %s %s\r\n",name,s); } + return i; } + return 0; } static void https_print_ip_range_list(struct str_buffer* sb, ip_range_list_t *value, const char* name) @@ -1674,6 +1676,13 @@ static void update_param(const char* pn, const char *value) } } +static void https_print_empty_row(struct str_buffer* sb, size_t span) +{ + str_buffer_append(sb,"
"); +} + static void write_pc_page(ioa_socket_handle s) { if(s && !ioa_socket_tobeclosed(s)) { @@ -1694,7 +1703,7 @@ static void write_pc_page(ioa_socket_handle s) str_buffer_append(sb,"Configuration Parameters:
\r\n"); str_buffer_append(sb,"\r\n"); @@ -1723,7 +1732,7 @@ static void write_pc_page(ioa_socket_handle s) } } - https_print_str(sb,"","",0); + https_print_empty_row(sb,3); if(turn_params.cipher_list[0]) https_print_str(sb,turn_params.cipher_list,"cipher-list",0); @@ -1753,7 +1762,7 @@ static void write_pc_page(ioa_socket_handle s) else https_print_str(sb,"SHA1","SHA type",0); - https_print_str(sb,"","",0); + https_print_empty_row(sb,3); https_print_str_array(sb,turn_params.listener.addrs,turn_params.listener.addrs_number,"Listener addr"); @@ -1777,13 +1786,17 @@ static void write_pc_page(ioa_socket_handle s) https_print_addr(sb,turn_params.external_ip,0,"External public IP"); - https_print_str(sb,"","",0); + https_print_empty_row(sb,3); - https_print_addr_list(sb,&turn_params.aux_servers_list,1,"Aux server"); - https_print_addr_list(sb,&turn_params.alternate_servers_list,1,"Alternate server"); - https_print_addr_list(sb,&turn_params.tls_alternate_servers_list,1,"TLS alternate server"); + { + size_t an = https_print_addr_list(sb,&turn_params.aux_servers_list,1,"Aux server"); + an += https_print_addr_list(sb,&turn_params.alternate_servers_list,1,"Alternate server"); + an += https_print_addr_list(sb,&turn_params.tls_alternate_servers_list,1,"TLS alternate server"); - https_print_str(sb,"","",0); + if(an) { + https_print_empty_row(sb,3); + } + } https_print_str_array(sb,turn_params.relay_addrs,turn_params.relays_number,"Relay addr"); @@ -1815,7 +1828,7 @@ static void write_pc_page(ioa_socket_handle s) https_print_flag(sb,turn_params.no_multicast_peers,"no-multicast-peers","no-multicast-peers"); https_print_flag(sb,turn_params.no_loopback_peers,"no-loopback-peers","no-loopback-peers"); - https_print_str(sb,"","",0); + https_print_empty_row(sb,3); if(turn_params.default_users_db.persistent_users_db.userdb[0]) { switch(turn_params.default_users_db.userdb_type) { @@ -1863,13 +1876,7 @@ static void write_pc_page(ioa_socket_handle s) } #endif - https_print_str(sb,"","",0); - - if(is_superuser()) { - char * rn = get_realm(NULL)->options.name; - if(rn[0]) - https_print_str(sb,rn,"Default realm",0); - } + https_print_empty_row(sb,3); if(turn_params.ct == TURN_CREDENTIALS_LONG_TERM) https_print_flag(sb,1,"Long-term authorization mechanism",0); @@ -1879,29 +1886,34 @@ static void write_pc_page(ioa_socket_handle s) if(turn_params.use_auth_secret_with_timestamp && turn_params.rest_api_separator) https_print_uint(sb,turn_params.rest_api_separator,"TURN REST API separator ASCII number",0); - https_print_str(sb,"","",0); + https_print_empty_row(sb,3); + + if(is_superuser()) { + char * rn = get_realm(NULL)->options.name; + if(rn[0]) + https_print_str(sb,rn,"Default realm",0); + } realm_params_t *rp = get_realm(get_eff_realm()); if(!rp) rp = get_realm(NULL); - if(get_eff_realm()[0]) - https_print_str(sb,get_eff_realm(),"current realm",0); + https_print_str(sb,rp->options.name,"current realm",0); https_print_uint(sb,(unsigned long)rp->options.perf_options.total_quota,"current realm total-quota",0); https_print_uint(sb,(unsigned long)rp->options.perf_options.user_quota,"current realm user-quota",0); - https_print_uint(sb,(unsigned long)rp->options.perf_options.max_bps,"current realm max-bps",0); + https_print_uint(sb,(unsigned long)rp->options.perf_options.max_bps,"current realm max-bps (per session)",0); - https_print_str(sb,"","",0); + https_print_empty_row(sb,3); https_print_uint(sb,(unsigned long)rp->status.total_current_allocs,"total-current-allocs",0); - https_print_str(sb,"","",0); + https_print_empty_row(sb,3); - https_print_uint(sb,(unsigned long)turn_params.total_quota,"Default total-quota","total-quota"); - https_print_uint(sb,(unsigned long)turn_params.user_quota,"Default user-quota","user-quota"); - https_print_uint(sb,(unsigned long)get_bps_capacity(),"Total server bps-capacity","bps-capacity"); - https_print_uint(sb,(unsigned long)get_bps_capacity_allocated(),"Allocated bps-capacity",0); - https_print_uint(sb,(unsigned long)get_max_bps(),"Default max-bps","max-bps"); + https_print_uint(sb,(unsigned long)turn_params.total_quota,"Default total-quota (per realm)","total-quota"); + https_print_uint(sb,(unsigned long)turn_params.user_quota,"Default user-quota (per realm)","user-quota"); + https_print_uint(sb,(unsigned long)get_bps_capacity(),"Total bps-capacity (per server)","bps-capacity"); + https_print_uint(sb,(unsigned long)get_bps_capacity_allocated(),"Allocated bps-capacity (per server)",0); + https_print_uint(sb,(unsigned long)get_max_bps(),"Default max-bps (per session)","max-bps"); } str_buffer_append(sb,"\r\n
ParameterCurrent Value"); if(is_superuser()) { - str_buffer_append(sb,"New (ephemeral) Value"); + str_buffer_append(sb,"Update Value"); } str_buffer_append(sb,"
\r\n\r\n"); From 3849c1d4f56778b9f16f8f770f2d040c52aa7e1a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 17 Jan 2015 08:11:47 +0000 Subject: [PATCH 428/805] cosmetics --- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/turn_admin_server.c | 91 +++++++++++++++++------------ src/server/ns_turn_session.h | 2 +- 3 files changed, 56 insertions(+), 37 deletions(-) diff --git a/examples/var/db/turndb b/examples/var/db/turndb index f06a31d409ebbf8537c5cdbcbaac4019f63153f7..a2b26f8de08ceb079f7883b8e80974c99cebbc92 100644 GIT binary patch delta 205 zcmZqJz}T>Xae_3X^+XwGM(d3U3$2BjpD?g7Yq2pOXYOG3Vb*2NVqU$m@hcMxa~6Z* zL`PXxAT7%^d6m8FWFLEZM()Wu_BJv=JyJX@^3sxd`9&oedg=LPxrr6JNd?8G1_qOl z*ekFwFfhnWbd(U_Vtx%YJ&b|*3iEvC9Okgi0uFA>VxmB;jObcZmzSuQUz83toe5~H=;Zgp;+xrAehC8rK4v&M delta 155 zcmZqJz}T>Xae_3X=|mZ4M$?T63$2A27#P@?eHfUZFdt`L!Q8=|#q6`O(SmuhkG(u2 z>*O4J8zx!i$@=!PlaJfWGD$H`UTZHUzy;Qn!@zunc|LOv^Xtt54sOg7Cx}hXaW(>K zn(u6)%PhvCD9xB$l$n>8sFz=qo|{;qn^aKDB*G#u&6$^9RFa{Wo?iwPUF0GH0HUEQ ACjbBd diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 83c11fee..bf1b778d 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1547,9 +1547,9 @@ static void https_print_flag(struct str_buffer* sb, int flag, const char* name, if(!is_superuser()) param_name = 0; if(!param_name) { - sbprintf(sb,"%s%s\r\n",name,get_flag(flag)); + sbprintf(sb,"%s%s\r\n",name,get_flag(flag)); } else { - sbprintf(sb,"%s%stoggle\r\n",name,get_flag(flag),param_name); + sbprintf(sb,"%s%s\r\n",name,param_name,get_flag(flag)); } } } @@ -1560,9 +1560,17 @@ static void https_print_uint(struct str_buffer* sb, unsigned long value, const c if(!is_superuser()) param_name = 0; if(!param_name) { - sbprintf(sb,"%s%lu\r\n",name,value); + if(value) { + sbprintf(sb,"%s%lu\r\n",name,value); + } else { + sbprintf(sb,"%s \r\n",name); + } } else { - sbprintf(sb,"%s%lu
\r\n",name,value,param_name,param_name,value); + if(value) { + sbprintf(sb,"%s
\r\n",name,param_name,param_name,value); + } else { + sbprintf(sb,"%s
\r\n",name,param_name,param_name); + } } } } @@ -1572,13 +1580,10 @@ static void https_print_str(struct str_buffer* sb, const char *value, const char if(sb && name && value) { if(!is_superuser()) param_name = 0; - const char *v = value; - if((value[0] == 0) && name[0]) - v="empty"; if(!param_name) { - sbprintf(sb,"%s%s\r\n",name,v); + sbprintf(sb,"%s%s\r\n",name,value); } else { - sbprintf(sb,"%s%s
\r\n",name,v,param_name,param_name,value); + sbprintf(sb,"%s
\r\n",name,param_name,param_name,value); } } } @@ -1589,7 +1594,7 @@ static void https_print_str_array(struct str_buffer* sb, char **value, size_t sz size_t i; for(i=0;i %s %s\r\n",name,value[i]); + sbprintf(sb," %s %s\r\n",name,value[i]); } } } @@ -1602,7 +1607,7 @@ static void https_print_addr(struct str_buffer* sb, ioa_addr *value, int use_por addr_to_string_no_port(value,(u08bits*)s); else addr_to_string(value,(u08bits*)s); - sbprintf(sb," %s %s\r\n",name,s); + sbprintf(sb," %s %s\r\n",name,s); } } @@ -1616,7 +1621,7 @@ static size_t https_print_addr_list(struct str_buffer* sb, turn_server_addrs_lis addr_to_string_no_port(&(value->addrs[i]),(u08bits*)s); else addr_to_string(&(value->addrs[i]),(u08bits*)s); - sbprintf(sb," %s %s\r\n",name,s); + sbprintf(sb," %s %s\r\n",name,s); } return i; } @@ -1632,10 +1637,10 @@ static void https_print_ip_range_list(struct str_buffer* sb, ip_range_list_t *va if(get_eff_realm()[0] && strcmp(get_eff_realm(),value->rs[i].realm)) { continue; } else { - sbprintf(sb," %s %s (%s)\r\n",name,value->rs[i].str,value->rs[i].realm); + sbprintf(sb," %s %s (%s)\r\n",name,value->rs[i].str,value->rs[i].realm); } } else { - sbprintf(sb," %s %s\r\n",name,value->rs[i].str); + sbprintf(sb," %s %s\r\n",name,value->rs[i].str); } } } @@ -1659,10 +1664,10 @@ static void toggle_param(const char* pn) static void update_param(const char* pn, const char *value) { - if(is_superuser()) { - if(pn) { - if(!value) - value = "0"; + if(pn) { + if(!value) + value = "0"; + if(is_superuser()) { if(strstr(pn,"total-quota")==pn) { turn_params.total_quota = atoi(value); } else if(strstr(pn,"user-quota")==pn) { @@ -1673,6 +1678,24 @@ static void update_param(const char* pn, const char *value) set_bps_capacity((band_limit_t)atol(value)); } } + { + realm_params_t *rp = get_realm(get_eff_realm()); + if(!rp) rp = get_realm(NULL); + + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->set_realm_option_one) { + if(strstr(pn,"cr-total-quota")==pn) { + rp->options.perf_options.total_quota = atoi(value); + dbd->set_realm_option_one((u08bits*)rp->options.name,rp->options.perf_options.total_quota,"total-quota"); + } else if(strstr(pn,"cr-user-quota")==pn) { + rp->options.perf_options.user_quota = atoi(value); + dbd->set_realm_option_one((u08bits*)rp->options.name,rp->options.perf_options.user_quota,"user-quota"); + } else if(strstr(pn,"cr-max-bps")==pn) { + rp->options.perf_options.max_bps = (band_limit_t)atol(value); + dbd->set_realm_option_one((u08bits*)rp->options.name,rp->options.perf_options.max_bps,"max-bps"); + } + } + } } } @@ -1701,11 +1724,7 @@ static void write_pc_page(ioa_socket_handle s) str_buffer_append(sb,home_link); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,"Configuration Parameters:
\r\n"); - str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,"\r\n"); { https_print_flag(sb,turn_params.verbose,"verbose",0); @@ -1732,7 +1751,7 @@ static void write_pc_page(ioa_socket_handle s) } } - https_print_empty_row(sb,3); + https_print_empty_row(sb,2); if(turn_params.cipher_list[0]) https_print_str(sb,turn_params.cipher_list,"cipher-list",0); @@ -1762,7 +1781,7 @@ static void write_pc_page(ioa_socket_handle s) else https_print_str(sb,"SHA1","SHA type",0); - https_print_empty_row(sb,3); + https_print_empty_row(sb,2); https_print_str_array(sb,turn_params.listener.addrs,turn_params.listener.addrs_number,"Listener addr"); @@ -1786,7 +1805,7 @@ static void write_pc_page(ioa_socket_handle s) https_print_addr(sb,turn_params.external_ip,0,"External public IP"); - https_print_empty_row(sb,3); + https_print_empty_row(sb,2); { size_t an = https_print_addr_list(sb,&turn_params.aux_servers_list,1,"Aux server"); @@ -1794,7 +1813,7 @@ static void write_pc_page(ioa_socket_handle s) an += https_print_addr_list(sb,&turn_params.tls_alternate_servers_list,1,"TLS alternate server"); if(an) { - https_print_empty_row(sb,3); + https_print_empty_row(sb,2); } } @@ -1828,7 +1847,7 @@ static void write_pc_page(ioa_socket_handle s) https_print_flag(sb,turn_params.no_multicast_peers,"no-multicast-peers","no-multicast-peers"); https_print_flag(sb,turn_params.no_loopback_peers,"no-loopback-peers","no-loopback-peers"); - https_print_empty_row(sb,3); + https_print_empty_row(sb,2); if(turn_params.default_users_db.persistent_users_db.userdb[0]) { switch(turn_params.default_users_db.userdb_type) { @@ -1876,7 +1895,7 @@ static void write_pc_page(ioa_socket_handle s) } #endif - https_print_empty_row(sb,3); + https_print_empty_row(sb,2); if(turn_params.ct == TURN_CREDENTIALS_LONG_TERM) https_print_flag(sb,1,"Long-term authorization mechanism",0); @@ -1886,7 +1905,7 @@ static void write_pc_page(ioa_socket_handle s) if(turn_params.use_auth_secret_with_timestamp && turn_params.rest_api_separator) https_print_uint(sb,turn_params.rest_api_separator,"TURN REST API separator ASCII number",0); - https_print_empty_row(sb,3); + https_print_empty_row(sb,2); if(is_superuser()) { char * rn = get_realm(NULL)->options.name; @@ -1897,17 +1916,17 @@ static void write_pc_page(ioa_socket_handle s) realm_params_t *rp = get_realm(get_eff_realm()); if(!rp) rp = get_realm(NULL); - https_print_str(sb,rp->options.name,"current realm",0); + https_print_str(sb,rp->options.name,"Admin session (current) realm",0); - https_print_uint(sb,(unsigned long)rp->options.perf_options.total_quota,"current realm total-quota",0); - https_print_uint(sb,(unsigned long)rp->options.perf_options.user_quota,"current realm user-quota",0); - https_print_uint(sb,(unsigned long)rp->options.perf_options.max_bps,"current realm max-bps (per session)",0); + https_print_uint(sb,(unsigned long)rp->options.perf_options.total_quota,"current realm max number of sessions (total-quota)","cr-total-quota"); + https_print_uint(sb,(unsigned long)rp->options.perf_options.user_quota,"current realm max sessions per user (user-quota)","cr-user-quota"); + https_print_uint(sb,(unsigned long)rp->options.perf_options.max_bps,"current realm max-bps (per session)","cr-max-bps"); - https_print_empty_row(sb,3); + https_print_empty_row(sb,2); https_print_uint(sb,(unsigned long)rp->status.total_current_allocs,"total-current-allocs",0); - https_print_empty_row(sb,3); + https_print_empty_row(sb,2); https_print_uint(sb,(unsigned long)turn_params.total_quota,"Default total-quota (per realm)","total-quota"); https_print_uint(sb,(unsigned long)turn_params.user_quota,"Default user-quota (per realm)","user-quota"); diff --git a/src/server/ns_turn_session.h b/src/server/ns_turn_session.h index c9d4b921..a3f4542e 100644 --- a/src/server/ns_turn_session.h +++ b/src/server/ns_turn_session.h @@ -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; From 91cafd9f1ab016815f4c7370fc33e958a5c1e22c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 17 Jan 2015 08:45:31 +0000 Subject: [PATCH 429/805] cosmetics --- src/apps/relay/netengine.c | 30 +++---- src/apps/relay/turn_admin_server.c | 130 ++++++++++++++--------------- src/apps/relay/turn_admin_server.h | 8 +- 3 files changed, 82 insertions(+), 86 deletions(-) diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 7ae2d0ee..fbb55a1b 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1773,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) @@ -1815,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 @@ -1867,8 +1864,7 @@ void setup_server(void) } } - if(use_cli) - setup_cli_server(); + setup_admin_server(); barrier_wait(); } diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index bf1b778d..b77208e0 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -72,7 +72,7 @@ /////////////////////////////// -struct cli_server cliserver; +struct admin_server adminserver; int use_cli = 1; @@ -594,7 +594,7 @@ static void print_sessions(struct cli_session* cs, const char* pn, int exact_mat arg.users = ur_string_map_create(NULL); } - ur_map_foreach_arg(cliserver.sessions, (foreachcb_arg_type)print_session, &arg); + ur_map_foreach_arg(adminserver.sessions, (foreachcb_arg_type)print_session, &arg); myprintf(cs,"\n"); @@ -891,7 +891,7 @@ static void close_cli_session(struct cli_session* cs) { if(cs) { - addr_debug_print(cliserver.verbose, &(cs->addr),"CLI session disconnected from"); + addr_debug_print(adminserver.verbose, &(cs->addr),"CLI session disconnected from"); if(cs->ts) { telnet_free(cs->ts); @@ -1170,7 +1170,7 @@ static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd UNUSED_ARG(arg); UNUSED_ARG(socklen); - addr_debug_print(cliserver.verbose, (ioa_addr*)sa,"CLI connected to"); + addr_debug_print(adminserver.verbose, (ioa_addr*)sa,"CLI connected to"); struct cli_session *clisession = (struct cli_session*)turn_malloc(sizeof(struct cli_session)); ns_bzero(clisession,sizeof(struct cli_session)); @@ -1183,7 +1183,7 @@ static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd addr_cpy(&(clisession->addr),(ioa_addr*)sa); - clisession->bev = bufferevent_socket_new(cliserver.event_base, + clisession->bev = bufferevent_socket_new(adminserver.event_base, fd, TURN_BUFFEREVENTS_OPTIONS); debug_ptr_add(clisession->bev); @@ -1196,7 +1196,7 @@ static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd if(!(clisession->ts)) { const char *str = "Cannot open telnet session\n"; - addr_debug_print(cliserver.verbose, (ioa_addr*)sa,str); + addr_debug_print(adminserver.verbose, (ioa_addr*)sa,str); close_cli_session(clisession); } else { print_str_array(clisession, CLI_GREETING_STR); @@ -1211,88 +1211,91 @@ static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd } } -void setup_cli_thread(void) +void setup_admin_thread(void) { - cliserver.event_base = turn_event_base_new(); + adminserver.event_base = turn_event_base_new(); super_memory_t* sm = new_super_memory_region(); - cliserver.e = create_ioa_engine(sm, cliserver.event_base, turn_params.listener.tp, turn_params.relay_ifname, turn_params.relays_number, turn_params.relay_addrs, + adminserver.e = create_ioa_engine(sm, adminserver.event_base, turn_params.listener.tp, turn_params.relay_ifname, turn_params.relays_number, turn_params.relay_addrs, turn_params.default_relays, turn_params.verbose #if !defined(TURN_NO_HIREDIS) ,turn_params.redis_statsdb #endif ); - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (cli thread): %s\n",event_base_get_method(cliserver.event_base)); + + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (admin thread): %s\n",event_base_get_method(adminserver.event_base)); { struct bufferevent *pair[2]; - bufferevent_pair_new(cliserver.event_base, TURN_BUFFEREVENTS_OPTIONS, pair); + bufferevent_pair_new(adminserver.event_base, TURN_BUFFEREVENTS_OPTIONS, pair); - cliserver.in_buf = pair[0]; - cliserver.out_buf = pair[1]; + adminserver.in_buf = pair[0]; + adminserver.out_buf = pair[1]; - bufferevent_setcb(cliserver.in_buf, cli_server_receive_message, NULL, NULL, &cliserver); - bufferevent_enable(cliserver.in_buf, EV_READ); + bufferevent_setcb(adminserver.in_buf, admin_server_receive_message, NULL, NULL, &adminserver); + bufferevent_enable(adminserver.in_buf, EV_READ); } { struct bufferevent *pair[2]; - bufferevent_pair_new(cliserver.event_base, TURN_BUFFEREVENTS_OPTIONS, pair); + bufferevent_pair_new(adminserver.event_base, TURN_BUFFEREVENTS_OPTIONS, pair); - cliserver.https_in_buf = pair[0]; - cliserver.https_out_buf = pair[1]; + adminserver.https_in_buf = pair[0]; + adminserver.https_out_buf = pair[1]; - bufferevent_setcb(cliserver.https_in_buf, https_admin_server_receive_message, NULL, NULL, &cliserver); - bufferevent_enable(cliserver.https_in_buf, EV_READ); + bufferevent_setcb(adminserver.https_in_buf, https_admin_server_receive_message, NULL, NULL, &adminserver); + bufferevent_enable(adminserver.https_in_buf, EV_READ); } - if(!cli_addr_set) { - if(make_ioa_addr((const u08bits*)CLI_DEFAULT_IP,0,&cli_addr)<0) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot set cli address %s\n",CLI_DEFAULT_IP); + if(use_cli) { + if(!cli_addr_set) { + if(make_ioa_addr((const u08bits*)CLI_DEFAULT_IP,0,&cli_addr)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot set cli address %s\n",CLI_DEFAULT_IP); + return; + } + } + + addr_set_port(&cli_addr,cli_port); + + adminserver.listen_fd = socket(cli_addr.ss.sa_family, SOCK_STREAM, 0); + if (adminserver.listen_fd < 0) { + perror("socket"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot open CLI socket\n"); return; } - } - addr_set_port(&cli_addr,cli_port); + if(addr_bind(adminserver.listen_fd,&cli_addr,1)<0) { + perror("Cannot bind CLI socket to addr"); + char saddr[129]; + addr_to_string(&cli_addr,(u08bits*)saddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind CLI listener socket to addr %s\n",saddr); + socket_closesocket(adminserver.listen_fd); + return; + } - cliserver.listen_fd = socket(cli_addr.ss.sa_family, SOCK_STREAM, 0); - if (cliserver.listen_fd < 0) { - perror("socket"); - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot open CLI socket\n"); - return; - } + socket_tcp_set_keepalive(adminserver.listen_fd); - if(addr_bind(cliserver.listen_fd,&cli_addr,1)<0) { - perror("Cannot bind CLI socket to addr"); - char saddr[129]; - addr_to_string(&cli_addr,(u08bits*)saddr); - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind CLI listener socket to addr %s\n",saddr); - socket_closesocket(cliserver.listen_fd); - return; - } + socket_set_nonblocking(adminserver.listen_fd); - socket_tcp_set_keepalive(cliserver.listen_fd); - - socket_set_nonblocking(cliserver.listen_fd); - - cliserver.l = evconnlistener_new(cliserver.event_base, - cliserver_input_handler, &cliserver, + adminserver.l = evconnlistener_new(adminserver.event_base, + cliserver_input_handler, &adminserver, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, - 1024, cliserver.listen_fd); + 1024, adminserver.listen_fd); - if(!(cliserver.l)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot create CLI listener\n"); - socket_closesocket(cliserver.listen_fd); - return; + if(!(adminserver.l)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot create CLI listener\n"); + socket_closesocket(adminserver.listen_fd); + return; + } + + addr_debug_print(adminserver.verbose, &cli_addr,"CLI listener opened on "); } - cliserver.sessions = ur_map_create(); - - addr_debug_print(cliserver.verbose, &cli_addr,"CLI listener opened on "); + adminserver.sessions = ur_map_create(); } -void cli_server_receive_message(struct bufferevent *bev, void *ptr) +void admin_server_receive_message(struct bufferevent *bev, void *ptr) { UNUSED_ARG(ptr); @@ -1308,15 +1311,15 @@ void cli_server_receive_message(struct bufferevent *bev, void *ptr) } ur_map_value_type t = 0; - if (ur_map_get(cliserver.sessions, (ur_map_key_type)tsi->id, &t) && t) { + if (ur_map_get(adminserver.sessions, (ur_map_key_type)tsi->id, &t) && t) { struct turn_session_info *old = (struct turn_session_info*)t; turn_session_info_clean(old); turn_free(old,sizeof(struct turn_session_info)); - ur_map_del(cliserver.sessions, (ur_map_key_type)tsi->id, NULL); + ur_map_del(adminserver.sessions, (ur_map_key_type)tsi->id, NULL); } if(tsi->valid) { - ur_map_put(cliserver.sessions, (ur_map_key_type)tsi->id, (ur_map_value_type)tsi); + ur_map_put(adminserver.sessions, (ur_map_key_type)tsi->id, (ur_map_value_type)tsi); tsi = (struct turn_session_info*)turn_malloc(sizeof(struct turn_session_info)); turn_session_info_init(tsi); } else { @@ -1334,11 +1337,8 @@ int send_turn_session_info(struct turn_session_info* tsi) { int ret = -1; - if(!use_cli) - return ret; - if(tsi) { - struct evbuffer *output = bufferevent_get_output(cliserver.out_buf); + struct evbuffer *output = bufferevent_get_output(adminserver.out_buf); if(output) { if(evbuffer_add(output,tsi,sizeof(struct turn_session_info))>=0) { ret = 0; @@ -2109,7 +2109,7 @@ static size_t https_print_sessions(struct str_buffer* sb, const char* client_pro arg.ct = turn_time(); - ur_map_foreach_arg(cliserver.sessions, (foreachcb_arg_type)https_print_session, &arg); + ur_map_foreach_arg(adminserver.sessions, (foreachcb_arg_type)https_print_session, &arg); return arg.counter; } @@ -2381,7 +2381,7 @@ static void https_input_handler(ioa_socket_handle s, int event_type, ioa_net_dat handle_https(s,data->nbh); - ioa_network_buffer_delete(cliserver.e, data->nbh); + ioa_network_buffer_delete(adminserver.e, data->nbh); data->nbh = NULL; } @@ -2399,14 +2399,14 @@ void https_admin_server_receive_message(struct bufferevent *bev, void *ptr) continue; } - register_callback_on_ioa_socket(cliserver.e, s, IOA_EV_READ, https_input_handler, NULL, 0); + register_callback_on_ioa_socket(adminserver.e, s, IOA_EV_READ, https_input_handler, NULL, 0); handle_https(s,NULL); } } void send_https_socket(ioa_socket_handle s) { - struct evbuffer *output = bufferevent_get_output(cliserver.https_out_buf); + struct evbuffer *output = bufferevent_get_output(adminserver.https_out_buf); if(output) { evbuffer_add(output,&s,sizeof(s)); } diff --git a/src/apps/relay/turn_admin_server.h b/src/apps/relay/turn_admin_server.h index 37c63298..013d0af3 100644 --- a/src/apps/relay/turn_admin_server.h +++ b/src/apps/relay/turn_admin_server.h @@ -51,7 +51,7 @@ extern "C" { //////////////////////////////////////////// -struct cli_server { +struct admin_server { evutil_socket_t listen_fd; struct event_base* event_base; ioa_engine_handle e; @@ -67,7 +67,7 @@ struct cli_server { /////////////////////////////////////////// -extern struct cli_server cliserver; +extern struct admin_server adminserver; extern int use_cli; @@ -86,9 +86,9 @@ 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); From e3d9f5484c9f3d63792ad28a75a85f8d87c82ce9 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 18 Jan 2015 05:48:34 +0000 Subject: [PATCH 430/805] list users --- src/apps/relay/dbdrivers/dbd_mongo.c | 28 +++++--- src/apps/relay/dbdrivers/dbd_mysql.c | 26 ++++++-- src/apps/relay/dbdrivers/dbd_pgsql.c | 30 ++++++--- src/apps/relay/dbdrivers/dbd_redis.c | 93 +++++++++++---------------- src/apps/relay/dbdrivers/dbd_sqlite.c | 22 +++++-- src/apps/relay/dbdrivers/dbdriver.h | 2 +- src/apps/relay/userdb.c | 2 +- turndb/schema.userdb.redis | 9 +-- turndb/testredisdbsetup.sh | 15 ++--- 9 files changed, 124 insertions(+), 103 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index d27211d5..ce9772ca 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -424,16 +424,21 @@ static int mongo_del_oauth_key(const u08bits *kid) { return ret; } -static int mongo_list_users(u08bits *realm) { +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); + 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); @@ -464,14 +469,21 @@ static int mongo_list_users(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 = ""; + const char *rval = ""; 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); + 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); } } } diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index ce118195..07f9b0e9 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -549,15 +549,20 @@ static int mysql_del_oauth_key(const u08bits *kid) { return ret; } -static int mysql_list_users(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(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) { @@ -575,10 +580,17 @@ static int mysql_list_users(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]); } } } diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index a9a9cec6..bdf2af91 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -327,15 +327,20 @@ static int pgsql_del_oauth_key(const u08bits *kid) { return ret; } -static int pgsql_list_users(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(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)) { @@ -346,10 +351,19 @@ static int pgsql_list_users(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); + } } } } diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index 6a9d70ac..5f820c97 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -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; } @@ -524,12 +507,10 @@ static int redis_set_user_key(u08bits *usname, u08bits *realm, const char *key) 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; } @@ -556,8 +537,6 @@ static int redis_del_user(u08bits *usname, u08bits *realm) { { 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")); @@ -579,9 +558,14 @@ static int redis_del_oauth_key(const u08bits *kid) { return ret; } -static int redis_list_users(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; @@ -596,27 +580,7 @@ static int redis_list_users(u08bits *realm) { } else { reply = (redisReply*)redisCommand(rc, "keys turn/realm/*/user/*/key"); } - 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); - } - - 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) @@ -634,22 +598,43 @@ static int redis_list_users(u08bits *realm) { } } + size_t rhsz=strlen("turn/realm/"); + size_t uhsz = strlen("user/"); + for(isz=0;iszlist_users) { - (*dbd->list_users)(realm); + (*dbd->list_users)(realm,NULL,NULL); } } } diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis index 6f554571..bcb5c4ff 100644 --- a/turndb/schema.userdb.redis +++ b/turndb/schema.userdb.redis @@ -8,9 +8,7 @@ has the following schema: "turn/realm//user//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 shared secrets (REST API), several key/value pairs may be used (same as in SQL schema). The secrets are stored as members @@ -118,11 +116,6 @@ 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" diff --git a/turndb/testredisdbsetup.sh b/turndb/testredisdbsetup.sh index 3091aeda..3d9ad825 100755 --- a/turndb/testredisdbsetup.sh +++ b/turndb/testredisdbsetup.sh @@ -1,5 +1,10 @@ #!/bin/sh +# ninefingers:password: youhavetoberealistic +# gorst:password: hero +# whirrun:password: sword +# stranger-come-knocking:password: civilization + redis-cli < Date: Sun, 18 Jan 2015 08:31:57 +0000 Subject: [PATCH 431/805] users admin --- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/turn_admin_server.c | 271 +++++++++++++++++++++++++++++ src/apps/relay/userdb.c | 18 +- 3 files changed, 280 insertions(+), 9 deletions(-) diff --git a/examples/var/db/turndb b/examples/var/db/turndb index a2b26f8de08ceb079f7883b8e80974c99cebbc92..9884d3f4822d13a406f0342b5d4cbf8824019922 100644 GIT binary patch delta 61 zcmZqJz}T>Xae_3X<3t%}M#qf_8!o+UG00KG_8#N}2vj1jc?%LQ`%FHeV M7UkL8$6e$D06Lry>;M1& delta 37 tcmZqJz}T>Xae_3X^+XwGM(d3U8<;mXvNBH=W&gdIk*AG$^EB=(9{}x`3~>Me diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index b77208e0..d66d00c6 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1359,6 +1359,7 @@ enum _AS_FORM { AS_FORM_TOGGLE, AS_FORM_UPDATE, AS_FORM_PS, + AS_FORM_USERS, AS_FORM_UNKNOWN }; @@ -1366,11 +1367,16 @@ typedef enum _AS_FORM AS_FORM; #define HR_USERNAME "uname" #define HR_PASSWORD "pwd" +#define HR_PASSWORD1 "pwd1" #define HR_REALM "realm" +#define HR_ADD_USER "add_user" +#define HR_ADD_USER_REALM "add_user_realm" #define HR_CLIENT_PROTOCOL "cprotocol" #define HR_USER_PATTERN "puser" #define HR_MAX_SESSIONS "maxsess" #define HR_CANCEL_SESSION "cs" +#define HR_DELETE_USER "du" +#define HR_DELETE_REALM "dr" struct form_name { AS_FORM form; @@ -1385,6 +1391,7 @@ static struct form_name form_names[] = { {AS_FORM_TOGGLE,"/toggle"}, {AS_FORM_UPDATE,"/update"}, {AS_FORM_PS,"/ps"}, + {AS_FORM_USERS,"/us"}, {AS_FORM_UNKNOWN,NULL} }; @@ -1510,6 +1517,10 @@ static void write_https_home_page(ioa_socket_handle s) str_buffer_append_sz(sb,cli_max_output_sessions); str_buffer_append(sb,"\">"); + str_buffer_append(sb,"
"); + str_buffer_append(sb,"\r\n"); str_buffer_append(sb,"\r\n"); @@ -2200,6 +2211,171 @@ static void write_ps_page(ioa_socket_handle s, const char* client_protocol, cons } } +static size_t https_print_users(struct str_buffer* sb) +{ + size_t ret = 0; + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->list_users) { + secrets_list_t users,realms; + init_secrets_list(&users); + init_secrets_list(&realms); + dbd->list_users((u08bits*)current_socket->as_eff_realm,&users,&realms); + + size_t sz = get_secrets_list_size(&users); + size_t i; + for(i=0;i
"); + str_buffer_append(sb,""); + if(!current_socket->as_eff_realm[0]) { + str_buffer_append(sb,""); + } + str_buffer_append(sb,""); + str_buffer_append(sb,""); + ++ret; + } + + clean_secrets_list(&users); + clean_secrets_list(&realms); + } + + return ret; +} + +static void write_users_page(ioa_socket_handle s, const u08bits *add_user, const u08bits *add_realm, const char* msg) +{ + if(s && !ioa_socket_tobeclosed(s)) { + + if(!(s->as_ok)) { + write_https_logon_page(s); + } else { + + struct str_buffer* sb = str_buffer_new(); + + str_buffer_append(sb,"\r\n\r\n \r\n "); + str_buffer_append(sb,admin_title); + str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,bold_admin_title); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,home_link); + str_buffer_append(sb,"
\r\n"); + + str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,"
Filter:\r\n"); + + str_buffer_append(sb,"
Realm name: "); + + str_buffer_append(sb,"
"); + + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"\r\n"); + + str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,"
User:\r\n"); + + if(msg && msg[0]) { + str_buffer_append(sb,"
ParameterCurrent Value"); - if(is_superuser()) { - str_buffer_append(sb,"Update Value"); - } - str_buffer_append(sb,"
ParameterValue
"); + str_buffer_append_sz(sb,i); + str_buffer_append(sb,""); + str_buffer_append(sb,get_secrets_list_elem(&users,i)); + str_buffer_append(sb,""); + str_buffer_append(sb,get_secrets_list_elem(&realms,i)); + str_buffer_append(sb," delete"); + str_buffer_append(sb,"
"); + str_buffer_append(sb,msg); + str_buffer_append(sb,"

"); + } + + str_buffer_append(sb,"
Realm name:
\r\n"); + + str_buffer_append(sb,"
User name:
\r\n"); + + str_buffer_append(sb,"
Password:
\r\n"); + + str_buffer_append(sb,"
Confirm password:
\r\n"); + + str_buffer_append(sb,"
"); + + str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,"\r\n"); + + str_buffer_append(sb,"Users:
\r\n"); + str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,""); + if(!current_socket->as_eff_realm[0]) { + str_buffer_append(sb,""); + } + str_buffer_append(sb,""); + str_buffer_append(sb,"\r\n"); + + size_t total_sz = https_print_users(sb); + + str_buffer_append(sb,"\r\n
NNameRealm
\r\n"); + + str_buffer_append(sb,"
Total users = "); + str_buffer_append_sz(sb,total_sz); + str_buffer_append(sb,"
\r\n"); + + str_buffer_append(sb,"\r\n\r\n"); + + send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); + send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); + send_str_from_ioa_socket_tcp(s,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + + send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); + + send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); + send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); + + str_buffer_free(sb); + } + } +} + static void handle_toggle_request(ioa_socket_handle s, struct http_request* hr) { if(s && hr) { @@ -2330,6 +2506,101 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } break; } + case AS_FORM_USERS: { + if(s->as_ok) { + { + const char *realm0 = get_http_header_value(hr, HR_REALM); + if(!realm0) + realm0=""; + if(!is_superuser()) + realm0 = current_socket->as_realm; + STRCPY(current_socket->as_eff_realm,realm0); + } + + { + const u08bits *user = (const u08bits*)get_http_header_value(hr, HR_DELETE_USER); + if(user && user[0]) { + const u08bits *realm = (const u08bits*)get_http_header_value(hr, HR_DELETE_REALM); + if(!is_superuser()) { + realm = (const u08bits*)current_socket->as_realm; + } + if(realm && realm[0]) { + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->del_user) { + u08bits u[STUN_MAX_USERNAME_SIZE+1]; + u08bits r[STUN_MAX_REALM_SIZE+1]; + STRCPY(u,user); + STRCPY(r,realm); + dbd->del_user(u,r); + } + } + } + } + + const u08bits *add_realm = (const u08bits*)current_socket->as_eff_realm; + const u08bits *add_user = (const u08bits*)get_http_header_value(hr, HR_ADD_USER); + const char* msg = ""; + if(!add_user) add_user = (const u08bits*)""; + if(add_user[0]) { + add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_USER_REALM); + if(!add_realm) { + add_realm=(const u08bits*)""; + } + if(!is_superuser()) { + add_realm = (const u08bits*)current_socket->as_realm; + } + if(!add_realm[0]) { + add_realm=(const u08bits*)current_socket->as_eff_realm; + } + if(add_realm[0]) { + const u08bits *pwd = (const u08bits*)get_http_header_value(hr, HR_PASSWORD); + const u08bits *pwd1 = (const u08bits*)get_http_header_value(hr, HR_PASSWORD1); + if(pwd && pwd1 && pwd[0] && pwd1[0] && !strcmp((const char*)pwd,(const char*)pwd1)) { + + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->set_user_key) { + + hmackey_t key; + char skey[sizeof(hmackey_t) * 2 + 1]; + + { + u08bits u[STUN_MAX_USERNAME_SIZE+1]; + u08bits r[STUN_MAX_REALM_SIZE+1]; + u08bits p[STUN_MAX_PWD_SIZE+1]; + STRCPY(u,add_user); + STRCPY(r,add_realm); + STRCPY(p,pwd); + stun_produce_integrity_key_str(u, r, p, key, SHATYPE_DEFAULT); + size_t i = 0; + size_t sz = get_hmackey_size(SHATYPE_DEFAULT); + int maxsz = (int) (sz * 2) + 1; + char *s = skey; + for (i = 0; (i < sz) && (maxsz > 2); i++) { + snprintf(s, (size_t) (sz * 2), "%02x", (unsigned int) key[i]); + maxsz -= 2; + s += 2; + } + skey[sz * 2] = 0; + + (*dbd->set_user_key)(u, r, skey); + } + + add_realm=(const u08bits*)""; + add_user=(const u08bits*)""; + } + } else { + msg = "Error: wrong password"; + } + } + } + + write_users_page(s,add_user,add_realm,msg); + + } else { + write_https_logon_page(s); + } + break; + } case AS_FORM_TOGGLE: if(s->as_ok) { handle_toggle_request(s,hr); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index b53172b6..3796de99 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -790,21 +790,21 @@ static int show_secret(u08bits *realm) const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->show_secret) { (*dbd->show_secret)(realm); - } + } - 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) { @@ -816,9 +816,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; From dd834dcca0d1f81eab2b344e3d22474c4d9cc91a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 18 Jan 2015 08:55:20 +0000 Subject: [PATCH 432/805] cosmetics --- src/apps/relay/turn_admin_server.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index d66d00c6..f0892200 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1408,10 +1408,8 @@ static int is_superuser(void) { static void https_cancel_session(const char* ssid) { - printf("%s: 111.111: %s\n",__FUNCTION__,ssid); if(ssid && *ssid) { turnsession_id sid = (turnsession_id)strtoull(ssid,NULL,10); - printf("%s: 111.222: %llu\n",__FUNCTION__,(unsigned long long)sid); send_session_cancellation_to_relay(sid); } } From 64f0a91ee896751414b8831f1c4eff9ce81eb89a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 18 Jan 2015 09:59:39 +0000 Subject: [PATCH 433/805] realm name check --- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/turn_admin_server.c | 33 ++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/examples/var/db/turndb b/examples/var/db/turndb index 9884d3f4822d13a406f0342b5d4cbf8824019922..f2a2cb5ed9536be135ad196a85f180f498a91a56 100644 GIT binary patch delta 81 zcmZqJz}T>Xae_3X=R_H2M$e52o0yrHwr*^k!NhCFfB+^F8;u!tCN^qJ7G?j-#9X$q VF_M{A4k6DVGSN|Zb1!$X4**w666*i} delta 49 zcmZqJz}T>Xae_3X<3t%}M#qf_o0vB?USVQ4VgLc1iH#bQMcMyuY%FDF6x!UuUEu=& Dg^>?p diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index f0892200..ae6bb794 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -53,6 +53,7 @@ #include #include #include +#include #include "userdb.h" #include "mainrelay.h" @@ -1402,6 +1403,17 @@ static const char* logout_link = "
Logout

\r\n static ioa_socket_handle current_socket = NULL; +static int wrong_html_name(const char* s) +{ + int ret = 0; + if(s) { + char* v=evhttp_encode_uri(s); + ret = strcmp(v,s); + free(v); + } + return ret; +} + static int is_superuser(void) { return !(current_socket->as_realm[0]); } @@ -1602,8 +1614,9 @@ static void https_print_str_array(struct str_buffer* sb, char **value, size_t sz if(sb && name && value && sz) { size_t i; for(i=0;i %s %s\r\n",name,value[i]); + } } } } @@ -1911,8 +1924,14 @@ static void write_pc_page(ioa_socket_handle s) else https_print_flag(sb,1,"Anonymous credentials",0); https_print_flag(sb,turn_params.use_auth_secret_with_timestamp,"TURN REST API support",0); - if(turn_params.use_auth_secret_with_timestamp && turn_params.rest_api_separator) - https_print_uint(sb,turn_params.rest_api_separator,"TURN REST API separator ASCII number",0); + if(turn_params.use_auth_secret_with_timestamp) { + + if(!turn_params.rest_api_separator || ((unsigned int)turn_params.rest_api_separator == (unsigned int)':')) { + https_print_str(sb,":","TURN REST API separator",0); + } else { + https_print_uint(sb,turn_params.rest_api_separator,"TURN REST API separator ASCII number",0); + } + } https_print_empty_row(sb,2); @@ -2539,6 +2558,10 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) const u08bits *add_user = (const u08bits*)get_http_header_value(hr, HR_ADD_USER); const char* msg = ""; if(!add_user) add_user = (const u08bits*)""; + if(wrong_html_name((const char*)add_user)) { + msg = "Error: wrong user name"; + add_user = (const u08bits*)""; + } if(add_user[0]) { add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_USER_REALM); if(!add_realm) { @@ -2550,6 +2573,10 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) if(!add_realm[0]) { add_realm=(const u08bits*)current_socket->as_eff_realm; } + if(wrong_html_name((const char*)add_realm)) { + msg = "Error: wrong realm name"; + add_realm = (const u08bits*)""; + } if(add_realm[0]) { const u08bits *pwd = (const u08bits*)get_http_header_value(hr, HR_PASSWORD); const u08bits *pwd1 = (const u08bits*)get_http_header_value(hr, HR_PASSWORD1); From 9bd8f29ac8a545e4a213cc42fc21761e6fa2e8ea Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 19 Jan 2015 06:15:06 +0000 Subject: [PATCH 434/805] shared secrets admin page and fixes --- ChangeLog | 4 +- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/dbdrivers/dbd_mongo.c | 97 +++++++---- src/apps/relay/dbdrivers/dbd_mysql.c | 40 ++++- src/apps/relay/dbdrivers/dbd_pgsql.c | 35 +++- src/apps/relay/dbdrivers/dbd_redis.c | 35 +++- src/apps/relay/dbdrivers/dbd_sqlite.c | 53 ++++-- src/apps/relay/dbdrivers/dbdriver.h | 2 +- src/apps/relay/http_server.c | 2 +- src/apps/relay/turn_admin_server.c | 241 +++++++++++++++++++++++++- src/apps/relay/userdb.c | 6 +- turndb/testmongosetup.sh | 4 +- turndb/testsqldbsetup.sql | 2 + 13 files changed, 445 insertions(+), 76 deletions(-) diff --git a/ChangeLog b/ChangeLog index e19a758a..208138e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,11 @@ 1/12/2015 Oleg Moskalenko Version 4.4.1.1 'Ardee West': - https admin server; - - SSLv2 support removed; + - SSLv2 support removed (security concern fixed); - The server-side short-term credentials mechanism support removed; - 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 Version 4.3.3.1 'Tolomei': diff --git a/examples/var/db/turndb b/examples/var/db/turndb index f2a2cb5ed9536be135ad196a85f180f498a91a56..6689f16992c77f642e74f8fb36cd2bff862067ce 100644 GIT binary patch delta 161 zcmZqJz}T>Xae_3X??f4AM&FGION9AYnAb5dzh%D3e1v%&^TN%HJd>CwiLgwbs4gm# zlbKYMSX3#@%q%aRmtRzpp_iUtmXwp9pHgW#`KGuwQ15C6=GDwMm=6I>mXae_3X=R_H2M$e52ON2R?m~S#Lzh%C;nUUu#^W>Z2+CY&T49qu}-vUL> LFmJvgtziQI2_q7d diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index ce9772ca..d8ae1a4c 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -583,47 +583,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) { @@ -1277,7 +1306,7 @@ static const turn_dbdriver_t driver = { &mongo_set_user_key, &mongo_del_user, &mongo_list_users, - &mongo_show_secret, + &mongo_list_secrets, &mongo_del_secret, &mongo_set_secret, &mongo_add_origin, diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 07f9b0e9..ca2977de 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -605,10 +605,19 @@ static int mysql_list_users(u08bits *realm, secrets_list_t *users, secrets_list_ 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; @@ -621,7 +630,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(;;) { @@ -629,19 +638,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) { @@ -1145,7 +1167,7 @@ static const turn_dbdriver_t driver = { &mysql_set_user_key, &mysql_del_user, &mysql_list_users, - &mysql_show_secret, + &mysql_list_secrets, &mysql_del_secret, &mysql_set_secret, &mysql_add_origin, diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index bdf2af91..c2d4402d 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -376,10 +376,19 @@ static int pgsql_list_users(u08bits *realm, secrets_list_t *users, secrets_list_ 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; @@ -393,16 +402,28 @@ static int pgsql_show_secret(u08bits *realm) { for(i=0;itype != 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); + } } } } @@ -1262,7 +1291,7 @@ static const turn_dbdriver_t driver = { &redis_set_user_key, &redis_del_user, &redis_list_users, - &redis_show_secret, + &redis_list_secrets, &redis_del_secret, &redis_set_secret, &redis_add_origin, diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 4a59bc2e..19dd1dba 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -581,13 +581,22 @@ static int sqlite_list_users(u08bits *realm, secrets_list_t *users, secrets_list 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; @@ -597,17 +606,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); @@ -1200,7 +1229,7 @@ static const turn_dbdriver_t driver = { &sqlite_set_user_key, &sqlite_del_user, &sqlite_list_users, - &sqlite_show_secret, + &sqlite_list_secrets, &sqlite_del_secret, &sqlite_set_secret, &sqlite_add_origin, diff --git a/src/apps/relay/dbdrivers/dbdriver.h b/src/apps/relay/dbdrivers/dbdriver.h index c08e15a7..da5c6ffe 100644 --- a/src/apps/relay/dbdrivers/dbdriver.h +++ b/src/apps/relay/dbdrivers/dbdriver.h @@ -53,7 +53,7 @@ typedef struct _turn_dbdriver_t { int (*set_user_key)(u08bits *usname, u08bits *realm, const char *key); int (*del_user)(u08bits *usname, u08bits *realm); int (*list_users)(u08bits *realm, secrets_list_t *users, secrets_list_t *realms); - int (*show_secret)(u08bits *realm); + int (*list_secrets)(u08bits *realm, secrets_list_t *users, 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); diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index 2d47d325..416c2364 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -61,7 +61,7 @@ static 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,"\r\n\r\n \r\n %s\r\n \r\n \r\n %s\r\n \r\n\r\n",title,title); + snprintf(content_http,sizeof(content_http)-1,"\r\n\r\n \r\n %s\r\n \r\n \r\n %s
use https connection for the admin session\r\n \r\n\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); len_http = strlen(data_http); ns_bcopy(data_http,data,len_http); diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index ae6bb794..20c341bb 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1361,6 +1361,7 @@ enum _AS_FORM { AS_FORM_UPDATE, AS_FORM_PS, AS_FORM_USERS, + AS_FORM_SS, AS_FORM_UNKNOWN }; @@ -1371,13 +1372,15 @@ typedef enum _AS_FORM AS_FORM; #define HR_PASSWORD1 "pwd1" #define HR_REALM "realm" #define HR_ADD_USER "add_user" -#define HR_ADD_USER_REALM "add_user_realm" +#define HR_ADD_REALM "add_user_realm" +#define HR_ADD_SECRET "add_secret" #define HR_CLIENT_PROTOCOL "cprotocol" #define HR_USER_PATTERN "puser" #define HR_MAX_SESSIONS "maxsess" #define HR_CANCEL_SESSION "cs" #define HR_DELETE_USER "du" #define HR_DELETE_REALM "dr" +#define HR_DELETE_SECRET "ds" struct form_name { AS_FORM form; @@ -1393,6 +1396,7 @@ static struct form_name form_names[] = { {AS_FORM_UPDATE,"/update"}, {AS_FORM_PS,"/ps"}, {AS_FORM_USERS,"/us"}, + {AS_FORM_SS,"/ss"}, {AS_FORM_UNKNOWN,NULL} }; @@ -1531,6 +1535,10 @@ static void write_https_home_page(ioa_socket_handle s) str_buffer_append(sb,form_names[AS_FORM_USERS].name); str_buffer_append(sb,"\">"); + str_buffer_append(sb,"
"); + str_buffer_append(sb,"\r\n"); str_buffer_append(sb,"\r\n"); @@ -2325,7 +2333,7 @@ static void write_users_page(ioa_socket_handle s, const u08bits *add_user, const } str_buffer_append(sb,"
Realm name: list_secrets) { + secrets_list_t secrets,realms; + init_secrets_list(&secrets); + init_secrets_list(&realms); + dbd->list_secrets((u08bits*)current_socket->as_eff_realm,&secrets,&realms); + + size_t sz = get_secrets_list_size(&secrets); + size_t i; + for(i=0;i"); + str_buffer_append_sz(sb,i); + str_buffer_append(sb,""); + str_buffer_append(sb,""); + str_buffer_append(sb,get_secrets_list_elem(&secrets,i)); + str_buffer_append(sb,""); + if(!current_socket->as_eff_realm[0]) { + str_buffer_append(sb,""); + str_buffer_append(sb,get_secrets_list_elem(&realms,i)); + str_buffer_append(sb,""); + } + str_buffer_append(sb," delete"); + str_buffer_append(sb,""); + str_buffer_append(sb,""); + ++ret; + } + + clean_secrets_list(&secrets); + clean_secrets_list(&realms); + } + + return ret; +} + +static void write_shared_secrets_page(ioa_socket_handle s, const char* add_secret, const char* add_realm, const char* msg) +{ + if(s && !ioa_socket_tobeclosed(s)) { + + if(!(s->as_ok)) { + write_https_logon_page(s); + } else { + + struct str_buffer* sb = str_buffer_new(); + + str_buffer_append(sb,"\r\n\r\n \r\n "); + str_buffer_append(sb,admin_title); + str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,bold_admin_title); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,home_link); + str_buffer_append(sb,"
\r\n"); + + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
Filter:\r\n"); + + str_buffer_append(sb,"
Realm name: "); + + str_buffer_append(sb,"
"); + + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
\r\n"); + + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
Secret:\r\n"); + + if(msg && msg[0]) { + str_buffer_append(sb,"
"); + str_buffer_append(sb,msg); + str_buffer_append(sb,"

"); + } + + str_buffer_append(sb,"
Realm name:
\r\n"); + + str_buffer_append(sb,"
Secret:
\r\n"); + + str_buffer_append(sb,"
"); + + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
\r\n"); + + str_buffer_append(sb,"Secrets:
\r\n"); + str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,""); + if(!current_socket->as_eff_realm[0]) { + str_buffer_append(sb,""); + } + str_buffer_append(sb,""); + str_buffer_append(sb,"\r\n"); + + size_t total_sz = https_print_secrets(sb); + + str_buffer_append(sb,"\r\n
NValueRealm
\r\n"); + + str_buffer_append(sb,"
Total secrets = "); + str_buffer_append_sz(sb,total_sz); + str_buffer_append(sb,"
\r\n"); + + str_buffer_append(sb,"\r\n\r\n"); + + send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); + send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); + send_str_from_ioa_socket_tcp(s,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + + send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); + + send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); + send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); + + str_buffer_free(sb); + } + } +} + static void handle_toggle_request(ioa_socket_handle s, struct http_request* hr) { if(s && hr) { @@ -2563,7 +2722,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) add_user = (const u08bits*)""; } if(add_user[0]) { - add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_USER_REALM); + add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_REALM); if(!add_realm) { add_realm=(const u08bits*)""; } @@ -2626,6 +2785,82 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } break; } + case AS_FORM_SS: { + if(s->as_ok) { + { + const char *realm0 = get_http_header_value(hr, HR_REALM); + if(!realm0) + realm0=""; + if(!is_superuser()) + realm0 = current_socket->as_realm; + STRCPY(current_socket->as_eff_realm,realm0); + } + + { + const u08bits *secret = (const u08bits*)get_http_header_value(hr, HR_DELETE_SECRET); + if(secret && secret[0]) { + const u08bits *realm = (const u08bits*)get_http_header_value(hr, HR_DELETE_REALM); + if(!is_superuser()) { + realm = (const u08bits*)current_socket->as_realm; + } + if(realm && realm[0]) { + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->del_secret) { + u08bits ss[AUTH_SECRET_SIZE+1]; + u08bits r[STUN_MAX_REALM_SIZE+1]; + STRCPY(ss,secret); + STRCPY(r,realm); + dbd->del_secret(ss,r); + } + } + } + } + + const u08bits *add_realm = (const u08bits*)current_socket->as_eff_realm; + const u08bits *add_secret = (const u08bits*)get_http_header_value(hr, HR_ADD_SECRET); + const char* msg = ""; + if(!add_secret) add_secret = (const u08bits*)""; + if(wrong_html_name((const char*)add_secret)) { + msg = "Error: wrong secret value"; + add_secret = (const u08bits*)""; + } + if(add_secret[0]) { + add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_REALM); + if(!add_realm) { + add_realm=(const u08bits*)""; + } + if(!is_superuser()) { + add_realm = (const u08bits*)current_socket->as_realm; + } + if(!add_realm[0]) { + add_realm=(const u08bits*)current_socket->as_eff_realm; + } + if(wrong_html_name((const char*)add_realm)) { + msg = "Error: wrong realm name"; + add_realm = (const u08bits*)""; + } + if(add_realm[0]) { + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->set_secret) { + u08bits ss[AUTH_SECRET_SIZE+1]; + u08bits r[STUN_MAX_REALM_SIZE+1]; + STRCPY(ss,add_secret); + STRCPY(r,add_realm); + (*dbd->set_secret)(ss, r); + } + + add_secret=(const u08bits*)""; + add_realm=(const u08bits*)""; + } + } + + write_shared_secrets_page(s,(const char*)add_secret,(const char*)add_realm,msg); + + } else { + write_https_logon_page(s); + } + break; + } case AS_FORM_TOGGLE: if(s->as_ok) { handle_toggle_request(s,hr); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 3796de99..1c18d2b3 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -785,11 +785,9 @@ static int list_users(u08bits *realm, int is_admin) 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; diff --git a/turndb/testmongosetup.sh b/turndb/testmongosetup.sh index dba4757d..b7c32fb1 100755 --- a/turndb/testmongosetup.sh +++ b/turndb/testmongosetup.sh @@ -5,7 +5,7 @@ mongo $* < Date: Mon, 19 Jan 2015 08:00:47 +0000 Subject: [PATCH 435/805] origins admin page --- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/dbdrivers/dbd_mongo.c | 117 +++++++------ src/apps/relay/dbdrivers/dbd_mysql.c | 29 +++- src/apps/relay/dbdrivers/dbd_pgsql.c | 38 ++++- src/apps/relay/dbdrivers/dbd_redis.c | 24 ++- src/apps/relay/dbdrivers/dbd_sqlite.c | 25 ++- src/apps/relay/dbdrivers/dbdriver.h | 4 +- src/apps/relay/turn_admin_server.c | 236 +++++++++++++++++++++++++- src/apps/relay/userdb.c | 24 +-- 9 files changed, 404 insertions(+), 93 deletions(-) diff --git a/examples/var/db/turndb b/examples/var/db/turndb index 6689f16992c77f642e74f8fb36cd2bff862067ce..8a52386f796f471f4b0ab4eb6dcc440391236492 100644 GIT binary patch delta 51 zcmZqJz}T>Xae_2s_(U0J#_){^YmAwg=Wk}@nZnE{HPKOQ@=o($CgyWMflbVef}0Oo H+sgm|s8SEs delta 38 tcmZqJz}T>Xae_3X??f4AM&FGIYm7HD@~mZ^ywf}w$T-Bj`JA> %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) { diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index ca2977de..4b793d37 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -740,16 +740,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) { @@ -767,7 +773,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); + } } } } diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index c2d4402d..9f843bf5 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -508,16 +508,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)) { @@ -525,21 +534,32 @@ static int pgsql_list_origins(u08bits *realm) { } else { int i = 0; for(i=0;i> %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) { diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index eac66418..fbd7fa57 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -840,9 +840,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; @@ -873,6 +879,7 @@ static int redis_list_origins(u08bits *realm) { } for(isz=0;isztype); } 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); @@ -893,9 +907,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) { diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 19dd1dba..36e6dc50 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -761,20 +761,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); @@ -789,8 +794,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 { diff --git a/src/apps/relay/dbdrivers/dbdriver.h b/src/apps/relay/dbdrivers/dbdriver.h index da5c6ffe..53f1fd06 100644 --- a/src/apps/relay/dbdrivers/dbdriver.h +++ b/src/apps/relay/dbdrivers/dbdriver.h @@ -53,12 +53,12 @@ typedef struct _turn_dbdriver_t { int (*set_user_key)(u08bits *usname, u08bits *realm, const char *key); 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 *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); diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 20c341bb..a115c87a 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1362,6 +1362,7 @@ enum _AS_FORM { AS_FORM_PS, AS_FORM_USERS, AS_FORM_SS, + AS_FORM_OS, AS_FORM_UNKNOWN }; @@ -1374,6 +1375,7 @@ typedef enum _AS_FORM AS_FORM; #define HR_ADD_USER "add_user" #define HR_ADD_REALM "add_user_realm" #define HR_ADD_SECRET "add_secret" +#define HR_ADD_ORIGIN "add_origin" #define HR_CLIENT_PROTOCOL "cprotocol" #define HR_USER_PATTERN "puser" #define HR_MAX_SESSIONS "maxsess" @@ -1381,6 +1383,7 @@ typedef enum _AS_FORM AS_FORM; #define HR_DELETE_USER "du" #define HR_DELETE_REALM "dr" #define HR_DELETE_SECRET "ds" +#define HR_DELETE_ORIGIN "do" struct form_name { AS_FORM form; @@ -1397,6 +1400,7 @@ static struct form_name form_names[] = { {AS_FORM_PS,"/ps"}, {AS_FORM_USERS,"/us"}, {AS_FORM_SS,"/ss"}, + {AS_FORM_OS,"/os"}, {AS_FORM_UNKNOWN,NULL} }; @@ -1539,6 +1543,10 @@ static void write_https_home_page(ioa_socket_handle s) str_buffer_append(sb,form_names[AS_FORM_SS].name); str_buffer_append(sb,"\">"); + str_buffer_append(sb,"
"); + str_buffer_append(sb,"\r\n"); str_buffer_append(sb,"\r\n"); @@ -2250,7 +2258,7 @@ static size_t https_print_users(struct str_buffer* sb) size_t i; for(i=0;i"); - str_buffer_append_sz(sb,i); + str_buffer_append_sz(sb,i+1); str_buffer_append(sb,""); str_buffer_append(sb,""); str_buffer_append(sb,get_secrets_list_elem(&users,i)); @@ -2415,7 +2423,7 @@ static size_t https_print_secrets(struct str_buffer* sb) size_t i; for(i=0;i"); - str_buffer_append_sz(sb,i); + str_buffer_append_sz(sb,i+1); str_buffer_append(sb,""); str_buffer_append(sb,""); str_buffer_append(sb,get_secrets_list_elem(&secrets,i)); @@ -2552,6 +2560,156 @@ static void write_shared_secrets_page(ioa_socket_handle s, const char* add_secre } } +static size_t https_print_origins(struct str_buffer* sb) +{ + size_t ret = 0; + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->list_origins) { + secrets_list_t origins,realms; + init_secrets_list(&origins); + init_secrets_list(&realms); + dbd->list_origins((u08bits*)current_socket->as_eff_realm,&origins,&realms); + + size_t sz = get_secrets_list_size(&origins); + size_t i; + for(i=0;i"); + str_buffer_append_sz(sb,i+1); + str_buffer_append(sb,""); + str_buffer_append(sb,""); + str_buffer_append(sb,get_secrets_list_elem(&origins,i)); + str_buffer_append(sb,""); + if(!current_socket->as_eff_realm[0]) { + str_buffer_append(sb,""); + str_buffer_append(sb,get_secrets_list_elem(&realms,i)); + str_buffer_append(sb,""); + } + if(is_superuser()) { + str_buffer_append(sb," delete"); + str_buffer_append(sb,""); + } + str_buffer_append(sb,""); + ++ret; + } + + clean_secrets_list(&origins); + clean_secrets_list(&realms); + } + + return ret; +} + +static void write_origins_page(ioa_socket_handle s, const char* add_origin, const char* add_realm, const char* msg) +{ + if(s && !ioa_socket_tobeclosed(s)) { + + if(!(s->as_ok)) { + write_https_logon_page(s); + } else { + + struct str_buffer* sb = str_buffer_new(); + + str_buffer_append(sb,"\r\n\r\n \r\n "); + str_buffer_append(sb,admin_title); + str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,bold_admin_title); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,home_link); + str_buffer_append(sb,"
\r\n"); + + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
Filter:\r\n"); + + str_buffer_append(sb,"
Realm name: "); + + str_buffer_append(sb,"
"); + + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
\r\n"); + + if(is_superuser()) { + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
Origin:\r\n"); + + if(msg && msg[0]) { + str_buffer_append(sb,"
"); + str_buffer_append(sb,msg); + str_buffer_append(sb,"

"); + } + + str_buffer_append(sb,"
Realm name:
\r\n"); + + str_buffer_append(sb,"
Origin:
\r\n"); + + str_buffer_append(sb,"
"); + + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
\r\n"); + } + + str_buffer_append(sb,"Origins:
\r\n"); + str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,""); + if(!current_socket->as_eff_realm[0]) { + str_buffer_append(sb,""); + } + if(is_superuser()) { + str_buffer_append(sb,""); + } + str_buffer_append(sb,"\r\n"); + + size_t total_sz = https_print_origins(sb); + + str_buffer_append(sb,"\r\n
NValueRealm
\r\n"); + + str_buffer_append(sb,"
Total origins = "); + str_buffer_append_sz(sb,total_sz); + str_buffer_append(sb,"
\r\n"); + + str_buffer_append(sb,"\r\n\r\n"); + + send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); + send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); + send_str_from_ioa_socket_tcp(s,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + + send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); + + send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); + send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); + + str_buffer_free(sb); + } + } +} + static void handle_toggle_request(ioa_socket_handle s, struct http_request* hr) { if(s && hr) { @@ -2732,6 +2890,9 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) if(!add_realm[0]) { add_realm=(const u08bits*)current_socket->as_eff_realm; } + if(!add_realm[0]) { + add_realm = (const u08bits*)get_realm(NULL)->options.name; + } if(wrong_html_name((const char*)add_realm)) { msg = "Error: wrong realm name"; add_realm = (const u08bits*)""; @@ -2835,6 +2996,9 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) if(!add_realm[0]) { add_realm=(const u08bits*)current_socket->as_eff_realm; } + if(!add_realm[0]) { + add_realm = (const u08bits*)get_realm(NULL)->options.name; + } if(wrong_html_name((const char*)add_realm)) { msg = "Error: wrong realm name"; add_realm = (const u08bits*)""; @@ -2861,6 +3025,74 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } break; } + case AS_FORM_OS: { + if(s->as_ok) { + { + const char *realm0 = get_http_header_value(hr, HR_REALM); + if(!realm0) + realm0=""; + if(!is_superuser()) + realm0 = current_socket->as_realm; + STRCPY(current_socket->as_eff_realm,realm0); + } + + if(is_superuser()) { + const u08bits *origin = (const u08bits*)get_http_header_value(hr, HR_DELETE_ORIGIN); + if(origin && origin[0]) { + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->del_origin) { + u08bits o[STUN_MAX_ORIGIN_SIZE+1]; + STRCPY(o,origin); + dbd->del_origin(o); + u08bits corigin[STUN_MAX_ORIGIN_SIZE+1]; + get_canonic_origin((const char *)origin, (char *)corigin, sizeof(corigin)-1); + dbd->del_origin(corigin); + } + } + } + + const u08bits *add_realm = (const u08bits*)current_socket->as_eff_realm; + const u08bits *add_origin = (const u08bits*)get_http_header_value(hr, HR_ADD_ORIGIN); + const char* msg = ""; + if(!add_origin) add_origin = (const u08bits*)""; + u08bits corigin[STUN_MAX_ORIGIN_SIZE+1]; + get_canonic_origin((const char *)add_origin, (char *)corigin, sizeof(corigin)-1); + if(corigin[0]) { + add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_REALM); + if(!add_realm) { + add_realm=(const u08bits*)""; + } + if(!is_superuser()) { + add_realm = (const u08bits*)current_socket->as_realm; + } + if(!add_realm[0]) { + add_realm=(const u08bits*)current_socket->as_eff_realm; + } + if(!add_realm[0]) { + add_realm = (const u08bits*)get_realm(NULL)->options.name; + } + if(add_realm[0]) { + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->add_origin) { + u08bits o[STUN_MAX_ORIGIN_SIZE+1]; + u08bits r[STUN_MAX_REALM_SIZE+1]; + STRCPY(o,corigin); + STRCPY(r,add_realm); + (*dbd->add_origin)(o, r); + } + + add_origin=(const u08bits*)""; + add_realm=(const u08bits*)""; + } + } + + write_origins_page(s,(const char*)add_origin,(const char*)add_realm,msg); + + } else { + write_https_logon_page(s); + } + break; + } case AS_FORM_TOGGLE: if(s->as_ok) { handle_toggle_request(s,hr); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 1c18d2b3..57ac5291 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -828,9 +828,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; @@ -842,9 +842,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; @@ -854,10 +854,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) @@ -865,9 +865,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; From 01e1316c493bf7cce3e6cfad206050ed13c7ce53 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 20 Jan 2015 08:55:28 +0000 Subject: [PATCH 436/805] black/white lists page --- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/dbdrivers/dbd_mongo.c | 104 +++++++++--- src/apps/relay/dbdrivers/dbd_mysql.c | 32 ++++ src/apps/relay/dbdrivers/dbd_pgsql.c | 47 +++++- src/apps/relay/dbdrivers/dbd_redis.c | 27 ++++ src/apps/relay/dbdrivers/dbd_sqlite.c | 40 +++++ src/apps/relay/dbdrivers/dbdriver.h | 1 + src/apps/relay/http_server.c | 5 +- src/apps/relay/http_server.h | 2 +- src/apps/relay/turn_admin_server.c | 223 +++++++++++++++++--------- turndb/schema.mongo.sh | 2 +- turndb/testmongosetup.sh | 1 + 12 files changed, 377 insertions(+), 107 deletions(-) diff --git a/examples/var/db/turndb b/examples/var/db/turndb index 8a52386f796f471f4b0ab4eb6dcc440391236492..8026af81d2843e4a1669b0916521d8352746dfe5 100644 GIT binary patch delta 139 zcmZqJz}T>Xae_2s@!jJ3XEC=jw{C1KVHPuDKmauuQ+A@GXae_2s_(U0J#_){^>!dd`@~mW@yj?yV$XL!id8=|XkkQUOdAfQfkkP_C Nd9^hE=Ed5vIskfV6tMsR diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index cf04a864..a491df68 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -666,7 +666,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); @@ -696,38 +696,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 delete) +{ + 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(delete) { + 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 = 0; + + if(delete) { + 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; @@ -1327,6 +1378,7 @@ 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, diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 4b793d37..a536bdac 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -701,6 +701,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 delete) +{ + 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(delete) { + 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; @@ -1196,6 +1227,7 @@ 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, diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index 9f843bf5..6b99e2a6 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -245,7 +245,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)); @@ -449,13 +449,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)); @@ -467,7 +467,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 delete) +{ + 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(delete) { + 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) { @@ -913,6 +951,7 @@ 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, diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index fbd7fa57..de1bf28c 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -809,6 +809,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 delete) +{ + 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(delete) { + 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; @@ -1315,6 +1341,7 @@ 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, diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 36e6dc50..f5f2c6d6 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -959,6 +959,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 delete) +{ + 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(delete) { + 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(); @@ -1254,6 +1293,7 @@ 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, diff --git a/src/apps/relay/dbdrivers/dbdriver.h b/src/apps/relay/dbdrivers/dbdriver.h index 53f1fd06..7cfd3b01 100644 --- a/src/apps/relay/dbdrivers/dbdriver.h +++ b/src/apps/relay/dbdrivers/dbdriver.h @@ -63,6 +63,7 @@ typedef struct _turn_dbdriver_t { 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 delete); 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); diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index 416c2364..337dbd77 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -238,8 +238,8 @@ static void free_headers_list(struct headers_list *h) { } } -const char *get_http_header_value(const struct http_request *request, const char* key) { - const char *ret = NULL; +const char *get_http_header_value(const struct http_request *request, const char* key, const char* default_value) { + const char *ret = default_value; if(key && key[0] && request && request->headers) { if(request->headers->uri_headers) { ret = evhttp_find_header(request->headers->uri_headers,key); @@ -247,6 +247,7 @@ const char *get_http_header_value(const struct http_request *request, const char if(!ret && request->headers->post_headers) { ret = get_headers_list_value(request->headers->post_headers,key); } + if(!ret) ret = default_value; } return ret; } diff --git a/src/apps/relay/http_server.h b/src/apps/relay/http_server.h index 8bb3f26d..422d7951 100644 --- a/src/apps/relay/http_server.h +++ b/src/apps/relay/http_server.h @@ -63,7 +63,7 @@ struct http_request { }; struct http_request* parse_http_request(char* request); -const char *get_http_header_value(const struct http_request *request, const char* key); +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); //////////////////////////////////////////// diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index a115c87a..821654f5 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1384,6 +1384,13 @@ typedef enum _AS_FORM AS_FORM; #define HR_DELETE_REALM "dr" #define HR_DELETE_SECRET "ds" #define HR_DELETE_ORIGIN "do" +#define HR_DELETE_IP "dip" +#define HR_DELETE_IP_REALM "dipr" +#define HR_DELETE_IP_KIND "dipk" +#define HR_ADD_IP "aip" +#define HR_ADD_IP_REALM "aipr" +#define HR_ADD_IP_KIND "aipk" +#define HR_UPDATE_PARAMETER "togglepar" struct form_name { AS_FORM form; @@ -1571,7 +1578,7 @@ static void sbprintf(struct str_buffer *sb, const char *format, ...) if(sb && format) { va_list args; va_start (args, format); - static char s[1025]="\0"; + char s[1025]="\0"; vsnprintf(s,sizeof(s)-1,format, args); str_buffer_append(sb,s); va_end (args); @@ -1586,7 +1593,7 @@ static void https_print_flag(struct str_buffer* sb, int flag, const char* name, if(!param_name) { sbprintf(sb,"%s%s\r\n",name,get_flag(flag)); } else { - sbprintf(sb,"%s%s\r\n",name,param_name,get_flag(flag)); + sbprintf(sb,"%s%s\r\n",name,HR_UPDATE_PARAMETER,param_name,get_flag(flag)); } } } @@ -1604,9 +1611,9 @@ static void https_print_uint(struct str_buffer* sb, unsigned long value, const c } } else { if(value) { - sbprintf(sb,"%s
\r\n",name,param_name,param_name,value); + sbprintf(sb,"%s
\r\n",name,form_names[AS_FORM_UPDATE].name,HR_UPDATE_PARAMETER,param_name,param_name,value); } else { - sbprintf(sb,"%s
\r\n",name,param_name,param_name); + sbprintf(sb,"%s
\r\n",name,form_names[AS_FORM_UPDATE].name,HR_UPDATE_PARAMETER,param_name,param_name); } } } @@ -1620,7 +1627,7 @@ static void https_print_str(struct str_buffer* sb, const char *value, const char if(!param_name) { sbprintf(sb,"%s%s\r\n",name,value); } else { - sbprintf(sb,"%s
\r\n",name,param_name,param_name,value); + sbprintf(sb,"%s
\r\n",name,form_names[AS_FORM_UPDATE].name,HR_UPDATE_PARAMETER,param_name,param_name,value); } } } @@ -1666,21 +1673,57 @@ static size_t https_print_addr_list(struct str_buffer* sb, turn_server_addrs_lis return 0; } -static void https_print_ip_range_list(struct str_buffer* sb, ip_range_list_t *value, const char* name) +static const char* change_ip_addr_html(int dynamic,const char* kind,const char* ip,const char *realm, char *buffer, size_t sz) { - if(sb && name && value && value->ranges_number && value->rs) { - size_t i; - for(i=0;iranges_number;++i) { - if(value->rs[i].realm[0]) { - if(get_eff_realm()[0] && strcmp(get_eff_realm(),value->rs[i].realm)) { - continue; - } else { - sbprintf(sb," %s %s (%s)\r\n",name,value->rs[i].str,value->rs[i].realm); - } + if(!buffer || !sz) { + return ""; + } else { + buffer[0]=0; + if(dynamic && kind && ip) { + + if(!realm) realm=""; + + if(current_socket->as_realm[0] && strcmp(current_socket->as_realm,realm)) { + //delete forbidden } else { - sbprintf(sb," %s %s\r\n",name,value->rs[i].str); + char *eip = evhttp_encode_uri(ip); + snprintf(buffer,sz-1,"delete",form_names[AS_FORM_UPDATE].name,HR_DELETE_IP_KIND,kind,HR_DELETE_IP_REALM,realm,HR_DELETE_IP,eip); + free(eip); } } + return buffer; + } +} + +static void https_print_ip_range_list(struct str_buffer* sb, ip_range_list_t *value, const char* name, const char* kind, int dynamic) +{ + if(sb && name) { + if(value && value->rs) { + size_t i; + char buffer[1025]; + for(i=0;iranges_number;++i) { + if(value->rs[i].realm[0]) { + if(get_eff_realm()[0] && strcmp(get_eff_realm(),value->rs[i].realm)) { + continue; + } else { + sbprintf(sb," %s %s [%s] %s\r\n",name,value->rs[i].str,value->rs[i].realm, change_ip_addr_html(dynamic,kind,value->rs[i].str,value->rs[i].realm,buffer,sizeof(buffer))); + } + } else { + sbprintf(sb," %s %s %s\r\n",name,value->rs[i].str, change_ip_addr_html(dynamic,kind,value->rs[i].str,value->rs[i].realm,buffer,sizeof(buffer))); + } + } + } + + if(dynamic) { + sbprintf(sb," %s",name); + sbprintf(sb,"
IP range:",form_names[AS_FORM_UPDATE].name,HR_ADD_IP_KIND,kind,HR_ADD_IP); + sbprintf(sb,"Realm: as_eff_realm); + if(!is_superuser()) { + sbprintf(sb," disabled "); + } + sbprintf(sb,">"); + sbprintf(sb,"
\r\n"); + } } } @@ -1868,17 +1911,17 @@ static void write_pc_page(ioa_socket_handle s) https_print_uint(sb,(unsigned long)turn_params.min_port,"min-port",0); https_print_uint(sb,(unsigned long)turn_params.max_port,"max-port",0); - https_print_ip_range_list(sb,&turn_params.ip_whitelist,"Whitelist IP (static)"); + https_print_ip_range_list(sb,&turn_params.ip_whitelist,"Whitelist IP (static)",NULL,0); { ip_range_list_t* l = get_ip_list("allowed"); - https_print_ip_range_list(sb,l,"Whitelist IP (dynamic)"); + https_print_ip_range_list(sb,l,"Whitelist IP (dynamic)","allowed",1); ip_list_free(l); } - https_print_ip_range_list(sb,&turn_params.ip_blacklist,"Blacklist IP (static)"); + https_print_ip_range_list(sb,&turn_params.ip_blacklist,"Blacklist IP (static)", NULL, 0); { ip_range_list_t* l = get_ip_list("denied"); - https_print_ip_range_list(sb,l,"Blacklist IP (dynamic)"); + https_print_ip_range_list(sb,l,"Blacklist IP (dynamic)", "denied", 1); ip_list_free(l); } @@ -2713,7 +2756,7 @@ static void write_origins_page(ioa_socket_handle s, const char* add_origin, cons static void handle_toggle_request(ioa_socket_handle s, struct http_request* hr) { if(s && hr) { - const char *param = get_http_header_value(hr, "parameter"); + const char *param = get_http_header_value(hr, HR_UPDATE_PARAMETER, NULL); toggle_param(param); } } @@ -2721,9 +2764,67 @@ static void handle_toggle_request(ioa_socket_handle s, struct http_request* hr) static void handle_update_request(ioa_socket_handle s, struct http_request* hr) { if(s && hr) { - const char *param = get_http_header_value(hr, "parameter"); - if(param) { - update_param(param,get_http_header_value(hr,param)); + { + const char *param = get_http_header_value(hr, HR_UPDATE_PARAMETER, NULL); + if(param) { + update_param(param,get_http_header_value(hr,param,"")); + } + } + + { + const char* eip = get_http_header_value(hr, HR_DELETE_IP, NULL); + if(eip && eip[0]) { + char* ip = evhttp_decode_uri(eip); + const char* r = get_http_header_value(hr, HR_DELETE_IP_REALM,""); + const char* kind = get_http_header_value(hr, HR_DELETE_IP_KIND,""); + + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->set_permission_ip) { + + if(!r || !r[0]) { + r = current_socket->as_realm; + } + + if(current_socket->as_realm[0] && strcmp(current_socket->as_realm,r)) { + //forbidden + } else { + + u08bits realm[STUN_MAX_REALM_SIZE+1]="\0"; + STRCPY(realm,r); + + dbd->set_permission_ip(kind, realm, ip, 1); + } + } + free(ip); + } + } + + { + const char* eip = get_http_header_value(hr, HR_ADD_IP,NULL); + if(eip && eip[0]) { + char* ip = evhttp_decode_uri(eip); + const char* r = get_http_header_value(hr, HR_ADD_IP_REALM,""); + const char* kind = get_http_header_value(hr, HR_ADD_IP_KIND,""); + + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->set_permission_ip) { + + if(!r || !r[0]) { + r = current_socket->as_realm; + } + + if(current_socket->as_realm[0] && strcmp(current_socket->as_realm,r)) { + //forbidden + } else { + + u08bits realm[STUN_MAX_REALM_SIZE+1]="\0"; + STRCPY(realm,r); + + dbd->set_permission_ip(kind, realm, ip, 0); + } + } + free(ip); + } } } } @@ -2731,15 +2832,15 @@ static void handle_update_request(ioa_socket_handle s, struct http_request* hr) static void handle_logon_request(ioa_socket_handle s, struct http_request* hr) { if(s && hr) { - const char *uname = get_http_header_value(hr, HR_USERNAME); - const char *pwd = get_http_header_value(hr, HR_PASSWORD); + const char *uname = get_http_header_value(hr, HR_USERNAME, NULL); + const char *pwd = get_http_header_value(hr, HR_PASSWORD, NULL); if(!(s->as_ok) && uname && pwd) { const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->get_admin_user) { password_t password; - char realm[STUN_MAX_REALM_SIZE]="\0"; + char realm[STUN_MAX_REALM_SIZE+1]="\0"; if((*(dbd->get_admin_user))((const u08bits*)uname,(u08bits*)realm,password)>=0) { if(!strcmp(pwd,(char*)password)) { STRCPY(s->as_login,uname); @@ -2791,9 +2892,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) switch(form) { case AS_FORM_PC: { if(s->as_ok) { - const char *realm0 = get_http_header_value(hr, HR_REALM); - if(!realm0) - realm0=""; + const char *realm0 = get_http_header_value(hr, HR_REALM, current_socket->as_realm); if(!is_superuser()) realm0 = current_socket->as_realm; STRCPY(current_socket->as_eff_realm,realm0); @@ -2805,28 +2904,24 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } case AS_FORM_PS: { if(s->as_ok) { - const char *realm0 = get_http_header_value(hr, HR_REALM); - if(!realm0) - realm0=""; + const char *realm0 = get_http_header_value(hr, HR_REALM, current_socket->as_realm); if(!is_superuser()) realm0 = current_socket->as_realm; STRCPY(current_socket->as_eff_realm,realm0); - const char* client_protocol = get_http_header_value(hr, HR_CLIENT_PROTOCOL); - if(!client_protocol) client_protocol=""; + const char* client_protocol = get_http_header_value(hr, HR_CLIENT_PROTOCOL, ""); - const char* user_pattern = get_http_header_value(hr, HR_USER_PATTERN); - if(!user_pattern) user_pattern=""; + const char* user_pattern = get_http_header_value(hr, HR_USER_PATTERN, ""); turnsession_id csid=0; - const char* ssid = get_http_header_value(hr, HR_CANCEL_SESSION); + const char* ssid = get_http_header_value(hr, HR_CANCEL_SESSION, NULL); if(ssid) { https_cancel_session(ssid); csid = (turnsession_id)strtoull(ssid,NULL,10); } size_t max_sessions = cli_max_output_sessions; - const char* s_max_sessions = get_http_header_value(hr, HR_MAX_SESSIONS); + const char* s_max_sessions = get_http_header_value(hr, HR_MAX_SESSIONS,NULL); if(s_max_sessions) { max_sessions=strtoul(s_max_sessions,NULL,10); if(!max_sessions) max_sessions = cli_max_output_sessions; @@ -2843,18 +2938,16 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) case AS_FORM_USERS: { if(s->as_ok) { { - const char *realm0 = get_http_header_value(hr, HR_REALM); - if(!realm0) - realm0=""; + const char *realm0 = get_http_header_value(hr, HR_REALM, current_socket->as_realm); if(!is_superuser()) realm0 = current_socket->as_realm; STRCPY(current_socket->as_eff_realm,realm0); } { - const u08bits *user = (const u08bits*)get_http_header_value(hr, HR_DELETE_USER); + const u08bits *user = (const u08bits*)get_http_header_value(hr, HR_DELETE_USER, NULL); if(user && user[0]) { - const u08bits *realm = (const u08bits*)get_http_header_value(hr, HR_DELETE_REALM); + const u08bits *realm = (const u08bits*)get_http_header_value(hr, HR_DELETE_REALM, ""); if(!is_superuser()) { realm = (const u08bits*)current_socket->as_realm; } @@ -2872,18 +2965,14 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } const u08bits *add_realm = (const u08bits*)current_socket->as_eff_realm; - const u08bits *add_user = (const u08bits*)get_http_header_value(hr, HR_ADD_USER); + const u08bits *add_user = (const u08bits*)get_http_header_value(hr, HR_ADD_USER,""); const char* msg = ""; - if(!add_user) add_user = (const u08bits*)""; if(wrong_html_name((const char*)add_user)) { msg = "Error: wrong user name"; add_user = (const u08bits*)""; } if(add_user[0]) { - add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_REALM); - if(!add_realm) { - add_realm=(const u08bits*)""; - } + add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_REALM, current_socket->as_realm); if(!is_superuser()) { add_realm = (const u08bits*)current_socket->as_realm; } @@ -2898,8 +2987,8 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) add_realm = (const u08bits*)""; } if(add_realm[0]) { - const u08bits *pwd = (const u08bits*)get_http_header_value(hr, HR_PASSWORD); - const u08bits *pwd1 = (const u08bits*)get_http_header_value(hr, HR_PASSWORD1); + const u08bits *pwd = (const u08bits*)get_http_header_value(hr, HR_PASSWORD, NULL); + const u08bits *pwd1 = (const u08bits*)get_http_header_value(hr, HR_PASSWORD1, NULL); if(pwd && pwd1 && pwd[0] && pwd1[0] && !strcmp((const char*)pwd,(const char*)pwd1)) { const turn_dbdriver_t * dbd = get_dbdriver(); @@ -2949,18 +3038,16 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) case AS_FORM_SS: { if(s->as_ok) { { - const char *realm0 = get_http_header_value(hr, HR_REALM); - if(!realm0) - realm0=""; + const char *realm0 = get_http_header_value(hr, HR_REALM, current_socket->as_realm); if(!is_superuser()) realm0 = current_socket->as_realm; STRCPY(current_socket->as_eff_realm,realm0); } { - const u08bits *secret = (const u08bits*)get_http_header_value(hr, HR_DELETE_SECRET); + const u08bits *secret = (const u08bits*)get_http_header_value(hr, HR_DELETE_SECRET, NULL); if(secret && secret[0]) { - const u08bits *realm = (const u08bits*)get_http_header_value(hr, HR_DELETE_REALM); + const u08bits *realm = (const u08bits*)get_http_header_value(hr, HR_DELETE_REALM, NULL); if(!is_superuser()) { realm = (const u08bits*)current_socket->as_realm; } @@ -2978,18 +3065,14 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } const u08bits *add_realm = (const u08bits*)current_socket->as_eff_realm; - const u08bits *add_secret = (const u08bits*)get_http_header_value(hr, HR_ADD_SECRET); + const u08bits *add_secret = (const u08bits*)get_http_header_value(hr, HR_ADD_SECRET, ""); const char* msg = ""; - if(!add_secret) add_secret = (const u08bits*)""; if(wrong_html_name((const char*)add_secret)) { msg = "Error: wrong secret value"; add_secret = (const u08bits*)""; } if(add_secret[0]) { - add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_REALM); - if(!add_realm) { - add_realm=(const u08bits*)""; - } + add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_REALM, current_socket->as_realm); if(!is_superuser()) { add_realm = (const u08bits*)current_socket->as_realm; } @@ -3028,16 +3111,14 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) case AS_FORM_OS: { if(s->as_ok) { { - const char *realm0 = get_http_header_value(hr, HR_REALM); - if(!realm0) - realm0=""; + const char *realm0 = get_http_header_value(hr, HR_REALM, current_socket->as_realm); if(!is_superuser()) realm0 = current_socket->as_realm; STRCPY(current_socket->as_eff_realm,realm0); } if(is_superuser()) { - const u08bits *origin = (const u08bits*)get_http_header_value(hr, HR_DELETE_ORIGIN); + const u08bits *origin = (const u08bits*)get_http_header_value(hr, HR_DELETE_ORIGIN, NULL); if(origin && origin[0]) { const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->del_origin) { @@ -3052,16 +3133,12 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } const u08bits *add_realm = (const u08bits*)current_socket->as_eff_realm; - const u08bits *add_origin = (const u08bits*)get_http_header_value(hr, HR_ADD_ORIGIN); + const u08bits *add_origin = (const u08bits*)get_http_header_value(hr, HR_ADD_ORIGIN, ""); const char* msg = ""; - if(!add_origin) add_origin = (const u08bits*)""; u08bits corigin[STUN_MAX_ORIGIN_SIZE+1]; get_canonic_origin((const char *)add_origin, (char *)corigin, sizeof(corigin)-1); if(corigin[0]) { - add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_REALM); - if(!add_realm) { - add_realm=(const u08bits*)""; - } + add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_REALM, current_socket->as_realm); if(!is_superuser()) { add_realm = (const u08bits*)current_socket->as_realm; } diff --git a/turndb/schema.mongo.sh b/turndb/schema.mongo.sh index 63ae491c..e62613ab 100755 --- a/turndb/schema.mongo.sh +++ b/turndb/schema.mongo.sh @@ -5,7 +5,7 @@ mongo $* < Date: Tue, 20 Jan 2015 17:05:58 +0000 Subject: [PATCH 437/805] third-party authetorization option is mandatory with oauth --- ChangeLog | 1 + README.turnserver | 2 +- examples/etc/turnserver.conf | 2 +- .../secure_relay_with_db_mongo.sh | 3 +- .../secure_relay_with_db_mysql.sh | 3 +- .../secure_relay_with_db_mysql_ssl.sh | 3 +- .../secure_relay_with_db_psql.sh | 5 +-- .../secure_relay_with_db_redis.sh | 3 +- .../secure_relay_with_db_sqlite.sh | 3 +- .../oauth/secure_relay_with_db_mongo.sh | 34 +++++++++++++++++ .../oauth/secure_relay_with_db_mysql.sh | 35 +++++++++++++++++ .../oauth/secure_relay_with_db_mysql_ssl.sh | 36 ++++++++++++++++++ .../oauth/secure_relay_with_db_psql.sh | 38 +++++++++++++++++++ .../oauth/secure_relay_with_db_redis.sh | 38 +++++++++++++++++++ .../oauth/secure_relay_with_db_sqlite.sh | 35 +++++++++++++++++ examples/scripts/oauth/secure_udp_client.sh | 34 +++++++++++++++++ man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 4 +- man/man1/turnutils.1 | 2 +- src/apps/relay/mainrelay.c | 2 +- src/apps/relay/turn_admin_server.c | 3 +- src/apps/relay/userdb.c | 2 +- 22 files changed, 268 insertions(+), 22 deletions(-) create mode 100755 examples/scripts/oauth/secure_relay_with_db_mongo.sh create mode 100755 examples/scripts/oauth/secure_relay_with_db_mysql.sh create mode 100755 examples/scripts/oauth/secure_relay_with_db_mysql_ssl.sh create mode 100755 examples/scripts/oauth/secure_relay_with_db_psql.sh create mode 100755 examples/scripts/oauth/secure_relay_with_db_redis.sh create mode 100755 examples/scripts/oauth/secure_relay_with_db_sqlite.sh create mode 100755 examples/scripts/oauth/secure_udp_client.sh diff --git a/ChangeLog b/ChangeLog index 208138e2..fb886eee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,7 @@ Version 4.4.1.1 'Ardee West': - OpenSSL 1.1.0 supported; - shared secrets fixed in MongoDB: multiple secrets per realm allowed; - shared secrets admin fixed in Redis; + - --oauth option now strictly requires oAuth authentication; 12/24/2014 Oleg Moskalenko Version 4.3.3.1 'Tolomei': diff --git a/README.turnserver b/README.turnserver index 85087bb4..50b3be53 100644 --- a/README.turnserver +++ b/README.turnserver @@ -181,7 +181,7 @@ Flags: The actual value of the secret is defined either by option static-auth-secret, or can be found in the turn_secret table in the database. ---oauth Support oAuth authentication, as in the third-party TURN specs document. +--oauth Require oAuth authentication, as in the third-party TURN specs document. --dh566 Use 566 bits predefined DH TLS key. Default size of the key is 1066. diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 33235e01..cc533781 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -213,7 +213,7 @@ # #server-name=blackdow.carleon.gov -# Flag to support oAuth authentication. +# Flag to require oAuth authentication. # #oauth diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh index 42452008..e070dbd2 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh @@ -21,7 +21,6 @@ # 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 means that we support all OpenSSL ciphers -# 11) --oauth - accept oAuth security dialog # Other parameters (config file name, etc) are default. if [ -d examples ] ; then @@ -31,4 +30,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 --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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh index fa86b507..04834a0d 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh @@ -22,7 +22,6 @@ # 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 means that we support all OpenSSL ciphers -# 11) --oauth - accept oAuth security dialog # Other parameters (config file name, etc) are default. if [ -d examples ] ; then @@ -32,4 +31,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 --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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh index 2ad97f7b..52751b1f 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh @@ -23,7 +23,6 @@ # 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 means that we support all OpenSSL ciphers -# 11) --oauth - accept oAuth security dialog # Other parameters (config file name, etc) are default. if [ -d examples ] ; then @@ -33,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 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 $@ +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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh index 927bdf18..4e422294 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh @@ -22,7 +22,6 @@ # 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 means that we support all OpenSSL ciphers -# 11) --oauth - accept oAuth security dialog # Other parameters (config file name, etc) are default. if [ -d examples ] ; then @@ -32,7 +31,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 --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 $@ # 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 --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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh index db7db638..af5449ff 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh @@ -25,7 +25,6 @@ # 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 means that we support all OpenSSL ciphers -# 12) --oauth - accept oAuth security dialog # Other parameters (config file name, etc) are default. if [ -d examples ] ; then @@ -35,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 --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 $@ +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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh index 1bc1c775..f0866065 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh @@ -21,7 +21,6 @@ # 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 means that we support all OpenSSL ciphers -# 11) --oauth - accept oAuth security dialog # Other parameters (config file name, etc) are default. if [ -d examples ] ; then @@ -31,5 +30,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 --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 $@ diff --git a/examples/scripts/oauth/secure_relay_with_db_mongo.sh b/examples/scripts/oauth/secure_relay_with_db_mongo.sh new file mode 100755 index 00000000..59254acb --- /dev/null +++ b/examples/scripts/oauth/secure_relay_with_db_mongo.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure mode with MongoDB database for users +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) "-r north.gov" means "use authentication realm north.gov" +# 6) --mongo-userdb="mongodb://localhost/coturn" +# means that local MongoDB database "turn" will be used. +# 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 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 + cd examples +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 --oauth $@ diff --git a/examples/scripts/oauth/secure_relay_with_db_mysql.sh b/examples/scripts/oauth/secure_relay_with_db_mysql.sh new file mode 100755 index 00000000..44448dae --- /dev/null +++ b/examples/scripts/oauth/secure_relay_with_db_mysql.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure mode with MySQL database for users +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) "-r north.gov" means "use authentication realm north.gov" +# 6) --mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" +# means that local MySQL database "coturn" will be used, with database user "turn" and +# database user password "turn", and connection timeout 30 seconds. +# 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 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 + 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 --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 $@ diff --git a/examples/scripts/oauth/secure_relay_with_db_mysql_ssl.sh b/examples/scripts/oauth/secure_relay_with_db_mysql_ssl.sh new file mode 100755 index 00000000..5da6af48 --- /dev/null +++ b/examples/scripts/oauth/secure_relay_with_db_mysql_ssl.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure mode with SSL connection to a MySQL database for users +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) "-r north.gov" means "use authentication realm north.gov" +# 6) --mysql-userdb="host=localhost dbname=coturn user=turn password=turn cipher=DHE-RSA-AES256-SHA connect_timeout=30" +# means that local MySQL database "coturn" will be used, with database user "turn" and +# database user password "turn", and with SSL connection with cipher DHE-RSA-AES256-SHA, +# and connection timeout 30 seconds. +# 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 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 + 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 --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 $@ diff --git a/examples/scripts/oauth/secure_relay_with_db_psql.sh b/examples/scripts/oauth/secure_relay_with_db_psql.sh new file mode 100755 index 00000000..f65852fb --- /dev/null +++ b/examples/scripts/oauth/secure_relay_with_db_psql.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure mode with Postgres database for users +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) "-r north.gov" means "use authentication realm north.gov" +# 6) --psql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" +# means that local database "coturn" will be used, with database user "turn" and database user +# password "turn". +# 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 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 + 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 --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 --oauth $@ diff --git a/examples/scripts/oauth/secure_relay_with_db_redis.sh b/examples/scripts/oauth/secure_relay_with_db_redis.sh new file mode 100755 index 00000000..1de0d158 --- /dev/null +++ b/examples/scripts/oauth/secure_relay_with_db_redis.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure mode with Redis database for users +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) "-r north.gov" means "use authentication realm north.gov" +# 6) --redis-userdb="ip=127.0.0.1 dbname=2 password=turn connect_timeout=30" +# means that local Redis database 0 will be used, +# database password is "turn", and connection timeout 30 seconds. +# 7) --redis-statsdb="ip=127.0.0.1 dbname=3 password=turn connect_timeout=30" +# means that we want to use Redis for status and statistics information, +# and this will be the database number 3. +# 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 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 + 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 --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 $@ diff --git a/examples/scripts/oauth/secure_relay_with_db_sqlite.sh b/examples/scripts/oauth/secure_relay_with_db_sqlite.sh new file mode 100755 index 00000000..892df9c0 --- /dev/null +++ b/examples/scripts/oauth/secure_relay_with_db_sqlite.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# +# This is an example how to start a TURN Server in +# secure mode with SQLite database for users +# with the long-term credentials mechanism. +# +# We start here a TURN Server listening on IPv4 address +# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as +# IPv4 relay address, and we use ::1 as IPv6 relay address. +# +# 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) "-r north.gov" means "use authentication realm north.gov" +# 6) --db= +# means that local database will be used. +# 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 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 + 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 --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 $@ + diff --git a/examples/scripts/oauth/secure_udp_client.sh b/examples/scripts/oauth/secure_udp_client.sh new file mode 100755 index 00000000..76df4619 --- /dev/null +++ b/examples/scripts/oauth/secure_udp_client.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN UDP client +# with the long-term credentials 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) -u ninefingers means that if the server challenges the client with +# authentication challenge, then we use account "ninefingers". +# 11) -w youhavetoberealistic sets the password for the account as "youhavetoberealistic". +# 12) -s option is absent - it means that the client will be using +# the "channel" mechanism for data. +# 13) -J means that the client supports oAuth third-party authorization +# (with kid='north') +# 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 -u ninefingers -w youhavetoberealistic -J $@ ::1 + diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index a9e34f63..a5b34d3b 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "10 January 2015" "" "" +.TH TURN 1 "20 January 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 5e66b223..a809a709 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "10 January 2015" "" "" +.TH TURN 1 "20 January 2015" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -265,7 +265,7 @@ or can be found in the turn_secret table in the database. .TP .B \fB\-\-oauth\fP -Support oAuth authentication, as in the third\-party TURN specs document. +Require oAuth authentication, as in the third\-party TURN specs document. .TP .B \fB\-\-dh566\fP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index c5cd42bb..29cb1a9b 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "10 January 2015" "" "" +.TH TURN 1 "20 January 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 7dd1e65d..1eb9440f 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -492,7 +492,7 @@ static char Usage[] = "Usage: turnserver [options]\n" " --server-name Server name used for\n" " the oAuth authentication purposes.\n" " The default value is the realm name.\n" -" --oauth Support oAuth authentication.\n" +" --oauth Require oAuth authentication.\n" " -n Do not use configuration file, take all parameters from the command line only.\n" " --cert Certificate file, PEM format. Same file search rules\n" " applied as for the configuration file.\n" diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 821654f5..36117901 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -2871,7 +2871,8 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) if(turn_params.verbose) { if(nbh) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection input: %.40s\n", __FUNCTION__, (char*)ioa_network_buffer_data(nbh)); + ((char*)ioa_network_buffer_data(nbh))[ioa_network_buffer_get_size(nbh)] = 0; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection input: %s\n", __FUNCTION__, (char*)ioa_network_buffer_data(nbh)); } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection initial input\n", __FUNCTION__); } diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 57ac5291..c89eb80e 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -527,7 +527,7 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u } } - if(out_oauth && *out_oauth) { + if(in_oauth) { return ret; } From 94e536d94fc81a3df242d2130f625a979a66d249 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 20 Jan 2015 17:08:54 +0000 Subject: [PATCH 438/805] rpm adjusted --- rpm/turnserver.spec | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 95a884c9..fcf68a4c 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -235,6 +235,14 @@ fi %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_psql.sh %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_redis.sh %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh +%dir %{_datadir}/%{name}/scripts/oauth +%{_datadir}/%{name}/scripts/oauth/secure_relay_with_db_mysql.sh +%{_datadir}/%{name}/scripts/oauth/secure_relay_with_db_mysql_ssl.sh +%{_datadir}/%{name}/scripts/oauth/secure_relay_with_db_mongo.sh +%{_datadir}/%{name}/scripts/oauth/secure_relay_with_db_psql.sh +%{_datadir}/%{name}/scripts/oauth/secure_relay_with_db_redis.sh +%{_datadir}/%{name}/scripts/oauth/secure_relay_with_db_sqlite.sh +%{_datadir}/%{name}/scripts/oauth/secure_udp_client.sh %dir %{_datadir}/%{name}/scripts/restapi %{_datadir}/%{name}/scripts/restapi/secure_relay_secret.sh %{_datadir}/%{name}/scripts/restapi/secure_relay_secret_with_db_mysql.sh From 0551cfcc9ca0315e07fc99758cb545867832aecd Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 20 Jan 2015 17:59:31 +0000 Subject: [PATCH 439/805] better http/1.1 support --- src/apps/relay/http_server.c | 29 ++++++++++++++++++++++++++++- src/apps/relay/http_server.h | 3 +++ src/apps/relay/turn_admin_server.c | 28 +++++++++++++++++++++------- 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index 337dbd77..c189c908 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -35,6 +35,8 @@ #include #include +#include + ////////////////////////////////////// struct headers_list { @@ -62,7 +64,7 @@ static void write_http_echo(ioa_socket_handle s) char content_http[1025]; const char* title = "TURN Server"; snprintf(content_http,sizeof(content_http)-1,"\r\n\r\n \r\n %s\r\n \r\n \r\n %s
use https connection for the admin session\r\n \r\n\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(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); @@ -75,6 +77,28 @@ 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) @@ -177,6 +201,9 @@ struct http_request* parse_http_request(char* 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); diff --git a/src/apps/relay/http_server.h b/src/apps/relay/http_server.h index 422d7951..2acda156 100644 --- a/src/apps/relay/http_server.h +++ b/src/apps/relay/http_server.h @@ -47,6 +47,7 @@ extern "C" { enum _HTTP_REQUEST_TYPE { HRT_UNKNOWN=0, HRT_GET, + HRT_HEAD, HRT_POST, HRT_PUT, HRT_DELETE @@ -66,6 +67,8 @@ 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; diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 36117901..fb79fb81 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1485,7 +1485,9 @@ static void write_https_logon_page(ioa_socket_handle s) str_buffer_append(sb_http,"HTTP/1.1 200 OK\r\nServer: "); str_buffer_append(sb_http,TURN_SOFTWARE); - str_buffer_append(sb_http,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + str_buffer_append(sb_http,"\r\n"); + str_buffer_append(sb_http,get_http_date_header()); + str_buffer_append(sb_http,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); str_buffer_append_sz(sb_http,str_buffer_get_str_len(sb)); str_buffer_append(sb_http,"\r\n\r\n"); str_buffer_append(sb_http,str_buffer_get_str(sb)); @@ -1561,7 +1563,9 @@ static void write_https_home_page(ioa_socket_handle s) send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); - send_str_from_ioa_socket_tcp(s,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + send_str_from_ioa_socket_tcp(s,"\r\n"); + send_str_from_ioa_socket_tcp(s,get_http_date_header()); + send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); @@ -2026,7 +2030,9 @@ static void write_pc_page(ioa_socket_handle s) send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); - send_str_from_ioa_socket_tcp(s,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + send_str_from_ioa_socket_tcp(s,"\r\n"); + send_str_from_ioa_socket_tcp(s,get_http_date_header()); + send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); @@ -2275,7 +2281,9 @@ static void write_ps_page(ioa_socket_handle s, const char* client_protocol, cons send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); - send_str_from_ioa_socket_tcp(s,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + send_str_from_ioa_socket_tcp(s,"\r\n"); + send_str_from_ioa_socket_tcp(s,get_http_date_header()); + send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); @@ -2440,7 +2448,9 @@ static void write_users_page(ioa_socket_handle s, const u08bits *add_user, const send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); - send_str_from_ioa_socket_tcp(s,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + send_str_from_ioa_socket_tcp(s,"\r\n"); + send_str_from_ioa_socket_tcp(s,get_http_date_header()); + send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); @@ -2591,7 +2601,9 @@ static void write_shared_secrets_page(ioa_socket_handle s, const char* add_secre send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); - send_str_from_ioa_socket_tcp(s,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + send_str_from_ioa_socket_tcp(s,"\r\n"); + send_str_from_ioa_socket_tcp(s,get_http_date_header()); + send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); @@ -2741,7 +2753,9 @@ static void write_origins_page(ioa_socket_handle s, const char* add_origin, cons send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); - send_str_from_ioa_socket_tcp(s,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + send_str_from_ioa_socket_tcp(s,"\r\n"); + send_str_from_ioa_socket_tcp(s,get_http_date_header()); + send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); From 1258e1220da2d3c662318db1c5e1f127f12cf092 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 20 Jan 2015 19:38:43 +0000 Subject: [PATCH 440/805] minor changes --- ChangeLog | 1 - TODO | 15 +++------------ src/apps/relay/userdb.c | 2 +- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index fb886eee..208138e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,7 +6,6 @@ Version 4.4.1.1 'Ardee West': - OpenSSL 1.1.0 supported; - shared secrets fixed in MongoDB: multiple secrets per realm allowed; - shared secrets admin fixed in Redis; - - --oauth option now strictly requires oAuth authentication; 12/24/2014 Oleg Moskalenko Version 4.3.3.1 'Tolomei': diff --git a/TODO b/TODO index 49ef28c2..5fe9a166 100644 --- a/TODO +++ b/TODO @@ -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. ================================================================== diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index c89eb80e..57ac5291 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -527,7 +527,7 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u } } - if(in_oauth) { + if(out_oauth && *out_oauth) { return ret; } From e86bd85acb4a2d1bc2b766316cd2145baeeaa1cd Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 21 Jan 2015 06:38:23 +0000 Subject: [PATCH 441/805] oauth restored --- README.turnserver | 2 +- examples/etc/turnserver.conf | 2 +- .../secure_relay_with_db_mongo.sh | 3 +- .../secure_relay_with_db_mysql.sh | 3 +- .../secure_relay_with_db_mysql_ssl.sh | 3 +- .../secure_relay_with_db_psql.sh | 5 ++- .../secure_relay_with_db_redis.sh | 3 +- .../secure_relay_with_db_sqlite.sh | 3 +- .../oauth/secure_relay_with_db_mongo.sh | 34 ----------------- .../oauth/secure_relay_with_db_mysql.sh | 35 ----------------- .../oauth/secure_relay_with_db_mysql_ssl.sh | 36 ------------------ .../oauth/secure_relay_with_db_psql.sh | 38 ------------------- .../oauth/secure_relay_with_db_redis.sh | 38 ------------------- .../oauth/secure_relay_with_db_sqlite.sh | 35 ----------------- examples/scripts/oauth/secure_udp_client.sh | 34 ----------------- man/man1/turnserver.1 | 2 +- rpm/turnserver.spec | 8 ---- src/apps/relay/mainrelay.c | 2 +- 18 files changed, 17 insertions(+), 269 deletions(-) delete mode 100755 examples/scripts/oauth/secure_relay_with_db_mongo.sh delete mode 100755 examples/scripts/oauth/secure_relay_with_db_mysql.sh delete mode 100755 examples/scripts/oauth/secure_relay_with_db_mysql_ssl.sh delete mode 100755 examples/scripts/oauth/secure_relay_with_db_psql.sh delete mode 100755 examples/scripts/oauth/secure_relay_with_db_redis.sh delete mode 100755 examples/scripts/oauth/secure_relay_with_db_sqlite.sh delete mode 100755 examples/scripts/oauth/secure_udp_client.sh diff --git a/README.turnserver b/README.turnserver index 50b3be53..85087bb4 100644 --- a/README.turnserver +++ b/README.turnserver @@ -181,7 +181,7 @@ Flags: The actual value of the secret is defined either by option static-auth-secret, or can be found in the turn_secret table in the database. ---oauth Require oAuth authentication, as in the third-party TURN specs document. +--oauth Support oAuth authentication, as in the third-party TURN specs document. --dh566 Use 566 bits predefined DH TLS key. Default size of the key is 1066. diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index cc533781..e4209026 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -213,7 +213,7 @@ # #server-name=blackdow.carleon.gov -# Flag to require oAuth authentication. +# Flag that allows oAuth authentication. # #oauth diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh index e070dbd2..59254acb 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh @@ -21,6 +21,7 @@ # 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 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 @@ -30,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 $@ +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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh index 04834a0d..44448dae 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh @@ -22,6 +22,7 @@ # 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 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 +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 $@ +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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh index 52751b1f..5da6af48 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh @@ -23,6 +23,7 @@ # 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 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 +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 $@ +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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh index 4e422294..f65852fb 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_psql.sh @@ -22,6 +22,7 @@ # 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 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,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 $@ +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 $@ +# 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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh index af5449ff..1de0d158 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_redis.sh @@ -25,6 +25,7 @@ # 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 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 @@ -34,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 $@ +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 $@ diff --git a/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh b/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh index f0866065..892df9c0 100755 --- a/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh +++ b/examples/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh @@ -21,6 +21,7 @@ # 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 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 @@ -30,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 $@ +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 $@ diff --git a/examples/scripts/oauth/secure_relay_with_db_mongo.sh b/examples/scripts/oauth/secure_relay_with_db_mongo.sh deleted file mode 100755 index 59254acb..00000000 --- a/examples/scripts/oauth/secure_relay_with_db_mongo.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -# -# This is an example how to start a TURN Server in -# secure mode with MongoDB database for users -# with the long-term credentials mechanism. -# -# We start here a TURN Server listening on IPv4 address -# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as -# IPv4 relay address, and we use ::1 as IPv6 relay address. -# -# 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) "-r north.gov" means "use authentication realm north.gov" -# 6) --mongo-userdb="mongodb://localhost/coturn" -# means that local MongoDB database "turn" will be used. -# 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 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 - cd examples -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 --oauth $@ diff --git a/examples/scripts/oauth/secure_relay_with_db_mysql.sh b/examples/scripts/oauth/secure_relay_with_db_mysql.sh deleted file mode 100755 index 44448dae..00000000 --- a/examples/scripts/oauth/secure_relay_with_db_mysql.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh -# -# This is an example how to start a TURN Server in -# secure mode with MySQL database for users -# with the long-term credentials mechanism. -# -# We start here a TURN Server listening on IPv4 address -# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as -# IPv4 relay address, and we use ::1 as IPv6 relay address. -# -# 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) "-r north.gov" means "use authentication realm north.gov" -# 6) --mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" -# means that local MySQL database "coturn" will be used, with database user "turn" and -# database user password "turn", and connection timeout 30 seconds. -# 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 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 - 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 --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 $@ diff --git a/examples/scripts/oauth/secure_relay_with_db_mysql_ssl.sh b/examples/scripts/oauth/secure_relay_with_db_mysql_ssl.sh deleted file mode 100755 index 5da6af48..00000000 --- a/examples/scripts/oauth/secure_relay_with_db_mysql_ssl.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -# -# This is an example how to start a TURN Server in -# secure mode with SSL connection to a MySQL database for users -# with the long-term credentials mechanism. -# -# We start here a TURN Server listening on IPv4 address -# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as -# IPv4 relay address, and we use ::1 as IPv6 relay address. -# -# 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) "-r north.gov" means "use authentication realm north.gov" -# 6) --mysql-userdb="host=localhost dbname=coturn user=turn password=turn cipher=DHE-RSA-AES256-SHA connect_timeout=30" -# means that local MySQL database "coturn" will be used, with database user "turn" and -# database user password "turn", and with SSL connection with cipher DHE-RSA-AES256-SHA, -# and connection timeout 30 seconds. -# 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 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 - 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 --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 $@ diff --git a/examples/scripts/oauth/secure_relay_with_db_psql.sh b/examples/scripts/oauth/secure_relay_with_db_psql.sh deleted file mode 100755 index f65852fb..00000000 --- a/examples/scripts/oauth/secure_relay_with_db_psql.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh -# -# This is an example how to start a TURN Server in -# secure mode with Postgres database for users -# with the long-term credentials mechanism. -# -# We start here a TURN Server listening on IPv4 address -# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as -# IPv4 relay address, and we use ::1 as IPv6 relay address. -# -# 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) "-r north.gov" means "use authentication realm north.gov" -# 6) --psql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" -# means that local database "coturn" will be used, with database user "turn" and database user -# password "turn". -# 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 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 - 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 --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 --oauth $@ diff --git a/examples/scripts/oauth/secure_relay_with_db_redis.sh b/examples/scripts/oauth/secure_relay_with_db_redis.sh deleted file mode 100755 index 1de0d158..00000000 --- a/examples/scripts/oauth/secure_relay_with_db_redis.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh -# -# This is an example how to start a TURN Server in -# secure mode with Redis database for users -# with the long-term credentials mechanism. -# -# We start here a TURN Server listening on IPv4 address -# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as -# IPv4 relay address, and we use ::1 as IPv6 relay address. -# -# 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) "-r north.gov" means "use authentication realm north.gov" -# 6) --redis-userdb="ip=127.0.0.1 dbname=2 password=turn connect_timeout=30" -# means that local Redis database 0 will be used, -# database password is "turn", and connection timeout 30 seconds. -# 7) --redis-statsdb="ip=127.0.0.1 dbname=3 password=turn connect_timeout=30" -# means that we want to use Redis for status and statistics information, -# and this will be the database number 3. -# 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 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 - 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 --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 $@ diff --git a/examples/scripts/oauth/secure_relay_with_db_sqlite.sh b/examples/scripts/oauth/secure_relay_with_db_sqlite.sh deleted file mode 100755 index 892df9c0..00000000 --- a/examples/scripts/oauth/secure_relay_with_db_sqlite.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh -# -# This is an example how to start a TURN Server in -# secure mode with SQLite database for users -# with the long-term credentials mechanism. -# -# We start here a TURN Server listening on IPv4 address -# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as -# IPv4 relay address, and we use ::1 as IPv6 relay address. -# -# 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) "-r north.gov" means "use authentication realm north.gov" -# 6) --db= -# means that local database will be used. -# 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 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 - 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 --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 $@ - diff --git a/examples/scripts/oauth/secure_udp_client.sh b/examples/scripts/oauth/secure_udp_client.sh deleted file mode 100755 index 76df4619..00000000 --- a/examples/scripts/oauth/secure_udp_client.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -# -# This is an example of a script to run a "secure" TURN UDP client -# with the long-term credentials 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) -u ninefingers means that if the server challenges the client with -# authentication challenge, then we use account "ninefingers". -# 11) -w youhavetoberealistic sets the password for the account as "youhavetoberealistic". -# 12) -s option is absent - it means that the client will be using -# the "channel" mechanism for data. -# 13) -J means that the client supports oAuth third-party authorization -# (with kid='north') -# 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 -u ninefingers -w youhavetoberealistic -J $@ ::1 - diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index a809a709..51c4d857 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -265,7 +265,7 @@ or can be found in the turn_secret table in the database. .TP .B \fB\-\-oauth\fP -Require oAuth authentication, as in the third\-party TURN specs document. +Support oAuth authentication, as in the third\-party TURN specs document. .TP .B \fB\-\-dh566\fP diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index fcf68a4c..95a884c9 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -235,14 +235,6 @@ fi %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_psql.sh %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_redis.sh %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_sqlite.sh -%dir %{_datadir}/%{name}/scripts/oauth -%{_datadir}/%{name}/scripts/oauth/secure_relay_with_db_mysql.sh -%{_datadir}/%{name}/scripts/oauth/secure_relay_with_db_mysql_ssl.sh -%{_datadir}/%{name}/scripts/oauth/secure_relay_with_db_mongo.sh -%{_datadir}/%{name}/scripts/oauth/secure_relay_with_db_psql.sh -%{_datadir}/%{name}/scripts/oauth/secure_relay_with_db_redis.sh -%{_datadir}/%{name}/scripts/oauth/secure_relay_with_db_sqlite.sh -%{_datadir}/%{name}/scripts/oauth/secure_udp_client.sh %dir %{_datadir}/%{name}/scripts/restapi %{_datadir}/%{name}/scripts/restapi/secure_relay_secret.sh %{_datadir}/%{name}/scripts/restapi/secure_relay_secret_with_db_mysql.sh diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 1eb9440f..7dd1e65d 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -492,7 +492,7 @@ static char Usage[] = "Usage: turnserver [options]\n" " --server-name Server name used for\n" " the oAuth authentication purposes.\n" " The default value is the realm name.\n" -" --oauth Require oAuth authentication.\n" +" --oauth Support oAuth authentication.\n" " -n Do not use configuration file, take all parameters from the command line only.\n" " --cert Certificate file, PEM format. Same file search rules\n" " applied as for the configuration file.\n" From 59389529f51d019ea17373899affd1fa14fec4b0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 21 Jan 2015 06:57:44 +0000 Subject: [PATCH 442/805] cosmetics --- src/apps/relay/turn_admin_server.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index fb79fb81..b8ba215e 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1808,7 +1808,7 @@ static void write_pc_page(ioa_socket_handle s) str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,home_link); str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,"Configuration Parameters:
\r\n"); + str_buffer_append(sb,"Configuration Parameters:

\r\n"); str_buffer_append(sb,"\r\n"); { @@ -2266,7 +2266,7 @@ static void write_ps_page(ioa_socket_handle s, const char* client_protocol, cons str_buffer_append(sb,"\r\n"); str_buffer_append(sb,"\r\n"); - str_buffer_append(sb,"TURN Sessions:
ParameterValue
\r\n"); + str_buffer_append(sb,"
TURN Sessions:

\r\n"); str_buffer_append(sb,"\r\n"); size_t total_sz = https_print_sessions(sb,client_protocol,user_pattern,max_sessions,cs); @@ -2420,14 +2420,19 @@ static void write_users_page(ioa_socket_handle s, const u08bits *add_user, const str_buffer_append(sb,"\" value=\""); str_buffer_append(sb,""); str_buffer_append(sb,"\""); - str_buffer_append(sb,">
\r\n"); + str_buffer_append(sb,">

\r\n"); + + if(turn_params.shatype == SHATYPE_SHA256) + str_buffer_append(sb,"SHA type: SHA256
\r\n"); + else + str_buffer_append(sb,"SHA type: SHA1
\r\n"); str_buffer_append(sb,"
"); str_buffer_append(sb,"\r\n"); str_buffer_append(sb,"\r\n"); - str_buffer_append(sb,"Users:
\r\n"); + str_buffer_append(sb,"
Users:

\r\n"); str_buffer_append(sb,"
NSession IDUserRealmOriginAge, secsExpires, secsClient protocolRelay protocolClient addrServer addrRelay addr (IPv4)Relay addr (IPv6)FingerprintsMobileTLS methodTLS cipherBPS (allocated)PacketsRatePeers
\r\n"); str_buffer_append(sb,""); if(!current_socket->as_eff_realm[0]) { @@ -2580,7 +2585,7 @@ static void write_shared_secrets_page(ioa_socket_handle s, const char* add_secre str_buffer_append(sb,"\r\n"); str_buffer_append(sb,"\r\n"); - str_buffer_append(sb,"Secrets:
\r\n"); + str_buffer_append(sb,"
Shared secrets:

\r\n"); str_buffer_append(sb,"
NName
\r\n"); str_buffer_append(sb,""); if(!current_socket->as_eff_realm[0]) { @@ -2730,7 +2735,7 @@ static void write_origins_page(ioa_socket_handle s, const char* add_origin, cons str_buffer_append(sb,"\r\n"); } - str_buffer_append(sb,"Origins:
\r\n"); + str_buffer_append(sb,"
Origins:

\r\n"); str_buffer_append(sb,"
NValue
\r\n"); str_buffer_append(sb,""); if(!current_socket->as_eff_realm[0]) { @@ -3019,9 +3024,9 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) STRCPY(u,add_user); STRCPY(r,add_realm); STRCPY(p,pwd); - stun_produce_integrity_key_str(u, r, p, key, SHATYPE_DEFAULT); + stun_produce_integrity_key_str(u, r, p, key, turn_params.shatype); size_t i = 0; - size_t sz = get_hmackey_size(SHATYPE_DEFAULT); + size_t sz = get_hmackey_size(turn_params.shatype); int maxsz = (int) (sz * 2) + 1; char *s = skey; for (i = 0; (i < sz) && (maxsz > 2); i++) { From 49c88a557676e577b0e8dee563e2d0100296b0c2 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 21 Jan 2015 18:43:47 +0000 Subject: [PATCH 443/805] start working on oauth --- src/apps/relay/dbdrivers/dbd_sqlite.c | 2 +- src/apps/relay/turn_admin_server.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index f5f2c6d6..e4ea4d09 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -447,7 +447,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); diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index b8ba215e..4b54ae6f 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1363,6 +1363,7 @@ enum _AS_FORM { AS_FORM_USERS, AS_FORM_SS, AS_FORM_OS, + AS_FORM_OAUTH, AS_FORM_UNKNOWN }; @@ -1408,6 +1409,7 @@ static struct form_name form_names[] = { {AS_FORM_USERS,"/us"}, {AS_FORM_SS,"/ss"}, {AS_FORM_OS,"/os"}, + {AS_FORM_OAUTH,"/oauth"}, {AS_FORM_UNKNOWN,NULL} }; @@ -1556,6 +1558,10 @@ static void write_https_home_page(ioa_socket_handle s) str_buffer_append(sb,form_names[AS_FORM_OS].name); str_buffer_append(sb,"\">"); + str_buffer_append(sb,"
"); + str_buffer_append(sb,"\r\n"); str_buffer_append(sb,"\r\n"); @@ -3190,6 +3196,15 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } break; } + case AS_FORM_OAUTH: { + if(s->as_ok) { + //TODO + write_https_home_page(s); + } else { + write_https_logon_page(s); + } + break; + } case AS_FORM_TOGGLE: if(s->as_ok) { handle_toggle_request(s,hr); From aefe2608d0691a2a939567192aa167af3a9e19cd Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 22 Jan 2015 10:03:40 +0000 Subject: [PATCH 444/805] oauth keys page --- INSTALL | 2 +- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/dbdrivers/dbd_mongo.c | 15 +- src/apps/relay/dbdrivers/dbd_mysql.c | 22 +- src/apps/relay/dbdrivers/dbd_pgsql.c | 14 +- src/apps/relay/dbdrivers/dbd_redis.c | 15 +- src/apps/relay/dbdrivers/dbd_sqlite.c | 17 +- src/apps/relay/dbdrivers/dbdriver.h | 2 +- src/apps/relay/http_server.c | 9 +- src/apps/relay/turn_admin_server.c | 312 +++++++++++++++++++++++++- src/apps/relay/userdb.c | 6 +- 11 files changed, 382 insertions(+), 32 deletions(-) diff --git a/INSTALL b/INSTALL index 3e9873ff..990dfbbb 100644 --- a/INSTALL +++ b/INSTALL @@ -757,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. diff --git a/examples/var/db/turndb b/examples/var/db/turndb index 8026af81d2843e4a1669b0916521d8352746dfe5..52b1258006a96f90e061d27631871022be8c1354 100644 GIT binary patch delta 58 zcmV-A0LA}+umOOu0gxL3Ympp70c){ftV03=PO*VM0|i3>002Lcfjg6pM}GnX;j;k@ Q(F2kc1OfmEv*k-03>}LRj{pDw delta 38 tcmZqJz}T>Xae_2s@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); + } 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; diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index a536bdac..4d71be21 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -402,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) { oauth_key_data_raw key_; oauth_key_data_raw *key=&key_; @@ -457,9 +457,16 @@ 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); + } 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); } @@ -496,8 +503,9 @@ static int mysql_set_user_key(u08bits *usname, u08bits *realm, const char *key) 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) { @@ -511,10 +519,14 @@ 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)); + } else { + ret = 0; } + } else { + ret = 0; } } - return ret; + return ret; } static int mysql_del_user(u08bits *usname, u08bits *realm) { diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index 6b99e2a6..873c47e5 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -187,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) { oauth_key_data_raw key_; oauth_key_data_raw *key=&key_; @@ -217,9 +217,16 @@ static int pgsql_list_oauth_keys(void) { STRCPY((char*)key->auth_key,PQgetvalue(res,i,7)); STRCPY((char*)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); + } 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; } @@ -283,7 +290,10 @@ static int pgsql_set_oauth_key(oauth_key_data_raw *key) { } else { ret = 0; } + } else { + ret = 0; } + if(res) { PQclear(res); } diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index de1bf28c..49befeea 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -637,7 +637,7 @@ static int redis_list_users(u08bits *realm, secrets_list_t *users, secrets_list_ 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) { int ret = -1; redisContext *rc = get_redis_connection(); secrets_list_t keys; @@ -673,9 +673,16 @@ 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); + } 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); + } } } diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index e4ea4d09..f2ac8443 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -329,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) { oauth_key_data_raw key_; oauth_key_data_raw *key=&key_; @@ -363,11 +363,18 @@ static int sqlite_list_oauth_keys(void) { 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((char*)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); + } 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; diff --git a/src/apps/relay/dbdrivers/dbdriver.h b/src/apps/relay/dbdrivers/dbdriver.h index 7cfd3b01..8776a3a2 100644 --- a/src/apps/relay/dbdrivers/dbdriver.h +++ b/src/apps/relay/dbdrivers/dbdriver.h @@ -68,7 +68,7 @@ typedef struct _turn_dbdriver_t { int (*set_oauth_key)(oauth_key_data_raw *key); int (*get_oauth_key)(const u08bits *kid, oauth_key_data_raw *key); int (*del_oauth_key)(const u08bits *kid); - int (*list_oauth_keys)(void); + int (*list_oauth_keys)(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas); int (*get_admin_user)(const u08bits *usname, u08bits *realm, password_t pwd); int (*set_admin_user)(const u08bits *usname, const u08bits *realm, const password_t pwd); int (*del_admin_user)(const u08bits *usname); diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index c189c908..39c98345 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -117,7 +117,7 @@ static struct headers_list * post_parse(char *data, size_t data_len) value = value ? value : ""; value = evhttp_decode_uri(value); char *p = value; - while (*p != '\0') { + while (*p) { if (*p == '+') *p = ' '; p++; @@ -135,6 +135,7 @@ static struct headers_list * post_parse(char *data, size_t data_len) 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/"); @@ -266,7 +267,7 @@ static void free_headers_list(struct headers_list *h) { } const char *get_http_header_value(const struct http_request *request, const char* key, const char* default_value) { - const char *ret = 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); @@ -274,7 +275,9 @@ const char *get_http_header_value(const struct http_request *request, const char if(!ret && request->headers->post_headers) { ret = get_headers_list_value(request->headers->post_headers,key); } - if(!ret) ret = default_value; + } + if(!ret) { + ret = default_value; } return ret; } diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 4b54ae6f..226cf8b6 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1392,6 +1392,12 @@ typedef enum _AS_FORM AS_FORM; #define HR_ADD_IP_REALM "aipr" #define HR_ADD_IP_KIND "aipk" #define HR_UPDATE_PARAMETER "togglepar" +#define HR_ADD_OAUTH_KID "oauth_kid" +#define HR_ADD_OAUTH_IKM "oauth_ikm" +#define HR_ADD_OAUTH_HKDF "oauth_hkdf" +#define HR_ADD_OAUTH_TEA "oauth_tea" +#define HR_ADD_OAUTH_AA "oauth_aa" +#define HR_DELETE_OAUTH_KID "oauth_kid_del" struct form_name { AS_FORM form; @@ -1558,9 +1564,11 @@ static void write_https_home_page(ioa_socket_handle s) str_buffer_append(sb,form_names[AS_FORM_OS].name); str_buffer_append(sb,"\">"); - str_buffer_append(sb,"
"); + if(is_superuser()) { + str_buffer_append(sb,"
"); + } str_buffer_append(sb,"\r\n"); str_buffer_append(sb,"\r\n"); @@ -2778,6 +2786,246 @@ static void write_origins_page(ioa_socket_handle s, const char* add_origin, cons } } +static size_t https_print_oauth_keys(struct str_buffer* sb) +{ + size_t ret = 0; + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->list_oauth_keys) { + secrets_list_t kids,hkdfs,teas,aas; + init_secrets_list(&kids); + init_secrets_list(&hkdfs); + init_secrets_list(&teas); + init_secrets_list(&aas); + dbd->list_oauth_keys(&kids,&hkdfs,&teas,&aas); + + size_t sz = get_secrets_list_size(&kids); + size_t i; + for(i=0;i
"); + str_buffer_append(sb,""); + str_buffer_append(sb,""); + str_buffer_append(sb,""); + str_buffer_append(sb,""); + + { + str_buffer_append(sb,""); + } + str_buffer_append(sb,""); + ++ret; + } + + clean_secrets_list(&kids); + clean_secrets_list(&hkdfs); + clean_secrets_list(&teas); + clean_secrets_list(&aas); + } + + return ret; +} + +static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, const char* add_ikm, + const char* add_hkdf_hash_func, const char* add_tea, const char* add_aa, + const char* msg) +{ + if(s && !ioa_socket_tobeclosed(s)) { + + if(!(s->as_ok)) { + write_https_logon_page(s); + } else if(!is_superuser()) { + write_https_home_page(s); + } else { + + struct str_buffer* sb = str_buffer_new(); + + str_buffer_append(sb,"\r\n\r\n \r\n "); + str_buffer_append(sb,admin_title); + str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,bold_admin_title); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,home_link); + str_buffer_append(sb,"
\r\n"); + + { + str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,"
oAuth key:\r\n"); + + if(msg && msg[0]) { + str_buffer_append(sb,"
NValue"); + str_buffer_append_sz(sb,i+1); + str_buffer_append(sb,""); + str_buffer_append(sb,get_secrets_list_elem(&kids,i)); + str_buffer_append(sb,""); + str_buffer_append(sb,get_secrets_list_elem(&hkdfs,i)); + str_buffer_append(sb,""); + str_buffer_append(sb,get_secrets_list_elem(&teas,i)); + str_buffer_append(sb,""); + str_buffer_append(sb,get_secrets_list_elem(&aas,i)); + str_buffer_append(sb," delete"); + str_buffer_append(sb,"
"); + str_buffer_append(sb,msg); + str_buffer_append(sb,"

"); + } + + { + if(!add_kid) add_kid=""; + + str_buffer_append(sb,"
KID:
\r\n"); + } + { + if(!add_ikm) add_ikm = ""; + + str_buffer_append(sb,"
Base64-encoded input keying material:
\r\n"); + } + { + str_buffer_append(sb,">
Hash key derivation function:
\r\n"); + + if(!add_hkdf_hash_func || !add_hkdf_hash_func[0]) + add_hkdf_hash_func = "SHA-256"; + + str_buffer_append(sb,"SHA-1\r\n
\r\n"); + + str_buffer_append(sb,"SHA-256\r\n
\r\n"); + } + { + str_buffer_append(sb,">
Token encryption algorithm:
\r\n"); + + if(!add_tea || !add_tea[0]) + add_tea = "AES-256-CBC"; + + str_buffer_append(sb,"AES-128-CBC\r\n
\r\n"); + + str_buffer_append(sb,"AES-256-CBC\r\n
\r\n"); + + str_buffer_append(sb,"AEAD-AES-128-GCM\r\n
\r\n"); + + str_buffer_append(sb,"AEAD-AES-256-GCM\r\n
\r\n"); + } + { + str_buffer_append(sb,">
Token authentication algorithm:
\r\n"); + + if(!add_aa || !add_aa[0]) + add_aa = "HMAC-SHA-256-128"; + + str_buffer_append(sb,"HMAC-SHA-256-128\r\n
\r\n"); + + str_buffer_append(sb,"HMAC-SHA-256\r\n
\r\n"); + + str_buffer_append(sb,"HMAC-SHA-1\r\n
\r\n"); + } + + str_buffer_append(sb,"
"); + + str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,"\r\n"); + } + + str_buffer_append(sb,"
OAuth keys:

\r\n"); + str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,""); + str_buffer_append(sb,""); + str_buffer_append(sb,""); + str_buffer_append(sb,""); + str_buffer_append(sb,""); + str_buffer_append(sb,"\r\n"); + + size_t total_sz = https_print_oauth_keys(sb); + + str_buffer_append(sb,"\r\n
NKIDHash key derivation functionToken encryption algorithmToken authentication algorithm
\r\n"); + + str_buffer_append(sb,"
Total oAuth keys = "); + str_buffer_append_sz(sb,total_sz); + str_buffer_append(sb,"
\r\n"); + + str_buffer_append(sb,"\r\n\r\n"); + + send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); + send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); + send_str_from_ioa_socket_tcp(s,"\r\n"); + send_str_from_ioa_socket_tcp(s,get_http_date_header()); + send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); + + send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); + + send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); + send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); + + str_buffer_free(sb); + } + } +} + static void handle_toggle_request(ioa_socket_handle s, struct http_request* hr) { if(s && hr) { @@ -3197,11 +3445,63 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) break; } case AS_FORM_OAUTH: { - if(s->as_ok) { - //TODO + if(!s->as_ok) { + write_https_logon_page(s); + } else if(!is_superuser()) { write_https_home_page(s); } else { - write_https_logon_page(s); + + { + const char* del_kid = get_http_header_value(hr,HR_DELETE_OAUTH_KID,""); + if(del_kid[0]) { + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->del_oauth_key) { + (*dbd->del_oauth_key)((const u08bits*)del_kid); + } + } + } + + const char* add_kid = ""; + const char* add_ikm = ""; + const char* add_hkdf_hash_func = ""; + const char* add_tea = ""; + const char* add_aa = ""; + const char* msg = ""; + + add_kid = get_http_header_value(hr,HR_ADD_OAUTH_KID,""); + if(add_kid[0]) { + add_ikm = get_http_header_value(hr,HR_ADD_OAUTH_IKM,""); + if(add_ikm[0]) { + add_hkdf_hash_func = get_http_header_value(hr,HR_ADD_OAUTH_HKDF,""); + add_tea = get_http_header_value(hr,HR_ADD_OAUTH_TEA,""); + add_aa = get_http_header_value(hr,HR_ADD_OAUTH_AA,""); + + oauth_key_data_raw key; + ns_bzero(&key,sizeof(key)); + STRCPY(key.kid,add_kid); + STRCPY(key.ikm_key,add_ikm); + STRCPY(key.hkdf_hash_func,add_hkdf_hash_func); + STRCPY(key.as_rs_alg,add_tea); + STRCPY(key.auth_alg,add_aa); + + if(strstr(key.as_rs_alg,"AEAD")) key.auth_alg[0]=0; + + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->set_oauth_key) { + if((*dbd->set_oauth_key)(&key)<0) { + msg = "Cannot insert oAuth key into the database"; + } else { + add_kid = ""; + add_ikm = ""; + add_hkdf_hash_func = ""; + add_tea = ""; + add_aa = ""; + } + } + } + } + + write_https_oauth_page(s,add_kid,add_ikm,add_hkdf_hash_func,add_tea,add_aa,msg); } break; } diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 57ac5291..5ab3d6c9 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -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) { From dede8a10fc850d5f8f95851c245d02a23f1b1e18 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 22 Jan 2015 10:08:16 +0000 Subject: [PATCH 445/805] ikm field fix --- src/apps/relay/turn_admin_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 226cf8b6..33cca404 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -2891,7 +2891,7 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,HR_ADD_OAUTH_IKM); str_buffer_append(sb,"\" value=\""); str_buffer_append(sb,(const char*)add_ikm); - str_buffer_append(sb,"\""); + str_buffer_append(sb,"\" maxlength=256 size=48 "); str_buffer_append(sb,">
\r\n"); } { From 71bfa10ba5b7b815e73f36185329e19cab7c59e6 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 22 Jan 2015 10:18:44 +0000 Subject: [PATCH 446/805] required fields --- src/apps/relay/turn_admin_server.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 33cca404..728c9c24 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1481,9 +1481,9 @@ static void write_https_logon_page(ioa_socket_handle s) str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,"
Admin user information: user name:
Admin user information: user name:

password:

password:


\r\n"); str_buffer_append(sb,"
\r\n"); @@ -1734,7 +1734,7 @@ static void https_print_ip_range_list(struct str_buffer* sb, ip_range_list_t *va if(dynamic) { sbprintf(sb," %s",name); - sbprintf(sb,"
IP range:",form_names[AS_FORM_UPDATE].name,HR_ADD_IP_KIND,kind,HR_ADD_IP); + sbprintf(sb,"IP range:",form_names[AS_FORM_UPDATE].name,HR_ADD_IP_KIND,kind,HR_ADD_IP); sbprintf(sb,"Realm: as_eff_realm); if(!is_superuser()) { sbprintf(sb," disabled "); @@ -2415,21 +2415,21 @@ static void write_users_page(ioa_socket_handle s, const u08bits *add_user, const } str_buffer_append(sb,">
\r\n"); - str_buffer_append(sb,"
User name: User name:
\r\n"); - str_buffer_append(sb,"
Password: Password:
\r\n"); - str_buffer_append(sb,"
Confirm password: Confirm password:
\r\n"); - str_buffer_append(sb,"
Secret: Secret:
"); } - str_buffer_append(sb,"
Realm name: Realm name:
\r\n"); - str_buffer_append(sb,"
Origin: Origin: KID: KID:
\r\n"); } { if(!add_ikm) add_ikm = ""; - str_buffer_append(sb,"
Base64-encoded input keying material: Base64-encoded input keying material:
\r\n"); } { From e95d9736aa6f73623a665482c5785cb13160cc78 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 22 Jan 2015 23:19:42 +0000 Subject: [PATCH 447/805] fixes --- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/ns_ioalib_engine_impl.c | 20 +++ src/apps/relay/ns_ioalib_impl.h | 9 +- src/apps/relay/turn_admin_server.c | 222 +++++++++++++++---------- src/apps/relay/turn_admin_server.h | 10 ++ 5 files changed, 165 insertions(+), 96 deletions(-) diff --git a/examples/var/db/turndb b/examples/var/db/turndb index 52b1258006a96f90e061d27631871022be8c1354..3b0da293efbb7a65b15012fac831f6ed8a92a848 100644 GIT binary patch delta 194 zcmZqJz}T>Xae_2s;Y1l{)Xae_2s_Cy(H)@%mdM`{~W)(SH&+|0-`iFuL;%jAjbqLcTEhcM0siu5sa x^D)4|=GD?k8jOA$8||4{oq?kE6C153_qsPQJ_IVg2-3{PzyVUd`K7lw4**(o9AN+e diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index f4dd6a1c..c6a12342 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1659,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); @@ -2599,6 +2605,12 @@ 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); @@ -2612,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; @@ -2778,6 +2791,12 @@ 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); @@ -2793,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; diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 04bd9c42..7bdee61a 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -66,8 +66,6 @@ extern "C" { #define MAX_BUFFER_QUEUE_SIZE_PER_ENGINE (64) #define MAX_SOCKET_BUFFER_BACKLOG (16) -#define ADMIN_USER_MAX_LENGTH (32) - #define BUFFEREVENT_HIGH_WATERMARK (128<<10) #define BUFFEREVENT_MAX_UDP_TO_TCP_WRITE (64<<9) #define BUFFEREVENT_MAX_TCP_TO_TCP_WRITE (192<<10) @@ -225,11 +223,8 @@ struct _ioa_socket accept_cb acb; void *acbarg; /* <<== RFC 6062 */ - //Admin server: - 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]; + void *special_session; + size_t special_session_size; }; typedef struct _timer_event diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 728c9c24..cedfd492 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1437,8 +1437,45 @@ static int wrong_html_name(const char* s) return ret; } +static int is_as_ok(ioa_socket_handle s) { + return (s && s->special_session && + ((struct admin_session*)s->special_session)->as_ok); +} + static int is_superuser(void) { - return !(current_socket->as_realm[0]); + return (is_as_ok(current_socket) && + (!((struct admin_session*)current_socket->special_session)->as_realm[0])); +} + +static char* current_realm(void) { + if(current_socket && current_socket->special_session && ((struct admin_session*)current_socket->special_session)->as_ok) { + return ((struct admin_session*)current_socket->special_session)->as_realm; + } else { + static char bad_realm[1025] = "_ERROR:UNKNOWN_REALM__"; + return bad_realm; + } +} + +static char* current_eff_realm(void) { + if(current_socket && current_socket->special_session && ((struct admin_session*)current_socket->special_session)->as_ok) { + return ((struct admin_session*)current_socket->special_session)->as_eff_realm; + } else { + static char bad_eff_realm[1025] = "_ERROR:UNKNOWN_REALM__"; + return bad_eff_realm; + } +} + +static size_t current_max_output_sessions(void) { + if(current_socket && current_socket->special_session && ((struct admin_session*)current_socket->special_session)->as_ok) { + return ((struct admin_session*)current_socket->special_session)->number_of_user_sessions; + } + return DEFAULT_CLI_MAX_OUTPUT_SESSIONS; +} + +static void set_current_max_output_sessions(size_t value) { + if(current_socket && current_socket->special_session && ((struct admin_session*)current_socket->special_session)->as_ok) { + ((struct admin_session*)current_socket->special_session)->number_of_user_sessions = value; + } } static void https_cancel_session(const char* ssid) @@ -1449,12 +1486,6 @@ static void https_cancel_session(const char* ssid) } } -static char* get_eff_realm(void) { - if(current_socket->as_realm[0]) - return current_socket->as_realm; - return current_socket->as_eff_realm; -} - static AS_FORM get_form(const char* path) { if(path) { size_t i = 0; @@ -1512,7 +1543,7 @@ static void write_https_home_page(ioa_socket_handle s) { if(s && !ioa_socket_tobeclosed(s)) { - if(!(s->as_ok)) { + if(!is_as_ok(s)) { write_https_logon_page(s); } else { @@ -1533,7 +1564,7 @@ static void write_https_home_page(ioa_socket_handle s) str_buffer_append(sb," Realm name: "); str_buffer_append(sb,"
as_realm[0] && strcmp(current_socket->as_realm,realm)) { + if(current_realm()[0] && strcmp(current_realm(),realm)) { //delete forbidden } else { char *eip = evhttp_encode_uri(ip); @@ -1721,7 +1752,7 @@ static void https_print_ip_range_list(struct str_buffer* sb, ip_range_list_t *va char buffer[1025]; for(i=0;iranges_number;++i) { if(value->rs[i].realm[0]) { - if(get_eff_realm()[0] && strcmp(get_eff_realm(),value->rs[i].realm)) { + if(current_eff_realm()[0] && strcmp(current_eff_realm(),value->rs[i].realm)) { continue; } else { sbprintf(sb," %s %s [%s] %s\r\n",name,value->rs[i].str,value->rs[i].realm, change_ip_addr_html(dynamic,kind,value->rs[i].str,value->rs[i].realm,buffer,sizeof(buffer))); @@ -1735,7 +1766,7 @@ static void https_print_ip_range_list(struct str_buffer* sb, ip_range_list_t *va if(dynamic) { sbprintf(sb," %s",name); sbprintf(sb,"IP range:",form_names[AS_FORM_UPDATE].name,HR_ADD_IP_KIND,kind,HR_ADD_IP); - sbprintf(sb,"Realm: as_eff_realm); + sbprintf(sb,"Realm: as_ok)) { + if(!is_as_ok(s)) { write_https_logon_page(s); } else { @@ -2018,7 +2049,7 @@ static void write_pc_page(ioa_socket_handle s) https_print_str(sb,rn,"Default realm",0); } - realm_params_t *rp = get_realm(get_eff_realm()); + realm_params_t *rp = get_realm(current_eff_realm()); if(!rp) rp = get_realm(NULL); https_print_str(sb,rp->options.name,"Admin session (current) realm",0); @@ -2075,7 +2106,7 @@ static int https_print_session(ur_map_key_type key, ur_map_value_type value, voi struct str_buffer* sb = csarg->sb; struct turn_session_info *tsi = (struct turn_session_info *)value; - if(get_eff_realm()[0] && strcmp(get_eff_realm(),tsi->realm)) + if(current_eff_realm()[0] && strcmp(current_eff_realm(),tsi->realm)) return 0; if(csarg->user_pattern[0]) { @@ -2225,7 +2256,7 @@ static void write_ps_page(ioa_socket_handle s, const char* client_protocol, cons { if(s && !ioa_socket_tobeclosed(s)) { - if(!(s->as_ok)) { + if(!is_as_ok(s)) { write_https_logon_page(s); } else { @@ -2247,7 +2278,7 @@ static void write_ps_page(ioa_socket_handle s, const char* client_protocol, cons str_buffer_append(sb,"
Realm name: list_users((u08bits*)current_socket->as_eff_realm,&users,&realms); + dbd->list_users((u08bits*)current_eff_realm(),&users,&realms); size_t sz = get_secrets_list_size(&users); size_t i; @@ -2328,7 +2359,7 @@ static size_t https_print_users(struct str_buffer* sb) str_buffer_append(sb,""); str_buffer_append(sb,get_secrets_list_elem(&users,i)); str_buffer_append(sb,""); - if(!current_socket->as_eff_realm[0]) { + if(!current_eff_realm()[0]) { str_buffer_append(sb,""); str_buffer_append(sb,get_secrets_list_elem(&realms,i)); str_buffer_append(sb,""); @@ -2360,7 +2391,7 @@ static void write_users_page(ioa_socket_handle s, const u08bits *add_user, const { if(s && !ioa_socket_tobeclosed(s)) { - if(!(s->as_ok)) { + if(!is_as_ok(s)) { write_https_logon_page(s); } else { @@ -2382,7 +2413,7 @@ static void write_users_page(ioa_socket_handle s, const u08bits *add_user, const str_buffer_append(sb,"
Realm name: Users:

\r\n"); str_buffer_append(sb,"\r\n"); str_buffer_append(sb,""); - if(!current_socket->as_eff_realm[0]) { + if(!current_eff_realm()[0]) { str_buffer_append(sb,""); } str_buffer_append(sb,""); @@ -2489,7 +2520,7 @@ static size_t https_print_secrets(struct str_buffer* sb) secrets_list_t secrets,realms; init_secrets_list(&secrets); init_secrets_list(&realms); - dbd->list_secrets((u08bits*)current_socket->as_eff_realm,&secrets,&realms); + dbd->list_secrets((u08bits*)current_eff_realm(),&secrets,&realms); size_t sz = get_secrets_list_size(&secrets); size_t i; @@ -2500,7 +2531,7 @@ static size_t https_print_secrets(struct str_buffer* sb) str_buffer_append(sb,""); - if(!current_socket->as_eff_realm[0]) { + if(!current_eff_realm()[0]) { str_buffer_append(sb,""); @@ -2532,7 +2563,7 @@ static void write_shared_secrets_page(ioa_socket_handle s, const char* add_secre { if(s && !ioa_socket_tobeclosed(s)) { - if(!(s->as_ok)) { + if(!is_as_ok(s)) { write_https_logon_page(s); } else { @@ -2554,7 +2585,7 @@ static void write_shared_secrets_page(ioa_socket_handle s, const char* add_secre str_buffer_append(sb,"
Realm name: Shared secrets:

\r\n"); str_buffer_append(sb,"
NNameRealm "); str_buffer_append(sb,get_secrets_list_elem(&secrets,i)); str_buffer_append(sb,""); str_buffer_append(sb,get_secrets_list_elem(&realms,i)); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,""); - if(!current_socket->as_eff_realm[0]) { + if(!current_eff_realm()[0]) { str_buffer_append(sb,""); } str_buffer_append(sb,""); @@ -2642,7 +2673,7 @@ static size_t https_print_origins(struct str_buffer* sb) secrets_list_t origins,realms; init_secrets_list(&origins); init_secrets_list(&realms); - dbd->list_origins((u08bits*)current_socket->as_eff_realm,&origins,&realms); + dbd->list_origins((u08bits*)current_eff_realm(),&origins,&realms); size_t sz = get_secrets_list_size(&origins); size_t i; @@ -2653,7 +2684,7 @@ static size_t https_print_origins(struct str_buffer* sb) str_buffer_append(sb,""); - if(!current_socket->as_eff_realm[0]) { + if(!current_eff_realm()[0]) { str_buffer_append(sb,""); @@ -2683,7 +2714,7 @@ static void write_origins_page(ioa_socket_handle s, const char* add_origin, cons { if(s && !ioa_socket_tobeclosed(s)) { - if(!(s->as_ok)) { + if(!is_as_ok(s)) { write_https_logon_page(s); } else { @@ -2705,7 +2736,7 @@ static void write_origins_page(ioa_socket_handle s, const char* add_origin, cons str_buffer_append(sb,"
Realm name: Origins:

\r\n"); str_buffer_append(sb,"
NValueRealm "); str_buffer_append(sb,get_secrets_list_elem(&origins,i)); str_buffer_append(sb,""); str_buffer_append(sb,get_secrets_list_elem(&realms,i)); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,""); - if(!current_socket->as_eff_realm[0]) { + if(!current_eff_realm()[0]) { str_buffer_append(sb,""); } if(is_superuser()) { @@ -2846,7 +2877,7 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con { if(s && !ioa_socket_tobeclosed(s)) { - if(!(s->as_ok)) { + if(!is_as_ok(s)) { write_https_logon_page(s); } else if(!is_superuser()) { write_https_home_page(s); @@ -3055,10 +3086,10 @@ static void handle_update_request(ioa_socket_handle s, struct http_request* hr) if (dbd && dbd->set_permission_ip) { if(!r || !r[0]) { - r = current_socket->as_realm; + r = current_realm(); } - if(current_socket->as_realm[0] && strcmp(current_socket->as_realm,r)) { + if(current_realm()[0] && strcmp(current_realm(),r)) { //forbidden } else { @@ -3083,10 +3114,10 @@ static void handle_update_request(ioa_socket_handle s, struct http_request* hr) if (dbd && dbd->set_permission_ip) { if(!r || !r[0]) { - r = current_socket->as_realm; + r = current_realm(); } - if(current_socket->as_realm[0] && strcmp(current_socket->as_realm,r)) { + if(current_realm()[0] && strcmp(current_realm(),r)) { //forbidden } else { @@ -3108,7 +3139,15 @@ static void handle_logon_request(ioa_socket_handle s, struct http_request* hr) const char *uname = get_http_header_value(hr, HR_USERNAME, NULL); const char *pwd = get_http_header_value(hr, HR_PASSWORD, NULL); - if(!(s->as_ok) && uname && pwd) { + struct admin_session* as = (struct admin_session*)s->special_session; + if(!as) { + as = (struct admin_session*)turn_malloc(sizeof(struct admin_session)); + ns_bzero(as,sizeof(struct admin_session)); + s->special_session = as; + s->special_session_size = sizeof(struct admin_session); + } + + if(!(as->as_ok) && uname && pwd) { const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->get_admin_user) { @@ -3116,10 +3155,11 @@ static void handle_logon_request(ioa_socket_handle s, struct http_request* hr) char realm[STUN_MAX_REALM_SIZE+1]="\0"; if((*(dbd->get_admin_user))((const u08bits*)uname,(u08bits*)realm,password)>=0) { if(!strcmp(pwd,(char*)password)) { - STRCPY(s->as_login,uname); - STRCPY(s->as_realm,realm); - s->as_eff_realm[0]=0; - s->as_ok = 1; + STRCPY(as->as_login,uname); + STRCPY(as->as_realm,realm); + as->as_eff_realm[0]=0; + as->as_ok = 1; + as->number_of_user_sessions = DEFAULT_CLI_MAX_OUTPUT_SESSIONS; } } } @@ -3131,10 +3171,13 @@ static void handle_logout_request(ioa_socket_handle s, struct http_request* hr) { UNUSED_ARG(hr); if(s) { - s->as_login[0] = 0; - s->as_ok = 0; - s->as_realm[0] = 0; - s->as_eff_realm[0] = 0; + struct admin_session* as = (struct admin_session*)s->special_session; + if(as) { + as->as_login[0] = 0; + as->as_ok = 0; + as->as_realm[0] = 0; + as->as_eff_realm[0] = 0; + } } } @@ -3165,11 +3208,11 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) switch(form) { case AS_FORM_PC: { - if(s->as_ok) { - const char *realm0 = get_http_header_value(hr, HR_REALM, current_socket->as_realm); + if(is_as_ok(s)) { + const char *realm0 = get_http_header_value(hr, HR_REALM, current_realm()); if(!is_superuser()) - realm0 = current_socket->as_realm; - STRCPY(current_socket->as_eff_realm,realm0); + realm0 = current_realm(); + STRCPY(current_eff_realm(),realm0); write_pc_page(s); } else { write_https_logon_page(s); @@ -3177,11 +3220,11 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) break; } case AS_FORM_PS: { - if(s->as_ok) { - const char *realm0 = get_http_header_value(hr, HR_REALM, current_socket->as_realm); + if(is_as_ok(s)) { + const char *realm0 = get_http_header_value(hr, HR_REALM, current_realm()); if(!is_superuser()) - realm0 = current_socket->as_realm; - STRCPY(current_socket->as_eff_realm,realm0); + realm0 = current_realm(); + STRCPY(current_eff_realm(),realm0); const char* client_protocol = get_http_header_value(hr, HR_CLIENT_PROTOCOL, ""); @@ -3194,11 +3237,12 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) csid = (turnsession_id)strtoull(ssid,NULL,10); } - size_t max_sessions = cli_max_output_sessions; + size_t max_sessions = current_max_output_sessions(); const char* s_max_sessions = get_http_header_value(hr, HR_MAX_SESSIONS,NULL); if(s_max_sessions) { max_sessions=strtoul(s_max_sessions,NULL,10); - if(!max_sessions) max_sessions = cli_max_output_sessions; + if(!max_sessions) max_sessions = current_max_output_sessions(); + set_current_max_output_sessions(max_sessions); } if(!max_sessions) max_sessions = DEFAULT_CLI_MAX_OUTPUT_SESSIONS; @@ -3210,12 +3254,12 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) break; } case AS_FORM_USERS: { - if(s->as_ok) { + if(is_as_ok(s)) { { - const char *realm0 = get_http_header_value(hr, HR_REALM, current_socket->as_realm); + const char *realm0 = get_http_header_value(hr, HR_REALM, current_realm()); if(!is_superuser()) - realm0 = current_socket->as_realm; - STRCPY(current_socket->as_eff_realm,realm0); + realm0 = current_realm(); + STRCPY(current_eff_realm(),realm0); } { @@ -3223,7 +3267,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) if(user && user[0]) { const u08bits *realm = (const u08bits*)get_http_header_value(hr, HR_DELETE_REALM, ""); if(!is_superuser()) { - realm = (const u08bits*)current_socket->as_realm; + realm = (const u08bits*)current_realm(); } if(realm && realm[0]) { const turn_dbdriver_t * dbd = get_dbdriver(); @@ -3238,7 +3282,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } } - const u08bits *add_realm = (const u08bits*)current_socket->as_eff_realm; + const u08bits *add_realm = (const u08bits*)current_eff_realm(); const u08bits *add_user = (const u08bits*)get_http_header_value(hr, HR_ADD_USER,""); const char* msg = ""; if(wrong_html_name((const char*)add_user)) { @@ -3246,12 +3290,12 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) add_user = (const u08bits*)""; } if(add_user[0]) { - add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_REALM, current_socket->as_realm); + add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_REALM, current_realm()); if(!is_superuser()) { - add_realm = (const u08bits*)current_socket->as_realm; + add_realm = (const u08bits*)current_realm(); } if(!add_realm[0]) { - add_realm=(const u08bits*)current_socket->as_eff_realm; + add_realm=(const u08bits*)current_eff_realm(); } if(!add_realm[0]) { add_realm = (const u08bits*)get_realm(NULL)->options.name; @@ -3310,12 +3354,12 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) break; } case AS_FORM_SS: { - if(s->as_ok) { + if(is_as_ok(s)) { { - const char *realm0 = get_http_header_value(hr, HR_REALM, current_socket->as_realm); + const char *realm0 = get_http_header_value(hr, HR_REALM, current_realm()); if(!is_superuser()) - realm0 = current_socket->as_realm; - STRCPY(current_socket->as_eff_realm,realm0); + realm0 = current_realm(); + STRCPY(current_eff_realm(),realm0); } { @@ -3323,7 +3367,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) if(secret && secret[0]) { const u08bits *realm = (const u08bits*)get_http_header_value(hr, HR_DELETE_REALM, NULL); if(!is_superuser()) { - realm = (const u08bits*)current_socket->as_realm; + realm = (const u08bits*)current_realm(); } if(realm && realm[0]) { const turn_dbdriver_t * dbd = get_dbdriver(); @@ -3338,7 +3382,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } } - const u08bits *add_realm = (const u08bits*)current_socket->as_eff_realm; + const u08bits *add_realm = (const u08bits*)current_eff_realm(); const u08bits *add_secret = (const u08bits*)get_http_header_value(hr, HR_ADD_SECRET, ""); const char* msg = ""; if(wrong_html_name((const char*)add_secret)) { @@ -3346,12 +3390,12 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) add_secret = (const u08bits*)""; } if(add_secret[0]) { - add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_REALM, current_socket->as_realm); + add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_REALM, current_realm()); if(!is_superuser()) { - add_realm = (const u08bits*)current_socket->as_realm; + add_realm = (const u08bits*)current_realm(); } if(!add_realm[0]) { - add_realm=(const u08bits*)current_socket->as_eff_realm; + add_realm=(const u08bits*)current_eff_realm(); } if(!add_realm[0]) { add_realm = (const u08bits*)get_realm(NULL)->options.name; @@ -3383,12 +3427,12 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) break; } case AS_FORM_OS: { - if(s->as_ok) { + if(is_as_ok(s)) { { - const char *realm0 = get_http_header_value(hr, HR_REALM, current_socket->as_realm); + const char *realm0 = get_http_header_value(hr, HR_REALM, current_realm()); if(!is_superuser()) - realm0 = current_socket->as_realm; - STRCPY(current_socket->as_eff_realm,realm0); + realm0 = current_realm(); + STRCPY(current_eff_realm(),realm0); } if(is_superuser()) { @@ -3406,18 +3450,18 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } } - const u08bits *add_realm = (const u08bits*)current_socket->as_eff_realm; + const u08bits *add_realm = (const u08bits*)current_eff_realm(); const u08bits *add_origin = (const u08bits*)get_http_header_value(hr, HR_ADD_ORIGIN, ""); const char* msg = ""; u08bits corigin[STUN_MAX_ORIGIN_SIZE+1]; get_canonic_origin((const char *)add_origin, (char *)corigin, sizeof(corigin)-1); if(corigin[0]) { - add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_REALM, current_socket->as_realm); + add_realm = (const u08bits*)get_http_header_value(hr, HR_ADD_REALM, current_realm()); if(!is_superuser()) { - add_realm = (const u08bits*)current_socket->as_realm; + add_realm = (const u08bits*)current_realm(); } if(!add_realm[0]) { - add_realm=(const u08bits*)current_socket->as_eff_realm; + add_realm=(const u08bits*)current_eff_realm(); } if(!add_realm[0]) { add_realm = (const u08bits*)get_realm(NULL)->options.name; @@ -3445,7 +3489,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) break; } case AS_FORM_OAUTH: { - if(!s->as_ok) { + if(!is_as_ok(s)) { write_https_logon_page(s); } else if(!is_superuser()) { write_https_home_page(s); @@ -3506,7 +3550,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) break; } case AS_FORM_TOGGLE: - if(s->as_ok) { + if(is_as_ok(s)) { handle_toggle_request(s,hr); write_pc_page(s); } else { @@ -3514,7 +3558,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } break; case AS_FORM_UPDATE: - if(s->as_ok) { + if(is_as_ok(s)) { handle_update_request(s,hr); write_pc_page(s); } else { @@ -3522,9 +3566,9 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } break; case AS_FORM_LOGON: - if(!(s->as_ok)) { + if(!is_as_ok(s)) { handle_logon_request(s,hr); - if(s->as_ok) { + if(is_as_ok(s)) { write_https_home_page(s); } else { write_https_logon_page(s); diff --git a/src/apps/relay/turn_admin_server.h b/src/apps/relay/turn_admin_server.h index 013d0af3..a1e5570c 100644 --- a/src/apps/relay/turn_admin_server.h +++ b/src/apps/relay/turn_admin_server.h @@ -51,6 +51,16 @@ extern "C" { //////////////////////////////////////////// +#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; From 40043a9afc2921fef77c6518c1214e65e1f8ad36 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 23 Jan 2015 01:48:08 +0000 Subject: [PATCH 448/805] fixes --- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/turn_admin_server.c | 68 +++++++++++++++++------------ src/apps/relay/userdb.c | 37 ++++++++++++++++ src/apps/relay/userdb.h | 1 + src/client/ns_turn_ioaddr.c | 28 +++++++++--- 5 files changed, 99 insertions(+), 35 deletions(-) diff --git a/examples/var/db/turndb b/examples/var/db/turndb index 3b0da293efbb7a65b15012fac831f6ed8a92a848..e8565976f04396f6cf5b6b3030b43dd7882b95a9 100644 GIT binary patch delta 220 zcmZqJz}T>Xae_2s^F$eE#^#L)>!n$jGj}p~Zfq=J);D5cV9--H)HBjE)&-M#CO{Dx zhzOW1pbU{U(KFREo4j2Xae_2s;Y1l{#=?yW>!q1zF}H3OP$^>;Gh#phH5gNNqNC*G?ebB~z0AEE z8}peZOkpx0S_96Jo9HODd8=}S0<$o)@Ww_q=E-92-dt(LDNr=|p1acIUiSv(o6I*i O3x=F!-h9_vnFj#XoFerA diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index cedfd492..35fecde8 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1765,7 +1765,7 @@ static void https_print_ip_range_list(struct str_buffer* sb, ip_range_list_t *va if(dynamic) { sbprintf(sb,"
NValueRealm
%s",name); - sbprintf(sb,"IP range:",form_names[AS_FORM_UPDATE].name,HR_ADD_IP_KIND,kind,HR_ADD_IP); + sbprintf(sb,"IP range:",form_names[AS_FORM_UPDATE].name,HR_ADD_IP_KIND,kind,HR_ADD_IP); sbprintf(sb,"Realm: \r\n\r\n"); @@ -2922,7 +2926,7 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,HR_ADD_OAUTH_IKM); str_buffer_append(sb,"\" value=\""); str_buffer_append(sb,(const char*)add_ikm); - str_buffer_append(sb,"\" maxlength=256 size=48 required "); + str_buffer_append(sb,"\" maxlength=256 size=64 "); str_buffer_append(sb,">
\r\n"); } { @@ -3107,24 +3111,30 @@ static void handle_update_request(ioa_socket_handle s, struct http_request* hr) const char* eip = get_http_header_value(hr, HR_ADD_IP,NULL); if(eip && eip[0]) { char* ip = evhttp_decode_uri(eip); - const char* r = get_http_header_value(hr, HR_ADD_IP_REALM,""); - const char* kind = get_http_header_value(hr, HR_ADD_IP_KIND,""); - const turn_dbdriver_t * dbd = get_dbdriver(); - if (dbd && dbd->set_permission_ip) { + if(check_ip_list_range(ip)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong address range format: %s\n", ip); + } else { - if(!r || !r[0]) { - r = current_realm(); - } + const char* r = get_http_header_value(hr, HR_ADD_IP_REALM,""); + const char* kind = get_http_header_value(hr, HR_ADD_IP_KIND,""); - if(current_realm()[0] && strcmp(current_realm(),r)) { - //forbidden - } else { + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->set_permission_ip) { - u08bits realm[STUN_MAX_REALM_SIZE+1]="\0"; - STRCPY(realm,r); + if(!r || !r[0]) { + r = current_realm(); + } - dbd->set_permission_ip(kind, realm, ip, 0); + if(current_realm()[0] && strcmp(current_realm(),r)) { + //forbidden + } else { + + u08bits realm[STUN_MAX_REALM_SIZE+1]="\0"; + STRCPY(realm,r); + + dbd->set_permission_ip(kind, realm, ip, 0); + } } } free(ip); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 5ab3d6c9..0fdda266 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -1266,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) diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index 84b944c6..c14a24e9 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -202,6 +202,7 @@ 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); diff --git a/src/client/ns_turn_ioaddr.c b/src/client/ns_turn_ioaddr.c index 13fb33d1..60ccd3d5 100644 --- a/src/client/ns_turn_ioaddr.c +++ b/src/client/ns_turn_ioaddr.c @@ -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; From 073d07b7469f6d68187df1bf8cfc17373585e7b0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 23 Jan 2015 06:39:10 +0000 Subject: [PATCH 449/805] cosmetics --- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/turn_admin_server.c | 47 +++++++++++++++++++---------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/examples/var/db/turndb b/examples/var/db/turndb index e8565976f04396f6cf5b6b3030b43dd7882b95a9..cbfa8c4a177d72689cc86cf5f548ef127152ee58 100644 GIT binary patch delta 77 zcmZqJz}T>Xae_2s=R_H2)=mc9M`{~WRyeaTr7{a|Z1iE`Wi)1h0Y;6DjVg?jd)*tD ZUozj^EEsZ@dGcLv4i=F7=9k{$JOETa6?Fgr delta 187 zcmZqJz}T>Xae_2s^F$eE)@BCXN2(iBRyeaTCo&6fY-D4uuQKM~kk;kp"admin_title"" -static const char* home_link = "
home page
\r\n
Logout

\r\n"; +static const char* home_link = "
home page
\r\n
Logout
\r\n"; static const char* logout_link = "
Logout

\r\n"; static ioa_socket_handle current_socket = NULL; @@ -1848,7 +1848,7 @@ static void write_pc_page(ioa_socket_handle s) str_buffer_append(sb,"\r\n\r\n \r\n "); str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,"\r\n \r\n \r\n "); str_buffer_append(sb,bold_admin_title); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,home_link); @@ -2268,7 +2268,7 @@ static void write_ps_page(ioa_socket_handle s, const char* client_protocol, cons str_buffer_append(sb,"\r\n\r\n \r\n "); str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,"\r\n \r\n \r\n "); str_buffer_append(sb,bold_admin_title); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,home_link); @@ -2403,7 +2403,7 @@ static void write_users_page(ioa_socket_handle s, const u08bits *add_user, const str_buffer_append(sb,"\r\n\r\n \r\n "); str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,"\r\n \r\n \r\n "); str_buffer_append(sb,bold_admin_title); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,home_link); @@ -2575,7 +2575,7 @@ static void write_shared_secrets_page(ioa_socket_handle s, const char* add_secre str_buffer_append(sb,"\r\n\r\n \r\n "); str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,"\r\n \r\n \r\n "); str_buffer_append(sb,bold_admin_title); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,home_link); @@ -2726,7 +2726,7 @@ static void write_origins_page(ioa_socket_handle s, const char* add_origin, cons str_buffer_append(sb,"\r\n\r\n \r\n "); str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,"\r\n \r\n \r\n "); str_buffer_append(sb,bold_admin_title); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,home_link); @@ -2891,7 +2891,7 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,"\r\n\r\n \r\n "); str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,"\r\n \r\n \r\n "); str_buffer_append(sb,bold_admin_title); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,home_link); @@ -2909,6 +2909,8 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,"

"); } + str_buffer_append(sb,"\r\n
"); + { if(!add_kid) add_kid=""; @@ -2916,21 +2918,26 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,HR_ADD_OAUTH_KID); str_buffer_append(sb,"\" value=\""); str_buffer_append(sb,(const char*)add_kid); - str_buffer_append(sb,"\" required "); - str_buffer_append(sb,">
\r\n"); + str_buffer_append(sb,"\">
\r\n"); } + + str_buffer_append(sb,"
"); + { if(!add_ikm) add_ikm = ""; - str_buffer_append(sb,"
Base64-encoded input keying material: Base64-encoded input keying material:
"); + str_buffer_append(sb,"
\r\n"); } + + str_buffer_append(sb,"
"); + { - str_buffer_append(sb,">
Hash key derivation function:
\r\n"); + str_buffer_append(sb,"
Hash key derivation function:
\r\n"); if(!add_hkdf_hash_func || !add_hkdf_hash_func[0]) add_hkdf_hash_func = "SHA-256"; @@ -2951,8 +2958,11 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con } str_buffer_append(sb,">SHA-256\r\n
\r\n"); } + + str_buffer_append(sb,"
"); + { - str_buffer_append(sb,">
Token encryption algorithm:
\r\n"); + str_buffer_append(sb,"
Token encryption algorithm:
\r\n"); if(!add_tea || !add_tea[0]) add_tea = "AES-256-CBC"; @@ -2989,8 +2999,11 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con } str_buffer_append(sb,">AEAD-AES-256-GCM\r\n
\r\n"); } + + str_buffer_append(sb,"
"); + { - str_buffer_append(sb,">
Token authentication algorithm:
\r\n"); + str_buffer_append(sb,"
Token authentication algorithm:
\r\n"); if(!add_aa || !add_aa[0]) add_aa = "HMAC-SHA-256-128"; @@ -3020,6 +3033,8 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,">HMAC-SHA-1\r\n
\r\n"); } + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
"); str_buffer_append(sb,"\r\n"); From 7c2fc1b1b6366f1d64916e77687fa4ec918936b4 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 23 Jan 2015 07:12:04 +0000 Subject: [PATCH 450/805] oauth timestamps added --- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/dbdrivers/dbd_mongo.c | 12 ++++- src/apps/relay/dbdrivers/dbd_mysql.c | 12 ++++- src/apps/relay/dbdrivers/dbd_pgsql.c | 12 ++++- src/apps/relay/dbdrivers/dbd_redis.c | 12 ++++- src/apps/relay/dbdrivers/dbd_sqlite.c | 12 ++++- src/apps/relay/dbdrivers/dbdriver.h | 2 +- src/apps/relay/turn_admin_server.c | 66 ++++++++++++++++++++++++-- 8 files changed, 118 insertions(+), 10 deletions(-) diff --git a/examples/var/db/turndb b/examples/var/db/turndb index cbfa8c4a177d72689cc86cf5f548ef127152ee58..e2b08c13a88f7bb6e31cc7a1435f23a8bd8ead19 100644 GIT binary patch delta 55 zcmV-70LcGtV09?P6HFMflLCETt@W)KaqhulZ{7!1K|VN Nvk_Fy1GC*rBMc=I6jcBK delta 53 zcmV-50LuS>umOOu0gxL3iIE&b0g16-tV09>WdjqjflLCETt@YgkUW!(M}PzA1KG0? LRLujk-Af}33{Dg~ diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index b7cf0fab..cefe3af0 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -497,7 +497,7 @@ static int mongo_list_users(u08bits *realm, secrets_list_t *users, secrets_list_ return ret; } -static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas) { +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); @@ -575,6 +575,16 @@ static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr 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, diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 4d71be21..ceaa96a9 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -402,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(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas) { +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_; @@ -462,6 +462,16 @@ static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr 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, diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index 873c47e5..2141a6ca 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -187,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(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas) { +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_; @@ -222,6 +222,16 @@ static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr 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, diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index 49befeea..4f100af6 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -637,7 +637,7 @@ static int redis_list_users(u08bits *realm, secrets_list_t *users, secrets_list_ return ret; } -static int redis_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas) { +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; @@ -678,6 +678,16 @@ static int redis_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr 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, diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index f2ac8443..f86b559d 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -329,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(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas) { +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_; @@ -370,6 +370,16 @@ static int sqlite_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,sec 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, diff --git a/src/apps/relay/dbdrivers/dbdriver.h b/src/apps/relay/dbdrivers/dbdriver.h index 8776a3a2..4aaa566a 100644 --- a/src/apps/relay/dbdrivers/dbdriver.h +++ b/src/apps/relay/dbdrivers/dbdriver.h @@ -68,7 +68,7 @@ typedef struct _turn_dbdriver_t { int (*set_oauth_key)(oauth_key_data_raw *key); int (*get_oauth_key)(const u08bits *kid, oauth_key_data_raw *key); int (*del_oauth_key)(const u08bits *kid); - int (*list_oauth_keys)(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas); + 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); diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index e59bf4c5..5351af43 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1393,6 +1393,8 @@ typedef enum _AS_FORM AS_FORM; #define HR_ADD_IP_KIND "aipk" #define HR_UPDATE_PARAMETER "togglepar" #define HR_ADD_OAUTH_KID "oauth_kid" +#define HR_ADD_OAUTH_TS "oauth_ts" +#define HR_ADD_OAUTH_LT "oauth_lt" #define HR_ADD_OAUTH_IKM "oauth_ikm" #define HR_ADD_OAUTH_HKDF "oauth_hkdf" #define HR_ADD_OAUTH_TEA "oauth_tea" @@ -2826,12 +2828,14 @@ static size_t https_print_oauth_keys(struct str_buffer* sb) size_t ret = 0; const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->list_oauth_keys) { - secrets_list_t kids,hkdfs,teas,aas; + secrets_list_t kids,hkdfs,teas,aas,tss,lts; init_secrets_list(&kids); init_secrets_list(&hkdfs); init_secrets_list(&teas); init_secrets_list(&aas); - dbd->list_oauth_keys(&kids,&hkdfs,&teas,&aas); + init_secrets_list(&tss); + init_secrets_list(<s); + dbd->list_oauth_keys(&kids,&hkdfs,&teas,&aas,&tss,<s); size_t sz = get_secrets_list_size(&kids); size_t i; @@ -2843,6 +2847,12 @@ static size_t https_print_oauth_keys(struct str_buffer* sb) str_buffer_append(sb,get_secrets_list_elem(&kids,i)); str_buffer_append(sb,""); str_buffer_append(sb,""); + str_buffer_append(sb,get_secrets_list_elem(&tss,i)); + str_buffer_append(sb,""); + str_buffer_append(sb,""); + str_buffer_append(sb,get_secrets_list_elem(<s,i)); + str_buffer_append(sb,""); + str_buffer_append(sb,""); str_buffer_append(sb,get_secrets_list_elem(&hkdfs,i)); str_buffer_append(sb,""); str_buffer_append(sb,""); @@ -2877,6 +2887,7 @@ static size_t https_print_oauth_keys(struct str_buffer* sb) static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, const char* add_ikm, const char* add_hkdf_hash_func, const char* add_tea, const char* add_aa, + const char *add_ts, const char* add_lt, const char* msg) { if(s && !ioa_socket_tobeclosed(s)) { @@ -2921,7 +2932,31 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,"\">
\r\n"); } - str_buffer_append(sb,""); + str_buffer_append(sb,""); + + { + if(!add_ts) add_ts=""; + + str_buffer_append(sb,"
Timestamp, secs:
\r\n"); + } + + str_buffer_append(sb,""); + + { + if(!add_lt) add_lt=""; + + str_buffer_append(sb,"
Lifetime, secs:
\r\n"); + } + + str_buffer_append(sb,""); { if(!add_ikm) add_ikm = ""; @@ -3044,6 +3079,8 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,"
OAuth keys:

\r\n"); str_buffer_append(sb,"\r\n"); str_buffer_append(sb,""); + str_buffer_append(sb,""); + str_buffer_append(sb,""); str_buffer_append(sb,""); str_buffer_append(sb,""); str_buffer_append(sb,""); @@ -3531,6 +3568,8 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } const char* add_kid = ""; + const char* add_ts = "0"; + const char* add_lt = "0"; const char* add_ikm = ""; const char* add_hkdf_hash_func = ""; const char* add_tea = ""; @@ -3541,6 +3580,8 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) if(add_kid[0]) { add_ikm = get_http_header_value(hr,HR_ADD_OAUTH_IKM,""); if(add_ikm[0]) { + add_ts = get_http_header_value(hr,HR_ADD_OAUTH_TS,""); + add_lt = get_http_header_value(hr,HR_ADD_OAUTH_LT,""); add_hkdf_hash_func = get_http_header_value(hr,HR_ADD_OAUTH_HKDF,""); add_tea = get_http_header_value(hr,HR_ADD_OAUTH_TEA,""); add_aa = get_http_header_value(hr,HR_ADD_OAUTH_AA,""); @@ -3548,6 +3589,21 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) oauth_key_data_raw key; ns_bzero(&key,sizeof(key)); STRCPY(key.kid,add_kid); + + if(add_lt && add_lt[0]) { + key.lifetime = (u32bits)strtoul(add_lt,NULL,10); + if(key.lifetime) { + if(add_ts && add_ts[0]) { + key.timestamp = (u64bits)strtoull(add_ts,NULL,10); + } + if(!key.timestamp) { + key.timestamp = (u64bits)time(NULL); + } + } + } else if(add_ts && add_ts[0]) { + key.timestamp = (u64bits)strtoull(add_ts,NULL,10); + } + STRCPY(key.ikm_key,add_ikm); STRCPY(key.hkdf_hash_func,add_hkdf_hash_func); STRCPY(key.as_rs_alg,add_tea); @@ -3561,6 +3617,8 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) msg = "Cannot insert oAuth key into the database"; } else { add_kid = ""; + add_ts = "0"; + add_lt = "0"; add_ikm = ""; add_hkdf_hash_func = ""; add_tea = ""; @@ -3570,7 +3628,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } } - write_https_oauth_page(s,add_kid,add_ikm,add_hkdf_hash_func,add_tea,add_aa,msg); + write_https_oauth_page(s,add_kid,add_ikm,add_hkdf_hash_func,add_tea,add_aa,add_ts,add_lt,msg); } break; } From 24053523b57e512ab59a262b04a623337269a52e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 23 Jan 2015 09:26:57 +0000 Subject: [PATCH 451/805] show oauth keys --- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/turn_admin_server.c | 230 +++++++++++++++++++++++++---- src/apps/uclient/mainuclient.c | 2 +- src/client/ns_turn_msg.c | 4 + 4 files changed, 205 insertions(+), 31 deletions(-) diff --git a/examples/var/db/turndb b/examples/var/db/turndb index e2b08c13a88f7bb6e31cc7a1435f23a8bd8ead19..847a60014a13228733709067e82c26cabba033e9 100644 GIT binary patch delta 92 zcmZqJz}T>Xae_4C^ocUgjMFzJtaWA$V^(3hys^=XX>yEP6{G9KMi<^v1_Usg*l5UT gKC#hwa<6+6^F!vFn;CfyG4pajRetwRG&0~4`PznVQcXxLLv*Al047{5b2mk;8 diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 5351af43..dbb688b1 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1364,6 +1364,7 @@ enum _AS_FORM { AS_FORM_SS, AS_FORM_OS, AS_FORM_OAUTH, + AS_FORM_OAUTH_SHOW_KEYS, AS_FORM_UNKNOWN }; @@ -1396,10 +1397,13 @@ typedef enum _AS_FORM AS_FORM; #define HR_ADD_OAUTH_TS "oauth_ts" #define HR_ADD_OAUTH_LT "oauth_lt" #define HR_ADD_OAUTH_IKM "oauth_ikm" +#define HR_ADD_OAUTH_RS_KEY "oauth_rs_key" +#define HR_ADD_OAUTH_AUTH_KEY "oauth_auth_key" #define HR_ADD_OAUTH_HKDF "oauth_hkdf" #define HR_ADD_OAUTH_TEA "oauth_tea" #define HR_ADD_OAUTH_AA "oauth_aa" #define HR_DELETE_OAUTH_KID "oauth_kid_del" +#define HR_OAUTH_KID "kid" struct form_name { AS_FORM form; @@ -1418,6 +1422,7 @@ static struct form_name form_names[] = { {AS_FORM_SS,"/ss"}, {AS_FORM_OS,"/os"}, {AS_FORM_OAUTH,"/oauth"}, + {AS_FORM_OAUTH_SHOW_KEYS,"/oauth_show_keys"}, {AS_FORM_UNKNOWN,NULL} }; @@ -2846,6 +2851,15 @@ static size_t https_print_oauth_keys(struct str_buffer* sb) str_buffer_append(sb,""); + + str_buffer_append(sb,""); + str_buffer_append(sb,""); @@ -2885,9 +2899,110 @@ static size_t https_print_oauth_keys(struct str_buffer* sb) return ret; } +static void write_https_oauth_show_keys(ioa_socket_handle s, const char* kid) +{ + if(s && !ioa_socket_tobeclosed(s)) { + + if(!is_as_ok(s)) { + write_https_logon_page(s); + } else if(!is_superuser()) { + write_https_home_page(s); + } else { + + struct str_buffer* sb = str_buffer_new(); + + str_buffer_append(sb,"\r\n\r\n \r\n "); + str_buffer_append(sb,admin_title); + str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,bold_admin_title); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
back to oauth list
\r\n"); + str_buffer_append(sb,home_link); + str_buffer_append(sb,"
\r\n"); + + if(kid && kid[0]) { + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->get_oauth_key) { + oauth_key_data_raw key; + if((*dbd->get_oauth_key)((const u08bits*)kid,&key)<0) { + str_buffer_append(sb,"data retrieval error"); + } else { + + oauth_key_data okd; + ns_bzero(&okd,sizeof(okd)); + + convert_oauth_key_data_raw(&key, &okd); + + char err_msg[1025] = "\0"; + size_t err_msg_size = sizeof(err_msg) - 1; + + oauth_key okey; + ns_bzero(&okey,sizeof(okey)); + + if (convert_oauth_key_data(&okd, &okey, err_msg, err_msg_size) < 0) { + str_buffer_append(sb,err_msg); + } else { + + str_buffer_append(sb,"
NKIDTimestamp, secsLifetime,secsHash key derivation functionToken encryption algorithmToken authentication algorithm"); str_buffer_append(sb,get_secrets_list_elem(&kids,i)); str_buffer_append(sb," show "); str_buffer_append(sb,get_secrets_list_elem(&tss,i)); str_buffer_append(sb,"
\r\n"); + + if(key.ikm_key[0]) { + str_buffer_append(sb,"\r\n"); + } + + if(okey.as_rs_key_size) { + size_t as_rs_key_size = 0; + char *as_rs_key = (char*)base64_encode((unsigned char*)okey.as_rs_key,okey.as_rs_key_size,&as_rs_key_size); + if(as_rs_key) { + str_buffer_append(sb,"\r\n"); + turn_free(as_rs_key,as_rs_key_size); + } + } + + if(okey.auth_key_size) { + size_t auth_key_size = 0; + char *auth_key = (char*)base64_encode((unsigned char*)okey.auth_key,okey.auth_key_size,&auth_key_size); + if(auth_key) { + str_buffer_append(sb,"\r\n"); + turn_free(auth_key,auth_key_size); + } + } + + str_buffer_append(sb,"
Input Keying Material:"); + str_buffer_append(sb,key.ikm_key); + str_buffer_append(sb,"
AS-RS key:"); + str_buffer_append(sb,as_rs_key); + str_buffer_append(sb,"
AUTH key:"); + str_buffer_append(sb,auth_key); + str_buffer_append(sb,"
\r\n"); + } + } + } + } + + str_buffer_append(sb,"\r\n\r\n"); + + send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); + send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); + send_str_from_ioa_socket_tcp(s,"\r\n"); + send_str_from_ioa_socket_tcp(s,get_http_date_header()); + send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); + + send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); + + send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); + send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); + + str_buffer_free(sb); + } + } +} + static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, const char* add_ikm, const char* add_hkdf_hash_func, const char* add_tea, const char* add_aa, const char *add_ts, const char* add_lt, + const char *add_rs_key, const char *add_auth_key, const char* msg) { if(s && !ioa_socket_tobeclosed(s)) { @@ -2925,7 +3040,7 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con { if(!add_kid) add_kid=""; - str_buffer_append(sb,"
KID: KID (required): Timestamp, secs: Timestamp, secs (optional): Lifetime, secs: Lifetime, secs (optional):
\r\n"); } - str_buffer_append(sb,""); + str_buffer_append(sb,""); { - if(!add_ikm) add_ikm = ""; - - str_buffer_append(sb,"
Base64-encoded input keying material:
"); - str_buffer_append(sb,"
\r\n"); - } - - str_buffer_append(sb,"\r\n"); - - { - str_buffer_append(sb,"
Hash key derivation function:
\r\n"); + str_buffer_append(sb,"
Hash key derivation function (optional):
\r\n"); if(!add_hkdf_hash_func || !add_hkdf_hash_func[0]) add_hkdf_hash_func = "SHA-256"; @@ -2994,10 +3096,23 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,">SHA-256\r\n
\r\n"); } - str_buffer_append(sb,""); + str_buffer_append(sb,""); { - str_buffer_append(sb,"
Token encryption algorithm:
\r\n"); + if(!add_ikm) add_ikm = ""; + + str_buffer_append(sb,"
Base64-encoded input keying material (optional):
"); + str_buffer_append(sb,"
\r\n"); + } + + str_buffer_append(sb,"\r\n"); + + { + str_buffer_append(sb,"
Token encryption algorithm (required):
\r\n"); if(!add_tea || !add_tea[0]) add_tea = "AES-256-CBC"; @@ -3035,10 +3150,23 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,">AEAD-AES-256-GCM\r\n
\r\n"); } - str_buffer_append(sb,""); + str_buffer_append(sb,""); { - str_buffer_append(sb,"
Token authentication algorithm:
\r\n"); + if(!add_rs_key) add_rs_key = ""; + + str_buffer_append(sb,"
Base64-encoded AS-RS key (optional):
"); + str_buffer_append(sb,"
\r\n"); + } + + str_buffer_append(sb,"\r\n"); + + { + str_buffer_append(sb,"
Token authentication algorithm (required if no AEAD used):
\r\n"); if(!add_aa || !add_aa[0]) add_aa = "HMAC-SHA-256-128"; @@ -3068,6 +3196,19 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,">HMAC-SHA-1\r\n
\r\n"); } + str_buffer_append(sb,""); + + { + if(!add_auth_key) add_auth_key = ""; + + str_buffer_append(sb,"
Base64-encoded AUTH key (optional):
"); + str_buffer_append(sb,"
\r\n"); + } + str_buffer_append(sb,"\r\n"); str_buffer_append(sb,"
"); @@ -3078,7 +3219,7 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,"
OAuth keys:

\r\n"); str_buffer_append(sb,"\r\n"); - str_buffer_append(sb,""); + str_buffer_append(sb,""); str_buffer_append(sb,""); str_buffer_append(sb,""); str_buffer_append(sb,""); @@ -3550,6 +3691,17 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } break; } + case AS_FORM_OAUTH_SHOW_KEYS: { + if(!is_as_ok(s)) { + write_https_logon_page(s); + } else if(!is_superuser()) { + write_https_home_page(s); + } else { + const char* kid = get_http_header_value(hr,HR_OAUTH_KID,""); + write_https_oauth_show_keys(s,kid); + } + break; + } case AS_FORM_OAUTH: { if(!is_as_ok(s)) { write_https_logon_page(s); @@ -3571,6 +3723,8 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) const char* add_ts = "0"; const char* add_lt = "0"; const char* add_ikm = ""; + const char *add_rs_key = ""; + const char *add_auth_key = ""; const char* add_hkdf_hash_func = ""; const char* add_tea = ""; const char* add_aa = ""; @@ -3579,13 +3733,25 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) add_kid = get_http_header_value(hr,HR_ADD_OAUTH_KID,""); if(add_kid[0]) { add_ikm = get_http_header_value(hr,HR_ADD_OAUTH_IKM,""); - if(add_ikm[0]) { - add_ts = get_http_header_value(hr,HR_ADD_OAUTH_TS,""); - add_lt = get_http_header_value(hr,HR_ADD_OAUTH_LT,""); - add_hkdf_hash_func = get_http_header_value(hr,HR_ADD_OAUTH_HKDF,""); - add_tea = get_http_header_value(hr,HR_ADD_OAUTH_TEA,""); - add_aa = get_http_header_value(hr,HR_ADD_OAUTH_AA,""); + add_rs_key = get_http_header_value(hr,HR_ADD_OAUTH_RS_KEY,""); + add_auth_key = get_http_header_value(hr,HR_ADD_OAUTH_AUTH_KEY,""); + add_ts = get_http_header_value(hr,HR_ADD_OAUTH_TS,""); + add_lt = get_http_header_value(hr,HR_ADD_OAUTH_LT,""); + add_hkdf_hash_func = get_http_header_value(hr,HR_ADD_OAUTH_HKDF,""); + add_tea = get_http_header_value(hr,HR_ADD_OAUTH_TEA,""); + add_aa = get_http_header_value(hr,HR_ADD_OAUTH_AA,""); + int keys_ok = 0; + if(add_ikm[0] && add_hkdf_hash_func[0]) { + keys_ok = 1; + } else if(add_rs_key[0] && add_auth_key[0]) { + keys_ok = 1; + } else if(strstr(add_tea,"AEAD") && add_rs_key[0]) { + keys_ok = 1; + } + if(!keys_ok) { + msg = "Provided information is insufficient for the oAuth key generation."; + } else { oauth_key_data_raw key; ns_bzero(&key,sizeof(key)); STRCPY(key.kid,add_kid); @@ -3608,6 +3774,8 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) STRCPY(key.hkdf_hash_func,add_hkdf_hash_func); STRCPY(key.as_rs_alg,add_tea); STRCPY(key.auth_alg,add_aa); + STRCPY(key.as_rs_key,add_rs_key); + STRCPY(key.auth_key,add_auth_key); if(strstr(key.as_rs_alg,"AEAD")) key.auth_alg[0]=0; @@ -3623,12 +3791,14 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) add_hkdf_hash_func = ""; add_tea = ""; add_aa = ""; + add_rs_key = ""; + add_auth_key = ""; } } } } - write_https_oauth_page(s,add_kid,add_ikm,add_hkdf_hash_func,add_tea,add_aa,add_ts,add_lt,msg); + write_https_oauth_page(s,add_kid,add_ikm,add_hkdf_hash_func,add_tea,add_aa,add_ts,add_lt,add_rs_key,add_auth_key,msg); } break; } diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index e509b797..3c7fa867 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -136,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" diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 061cbf65..464a581f 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1895,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; @@ -1904,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); From 547b3467fa03ea44ddf354937e82edb28db2593d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 23 Jan 2015 09:36:37 +0000 Subject: [PATCH 452/805] cosmetics --- src/apps/relay/turn_admin_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index dbb688b1..9cca3f76 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1771,7 +1771,7 @@ static void https_print_ip_range_list(struct str_buffer* sb, ip_range_list_t *va } if(dynamic) { - sbprintf(sb,"
NKID
NKIDkeysTimestamp, secsLifetime,secsHash key derivation function
%s",name); + sbprintf(sb,"
Add %s",name); sbprintf(sb,"IP range:",form_names[AS_FORM_UPDATE].name,HR_ADD_IP_KIND,kind,HR_ADD_IP); sbprintf(sb,"Realm: Date: Sat, 24 Jan 2015 08:08:42 +0000 Subject: [PATCH 453/805] cosmetics --- src/apps/relay/turn_admin_server.c | 278 +++++++++-------------------- 1 file changed, 86 insertions(+), 192 deletions(-) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 9cca3f76..96aed71d 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1427,12 +1427,35 @@ static struct form_name form_names[] = { }; #define admin_title "TURN Server (https admin connection)" -#define bold_admin_title ""admin_title"" -static const char* home_link = "
home page
\r\n
Logout
\r\n"; -static const char* logout_link = "
Logout

\r\n"; +#define __bold_admin_title "TURN Server
https admin connection
\r\n" +#define bold_admin_title get_bold_admin_title() +static const char* home_link = "
home page
\r\n
logout
\r\n"; static ioa_socket_handle current_socket = NULL; +static char *get_bold_admin_title(void) +{ + static char sbat[1025]; + STRCPY(sbat,__bold_admin_title); + if(current_socket && current_socket->special_session) { + struct admin_session* as = (struct admin_session*)current_socket->special_session; + if(as->as_ok) { + if(as->as_login[0]) { + char *dst=sbat+strlen(sbat); + snprintf(dst,ADMIN_USER_MAX_LENGTH*2," admin user: %s
\r\n",as->as_login); + } + if(as->as_realm[0]) { + char *dst=sbat+strlen(sbat); + snprintf(dst,STUN_MAX_REALM_SIZE*2," admin session realm: %s
\r\n",as->as_realm); + } else if(as->as_eff_realm[0]) { + char *dst=sbat+strlen(sbat); + snprintf(dst,STUN_MAX_REALM_SIZE*2," admin session realm: %s
\r\n",as->as_eff_realm); + } + } + } + return sbat; +} + static int wrong_html_name(const char* s) { int ret = 0; @@ -1464,7 +1487,9 @@ static char* current_realm(void) { } static char* current_eff_realm(void) { - if(current_socket && current_socket->special_session && ((struct admin_session*)current_socket->special_session)->as_ok) { + char* r = current_realm(); + if(r && r[0]) return r; + else if(current_socket && current_socket->special_session && ((struct admin_session*)current_socket->special_session)->as_ok) { return ((struct admin_session*)current_socket->special_session)->as_eff_realm; } else { static char bad_eff_realm[1025] = "_ERROR:UNKNOWN_REALM__"; @@ -1493,6 +1518,39 @@ static void https_cancel_session(const char* ssid) } } +static void https_print_top_page_header(struct str_buffer *sb) +{ + str_buffer_append(sb,"\r\n\r\n \r\n "); + str_buffer_append(sb,admin_title); + str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,bold_admin_title); +} + +static void https_print_page_header(struct str_buffer *sb) +{ + https_print_top_page_header(sb); + str_buffer_append(sb,home_link); + str_buffer_append(sb,"
\r\n"); +} + +static void https_finish_page(struct str_buffer *sb, ioa_socket_handle s) +{ + str_buffer_append(sb,"\r\n\r\n"); + + send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); + send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); + send_str_from_ioa_socket_tcp(s,"\r\n"); + send_str_from_ioa_socket_tcp(s,get_http_date_header()); + send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); + + send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); + + send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); + send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); + + str_buffer_free(sb); +} + static AS_FORM get_form(const char* path) { if(path) { size_t i = 0; @@ -1511,10 +1569,8 @@ static void write_https_logon_page(ioa_socket_handle s) struct str_buffer* sb = str_buffer_new(); - str_buffer_append(sb,"\r\n\r\n \r\n "); - str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); - str_buffer_append(sb,bold_admin_title); + https_print_top_page_header(sb); + str_buffer_append(sb,"

\r\n"); str_buffer_append(sb,"

\r\n"); str_buffer_append(sb,"\r\n"); - str_buffer_append(sb,"\r\n \r\n\r\n"); - struct str_buffer* sb_http = str_buffer_new(); - - str_buffer_append(sb_http,"HTTP/1.1 200 OK\r\nServer: "); - str_buffer_append(sb_http,TURN_SOFTWARE); - str_buffer_append(sb_http,"\r\n"); - str_buffer_append(sb_http,get_http_date_header()); - str_buffer_append(sb_http,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); - str_buffer_append_sz(sb_http,str_buffer_get_str_len(sb)); - str_buffer_append(sb_http,"\r\n\r\n"); - str_buffer_append(sb_http,str_buffer_get_str(sb)); - - str_buffer_free(sb); - - send_data_from_ioa_socket_tcp(s, str_buffer_get_str(sb_http), str_buffer_get_str_len(sb_http)); - - str_buffer_free(sb_http); + https_finish_page(sb,s); } } @@ -1556,12 +1596,7 @@ static void write_https_home_page(ioa_socket_handle s) struct str_buffer* sb = str_buffer_new(); - str_buffer_append(sb,"\r\n\r\n \r\n "); - str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); - str_buffer_append(sb,bold_admin_title); - str_buffer_append(sb,"

\r\n"); - str_buffer_append(sb,logout_link); + https_print_page_header(sb); str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,"\r\n \r\n\r\n"); - - send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); - send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); - send_str_from_ioa_socket_tcp(s,"\r\n"); - send_str_from_ioa_socket_tcp(s,get_http_date_header()); - send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); - - send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); - - send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); - send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); - - str_buffer_free(sb); + https_finish_page(sb,s); } } } @@ -1853,12 +1875,8 @@ static void write_pc_page(ioa_socket_handle s) struct str_buffer* sb = str_buffer_new(); - str_buffer_append(sb,"\r\n\r\n \r\n "); - str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); - str_buffer_append(sb,bold_admin_title); - str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,home_link); + https_print_page_header(sb); + str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,"Configuration Parameters:

\r\n"); str_buffer_append(sb,"\r\n"); @@ -2082,20 +2100,9 @@ static void write_pc_page(ioa_socket_handle s) } } - str_buffer_append(sb,"\r\n
ParameterValue
\r\n\r\n"); + str_buffer_append(sb,"\r\n
\r\n"); - send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); - send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); - send_str_from_ioa_socket_tcp(s,"\r\n"); - send_str_from_ioa_socket_tcp(s,get_http_date_header()); - send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); - - send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); - - send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); - send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); - - str_buffer_free(sb); + https_finish_page(sb,s); } } } @@ -2273,13 +2280,7 @@ static void write_ps_page(ioa_socket_handle s, const char* client_protocol, cons struct str_buffer* sb = str_buffer_new(); - str_buffer_append(sb,"\r\n\r\n \r\n "); - str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); - str_buffer_append(sb,bold_admin_title); - str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,home_link); - str_buffer_append(sb,"
\r\n"); + https_print_page_header(sb); str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,"\r\n\r\n"); - - send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); - send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); - send_str_from_ioa_socket_tcp(s,"\r\n"); - send_str_from_ioa_socket_tcp(s,get_http_date_header()); - send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); - - send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); - - send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); - send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); - - str_buffer_free(sb); + https_finish_page(sb,s); } } } @@ -2408,13 +2396,7 @@ static void write_users_page(ioa_socket_handle s, const u08bits *add_user, const struct str_buffer* sb = str_buffer_new(); - str_buffer_append(sb,"\r\n\r\n \r\n "); - str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); - str_buffer_append(sb,bold_admin_title); - str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,home_link); - str_buffer_append(sb,"
\r\n"); + https_print_page_header(sb); str_buffer_append(sb,"\r\n"); - str_buffer_append(sb,"\r\n\r\n"); - - send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); - send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); - send_str_from_ioa_socket_tcp(s,"\r\n"); - send_str_from_ioa_socket_tcp(s,get_http_date_header()); - send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); - - send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); - - send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); - send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); - - str_buffer_free(sb); + https_finish_page(sb,s); } } } @@ -2580,13 +2549,7 @@ static void write_shared_secrets_page(ioa_socket_handle s, const char* add_secre struct str_buffer* sb = str_buffer_new(); - str_buffer_append(sb,"\r\n\r\n \r\n "); - str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); - str_buffer_append(sb,bold_admin_title); - str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,home_link); - str_buffer_append(sb,"
\r\n"); + https_print_page_header(sb); str_buffer_append(sb,"\r\n"); - str_buffer_append(sb,"\r\n\r\n"); - - send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); - send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); - send_str_from_ioa_socket_tcp(s,"\r\n"); - send_str_from_ioa_socket_tcp(s,get_http_date_header()); - send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); - - send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); - - send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); - send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); - - str_buffer_free(sb); + https_finish_page(sb,s); } } } @@ -2731,13 +2681,7 @@ static void write_origins_page(ioa_socket_handle s, const char* add_origin, cons struct str_buffer* sb = str_buffer_new(); - str_buffer_append(sb,"\r\n\r\n \r\n "); - str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); - str_buffer_append(sb,bold_admin_title); - str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,home_link); - str_buffer_append(sb,"
\r\n"); + https_print_page_header(sb); str_buffer_append(sb,"\r\n"); - str_buffer_append(sb,"\r\n\r\n"); - - send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); - send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); - send_str_from_ioa_socket_tcp(s,"\r\n"); - send_str_from_ioa_socket_tcp(s,get_http_date_header()); - send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); - - send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); - - send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); - send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); - - str_buffer_free(sb); + https_finish_page(sb,s); } } } @@ -2911,16 +2842,11 @@ static void write_https_oauth_show_keys(ioa_socket_handle s, const char* kid) struct str_buffer* sb = str_buffer_new(); - str_buffer_append(sb,"\r\n\r\n \r\n "); - str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); - str_buffer_append(sb,bold_admin_title); - str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,"
back to oauth list
\r\n"); - str_buffer_append(sb,home_link); - str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"\">back to oauth list

\r\n"); if(kid && kid[0]) { const turn_dbdriver_t * dbd = get_dbdriver(); @@ -2981,20 +2907,7 @@ static void write_https_oauth_show_keys(ioa_socket_handle s, const char* kid) } } - str_buffer_append(sb,"\r\n\r\n"); - - send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); - send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); - send_str_from_ioa_socket_tcp(s,"\r\n"); - send_str_from_ioa_socket_tcp(s,get_http_date_header()); - send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); - - send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); - - send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); - send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); - - str_buffer_free(sb); + https_finish_page(sb,s); } } } @@ -3015,13 +2928,7 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con struct str_buffer* sb = str_buffer_new(); - str_buffer_append(sb,"\r\n\r\n \r\n "); - str_buffer_append(sb,admin_title); - str_buffer_append(sb,"\r\n \r\n \r\n "); - str_buffer_append(sb,bold_admin_title); - str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,home_link); - str_buffer_append(sb,"
\r\n"); + https_print_page_header(sb); { str_buffer_append(sb,"\r\n"); - str_buffer_append(sb,"\r\n\r\n"); - - send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); - send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); - send_str_from_ioa_socket_tcp(s,"\r\n"); - send_str_from_ioa_socket_tcp(s,get_http_date_header()); - send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); - - send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); - - send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); - send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); - - str_buffer_free(sb); + https_finish_page(sb,s); } } } From b6f1eb9dc362a8543bdbcef6cbaca74336f08754 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 24 Jan 2015 08:10:21 +0000 Subject: [PATCH 454/805] dates adjusted --- ChangeLog | 2 +- rpm/turnserver.spec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 208138e2..50f7dd59 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -1/12/2015 Oleg Moskalenko +1/24/2015 Oleg Moskalenko Version 4.4.1.1 'Ardee West': - https admin server; - SSLv2 support removed (security concern fixed); diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 95a884c9..9912ff89 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -288,7 +288,7 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Sat Jan 10 2015 Oleg Moskalenko +* Sat Jan 24 2015 Oleg Moskalenko - Sync to 4.4.1.1 * Wed Dec 24 2014 Oleg Moskalenko - Sync to 4.3.3.1 From 4e8b95bbb0946b7e2d5fc1e88a27166c65b64fb7 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 24 Jan 2015 08:21:32 +0000 Subject: [PATCH 455/805] c++ compilation errors fixed --- src/apps/relay/dbdrivers/dbd_mongo.c | 8 ++++---- src/apps/relay/dbdrivers/dbd_mysql.c | 4 ++-- src/apps/relay/dbdrivers/dbd_pgsql.c | 4 ++-- src/apps/relay/dbdrivers/dbd_redis.c | 4 ++-- src/apps/relay/dbdrivers/dbd_sqlite.c | 4 ++-- src/apps/relay/dbdrivers/dbdriver.h | 2 +- src/apps/relay/http_server.c | 6 ++++-- src/apps/relay/ns_ioalib_engine_impl.c | 6 +++++- 8 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index cefe3af0..da28fe69 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -714,7 +714,7 @@ static int mongo_set_secret(u08bits *secret, u08bits *realm) { } } -static int mongo_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int delete) +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); @@ -733,7 +733,7 @@ static int mongo_set_permission_ip(const char *kind, u08bits *realm, const char* bson_init(&query); BSON_APPEND_UTF8(&query, "realm", (const char *)realm); bson_init(&doc); - if(delete) { + if(del) { bson_append_document_begin(&doc, "$pull", -1, &child); } else { bson_append_document_begin(&doc, "$addToSet", -1, &child); @@ -741,9 +741,9 @@ static int mongo_set_permission_ip(const char *kind, u08bits *realm, const char* BSON_APPEND_UTF8(&child, sub_collection_name, (const char *)ip); bson_append_document_end(&doc, &child); - mongoc_update_flags_t flags = 0; + mongoc_update_flags_t flags = MONGOC_UPDATE_NONE; - if(delete) { + if(del) { flags = MONGOC_UPDATE_MULTI_UPDATE; } else { flags = MONGOC_UPDATE_UPSERT; diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index ceaa96a9..068cc048 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -724,7 +724,7 @@ 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 delete) +static int mysql_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int del) { int ret = -1; @@ -737,7 +737,7 @@ static int mysql_set_permission_ip(const char *kind, u08bits *realm, const char* MYSQL * myc = get_mydb_connection(); if (myc) { - if(delete) { + 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); diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index 2141a6ca..c94ab1de 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -490,7 +490,7 @@ static int pgsql_set_secret(u08bits *secret, u08bits *realm) { return ret; } -static int pgsql_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int delete) +static int pgsql_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int del) { int ret = -1; @@ -505,7 +505,7 @@ static int pgsql_set_permission_ip(const char *kind, u08bits *realm, const char* if (pqc) { - if(delete) { + 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); diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index 4f100af6..0f3e44ec 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -827,7 +827,7 @@ 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 delete) +static int redis_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int del) { int ret = -1; @@ -840,7 +840,7 @@ static int redis_set_permission_ip(const char *kind, u08bits *realm, const char* if (rc) { char s[TURN_LONG_STRING_SIZE]; - if(delete) { + 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); diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index f86b559d..7815fe7f 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -976,7 +976,7 @@ 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 delete) +static int sqlite_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int del) { int ret = -1; @@ -995,7 +995,7 @@ static int sqlite_set_permission_ip(const char *kind, u08bits *realm, const char sqlite_lock(1); - if(delete) { + 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); diff --git a/src/apps/relay/dbdrivers/dbdriver.h b/src/apps/relay/dbdrivers/dbdriver.h index 4aaa566a..5b36aad2 100644 --- a/src/apps/relay/dbdrivers/dbdriver.h +++ b/src/apps/relay/dbdrivers/dbdriver.h @@ -63,7 +63,7 @@ typedef struct _turn_dbdriver_t { 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 delete); + 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); diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index 39c98345..7b0b0b8f 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -104,7 +104,7 @@ const char* get_http_date_header() static struct headers_list * post_parse(char *data, size_t data_len) { while((*data=='\r')||(*data=='\n')) ++data; - char *post_data = calloc(data_len + 1, sizeof(char)); + 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); @@ -114,7 +114,9 @@ static struct headers_list * post_parse(char *data, size_t data_len) char *vmarker = NULL; char *key = strtok_r(fsplit, "=", &vmarker); char *value = strtok_r(NULL, "=", &vmarker); - value = value ? value : ""; + char empty[1]; + empty[0]=0; + value = value ? value : empty; value = evhttp_decode_uri(value); char *p = value; while (*p) { diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index c6a12342..34027854 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -3257,7 +3257,11 @@ int send_data_from_ioa_socket_tcp(ioa_socket_handle s, const void *data, size_t int send_str_from_ioa_socket_tcp(ioa_socket_handle s, const void *data) { - return send_data_from_ioa_socket_tcp(s, data, strlen(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) From e79e4279ad677d2bf71cade9f9a7778dc86729d8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 24 Jan 2015 08:40:10 +0000 Subject: [PATCH 456/805] cygwin warnings fixed --- src/client/ns_turn_msg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 464a581f..fed7d46f 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -615,7 +615,7 @@ static inline int sheadof(const char *head, const char* full, int ignore_case) { while(*head) { if(*head != *full) { - if(ignore_case && (tolower(*head)==tolower(*full))) { + if(ignore_case && (tolower((int)*head)==tolower((int)*full))) { //OK } else { return 0; From f29f111fdc707d1690a6fd4bb913166cf646030d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 24 Jan 2015 09:31:07 +0000 Subject: [PATCH 457/805] adjustments for old browsers --- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/turn_admin_server.c | 73 +++++++++++++++++++++-------- 2 files changed, 54 insertions(+), 19 deletions(-) diff --git a/examples/var/db/turndb b/examples/var/db/turndb index 847a60014a13228733709067e82c26cabba033e9..bd93f071598d22131933274dbff1ab2600efefe8 100644 GIT binary patch delta 51 zcmZqJz}T>Xae_4CjEOSNtTPyNA4zXaS#8al#k`tXcVpvMrpcW4s*Jpw_3f9i0I4g^ GIwAna{}8?a delta 51 zcmZqJz}T>Xae_4C^ocUgtkW5EAE|9jS#8a#%bdl$dSl~PrpcW4s*GHl_3f9i0I4g^ GIwAnaY!JZ! diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 96aed71d..f4934c8d 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1429,7 +1429,6 @@ static struct form_name form_names[] = { #define admin_title "TURN Server (https admin connection)" #define __bold_admin_title "TURN Server
https admin connection
\r\n" #define bold_admin_title get_bold_admin_title() -static const char* home_link = "
home page
\r\n
logout
\r\n"; static ioa_socket_handle current_socket = NULL; @@ -1529,7 +1528,11 @@ static void https_print_top_page_header(struct str_buffer *sb) static void https_print_page_header(struct str_buffer *sb) { https_print_top_page_header(sb); - str_buffer_append(sb,home_link); + str_buffer_append(sb,"
home page
\r\n
logout
\r\n"); str_buffer_append(sb,"
\r\n"); } @@ -1609,38 +1612,65 @@ static void write_https_home_page(ioa_socket_handle s) str_buffer_append(sb,current_eff_realm()); str_buffer_append(sb,"\""); if(!is_superuser()) { - str_buffer_append(sb," disabled "); + str_buffer_append(sb," disabled >"); + } else { + str_buffer_append(sb,"> "); } - str_buffer_append(sb,">
"); - str_buffer_append(sb,"
"); + + str_buffer_append(sb,"
"); + str_buffer_append(sb,"?"); + str_buffer_append(sb,HR_REALM); + str_buffer_append(sb,"="); + str_buffer_append(sb,current_eff_realm()); + str_buffer_append(sb,"\">Configuration Parameters"); - str_buffer_append(sb,"
"); + str_buffer_append(sb,"\">TURN Sessions"); - str_buffer_append(sb,"
"); + str_buffer_append(sb,"?"); + str_buffer_append(sb,HR_REALM); + str_buffer_append(sb,"="); + str_buffer_append(sb,current_eff_realm()); + str_buffer_append(sb,"\">Users"); - str_buffer_append(sb,"
"); + str_buffer_append(sb,"?"); + str_buffer_append(sb,HR_REALM); + str_buffer_append(sb,"="); + str_buffer_append(sb,current_eff_realm()); + str_buffer_append(sb,"\">Shared Secrets (for TURN REST API)"); - str_buffer_append(sb,"
"); + str_buffer_append(sb,"?"); + str_buffer_append(sb,HR_REALM); + str_buffer_append(sb,"="); + str_buffer_append(sb,current_eff_realm()); + str_buffer_append(sb,"\">Origins"); if(is_superuser()) { - str_buffer_append(sb,"
"); + str_buffer_append(sb,"
oAuth keys"); } str_buffer_append(sb,"\r\n"); @@ -3728,8 +3758,13 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) handle_logout_request(s,hr); write_https_logon_page(s); break; - default: - write_https_home_page(s); + default: { + const char *realm0 = get_http_header_value(hr, HR_REALM, current_realm()); + if(!is_superuser()) + realm0 = current_realm(); + STRCPY(current_eff_realm(),realm0); + write_https_home_page(s); + } }; free_http_request(hr); } From da0f380b1895e4d839f96be65778395154b0e059 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 24 Jan 2015 10:43:56 +0000 Subject: [PATCH 458/805] cosmetics --- src/apps/relay/dbdrivers/dbd_mongo.c | 15 ++++--- src/apps/relay/dbdrivers/dbd_mysql.c | 7 ++-- src/apps/relay/dbdrivers/dbd_pgsql.c | 7 ++-- src/apps/relay/dbdrivers/dbd_redis.c | 15 ++++--- src/apps/relay/dbdrivers/dbd_sqlite.c | 14 ++++--- src/apps/relay/dbdrivers/dbdriver.h | 2 +- src/apps/relay/turn_admin_server.c | 56 +++++++++++++++++---------- src/apps/relay/userdb.c | 2 +- 8 files changed, 73 insertions(+), 45 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index da28fe69..e3d50fbe 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -1318,7 +1318,7 @@ static int mongo_del_admin_user(const u08bits *usname) return ret; } -static int mongo_list_admin_users(void) +static int mongo_list_admin_users(int no_print) { const char * collection_name = "admin_user"; mongoc_collection_t * collection = mongo_get_collection(collection_name); @@ -1352,6 +1352,7 @@ static int mongo_list_admin_users(void) 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); @@ -1360,16 +1361,18 @@ static int mongo_list_admin_users(void) 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); } - if(realm && *realm) { - printf("%s[%s]\n", value, realm); - } else { - printf("%s\n", value); + ++ret; + if(!no_print) { + if(realm && *realm) { + printf("%s[%s]\n", value, realm); + } else { + printf("%s\n", value); + } } } } } mongoc_cursor_destroy(cursor); - ret = 0; } mongoc_collection_destroy(collection); bson_destroy(&query); diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 068cc048..464d5353 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -1189,7 +1189,7 @@ static int mysql_del_admin_user(const u08bits *usname) return ret; } -static int mysql_list_admin_users(void) +static int mysql_list_admin_users(int no_print) { int ret = -1; char statement[TURN_LONG_STRING_SIZE]; @@ -1207,12 +1207,14 @@ static int mysql_list_admin_users(void) } 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 { - if(row[0]) { + ++ret; + if(row[0] && !no_print) { if(row[1] && row[1][0]) { printf("%s[%s]\n",row[0],row[1]); } else { @@ -1221,7 +1223,6 @@ static int mysql_list_admin_users(void) } } } - ret = 0; } if(mres) diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index c94ab1de..d107af9e 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -920,7 +920,7 @@ static int pgsql_del_admin_user(const u08bits *usname) return ret; } -static int pgsql_list_admin_users(void) +static int pgsql_list_admin_users(int no_print) { int ret = -1; char statement[TURN_LONG_STRING_SIZE]; @@ -934,9 +934,11 @@ static int pgsql_list_admin_users(void) 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\r\n"); } -static void https_finish_page(struct str_buffer *sb, ioa_socket_handle s) +static void https_finish_page(struct str_buffer *sb, ioa_socket_handle s, int cclose) { str_buffer_append(sb,"\r\n\r\n"); @@ -1544,6 +1544,9 @@ static void https_finish_page(struct str_buffer *sb, ioa_socket_handle s) send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); send_str_from_ioa_socket_tcp(s,"\r\n"); send_str_from_ioa_socket_tcp(s,get_http_date_header()); + if(cclose) { + send_str_from_ioa_socket_tcp(s,"Connection: close"); + } send_str_from_ioa_socket_tcp(s,"Content-Type: text/html; charset=UTF-8\r\nContent-Length: "); send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); @@ -1574,18 +1577,31 @@ static void write_https_logon_page(ioa_socket_handle s) https_print_top_page_header(sb); - str_buffer_append(sb,"

\r\n"); - str_buffer_append(sb,"\r\n"); - str_buffer_append(sb,"
Admin user information: user name:

password:


\r\n"); - str_buffer_append(sb,"\r\n"); + int we_have_admin_users = 0; + const turn_dbdriver_t * dbd = get_dbdriver(); + if (dbd && dbd->list_admin_users) { + int ausers = dbd->list_admin_users(1); + if(ausers>0) { + we_have_admin_users = 1; + } + } - https_finish_page(sb,s); + if(!we_have_admin_users) { + str_buffer_append(sb,"
To use the HTTPS admin connection, you have to set the database table admin_user with the admin user accounts.
\r\n"); + } else { + str_buffer_append(sb,"

\r\n"); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
Admin user information: user name:

password:


\r\n"); + str_buffer_append(sb,"
\r\n"); + } + + https_finish_page(sb,s,!we_have_admin_users); } } @@ -1676,7 +1692,7 @@ static void write_https_home_page(ioa_socket_handle s) str_buffer_append(sb,"\r\n"); str_buffer_append(sb,"\r\n"); - https_finish_page(sb,s); + https_finish_page(sb,s,0); } } } @@ -2132,7 +2148,7 @@ static void write_pc_page(ioa_socket_handle s) str_buffer_append(sb,"\r\n\r\n"); - https_finish_page(sb,s); + https_finish_page(sb,s,0); } } } @@ -2364,7 +2380,7 @@ static void write_ps_page(ioa_socket_handle s, const char* client_protocol, cons str_buffer_append_sz(sb,total_sz); str_buffer_append(sb,"
\r\n"); - https_finish_page(sb,s); + https_finish_page(sb,s,0); } } } @@ -2517,7 +2533,7 @@ static void write_users_page(ioa_socket_handle s, const u08bits *add_user, const str_buffer_append_sz(sb,total_sz); str_buffer_append(sb,"
\r\n"); - https_finish_page(sb,s); + https_finish_page(sb,s,0); } } } @@ -2651,7 +2667,7 @@ static void write_shared_secrets_page(ioa_socket_handle s, const char* add_secre str_buffer_append_sz(sb,total_sz); str_buffer_append(sb,"
\r\n"); - https_finish_page(sb,s); + https_finish_page(sb,s,0); } } } @@ -2784,7 +2800,7 @@ static void write_origins_page(ioa_socket_handle s, const char* add_origin, cons str_buffer_append_sz(sb,total_sz); str_buffer_append(sb,"
\r\n"); - https_finish_page(sb,s); + https_finish_page(sb,s,0); } } } @@ -2937,7 +2953,7 @@ static void write_https_oauth_show_keys(ioa_socket_handle s, const char* kid) } } - https_finish_page(sb,s); + https_finish_page(sb,s,0); } } } @@ -3173,7 +3189,7 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append_sz(sb,total_sz); str_buffer_append(sb,"
\r\n"); - https_finish_page(sb,s); + https_finish_page(sb,s,0); } } } diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 0fdda266..044bf747 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -775,7 +775,7 @@ static int list_users(u08bits *realm, int is_admin) if (dbd) { if(is_admin) { if(dbd->list_admin_users) { - (*dbd->list_admin_users)(); + (*dbd->list_admin_users)(0); } } else { if(dbd->list_users) { From 11becb068ccb942a608e7dfbceb2d2d3af96d236 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 24 Jan 2015 18:43:52 +0000 Subject: [PATCH 459/805] warnings fixed --- src/apps/relay/dbdrivers/dbd_sqlite.c | 28 +++++++++++++-------------- src/apps/relay/turn_admin_server.c | 12 ++++++------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 98d08484..7882e910 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -305,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 { @@ -355,15 +355,15 @@ static int sqlite_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,sec 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, 8)); + 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)); if(kids) { add_to_secrets_list(kids,key->kid); diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 7e4040c9..6bba4eb7 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -3355,7 +3355,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) const char *realm0 = get_http_header_value(hr, HR_REALM, current_realm()); if(!is_superuser()) realm0 = current_realm(); - STRCPY(current_eff_realm(),realm0); + strncpy(current_eff_realm(),realm0,STUN_MAX_REALM_SIZE); write_pc_page(s); } else { write_https_logon_page(s); @@ -3367,7 +3367,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) const char *realm0 = get_http_header_value(hr, HR_REALM, current_realm()); if(!is_superuser()) realm0 = current_realm(); - STRCPY(current_eff_realm(),realm0); + strncpy(current_eff_realm(),realm0,STUN_MAX_REALM_SIZE); const char* client_protocol = get_http_header_value(hr, HR_CLIENT_PROTOCOL, ""); @@ -3402,7 +3402,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) const char *realm0 = get_http_header_value(hr, HR_REALM, current_realm()); if(!is_superuser()) realm0 = current_realm(); - STRCPY(current_eff_realm(),realm0); + strncpy(current_eff_realm(),realm0,STUN_MAX_REALM_SIZE); } { @@ -3502,7 +3502,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) const char *realm0 = get_http_header_value(hr, HR_REALM, current_realm()); if(!is_superuser()) realm0 = current_realm(); - STRCPY(current_eff_realm(),realm0); + strncpy(current_eff_realm(),realm0,STUN_MAX_REALM_SIZE); } { @@ -3575,7 +3575,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) const char *realm0 = get_http_header_value(hr, HR_REALM, current_realm()); if(!is_superuser()) realm0 = current_realm(); - STRCPY(current_eff_realm(),realm0); + strncpy(current_eff_realm(),realm0,STUN_MAX_REALM_SIZE); } if(is_superuser()) { @@ -3778,7 +3778,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) const char *realm0 = get_http_header_value(hr, HR_REALM, current_realm()); if(!is_superuser()) realm0 = current_realm(); - STRCPY(current_eff_realm(),realm0); + strncpy(current_eff_realm(),realm0,STUN_MAX_REALM_SIZE); write_https_home_page(s); } }; From 425547b774c74851617c42ea406829457cc9823e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 24 Jan 2015 18:48:19 +0000 Subject: [PATCH 460/805] warnings fixed --- src/apps/relay/dbdrivers/dbd_mysql.c | 2 +- src/apps/relay/dbdrivers/dbd_pgsql.c | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 464d5353..ff665054 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -361,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; diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index d107af9e..cae1a3f1 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -167,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; } @@ -207,15 +207,15 @@ static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr int i = 0; for(i=0;iikm_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)); if(kids) { add_to_secrets_list(kids,key->kid); From 10f880c975fea61ec50cc179cbe67a35cf9b0a73 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 25 Jan 2015 03:38:10 +0000 Subject: [PATCH 461/805] docs updates --- INSTALL | 18 +++++++++++++++--- README.turnserver | 18 +++++++++++++++++- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 19 +++++++++++++++++-- man/man1/turnutils.1 | 2 +- 5 files changed, 51 insertions(+), 8 deletions(-) diff --git a/INSTALL b/INSTALL index 990dfbbb..1706efb4 100644 --- a/INSTALL +++ b/INSTALL @@ -1146,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 @@ -1154,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 @@ -1163,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). diff --git a/README.turnserver b/README.turnserver index 85087bb4..5fb0b495 100644 --- a/README.turnserver +++ b/README.turnserver @@ -822,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. ================================= diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index a5b34d3b..90d0a6a2 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "20 January 2015" "" "" +.TH TURN 1 "24 January 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 51c4d857..5657ca3c 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "20 January 2015" "" "" +.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 @@ -1075,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 diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 29cb1a9b..4ce6de03 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "20 January 2015" "" "" +.TH TURN 1 "24 January 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used From 66f46e4a4a230b92b826c76f0caef5e546385ba4 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 25 Jan 2015 04:54:12 +0000 Subject: [PATCH 462/805] docs updates --- ChangeLog | 4 ++-- STATUS | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 50f7dd59..7ac716ba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,8 @@ 1/24/2015 Oleg Moskalenko Version 4.4.1.1 'Ardee West': - https admin server; - - SSLv2 support removed (security concern fixed); - - The server-side short-term credentials mechanism support removed; + - 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; diff --git a/STATUS b/STATUS index d137195a..c3f1b1b3 100644 --- a/STATUS +++ b/STATUS @@ -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. From 5540622642a5477134cc79d2887f7026c066efdd Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 25 Jan 2015 08:18:41 +0000 Subject: [PATCH 463/805] docs change --- examples/scripts/readme.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/examples/scripts/readme.txt b/examples/scripts/readme.txt index f97308e5..4be04b5e 100644 --- a/examples/scripts/readme.txt +++ b/examples/scripts/readme.txt @@ -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. + From a1a47413942dd789f4009fdf544a6daef12bed87 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 25 Jan 2015 10:08:37 +0000 Subject: [PATCH 464/805] a script fix --- turndb/testredisdbsetup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/turndb/testredisdbsetup.sh b/turndb/testredisdbsetup.sh index 3d9ad825..1fe32ece 100755 --- a/turndb/testredisdbsetup.sh +++ b/turndb/testredisdbsetup.sh @@ -7,8 +7,8 @@ redis-cli < Date: Wed, 28 Jan 2015 07:00:32 +0000 Subject: [PATCH 465/805] email fixed --- AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 9b07296e..07301060 100644 --- a/AUTHORS +++ b/AUTHORS @@ -36,7 +36,7 @@ Po-sheng Lin : Libevent dependencies cleaning (since v2.0.1.1); -Peter Dunkley : +Peter Dunkley : CentOS/Fedora port (since v2.6.6.1) From e212b7e961a7648051cd5cb91b00d5617763c2cf Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 31 Jan 2015 07:14:06 +0000 Subject: [PATCH 466/805] ip address resolution fix --- ChangeLog | 4 ++++ rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/client/ns_turn_ioaddr.c | 12 +++++++----- src/ns_turn_defs.h | 2 +- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7ac716ba..9a69efbc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +1/31/2015 Oleg Moskalenko +Version 4.4.1.2 'Ardee West': + - IP address resolution fix; + 1/24/2015 Oleg Moskalenko Version 4.4.1.1 'Ardee West': - https admin server; diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 5121d85b..c5c3ea19 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.4.1.1 +TURNVERSION=4.4.1.2 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 9912ff89..747a3562 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.4.1.1 +Version: 4.4.1.2 Release: 0%{dist} Summary: Coturn TURN Server @@ -288,6 +288,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Sat Jan 31 2015 Oleg Moskalenko + - Sync to 4.4.1.2 * Sat Jan 24 2015 Oleg Moskalenko - Sync to 4.4.1.1 * Wed Dec 24 2014 Oleg Moskalenko diff --git a/src/client/ns_turn_ioaddr.c b/src/client/ns_turn_ioaddr.c index 60ccd3d5..f86ede17 100644 --- a/src/client/ns_turn_ioaddr.c +++ b/src/client/ns_turn_ioaddr.c @@ -245,24 +245,26 @@ int make_ioa_addr(const u08bits* saddr0, int port, ioa_addr *addr) { beg_af: - while(!found && addr_result) { + while(addr_result) { if(addr_result->ai_family == family) { - ns_bcopy(addr_result->ai_addr, addr, addr_result->ai_addrlen); if (addr_result->ai_family == AF_INET) { + ns_bcopy(addr_result->ai_addr, addr, addr_result->ai_addrlen); addr->s4.sin_port = nswap16(port); #if defined(TURN_HAS_SIN_LEN) /* tested when configured */ addr->s4.sin_len = sizeof(struct sockaddr_in); #endif + found = 1; + break; } else if (addr_result->ai_family == AF_INET6) { + ns_bcopy(addr_result->ai_addr, addr, addr_result->ai_addrlen); addr->s6.sin6_port = nswap16(port); #if defined(SIN6_LEN) /* this define is required by IPv6 if used */ addr->s6.sin6_len = sizeof(struct sockaddr_in6); #endif - } else { - continue; + found = 1; + break; } - found = 1; } addr_result = addr_result->ai_next; diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 3cedbe84..570e1fdc 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.4.1.1" +#define TURN_SERVER_VERSION "4.4.1.2" #define TURN_SERVER_VERSION_NAME "Ardee West" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From caff982f26ea9bb41a7dc87636bf90e3b039986c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 31 Jan 2015 07:20:41 +0000 Subject: [PATCH 467/805] minor fixes --- examples/scripts/basic/relay.sh | 2 +- examples/scripts/longtermsecure/secure_relay.sh | 2 +- src/client/ns_turn_ioaddr.c | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/scripts/basic/relay.sh b/examples/scripts/basic/relay.sh index ee597c73..4b3483eb 100755 --- a/examples/scripts/basic/relay.sh +++ b/examples/scripts/basic/relay.sh @@ -23,7 +23,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 -v --syslog -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 --no-tls --no-dtls --no-auth $@ +PATH="bin:../bin:../../bin:${PATH}" turnserver -v --syslog -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 --no-tls --no-dtls --no-auth --db="var/db/turndb" $@ diff --git a/examples/scripts/longtermsecure/secure_relay.sh b/examples/scripts/longtermsecure/secure_relay.sh index 4fd53c88..7bcb5ac1 100755 --- a/examples/scripts/longtermsecure/secure_relay.sh +++ b/examples/scripts/longtermsecure/secure_relay.sh @@ -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 $@ +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 --db="var/db/turndb" $@ diff --git a/src/client/ns_turn_ioaddr.c b/src/client/ns_turn_ioaddr.c index f86ede17..685b8755 100644 --- a/src/client/ns_turn_ioaddr.c +++ b/src/client/ns_turn_ioaddr.c @@ -324,14 +324,14 @@ int make_ioa_addr_from_full_string(const u08bits* saddr, int default_port, ioa_a int ret = -1; int port = 0; - char* s = strdup((const char*)saddr); + char* s = turn_strdup((const char*)saddr); char *sa = get_addr_string_and_port(s,&port); if(sa) { if(port<1) port = default_port; ret = make_ioa_addr((u08bits*)sa,port,addr); } - free(s); + turn_free(s,strlen(s)+1); return ret; } @@ -511,10 +511,10 @@ static size_t msz = 0; void ioa_addr_add_mapping(ioa_addr *apub, ioa_addr *apriv) { size_t new_size = msz + sizeof(ioa_addr*); - public_addrs = (ioa_addr**)realloc(public_addrs, new_size); - private_addrs = (ioa_addr**)realloc(private_addrs, new_size); - public_addrs[mcount]=(ioa_addr*)malloc(sizeof(ioa_addr)); - private_addrs[mcount]=(ioa_addr*)malloc(sizeof(ioa_addr)); + public_addrs = (ioa_addr**)turn_realloc(public_addrs, msz, new_size); + private_addrs = (ioa_addr**)turn_realloc(private_addrs, msz, new_size); + public_addrs[mcount]=(ioa_addr*)turn_malloc(sizeof(ioa_addr)); + private_addrs[mcount]=(ioa_addr*)turn_malloc(sizeof(ioa_addr)); addr_cpy(public_addrs[mcount],apub); addr_cpy(private_addrs[mcount],apriv); ++mcount; From ccf9394ea9a5125713ab4e8138802f8941fb2e16 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 31 Jan 2015 07:24:58 +0000 Subject: [PATCH 468/805] cosmetics --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 9a69efbc..11674133 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ 1/31/2015 Oleg Moskalenko Version 4.4.1.2 'Ardee West': - - IP address resolution fix; + - hostname-to-IP-address resolution fix; 1/24/2015 Oleg Moskalenko Version 4.4.1.1 'Ardee West': From 3c40c14f40b1f382e7fac9dff548865358cd8655 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 31 Jan 2015 23:25:45 +0000 Subject: [PATCH 469/805] working on new dual-allocation implementation --- ChangeLog | 2 + TODO | 4 +- src/apps/common/stun_buffer.c | 4 +- src/apps/common/stun_buffer.h | 2 +- src/apps/uclient/mainuclient.c | 4 ++ src/apps/uclient/startuclient.c | 25 +++---- src/client++/TurnMsgLib.h | 4 +- src/client/ns_turn_msg.c | 109 +++++++++++++++++++++++------- src/client/ns_turn_msg.h | 5 +- src/client/ns_turn_msg_defs.h | 6 +- src/client/ns_turn_msg_defs_new.h | 5 ++ src/server/ns_turn_server.c | 45 +++++++++--- 12 files changed, 155 insertions(+), 60 deletions(-) diff --git a/ChangeLog b/ChangeLog index 11674133..889630d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,8 @@ 1/31/2015 Oleg Moskalenko Version 4.4.1.2 'Ardee West': - hostname-to-IP-address resolution fix; + - SSODA updates according to turnbis specs; + - TRANSPORT attribute handling fixed; 1/24/2015 Oleg Moskalenko Version 4.4.1.1 'Ardee West': diff --git a/TODO b/TODO index 5fe9a166..cc38d831 100644 --- a/TODO +++ b/TODO @@ -4,7 +4,7 @@ ================================================================== -1) Fedora official package (turnserver or coturn ? TBD). +1) Fedora official package. 2) MS Windows support. @@ -90,7 +90,7 @@ ================================================================== -nope +1) Peer for TCP relay. ================================================================== diff --git a/src/apps/common/stun_buffer.c b/src/apps/common/stun_buffer.c index 09990e65..c4ee5754 100644 --- a/src/apps/common/stun_buffer.c +++ b/src/apps/common/stun_buffer.c @@ -153,8 +153,8 @@ int stun_is_channel_message(stun_buffer* buf, u16bits* chnumber, int is_padding_ /////////////////////////////////////////////////////////////////////////////// -int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int af4, int af6, u08bits transport, int mobile) { - return stun_set_allocate_request_str(buf->buf, (size_t*)(&(buf->len)), lifetime, af4, af6, transport, mobile); +int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int af4, int af6, u08bits transport, int mobile, const char *rt, int ep) { + return stun_set_allocate_request_str(buf->buf, (size_t*)(&(buf->len)), lifetime, af4, af6, transport, mobile, rt, ep); } int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid, diff --git a/src/apps/common/stun_buffer.h b/src/apps/common/stun_buffer.h index 0d3e3608..fe7dc256 100644 --- a/src/apps/common/stun_buffer.h +++ b/src/apps/common/stun_buffer.h @@ -101,7 +101,7 @@ int stun_is_channel_message(stun_buffer* buf, u16bits* chnumber, int is_padding_ /////////////////////////////////////////////////////////////// -int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int af4, int af6, u08bits transport, int mobile); +int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int af4, int af6, u08bits transport, int mobile, const char* rt, int ep); int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid, const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2, const ioa_addr *reflexive_addr, diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 3c7fa867..a794323b 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -392,6 +392,10 @@ int main(int argc, char **argv) } } + if(dual_allocation) { + no_rtcp = 1; + } + if(g_use_auth_secret_with_timestamp) { { diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 54da33c6..8019df82 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -370,39 +370,30 @@ static int clnet_allocate(int verbose, reopen_socket = 0; } - if(current_reservation_token) { - af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT; - } - int af4 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4); int af6 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6); + uint64_t reservation_token = 0; + char* rt = NULL; + int ep = !no_rtcp; + if(!no_rtcp) { if (!never_allocate_rtcp && allocate_rtcp) { - af4 = 0; - af6 = 0; + reservation_token = ioa_ntoh64(current_reservation_token); + rt = (char*) (&reservation_token); } } if(!dos) - stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME, af4, af6, relay_transport, mobility); + stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME, af4, af6, relay_transport, mobility, rt, ep); else - stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME/3, af4, af6, relay_transport, mobility); + stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME/3, af4, af6, relay_transport, mobility, rt, ep); if(bps) stun_attr_add_bandwidth_str(request_message.buf, (size_t*)(&(request_message.len)), bps); if(dont_fragment) stun_attr_add(&request_message, STUN_ATTRIBUTE_DONT_FRAGMENT, NULL, 0); - if(!no_rtcp) { - if (!never_allocate_rtcp && allocate_rtcp) { - uint64_t reservation_token = ioa_ntoh64(current_reservation_token); - stun_attr_add(&request_message, STUN_ATTRIBUTE_RESERVATION_TOKEN, - (char*) (&reservation_token), 8); - } else { - stun_attr_add_even_port(&request_message, 1); - } - } add_origin(&request_message); diff --git a/src/client++/TurnMsgLib.h b/src/client++/TurnMsgLib.h index 008bbc05..a0332927 100644 --- a/src/client++/TurnMsgLib.h +++ b/src/client++/TurnMsgLib.h @@ -849,8 +849,8 @@ public: /** * Construct allocate request */ - void constructAllocateRequest(u32bits lifetime, int af4, int af6, u08bits transport, int mobile) { - stun_set_allocate_request_str(_buffer, &_sz, lifetime, af4, af6, transport, mobile); + void constructAllocateRequest(u32bits lifetime, int af4, int af6, u08bits transport, int mobile, const char* rt, int ep) { + stun_set_allocate_request_str(_buffer, &_sz, lifetime, af4, af6, transport, mobile, rt, ep); } /** diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index fed7d46f..5a463f18 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -737,7 +737,7 @@ int stun_get_message_len_str(u08bits *buf, size_t blen, int padding, size_t *app ////////// ALLOCATE /////////////////////////////////// int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int af4, int af6, - u08bits transport, int mobile) { + u08bits transport, int mobile, const char* rt, int ep) { stun_init_request_str(STUN_METHOD_ALLOCATE, buf, len); @@ -758,28 +758,49 @@ int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, i if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_LIFETIME,(u08bits*)(&field),sizeof(field))<0) return -1; } - if(mobile) { - if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_MOBILITY_TICKET,(const u08bits*)"",0)<0) return -1; - } + if(rt) { - //ADRESS-FAMILY - if (af4) { - u08bits field[4]; - field[0] = (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4; - field[1]=0; - field[2]=0; - field[3]=0; - if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1; - } + stun_attr_add_str(buf,len, STUN_ATTRIBUTE_RESERVATION_TOKEN, (const u08bits*) rt, 8); - if (af6) { - u08bits field[4]; - field[0] = (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; - field[1]=0; - field[2]=0; - field[3]=0; - if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1; - }; + } else { + + if(mobile) { + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_MOBILITY_TICKET,(const u08bits*)"",0)<0) return -1; + } + + if(ep) { + uint8_t value = 0x80; + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_EVEN_PORT,(const u08bits*)&value,1)<0) return -1; + } + + //ADRESS-FAMILY + if (af4 && !af6) { + u08bits field[4]; + field[0] = (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4; + field[1]=0; + field[2]=0; + field[3]=0; + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1; + } + + if (af6 && !af4) { + u08bits field[4]; + field[0] = (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; + field[1]=0; + field[2]=0; + field[3]=0; + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1; + } + + if (af4 && af6) { + u08bits field[4]; + field[0] = (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; + field[1]=0; + field[2]=0; + field[3]=0; + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY,field,sizeof(field))<0) return -1; + } + } return 0; } @@ -1246,7 +1267,7 @@ int stun_attr_get_first_addr_str(const u08bits *buf, size_t len, u16bits attr_ty while(attr) { if(stun_attr_is_addr(attr) && (attr_type == stun_attr_get_type(attr))) { if(stun_attr_get_addr_str(buf,len,attr,ca,default_addr)==0) { - return 0; + return 0; } } attr=stun_attr_get_next_str(buf,len,attr); @@ -1273,6 +1294,48 @@ int stun_attr_add_bandwidth_str(u08bits* buf, size_t *len, band_limit_t bps0) { return stun_attr_add_str(buf,len,STUN_ATTRIBUTE_NEW_BANDWIDTH,(u08bits*)(&field),sizeof(field)); } +int stun_attr_add_address_error_code(u08bits* buf, size_t *len, int requested_address_family, u08bits error_code) +{ + u08bits field[4]; + field[0]=(u08bits)requested_address_family; + field[1]=error_code; + field[2]=0; + field[3]=0; + return stun_attr_add_str(buf,len,STUN_ATTRIBUTE_ADDRESS_ERROR_CODE,field,sizeof(field)); +} + +int stun_attr_get_address_error_code(u08bits* buf, size_t len, int *requested_address_family, u08bits *error_code) +{ + if(requested_address_family) { + *requested_address_family = 0; + } + if(error_code) { + *error_code = 0; + } + if(buf && len) { + stun_attr_ref sar = stun_attr_get_first_by_type_str(buf, len, STUN_ATTRIBUTE_ADDRESS_ERROR_CODE); + if(sar) { + const u08bits* value = stun_attr_get_value(sar); + if(!value) { + return -1; + } else { + int alen = stun_attr_get_len(sar); + if(alen != 4) { + return -1; + } + if(requested_address_family) { + *requested_address_family = value[0]; + } + if(error_code) { + *error_code = value[1]; + } + return 0; + } + } + } + return 0; +} + u16bits stun_attr_get_first_channel_number_str(const u08bits *buf, size_t len) { stun_attr_ref attr=stun_attr_get_first_str(buf,len); @@ -1280,7 +1343,7 @@ u16bits stun_attr_get_first_channel_number_str(const u08bits *buf, size_t len) { if(stun_attr_get_type(attr) == STUN_ATTRIBUTE_CHANNEL_NUMBER) { u16bits ret = stun_attr_get_channel_number(attr); if(STUN_VALID_CHANNEL(ret)) { - return ret; + return ret; } } attr=stun_attr_get_next_str(buf,len,attr); diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 0d6d93ea..0b248bdc 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -151,9 +151,12 @@ int stun_attr_get_addr_str(const u08bits *buf, size_t len, stun_attr_ref attr, i int stun_attr_get_first_addr_str(const u08bits *buf, size_t len, u16bits attr_type, ioa_addr* ca, const ioa_addr *default_addr); int stun_attr_add_channel_number_str(u08bits* buf, size_t *len, u16bits chnumber); int stun_attr_add_bandwidth_str(u08bits* buf, size_t *len, band_limit_t bps); +int stun_attr_add_address_error_code(u08bits* buf, size_t *len, int requested_address_family, u08bits error_code); +/* return +1 if present, 0 if not, -1 if error: */ +int stun_attr_get_address_error_code(u08bits* buf, size_t len, int *requested_address_family, u08bits *error_code); u16bits stun_attr_get_first_channel_number_str(const u08bits *buf, size_t len); -int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int af4, int af6, u08bits transport, int mobile); +int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int af4, int af6, u08bits transport, int mobile, const char* rt, int ep); int stun_set_allocate_response_str(u08bits* buf, size_t *len, stun_tid* tid, const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2, const ioa_addr *reflexive_addr, diff --git a/src/client/ns_turn_msg_defs.h b/src/client/ns_turn_msg_defs.h index 5e22c251..f0a22ee6 100644 --- a/src/client/ns_turn_msg_defs.h +++ b/src/client/ns_turn_msg_defs.h @@ -123,11 +123,11 @@ /* RFC 5780 */ #define STUN_ATTRIBUTE_PADDING (0x0026) #define STUN_ATTRIBUTE_RESPONSE_PORT (0x0027) -#define STUN_ATTRIBUTE_RESPONSE_ORIGIN (0x802b) -#define STUN_ATTRIBUTE_OTHER_ADDRESS (0x802c) +#define STUN_ATTRIBUTE_RESPONSE_ORIGIN (0x802B) +#define STUN_ATTRIBUTE_OTHER_ADDRESS (0x802C) /* RFC 6062 ==>> */ -#define STUN_ATTRIBUTE_CONNECTION_ID (0x002a) +#define STUN_ATTRIBUTE_CONNECTION_ID (0x002A) /* <<== RFC 6062 */ #define STUN_VALID_CHANNEL(chn) ((chn)>=0x4000 && (chn)<=0x7FFF) diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 82909716..99709b3a 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -175,4 +175,9 @@ struct _encoded_oauth_token { typedef struct _encoded_oauth_token encoded_oauth_token; +////////////// SSODA /////////////////// + +#define STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY (0x8032) +#define STUN_ATTRIBUTE_ADDRESS_ERROR_CODE (0x8033) + #endif //__LIB_TURN_MSG_DEFS_NEW__ diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 6b9d8f8a..dd7f2b2d 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -914,6 +914,10 @@ static int handle_turn_allocate(turn_turnserver *server, int *err_code, const u08bits **reason, u16bits *unknown_attrs, u16bits *ua_num, ioa_net_data *in_buffer, ioa_network_buffer_handle nbh) { + + int err_code4 = 0; + int err_code6 = 0; + allocation* alloc = get_allocation_ss(ss); if (is_allocation_valid(alloc)) { @@ -1033,15 +1037,15 @@ static int handle_turn_allocate(turn_turnserver *server, const u08bits* value = stun_attr_get_value(sar); if (value) { transport = get_transport_value(value); - if (!transport || value[1] || value[2] || value[3]) { + if (!transport) { *err_code = 442; *reason = (const u08bits *)"Unsupported Transport Protocol"; } if((transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) && *(server->no_tcp_relay)) { - *err_code = 403; + *err_code = 442; *reason = (const u08bits *)"TCP Transport is not allowed by the TURN Server configuration"; } else if((transport == STUN_ATTRIBUTE_TRANSPORT_UDP_VALUE) && *(server->no_udp_relay)) { - *err_code = 403; + *err_code = 442; *reason = (const u08bits *)"UDP Transport is not allowed by the TURN Server configuration"; } else if(ss->client_socket) { SOCKET_TYPE cst = get_ioa_socket_type(ss->client_socket); @@ -1113,17 +1117,29 @@ static int handle_turn_allocate(turn_turnserver *server, } } break; + case STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY: case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY: { if(in_reservation_token) { *err_code = 400; *reason = (const u08bits *)"Address family attribute can not be used with reservation token request"; + } else if(af4 || af6) { + *err_code = 400; + *reason = (const u08bits *)"Extra address family attribute can not be used in the request"; } else { int af_req = stun_get_requested_address_family(sar); switch (af_req) { case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: - af4 = af_req; + if(attr_type == STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY) { + *err_code = 400; + *reason = (const u08bits *)"Invalid value of the additional address family attribute"; + } else { + af4 = af_req; + } break; case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: + if(attr_type == STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY) { + af4 = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4; + } af6 = af_req; break; default: @@ -1248,9 +1264,9 @@ static int handle_turn_allocate(turn_turnserver *server, } } } else { - int err_code4 = 0; const u08bits *reason4 = NULL; - if(af4) { + const u08bits *reason6 = NULL; + { int af4res = create_relay_connection(server, ss, lifetime, af4, transport, even_port, in_reservation_token, &out_reservation_token, @@ -1263,9 +1279,7 @@ static int handle_turn_allocate(turn_turnserver *server, } } } - int err_code6 = 0; - const u08bits *reason6 = NULL; - if(af6) { + { int af6res = create_relay_connection(server, ss, lifetime, af6, transport, even_port, in_reservation_token, &out_reservation_token, @@ -1373,6 +1387,19 @@ static int handle_turn_allocate(turn_turnserver *server, *resp_constructed = 1; } + if(*resp_constructed && !(*err_code)) { + if(err_code4) { + size_t len = ioa_network_buffer_get_size(nbh); + stun_attr_add_address_error_code(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4, (u08bits)err_code4); + ioa_network_buffer_set_size(nbh,len); + } + if(err_code6) { + size_t len = ioa_network_buffer_get_size(nbh); + stun_attr_add_address_error_code(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6, (u08bits)err_code6); + ioa_network_buffer_set_size(nbh,len); + } + } + return 0; } From d5b84163b6b3df0ce5ebce093f129335c45e7602 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 1 Feb 2015 07:26:29 +0000 Subject: [PATCH 470/805] working on even-port. --- README.turnutils | 2 +- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 2 +- man/man1/turnutils.1 | 4 ++-- src/apps/uclient/mainuclient.c | 12 +++++++++--- src/apps/uclient/startuclient.c | 11 ++++++++++- src/client/ns_turn_msg.c | 20 +++++++++++--------- src/server/ns_turn_server.c | 16 ++++++++++++---- 8 files changed, 47 insertions(+), 22 deletions(-) diff --git a/README.turnutils b/README.turnutils index c2c5e9dc..a39fa889 100644 --- a/README.turnutils +++ b/README.turnutils @@ -104,7 +104,7 @@ Flags: -B Random disconnect after a few initial packets. --Z Dual allocation (SSODA draft support). +-Z Dual allocation (SSODA). Implies -c option. -J Use oAuth with default test key kid='north'. diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 90d0a6a2..2dd8022a 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "24 January 2015" "" "" +.TH TURN 1 "31 January 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 5657ca3c..d471c104 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "24 January 2015" "" "" +.TH TURN 1 "31 January 2015" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 4ce6de03..a43fd9b8 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "24 January 2015" "" "" +.TH TURN 1 "31 January 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -161,7 +161,7 @@ Random disconnect after a few initial packets. .TP .B \fB\-Z\fP -Dual allocation (SSODA draft support). +Dual allocation (SSODA). Implies \fB\-c\fP option. .TP .B \fB\-J\fP diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index a794323b..5adce35f 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -135,7 +135,7 @@ static char Usage[] = " (for testing the non-standard server relay functionality).\n" " -G Generate extra requests (create permissions, channel bind).\n" " -B Random disconnect after a few initial packets.\n" - " -Z Dual allocation.\n" + " -Z Dual allocation (implies -c).\n" " -J Use oAuth with default test key kid='north' or 'oldempire'.\n" "Options:\n" " -l Message length (Default: 100 Bytes).\n" @@ -467,10 +467,16 @@ int main(int argc, char **argv) } if (!c2c) { - if (make_ioa_addr((const u08bits*) peer_address, peer_port, &peer_addr) < 0) + + if (make_ioa_addr((const u08bits*) peer_address, peer_port, &peer_addr) < 0) { return -1; - if(peer_addr.ss.sa_family == AF_INET6) + } + + if(peer_addr.ss.sa_family == AF_INET6) { default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; + } else if(peer_addr.ss.sa_family == AF_INET) { + default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4; + } } diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 8019df82..58037ddd 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -375,7 +375,7 @@ static int clnet_allocate(int verbose, uint64_t reservation_token = 0; char* rt = NULL; - int ep = !no_rtcp; + int ep = !no_rtcp && !dual_allocation; if(!no_rtcp) { if (!never_allocate_rtcp && allocate_rtcp) { @@ -384,6 +384,15 @@ static int clnet_allocate(int verbose, } } + if(is_TCP_relay()) { + ep = -1; + } else if(rt) { + ep = -1; + } else if(!ep) { + ep = (((u08bits)random()) % 2); + ep = ep-1; + } + if(!dos) stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME, af4, af6, relay_transport, mobility, rt, ep); else diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 5a463f18..4df6f5fb 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -758,21 +758,23 @@ int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, i if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_LIFETIME,(u08bits*)(&field),sizeof(field))<0) return -1; } + //MICE + if(mobile) { + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_MOBILITY_TICKET,(const u08bits*)"",0)<0) return -1; + } + + if(ep>-1) { + uint8_t value = ep ? 0x80 : 0x00; + if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_EVEN_PORT,(const u08bits*)&value,1)<0) return -1; + } + + //RESERVATION-TOKEN, EVEN-PORT and DUAL-ALLOCATION are mutually exclusive: if(rt) { stun_attr_add_str(buf,len, STUN_ATTRIBUTE_RESERVATION_TOKEN, (const u08bits*) rt, 8); } else { - if(mobile) { - if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_MOBILITY_TICKET,(const u08bits*)"",0)<0) return -1; - } - - if(ep) { - uint8_t value = 0x80; - if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_EVEN_PORT,(const u08bits*)&value,1)<0) return -1; - } - //ADRESS-FAMILY if (af4 && !af6) { u08bits field[4]; diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index dd7f2b2d..0cc8e9eb 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1088,11 +1088,14 @@ static int handle_turn_allocate(turn_turnserver *server, if (in_reservation_token) { *err_code = 400; *reason = (const u08bits *)"Even Port and Reservation Token cannot be used together"; - } else if (even_port >= 0) { - *err_code = 400; - *reason = (const u08bits *)"Even Port cannot be used in this request"; } else { even_port = stun_attr_get_even_port(sar); + if(even_port) { + if (af4 && af6) { + *err_code = 400; + *reason = (const u08bits *)"Even Port cannot be used with Dual Allocation"; + } + } } } break; @@ -1118,6 +1121,11 @@ static int handle_turn_allocate(turn_turnserver *server, } break; case STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY: + if(even_port>0) { + *err_code = 400; + *reason = (const u08bits *)"Even Port cannot be used with Dual Allocation"; + break; + } case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY: { if(in_reservation_token) { *err_code = 400; @@ -1220,7 +1228,7 @@ static int handle_turn_allocate(turn_turnserver *server, *err_code = 440; *reason = (const u08bits *)"Dual allocation cannot be supported in the current server configuration"; } - if(even_port >= 0) { + if(even_port > 0) { *err_code = 440; *reason = (const u08bits *)"Dual allocation cannot be supported with even-port functionality"; } From e8b18b458619e464859a330063f62a515a9be95c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 1 Feb 2015 08:59:30 +0000 Subject: [PATCH 471/805] REFRESH adjusted for the new SSODA specs --- examples/scripts/selfloadbalance/secure_relay.sh | 2 +- src/apps/uclient/startuclient.c | 12 ++++++++++++ src/apps/uclient/uclient.c | 13 +++++++++++++ src/server/ns_turn_server.c | 11 ++++++----- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/examples/scripts/selfloadbalance/secure_relay.sh b/examples/scripts/selfloadbalance/secure_relay.sh index 5fb97ff2..077f49ef 100755 --- a/examples/scripts/selfloadbalance/secure_relay.sh +++ b/examples/scripts/selfloadbalance/secure_relay.sh @@ -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 $@ +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 --db=var/db/turndb $@ diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 58037ddd..d26cd718 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -649,6 +649,18 @@ static int clnet_allocate(int verbose, stun_attr_add(&request_message, STUN_ATTRIBUTE_MOBILITY_TICKET, (const char*)clnet_info->s_mobile_id, strlen(clnet_info->s_mobile_id)); } + if(dual_allocation && !mobility) { + int t = ((u08bits)random())%3; + if(t) { + u08bits field[4]; + field[0] = (t==1) ? (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4 : (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; + field[1]=0; + field[2]=0; + field[3]=0; + stun_attr_add(&request_message, STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY, (const char*) field, 4); + } + } + add_origin(&request_message); if(add_integrity(clnet_info, &request_message)<0) return -1; diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 46b2dc6f..1f3d9c07 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1232,6 +1232,19 @@ static int refresh_channel(app_ur_session* elem, u16bits method, uint32_t lt) stun_init_request(STUN_METHOD_REFRESH, &message); lt = htonl(lt); stun_attr_add(&message, STUN_ATTRIBUTE_LIFETIME, (const char*) <, 4); + + if(dual_allocation && !mobility) { + int t = ((u08bits)random())%3; + if(t) { + u08bits field[4]; + field[0] = (t==1) ? (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4 : (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; + field[1]=0; + field[2]=0; + field[3]=0; + stun_attr_add(&message, STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY, (const char*) field, 4); + } + } + add_origin(&message); if(add_integrity(clnet_info, &message)<0) return -1; if(use_fingerprints) diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 0cc8e9eb..acde670c 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1512,7 +1512,8 @@ static int handle_turn_refresh(turn_turnserver *server, } } break; - case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY: { + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY: /* <<== ??? */ + case STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY: { int af_req = stun_get_requested_address_family(sar); { int is_err = 0; @@ -1537,7 +1538,7 @@ static int handle_turn_refresh(turn_turnserver *server, if(is_err) { *err_code = 443; - *reason = (const u08bits *)"Peer Address Family Mismatch"; + *reason = (const u08bits *)"Peer Address Family Mismatch (1)"; } } } @@ -2231,7 +2232,7 @@ static int handle_turn_connect(turn_turnserver *server, } else { if(!get_relay_socket(a,peer_addr.ss.sa_family)) { *err_code = 443; - *reason = (const u08bits *)"Peer Address Family Mismatch"; + *reason = (const u08bits *)"Peer Address Family Mismatch (2)"; } peer_found = 1; @@ -2552,7 +2553,7 @@ static int handle_turn_channel_bind(turn_turnserver *server, if(!get_relay_socket(a,peer_addr.ss.sa_family)) { *err_code = 443; - *reason = (const u08bits *)"Peer Address Family Mismatch"; + *reason = (const u08bits *)"Peer Address Family Mismatch (3)"; } if(addr_get_port(&peer_addr) < 1) { @@ -3050,7 +3051,7 @@ static int handle_turn_create_permission(turn_turnserver *server, if(!get_relay_socket(a,peer_addr.ss.sa_family)) { *err_code = 443; - *reason = (const u08bits *)"Peer Address Family Mismatch"; + *reason = (const u08bits *)"Peer Address Family Mismatch (4)"; } else if(!good_peer_addr(server, ss->realm_options.name, &peer_addr)) { *err_code = 403; *reason = (const u08bits *) "Forbidden IP"; From 88a8491991a2eef2e89588c01635536fb6500b08 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 1 Feb 2015 20:29:40 +0000 Subject: [PATCH 472/805] library updates --- ChangeLog | 1 + configure | 2 ++ 2 files changed, 3 insertions(+) diff --git a/ChangeLog b/ChangeLog index 889630d9..8fc2eede 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ Version 4.4.1.2 'Ardee West': - hostname-to-IP-address resolution fix; - SSODA updates according to turnbis specs; - TRANSPORT attribute handling fixed; + - updates for Solaris (name resolution libraries); 1/24/2015 Oleg Moskalenko Version 4.4.1.1 'Ardee West': diff --git a/configure b/configure index 4cd9b101..fbb02442 100755 --- a/configure +++ b/configure @@ -867,6 +867,8 @@ if ! [ ${ER} -eq 0 ] ; then fi testlib wldap64 testlib intl +testlib nsl +testlib resolv ########################### # Test sockets compilation From a1e3dad968ff78fb8ef7eedd4d95b04e68e81028 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 1 Feb 2015 21:59:52 +0000 Subject: [PATCH 473/805] date changed --- ChangeLog | 4 ++-- rpm/turnserver.spec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8fc2eede..2c739d2e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,8 @@ -1/31/2015 Oleg Moskalenko +2/1/2015 Oleg Moskalenko Version 4.4.1.2 'Ardee West': - - hostname-to-IP-address resolution fix; - SSODA updates according to turnbis specs; - TRANSPORT attribute handling fixed; + - hostname-to-IP-address resolution fix; - updates for Solaris (name resolution libraries); 1/24/2015 Oleg Moskalenko diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 747a3562..fe251e84 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -288,7 +288,7 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Sat Jan 31 2015 Oleg Moskalenko +* Sun Feb 1 2015 Oleg Moskalenko - Sync to 4.4.1.2 * Sat Jan 24 2015 Oleg Moskalenko - Sync to 4.4.1.1 From 0d7d85da5833e76ab7175f9e3fef935a6ba0dd2f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 3 Feb 2015 07:38:40 +0000 Subject: [PATCH 474/805] SHA-512 added to oauth --- ChangeLog | 4 ++ INSTALL | 4 +- examples/var/db/turndb | Bin 22528 -> 22528 bytes man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 2 +- man/man1/turnutils.1 | 2 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +- src/apps/relay/turn_admin_server.c | 24 +++++++- src/apps/relay/userdb.c | 11 ++++ src/apps/rfc5769/rfc5769check.c | 6 ++ src/apps/uclient/mainuclient.c | 16 ++++- src/apps/uclient/uclient.c | 5 +- src/apps/uclient/uclient.h | 2 +- src/client/ns_turn_msg.c | 94 ++++++++++++++++++++++++----- src/client/ns_turn_msg_defs_new.h | 9 ++- src/ns_turn_defs.h | 2 +- src/server/ns_turn_server.c | 6 ++ turndb/schema.userdb.redis | 4 +- turndb/testmongosetup.sh | 6 ++ turndb/testredisdbsetup.sh | 1 + turndb/testsqldbsetup.sql | 1 + 22 files changed, 171 insertions(+), 36 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2c739d2e..81cf0102 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2/2/2015 Oleg Moskalenko +Version 4.4.1.3 'Ardee West': + - SHA-512 added to oAuth; + 2/1/2015 Oleg Moskalenko Version 4.4.1.2 'Ardee West': - SSODA updates according to turnbis specs; diff --git a/INSTALL b/INSTALL index 1706efb4..95c56016 100644 --- a/INSTALL +++ b/INSTALL @@ -763,7 +763,7 @@ The oauth_key table fields meanings are: is 0 - unlimited lifetime. hkdf_hash_func - (optional) hash function for HKDF procedure; the - valid values are SHA-1 and SHA-256, with SHA-256 as default; + valid values are SHA-1, SHA-256 and SHA-512, with SHA-256 as default; The hkdf_hash_func is not needed if the as_rs_key and auth_key are defined explicitly in the database; @@ -777,7 +777,7 @@ The oauth_key table fields meanings are: is defined by as_rs_alg. auth_alg - (optional) oAuth token authentication algorithm; the valid values are - "HMAC-SHA-256-128", "HMAC-SHA-256" and "HMAC-SHA-1". + "HMAC-SHA-256-128", "HMAC-SHA-256", "HMAC-SHA-512" and "HMAC-SHA-1". The default value is "HMAC-SHA-256-128". auth_key - (optional) base64-encoded AUTH key. If not defined, then diff --git a/examples/var/db/turndb b/examples/var/db/turndb index bd93f071598d22131933274dbff1ab2600efefe8..1805bfb55f20ec83c60a4a0935daa6ccdc10595f 100644 GIT binary patch delta 101 zcmZqJz}T>Xae_4C%!xA2tTP#OAE|9jS>Vjf%pA6v-Nm0-!jzdyT$Y1FTA5dsw=^#^ zKQGZetTM?caPnPu8D>*MqshJQXae_4CjEOSNtTPyNA4zXaS>Vjf#N4}?-Nm1og@J*=d}5>V1=K%nKLlsm2 diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 2dd8022a..4f3538f4 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "31 January 2015" "" "" +.TH TURN 1 "02 February 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index d471c104..943c7fca 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "31 January 2015" "" "" +.TH TURN 1 "02 February 2015" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index a43fd9b8..b72d8b39 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "31 January 2015" "" "" +.TH TURN 1 "02 February 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index c5c3ea19..7057e035 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.4.1.2 +TURNVERSION=4.4.1.3 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index fe251e84..96cd4658 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.4.1.2 +Version: 4.4.1.3 Release: 0%{dist} Summary: Coturn TURN Server @@ -288,6 +288,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Sun Feb 2 2015 Oleg Moskalenko + - Sync to 4.4.1.3 * Sun Feb 1 2015 Oleg Moskalenko - Sync to 4.4.1.2 * Sat Jan 24 2015 Oleg Moskalenko diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 6bba4eb7..8ad74912 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -712,6 +712,8 @@ static void cli_print_configuration(struct cli_session* cs) if(turn_params.shatype == SHATYPE_SHA256) cli_print_str(cs,"SHA256","SHA type",0); + else if(turn_params.shatype == SHATYPE_SHA512) + cli_print_str(cs,"SHA512","SHA type",0); else cli_print_str(cs,"SHA1","SHA type",0); myprintf(cs,"\n"); @@ -1979,6 +1981,8 @@ static void write_pc_page(ioa_socket_handle s) if(turn_params.shatype == SHATYPE_SHA256) https_print_str(sb,"SHA256","SHA type",0); + else if(turn_params.shatype == SHATYPE_SHA512) + https_print_str(sb,"SHA512","SHA type",0); else https_print_str(sb,"SHA1","SHA type",0); @@ -2508,6 +2512,8 @@ static void write_users_page(ioa_socket_handle s, const u08bits *add_user, const if(turn_params.shatype == SHATYPE_SHA256) str_buffer_append(sb,"SHA type: SHA256
\r\n"); + else if(turn_params.shatype == SHATYPE_SHA512) + str_buffer_append(sb,"SHA type: SHA512
\r\n"); else str_buffer_append(sb,"SHA type: SHA1
\r\n"); @@ -3043,10 +3049,18 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,"SHA-256\r\n
\r\n"); + + str_buffer_append(sb,"SHA-512\r\n
\r\n"); } str_buffer_append(sb,""); @@ -3140,6 +3154,14 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con } str_buffer_append(sb,">HMAC-SHA-256\r\n
\r\n"); + str_buffer_append(sb,"HMAC-SHA-512\r\n
\r\n"); + str_buffer_append(sb,"key_set)) { - cok=(random())%2; - if(cok<0) cok=-cok; + cok=((unsigned short)random())%3; clnet_info->cok = cok; oauth_token otoken; encoded_oauth_token etoken; @@ -1627,6 +1626,8 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) otoken.enc_block.timestamp = ((uint64_t)turn_time()) << 16; if(shatype == SHATYPE_SHA256) { otoken.enc_block.key_length = 32; + } else if(shatype == SHATYPE_SHA512) { + otoken.enc_block.key_length = 64; } else { otoken.enc_block.key_length = 20; } diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index e68de6ee..045e53ba 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -88,7 +88,7 @@ extern int dual_allocation; extern char origin[STUN_MAX_ORIGIN_SIZE+1]; extern int oauth; -extern oauth_key okey_array[2]; +extern oauth_key okey_array[3]; #define UCLIENT_SESSION_LIFETIME (777) #define OAUTH_SESSION_LIFETIME (555) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 4df6f5fb..fd9004ad 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -125,6 +125,15 @@ int stun_calculate_hmac(const u08bits *buf, size_t len, const u08bits *key, size #else fprintf(stderr,"SHA256 is not supported\n"); return -1; +#endif + } else if(shatype == SHATYPE_SHA512) { +#if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH) + if (!HMAC(EVP_sha512(), key, keylen, buf, len, hmac, hmac_len)) { + return -1; + } +#else + fprintf(stderr,"SHA512 is not supported\n"); + return -1; #endif } else if (!HMAC(EVP_sha1(), key, keylen, buf, len, hmac, hmac_len)) { @@ -164,6 +173,18 @@ int stun_produce_integrity_key_str(u08bits *uname, u08bits *realm, u08bits *upwd #else fprintf(stderr,"SHA256 is not supported\n"); return -1; +#endif + } else if(shatype == SHATYPE_SHA512) { +#if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH) + unsigned int keylen = 0; + EVP_MD_CTX ctx; + EVP_DigestInit(&ctx,EVP_sha512()); + EVP_DigestUpdate(&ctx,str,strl); + EVP_DigestFinal(&ctx,key,&keylen); + EVP_MD_CTX_cleanup(&ctx); +#else + fprintf(stderr,"SHA512 is not supported\n"); + return -1; #endif } else { MD5_CTX ctx; @@ -1517,6 +1538,8 @@ size_t get_hmackey_size(SHATYPE shatype) { if(shatype == SHATYPE_SHA256) return 32; + if(shatype == SHATYPE_SHA512) + return 64; return 16; } @@ -1540,6 +1563,9 @@ int stun_attr_add_integrity_str(turn_credential_type ct, u08bits *buf, size_t *l case SHATYPE_SHA256: shasize = SHA256SIZEBYTES; break; + case SHATYPE_SHA512: + shasize = SHA512SIZEBYTES; + break; default: shasize = SHA1SIZEBYTES; }; @@ -1624,6 +1650,11 @@ int stun_check_message_integrity_by_key_str(turn_credential_type ct, u08bits *bu if(shatype != SHATYPE_SHA256) return -1; break; + case SHA512SIZEBYTES: + shasize = SHA512SIZEBYTES; + if(shatype != SHATYPE_SHA512) + return -1; + break; case SHA1SIZEBYTES: shasize = SHA1SIZEBYTES; if(shatype != SHATYPE_SHA1) { @@ -1818,6 +1849,8 @@ static size_t calculate_auth_key_length(AUTH_ALG a) return 32; case AUTH_ALG_HMAC_SHA_256: return 32; + case AUTH_ALG_HMAC_SHA_512: + return 64; default: break; }; @@ -1834,6 +1867,8 @@ static size_t calculate_auth_output_length(AUTH_ALG a) return 16; case AUTH_ALG_HMAC_SHA_256: return 32; + case AUTH_ALG_HMAC_SHA_512: + return 64; default: break; }; @@ -1852,25 +1887,44 @@ static int calculate_key(char *key, size_t key_size, char *new_key, size_t new_k //Expand: u08bits buf[128]; buf[0]=1; - u08bits hmac[128]; - unsigned int hmac_len = 0; - stun_calculate_hmac((const u08bits *)buf, 1, prk, prk_len, hmac, &hmac_len, shatype); - ns_bcopy(hmac,new_key,hmac_len); + u08bits hmac1[128]; + unsigned int hmac1_len = 0; + stun_calculate_hmac((const u08bits *)buf, 1, prk, prk_len, hmac1, &hmac1_len, shatype); + ns_bcopy(hmac1,new_key,hmac1_len); //Check - if(new_key_size>hmac_len) { - ns_bcopy(hmac,buf,hmac_len); - buf[hmac_len]=2; - u08bits hmac1[128]; - unsigned int hmac1_len = 0; - stun_calculate_hmac((const u08bits *)buf, hmac_len+1, prk, prk_len, hmac1, &hmac1_len, shatype); - ns_bcopy(hmac1,new_key+hmac_len,hmac1_len); - if(new_key_size > (hmac_len + hmac1_len)) { - if(err_msg) { - snprintf(err_msg,err_msg_size,"Wrong HKDF procedure (key sizes): output.sz=%lu, hmac(1)=%lu, hmac(2)=%lu",(unsigned long)new_key_size,(unsigned long)hmac_len,(unsigned long)hmac1_len); + if(new_key_size>hmac1_len) { + ns_bcopy(hmac1,buf,hmac1_len); + buf[hmac1_len]=2; + u08bits hmac2[128]; + unsigned int hmac2_len = 0; + stun_calculate_hmac((const u08bits *)buf, hmac1_len+1, prk, prk_len, hmac2, &hmac2_len, shatype); + ns_bcopy(hmac2,new_key+hmac1_len,hmac2_len); + if(new_key_size > (hmac1_len + hmac2_len)) { + + ns_bcopy(hmac2,buf,hmac2_len); + buf[hmac2_len]=3; + u08bits hmac3[128]; + unsigned int hmac3_len = 0; + stun_calculate_hmac((const u08bits *)buf, hmac2_len+1, prk, prk_len, hmac3, &hmac3_len, shatype); + ns_bcopy(hmac3,new_key+hmac1_len+hmac2_len,hmac3_len); + if(new_key_size > (hmac1_len + hmac2_len + hmac3_len)) { + + ns_bcopy(hmac3,buf,hmac3_len); + buf[hmac3_len]=4; + u08bits hmac4[128]; + unsigned int hmac4_len = 0; + stun_calculate_hmac((const u08bits *)buf, hmac3_len+1, prk, prk_len, hmac4, &hmac4_len, shatype); + ns_bcopy(hmac4,new_key+hmac1_len+hmac2_len+hmac3_len,hmac4_len); + if(new_key_size > (hmac1_len + hmac2_len + hmac3_len + hmac4_len)) { + + if(err_msg) { + snprintf(err_msg,err_msg_size,"Wrong HKDF procedure (key sizes): output.sz=%lu, hmac(1)=%lu, hmac(2)=%lu",(unsigned long)new_key_size,(unsigned long)hmac1_len,(unsigned long)hmac2_len); + } + OAUTH_ERROR("Wrong HKDF procedure (key sizes): output.sz=%lu, hmac(1)=%lu, hmac(2)=%lu",(unsigned long)new_key_size,(unsigned long)hmac1_len,(unsigned long)hmac2_len); + return -1; + } } - OAUTH_ERROR("Wrong HKDF procedure (key sizes): output.sz=%lu, hmac(1)=%lu, hmac(2)=%lu",(unsigned long)new_key_size,(unsigned long)hmac_len,(unsigned long)hmac1_len); - return -1; } } @@ -1938,6 +1992,8 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er key->hkdf_hash_func = SHATYPE_SHA1; } else if(!strcmp(oakd->hkdf_hash_func,"SHA256") || !strcmp(oakd->hkdf_hash_func,"SHA-256")) { key->hkdf_hash_func = SHATYPE_SHA256; + } else if(!strcmp(oakd->hkdf_hash_func,"SHA512") || !strcmp(oakd->hkdf_hash_func,"SHA-512")) { + key->hkdf_hash_func = SHATYPE_SHA512; } else if(oakd->hkdf_hash_func[0]) { if(err_msg) { snprintf(err_msg,err_msg_size,"Wrong HKDF hash function algorithm: %s",oakd->hkdf_hash_func); @@ -1951,6 +2007,8 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er key->auth_alg = AUTH_ALG_HMAC_SHA_1; } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256")) { key->auth_alg = AUTH_ALG_HMAC_SHA_256; + } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-512")) { + key->auth_alg = AUTH_ALG_HMAC_SHA_512; } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256-128")) { key->auth_alg = AUTH_ALG_HMAC_SHA_256_128; } else if(oakd->auth_alg[0]) { @@ -2034,6 +2092,10 @@ static const EVP_MD *get_auth_type(AUTH_ALG aa) case AUTH_ALG_HMAC_SHA_256_128: case AUTH_ALG_HMAC_SHA_256: return EVP_sha256(); +#if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH) + case AUTH_ALG_HMAC_SHA_512: + return EVP_sha512(); +#endif #endif default: break; diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 99709b3a..ae0b122c 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -48,6 +48,7 @@ #define SHA1SIZEBYTES (20) #define SHA256SIZEBYTES (32) +#define SHA512SIZEBYTES (64) #define MAXSHASIZE (128) @@ -55,12 +56,13 @@ enum _SHATYPE { SHATYPE_ERROR = -1, SHATYPE_DEFAULT=0, SHATYPE_SHA1=SHATYPE_DEFAULT, - SHATYPE_SHA256 + SHATYPE_SHA256, + SHATYPE_SHA512 }; typedef enum _SHATYPE SHATYPE; -#define shatype_name(sht) ((sht == SHATYPE_SHA1) ? "SHA1" : ((sht == SHATYPE_SHA256) ? "SHA256" : "SHA UNKNOWN")) +#define shatype_name(sht) ((sht == SHATYPE_SHA1) ? "SHA1" : ((sht == SHATYPE_SHA256) ? "SHA256" : ((sht == SHATYPE_SHA512) ? "SHA512" : "SHA UNKNOWN"))) #define SHA_TOO_WEAK_ERROR_CODE (426) @@ -90,7 +92,8 @@ enum _AUTH_ALG { AUTH_ALG_DEFAULT = 1, AUTH_ALG_HMAC_SHA_256_128 = AUTH_ALG_DEFAULT, AUTH_ALG_HMAC_SHA_1, - AUTH_ALG_HMAC_SHA_256 + AUTH_ALG_HMAC_SHA_256, + AUTH_ALG_HMAC_SHA_512 }; typedef enum _AUTH_ALG AUTH_ALG; diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 570e1fdc..4e48fa0b 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.4.1.2" +#define TURN_SERVER_VERSION "4.4.1.3" #define TURN_SERVER_VERSION_NAME "Ardee West" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index acde670c..7a61f59e 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3297,6 +3297,12 @@ static int check_stun_auth(turn_turnserver *server, return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); } break; + case SHA512SIZEBYTES: + if(server->shatype != SHATYPE_SHA512) { + *err_code = 401; + return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); + } + break; default: *err_code = 401; return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis index bcb5c4ff..e25fcd5b 100644 --- a/turndb/schema.userdb.redis +++ b/turndb/schema.userdb.redis @@ -45,7 +45,7 @@ and they will be almost immediately "seen" by the turnserver process. is 0 - unlimited lifetime. hkdf_hash_func - (optional) hash function for HKDF procedure; the - valid values are SHA-1 and SHA-256, with SHA-256 as default; + valid values are SHA-1, SHA-256 and SHA-512, with SHA-256 as default; The hkdf_hash_func is not needed if the as_rs_key and auth_key are defined explicitly in the database; @@ -59,7 +59,7 @@ and they will be almost immediately "seen" by the turnserver process. is defined by as_rs_alg. auth_alg - (optional) oAuth token authentication algorithm; the valid values are - "HMAC-SHA-256-128", "HMAC-SHA-256" and "HMAC-SHA-1". + "HMAC-SHA-256-128", "HMAC-SHA-256", "HMAC-SHA-512" and "HMAC-SHA-1". The default value is "HMAC-SHA-256-128". auth_key - (optional) base64-encoded AUTH key. If not defined, then diff --git a/turndb/testmongosetup.sh b/turndb/testmongosetup.sh index b6a8779c..a266cf90 100755 --- a/turndb/testmongosetup.sh +++ b/turndb/testmongosetup.sh @@ -51,6 +51,12 @@ db.oauth_key.insert({ kid: 'north', hkdf_hash_func: 'SHA-256', as_rs_alg: 'AES-256-CBC', auth_alg: 'HMAC-SHA-256-128' }); + +db.oauth_key.insert({ kid: 'union', + ikm_key: 'aGVyb2Q=', + hkdf_hash_func: 'SHA-256', + as_rs_alg: 'AES-256-CBC', + auth_alg: 'HMAC-SHA-512' }); db.oauth_key.insert({ kid: 'oldempire', ikm_key: 'YXVsY3Vz', diff --git a/turndb/testredisdbsetup.sh b/turndb/testredisdbsetup.sh index 1fe32ece..29d6d584 100755 --- a/turndb/testredisdbsetup.sh +++ b/turndb/testredisdbsetup.sh @@ -36,6 +36,7 @@ sadd turn/realm/north.gov/denied-peer-ip "172.17.13.133-172.17.14.56" "172.17.17 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/union ikm_key 'aGVyb2Q=' hkdf_hash_func 'SHA-256' as_rs_alg 'AES-256-CBC' auth_alg 'HMAC-SHA-512' 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' diff --git a/turndb/testsqldbsetup.sql b/turndb/testsqldbsetup.sql index b20dec5e..8bd0c7a7 100644 --- a/turndb/testsqldbsetup.sql +++ b/turndb/testsqldbsetup.sql @@ -32,4 +32,5 @@ insert into denied_peer_ip (realm,ip_range) values('north.gov','172.17.17.133-17 insert into denied_peer_ip (realm,ip_range) values('crinna.org','123::77'); insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('north','Y2FybGVvbg==',0,0,'SHA-256','AES-256-CBC','','HMAC-SHA-256-128',''); +insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('union','aGVyb2Q=',0,0,'SHA-256','AES-256-CBC','','HMAC-SHA-512',''); insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('oldempire','YXVsY3Vz',0,0,'SHA-256','AEAD-AES-256-GCM','','',''); From 2e0b8aefcca4f982ac79ee9961cc8b880eeb0c9a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 4 Feb 2015 06:14:11 +0000 Subject: [PATCH 475/805] TOS fixed --- ChangeLog | 6 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 6 +- src/apps/common/apputils.c | 125 +++++++++++++++++++++++ src/apps/common/apputils.h | 8 ++ src/apps/relay/ns_ioalib_engine_impl.c | 136 +------------------------ src/apps/rfc5769/rfc5769check.c | 6 +- src/apps/uclient/startuclient.c | 3 + src/ns_turn_defs.h | 2 +- 9 files changed, 152 insertions(+), 142 deletions(-) diff --git a/ChangeLog b/ChangeLog index 81cf0102..081ad00c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,8 @@ -2/2/2015 Oleg Moskalenko -Version 4.4.1.3 'Ardee West': +2/3/2015 Oleg Moskalenko +Version 4.4.2.1 'Ardee West': - SHA-512 added to oAuth; + - updates according to the new third-party-auth draft (oauth); + - TOS behavior fixed; 2/1/2015 Oleg Moskalenko Version 4.4.1.2 'Ardee West': diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 7057e035..7b0ed997 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.4.1.3 +TURNVERSION=4.4.2.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 96cd4658..9f1cd82b 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.4.1.3 +Version: 4.4.2.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -288,8 +288,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Sun Feb 2 2015 Oleg Moskalenko - - Sync to 4.4.1.3 +* Tue Feb 3 2015 Oleg Moskalenko + - Sync to 4.4.2.1 * Sun Feb 1 2015 Oleg Moskalenko - Sync to 4.4.1.2 * Sat Jan 24 2015 Oleg Moskalenko diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c index a8ec8ef3..690c60d4 100644 --- a/src/apps/common/apputils.c +++ b/src/apps/common/apputils.c @@ -289,6 +289,131 @@ int addr_get_from_sock(evutil_socket_t fd, ioa_addr *addr) } } +int get_raw_socket_ttl(evutil_socket_t fd, int family) +{ + int ttl = 0; + + if(family == AF_INET6) { +#if !defined(IPV6_UNICAST_HOPS) + UNUSED_ARG(fd); + do { return TTL_IGNORE; } while(0); +#else + socklen_t slen = (socklen_t)sizeof(ttl); + if(getsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,&slen)<0) { + perror("get HOPLIMIT on socket"); + return TTL_IGNORE; + } +#endif + } else { +#if !defined(IP_TTL) + UNUSED_ARG(fd); + do { return TTL_IGNORE; } while(0); +#else + socklen_t slen = (socklen_t)sizeof(ttl); + if(getsockopt(fd, IPPROTO_IP, IP_TTL, &ttl,&slen)<0) { + perror("get TTL on socket"); + return TTL_IGNORE; + } +#endif + } + + CORRECT_RAW_TTL(ttl); + + return ttl; +} + +int get_raw_socket_tos(evutil_socket_t fd, int family) +{ + int tos = 0; + + if(family == AF_INET6) { +#if !defined(IPV6_TCLASS) + UNUSED_ARG(fd); + do { return TOS_IGNORE; } while(0); +#else + socklen_t slen = (socklen_t)sizeof(tos); + if(getsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos,&slen)<0) { + perror("get TCLASS on socket"); + return -1; + } +#endif + } else { +#if !defined(IP_TOS) + UNUSED_ARG(fd); + do { return TOS_IGNORE; } while(0); +#else + socklen_t slen = (socklen_t)sizeof(tos); + if(getsockopt(fd, IPPROTO_IP, IP_TOS, &tos,&slen)<0) { + perror("get TOS on socket"); + return -1; + } +#endif + } + + CORRECT_RAW_TOS(tos); + + return tos; +} + +int set_raw_socket_ttl(evutil_socket_t fd, int family, int ttl) +{ + + if(family == AF_INET6) { +#if !defined(IPV6_UNICAST_HOPS) + UNUSED_ARG(fd); + UNUSED_ARG(ttl); +#else + CORRECT_RAW_TTL(ttl); + if(setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,sizeof(ttl))<0) { + perror("set HOPLIMIT on socket"); + return -1; + } +#endif + } else { +#if !defined(IP_TTL) + UNUSED_ARG(fd); + UNUSED_ARG(ttl); +#else + CORRECT_RAW_TTL(ttl); + if(setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl,sizeof(ttl))<0) { + perror("set TTL on socket"); + return -1; + } +#endif + } + + return 0; +} + +int set_raw_socket_tos(evutil_socket_t fd, int family, int tos) +{ + + if(family == AF_INET6) { +#if !defined(IPV6_TCLASS) + UNUSED_ARG(fd); + UNUSED_ARG(tos); +#else + CORRECT_RAW_TOS(tos); + if(setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos,sizeof(tos))<0) { + perror("set TCLASS on socket"); + return -1; + } +#endif + } else { +#if !defined(IP_TOS) + UNUSED_ARG(fd); + UNUSED_ARG(tos); +#else + if(setsockopt(fd, IPPROTO_IP, IP_TOS, &tos,sizeof(tos))<0) { + perror("set TOS on socket"); + return -1; + } +#endif + } + + return 0; +} + /////////////////// MTU ///////////////////////////////////////// int set_socket_df(evutil_socket_t fd, int family, int value) diff --git a/src/apps/common/apputils.h b/src/apps/common/apputils.h index adb38b69..fb3133b1 100644 --- a/src/apps/common/apputils.h +++ b/src/apps/common/apputils.h @@ -186,6 +186,14 @@ int addr_get_from_sock(evutil_socket_t fd, ioa_addr *addr); int handle_socket_error(void); +#define CORRECT_RAW_TTL(ttl) do { if(ttl<0 || ttl>255) ttl=TTL_DEFAULT; } while(0) +#define CORRECT_RAW_TOS(tos) do { if(tos<0 || tos>255) tos=TOS_DEFAULT; } while(0) + +int set_raw_socket_tos(evutil_socket_t fd, int family, int tos); +int set_raw_socket_ttl(evutil_socket_t fd, int family, int ttl); +int get_raw_socket_tos(evutil_socket_t fd, int family); +int get_raw_socket_ttl(evutil_socket_t fd, int family); + /////////////////////// SYS ///////////////////// void ignore_sigpipe(void); diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 34027854..697d63c7 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -355,16 +355,16 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm, #if !defined(CMSG_SPACE) TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "On this platform, I am using alternative behavior of TTL/TOS according to RFC 5766.\n"); #endif -#if !defined(IP_RECVTTL) +#if !defined(IP_RECVTTL) || !defined(IP_TTL) TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv4: On this platform, I am using alternative behavior of TTL according to RFC 5766.\n"); #endif -#if !defined(IPV6_RECVHOPLIMIT) +#if !defined(IPV6_RECVHOPLIMIT) || !defined(IPV6_HOPLIMIT) TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv6: On this platform, I am using alternative behavior of TTL (HOPLIMIT) according to RFC 6156.\n"); #endif -#if !defined(IP_RECVTOS) +#if !defined(IP_RECVTOS) || !defined(IP_TOS) TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv4: On this platform, I am using alternative behavior of TOS according to RFC 5766.\n"); #endif -#if !defined(IPV6_RECVTCLASS) +#if !defined(IPV6_RECVTCLASS) || !defined(IPV6_TCLASS) TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv6: On this platform, I am using alternative behavior of TRAFFIC CLASS according to RFC 6156.\n"); #endif } @@ -706,134 +706,6 @@ int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_ /* Socket options helpers ==>> */ -#define CORRECT_RAW_TTL(ttl) do { if(ttl<0 || ttl>255) ttl=TTL_DEFAULT; } while(0) -#define CORRECT_RAW_TOS(tos) do { if(tos<0 || tos>255) tos=TOS_DEFAULT; } while(0) - -static int get_raw_socket_ttl(evutil_socket_t fd, int family) -{ - int ttl = 0; - - if(family == AF_INET6) { -#if !defined(IPV6_RECVHOPLIMIT) - UNUSED_ARG(fd); - do { return TTL_IGNORE; } while(0); -#else - socklen_t slen = (socklen_t)sizeof(ttl); - if(getsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,&slen)<0) { - perror("get HOPLIMIT on socket"); - return TTL_IGNORE; - } -#endif - } else { -#if !defined(IP_RECVTTL) - UNUSED_ARG(fd); - do { return TTL_IGNORE; } while(0); -#else - socklen_t slen = (socklen_t)sizeof(ttl); - if(getsockopt(fd, IPPROTO_IP, IP_TTL, &ttl,&slen)<0) { - perror("get TTL on socket"); - return TTL_IGNORE; - } -#endif - } - - CORRECT_RAW_TTL(ttl); - - return ttl; -} - -static int get_raw_socket_tos(evutil_socket_t fd, int family) -{ - int tos = 0; - - if(family == AF_INET6) { -#if !defined(IPV6_RECVTCLASS) - UNUSED_ARG(fd); - do { return TOS_IGNORE; } while(0); -#else - socklen_t slen = (socklen_t)sizeof(tos); - if(getsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos,&slen)<0) { - perror("get TCLASS on socket"); - return -1; - } -#endif - } else { -#if !defined(IP_RECVTOS) - UNUSED_ARG(fd); - do { return TOS_IGNORE; } while(0); -#else - socklen_t slen = (socklen_t)sizeof(tos); - if(getsockopt(fd, IPPROTO_IP, IP_TOS, &tos,&slen)<0) { - perror("get TOS on socket"); - return -1; - } -#endif - } - - CORRECT_RAW_TOS(tos); - - return tos; -} - -static int set_raw_socket_ttl(evutil_socket_t fd, int family, int ttl) -{ - - if(family == AF_INET6) { -#if !defined(IPV6_RECVHOPLIMIT) - UNUSED_ARG(fd); - UNUSED_ARG(ttl); -#else - CORRECT_RAW_TTL(ttl); - if(setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,sizeof(ttl))<0) { - perror("set HOPLIMIT on socket"); - return -1; - } -#endif - } else { -#if !defined(IP_RECVTTL) - UNUSED_ARG(fd); - UNUSED_ARG(ttl); -#else - CORRECT_RAW_TTL(ttl); - if(setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl,sizeof(ttl))<0) { - perror("set TTL on socket"); - return -1; - } -#endif - } - - return 0; -} - -static int set_raw_socket_tos(evutil_socket_t fd, int family, int tos) -{ - - if(family == AF_INET6) { -#if !defined(IPV6_RECVTCLASS) - UNUSED_ARG(fd); - UNUSED_ARG(tos); -#else - CORRECT_RAW_TOS(tos); - if(setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos,sizeof(tos))<0) { - perror("set TCLASS on socket"); - return -1; - } -#endif - } else { -#if !defined(IPV6_RECVTOS) - UNUSED_ARG(fd); - UNUSED_ARG(tos); -#else - if(setsockopt(fd, IPPROTO_IP, IP_TOS, &tos,sizeof(tos))<0) { - perror("set TOS on socket"); - return -1; - } -#endif - } - - return 0; -} - static int set_socket_ttl(ioa_socket_handle s, int ttl) { if(s->default_ttl < 0) //Unsupported diff --git a/src/apps/rfc5769/rfc5769check.c b/src/apps/rfc5769/rfc5769check.c index af781f84..dee77a76 100644 --- a/src/apps/rfc5769/rfc5769check.c +++ b/src/apps/rfc5769/rfc5769check.c @@ -82,12 +82,12 @@ static int check_oauth(void) { size_t i_hmacs,i_shas,i_encs; - const char long_term_password[33] = "HGkj32KJGiuy098sdfaqbNjOiaz71923"; + const char long_term_key[33] = "HGkj32KJGiuy098sdfaqbNjOiaz71923"; size_t ltp_output_length=0; - const char* base64encoded_ltp = base64_encode((const unsigned char *)long_term_password, - strlen(long_term_password), + const char* base64encoded_ltp = base64_encode((const unsigned char *)long_term_key, + strlen(long_term_key), <p_output_length); const char mac_key[33] = "ZksjpweoixXmvn67534m"; diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index d26cd718..4dd6a13a 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -242,6 +242,9 @@ static int clnet_connect(uint16_t clnet_remote_port, const char *remote_address, set_sock_buf_size(clnet_fd, UR_CLIENT_SOCK_BUF_SIZE); + set_raw_socket_tos(clnet_fd, remote_addr.ss.sa_family, 0x22); + set_raw_socket_ttl(clnet_fd, remote_addr.ss.sa_family, 47); + if(clnet_info->is_peer && (*local_address==0)) { if(remote_addr.ss.sa_family == AF_INET6) { diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 4e48fa0b..b3d091ab 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.4.1.3" +#define TURN_SERVER_VERSION "4.4.2.1" #define TURN_SERVER_VERSION_NAME "Ardee West" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 1afe1e977bc4728ffeb4a0c0963ca96efaa1c474 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 4 Feb 2015 08:10:18 +0000 Subject: [PATCH 476/805] fixes for TOS --- src/apps/relay/dtls_listener.c | 3 +++ src/apps/relay/ns_ioalib_engine_impl.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index cddd0768..0b5df852 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -762,6 +762,9 @@ static int create_server_socket(dtls_listener_relay_server_type* server, int rep TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind listener socket to device %s\n",server->ifname); } + set_raw_socket_ttl_options(udp_listen_fd, server->addr.ss.sa_family); + set_raw_socket_tos_options(udp_listen_fd, server->addr.ss.sa_family); + { const int max_binding_time = 60; int addr_bind_cycle = 0; diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 697d63c7..87c2eaed 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -1605,6 +1605,8 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s) close(udp_fd); return ret; } + set_raw_socket_ttl_options(udp_fd, s->local_addr.ss.sa_family); + set_raw_socket_tos_options(udp_fd, s->local_addr.ss.sa_family); } detach_socket_net_data(s); From d1f890160617aa4c92fb534005050e339cd4d47e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 4 Feb 2015 09:18:28 +0000 Subject: [PATCH 477/805] TOS fixed for Linux --- src/apps/relay/dtls_listener.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index 0b5df852..2d591c45 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -638,14 +638,14 @@ static void udp_server_input_handler(evutil_socket_t fd, short what, void* arg) addr_set_any(&(server->sm.m.sm.nd.src_addr)); - int slen = server->slen0; ssize_t bsize = 0; - int flags = 0; + int flags = MSG_DONTWAIT; - do { - bsize = recvfrom(fd, ioa_network_buffer_data(elem), ioa_network_buffer_get_capacity_udp(), flags, (struct sockaddr*) &(server->sm.m.sm.nd.src_addr), (socklen_t*) &slen); - } while (bsize < 0 && (errno == EINTR)); + bsize = udp_recvfrom(fd, &(server->sm.m.sm.nd.src_addr), &(server->addr), + (s08bits*)ioa_network_buffer_data(elem), (int)ioa_network_buffer_get_capacity_udp(), + &(server->sm.m.sm.nd.recv_ttl), &(server->sm.m.sm.nd.recv_tos), + server->e->cmsg, flags, NULL); int conn_reset = is_connreset(); int to_block = would_block(); @@ -668,6 +668,7 @@ static void udp_server_input_handler(evutil_socket_t fd, short what, void* arg) ioa_addr orig_addr; int ttl = 0; int tos = 0; + int slen = server->slen0; udp_recvfrom(fd, &orig_addr, &(server->addr), buffer, (int) sizeof(buffer), &ttl, &tos, server->e->cmsg, eflags, &errcode); From 523be275ee633180870c8ae7ece3357833ad7536 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 4 Feb 2015 17:07:53 +0000 Subject: [PATCH 478/805] changelog update --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 081ad00c..d471ff8c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,7 +2,7 @@ Version 4.4.2.1 'Ardee West': - SHA-512 added to oAuth; - updates according to the new third-party-auth draft (oauth); - - TOS behavior fixed; + - TOS (DiffServer) and TTL IP header field handling fixed; 2/1/2015 Oleg Moskalenko Version 4.4.1.2 'Ardee West': From 08f048825511cd689bf4b648f32041b3230c00fa Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 5 Feb 2015 07:39:07 +0000 Subject: [PATCH 479/805] sha512 added --- ChangeLog | 4 ++-- INSTALL | 30 ++++++++++++++++-------------- README.turnadmin | 5 ++++- README.turnserver | 1 + README.turnutils | 2 ++ STATUS | 2 ++ examples/etc/turnserver.conf | 11 ++++++----- examples/var/db/turndb | Bin 22528 -> 22528 bytes man/man1/turnadmin.1 | 8 +++++++- man/man1/turnserver.1 | 6 +++++- man/man1/turnutils.1 | 6 +++++- src/apps/relay/mainrelay.c | 19 ++++++++++++++----- src/apps/uclient/mainuclient.c | 17 ++++++++++++----- src/apps/uclient/startuclient.c | 25 ++++++++++++++++++++----- src/apps/uclient/uclient.c | 5 ++++- src/apps/uclient/uclient.h | 2 +- src/client/ns_turn_msg_defs.h | 2 +- turndb/schema.sql | 2 +- 18 files changed, 103 insertions(+), 44 deletions(-) diff --git a/ChangeLog b/ChangeLog index d471ff8c..a7ee0ab1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,8 @@ 2/3/2015 Oleg Moskalenko Version 4.4.2.1 'Ardee West': - - SHA-512 added to oAuth; - - updates according to the new third-party-auth draft (oauth); + - (HMAC-)SHA-512 algorithms added; - TOS (DiffServer) and TTL IP header field handling fixed; + - updates according to the new third-party-auth draft (oauth); 2/1/2015 Oleg Moskalenko Version 4.4.1.2 'Ardee West': diff --git a/INSTALL b/INSTALL index 95c56016..00cd59ec 100644 --- a/INSTALL +++ b/INSTALL @@ -470,14 +470,15 @@ libevent2 from their web site. It was tested with older *NIXes NOTE: SQLite must be of version 3.x. -NOTE: For extra security features (DTLS and SHA256) support, OpenSSL version -1.0.0a or newer is recommended. Older versions do not support DTLS, reliably, -in some cases. For example, the Debian 'Squeeze' Linux supplies 0.9.8 version -of OpenSSL, that does not work correctly with DTLS over IPv6. If your system -already has an older version of OpenSSL installed (usually in directory /usr) -then you may want to install your newer OpenSSL "over" the old one (because it -will most probably will not allow removal of the old one). When installing -the newer OpenSSL, run the OpenSSL's configure command like this: +NOTE: For extra security features (DTLS and SHA256 and SHA512) support, OpenSSL +version 1.0.0a or newer is recommended. Older versions do not support DTLS, +reliably, in some cases. For example, the Debian 'Squeeze' Linux supplies +0.9.8 version of OpenSSL, that does not work correctly with DTLS over IPv6. +If your system already has an older version of OpenSSL installed (usually +in directory /usr) then you may want to install your newer OpenSSL "over" +the old one (because it will most probably will not allow removal of the +old one). When installing the newer OpenSSL, run the OpenSSL's configure +command like this: $ ./config --prefix=/usr @@ -676,13 +677,14 @@ CREATE TABLE turnusers_lt ( ); The field hmackey contains HEX string representation of the key. -We do not store the user open passwords for long-term credentials, for security reasons. -Storing only the HMAC key has its own implications - if you change the realm, -you will have to update the HMAC keys of all users, because the realm is -used for the HMAC key generation. +We do not store the user open passwords for long-term credentials, for +security reasons. Storing only the HMAC key has its own implications - +if you change the realm, you will have to update the HMAC keys of all +users, because the realm is 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. +The key must be up to 32 characters (HEX representation of 16 bytes) for SHA1, +or up to 64 characters (HEX representation of 32 bytes) for SHA256, +or up to 128 characters (HEX representation of 64 bytes) for SHA512: # Table holding shared secrets for secret-based authorization # (REST API). It can only be used together with the long-term diff --git a/README.turnadmin b/README.turnadmin index b10f2379..76112fe6 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -95,7 +95,10 @@ Options with required values: -r, --realm Realm. -p, --password Password. -o, --origin Origin --H, --sha256 Use SHA256 as the keys hash function (a non-standard feature). +-H, --sha256 Use SHA256 as the keys hash function (a non-standard feature). + By default, MD5 is used for the key storage encryption + (as required by the current STUN/TURNstandards). +-K, --sha512 Use SHA512 as the keys hash function (a non-standard feature). By default, MD5 is used for the key storage encryption (as required by the current STUN/TURNstandards). --max-bps Set value of realm's max-bps parameter. diff --git a/README.turnserver b/README.turnserver index 5fb0b495..2eb35408 100644 --- a/README.turnserver +++ b/README.turnserver @@ -242,6 +242,7 @@ Flags: SHA256 hash function if this option is used. If the server obtains a message from the client with a weaker (SHA1) hash function then the server returns error code 426. +--sha512 Require SHA512 digest function to be used for the message integrity. --mobility Mobility with ICE (MICE) specs support. diff --git a/README.turnutils b/README.turnutils index a39fa889..3f2977e3 100644 --- a/README.turnutils +++ b/README.turnutils @@ -94,6 +94,8 @@ Flags: -H SHA256 digest function for message integrity calculation. Without this option, by default, SHA1 is used. + +-K SHA512 digest function for message integrity calculation. -M Use TURN ICE Mobility. diff --git a/STATUS b/STATUS index c3f1b1b3..405cd8d8 100644 --- a/STATUS +++ b/STATUS @@ -119,6 +119,8 @@ compatibility. supported in the client library). 52) Web HTTPS admin interface implemented. + +53) SHA512 support added (experimental). Things to be implemented in future (the development roadmap) are described in the TODO file. diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index e4209026..bf67d4f6 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -557,15 +557,16 @@ # #secure-stun -# Require SHA256 digest function to be used for the message integrity. -# By default, the server uses SHA1 (as per TURN standard specs). -# With this option, the server -# always requires the stronger SHA256 function. The client application -# must support SHA256 hash function if this option is used. If the server obtains +# Require SHA256 or SHA512 digest function to be used for the message +# integrity. By default, the server uses SHA1 (as per TURN standard specs). +# With this option, the server always requires the stronger SHA256 or SHA512 +# function. The client application must support SHA256 or SHA512 hash function +# if this option is used. If the server obtains # a message from the client with a weaker (SHA1) hash function then the # server returns error code 426. # #sha256 +#sha512 # Mobility with ICE (MICE) specs support. # diff --git a/examples/var/db/turndb b/examples/var/db/turndb index 1805bfb55f20ec83c60a4a0935daa6ccdc10595f..bad666cb7f6e5ca5436b9114b6b46a5982458457 100644 GIT binary patch delta 521 zcmZqJz}T>Xae}nqN(Kf7F(76IVkRIKny6#UxN>8{0&W3bAeV)C9Ru@Q<{QjMnAdG) zp8Ny7=^3q_IUV466Qciw;N~NVB zBeT3XTrej;Jv9$#FbFULF*^{m0Wk~E^f$}`Tp%X%Y6j-j%!in-Grt9j&Snl3V^Nf5 zMA(&+nN*ZmRLLU3q9~3e47P(=lto^e5pEsS4NO8T^5UFuQLrNxGxD%Za$(!dCi9P< zhne9O1H&uExy&)lF`ET+PB1btwoPnom>i{N#sYNG)QOE#7|ka(8gGu#-z37u^aTiy zZfx{mnjGVn!>B*8QI9ccVxs}0;lxJW$zkq0SAA<*&Ln1wlj`awVdLNNgOlka+~ z3$Zh_F)&FmMKhme3}C#^(8ee^v9W-wQ9zhoTv?g1F@5qZJ!uyf=O9uy!hhOXae}nqOa=x9F(76IVkRKwo2X;VICEpd0`AR>691Ve25>MkZWa*u0Afv& zVc}z8UdO=vmiZ?05$1Kwi#H4MOkw8W7A`C-EH5vgypCVYPnelmUOF$os3b!#J-;j| zCqF->(o%?tSy4Q>C^IiFQ7^wJ9V{)#$Sf}oSD2HZo|?x6bN~zUY6j-j%r}@10j-%2 zv|s{r91kPJ0#-2=MQKKaIXRh0MTtd~ETSy((u{DUpms8guqcWnDF(|k39-nFbHbH^ zZQUfpBEZAS@QQ)q72{l{3CyaS1$0g@GBNC$*w`>RO3#d|QHYgYTv?g1F?;d^A8AIm z$!mP1CtoyFnEcE~X!0{7k;(7%*|^FQb4pV+xin4LCQJL8FtTrs(cdJ(!mPq{d1Ip& z)8rVpoQVN^jII+KU3g1@-h=_8iH&-b!`yc=KV-hSSyA8+GbaaBievI!Z*@La#sCH; X38rY~vy1_Z_cu1$F>Vg<-M|F^=7fNh diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 4f3538f4..23e930d9 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "02 February 2015" "" "" +.TH TURN 1 "04 February 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage @@ -179,6 +179,12 @@ By default, MD5 is used for the key storage encryption (as required by the current STUN/TURNstandards). .TP .B +\fB\-K\fP, \fB\-\-sha512\fP +Use SHA512 as the keys hash function (a non\-standard feature). +By default, MD5 is used for the key storage encryption +(as required by the current STUN/TURNstandards). +.TP +.B \fB\-\-max\-bps\fP Set value of realm's max\-bps parameter. .TP diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 943c7fca..aa7ab86c 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "02 February 2015" "" "" +.TH TURN 1 "04 February 2015" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -372,6 +372,10 @@ from the client with a weaker (SHA1) hash function then the server returns error code 426. .TP .B +\fB\-\-sha512\fP +Require SHA512 digest function to be used for the message integrity. +.TP +.B \fB\-\-mobility\fP Mobility with ICE (MICE) specs support. .TP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index b72d8b39..e605e40f 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "02 February 2015" "" "" +.TH TURN 1 "04 February 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -143,6 +143,10 @@ SHA256 digest function for message integrity calculation. Without this option, by default, SHA1 is used. .TP .B +\fB\-K\fP +SHA512 digest function for message integrity calculation. +.TP +.B \fB\-M\fP Use TURN ICE Mobility. .TP diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 7dd1e65d..49376be4 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -569,6 +569,7 @@ static char Usage[] = "Usage: turnserver [options]\n" " support SHA256 hash function if this option is used. If the server obtains\n" " a message from the client with a weaker (SHA1) hash function then the server\n" " returns error code 426.\n" +" --sha512 Require SHA512 digest function to be used for the message integrity.\n" " --proc-user User name to run the turnserver process.\n" " After the initialization, the turnserver process\n" " will make an attempt to change the current user ID to that user.\n" @@ -638,6 +639,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" #endif " -H, --sha256 Use SHA256 digest function to be used for the message integrity.\n" " By default, the server SHA1 (as per TURN standard specs).\n" + " -K, --sha512 Use SHA512 digest function to be used for the message integrity.\n" " --max-bps Set value of realm's max-bps parameter.\n" " Setting to zero value means removal of the option.\n" " --total-quota Set value of realm's total-quota parameter.\n" @@ -648,7 +650,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" #define OPTIONS "c:d:p:L:E:X:i:m:l:r:u:b:B:e:M:J:N:O:q:Q:s:C:vVofhznaAS" -#define ADMIN_OPTIONS "gGORIHlLkaADSdb:e:M:J:N:u:r:p:s:X:o:h" +#define ADMIN_OPTIONS "gGORIHKlLkaADSdb:e:M:J:N:u:r:p:s:X:o:h" enum EXTRA_OPTS { NO_UDP_OPT=256, @@ -688,6 +690,7 @@ enum EXTRA_OPTS { CA_FILE_OPT, DH_FILE_OPT, SHA256_OPT, + SHA512_OPT, NO_STUN_OPT, PROC_USER_OPT, PROC_GROUP_OPT, @@ -811,6 +814,7 @@ static const struct myoption long_options[] = { { "CA-file", required_argument, NULL, CA_FILE_OPT }, { "dh-file", required_argument, NULL, DH_FILE_OPT }, { "sha256", optional_argument, NULL, SHA256_OPT }, + { "sha512", optional_argument, NULL, SHA512_OPT }, { "proc-user", required_argument, NULL, PROC_USER_OPT }, { "proc-group", required_argument, NULL, PROC_GROUP_OPT }, { "mobility", optional_argument, NULL, MOBILITY_OPT }, @@ -865,6 +869,7 @@ static const struct myoption admin_long_options[] = { { "realm", required_argument, NULL, 'r' }, { "password", required_argument, NULL, 'p' }, { "sha256", no_argument, NULL, 'H' }, + { "sha512", no_argument, NULL, 'K' }, { "add-origin", no_argument, NULL, 'O' }, { "del-origin", no_argument, NULL, 'R' }, { "list-origins", required_argument, NULL, 'I' }, @@ -1031,8 +1036,10 @@ static void set_option(int c, char *value) case SHA256_OPT: if(get_bool_value(value)) turn_params.shatype = SHATYPE_SHA256; - else - turn_params.shatype = SHATYPE_SHA1; + break; + case SHA512_OPT: + if(get_bool_value(value)) + turn_params.shatype = SHATYPE_SHA512; break; case NO_MULTICAST_PEERS_OPT: turn_params.no_multicast_peers = get_bool_value(value); @@ -1554,8 +1561,10 @@ static int adminmain(int argc, char **argv) case 'H': if(get_bool_value(optarg)) turn_params.shatype = SHATYPE_SHA256; - else - turn_params.shatype = SHATYPE_SHA1; + break; + case 'K': + if(get_bool_value(optarg)) + turn_params.shatype = SHATYPE_SHA512; break; case 'h': printf("\n%s\n", AdminUsage); diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 26a5b934..1e4e90b4 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -131,6 +131,7 @@ static char Usage[] = " -O DOS attack mode (quick connect and exit).\n" " -H SHA256 digest function for message integrity calculation.\n" " Without this option, by default, SHA1 is used.\n" + " -K SHA512 digest function for message integrity calculation.\n" " -M ICE Mobility engaged.\n" " -I Do not set permissions on TURN relay endpoints\n" " (for testing the non-standard server relay functionality).\n" @@ -162,20 +163,23 @@ static char Usage[] = ////////////////////////////////////////////////// -void recalculate_restapi_hmac(void) { +void recalculate_restapi_hmac(SHATYPE st) { if (g_use_auth_secret_with_timestamp) { u08bits hmac[MAXSHASIZE]; - unsigned int hmac_len; + unsigned int hmac_len = 0; - hmac_len = SHA256SIZEBYTES; + if(st == SHATYPE_SHA256) + hmac_len = SHA256SIZEBYTES; + else if(st == SHATYPE_SHA512) + hmac_len = SHA512SIZEBYTES; hmac[0] = 0; if (stun_calculate_hmac(g_uname, strlen((char*) g_uname), (u08bits*) g_auth_secret, strlen(g_auth_secret), hmac, - &hmac_len, SHATYPE_SHA256) >= 0) { + &hmac_len, st) >= 0) { size_t pwd_length = 0; char *pwd = base64_encode(hmac, hmac_len, &pwd_length); @@ -211,7 +215,7 @@ int main(int argc, char **argv) ns_bzero(local_addr, sizeof(local_addr)); - while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:ZvsyhcxXgtTSAPDNOUHMRIGBJ")) != -1) { + while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:ZvsyhcxXgtTSAPDNOUHKMRIGBJ")) != -1) { switch (c){ case 'J': { @@ -265,6 +269,9 @@ int main(int argc, char **argv) case 'H': shatype = SHATYPE_SHA256; break; + case 'K': + shatype = SHATYPE_SHA512; + break; case 'E': { char* fn = find_config_file(optarg,1); diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 4dd6a13a..39c6d820 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -526,7 +526,10 @@ static int clnet_allocate(int verbose, clnet_info->server_name, &(clnet_info->oauth))) { if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { clnet_info->shatype = SHATYPE_SHA256; - recalculate_restapi_hmac(); + recalculate_restapi_hmac(clnet_info->shatype); + } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) { + clnet_info->shatype = SHATYPE_SHA512; + recalculate_restapi_hmac(clnet_info->shatype); } goto beg_allocate; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { @@ -724,7 +727,10 @@ static int clnet_allocate(int verbose, clnet_info->server_name, &(clnet_info->oauth))) { if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { clnet_info->shatype = SHATYPE_SHA256; - recalculate_restapi_hmac(); + recalculate_restapi_hmac(clnet_info->shatype); + } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) { + clnet_info->shatype = SHATYPE_SHA512; + recalculate_restapi_hmac(clnet_info->shatype); } goto beg_refresh; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { @@ -822,7 +828,10 @@ static int turn_channel_bind(int verbose, uint16_t *chn, clnet_info->server_name, &(clnet_info->oauth))) { if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { clnet_info->shatype = SHATYPE_SHA256; - recalculate_restapi_hmac(); + recalculate_restapi_hmac(clnet_info->shatype); + } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) { + clnet_info->shatype = SHATYPE_SHA512; + recalculate_restapi_hmac(clnet_info->shatype); } goto beg_bind; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { @@ -930,7 +939,10 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, clnet_info->server_name, &(clnet_info->oauth))) { if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { clnet_info->shatype = SHATYPE_SHA256; - recalculate_restapi_hmac(); + recalculate_restapi_hmac(clnet_info->shatype); + } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) { + clnet_info->shatype = SHATYPE_SHA512; + recalculate_restapi_hmac(clnet_info->shatype); } goto beg_cp; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { @@ -1509,7 +1521,10 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a clnet_info->server_name, &(clnet_info->oauth))) { if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { clnet_info->shatype = SHATYPE_SHA256; - recalculate_restapi_hmac(); + recalculate_restapi_hmac(clnet_info->shatype); + } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) { + clnet_info->shatype = SHATYPE_SHA512; + recalculate_restapi_hmac(clnet_info->shatype); } goto beg_cb; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index a75dd0e2..b6c68fc3 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -753,7 +753,10 @@ static int client_read(app_ur_session *elem, int is_tcp_data, app_tcp_conn_info clnet_info->server_name, &(clnet_info->oauth))) { if(err_code == SHA_TOO_WEAK_ERROR_CODE && (elem->pinfo.shatype == SHATYPE_SHA1)) { elem->pinfo.shatype = SHATYPE_SHA256; - recalculate_restapi_hmac(); + recalculate_restapi_hmac(elem->pinfo.shatype); + } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (elem->pinfo.shatype == SHATYPE_SHA256)) { + elem->pinfo.shatype = SHATYPE_SHA512; + recalculate_restapi_hmac(elem->pinfo.shatype); } if(is_TCP_relay() && (stun_get_method(&(elem->in_buffer)) == STUN_METHOD_CONNECT)) { diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index 045e53ba..fe930f3f 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -109,7 +109,7 @@ turn_credential_type get_turn_credentials_type(void); int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message); int check_integrity(app_ur_conn_info *clnet_info, stun_buffer *message); -void recalculate_restapi_hmac(void); +void recalculate_restapi_hmac(SHATYPE st); //////////////////////////////////////////// diff --git a/src/client/ns_turn_msg_defs.h b/src/client/ns_turn_msg_defs.h index f0a22ee6..78653e05 100644 --- a/src/client/ns_turn_msg_defs.h +++ b/src/client/ns_turn_msg_defs.h @@ -44,7 +44,7 @@ #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 STUN_MAX_PWD_SIZE (256) #define AUTH_SECRET_SIZE STUN_MAX_PWD_SIZE #define STUN_MAGIC_COOKIE (0x2112A442) diff --git a/turndb/schema.sql b/turndb/schema.sql index 2b2edd2e..b44f1bec 100644 --- a/turndb/schema.sql +++ b/turndb/schema.sql @@ -8,7 +8,7 @@ CREATE TABLE turnusers_lt ( CREATE TABLE turn_secret ( realm varchar(127) default '', - value varchar(127), + value varchar(256), primary key (realm,value) ); From 942e11e24e24545390c2fcc0b86da68d2df95f83 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 6 Feb 2015 07:07:06 +0000 Subject: [PATCH 480/805] peer loggin added --- src/server/ns_turn_allocation.c | 6 ++++++ src/server/ns_turn_allocation.h | 2 ++ src/server/ns_turn_server.c | 8 ++++++++ 3 files changed, 16 insertions(+) diff --git a/src/server/ns_turn_allocation.c b/src/server/ns_turn_allocation.c index 26980dde..7fef9b1e 100644 --- a/src/server/ns_turn_allocation.c +++ b/src/server/ns_turn_allocation.c @@ -172,6 +172,12 @@ void turn_permission_clean(turn_permission_info* tinfo) { if (tinfo && tinfo->allocated) { + if(tinfo->verbose) { + char s[257]="\0"; + addr_to_string(&(tinfo->addr),(u08bits*)s); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: peer %s deleted\n",tinfo->session_id,s); + } + if(!(tinfo->lifetime_ev)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: strange (1) permission to be cleaned\n",__FUNCTION__); } diff --git a/src/server/ns_turn_allocation.h b/src/server/ns_turn_allocation.h index 96da5684..ff3d4594 100644 --- a/src/server/ns_turn_allocation.h +++ b/src/server/ns_turn_allocation.h @@ -147,6 +147,8 @@ typedef struct _turn_permission_info { turn_time_t expiration_time; ioa_timer_handle lifetime_ev; void* owner; //a + int verbose; + unsigned long long session_id; } turn_permission_info; typedef struct _turn_permission_slot { diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 7a61f59e..53f22e29 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -856,6 +856,14 @@ static int update_turn_permission_lifetime(ts_ur_super_session *ss, turn_permiss client_ss_perm_timeout_handler, tinfo, 0, "client_ss_channel_timeout_handler"); + if(server->verbose) { + tinfo->verbose = 1; + tinfo->session_id = ss->id; + char s[257]="\0"; + addr_to_string(&(tinfo->addr),(u08bits*)s); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: peer %s lifetime updated: %lu\n",(unsigned long long)ss->id,s,(unsigned long)time_delta); + } + return 0; } } From 28f125534e182f621c0b0ddbb8c7cba98ad4eeab Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 6 Feb 2015 07:07:55 +0000 Subject: [PATCH 481/805] changelog --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index a7ee0ab1..985463d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ Version 4.4.2.1 'Ardee West': - (HMAC-)SHA-512 algorithms added; - TOS (DiffServer) and TTL IP header field handling fixed; - updates according to the new third-party-auth draft (oauth); + - peer logging added; 2/1/2015 Oleg Moskalenko Version 4.4.1.2 'Ardee West': From 07753ebebceebb387d2f358a40a362290e655708 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 6 Feb 2015 07:41:29 +0000 Subject: [PATCH 482/805] sha512 fixes --- src/client/ns_turn_msg.c | 14 +++++++++++++- src/client/ns_turn_msg_defs_new.h | 1 + src/server/ns_turn_server.c | 19 ++++++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index fd9004ad..46f72002 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1647,21 +1647,33 @@ int stun_check_message_integrity_by_key_str(turn_credential_type ct, u08bits *bu switch(sarlen) { case SHA256SIZEBYTES: shasize = SHA256SIZEBYTES; + if(shatype > SHATYPE_SHA256) { + if(too_weak) + *too_weak = 1; + return -1; + } if(shatype != SHATYPE_SHA256) return -1; break; case SHA512SIZEBYTES: shasize = SHA512SIZEBYTES; + if(shatype > SHATYPE_SHA512) { + if(too_weak) + *too_weak = 1; + return -1; + } if(shatype != SHATYPE_SHA512) return -1; break; case SHA1SIZEBYTES: shasize = SHA1SIZEBYTES; - if(shatype != SHATYPE_SHA1) { + if(shatype > SHATYPE_SHA1) { if(too_weak) *too_weak = 1; return -1; } + if(shatype != SHATYPE_SHA1) + return -1; break; default: return -1; diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index ae0b122c..baa6f9d2 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -65,6 +65,7 @@ typedef enum _SHATYPE SHATYPE; #define shatype_name(sht) ((sht == SHATYPE_SHA1) ? "SHA1" : ((sht == SHATYPE_SHA256) ? "SHA256" : ((sht == SHATYPE_SHA512) ? "SHA512" : "SHA UNKNOWN"))) #define SHA_TOO_WEAK_ERROR_CODE (426) +#define SHA_TOO_WEAK_ERROR_REASON ((const u08bits*)("credentials too weak")) /* <<== SHA AGILITY */ diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 53f22e29..71c7d2d7 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3292,20 +3292,36 @@ static int check_stun_auth(turn_turnserver *server, { int sarlen = stun_attr_get_len(sar); + switch(sarlen) { case SHA1SIZEBYTES: - if(server->shatype != SHATYPE_SHA1) { + if(server->shatype > SHATYPE_SHA1) { *err_code = SHA_TOO_WEAK_ERROR_CODE; + *reason = SHA_TOO_WEAK_ERROR_REASON; + return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); + } + if(server->shatype != SHATYPE_SHA1) { + *err_code = 401; return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); } break; case SHA256SIZEBYTES: + if(server->shatype > SHATYPE_SHA256) { + *err_code = SHA_TOO_WEAK_ERROR_CODE; + *reason = SHA_TOO_WEAK_ERROR_REASON; + return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); + } if(server->shatype != SHATYPE_SHA256) { *err_code = 401; return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); } break; case SHA512SIZEBYTES: + if(server->shatype > SHATYPE_SHA512) { + *err_code = SHA_TOO_WEAK_ERROR_CODE; + *reason = SHA_TOO_WEAK_ERROR_REASON; + return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); + } if(server->shatype != SHATYPE_SHA512) { *err_code = 401; return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); @@ -3452,6 +3468,7 @@ static int check_stun_auth(turn_turnserver *server, "%s: user %s credentials are incorrect: SHA function is too weak\n", __FUNCTION__, (char*)usname); *err_code = SHA_TOO_WEAK_ERROR_CODE; + *reason = SHA_TOO_WEAK_ERROR_REASON; *reason = (const u08bits*)"Unauthorised: weak SHA function is used"; return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); } From caf63a35de9089eceb56deeb42f69936fcf1e24d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 6 Feb 2015 08:17:49 +0000 Subject: [PATCH 483/805] sha384 added --- ChangeLog | 1 + INSTALL | 29 +++++++++-------- README.turnadmin | 5 ++- README.turnserver | 3 ++ README.turnutils | 2 ++ STATUS | 2 +- examples/etc/turnserver.conf | 7 +++-- man/man1/turnadmin.1 | 10 +++--- man/man1/turnserver.1 | 6 +++- man/man1/turnutils.1 | 6 +++- src/apps/relay/mainrelay.c | 15 ++++++++- src/apps/relay/turn_admin_server.c | 22 +++++++++++++ src/apps/relay/userdb.c | 11 +++++++ src/apps/rfc5769/rfc5769check.c | 6 ++++ src/apps/uclient/mainuclient.c | 11 ++++++- src/apps/uclient/startuclient.c | 15 +++++++++ src/apps/uclient/uclient.c | 5 +++ src/client/ns_turn_msg.c | 50 +++++++++++++++++++++++++++++- src/client/ns_turn_msg_defs_new.h | 5 ++- src/server/ns_turn_server.c | 11 +++++++ turndb/schema.userdb.redis | 10 +++--- 21 files changed, 198 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 985463d8..1b19e32c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 2/3/2015 Oleg Moskalenko Version 4.4.2.1 'Ardee West': - (HMAC-)SHA-512 algorithms added; + - (HMAC-)SHA-384 algorithms added; - TOS (DiffServer) and TTL IP header field handling fixed; - updates according to the new third-party-auth draft (oauth); - peer logging added; diff --git a/INSTALL b/INSTALL index 00cd59ec..23059ca6 100644 --- a/INSTALL +++ b/INSTALL @@ -470,15 +470,15 @@ libevent2 from their web site. It was tested with older *NIXes NOTE: SQLite must be of version 3.x. -NOTE: For extra security features (DTLS and SHA256 and SHA512) support, OpenSSL -version 1.0.0a or newer is recommended. Older versions do not support DTLS, -reliably, in some cases. For example, the Debian 'Squeeze' Linux supplies -0.9.8 version of OpenSSL, that does not work correctly with DTLS over IPv6. -If your system already has an older version of OpenSSL installed (usually -in directory /usr) then you may want to install your newer OpenSSL "over" -the old one (because it will most probably will not allow removal of the -old one). When installing the newer OpenSSL, run the OpenSSL's configure -command like this: +NOTE: For extra security features (DTLS and SHA256 and and SHA384 and SHA512) +support, OpenSSL version 1.0.0a or newer is recommended. Older versions do +not support DTLS, reliably, in some cases. For example, the Debian 'Squeeze' +Linux supplies 0.9.8 version of OpenSSL, that does not work correctly with +DTLS over IPv6. If your system already has an older version of OpenSSL +installed (usually in directory /usr) then you may want to install your +newer OpenSSL "over" the old one (because it will most probably will not allow +removal of the old one). When installing the newer OpenSSL, run the OpenSSL's +configure command like this: $ ./config --prefix=/usr @@ -684,6 +684,7 @@ users, because the realm is used for the HMAC key generation. The key must be up to 32 characters (HEX representation of 16 bytes) for SHA1, or up to 64 characters (HEX representation of 32 bytes) for SHA256, +or up to 96 characters (HEX representation of 48 bytes) for SHA384, or up to 128 characters (HEX representation of 64 bytes) for SHA512: # Table holding shared secrets for secret-based authorization @@ -765,9 +766,10 @@ The oauth_key table fields meanings are: is 0 - unlimited lifetime. hkdf_hash_func - (optional) hash function for HKDF procedure; the - valid values are SHA-1, SHA-256 and SHA-512, with SHA-256 as default; - The hkdf_hash_func is not needed if the as_rs_key and auth_key - are defined explicitly in the database; + valid values are SHA-1, SHA-256, SHA-384 and SHA-512, + with SHA-256 as default. The hkdf_hash_func is not needed + if the as_rs_key and auth_key are defined explicitly + in the database; as_rs_alg - oAuth token encryption algorithm; the valid values are "AES-128-CBC" and "AES-256-CBC", , "AEAD-AES-128-GCM", @@ -779,7 +781,8 @@ The oauth_key table fields meanings are: is defined by as_rs_alg. auth_alg - (optional) oAuth token authentication algorithm; the valid values are - "HMAC-SHA-256-128", "HMAC-SHA-256", "HMAC-SHA-512" and "HMAC-SHA-1". + "HMAC-SHA-256-128", "HMAC-SHA-256", "HMAC-SHA-384", + "HMAC-SHA-512" and "HMAC-SHA-1". The default value is "HMAC-SHA-256-128". auth_key - (optional) base64-encoded AUTH key. If not defined, then diff --git a/README.turnadmin b/README.turnadmin index 76112fe6..53166f6c 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -98,9 +98,8 @@ Options with required values: -H, --sha256 Use SHA256 as the keys hash function (a non-standard feature). By default, MD5 is used for the key storage encryption (as required by the current STUN/TURNstandards). --K, --sha512 Use SHA512 as the keys hash function (a non-standard feature). - By default, MD5 is used for the key storage encryption - (as required by the current STUN/TURNstandards). +-Y, --sha384 Use SHA384 as the keys hash function (a non-standard feature). +-K, --sha512 Use SHA512 as the keys hash function (a non-standard feature). --max-bps Set value of realm's max-bps parameter. --total-quota Set value of realm's total-quota parameter. --user-quota Set value of realm's user-quota parameter. diff --git a/README.turnserver b/README.turnserver index 2eb35408..22f1a505 100644 --- a/README.turnserver +++ b/README.turnserver @@ -242,6 +242,9 @@ Flags: SHA256 hash function if this option is used. If the server obtains a message from the client with a weaker (SHA1) hash function then the server returns error code 426. + +--sha384 Require SHA384 digest function to be used for the message integrity. + --sha512 Require SHA512 digest function to be used for the message integrity. --mobility Mobility with ICE (MICE) specs support. diff --git a/README.turnutils b/README.turnutils index 3f2977e3..a23ddbbb 100644 --- a/README.turnutils +++ b/README.turnutils @@ -95,6 +95,8 @@ Flags: -H SHA256 digest function for message integrity calculation. Without this option, by default, SHA1 is used. +-Y SHA384 digest function for message integrity calculation. + -K SHA512 digest function for message integrity calculation. -M Use TURN ICE Mobility. diff --git a/STATUS b/STATUS index 405cd8d8..499804ae 100644 --- a/STATUS +++ b/STATUS @@ -120,7 +120,7 @@ supported in the client library). 52) Web HTTPS admin interface implemented. -53) SHA512 support added (experimental). +53) SHA384 and SHA512 support added (experimental). Things to be implemented in future (the development roadmap) are described in the TODO file. diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index bf67d4f6..9ae0f375 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -557,15 +557,16 @@ # #secure-stun -# Require SHA256 or SHA512 digest function to be used for the message +# Require SHA256, or SHA384, or SHA512 digest function to be used for the message # integrity. By default, the server uses SHA1 (as per TURN standard specs). -# With this option, the server always requires the stronger SHA256 or SHA512 -# function. The client application must support SHA256 or SHA512 hash function +# With this option, the server always requires the stronger SHA256, SHA384 or SHA512 +# function. The client application must support SHA256, SHA384 or SHA512 hash function # if this option is used. If the server obtains # a message from the client with a weaker (SHA1) hash function then the # server returns error code 426. # #sha256 +#sha384 #sha512 # Mobility with ICE (MICE) specs support. diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 23e930d9..be71dfd8 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "04 February 2015" "" "" +.TH TURN 1 "06 February 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage @@ -179,10 +179,12 @@ By default, MD5 is used for the key storage encryption (as required by the current STUN/TURNstandards). .TP .B +\fB\-Y\fP, \fB\-\-sha384\fP +Use SHA384 as the keys hash function (a non\-standard feature). +.TP +.B \fB\-K\fP, \fB\-\-sha512\fP -Use SHA512 as the keys hash function (a non\-standard feature). -By default, MD5 is used for the key storage encryption -(as required by the current STUN/TURNstandards). +Use SHA512 as the keys hash function (a non\-standard feature). .TP .B \fB\-\-max\-bps\fP diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index aa7ab86c..7b3b475f 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "04 February 2015" "" "" +.TH TURN 1 "06 February 2015" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -372,6 +372,10 @@ from the client with a weaker (SHA1) hash function then the server returns error code 426. .TP .B +\fB\-\-sha384\fP +Require SHA384 digest function to be used for the message integrity. +.TP +.B \fB\-\-sha512\fP Require SHA512 digest function to be used for the message integrity. .TP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index e605e40f..83f28d48 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "04 February 2015" "" "" +.TH TURN 1 "06 February 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -143,6 +143,10 @@ SHA256 digest function for message integrity calculation. Without this option, by default, SHA1 is used. .TP .B +\fB\-Y\fP +SHA384 digest function for message integrity calculation. +.TP +.B \fB\-K\fP SHA512 digest function for message integrity calculation. .TP diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 49376be4..829842b0 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -569,6 +569,7 @@ static char Usage[] = "Usage: turnserver [options]\n" " support SHA256 hash function if this option is used. If the server obtains\n" " a message from the client with a weaker (SHA1) hash function then the server\n" " returns error code 426.\n" +" --sha384 Require SHA384 digest function to be used for the message integrity.\n" " --sha512 Require SHA512 digest function to be used for the message integrity.\n" " --proc-user User name to run the turnserver process.\n" " After the initialization, the turnserver process\n" @@ -639,6 +640,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" #endif " -H, --sha256 Use SHA256 digest function to be used for the message integrity.\n" " By default, the server SHA1 (as per TURN standard specs).\n" + " -Y, --sha384 Use SHA384 digest function to be used for the message integrity.\n" " -K, --sha512 Use SHA512 digest function to be used for the message integrity.\n" " --max-bps Set value of realm's max-bps parameter.\n" " Setting to zero value means removal of the option.\n" @@ -650,7 +652,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" #define OPTIONS "c:d:p:L:E:X:i:m:l:r:u:b:B:e:M:J:N:O:q:Q:s:C:vVofhznaAS" -#define ADMIN_OPTIONS "gGORIHKlLkaADSdb:e:M:J:N:u:r:p:s:X:o:h" +#define ADMIN_OPTIONS "gGORIHKYlLkaADSdb:e:M:J:N:u:r:p:s:X:o:h" enum EXTRA_OPTS { NO_UDP_OPT=256, @@ -690,6 +692,7 @@ enum EXTRA_OPTS { CA_FILE_OPT, DH_FILE_OPT, SHA256_OPT, + SHA384_OPT, SHA512_OPT, NO_STUN_OPT, PROC_USER_OPT, @@ -814,6 +817,7 @@ static const struct myoption long_options[] = { { "CA-file", required_argument, NULL, CA_FILE_OPT }, { "dh-file", required_argument, NULL, DH_FILE_OPT }, { "sha256", optional_argument, NULL, SHA256_OPT }, + { "sha384", optional_argument, NULL, SHA384_OPT }, { "sha512", optional_argument, NULL, SHA512_OPT }, { "proc-user", required_argument, NULL, PROC_USER_OPT }, { "proc-group", required_argument, NULL, PROC_GROUP_OPT }, @@ -869,6 +873,7 @@ static const struct myoption admin_long_options[] = { { "realm", required_argument, NULL, 'r' }, { "password", required_argument, NULL, 'p' }, { "sha256", no_argument, NULL, 'H' }, + { "sha384", no_argument, NULL, 'Y' }, { "sha512", no_argument, NULL, 'K' }, { "add-origin", no_argument, NULL, 'O' }, { "del-origin", no_argument, NULL, 'R' }, @@ -1037,6 +1042,10 @@ static void set_option(int c, char *value) if(get_bool_value(value)) turn_params.shatype = SHATYPE_SHA256; break; + case SHA384_OPT: + if(get_bool_value(value)) + turn_params.shatype = SHATYPE_SHA384; + break; case SHA512_OPT: if(get_bool_value(value)) turn_params.shatype = SHATYPE_SHA512; @@ -1562,6 +1571,10 @@ static int adminmain(int argc, char **argv) if(get_bool_value(optarg)) turn_params.shatype = SHATYPE_SHA256; break; + case 'Y': + if(get_bool_value(optarg)) + turn_params.shatype = SHATYPE_SHA384; + break; case 'K': if(get_bool_value(optarg)) turn_params.shatype = SHATYPE_SHA512; diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 8ad74912..ec61235f 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -712,6 +712,8 @@ static void cli_print_configuration(struct cli_session* cs) if(turn_params.shatype == SHATYPE_SHA256) cli_print_str(cs,"SHA256","SHA type",0); + else if(turn_params.shatype == SHATYPE_SHA384) + cli_print_str(cs,"SHA384","SHA type",0); else if(turn_params.shatype == SHATYPE_SHA512) cli_print_str(cs,"SHA512","SHA type",0); else @@ -1981,6 +1983,8 @@ static void write_pc_page(ioa_socket_handle s) if(turn_params.shatype == SHATYPE_SHA256) https_print_str(sb,"SHA256","SHA type",0); + else if(turn_params.shatype == SHATYPE_SHA384) + https_print_str(sb,"SHA384","SHA type",0); else if(turn_params.shatype == SHATYPE_SHA512) https_print_str(sb,"SHA512","SHA type",0); else @@ -2512,6 +2516,8 @@ static void write_users_page(ioa_socket_handle s, const u08bits *add_user, const if(turn_params.shatype == SHATYPE_SHA256) str_buffer_append(sb,"SHA type: SHA256
\r\n"); + else if(turn_params.shatype == SHATYPE_SHA384) + str_buffer_append(sb,"SHA type: SHA384
\r\n"); else if(turn_params.shatype == SHATYPE_SHA512) str_buffer_append(sb,"SHA type: SHA512
\r\n"); else @@ -3054,6 +3060,14 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con } str_buffer_append(sb,">SHA-256\r\n
\r\n"); + str_buffer_append(sb,"SHA-384\r\n
\r\n"); + str_buffer_append(sb,"HMAC-SHA-256\r\n
\r\n"); + str_buffer_append(sb,"HMAC-SHA-384\r\n
\r\n"); + str_buffer_append(sb,"shatype = SHATYPE_SHA256; recalculate_restapi_hmac(clnet_info->shatype); } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) { + clnet_info->shatype = SHATYPE_SHA384; + recalculate_restapi_hmac(clnet_info->shatype); + } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA384)) { clnet_info->shatype = SHATYPE_SHA512; recalculate_restapi_hmac(clnet_info->shatype); } @@ -729,6 +732,9 @@ static int clnet_allocate(int verbose, clnet_info->shatype = SHATYPE_SHA256; recalculate_restapi_hmac(clnet_info->shatype); } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) { + clnet_info->shatype = SHATYPE_SHA384; + recalculate_restapi_hmac(clnet_info->shatype); + } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA384)) { clnet_info->shatype = SHATYPE_SHA512; recalculate_restapi_hmac(clnet_info->shatype); } @@ -830,6 +836,9 @@ static int turn_channel_bind(int verbose, uint16_t *chn, clnet_info->shatype = SHATYPE_SHA256; recalculate_restapi_hmac(clnet_info->shatype); } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) { + clnet_info->shatype = SHATYPE_SHA384; + recalculate_restapi_hmac(clnet_info->shatype); + } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA384)) { clnet_info->shatype = SHATYPE_SHA512; recalculate_restapi_hmac(clnet_info->shatype); } @@ -941,6 +950,9 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, clnet_info->shatype = SHATYPE_SHA256; recalculate_restapi_hmac(clnet_info->shatype); } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) { + clnet_info->shatype = SHATYPE_SHA384; + recalculate_restapi_hmac(clnet_info->shatype); + } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA384)) { clnet_info->shatype = SHATYPE_SHA512; recalculate_restapi_hmac(clnet_info->shatype); } @@ -1523,6 +1535,9 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a clnet_info->shatype = SHATYPE_SHA256; recalculate_restapi_hmac(clnet_info->shatype); } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) { + clnet_info->shatype = SHATYPE_SHA384; + recalculate_restapi_hmac(clnet_info->shatype); + } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA384)) { clnet_info->shatype = SHATYPE_SHA512; recalculate_restapi_hmac(clnet_info->shatype); } diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index b6c68fc3..e73109a7 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -755,6 +755,9 @@ static int client_read(app_ur_session *elem, int is_tcp_data, app_tcp_conn_info elem->pinfo.shatype = SHATYPE_SHA256; recalculate_restapi_hmac(elem->pinfo.shatype); } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (elem->pinfo.shatype == SHATYPE_SHA256)) { + elem->pinfo.shatype = SHATYPE_SHA384; + recalculate_restapi_hmac(elem->pinfo.shatype); + } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (elem->pinfo.shatype == SHATYPE_SHA384)) { elem->pinfo.shatype = SHATYPE_SHA512; recalculate_restapi_hmac(elem->pinfo.shatype); } @@ -1629,6 +1632,8 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) otoken.enc_block.timestamp = ((uint64_t)turn_time()) << 16; if(shatype == SHATYPE_SHA256) { otoken.enc_block.key_length = 32; + } else if(shatype == SHATYPE_SHA384) { + otoken.enc_block.key_length = 48; } else if(shatype == SHATYPE_SHA512) { otoken.enc_block.key_length = 64; } else { diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 46f72002..92334cf0 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -125,6 +125,15 @@ int stun_calculate_hmac(const u08bits *buf, size_t len, const u08bits *key, size #else fprintf(stderr,"SHA256 is not supported\n"); return -1; +#endif + } else if(shatype == SHATYPE_SHA384) { +#if !defined(OPENSSL_NO_SHA384) && defined(SHA384_DIGEST_LENGTH) + if (!HMAC(EVP_sha384(), key, keylen, buf, len, hmac, hmac_len)) { + return -1; + } +#else + fprintf(stderr,"SHA384 is not supported\n"); + return -1; #endif } else if(shatype == SHATYPE_SHA512) { #if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH) @@ -173,6 +182,18 @@ int stun_produce_integrity_key_str(u08bits *uname, u08bits *realm, u08bits *upwd #else fprintf(stderr,"SHA256 is not supported\n"); return -1; +#endif + } else if(shatype == SHATYPE_SHA384) { +#if !defined(OPENSSL_NO_SHA384) && defined(SHA384_DIGEST_LENGTH) + unsigned int keylen = 0; + EVP_MD_CTX ctx; + EVP_DigestInit(&ctx,EVP_sha384()); + EVP_DigestUpdate(&ctx,str,strl); + EVP_DigestFinal(&ctx,key,&keylen); + EVP_MD_CTX_cleanup(&ctx); +#else + fprintf(stderr,"SHA384 is not supported\n"); + return -1; #endif } else if(shatype == SHATYPE_SHA512) { #if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH) @@ -1538,6 +1559,8 @@ size_t get_hmackey_size(SHATYPE shatype) { if(shatype == SHATYPE_SHA256) return 32; + if(shatype == SHATYPE_SHA384) + return 48; if(shatype == SHATYPE_SHA512) return 64; return 16; @@ -1563,6 +1586,9 @@ int stun_attr_add_integrity_str(turn_credential_type ct, u08bits *buf, size_t *l case SHATYPE_SHA256: shasize = SHA256SIZEBYTES; break; + case SHATYPE_SHA384: + shasize = SHA384SIZEBYTES; + break; case SHATYPE_SHA512: shasize = SHA512SIZEBYTES; break; @@ -1655,6 +1681,16 @@ int stun_check_message_integrity_by_key_str(turn_credential_type ct, u08bits *bu if(shatype != SHATYPE_SHA256) return -1; break; + case SHA384SIZEBYTES: + shasize = SHA384SIZEBYTES; + if(shatype > SHATYPE_SHA384) { + if(too_weak) + *too_weak = 1; + return -1; + } + if(shatype != SHATYPE_SHA384) + return -1; + break; case SHA512SIZEBYTES: shasize = SHA512SIZEBYTES; if(shatype > SHATYPE_SHA512) { @@ -1861,6 +1897,8 @@ static size_t calculate_auth_key_length(AUTH_ALG a) return 32; case AUTH_ALG_HMAC_SHA_256: return 32; + case AUTH_ALG_HMAC_SHA_384: + return 48; case AUTH_ALG_HMAC_SHA_512: return 64; default: @@ -1879,6 +1917,8 @@ static size_t calculate_auth_output_length(AUTH_ALG a) return 16; case AUTH_ALG_HMAC_SHA_256: return 32; + case AUTH_ALG_HMAC_SHA_384: + return 48; case AUTH_ALG_HMAC_SHA_512: return 64; default: @@ -2004,6 +2044,8 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er key->hkdf_hash_func = SHATYPE_SHA1; } else if(!strcmp(oakd->hkdf_hash_func,"SHA256") || !strcmp(oakd->hkdf_hash_func,"SHA-256")) { key->hkdf_hash_func = SHATYPE_SHA256; + } else if(!strcmp(oakd->hkdf_hash_func,"SHA384") || !strcmp(oakd->hkdf_hash_func,"SHA-384")) { + key->hkdf_hash_func = SHATYPE_SHA384; } else if(!strcmp(oakd->hkdf_hash_func,"SHA512") || !strcmp(oakd->hkdf_hash_func,"SHA-512")) { key->hkdf_hash_func = SHATYPE_SHA512; } else if(oakd->hkdf_hash_func[0]) { @@ -2019,6 +2061,8 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er key->auth_alg = AUTH_ALG_HMAC_SHA_1; } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256")) { key->auth_alg = AUTH_ALG_HMAC_SHA_256; + } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-384")) { + key->auth_alg = AUTH_ALG_HMAC_SHA_384; } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-512")) { key->auth_alg = AUTH_ALG_HMAC_SHA_512; } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256-128")) { @@ -2104,10 +2148,14 @@ static const EVP_MD *get_auth_type(AUTH_ALG aa) case AUTH_ALG_HMAC_SHA_256_128: case AUTH_ALG_HMAC_SHA_256: return EVP_sha256(); +#endif +#if !defined(OPENSSL_NO_SHA384) && defined(SHA384_DIGEST_LENGTH) + case AUTH_ALG_HMAC_SHA_384: + return EVP_sha384(); +#endif #if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH) case AUTH_ALG_HMAC_SHA_512: return EVP_sha512(); -#endif #endif default: break; diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index baa6f9d2..9e5d2cf5 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -48,6 +48,7 @@ #define SHA1SIZEBYTES (20) #define SHA256SIZEBYTES (32) +#define SHA384SIZEBYTES (48) #define SHA512SIZEBYTES (64) #define MAXSHASIZE (128) @@ -57,12 +58,13 @@ enum _SHATYPE { SHATYPE_DEFAULT=0, SHATYPE_SHA1=SHATYPE_DEFAULT, SHATYPE_SHA256, + SHATYPE_SHA384, SHATYPE_SHA512 }; typedef enum _SHATYPE SHATYPE; -#define shatype_name(sht) ((sht == SHATYPE_SHA1) ? "SHA1" : ((sht == SHATYPE_SHA256) ? "SHA256" : ((sht == SHATYPE_SHA512) ? "SHA512" : "SHA UNKNOWN"))) +#define shatype_name(sht) ((sht == SHATYPE_SHA1) ? "SHA1" : ((sht == SHATYPE_SHA256) ? "SHA256" : ((sht == SHATYPE_SHA384) ? "SHA384" : "SHA512"))) #define SHA_TOO_WEAK_ERROR_CODE (426) #define SHA_TOO_WEAK_ERROR_REASON ((const u08bits*)("credentials too weak")) @@ -94,6 +96,7 @@ enum _AUTH_ALG { AUTH_ALG_HMAC_SHA_256_128 = AUTH_ALG_DEFAULT, AUTH_ALG_HMAC_SHA_1, AUTH_ALG_HMAC_SHA_256, + AUTH_ALG_HMAC_SHA_384, AUTH_ALG_HMAC_SHA_512 }; diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 71c7d2d7..55bc3b85 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3316,6 +3316,17 @@ static int check_stun_auth(turn_turnserver *server, return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); } break; + case SHA384SIZEBYTES: + if(server->shatype > SHATYPE_SHA384) { + *err_code = SHA_TOO_WEAK_ERROR_CODE; + *reason = SHA_TOO_WEAK_ERROR_REASON; + return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); + } + if(server->shatype != SHATYPE_SHA384) { + *err_code = 401; + return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); + } + break; case SHA512SIZEBYTES: if(server->shatype > SHATYPE_SHA512) { *err_code = SHA_TOO_WEAK_ERROR_CODE; diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis index e25fcd5b..31bc8b51 100644 --- a/turndb/schema.userdb.redis +++ b/turndb/schema.userdb.redis @@ -45,9 +45,10 @@ and they will be almost immediately "seen" by the turnserver process. is 0 - unlimited lifetime. hkdf_hash_func - (optional) hash function for HKDF procedure; the - valid values are SHA-1, SHA-256 and SHA-512, with SHA-256 as default; - The hkdf_hash_func is not needed if the as_rs_key and auth_key - are defined explicitly in the database; + valid values are SHA-1, SHA-256, SHA-384 and SHA-512, + with SHA-256 as default. The hkdf_hash_func is not needed + if the as_rs_key and auth_key are defined explicitly + in the database; as_rs_alg - oAuth token encryption algorithm; the valid values are "AES-128-CBC" and "AES-256-CBC", , "AEAD-AES-128-GCM", @@ -59,7 +60,8 @@ and they will be almost immediately "seen" by the turnserver process. is defined by as_rs_alg. auth_alg - (optional) oAuth token authentication algorithm; the valid values are - "HMAC-SHA-256-128", "HMAC-SHA-256", "HMAC-SHA-512" and "HMAC-SHA-1". + "HMAC-SHA-256-128", "HMAC-SHA-256", "HMAC-SHA-384", + "HMAC-SHA-512" and "HMAC-SHA-1". The default value is "HMAC-SHA-256-128". auth_key - (optional) base64-encoded AUTH key. If not defined, then From 20235c1a100e3a9c11894a75b503c7885e8f21cd Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 7 Feb 2015 07:44:11 +0000 Subject: [PATCH 484/805] new "info" strings for the oauth key generation --- src/apps/rfc5769/rfc5769check.c | 2 +- src/client/ns_turn_msg.c | 34 ++++++++++++++++++++------------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/apps/rfc5769/rfc5769check.c b/src/apps/rfc5769/rfc5769check.c index 173b96fc..36cde6db 100644 --- a/src/apps/rfc5769/rfc5769check.c +++ b/src/apps/rfc5769/rfc5769check.c @@ -77,7 +77,7 @@ void print_field5769(const char* name, const void* f0, size_t len) { printf("\nfield %s %lu==>>\n",name,(unsigned long)len); size_t i; for(i = 0;ihmac1_len) { ns_bcopy(hmac1,buf,hmac1_len); - buf[hmac1_len]=2; + ns_bcopy(info,buf+hmac1_len,info_len); + buf[hmac1_len+info_len]=0x02; u08bits hmac2[128]; unsigned int hmac2_len = 0; - stun_calculate_hmac((const u08bits *)buf, hmac1_len+1, prk, prk_len, hmac2, &hmac2_len, shatype); + stun_calculate_hmac((const u08bits *)buf, hmac1_len+info_len+1, prk, prk_len, hmac2, &hmac2_len, shatype); ns_bcopy(hmac2,new_key+hmac1_len,hmac2_len); if(new_key_size > (hmac1_len + hmac2_len)) { ns_bcopy(hmac2,buf,hmac2_len); - buf[hmac2_len]=3; + ns_bcopy(info,buf+hmac2_len,info_len); + buf[hmac2_len+info_len]=0x03; u08bits hmac3[128]; unsigned int hmac3_len = 0; - stun_calculate_hmac((const u08bits *)buf, hmac2_len+1, prk, prk_len, hmac3, &hmac3_len, shatype); + stun_calculate_hmac((const u08bits *)buf, hmac2_len+info_len+1, prk, prk_len, hmac3, &hmac3_len, shatype); ns_bcopy(hmac3,new_key+hmac1_len+hmac2_len,hmac3_len); if(new_key_size > (hmac1_len + hmac2_len + hmac3_len)) { ns_bcopy(hmac3,buf,hmac3_len); - buf[hmac3_len]=4; + ns_bcopy(info,buf+hmac3_len,info_len); + buf[hmac3_len+info_len]=0x04; u08bits hmac4[128]; unsigned int hmac4_len = 0; - stun_calculate_hmac((const u08bits *)buf, hmac3_len+1, prk, prk_len, hmac4, &hmac4_len, shatype); + stun_calculate_hmac((const u08bits *)buf, hmac3_len+info_len+1, prk, prk_len, hmac4, &hmac4_len, shatype); ns_bcopy(hmac4,new_key+hmac1_len+hmac2_len+hmac3_len,hmac4_len); if(new_key_size > (hmac1_len + hmac2_len + hmac3_len + hmac4_len)) { @@ -2103,14 +2111,14 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er key->auth_key[0] = 0; } else if(!(key->auth_key_size)) { key->auth_key_size = calculate_auth_key_length(key->auth_alg); - if(calculate_key(key->ikm_key,key->ikm_key_size,key->auth_key,key->auth_key_size,key->hkdf_hash_func,err_msg,err_msg_size)<0) { + if(calculate_key(key->ikm_key,key->ikm_key_size,key->auth_key,key->auth_key_size,key->hkdf_hash_func,err_msg,err_msg_size,"AUTH key")<0) { return -1; } } if(!(key->as_rs_key_size)) { key->as_rs_key_size = calculate_enc_key_length(key->as_rs_alg); - if(calculate_key(key->ikm_key,key->ikm_key_size,key->as_rs_key,key->as_rs_key_size,key->hkdf_hash_func,err_msg,err_msg_size)<0) { + if(calculate_key(key->ikm_key,key->ikm_key_size,key->as_rs_key,key->as_rs_key_size,key->hkdf_hash_func,err_msg,err_msg_size,"AS-RS key")<0) { return -1; } } From 1e83139b8ed67236701b8dee23085ab41683ba75 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 8 Feb 2015 20:26:37 +0000 Subject: [PATCH 485/805] text change --- ChangeLog | 3 +-- TODO | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1b19e32c..d6f247bd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,6 @@ 2/3/2015 Oleg Moskalenko Version 4.4.2.1 'Ardee West': - - (HMAC-)SHA-512 algorithms added; - - (HMAC-)SHA-384 algorithms added; + - (HMAC-)SHA-512 and -384 algorithms added; - TOS (DiffServer) and TTL IP header field handling fixed; - updates according to the new third-party-auth draft (oauth); - peer logging added; diff --git a/TODO b/TODO index cc38d831..8fe61eb1 100644 --- a/TODO +++ b/TODO @@ -90,7 +90,7 @@ ================================================================== -1) Peer for TCP relay. +1) Peer app for TCP relay. ================================================================== From 7ee0681fd46fe323271bc55a6f66c2a634800f90 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 16 Feb 2015 05:18:09 +0000 Subject: [PATCH 486/805] postgres install info extended --- INSTALL | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/INSTALL b/INSTALL index 23059ca6..8edc407a 100644 --- a/INSTALL +++ b/INSTALL @@ -856,7 +856,12 @@ connection string format. Below are the steps to setup the PostgreSQL database server from scratch: -1) Install PostgreSQL server. +1) Install PostgreSQL server. After the installation, do not forget to +initialize the postgres root database directory: + + $ sudo bash + $ su -l pgsql + $ initdb -D /usr/local/pgsql/data 2) Find and edit Postgres' pg_hba.conf file to set the access options (see docs). On different systems, it may be located in different places. From 8695e7c4a9bead2bd19da8f36c7bea1742e1ec7c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 19 Feb 2015 06:36:04 +0000 Subject: [PATCH 487/805] REST API docs fixed --- ChangeLog | 4 ++++ README.turnserver | 2 +- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 4 ++-- man/man1/turnutils.1 | 2 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/ns_turn_defs.h | 2 +- 8 files changed, 14 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index d6f247bd..1f99761e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2/18/2015 Oleg Moskalenko +Version 4.4.2.2 'Ardee West': + - REST API docs fixed; + 2/3/2015 Oleg Moskalenko Version 4.4.2.1 'Ardee West': - (HMAC-)SHA-512 and -384 algorithms added; diff --git a/README.turnserver b/README.turnserver index 22f1a505..d7e9c274 100644 --- a/README.turnserver +++ b/README.turnserver @@ -174,7 +174,7 @@ Flags: This option uses timestamp as part of combined username: usercombo -> "timestamp:username", turn user -> usercombo, - turn password -> base64(hmac(secret key, usercombo)). + turn password -> base64(hmac(input_buffer = usercombo, key = shared-secret)). This allows TURN credentials to be accounted for a specific user id. If you don't have a suitable id, the timestamp alone can be used. This option is just turns on secret-based authentication. diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index be71dfd8..14c658df 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "06 February 2015" "" "" +.TH TURN 1 "18 February 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 7b3b475f..12ddcd14 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "06 February 2015" "" "" +.TH TURN 1 "18 February 2015" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -256,7 +256,7 @@ the TURN REST API section below. This option uses timestamp as part of combined username: usercombo \-> "timestamp:username", turn user \-> usercombo, -turn password \-> \fBbase64\fP(hmac(secret key, usercombo)). +turn password \-> \fBbase64\fP(hmac(input_buffer = usercombo, key = shared\-secret)). This allows TURN credentials to be accounted for a specific user id. If you don't have a suitable id, the timestamp alone can be used. This option is just turns on secret\-based authentication. diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 83f28d48..e381670b 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "06 February 2015" "" "" +.TH TURN 1 "18 February 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 7b0ed997..31646032 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.4.2.1 +TURNVERSION=4.4.2.2 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 9f1cd82b..b45b9a31 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.4.2.1 +Version: 4.4.2.2 Release: 0%{dist} Summary: Coturn TURN Server @@ -288,6 +288,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Wed Feb 18 2015 Oleg Moskalenko + - Sync to 4.4.2.2 * Tue Feb 3 2015 Oleg Moskalenko - Sync to 4.4.2.1 * Sun Feb 1 2015 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index b3d091ab..4eeaf7ea 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.4.2.1" +#define TURN_SERVER_VERSION "4.4.2.2" #define TURN_SERVER_VERSION_NAME "Ardee West" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 304608f7140d66286749bc806d512122398deba3 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 20 Feb 2015 07:01:24 +0000 Subject: [PATCH 488/805] TODO updated --- TODO | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/TODO b/TODO index 8fe61eb1..ec826dd9 100644 --- a/TODO +++ b/TODO @@ -59,6 +59,10 @@ 2) Redirect draft. +3) STUN-Bis: + a. SCTP + b. New integrity attribute, algorithms + ================================================================== ### VII. MISC FEATURES ### From 6a633fadc9583b7be59a3533baab3d2c6de30214 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 22 Feb 2015 07:14:00 +0000 Subject: [PATCH 489/805] default sqlite database schema fixed --- ChangeLog | 2 ++ src/apps/relay/dbdrivers/dbd_sqlite.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1f99761e..1e193644 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,8 @@ 2/18/2015 Oleg Moskalenko Version 4.4.2.2 'Ardee West': + - admin_user table schema fixed; - REST API docs fixed; + - Amazon AWS uses syslog; 2/3/2015 Oleg Moskalenko Version 4.4.2.1 'Ardee West': diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 7882e910..679efb14 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -155,7 +155,7 @@ static void init_sqlite_database(sqlite3 *sqliteconnection) { "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))", + "CREATE TABLE admin_user (name varchar(32), realm varchar(127), password varchar(127), primary key (name))", NULL }; From 757956565e30efd8b29c2ccc80862af4f3331c96 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 25 Feb 2015 08:21:40 +0000 Subject: [PATCH 490/805] working on bw fixes --- src/apps/relay/ns_ioalib_engine_impl.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 87c2eaed..ce51d279 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -327,7 +327,6 @@ static void free_blist_elem(ioa_engine_handle e, stun_buffer_list_elem *buf_elem /************** ENGINE *************************/ #define TURN_JIFFIE_SIZE (3) -#define TURN_JIFFIE_LENGTH (1<<(TURN_JIFFIE_SIZE)) static void timer_handler(ioa_engine_handle e, void* arg) { @@ -642,9 +641,7 @@ void delete_ioa_timer(ioa_timer_handle th) static int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read) { - if(read && s && (s->e) && sz && - ((s->sat == CLIENT_SOCKET) || (s->sat == RELAY_SOCKET) || (s->sat == RELAY_RTCP_SOCKET)) && - (s->session)) { + if(s && (s->e) && sz && (s->sat == CLIENT_SOCKET) && (s->session)) { band_limit_t max_bps = s->session->bps; @@ -670,9 +667,11 @@ static int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read) s->jiffie_bytes_read = bsz; else s->jiffie_bytes_write = bsz; + return 1; } } else { + band_limit_t nsz; if(read) nsz = s->jiffie_bytes_read + bsz; From a92b7191a6b61bfde4276fb4100a7062c953588e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 25 Feb 2015 08:23:30 +0000 Subject: [PATCH 491/805] version bump --- ChangeLog | 4 ++++ rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/ns_turn_defs.h | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1e193644..06c06f71 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2/25/2015 Oleg Moskalenko +Version 4.4.2.3 'Ardee West': + - bandwidth limitation fixes; + 2/18/2015 Oleg Moskalenko Version 4.4.2.2 'Ardee West': - admin_user table schema fixed; diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 31646032..0150ec91 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.4.2.2 +TURNVERSION=4.4.2.3 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index b45b9a31..7289b861 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.4.2.2 +Version: 4.4.2.3 Release: 0%{dist} Summary: Coturn TURN Server @@ -288,6 +288,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Wed Feb 25 2015 Oleg Moskalenko + - Sync to 4.4.2.3 * Wed Feb 18 2015 Oleg Moskalenko - Sync to 4.4.2.2 * Tue Feb 3 2015 Oleg Moskalenko diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 4eeaf7ea..d5af888d 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.4.2.2" +#define TURN_SERVER_VERSION "4.4.2.3" #define TURN_SERVER_VERSION_NAME "Ardee West" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 4afd423beff71568d8eb2e07d03fdbb848beb0ec Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 26 Feb 2015 06:39:45 +0000 Subject: [PATCH 492/805] working on bw limitations --- src/apps/relay/http_server.c | 2 +- src/apps/relay/ns_ioalib_engine_impl.c | 11 ++++------ src/server/ns_turn_ioalib.h | 2 +- src/server/ns_turn_server.c | 29 ++++++++++++++------------ 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index 7b0b0b8f..72288131 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -68,7 +68,7 @@ static void write_http_echo(ioa_socket_handle s) len_http = strlen(data_http); ns_bcopy(data_http,data,len_http); ioa_network_buffer_set_size(nbh_http,len_http); - send_data_from_ioa_socket_nbh(s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE); + send_data_from_ioa_socket_nbh(s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE,NULL); } } } diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index ce51d279..381942e6 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -326,8 +326,6 @@ static void free_blist_elem(ioa_engine_handle e, stun_buffer_list_elem *buf_elem /************** ENGINE *************************/ -#define TURN_JIFFIE_SIZE (3) - static void timer_handler(ioa_engine_handle e, void* arg) { UNUSED_ARG(arg); @@ -335,7 +333,7 @@ static void timer_handler(ioa_engine_handle e, void* arg) { _log_time_value = turn_time(); _log_time_value_set = 1; - e->jiffie = _log_time_value >> TURN_JIFFIE_SIZE; + e->jiffie = _log_time_value; } ioa_engine_handle create_ioa_engine(super_memory_t *sm, @@ -641,15 +639,13 @@ void delete_ioa_timer(ioa_timer_handle th) static int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read) { - if(s && (s->e) && sz && (s->sat == CLIENT_SOCKET) && (s->session)) { + if(s && (s->e) && sz && ((s->sat == CLIENT_SOCKET) || (s->sat == LISTENER_SOCKET)) && (s->session)) { band_limit_t max_bps = s->session->bps; if(max_bps<1) return 1; - max_bps = max_bps<jiffie != s->e->jiffie) { @@ -2965,7 +2961,7 @@ int udp_send(ioa_socket_handle s, const ioa_addr* dest_addr, const s08bits* buff int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, ioa_network_buffer_handle nbh, - int ttl, int tos) + int ttl, int tos, int *skip) { int ret = -1; @@ -2986,6 +2982,7 @@ int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, if(!ioa_socket_check_bandwidth(s,ioa_network_buffer_get_size(nbh),0)) { /* Bandwidth exhausted, we pretend everything is fine: */ ret = (int)(ioa_network_buffer_get_size(nbh)); + if(skip) *skip = 1; } else { if (!ioa_socket_tobeclosed(s) && s->e) { diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 5abc1d51..4e6cb518 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -243,7 +243,7 @@ void clear_ioa_socket_session_if(ioa_socket_handle s, void *ss); tcp_connection *get_ioa_socket_sub_session(ioa_socket_handle s); void set_ioa_socket_sub_session(ioa_socket_handle s, tcp_connection *tc); 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); -int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, ioa_network_buffer_handle nbh, int ttl, int tos); +int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, ioa_network_buffer_handle nbh, int ttl, int tos, int *skip); void close_ioa_socket(ioa_socket_handle s); #define IOA_CLOSE_SOCKET(S) do { if(S) { close_ioa_socket(S); S = NULL; } } while(0) ioa_socket_handle detach_ioa_socket(ioa_socket_handle s); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 55bc3b85..cbf4fd93 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1838,7 +1838,7 @@ static void tcp_deliver_delayed_buffer(unsent_buffer *ub, ioa_socket_handle s, t u32bits bytes = (u32bits)ioa_network_buffer_get_size(nbh); - int ret = send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE); + int ret = send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE, NULL); if (ret < 0) { set_ioa_socket_tobeclosed(s); } else { @@ -1877,7 +1877,7 @@ static void tcp_peer_input_handler(ioa_socket_handle s, int event_type, ioa_net_ u32bits bytes = (u32bits)ioa_network_buffer_get_size(nbh); - int ret = send_data_from_ioa_socket_nbh(tc->client_s, NULL, nbh, TTL_IGNORE, TOS_IGNORE); + int ret = send_data_from_ioa_socket_nbh(tc->client_s, NULL, nbh, TTL_IGNORE, TOS_IGNORE, NULL); if (ret < 0) { set_ioa_socket_tobeclosed(s); } else if(ss) { @@ -1917,7 +1917,7 @@ static void tcp_client_input_handler_rfc6062data(ioa_socket_handle s, int event_ ss->received_bytes += bytes; } - int ret = send_data_from_ioa_socket_nbh(tc->peer_s, NULL, nbh, TTL_IGNORE, TOS_IGNORE); + int ret = send_data_from_ioa_socket_nbh(tc->peer_s, NULL, nbh, TTL_IGNORE, TOS_IGNORE, NULL); if (ret < 0) { set_ioa_socket_tobeclosed(s); } @@ -2009,7 +2009,7 @@ static void tcp_peer_connection_completed_callback(int success, void *arg) len_test = strlen(data_test); ns_bcopy(data_test,data,len_test); ioa_network_buffer_set_size(nbh_test,len_test); - send_data_from_ioa_socket_nbh(tc->peer_s, NULL, nbh_test, TTL_IGNORE, TOS_IGNORE); + send_data_from_ioa_socket_nbh(tc->peer_s, NULL, nbh_test, TTL_IGNORE, TOS_IGNORE, NULL); } } } @@ -2490,7 +2490,7 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co } if(ss && !err_code) { - send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE); + send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE, NULL); tcp_deliver_delayed_buffer(&(tc->ub_to_client),s,ss); IOA_CLOSE_SOCKET(s_to_delete); FUNCEND; @@ -2501,7 +2501,7 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: cannot set TCP tmp client data input callback\n", __FUNCTION__); ioa_network_buffer_delete(server->e, nbh); } else { - send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE); + send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE, NULL); } } } @@ -2978,7 +2978,7 @@ static int handle_turn_send(turn_turnserver *server, ts_ur_super_session *ss, ioa_network_buffer_set_size(nbh,len); } ioa_network_buffer_header_init(nbh); - send_data_from_ioa_socket_nbh(get_relay_socket_ss(ss,peer_addr.ss.sa_family), &peer_addr, nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos); + send_data_from_ioa_socket_nbh(get_relay_socket_ss(ss,peer_addr.ss.sa_family), &peer_addr, nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos, NULL); in_buffer->nbh = NULL; } @@ -4103,7 +4103,7 @@ static int write_to_peerchannel(ts_ur_super_session* ss, u16bits chnum, ioa_net_ ioa_network_buffer_header_init(nbh); - rc = send_data_from_ioa_socket_nbh(get_relay_socket_ss(ss, chn->peer_addr.ss.sa_family), &(chn->peer_addr), nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos); + rc = send_data_from_ioa_socket_nbh(get_relay_socket_ss(ss, chn->peer_addr.ss.sa_family), &(chn->peer_addr), nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos, NULL); in_buffer->nbh = NULL; } } @@ -4248,17 +4248,20 @@ static int write_client_connection(turn_turnserver *server, ts_ur_super_session* return -1; } else { - ++(ss->sent_packets); - ss->sent_bytes += (u32bits)ioa_network_buffer_get_size(nbh); - turn_report_session_usage(ss); - if (eve(server->verbose)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: prepare to write to s 0x%lx\n", __FUNCTION__, (long) (ss->client_socket)); } - int ret = send_data_from_ioa_socket_nbh(ss->client_socket, NULL, nbh, ttl, tos); + int skip = 0; + int ret = send_data_from_ioa_socket_nbh(ss->client_socket, NULL, nbh, ttl, tos, &skip); + + if(!skip) { + ++(ss->sent_packets); + ss->sent_bytes += (u32bits)ioa_network_buffer_get_size(nbh); + turn_report_session_usage(ss); + } FUNCEND; return ret; From ba98e3070c90b363790d7f0ed52348a4f6a4f267 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 26 Feb 2015 06:51:08 +0000 Subject: [PATCH 493/805] BW fixes --- src/apps/relay/dtls_listener.c | 22 ++++++++++++---------- src/apps/relay/ns_ioalib_engine_impl.c | 2 +- src/apps/relay/ns_ioalib_impl.h | 2 ++ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index 2d591c45..87aac30c 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -367,18 +367,20 @@ static int handle_udp_packet(dtls_listener_relay_server_type *server, } } - if (s && s->read_cb && sm->m.sm.nd.nbh) { + if(ioa_socket_check_bandwidth(s,ioa_network_buffer_get_size(sm->m.sm.nd.nbh),1)) { s->e = ioa_eng; - s->read_cb(s, IOA_EV_READ, &(sm->m.sm.nd), s->read_ctx, 1); - ioa_network_buffer_delete(ioa_eng, sm->m.sm.nd.nbh); - sm->m.sm.nd.nbh = NULL; + if (s && s->read_cb && sm->m.sm.nd.nbh) { + s->read_cb(s, IOA_EV_READ, &(sm->m.sm.nd), s->read_ctx, 1); + ioa_network_buffer_delete(ioa_eng, sm->m.sm.nd.nbh); + sm->m.sm.nd.nbh = NULL; - if (ioa_socket_tobeclosed(s)) { - ts_ur_super_session *ss = (ts_ur_super_session *) s->session; - if (ss) { - turn_turnserver *server = (turn_turnserver *) ss->server; - if (server) { - shutdown_client_connection(server, ss, 0, "UDP packet processing error"); + if (ioa_socket_tobeclosed(s)) { + ts_ur_super_session *ss = (ts_ur_super_session *) s->session; + if (ss) { + turn_turnserver *server = (turn_turnserver *) ss->server; + if (server) { + shutdown_client_connection(server, ss, 0, "UDP packet processing error"); + } } } } diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 381942e6..80da64c4 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -637,7 +637,7 @@ void delete_ioa_timer(ioa_timer_handle th) /************** SOCKETS HELPERS ***********************/ -static int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read) +int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read) { if(s && (s->e) && sz && ((s->sat == CLIENT_SOCKET) || (s->sat == LISTENER_SOCKET)) && (s->session)) { diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 7bdee61a..8abfe656 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -303,6 +303,8 @@ int send_data_from_ioa_socket_tcp(ioa_socket_handle s, const void *data, size_t 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); +int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read); + ///////////////////////// SUPER MEMORY //////// #define allocate_super_memory_engine(e,size) allocate_super_memory_engine_func(e, size, __FILE__, __FUNCTION__, __LINE__) From 3eacd81b405796c7457a42f18592de637614617d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 28 Feb 2015 07:54:46 +0000 Subject: [PATCH 494/805] redis realm options fixed --- ChangeLog | 3 +- src/apps/relay/dbdrivers/dbd_redis.c | 45 ++++++++++++++++---------- src/apps/relay/ns_ioalib_engine_impl.c | 4 ++- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index 06c06f71..eceffb2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 2/25/2015 Oleg Moskalenko Version 4.4.2.3 'Ardee West': - - bandwidth limitation fixes; + - bandwidth control fixed; + - redis operations with the realm options fixed; 2/18/2015 Oleg Moskalenko Version 4.4.2.2 'Ardee West': diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index 95312b50..c79d6d09 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -1176,7 +1176,7 @@ static void redis_reread_realms(secrets_list_t * realms_list) { clean_secrets_list(&keys); - update_o_to_realm(o_to_realm_new); + update_o_to_realm(o_to_realm_new); turnFreeRedisReply(reply); } @@ -1192,25 +1192,36 @@ static void redis_reread_realms(secrets_list_t * realms_list) { for (i = 0; isecrets[i]; realm_params_t* rp = get_realm(realm); - unsigned long value = 0; - if(!set_redis_realm_opt(realm,"max-bps",&value)) { - lock_realms(); - rp->options.perf_options.max_bps = turn_params.max_bps; - unlock_realms(); + { + unsigned long value = 0; + if(!set_redis_realm_opt(realm,"max-bps",&value)) { + lock_realms(); + rp->options.perf_options.max_bps = turn_params.max_bps; + unlock_realms(); + } else { + rp->options.perf_options.max_bps = (band_limit_t)value; + } } - rp->options.perf_options.max_bps = (band_limit_t)value; - if(!set_redis_realm_opt(realm,"total-quota",&value)) { - lock_realms(); - rp->options.perf_options.total_quota = turn_params.total_quota; - unlock_realms(); + { + unsigned long value = 0; + if(!set_redis_realm_opt(realm,"total-quota",&value)) { + lock_realms(); + rp->options.perf_options.total_quota = turn_params.total_quota; + unlock_realms(); + } else { + rp->options.perf_options.total_quota = (vint)value; + } } - rp->options.perf_options.total_quota = (vint)value; - if(!set_redis_realm_opt(realm,"user-quota",&value)) { - lock_realms(); - rp->options.perf_options.user_quota = turn_params.user_quota; - unlock_realms(); + { + unsigned long value = 0; + if(!set_redis_realm_opt(realm,"user-quota",&value)) { + lock_realms(); + rp->options.perf_options.user_quota = turn_params.user_quota; + unlock_realms(); + } else { + rp->options.perf_options.user_quota = (vint)value; + } } - rp->options.perf_options.user_quota = (vint)value; } } } diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 80da64c4..0ffa18aa 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -639,7 +639,9 @@ void delete_ioa_timer(ioa_timer_handle th) int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read) { - if(s && (s->e) && sz && ((s->sat == CLIENT_SOCKET) || (s->sat == LISTENER_SOCKET)) && (s->session)) { + if(s && (s->e) && sz && + ((s->sat == CLIENT_SOCKET) || (s->sat == RELAY_SOCKET) || (s->sat == RELAY_RTCP_SOCKET)) && + (s->session)) { band_limit_t max_bps = s->session->bps; From 55ee70dea0632a3a49bf91c0452845d18e2b0922 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 1 Mar 2015 01:37:44 +0000 Subject: [PATCH 495/805] control traffic excluded from the bandwidth limitation --- src/apps/relay/dtls_listener.c | 2 +- src/apps/relay/ns_ioalib_engine_impl.c | 36 +++++++++++++++++--------- src/apps/relay/ns_ioalib_impl.h | 2 +- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index 87aac30c..0762fbc8 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -367,7 +367,7 @@ static int handle_udp_packet(dtls_listener_relay_server_type *server, } } - if(ioa_socket_check_bandwidth(s,ioa_network_buffer_get_size(sm->m.sm.nd.nbh),1)) { + if(ioa_socket_check_bandwidth(s,sm->m.sm.nd.nbh,1)) { s->e = ioa_eng; if (s && s->read_cb && sm->m.sm.nd.nbh) { s->read_cb(s, IOA_EV_READ, &(sm->m.sm.nd), s->read_ctx, 1); diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 0ffa18aa..8dc1ab68 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -637,12 +637,14 @@ void delete_ioa_timer(ioa_timer_handle th) /************** SOCKETS HELPERS ***********************/ -int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read) +int ioa_socket_check_bandwidth(ioa_socket_handle s, ioa_network_buffer_handle nbh, int read) { - if(s && (s->e) && sz && + if(s && (s->e) && nbh && ((s->sat == CLIENT_SOCKET) || (s->sat == RELAY_SOCKET) || (s->sat == RELAY_RTCP_SOCKET)) && (s->session)) { + size_t sz = ioa_network_buffer_get_size(nbh); + band_limit_t max_bps = s->session->bps; if(max_bps<1) @@ -657,9 +659,12 @@ int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read) s->jiffie_bytes_write = 0; if(bsz > max_bps) { - - return 0; - + u08bits *buf = ioa_network_buffer_data(nbh); + if((s->sat == CLIENT_SOCKET) && ((read && stun_is_request_str(buf,sz)) || (!read && stun_is_response_str(buf,sz)))) { + return 1; + } else { + return 0; + } } else { if(read) s->jiffie_bytes_read = bsz; @@ -676,7 +681,12 @@ int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read) else nsz = s->jiffie_bytes_write + bsz; if(nsz > max_bps) { - return 0; + u08bits *buf = ioa_network_buffer_data(nbh); + if((s->sat == CLIENT_SOCKET) && ((read && stun_is_request_str(buf,sz)) || (!read && stun_is_response_str(buf,sz)))) { + return 1; + } else { + return 0; + } } else { if(read) s->jiffie_bytes_read = nsz; @@ -2382,11 +2392,13 @@ static int socket_input_worker(ioa_socket_handle s) } if ((ret!=-1) && (len >= 0)) { - if(ioa_socket_check_bandwidth(s,(size_t)len,1)) { - if(app_msg_len) - buf_elem->buf.len = app_msg_len; - else - buf_elem->buf.len = len; + + if(app_msg_len) + buf_elem->buf.len = app_msg_len; + else + buf_elem->buf.len = len; + + if(ioa_socket_check_bandwidth(s,buf_elem,1)) { if(s->read_cb) { ioa_net_data nd; @@ -2981,7 +2993,7 @@ int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s); } else if (nbh) { - if(!ioa_socket_check_bandwidth(s,ioa_network_buffer_get_size(nbh),0)) { + if(!ioa_socket_check_bandwidth(s,nbh,0)) { /* Bandwidth exhausted, we pretend everything is fine: */ ret = (int)(ioa_network_buffer_get_size(nbh)); if(skip) *skip = 1; diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 8abfe656..6a6ff8b4 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -303,7 +303,7 @@ int send_data_from_ioa_socket_tcp(ioa_socket_handle s, const void *data, size_t 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); -int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read); +int ioa_socket_check_bandwidth(ioa_socket_handle s, ioa_network_buffer_handle nbh, int read); ///////////////////////// SUPER MEMORY //////// From 1fa6853e031b3eec0c5c7519166a4f82df7e6297 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 1 Mar 2015 01:41:53 +0000 Subject: [PATCH 496/805] control traffic fix --- ChangeLog | 1 + src/apps/relay/ns_ioalib_engine_impl.c | 21 +++++++++------------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index eceffb2f..4f12142f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 2/25/2015 Oleg Moskalenko Version 4.4.2.3 'Ardee West': - bandwidth control fixed; + - STUN/TURN control traffic excluded from the bandwidth limitation; - redis operations with the realm options fixed; 2/18/2015 Oleg Moskalenko diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 8dc1ab68..a010a384 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -650,6 +650,13 @@ int ioa_socket_check_bandwidth(ioa_socket_handle s, ioa_network_buffer_handle nb if(max_bps<1) return 1; + if(s->sat == CLIENT_SOCKET) { + u08bits *buf = ioa_network_buffer_data(nbh); + if((read && stun_is_request_str(buf,sz)) || (!read && stun_is_response_str(buf,sz))) { + return 1; + } + } + band_limit_t bsz = (band_limit_t)sz; if(s->jiffie != s->e->jiffie) { @@ -659,12 +666,7 @@ int ioa_socket_check_bandwidth(ioa_socket_handle s, ioa_network_buffer_handle nb s->jiffie_bytes_write = 0; if(bsz > max_bps) { - u08bits *buf = ioa_network_buffer_data(nbh); - if((s->sat == CLIENT_SOCKET) && ((read && stun_is_request_str(buf,sz)) || (!read && stun_is_response_str(buf,sz)))) { - return 1; - } else { - return 0; - } + return 0; } else { if(read) s->jiffie_bytes_read = bsz; @@ -681,12 +683,7 @@ int ioa_socket_check_bandwidth(ioa_socket_handle s, ioa_network_buffer_handle nb else nsz = s->jiffie_bytes_write + bsz; if(nsz > max_bps) { - u08bits *buf = ioa_network_buffer_data(nbh); - if((s->sat == CLIENT_SOCKET) && ((read && stun_is_request_str(buf,sz)) || (!read && stun_is_response_str(buf,sz)))) { - return 1; - } else { - return 0; - } + return 0; } else { if(read) s->jiffie_bytes_read = nsz; From 48b4be301b3ca4a98d20f1cc30642ce49737fc9d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 1 Mar 2015 01:46:21 +0000 Subject: [PATCH 497/805] cosmetics --- src/apps/relay/ns_ioalib_engine_impl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index a010a384..2d2f4b1d 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -672,11 +672,9 @@ int ioa_socket_check_bandwidth(ioa_socket_handle s, ioa_network_buffer_handle nb s->jiffie_bytes_read = bsz; else s->jiffie_bytes_write = bsz; - return 1; } } else { - band_limit_t nsz; if(read) nsz = s->jiffie_bytes_read + bsz; From 6a508683c4c80365568791addf3af431f391193c Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 1 Mar 2015 05:02:42 +0000 Subject: [PATCH 498/805] bandwidth control fixes --- src/apps/relay/ns_ioalib_engine_impl.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 2d2f4b1d..e2a18e1d 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -652,8 +652,11 @@ int ioa_socket_check_bandwidth(ioa_socket_handle s, ioa_network_buffer_handle nb if(s->sat == CLIENT_SOCKET) { u08bits *buf = ioa_network_buffer_data(nbh); - if((read && stun_is_request_str(buf,sz)) || (!read && stun_is_response_str(buf,sz))) { - return 1; + if(stun_is_command_message_str(buf,sz)) { + u16bits method = stun_get_method_str(buf,sz); + if((method != STUN_METHOD_SEND) && (method != STUN_METHOD_DATA)) { + return 1; + } } } From 7e419731819148188407ad9c4f793718659f3e2d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 1 Mar 2015 06:02:59 +0000 Subject: [PATCH 499/805] date change --- rpm/turnserver.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 7289b861..aeb818bd 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -288,7 +288,7 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Wed Feb 25 2015 Oleg Moskalenko +* Wed Feb 28 2015 Oleg Moskalenko - Sync to 4.4.2.3 * Wed Feb 18 2015 Oleg Moskalenko - Sync to 4.4.2.2 From de0c3bab5830ea08d5af3f7d7f6be2ad9a0663a0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 1 Mar 2015 06:03:14 +0000 Subject: [PATCH 500/805] date change --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 4f12142f..e7edfb75 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -2/25/2015 Oleg Moskalenko +2/28/2015 Oleg Moskalenko Version 4.4.2.3 'Ardee West': - bandwidth control fixed; - STUN/TURN control traffic excluded from the bandwidth limitation; From 2411e212b8d95c95ef129ff81acc900b3b4b8f6e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 1 Mar 2015 06:04:37 +0000 Subject: [PATCH 501/805] date change --- rpm/turnserver.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index aeb818bd..32e4ae8d 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -288,7 +288,7 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Wed Feb 28 2015 Oleg Moskalenko +* Sat Feb 28 2015 Oleg Moskalenko - Sync to 4.4.2.3 * Wed Feb 18 2015 Oleg Moskalenko - Sync to 4.4.2.2 From 61239f9aa8051748865b24a0a0f559752cded62d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 2 Mar 2015 01:44:29 +0000 Subject: [PATCH 502/805] bandwidth limit is 64 bits now --- ChangeLog | 4 +++- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/dbdrivers/dbd_mongo.c | 17 +++++++---------- src/apps/relay/dbdrivers/dbd_mysql.c | 2 +- src/apps/relay/dbdrivers/dbd_pgsql.c | 2 +- src/apps/relay/dbdrivers/dbd_sqlite.c | 2 +- src/apps/relay/mainrelay.c | 6 +++--- src/apps/relay/ns_ioalib_engine_impl.c | 20 +++++++++++--------- src/apps/relay/ns_ioalib_impl.h | 9 +++++++-- src/apps/relay/turn_admin_server.c | 10 +++++----- src/apps/uclient/mainuclient.c | 2 +- src/client/ns_turn_msg.h | 2 +- 12 files changed, 41 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index e7edfb75..0a5a39c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,9 @@ 2/28/2015 Oleg Moskalenko Version 4.4.2.3 'Ardee West': - bandwidth control fixed; - - STUN/TURN control traffic excluded from the bandwidth limitation; + - STUN/TURN control traffic counted separately from data traffic, + for the sake of the bandwidth control; + - higher bandwidth limit capacity on 64 bits systems; - redis operations with the realm options fixed; 2/18/2015 Oleg Moskalenko diff --git a/examples/var/db/turndb b/examples/var/db/turndb index bad666cb7f6e5ca5436b9114b6b46a5982458457..8802a7f5d6bc0f1fbb11b1baa598cc35253c36a3 100644 GIT binary patch delta 128 zcmZqJz}T>Xae_4Cs);hrjH@;#EV33_&A`H}#m3yh?8BVJtP6r08^1D5=CohL!oa`~ zI?+*ja+IDdqs&A{2@x*lD?rsb49xSHbC`EAw}IfsMki)5ptu-NH5!Xae_4C%84@0j4L-LEV34Q!obF?#m0P`xr5noptions.perf_options.max_bps - = (band_limit_t) _v; + rp->options.perf_options.max_bps = (band_limit_t) _v; else if (!strcmp(_k, "total-quota")) - rp->options.perf_options.total_quota - = (vint) _v; + rp->options.perf_options.total_quota = (vint) _v; else if (!strcmp(_k, "user-quota")) - rp->options.perf_options.user_quota - = (vint) _v; + rp->options.perf_options.user_quota = (vint) _v; else { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", _k); diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index ff665054..73ecfc96 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -1089,7 +1089,7 @@ static void mysql_reread_realms(secrets_list_t * realms_list) { vval[sz]=0; realm_params_t* rp = get_realm(rval); if(!strcmp(oval,"max-bps")) - rp->options.perf_options.max_bps = (band_limit_t)atol(vval); + rp->options.perf_options.max_bps = (band_limit_t)strtoul(vval,NULL,10); else if(!strcmp(oval,"total-quota")) rp->options.perf_options.total_quota = (vint)atoi(vval); else if(!strcmp(oval,"user-quota")) diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index cae1a3f1..e3b7941c 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -819,7 +819,7 @@ static void pgsql_reread_realms(secrets_list_t * realms_list) { if(rval && oval && vval) { realm_params_t* rp = get_realm(rval); if(!strcmp(oval,"max-bps")) - rp->options.perf_options.max_bps = (band_limit_t)atol(vval); + rp->options.perf_options.max_bps = (band_limit_t)strtoul(vval,NULL,10); else if(!strcmp(oval,"total-quota")) rp->options.perf_options.total_quota = (vint)atoi(vval); else if(!strcmp(oval,"user-quota")) diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 679efb14..79aca9aa 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -1109,7 +1109,7 @@ static void sqlite_reread_realms(secrets_list_t * realms_list) realm_params_t* rp = get_realm(rval); if(!strcmp(oval,"max-bps")) - rp->options.perf_options.max_bps = (band_limit_t)atol(vval); + rp->options.perf_options.max_bps = (band_limit_t)strtoul(vval,NULL,10); else if(!strcmp(oval,"total-quota")) rp->options.perf_options.total_quota = (vint)atoi(vval); else if(!strcmp(oval,"user-quota")) diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 829842b0..035caf8e 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1203,12 +1203,12 @@ static void set_option(int c, char *value) get_realm(NULL)->options.perf_options.total_quota = atoi(value); break; case 's': - turn_params.max_bps = (band_limit_t)atoi(value); - get_realm(NULL)->options.perf_options.max_bps = atoi(value); + turn_params.max_bps = (band_limit_t)strtoul(value,NULL,10); + get_realm(NULL)->options.perf_options.max_bps = (band_limit_t)strtoul(value,NULL,10); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%lu bytes per second allowed per session\n",(unsigned long)turn_params.max_bps); break; case 'B': - turn_params.bps_capacity = (band_limit_t)atoi(value); + turn_params.bps_capacity = (band_limit_t)strtoul(value,NULL,10); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%lu bytes per second allowed, combined server capacity\n",(unsigned long)turn_params.bps_capacity); break; case CHECK_ORIGIN_CONSISTENCY_OPT: diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index e2a18e1d..b7066335 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -650,12 +650,14 @@ int ioa_socket_check_bandwidth(ioa_socket_handle s, ioa_network_buffer_handle nb if(max_bps<1) return 1; + struct traffic_bytes *traffic = &(s->data_traffic); + if(s->sat == CLIENT_SOCKET) { u08bits *buf = ioa_network_buffer_data(nbh); if(stun_is_command_message_str(buf,sz)) { u16bits method = stun_get_method_str(buf,sz); if((method != STUN_METHOD_SEND) && (method != STUN_METHOD_DATA)) { - return 1; + traffic = &(s->control_traffic); } } } @@ -665,31 +667,31 @@ int ioa_socket_check_bandwidth(ioa_socket_handle s, ioa_network_buffer_handle nb if(s->jiffie != s->e->jiffie) { s->jiffie = s->e->jiffie; - s->jiffie_bytes_read = 0; - s->jiffie_bytes_write = 0; + traffic->jiffie_bytes_read = 0; + traffic->jiffie_bytes_write = 0; if(bsz > max_bps) { return 0; } else { if(read) - s->jiffie_bytes_read = bsz; + traffic->jiffie_bytes_read = bsz; else - s->jiffie_bytes_write = bsz; + traffic->jiffie_bytes_write = bsz; return 1; } } else { band_limit_t nsz; if(read) - nsz = s->jiffie_bytes_read + bsz; + nsz = traffic->jiffie_bytes_read + bsz; else - nsz = s->jiffie_bytes_write + bsz; + nsz = traffic->jiffie_bytes_write + bsz; if(nsz > max_bps) { return 0; } else { if(read) - s->jiffie_bytes_read = nsz; + traffic->jiffie_bytes_read = nsz; else - s->jiffie_bytes_write = nsz; + traffic->jiffie_bytes_write = nsz; return 1; } } diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 6a6ff8b4..21b7fe32 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -171,6 +171,11 @@ struct _ioa_engine #define SOCKET_MAGIC (0xABACADEF) +struct traffic_bytes { + band_limit_t jiffie_bytes_read; + band_limit_t jiffie_bytes_write; +}; + struct _ioa_socket { evutil_socket_t fd; @@ -207,8 +212,8 @@ struct _ioa_socket int current_tos; stun_buffer_list bufs; turn_time_t jiffie; /* bandwidth check interval */ - band_limit_t jiffie_bytes_read; - band_limit_t jiffie_bytes_write; + struct traffic_bytes data_traffic; + struct traffic_bytes control_traffic; /* RFC 6062 ==>> */ //Connection session: tcp_connection *sub_session; diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index ec61235f..af616aa8 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -382,11 +382,11 @@ static void change_cli_param(struct cli_session* cs, const char* pn) cli_print_uint(cs,(unsigned long)turn_params.user_quota,"user-quota",2); return; } else if(strstr(pn,"max-bps")==pn) { - set_max_bps((band_limit_t)atol(pn+strlen("max-bps"))); + set_max_bps((band_limit_t)strtoul(pn+strlen("max-bps"),NULL,10)); cli_print_uint(cs,(unsigned long)get_max_bps(),"max-bps",2); return; } else if(strstr(pn,"bps-capacity")==pn) { - set_bps_capacity((band_limit_t)atol(pn+strlen("bps-capacity"))); + set_bps_capacity((band_limit_t)strtoul(pn+strlen("bps-capacity"),NULL,10)); cli_print_uint(cs,(unsigned long)get_bps_capacity(),"bps-capacity",2); return; } else if(strstr(pn,"cli-max-output-sessions")==pn) { @@ -1882,9 +1882,9 @@ static void update_param(const char* pn, const char *value) } else if(strstr(pn,"user-quota")==pn) { turn_params.user_quota = atoi(value); } else if(strstr(pn,"max-bps")==pn) { - set_max_bps((band_limit_t)atol(value)); + set_max_bps((band_limit_t)strtoul(value,NULL,10)); } else if(strstr(pn,"bps-capacity")==pn) { - set_bps_capacity((band_limit_t)atol(value)); + set_bps_capacity((band_limit_t)strtoul(value,NULL,10)); } } { @@ -1900,7 +1900,7 @@ static void update_param(const char* pn, const char *value) rp->options.perf_options.user_quota = atoi(value); dbd->set_realm_option_one((u08bits*)rp->options.name,rp->options.perf_options.user_quota,"user-quota"); } else if(strstr(pn,"cr-max-bps")==pn) { - rp->options.perf_options.max_bps = (band_limit_t)atol(value); + rp->options.perf_options.max_bps = (band_limit_t)strtoul(value,NULL,10); dbd->set_realm_option_one((u08bits*)rp->options.name,rp->options.perf_options.max_bps,"max-bps"); } } diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 4439102e..3d0344dd 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -249,7 +249,7 @@ int main(int argc, char **argv) } break; case 'a': - bps = (band_limit_t)atol(optarg); + bps = (band_limit_t)strtoul(optarg,NULL,10); break; case 'o': STRCPY(origin,optarg); diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 0b248bdc..a2faf3fa 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -64,7 +64,7 @@ typedef enum { typedef u08bits hmackey_t[64]; typedef u08bits password_t[STUN_MAX_PWD_SIZE+1]; -typedef unsigned int band_limit_t; +typedef unsigned long band_limit_t; /////////////////////////////////// From 1b279a2a5ff58aa9f7b00a7cc8c33cd68c51b8d0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 15 Mar 2015 06:10:49 +0000 Subject: [PATCH 503/805] optional SCTP support added --- ChangeLog | 4 ++++ configure | 12 +++++++++++- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/apps/peer/udpserver.c | 2 +- src/apps/relay/dtls_listener.c | 6 +++--- src/apps/relay/mainrelay.c | 6 +++++- src/apps/relay/ns_ioalib_engine_impl.c | 14 +++++++------- src/apps/relay/tls_listener.c | 2 +- src/apps/relay/turn_admin_server.c | 2 +- src/apps/stunclient/stunclient.c | 4 ++-- src/apps/uclient/startuclient.c | 8 +++++--- src/ns_turn_defs.h | 26 +++++++++++++++++++++++++- src/server/ns_turn_ioalib.h | 2 +- 14 files changed, 70 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0a5a39c5..5e16ef91 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +3/15/2015 Oleg Moskalenko +Version 4.4.3.1 'Ardee West': + - SCTP support compilation option; + 2/28/2015 Oleg Moskalenko Version 4.4.2.3 'Ardee West': - bandwidth control fixed; diff --git a/configure b/configure index fbb02442..1cb67df0 100755 --- a/configure +++ b/configure @@ -1157,12 +1157,22 @@ if [ -z "${LDCONFIG}" ] ; then fi fi +############################### +# SCTP +############################### + +if [ -z "${TURN_SCTP}" ] ; then + echo "no SCTP support" +else + echo "compiling with native SCTP client-side support (in place of TCP)" + TURN_SCTP="-DTURN_SCTP" +fi ############################### # So, what we have now: ############################### -OSCFLAGS="${OSCFLAGS} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX} -DTURNDB=${TURNDBDIR}/turndb" +OSCFLAGS="${OSCFLAGS} ${TURN_SCTP} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX} -DTURNDB=${TURNDBDIR}/turndb" if ! [ -z "${TURN_ACCEPT_RPATH}" ] ; then if [ -z "${TURN_DISABLE_RPATH}" ] ; then diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 0150ec91..df864e5f 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.4.2.3 +TURNVERSION=4.4.3.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 32e4ae8d..be515ffd 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.4.2.3 +Version: 4.4.3.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -288,6 +288,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Sun Mar 15 2015 Oleg Moskalenko + - Sync to 4.4.3.1 * Sat Feb 28 2015 Oleg Moskalenko - Sync to 4.4.2.3 * Wed Feb 18 2015 Oleg Moskalenko diff --git a/src/apps/peer/udpserver.c b/src/apps/peer/udpserver.c index 9e6e3fde..4b15f0bd 100644 --- a/src/apps/peer/udpserver.c +++ b/src/apps/peer/udpserver.c @@ -74,7 +74,7 @@ static int udp_create_server_socket(server_type* server, if(make_ioa_addr((const u08bits*)local_address, port, server_addr)<0) return -1; - udp_fd = socket(server_addr->ss.sa_family, SOCK_DGRAM, 0); + udp_fd = socket(server_addr->ss.sa_family, RELAY_DGRAM_SOCKET_TYPE, RELAY_DGRAM_SOCKET_PROTOCOL); if (udp_fd < 0) { perror("socket"); return -1; diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index 0762fbc8..26393548 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -474,7 +474,7 @@ static int create_new_connected_udp_socket( dtls_listener_relay_server_type* server, ioa_socket_handle s) { - evutil_socket_t udp_fd = socket(s->local_addr.ss.sa_family, SOCK_DGRAM, 0); + evutil_socket_t udp_fd = socket(s->local_addr.ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); if (udp_fd < 0) { perror("socket"); TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Cannot allocate new socket\n", @@ -751,7 +751,7 @@ static int create_server_socket(dtls_listener_relay_server_type* server, int rep { ioa_socket_raw udp_listen_fd = -1; - udp_listen_fd = socket(server->addr.ss.sa_family, SOCK_DGRAM, 0); + udp_listen_fd = socket(server->addr.ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); if (udp_listen_fd < 0) { perror("socket"); return -1; @@ -830,7 +830,7 @@ static int reopen_server_socket(dtls_listener_relay_server_type* server, evutil_ return create_server_socket(server,1); } - ioa_socket_raw udp_listen_fd = socket(server->addr.ss.sa_family, SOCK_DGRAM, 0); + ioa_socket_raw udp_listen_fd = socket(server->addr.ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); if (udp_listen_fd < 0) { perror("socket"); FUNCEND; diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 035caf8e..206e1075 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1690,7 +1690,11 @@ static void set_network_engine(void) turn_params.net_engine_version = NEV_UDP_SOCKET_PER_ENDPOINT; #if defined(SO_REUSEPORT) #if defined(__linux__) || defined(__LINUX__) || defined(__linux) || defined(linux__) || defined(LINUX) || defined(__LINUX) || defined(LINUX__) - turn_params.net_engine_version = NEV_UDP_SOCKET_PER_THREAD; + if(CLIENT_STREAM_SOCKET_PROTOCOL == IPPROTO_IP) { + turn_params.net_engine_version = NEV_UDP_SOCKET_PER_THREAD; + } else { + turn_params.net_engine_version = NEV_UDP_SOCKET_PER_SESSION; + } #else /* BSD ? */ turn_params.net_engine_version = NEV_UDP_SOCKET_PER_SESSION; #endif /* Linux */ diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index b7066335..3804a80a 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -892,14 +892,14 @@ int set_socket_options(ioa_socket_handle s) /* <<== Socket options helpers */ -ioa_socket_handle create_unbound_ioa_socket(ioa_engine_handle e, int family, SOCKET_TYPE st, SOCKET_APP_TYPE sat) +ioa_socket_handle create_unbound_relay_ioa_socket(ioa_engine_handle e, int family, SOCKET_TYPE st, SOCKET_APP_TYPE sat) { evutil_socket_t fd = -1; ioa_socket_handle ret = NULL; switch (st){ case UDP_SOCKET: - fd = socket(family, SOCK_DGRAM, 0); + fd = socket(family, RELAY_DGRAM_SOCKET_TYPE, RELAY_DGRAM_SOCKET_PROTOCOL); if (fd < 0) { perror("UDP socket"); return NULL; @@ -907,7 +907,7 @@ ioa_socket_handle create_unbound_ioa_socket(ioa_engine_handle e, int family, SOC set_sock_buf_size(fd, UR_CLIENT_SOCK_BUF_SIZE); break; case TCP_SOCKET: - fd = socket(family, SOCK_STREAM, 0); + fd = socket(family, RELAY_STREAM_SOCKET_TYPE, RELAY_STREAM_SOCKET_PROTOCOL); if (fd < 0) { perror("TCP socket"); return NULL; @@ -1016,7 +1016,7 @@ int create_relay_ioa_sockets(ioa_engine_handle e, if (port >= 0 && even_port > 0) { IOA_CLOSE_SOCKET(*rtcp_s); - *rtcp_s = create_unbound_ioa_socket(e, relay_addr.ss.sa_family, UDP_SOCKET, RELAY_RTCP_SOCKET); + *rtcp_s = create_unbound_relay_ioa_socket(e, relay_addr.ss.sa_family, UDP_SOCKET, RELAY_RTCP_SOCKET); if (*rtcp_s == NULL) { perror("socket"); IOA_CLOSE_SOCKET(*rtp_s); @@ -1052,7 +1052,7 @@ int create_relay_ioa_sockets(ioa_engine_handle e, IOA_CLOSE_SOCKET(*rtp_s); - *rtp_s = create_unbound_ioa_socket(e, relay_addr.ss.sa_family, + *rtp_s = create_unbound_relay_ioa_socket(e, relay_addr.ss.sa_family, (transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) ? TCP_SOCKET : UDP_SOCKET, RELAY_SOCKET); if (*rtp_s == NULL) { @@ -1224,7 +1224,7 @@ static void connect_eventcb(struct bufferevent *bev, short events, void *ptr) ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, ioa_addr *peer_addr, connect_cb cb, void *arg) { - ioa_socket_handle ret = create_unbound_ioa_socket(s->e, s->family, s->st, TCP_RELAY_DATA_SOCKET); + ioa_socket_handle ret = create_unbound_relay_ioa_socket(s->e, s->family, s->st, TCP_RELAY_DATA_SOCKET); if(!ret) { return NULL; @@ -1590,7 +1590,7 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s) evutil_socket_t udp_fd = -1; if(s->parent_s) { - udp_fd = socket(s->local_addr.ss.sa_family, SOCK_DGRAM, 0); + udp_fd = socket(s->local_addr.ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); if (udp_fd < 0) { perror("socket"); TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"%s: Cannot allocate new socket\n",__FUNCTION__); diff --git a/src/apps/relay/tls_listener.c b/src/apps/relay/tls_listener.c index 03208b4a..12d874be 100644 --- a/src/apps/relay/tls_listener.c +++ b/src/apps/relay/tls_listener.c @@ -130,7 +130,7 @@ static int create_server_listener(tls_listener_relay_server_type* server) { evutil_socket_t tls_listen_fd = -1; - tls_listen_fd = socket(server->addr.ss.sa_family, SOCK_STREAM, 0); + tls_listen_fd = socket(server->addr.ss.sa_family, CLIENT_STREAM_SOCKET_TYPE, CLIENT_STREAM_SOCKET_PROTOCOL); if (tls_listen_fd < 0) { perror("socket"); return -1; diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index af616aa8..a9fb4d3a 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1263,7 +1263,7 @@ void setup_admin_thread(void) addr_set_port(&cli_addr,cli_port); - adminserver.listen_fd = socket(cli_addr.ss.sa_family, SOCK_STREAM, 0); + adminserver.listen_fd = socket(cli_addr.ss.sa_family, ADMIN_STREAM_SOCKET_TYPE, ADMIN_STREAM_SOCKET_PROTOCOL); if (adminserver.listen_fd < 0) { perror("socket"); TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot open CLI socket\n"); diff --git a/src/apps/stunclient/stunclient.c b/src/apps/stunclient/stunclient.c index d7ff4c81..6565d5f2 100644 --- a/src/apps/stunclient/stunclient.c +++ b/src/apps/stunclient/stunclient.c @@ -258,7 +258,7 @@ static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, i err(-1, NULL); if (udp_fd < 0) { - udp_fd = socket(remote_addr.ss.sa_family, SOCK_DGRAM, 0); + udp_fd = socket(remote_addr.ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); if (udp_fd < 0) err(-1, NULL); @@ -270,7 +270,7 @@ static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, i if (response_port >= 0) { - new_udp_fd = socket(remote_addr.ss.sa_family, SOCK_DGRAM, 0); + new_udp_fd = socket(remote_addr.ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); if (new_udp_fd < 0) err(-1, NULL); diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index c8e2e138..f9345717 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -229,7 +229,9 @@ static int clnet_connect(uint16_t clnet_remote_port, const char *remote_address, ns_bzero(&local_addr, sizeof(ioa_addr)); - clnet_fd = socket(remote_addr.ss.sa_family, use_tcp ? SOCK_STREAM : SOCK_DGRAM, 0); + clnet_fd = socket(remote_addr.ss.sa_family, + use_tcp ? CLIENT_STREAM_SOCKET_TYPE : CLIENT_DGRAM_SOCKET_TYPE, + use_tcp ? CLIENT_STREAM_SOCKET_PROTOCOL : CLIENT_DGRAM_SOCKET_PROTOCOL); if (clnet_fd < 0) { perror("socket"); exit(-1); @@ -1570,7 +1572,7 @@ void tcp_data_connect(app_ur_session *elem, u32bits cid) again: - clnet_fd = socket(elem->pinfo.remote_addr.ss.sa_family, SOCK_STREAM, 0); + clnet_fd = socket(elem->pinfo.remote_addr.ss.sa_family, CLIENT_STREAM_SOCKET_TYPE, CLIENT_STREAM_SOCKET_PROTOCOL); if (clnet_fd < 0) { perror("socket"); exit(-1); @@ -1606,7 +1608,7 @@ void tcp_data_connect(app_ur_session *elem, u32bits cid) if (addr_connect(clnet_fd, &(elem->pinfo.remote_addr),&err) < 0) { if(err == EADDRINUSE) { socket_closesocket(clnet_fd); - clnet_fd = socket(elem->pinfo.remote_addr.ss.sa_family, SOCK_STREAM, 0); + clnet_fd = socket(elem->pinfo.remote_addr.ss.sa_family, CLIENT_STREAM_SOCKET_TYPE, CLIENT_STREAM_SOCKET_PROTOCOL); if (clnet_fd < 0) { perror("socket"); exit(-1); diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index d5af888d..3a4325bf 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.4.2.3" +#define TURN_SERVER_VERSION "4.4.3.1" #define TURN_SERVER_VERSION_NAME "Ardee West" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" @@ -218,6 +218,30 @@ typedef u32bits turn_time_t; //////////////////////////////////////////////////////// +//#define DGRAM_SOCKET_TYPE SOCK_SEQPACKET +//#define DGRAM_SOCKET_PROTOCOL IPPROTO_SCTP + +#define CLIENT_DGRAM_SOCKET_TYPE SOCK_DGRAM +#define CLIENT_DGRAM_SOCKET_PROTOCOL IPPROTO_IP + +#define CLIENT_STREAM_SOCKET_TYPE SOCK_STREAM + +#if defined(TURN_SCTP) + #define CLIENT_STREAM_SOCKET_PROTOCOL IPPROTO_SCTP +#else + #define CLIENT_STREAM_SOCKET_PROTOCOL IPPROTO_IP +#endif + +#define RELAY_DGRAM_SOCKET_TYPE SOCK_DGRAM +#define RELAY_DGRAM_SOCKET_PROTOCOL IPPROTO_IP +#define RELAY_STREAM_SOCKET_TYPE SOCK_STREAM +#define RELAY_STREAM_SOCKET_PROTOCOL IPPROTO_IP + +#define ADMIN_STREAM_SOCKET_TYPE SOCK_STREAM +#define ADMIN_STREAM_SOCKET_PROTOCOL IPPROTO_IP + +//////////////////////////////////////////////////////// + #ifdef __cplusplus } #endif diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 4e6cb518..5208484a 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -206,7 +206,7 @@ void stop_ioa_timer(ioa_timer_handle th); void delete_ioa_timer(ioa_timer_handle th); #define IOA_EVENT_DEL(E) do { if(E) { delete_ioa_timer(E); E = NULL; } } while(0) -ioa_socket_handle create_unbound_ioa_socket(ioa_engine_handle e, int family, SOCKET_TYPE st, SOCKET_APP_TYPE sat); +ioa_socket_handle create_unbound_relay_ioa_socket(ioa_engine_handle e, int family, SOCKET_TYPE st, SOCKET_APP_TYPE sat); void inc_ioa_socket_ref_counter(ioa_socket_handle s); From 3888a928bf7031708d93fa2890c66ad7c6f39a8e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 15 Mar 2015 06:33:06 +0000 Subject: [PATCH 504/805] working on SCTP support --- INSTALL | 17 ++++++++++++++++- src/apps/relay/ns_ioalib_engine_impl.c | 12 +++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/INSTALL b/INSTALL index 8edc407a..fa548cbe 100644 --- a/INSTALL +++ b/INSTALL @@ -1191,4 +1191,19 @@ 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). If the ALPN functionality is needed, then OpenSSL version 1.0.2 or newer has to be used. See OPENSSL section for the OpenSSL upgrade hints. - \ No newline at end of file + +XXV. SCTP support + +Starting with version 4.4.3.1, the TURN server can have 'native' SCTP support +compiling in (if the platform supports SCTP). If compiled with TURN_SCTP +environment variable set to a non-empty value, then SCTP replaces TCP in the +TURN client - TURN server communications: + + $ TURN_SCTP=1 ./configure + $ make + +With this option, on the client side, the TURN server will support UDP, DTLS, +SCTP and TLS-over-SCTP. + +The relay side is not changing - the relay communications will still be UDP +or TCP. diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 3804a80a..9caf17e6 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -810,7 +810,6 @@ int set_raw_socket_tos_options(evutil_socket_t fd, int family) int set_socket_options_fd(evutil_socket_t fd, int tcp, int family) { - if(fd<0) return 0; @@ -859,14 +858,17 @@ int set_socket_options_fd(evutil_socket_t fd, int tcp, int family) #endif } else { - int flag = 1; - int result = setsockopt(fd, /* socket affected */ + + if(CLIENT_STREAM_SOCKET_PROTOCOL == IPPROTO_IP) { + int flag = 1; + int result = setsockopt(fd, /* socket affected */ IPPROTO_TCP, /* set option at TCP level */ TCP_NODELAY, /* name of option */ (char*)&flag, /* value */ sizeof(int)); /* length of option value */ - if (result < 0) - perror("TCP_NODELAY"); + if (result < 0) + perror("TCP_NODELAY"); + } socket_tcp_set_keepalive(fd); } From 69653ea259b894c647143431392c3a47ca670206 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 15 Mar 2015 19:48:30 +0000 Subject: [PATCH 505/805] native SCTP support --- ChangeLog | 4 +- INSTALL | 13 +--- README.turnutils | 7 ++- configure | 13 +--- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 2 +- man/man1/turnutils.1 | 11 +++- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +- src/apps/relay/dtls_listener.c | 12 ++-- src/apps/relay/mainrelay.c | 8 +-- src/apps/relay/netengine.c | 16 +++-- src/apps/relay/ns_ioalib_engine_impl.c | 24 +++----- src/apps/relay/tls_listener.c | 85 ++++++++++++++++++++++++-- src/apps/uclient/mainuclient.c | 10 ++- src/apps/uclient/startuclient.c | 4 +- src/apps/uclient/uclient.h | 1 + src/ns_turn_defs.h | 13 ++-- 18 files changed, 148 insertions(+), 83 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5e16ef91..60e2bcc5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ 3/15/2015 Oleg Moskalenko -Version 4.4.3.1 'Ardee West': - - SCTP support compilation option; +Version 4.4.4.1 'Ardee West': + - 'native' SCTP support; 2/28/2015 Oleg Moskalenko Version 4.4.2.3 'Ardee West': diff --git a/INSTALL b/INSTALL index fa548cbe..00c9fb2d 100644 --- a/INSTALL +++ b/INSTALL @@ -1194,16 +1194,9 @@ newer has to be used. See OPENSSL section for the OpenSSL upgrade hints. XXV. SCTP support -Starting with version 4.4.3.1, the TURN server can have 'native' SCTP support -compiling in (if the platform supports SCTP). If compiled with TURN_SCTP -environment variable set to a non-empty value, then SCTP replaces TCP in the -TURN client - TURN server communications: - - $ TURN_SCTP=1 ./configure - $ make - -With this option, on the client side, the TURN server will support UDP, DTLS, -SCTP and TLS-over-SCTP. +Starting with version 4.4.3.1, the TURN server supports 'native' SCTP. +On the client side, the TURN server, additionally, supports SCTP and +TLS-over-SCTP. The relay side is not changing - the relay communications will still be UDP or TCP. diff --git a/README.turnutils b/README.turnutils index a23ddbbb..65c332bb 100644 --- a/README.turnutils +++ b/README.turnutils @@ -56,12 +56,15 @@ Flags: -t Use TCP for communications between client and TURN server (default is UDP). +-b Use SCTP for communications between client and TURN server (default is UDP). + -T Use TCP for the relay transport (default - UDP). Implies options -t, -y, -c, - and ignores flags and options -s, -e, -r and -g. + and ignores flags and options -s, -e, -r and -g. Can be used together + with -b. -P Passive TCP (RFC6062 with active peer). Implies -T. --S Secure SSL connection: SSL/TLS for TCP, DTLS for UDP. +-S Secure SSL connection: SSL/TLS for TCP, DTLS for UDP, TLS/SCTP for SCTP. -U Secure unencrypted connection (suite eNULL): SSL/TLS for TCP, DTLS for UDP. diff --git a/configure b/configure index 1cb67df0..61a25a5c 100755 --- a/configure +++ b/configure @@ -1157,22 +1157,11 @@ if [ -z "${LDCONFIG}" ] ; then fi fi -############################### -# SCTP -############################### - -if [ -z "${TURN_SCTP}" ] ; then - echo "no SCTP support" -else - echo "compiling with native SCTP client-side support (in place of TCP)" - TURN_SCTP="-DTURN_SCTP" -fi - ############################### # So, what we have now: ############################### -OSCFLAGS="${OSCFLAGS} ${TURN_SCTP} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX} -DTURNDB=${TURNDBDIR}/turndb" +OSCFLAGS="${OSCFLAGS} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX} -DTURNDB=${TURNDBDIR}/turndb" if ! [ -z "${TURN_ACCEPT_RPATH}" ] ; then if [ -z "${TURN_DISABLE_RPATH}" ] ; then diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 14c658df..463a0b4e 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "18 February 2015" "" "" +.TH TURN 1 "15 March 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 12ddcd14..158ac135 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "18 February 2015" "" "" +.TH TURN 1 "15 March 2015" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index e381670b..aaf9ea34 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "18 February 2015" "" "" +.TH TURN 1 "15 March 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -70,9 +70,14 @@ Flags: Use TCP for communications between client and TURN server (default is UDP). .TP .B +\fB\-b\fP +Use SCTP for communications between client and TURN server (default is UDP). +.TP +.B \fB\-T\fP Use TCP for the relay transport (default \- UDP). Implies options \fB\-t\fP, \fB\-y\fP, \fB\-c\fP, -and ignores flags and options \fB\-s\fP, \fB\-e\fP, \fB\-r\fP and \fB\-g\fP. +and ignores flags and options \fB\-s\fP, \fB\-e\fP, \fB\-r\fP and \fB\-g\fP. Can be used together +with \fB\-b\fP. .TP .B \fB\-P\fP @@ -80,7 +85,7 @@ Passive TCP (RFC6062 with active peer). Implies \fB\-T\fP. .TP .B \fB\-S\fP -Secure SSL connection: SSL/TLS for TCP, DTLS for UDP. +Secure SSL connection: SSL/TLS for TCP, DTLS for UDP, TLS/SCTP for SCTP. .TP .B \fB\-U\fP diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index df864e5f..2ecdefda 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.4.3.1 +TURNVERSION=4.4.4.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index be515ffd..d4773162 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.4.3.1 +Version: 4.4.4.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -289,7 +289,7 @@ fi %changelog * Sun Mar 15 2015 Oleg Moskalenko - - Sync to 4.4.3.1 + - Sync to 4.4.4.1 * Sat Feb 28 2015 Oleg Moskalenko - Sync to 4.4.2.3 * Wed Feb 18 2015 Oleg Moskalenko diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index 26393548..4e4b5d3f 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -777,13 +777,13 @@ static int create_server_socket(dtls_listener_relay_server_type* server, int rep perror("Cannot bind local socket to addr"); char saddr[129]; addr_to_string(&server->addr,(u08bits*)saddr); - TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,"Cannot bind UDP/DTLS listener socket to addr %s\n",saddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,"Cannot bind DTLS/UDP listener socket to addr %s\n",saddr); if(addr_bind_cycle++verbose, &server->addr,"UDP/DTLS listener opened on"); + addr_debug_print(server->verbose, &server->addr,"DTLS/UDP listener opened on"); else if(!turn_params.no_dtls) addr_debug_print(server->verbose, &server->addr,"DTLS listener opened on"); else if(!turn_params.no_udp) @@ -868,7 +868,7 @@ static int reopen_server_socket(dtls_listener_relay_server_type* server, evutil_ if (!turn_params.no_udp && !turn_params.no_dtls) addr_debug_print(server->verbose, &server->addr, - "UDP/DTLS listener opened on "); + "DTLS/UDP listener opened on "); else if (!turn_params.no_dtls) addr_debug_print(server->verbose, &server->addr, "DTLS listener opened on "); @@ -920,7 +920,7 @@ static int init_server(dtls_listener_relay_server_type* server, if(ifname) STRCPY(server->ifname,ifname); if(make_ioa_addr((const u08bits*)local_address, port, &server->addr)<0) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot create a UDP/DTLS listener for address: %s\n",local_address); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot create a DTLS/UDP listener for address: %s\n",local_address); return -1; } diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 206e1075..2899e90e 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1614,7 +1614,7 @@ static void print_features(unsigned long mfn) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\nRFC 3489/5389/5766/5780/6062/6156 STUN/TURN Server\nVersion %s\n",TURN_SOFTWARE); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\nMax number of open files/sockets allowed for this process: %lu\n",mfn); - if(turn_params.net_engine_version == 1) + if(turn_params.net_engine_version == NEV_UDP_SOCKET_PER_ENDPOINT) mfn = mfn/3; else mfn = mfn/2; @@ -1690,11 +1690,7 @@ static void set_network_engine(void) turn_params.net_engine_version = NEV_UDP_SOCKET_PER_ENDPOINT; #if defined(SO_REUSEPORT) #if defined(__linux__) || defined(__LINUX__) || defined(__linux) || defined(linux__) || defined(LINUX) || defined(__LINUX) || defined(LINUX__) - if(CLIENT_STREAM_SOCKET_PROTOCOL == IPPROTO_IP) { - turn_params.net_engine_version = NEV_UDP_SOCKET_PER_THREAD; - } else { - turn_params.net_engine_version = NEV_UDP_SOCKET_PER_SESSION; - } + turn_params.net_engine_version = NEV_UDP_SOCKET_PER_THREAD; #else /* BSD ? */ turn_params.net_engine_version = NEV_UDP_SOCKET_PER_SESSION; #endif /* Linux */ diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index fbb55a1b..3f71bfb6 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1842,16 +1842,20 @@ void setup_server(void) if(udp_relay_servers[0]) { tot = get_real_udp_relay_servers_number(); } - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Total UDP servers: %d\n",(int)tot); + if(tot) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Total UDP servers: %d\n",(int)tot); + } } { int tot = get_real_general_relay_servers_number(); - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Total General servers: %d\n",(int)tot); - int i; - for(i = 0;iremote_addr),(u08bits*)sraddr); if (events & BEV_EVENT_EOF) { if(server->verbose) - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: TCP socket closed remotely %s\n",(unsigned long long)(ss->id),sraddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: TCP (or SCTP) socket closed remotely %s\n",(unsigned long long)(ss->id),sraddr); if(s == ss->client_socket) { shutdown_client_connection(server, ss, 0, "TCP connection closed by client (callback)"); } else if(s == ss->alloc.relay_sessions[ALLOC_IPV4_INDEX].s) { @@ -2726,12 +2722,12 @@ static void eventcb_bev(struct bufferevent *bev, short events, void *arg) } } else if (events & BEV_EVENT_ERROR) { if(EVUTIL_SOCKET_ERROR()) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"session %018llu: TCP socket error: %s %s\n",(unsigned long long)(ss->id), + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"session %018llu: TCP (or SCTP) socket error: %s %s\n",(unsigned long long)(ss->id), evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()), sraddr); } else if(server->verbose) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: TCP socket disconnected: %s\n",(unsigned long long)(ss->id),sraddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: TCP (or SCTP) socket disconnected: %s\n",(unsigned long long)(ss->id),sraddr); } - shutdown_client_connection(server, ss, 0, "TCP socket buffer operation error (callback)"); + shutdown_client_connection(server, ss, 0, "TCP (or SCTP) socket buffer operation error (callback)"); } } } diff --git a/src/apps/relay/tls_listener.c b/src/apps/relay/tls_listener.c index 12d874be..8faf28c8 100644 --- a/src/apps/relay/tls_listener.c +++ b/src/apps/relay/tls_listener.c @@ -38,6 +38,8 @@ #include +#include + /////////////////////////////////////////////////// #define FUNCSTART if(server && eve(server->verbose)) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s:%d:start\n",__FUNCTION__,__LINE__) @@ -50,6 +52,7 @@ struct tls_listener_relay_server_info ioa_engine_handle e; int verbose; struct evconnlistener *l; + struct evconnlistener *sctp_l; struct message_to_relay sm; ioa_engine_new_connection_event_handler connect_cb; struct relay_server *relay_server; @@ -149,13 +152,13 @@ static int create_server_listener(tls_listener_relay_server_type* server) { perror("Cannot bind local socket to addr"); char saddr[129]; addr_to_string(&server->addr,(u08bits*)saddr); - TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,"Cannot bind TCP/TLS listener socket to addr %s\n",saddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,"Cannot bind TLS/TCP listener socket to addr %s\n",saddr); if(addr_bind_cycle++verbose, &server->addr,"TCP/TLS listener opened on "); + addr_debug_print(server->verbose, &server->addr,"TLS/TCP listener opened on "); else if(!turn_params.no_tls) addr_debug_print(server->verbose, &server->addr,"TLS listener opened on "); else if(!turn_params.no_tcp) @@ -187,6 +190,78 @@ static int create_server_listener(tls_listener_relay_server_type* server) { return 0; } +static int sctp_create_server_listener(tls_listener_relay_server_type* server) { + + FUNCSTART; + + if(!server) return -1; + + evutil_socket_t tls_listen_fd = -1; + + tls_listen_fd = socket(server->addr.ss.sa_family, SCTP_CLIENT_STREAM_SOCKET_TYPE, SCTP_CLIENT_STREAM_SOCKET_PROTOCOL); + if (tls_listen_fd < 0) { + perror("socket"); + return -1; + } + + if(sock_bind_to_device(tls_listen_fd, (unsigned char*)server->ifname)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind listener socket to device %s\n",server->ifname); + } + + if(addr_bind(tls_listen_fd,&server->addr,1)<0) { + close(tls_listen_fd); + return -1; + } + + socket_tcp_set_keepalive(tls_listen_fd); + + socket_set_nonblocking(tls_listen_fd); + + { + struct sctp_paddrparams heartbeat; + ns_bzero(&heartbeat, sizeof(struct sctp_paddrparams)); + + heartbeat.spp_flags = SPP_HB_ENABLE; + heartbeat.spp_hbinterval = 5000; + heartbeat.spp_pathmaxrxt = 5; + + /*Set Heartbeats*/ + if(setsockopt(tls_listen_fd, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS , &heartbeat, sizeof(heartbeat)) != 0) + perror("setsockopt"); + } + + { + struct sctp_rtoinfo rtoinfo; + ns_bzero(&rtoinfo, sizeof(struct sctp_rtoinfo)); + + rtoinfo.srto_max = 5000; + + /*Set rto_max*/ + if(setsockopt(tls_listen_fd, IPPROTO_SCTP, SCTP_RTOINFO , &rtoinfo, sizeof(rtoinfo)) != 0) + perror("setsockopt"); + } + + server->sctp_l = evconnlistener_new(server->e->event_base, + server_input_handler, server, + LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, + 1024, tls_listen_fd); + + if(!(server->sctp_l)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot create SCTP listener\n"); + socket_closesocket(tls_listen_fd); + return -1; + } + + if (!turn_params.no_tls) + addr_debug_print(server->verbose, &server->addr, "TLS/SCTP listener opened on "); + else + addr_debug_print(server->verbose, &server->addr, "SCTP listener opened on "); + + FUNCEND; + + return 0; +} + static int init_server(tls_listener_relay_server_type* server, const char* ifname, const char *local_address, @@ -212,6 +287,8 @@ static int init_server(tls_listener_relay_server_type* server, server->e = e; + sctp_create_server_listener(server); + return create_server_listener(server); } diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 3d0344dd..d7ef3554 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -55,6 +55,7 @@ int do_not_use_channel=0; int c2c=0; int clnet_verbose=TURN_VERBOSE_NONE; int use_tcp=0; +int use_sctp=0; int use_secure=0; int hang_on=0; ioa_addr peer_addr; @@ -112,8 +113,9 @@ static char Usage[] = "Usage: uclient [flags] [options] turn-server-ip-address\n" "Flags:\n" " -t TCP (default - UDP).\n" + " -b SCTP (default - UDP).\n" " -T TCP relay transport (default - UDP). Implies options -t, -y, -c, and ignores \n" - " options -s, -e, -r and -g.\n" + " options -s, -e, -r and -g. Can be used together with -b\n" " -P Passive TCP (RFC6062 with active peer). Implies -T.\n" " -S Secure connection: TLS for TCP, DTLS for UDP.\n" " -U Secure connection with eNULL cipher.\n" @@ -218,7 +220,7 @@ int main(int argc, char **argv) ns_bzero(local_addr, sizeof(local_addr)); - while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:ZvsyhcxXgtTSAPDNOUHYKMRIGBJ")) != -1) { + while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:bZvsyhcxXgtTSAPDNOUHYKMRIGBJ")) != -1) { switch (c){ case 'J': { @@ -366,6 +368,10 @@ int main(int argc, char **argv) case 't': use_tcp = 1; break; + case 'b': + use_sctp = 1; + use_tcp = 1; + break; case 'P': passive_tcp = 1; /* implies 'T': */ diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index f9345717..a3fb92a6 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -230,8 +230,8 @@ static int clnet_connect(uint16_t clnet_remote_port, const char *remote_address, ns_bzero(&local_addr, sizeof(ioa_addr)); clnet_fd = socket(remote_addr.ss.sa_family, - use_tcp ? CLIENT_STREAM_SOCKET_TYPE : CLIENT_DGRAM_SOCKET_TYPE, - use_tcp ? CLIENT_STREAM_SOCKET_PROTOCOL : CLIENT_DGRAM_SOCKET_PROTOCOL); + use_sctp ? SCTP_CLIENT_STREAM_SOCKET_TYPE : (use_tcp ? CLIENT_STREAM_SOCKET_TYPE : CLIENT_DGRAM_SOCKET_TYPE), + use_sctp ? SCTP_CLIENT_STREAM_SOCKET_PROTOCOL : (use_tcp ? CLIENT_STREAM_SOCKET_PROTOCOL : CLIENT_DGRAM_SOCKET_PROTOCOL)); if (clnet_fd < 0) { perror("socket"); exit(-1); diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index fe930f3f..995f3697 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -52,6 +52,7 @@ extern int clmessage_length; extern int do_not_use_channel; extern int clnet_verbose; extern int use_tcp; +extern int use_sctp; extern int use_secure; extern char cert_file[1025]; extern char pkey_file[1025]; diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 3a4325bf..82106157 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.4.3.1" +#define TURN_SERVER_VERSION "4.4.4.1" #define TURN_SERVER_VERSION_NAME "Ardee West" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" @@ -218,19 +218,14 @@ typedef u32bits turn_time_t; //////////////////////////////////////////////////////// -//#define DGRAM_SOCKET_TYPE SOCK_SEQPACKET -//#define DGRAM_SOCKET_PROTOCOL IPPROTO_SCTP - #define CLIENT_DGRAM_SOCKET_TYPE SOCK_DGRAM #define CLIENT_DGRAM_SOCKET_PROTOCOL IPPROTO_IP #define CLIENT_STREAM_SOCKET_TYPE SOCK_STREAM +#define CLIENT_STREAM_SOCKET_PROTOCOL IPPROTO_IP -#if defined(TURN_SCTP) - #define CLIENT_STREAM_SOCKET_PROTOCOL IPPROTO_SCTP -#else - #define CLIENT_STREAM_SOCKET_PROTOCOL IPPROTO_IP -#endif +#define SCTP_CLIENT_STREAM_SOCKET_TYPE SOCK_STREAM +#define SCTP_CLIENT_STREAM_SOCKET_PROTOCOL IPPROTO_SCTP #define RELAY_DGRAM_SOCKET_TYPE SOCK_DGRAM #define RELAY_DGRAM_SOCKET_PROTOCOL IPPROTO_IP From 0496635eddc6844562d96b34852b31da678f8d51 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 15 Mar 2015 21:08:31 +0000 Subject: [PATCH 506/805] fixing SCTP on Linux --- src/apps/common/apputils.c | 14 ++++++++------ src/apps/common/apputils.h | 2 +- src/apps/peer/udpserver.c | 2 +- src/apps/relay/dtls_listener.c | 6 +++--- src/apps/relay/ns_ioalib_engine_impl.c | 4 ++-- src/apps/relay/tls_listener.c | 10 +++++++--- src/apps/relay/turn_admin_server.c | 2 +- src/apps/stunclient/stunclient.c | 4 ++-- src/apps/uclient/startuclient.c | 8 ++++---- 9 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c index 690c60d4..b8da9a97 100644 --- a/src/apps/common/apputils.c +++ b/src/apps/common/apputils.c @@ -229,7 +229,7 @@ int addr_connect(evutil_socket_t fd, const ioa_addr* addr, int *out_errno) } } -int addr_bind(evutil_socket_t fd, const ioa_addr* addr, int reusable) +int addr_bind(evutil_socket_t fd, const ioa_addr* addr, int reusable, int debug) { if (!addr || fd < 0) { @@ -255,11 +255,13 @@ int addr_bind(evutil_socket_t fd, const ioa_addr* addr, int reusable) return -1; } if(ret<0) { - int err = errno; - perror("bind"); - char str[129]; - addr_to_string(addr,(u08bits*)str); - TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "Trying to bind fd %d to <%s>: errno=%d\n", fd, str, err); + if(debug) { + int err = errno; + perror("bind"); + char str[129]; + addr_to_string(addr,(u08bits*)str); + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "Trying to bind fd %d to <%s>: errno=%d\n", fd, str, err); + } } return ret; } diff --git a/src/apps/common/apputils.h b/src/apps/common/apputils.h index fb3133b1..9d871153 100644 --- a/src/apps/common/apputils.h +++ b/src/apps/common/apputils.h @@ -180,7 +180,7 @@ int socket_tcp_set_keepalive(evutil_socket_t fd); int addr_connect(evutil_socket_t fd, const ioa_addr* addr, int *out_errno); -int addr_bind(evutil_socket_t fd, const ioa_addr* addr, int reusable); +int addr_bind(evutil_socket_t fd, const ioa_addr* addr, int reusable, int debug); int addr_get_from_sock(evutil_socket_t fd, ioa_addr *addr); diff --git a/src/apps/peer/udpserver.c b/src/apps/peer/udpserver.c index 4b15f0bd..d1b6b519 100644 --- a/src/apps/peer/udpserver.c +++ b/src/apps/peer/udpserver.c @@ -86,7 +86,7 @@ static int udp_create_server_socket(server_type* server, set_sock_buf_size(udp_fd,UR_SERVER_SOCK_BUF_SIZE); - if(addr_bind(udp_fd,server_addr,1)<0) return -1; + if(addr_bind(udp_fd,server_addr,1,1)<0) return -1; socket_set_nonblocking(udp_fd); diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index 4e4b5d3f..7c4d590f 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -509,7 +509,7 @@ static int create_new_connected_udp_socket( ret->local_addr_known = 1; addr_cpy(&(ret->local_addr), &(s->local_addr)); - if (addr_bind(udp_fd,&(s->local_addr),1) < 0) { + if (addr_bind(udp_fd,&(s->local_addr),1,1) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot bind new detached udp server socket to local addr\n"); IOA_CLOSE_SOCKET(ret); @@ -773,7 +773,7 @@ static int create_server_socket(dtls_listener_relay_server_type* server, int rep int addr_bind_cycle = 0; retry_addr_bind: - if(addr_bind(udp_listen_fd,&server->addr,1)<0) { + if(addr_bind(udp_listen_fd,&server->addr,1,1)<0) { perror("Cannot bind local socket to addr"); char saddr[129]; addr_to_string(&server->addr,(u08bits*)saddr); @@ -851,7 +851,7 @@ static int reopen_server_socket(dtls_listener_relay_server_type* server, evutil_ server->ifname); } - if(addr_bind(udp_listen_fd,&server->addr,1)<0) { + if(addr_bind(udp_listen_fd,&server->addr,1,1)<0) { perror("Cannot bind local socket to addr"); char saddr[129]; addr_to_string(&server->addr,(u08bits*)saddr); diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 75890d87..8c1316cc 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -940,7 +940,7 @@ static int bind_ioa_socket(ioa_socket_handle s, const ioa_addr* local_addr, int if (s && s->fd >= 0 && s->e && local_addr) { - int res = addr_bind(s->fd, local_addr, reusable); + int res = addr_bind(s->fd, local_addr, reusable,1); if (res >= 0) { s->bound = 1; addr_cpy(&(s->local_addr), local_addr); @@ -1598,7 +1598,7 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind udp server socket to device %s\n",(char*)(s->e->relay_ifname)); } - if(addr_bind(udp_fd,&(s->local_addr),1)<0) { + if(addr_bind(udp_fd,&(s->local_addr),1,1)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind new detached udp server socket to local addr\n"); close(udp_fd); return ret; diff --git a/src/apps/relay/tls_listener.c b/src/apps/relay/tls_listener.c index 8faf28c8..6c62aa26 100644 --- a/src/apps/relay/tls_listener.c +++ b/src/apps/relay/tls_listener.c @@ -38,7 +38,11 @@ #include +#if defined(__linux__) || defined(__LINUX__) || defined(__linux) || defined(linux__) || defined(LINUX) || defined(__LINUX) || defined(LINUX__) +#include +#else #include +#endif /////////////////////////////////////////////////// @@ -148,7 +152,7 @@ static int create_server_listener(tls_listener_relay_server_type* server) { int addr_bind_cycle = 0; retry_addr_bind: - if(addr_bind(tls_listen_fd,&server->addr,1)<0) { + if(addr_bind(tls_listen_fd,&server->addr,1,1)<0) { perror("Cannot bind local socket to addr"); char saddr[129]; addr_to_string(&server->addr,(u08bits*)saddr); @@ -208,10 +212,10 @@ static int sctp_create_server_listener(tls_listener_relay_server_type* server) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind listener socket to device %s\n",server->ifname); } - if(addr_bind(tls_listen_fd,&server->addr,1)<0) { + if(addr_bind(tls_listen_fd,&server->addr,1,0)<0) { close(tls_listen_fd); return -1; - } + } socket_tcp_set_keepalive(tls_listen_fd); diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index a9fb4d3a..dcb58cc0 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1270,7 +1270,7 @@ void setup_admin_thread(void) return; } - if(addr_bind(adminserver.listen_fd,&cli_addr,1)<0) { + if(addr_bind(adminserver.listen_fd,&cli_addr,1,1)<0) { perror("Cannot bind CLI socket to addr"); char saddr[129]; addr_to_string(&cli_addr,(u08bits*)saddr); diff --git a/src/apps/stunclient/stunclient.c b/src/apps/stunclient/stunclient.c index 6565d5f2..eb1029c7 100644 --- a/src/apps/stunclient/stunclient.c +++ b/src/apps/stunclient/stunclient.c @@ -263,7 +263,7 @@ static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, i err(-1, NULL); if (!addr_any(&real_local_addr)) { - if (addr_bind(udp_fd, &real_local_addr,0) < 0) + if (addr_bind(udp_fd, &real_local_addr,0,1) < 0) err(-1, NULL); } } @@ -276,7 +276,7 @@ static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, i addr_set_port(&real_local_addr, response_port); - if (addr_bind(new_udp_fd, &real_local_addr,0) < 0) + if (addr_bind(new_udp_fd, &real_local_addr,0,1) < 0) err(-1, NULL); } diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index a3fb92a6..3153dc5d 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -259,7 +259,7 @@ static int clnet_connect(uint16_t clnet_remote_port, const char *remote_address, } } - addr_bind(clnet_fd, &local_addr, 0); + addr_bind(clnet_fd, &local_addr, 0, 1); } else if (strlen(local_address) > 0) { @@ -267,7 +267,7 @@ static int clnet_connect(uint16_t clnet_remote_port, const char *remote_address, &local_addr) < 0) return -1; - addr_bind(clnet_fd, &local_addr,0); + addr_bind(clnet_fd, &local_addr,0,1); } if(clnet_info->is_peer) { @@ -1597,7 +1597,7 @@ void tcp_data_connect(app_ur_session *elem, u32bits cid) addr_set_port(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),0); - addr_bind(clnet_fd, &(elem->pinfo.tcp_conn[i]->tcp_data_local_addr), 1); + addr_bind(clnet_fd, &(elem->pinfo.tcp_conn[i]->tcp_data_local_addr), 1, 1); addr_get_from_sock(clnet_fd,&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr)); @@ -1625,7 +1625,7 @@ void tcp_data_connect(app_ur_session *elem, u32bits cid) addr_set_port(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),0); - addr_bind(clnet_fd, &(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),1); + addr_bind(clnet_fd, &(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),1,1); addr_get_from_sock(clnet_fd,&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr)); From 7d5ab2472acb9a170f9a4d14f204ecc5f956eb42 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 15 Mar 2015 21:24:36 +0000 Subject: [PATCH 507/805] working on SCTP --- INSTALL | 3 +- .../longtermsecure/secure_sctp_client.sh | 34 +++++++++++++++++++ rpm/turnserver.spec | 1 + 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100755 examples/scripts/longtermsecure/secure_sctp_client.sh diff --git a/INSTALL b/INSTALL index 00c9fb2d..6ec90a12 100644 --- a/INSTALL +++ b/INSTALL @@ -594,6 +594,7 @@ In shell number 3, run secure test client application: (or ./scripts/longtermsecure/secure_tcp_client.sh) (or ./scripts/longtermsecure/secure_tls_client.sh) (or ./scripts/longtermsecure/secure_dtls_client.sh) + (or ./scripts/longtermsecure/secure_sctp_client.sh) (or ./scripts/longtermsecure/secure_udp_c2c.sh for "peerless" client-to-client communications) @@ -1196,7 +1197,7 @@ XXV. SCTP support Starting with version 4.4.3.1, the TURN server supports 'native' SCTP. On the client side, the TURN server, additionally, supports SCTP and -TLS-over-SCTP. +TLS-over-SCTP. The relay side is not changing - the relay communications will still be UDP or TCP. diff --git a/examples/scripts/longtermsecure/secure_sctp_client.sh b/examples/scripts/longtermsecure/secure_sctp_client.sh new file mode 100755 index 00000000..cff79e19 --- /dev/null +++ b/examples/scripts/longtermsecure/secure_sctp_client.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# This is an example of a script to run a "secure" TURN TLS client +# with the long-term credentials mechanism. +# +# Options: +# +# 1) -b is present, it means that SCTP networking is used. +# 2) -S means "SSL/TLS protocol with default cipher" will be used over SCTP. +# 3) -i absent. +# 4) -k sets private key file for TLS. +# 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) -u gorst means that if the server challenges the client with +# authentication challenge, then we use account "gorst". +# 11) -w hero sets the password for the account as "hero". +# 12) -s option means that the client will be using "send" mechanism for data. +# 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 -S -k turn_client_pkey.pem -n 1000 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 + diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index d4773162..e6e630fd 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -228,6 +228,7 @@ fi %{_datadir}/%{name}/scripts/longtermsecure/secure_tls_client_c2c_tcp_relay.sh %{_datadir}/%{name}/scripts/longtermsecure/secure_udp_c2c.sh %{_datadir}/%{name}/scripts/longtermsecure/secure_udp_client.sh +%{_datadir}/%{name}/scripts/longtermsecure/secure_sctp_client.sh %dir %{_datadir}/%{name}/scripts/longtermsecuredb %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh From b824384faa0d6207bee35bbdd8a11472aa97f734 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 16 Mar 2015 06:10:10 +0000 Subject: [PATCH 508/805] working on SCTP --- src/apps/relay/ns_ioalib_engine_impl.c | 122 +++++++++++++++++++++---- src/apps/relay/tls_listener.c | 65 ++++++++++++- src/apps/relay/turn_admin_server.c | 18 ++-- src/server/ns_turn_ioalib.h | 4 + src/server/ns_turn_server.c | 16 ++-- 5 files changed, 194 insertions(+), 31 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 8c1316cc..4e3f73f5 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -121,8 +121,12 @@ static int is_socket_writeable(ioa_socket_handle s, size_t sz, const char *msg, switch (s->st){ + case SCTP_SOCKET: + case TLS_SCTP_SOCKET: + case TCP_SOCKET: case TLS_SOCKET: + if (s->bev) { struct evbuffer *evb = bufferevent_get_output(s->bev); @@ -877,7 +881,7 @@ int set_socket_options(ioa_socket_handle s) if(!s || (s->parent_s)) return 0; - set_socket_options_fd(s->fd,((s->st == TCP_SOCKET) || (s->st == TLS_SOCKET) || (s->st == TENTATIVE_TCP_SOCKET)),s->family); + set_socket_options_fd(s->fd,is_stream_socket(s->st),s->family); s->default_ttl = get_raw_socket_ttl(s->fd, s->family); s->current_ttl = s->default_ttl; @@ -888,6 +892,21 @@ int set_socket_options(ioa_socket_handle s) return 0; } +int is_stream_socket(int st) { + switch(st) { + case TCP_SOCKET: + case TLS_SOCKET: + case TENTATIVE_TCP_SOCKET: + case SCTP_SOCKET: + case TLS_SCTP_SOCKET: + case TENTATIVE_SCTP_SOCKET: + return 1; + default: + ; + } + return 0; +} + /* <<== Socket options helpers */ ioa_socket_handle create_unbound_relay_ioa_socket(ioa_engine_handle e, int family, SOCKET_TYPE st, SOCKET_APP_TYPE sat) @@ -1282,7 +1301,7 @@ ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, io * Section 5.2 of RFC 6062 will not work correctly * for those OSes (for example, Linux pre-3.9 kernel). */ - s->fd = socket(s->family, SOCK_STREAM, 0); + s->fd = socket(s->family, RELAY_STREAM_SOCKET_TYPE, RELAY_STREAM_SOCKET_PROTOCOL); if (s->fd < 0) { perror("TCP socket"); if(ret) { @@ -2209,7 +2228,7 @@ static int socket_input_worker(ioa_socket_handle s) } } - if(s->st == TLS_SOCKET) { + if((s->st == TLS_SOCKET)||(s->st == TLS_SCTP_SOCKET)) { #if TLS_SUPPORTED SSL *ctx = bufferevent_openssl_get_ssl(s->bev); if(!ctx || SSL_get_shutdown(ctx)) { @@ -2295,6 +2314,74 @@ static int socket_input_worker(ioa_socket_handle s) bufferevent_setwatermark(s->bev, EV_READ|EV_WRITE, 0, BUFFEREVENT_HIGH_WATERMARK); bufferevent_enable(s->bev, EV_READ|EV_WRITE); /* Start reading. */ } + } else if(s->st == TENTATIVE_SCTP_SOCKET) { + EVENT_DEL(s->read_event); +#if TLS_SUPPORTED + TURN_TLS_TYPE tls_type = check_tentative_tls(s->fd); + if(tls_type) { + s->st = TLS_SCTP_SOCKET; + if(s->ssl) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!!%s on socket: 0x%lx, st=%d, sat=%d: ssl already exist\n", __FUNCTION__,(long)s, s->st, s->sat); + } + if(s->bev) { + 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); + } + switch(tls_type) { +#if TLSv1_2_SUPPORTED + case TURN_TLS_v1_2: + if(s->e->tls_ctx_v1_2) { + set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_2)); + } + break; +#endif +#if TLSv1_1_SUPPORTED + case TURN_TLS_v1_1: + if(s->e->tls_ctx_v1_1) { + set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_1)); + } + break; +#endif + case TURN_TLS_v1_0: + if(s->e->tls_ctx_v1_0) { + set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_0)); + } + break; + default: + if(s->e->tls_ctx_ssl23) { + set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_ssl23)); + } else { + s->tobeclosed = 1; + return 0; + } + }; + if(s->ssl) { + s->bev = bufferevent_openssl_socket_new(s->e->event_base, + s->fd, + s->ssl, + BUFFEREVENT_SSL_ACCEPTING, + 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. */ + } + } else +#endif //TLS_SUPPORTED + { + s->st = SCTP_SOCKET; + if(s->bev) { + 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); + 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. */ + } } try_start: @@ -2308,7 +2395,7 @@ static int socket_input_worker(ioa_socket_handle s) stun_buffer_list_elem *buf_elem = new_blist_elem(s->e); len = -1; - if(s->bev) { /* TCP & TLS */ + if(s->bev) { /* TCP & TLS & SCTP & SCTP/TLS */ struct evbuffer *inbuf = bufferevent_get_input(s->bev); if(inbuf) { ev_ssize_t blen = evbuffer_copyout(inbuf, buf_elem->buf.buf, STUN_BUFFER_SIZE); @@ -2318,7 +2405,7 @@ static int socket_input_worker(ioa_socket_handle s) if(blen>(ev_ssize_t)STUN_BUFFER_SIZE) blen=(ev_ssize_t)STUN_BUFFER_SIZE; - if(((s->st == TCP_SOCKET)||(s->st == TLS_SOCKET)) && ((s->sat == TCP_CLIENT_DATA_SOCKET)||(s->sat==TCP_RELAY_DATA_SOCKET))) { + if(is_stream_socket(s->st) && ((s->sat == TCP_CLIENT_DATA_SOCKET)||(s->sat==TCP_RELAY_DATA_SOCKET))) { mlen = blen; } else { mlen = stun_get_message_len_str(buf_elem->buf.buf, blen, 1, &app_msg_len); @@ -2331,7 +2418,7 @@ static int socket_input_worker(ioa_socket_handle s) s->tobeclosed = 1; s->broken = 1; log_socket_event(s, "socket read failed, to be closed",1); - } else if(s->st == TLS_SOCKET) { + } else if((s->st == TLS_SOCKET)||(s->st == TLS_SCTP_SOCKET)) { #if TLS_SUPPORTED SSL *ctx = bufferevent_openssl_get_ssl(s->bev); if(!ctx || SSL_get_shutdown(ctx)) { @@ -2650,7 +2737,7 @@ static void eventcb_bev(struct bufferevent *bev, short events, void *arg) if (arg) { ioa_socket_handle s = (ioa_socket_handle) arg; - if((s->st != TCP_SOCKET)&&(s->st != TLS_SOCKET)&&(s->st != TENTATIVE_TCP_SOCKET)) { + if(!is_stream_socket(s->st)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s: socket type is wrong on the socket: 0x%lx, st=%d, sat=%d\n",__FUNCTION__,(long)s,s->st,s->sat); return; } @@ -2710,24 +2797,24 @@ static void eventcb_bev(struct bufferevent *bev, short events, void *arg) addr_to_string(&(s->remote_addr),(u08bits*)sraddr); if (events & BEV_EVENT_EOF) { if(server->verbose) - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: TCP (or SCTP) socket closed remotely %s\n",(unsigned long long)(ss->id),sraddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: stream (TCP or SCTP) socket closed remotely %s\n",(unsigned long long)(ss->id),sraddr); if(s == ss->client_socket) { - shutdown_client_connection(server, ss, 0, "TCP connection closed by client (callback)"); + shutdown_client_connection(server, ss, 0, "Stream (TCP or SCTP) connection closed by client (callback)"); } else if(s == ss->alloc.relay_sessions[ALLOC_IPV4_INDEX].s) { - shutdown_client_connection(server, ss, 0, "TCP connection closed by peer (ipv4 callback)"); + shutdown_client_connection(server, ss, 0, "Stream (TCP or SCTP) connection closed by peer (ipv4 callback)"); } else if(s == ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].s) { - shutdown_client_connection(server, ss, 0, "TCP connection closed by peer (ipv6 callback)"); + shutdown_client_connection(server, ss, 0, "Stream (TCP or SCTP) connection closed by peer (ipv6 callback)"); } else { - shutdown_client_connection(server, ss, 0, "TCP connection closed by remote party (callback)"); + shutdown_client_connection(server, ss, 0, "Stream (TCP or SCTP) connection closed by remote party (callback)"); } } else if (events & BEV_EVENT_ERROR) { if(EVUTIL_SOCKET_ERROR()) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"session %018llu: TCP (or SCTP) socket error: %s %s\n",(unsigned long long)(ss->id), evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()), sraddr); } else if(server->verbose) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: TCP (or SCTP) socket disconnected: %s\n",(unsigned long long)(ss->id),sraddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: stream (TCP or SCTP) socket disconnected: %s\n",(unsigned long long)(ss->id),sraddr); } - shutdown_client_connection(server, ss, 0, "TCP (or SCTP) socket buffer operation error (callback)"); + shutdown_client_connection(server, ss, 0, "Stream (TCP or SCTP) socket buffer operation error (callback)"); } } } @@ -3003,7 +3090,7 @@ int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, set_socket_tos(s, tos); if (s->connected && s->bev) { - if (s->st == TLS_SOCKET) { + if ((s->st == TLS_SOCKET)||(s->st == TLS_SCTP_SOCKET)) { #if TLS_SUPPORTED SSL *ctx = bufferevent_openssl_get_ssl(s->bev); if (!ctx || SSL_get_shutdown(ctx)) { @@ -3107,7 +3194,7 @@ int send_data_from_ioa_socket_tcp(ioa_socket_handle s, const void *data, size_t 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 ((s->st == TLS_SOCKET)||(s->st == TLS_SCTP_SOCKET)) { #if TLS_SUPPORTED SSL *ctx = bufferevent_openssl_get_ssl(s->bev); if (!ctx || SSL_get_shutdown(ctx)) { @@ -3180,6 +3267,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in } break; case TENTATIVE_TCP_SOCKET: + case TENTATIVE_SCTP_SOCKET: if(s->bev) { if(!clean_preexisting) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, @@ -3197,6 +3285,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in event_add(s->read_event,NULL); } break; + case SCTP_SOCKET: case TCP_SOCKET: if(s->bev) { if(!clean_preexisting) { @@ -3220,6 +3309,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in } } break; + case TLS_SCTP_SOCKET: case TLS_SOCKET: if(s->bev) { if(!clean_preexisting) { diff --git a/src/apps/relay/tls_listener.c b/src/apps/relay/tls_listener.c index 6c62aa26..85fa0c6c 100644 --- a/src/apps/relay/tls_listener.c +++ b/src/apps/relay/tls_listener.c @@ -127,6 +127,69 @@ static void server_input_handler(struct evconnlistener *l, evutil_socket_t fd, FUNCEND ; } +static void sctp_server_input_handler(struct evconnlistener *l, evutil_socket_t fd, + struct sockaddr *sa, int socklen, void *arg) +{ + + UNUSED_ARG(l); + + tls_listener_relay_server_type * server = (tls_listener_relay_server_type*) arg; + + if(!(server->connect_cb)) { + socket_closesocket(fd); + return; + } + + FUNCSTART; + + if (!server) + return; + + ns_bcopy(sa,&(server->sm.m.sm.nd.src_addr),socklen); + + addr_debug_print(server->verbose, &(server->sm.m.sm.nd.src_addr),"tcp or tls connected to"); + + SOCKET_TYPE st = TENTATIVE_SCTP_SOCKET; + + if(turn_params.no_tls) + st = SCTP_SOCKET; + else if(turn_params.no_tcp) + st = TLS_SCTP_SOCKET; + + ioa_socket_handle ioas = + create_ioa_socket_from_fd( + server->e, + fd, + NULL, + st, + CLIENT_SOCKET, + &(server->sm.m.sm.nd.src_addr), + &(server->addr)); + + if (ioas) { + + server->sm.m.sm.nd.recv_ttl = TTL_IGNORE; + server->sm.m.sm.nd.recv_tos = TOS_IGNORE; + server->sm.m.sm.nd.nbh = NULL; + server->sm.m.sm.s = ioas; + server->sm.m.sm.can_resume = 1; + server->sm.relay_server = server->relay_server; + + int rc = server->connect_cb(server->e, &(server->sm)); + + if (rc < 0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Cannot create sctp or tls/sctp session\n"); + } + } else { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, + "Cannot create ioa_socket from FD\n"); + socket_closesocket(fd); + } + + FUNCEND ; +} + ///////////////////// operations ////////////////////////// static int create_server_listener(tls_listener_relay_server_type* server) { @@ -246,7 +309,7 @@ static int sctp_create_server_listener(tls_listener_relay_server_type* server) { } server->sctp_l = evconnlistener_new(server->e->event_base, - server_input_handler, server, + sctp_server_input_handler, server, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 1024, tls_listen_fd); diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index dcb58cc0..f86f26c1 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -419,14 +419,20 @@ static const char* pname(SOCKET_TYPE st) switch(st) { case TCP_SOCKET: return "TCP"; + case SCTP_SOCKET: + return "SCTP"; case UDP_SOCKET: return "UDP"; case TLS_SOCKET: - return "TLS"; + return "TLS/TCP"; + case TLS_SCTP_SOCKET: + return "TLS/SCTP"; case DTLS_SOCKET: return "DTLS"; case TENTATIVE_TCP_SOCKET: - return "TCP/TLS"; + return "TLS/TCP ?"; + case TENTATIVE_SCTP_SOCKET: + return "TLS/SCTP ?"; default: ; }; @@ -451,13 +457,13 @@ static int print_session(ur_map_key_type key, ur_map_value_type value, void *arg const char *pn=csarg->pname; if(pn[0]) { if(!strcmp(pn,"TLS") || !strcmp(pn,"tls") || !strcmp(pn,"Tls")) { - if(tsi->client_protocol != TLS_SOCKET) + if((tsi->client_protocol != TLS_SOCKET)||(tsi->client_protocol != TLS_SCTP_SOCKET)) return 0; } else if(!strcmp(pn,"DTLS") || !strcmp(pn,"dtls") || !strcmp(pn,"Dtls")) { if(tsi->client_protocol != DTLS_SOCKET) return 0; } else if(!strcmp(pn,"TCP") || !strcmp(pn,"tcp") || !strcmp(pn,"Tcp")) { - if(tsi->client_protocol != TCP_SOCKET) + if((tsi->client_protocol != TCP_SOCKET)||(tsi->client_protocol != SCTP_SOCKET)) return 0; } else if(!strcmp(pn,"UDP") || !strcmp(pn,"udp") || !strcmp(pn,"Udp")) { if(tsi->client_protocol != UDP_SOCKET) @@ -2195,13 +2201,13 @@ static int https_print_session(ur_map_key_type key, ur_map_value_type value, voi const char *pn=csarg->client_protocol; if(pn[0]) { if(!strcmp(pn,"TLS") || !strcmp(pn,"tls") || !strcmp(pn,"Tls")) { - if(tsi->client_protocol != TLS_SOCKET) + if((tsi->client_protocol != TLS_SOCKET)||(tsi->client_protocol != TLS_SCTP_SOCKET)) return 0; } else if(!strcmp(pn,"DTLS") || !strcmp(pn,"dtls") || !strcmp(pn,"Dtls")) { if(tsi->client_protocol != DTLS_SOCKET) return 0; } else if(!strcmp(pn,"TCP") || !strcmp(pn,"tcp") || !strcmp(pn,"Tcp")) { - if(tsi->client_protocol != TCP_SOCKET) + if((tsi->client_protocol != TCP_SOCKET)||(tsi->client_protocol != SCTP_SOCKET)) return 0; } else if(!strcmp(pn,"UDP") || !strcmp(pn,"udp") || !strcmp(pn,"Udp")) { if(tsi->client_protocol != UDP_SOCKET) diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 5208484a..75fc3ae5 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -87,7 +87,10 @@ enum _SOCKET_TYPE { TCP_SOCKET=6, UDP_SOCKET=17, TLS_SOCKET=56, + SCTP_SOCKET=132, + TLS_SCTP_SOCKET=133, DTLS_SOCKET=250, + TENTATIVE_SCTP_SOCKET=254, TENTATIVE_TCP_SOCKET=255 }; @@ -227,6 +230,7 @@ ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, i int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_token, ioa_socket_handle *s, u08bits *realm); int get_ioa_socket_address_family(ioa_socket_handle s); +int is_stream_socket(int st); const char* get_ioa_socket_cipher(ioa_socket_handle s); const char* get_ioa_socket_ssl_method(ioa_socket_handle s); SOCKET_TYPE get_ioa_socket_type(ioa_socket_handle s); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index cbf4fd93..68dc4cef 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1057,8 +1057,7 @@ static int handle_turn_allocate(turn_turnserver *server, *reason = (const u08bits *)"UDP Transport is not allowed by the TURN Server configuration"; } else if(ss->client_socket) { SOCKET_TYPE cst = get_ioa_socket_type(ss->client_socket); - if((transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) && - (cst!=TCP_SOCKET) && (cst!=TLS_SOCKET)) { + if((transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) && !is_stream_socket(cst)) { *err_code = 400; *reason = (const u08bits *)"Wrong Transport Data"; } else { @@ -2304,7 +2303,7 @@ static int handle_turn_connection_bind(turn_turnserver *server, *err_code = 400; *reason = (const u08bits *)"Bad request: CONNECTION_BIND cannot be issued after allocation"; - } else if((get_ioa_socket_type(ss->client_socket)!=TCP_SOCKET) && (get_ioa_socket_type(ss->client_socket)!=TLS_SOCKET)) { + } else if(!is_stream_socket(get_ioa_socket_type(ss->client_socket))) { *err_code = 400; *reason = (const u08bits *)"Bad request: CONNECTION_BIND only possible with TCP/TLS"; @@ -2666,7 +2665,8 @@ static int handle_turn_channel_bind(turn_turnserver *server, if(!(ss->is_mobile)) { if(get_ioa_socket_type(ss->client_socket) == UDP_SOCKET || - get_ioa_socket_type(ss->client_socket) == TCP_SOCKET) { + get_ioa_socket_type(ss->client_socket) == TCP_SOCKET || + get_ioa_socket_type(ss->client_socket) == SCTP_SOCKET) { if(get_ioa_socket_type(get_relay_socket(&(ss->alloc),peer_addr.ss.sa_family)) == UDP_SOCKET) { chn->kernel_channel = CREATE_TURN_CHANNEL_KERNEL(chn->chnum, get_ioa_socket_address_family(ss->client_socket), @@ -3605,7 +3605,7 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, if(((cst == UDP_SOCKET)||(cst == DTLS_SOCKET)) && server->self_udp_balance && server->aux_servers_list && server->aux_servers_list->size) { asl = server->aux_servers_list; - } else if(((cst == TLS_SOCKET) || (cst == DTLS_SOCKET)) && + } else if(((cst == TLS_SOCKET) || (cst == DTLS_SOCKET) ||(cst == TLS_SCTP_SOCKET)) && server->tls_alternate_servers_list && server->tls_alternate_servers_list->size) { asl = server->tls_alternate_servers_list; } @@ -4490,7 +4490,7 @@ static int read_client_connection(turn_turnserver *server, size_t orig_blen = blen; SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket); SOCKET_APP_TYPE sat = get_ioa_socket_app_type(ss->client_socket); - int is_padding_mandatory = ((st == TCP_SOCKET)||(st==TLS_SOCKET)||(st==TENTATIVE_TCP_SOCKET)); + int is_padding_mandatory = is_stream_socket(st); if(sat == HTTP_CLIENT_SOCKET) { @@ -4590,7 +4590,7 @@ 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_stream_socket(st)) { 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; @@ -4761,7 +4761,7 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, ioa_network_buffer_header_init(nbh); SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket); - int do_padding = ((st == TCP_SOCKET)||(st==TLS_SOCKET)||(st==TENTATIVE_TCP_SOCKET)); + int do_padding = is_stream_socket(st); stun_init_channel_message_str(chnum, ioa_network_buffer_data(nbh), &len, len, do_padding); ioa_network_buffer_set_size(nbh,len); From 2958c8ec73dcb35eba6d5888fb515745b316a1cc Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 16 Mar 2015 07:10:07 +0000 Subject: [PATCH 509/805] working on sctp --- src/apps/relay/ns_ioalib_engine_impl.c | 13 +++++++++++ src/apps/relay/tls_listener.c | 30 -------------------------- 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 4e3f73f5..44361c0c 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -50,6 +50,13 @@ #include "hiredis_libevent2.h" #endif +#if defined(__linux__) || defined(__LINUX__) || defined(__linux) || defined(linux__) || defined(LINUX) || defined(__LINUX) || defined(LINUX__) +#include +#else +#include +#endif + + /* Compilation test: #if defined(IP_RECVTTL) #undef IP_RECVTTL @@ -870,6 +877,12 @@ int set_socket_options_fd(evutil_socket_t fd, int tcp, int family) (char*)&flag, /* value */ sizeof(int)); /* length of option value */ + setsockopt(fd, /* socket affected */ + IPPROTO_SCTP, /* set option at TCP level */ + SCTP_NODELAY, /* name of option */ + (char*)&flag, /* value */ + sizeof(int)); /* length of option value */ + socket_tcp_set_keepalive(fd); } diff --git a/src/apps/relay/tls_listener.c b/src/apps/relay/tls_listener.c index 85fa0c6c..accdfa26 100644 --- a/src/apps/relay/tls_listener.c +++ b/src/apps/relay/tls_listener.c @@ -38,12 +38,6 @@ #include -#if defined(__linux__) || defined(__LINUX__) || defined(__linux) || defined(linux__) || defined(LINUX) || defined(__LINUX) || defined(LINUX__) -#include -#else -#include -#endif - /////////////////////////////////////////////////// #define FUNCSTART if(server && eve(server->verbose)) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s:%d:start\n",__FUNCTION__,__LINE__) @@ -284,30 +278,6 @@ static int sctp_create_server_listener(tls_listener_relay_server_type* server) { socket_set_nonblocking(tls_listen_fd); - { - struct sctp_paddrparams heartbeat; - ns_bzero(&heartbeat, sizeof(struct sctp_paddrparams)); - - heartbeat.spp_flags = SPP_HB_ENABLE; - heartbeat.spp_hbinterval = 5000; - heartbeat.spp_pathmaxrxt = 5; - - /*Set Heartbeats*/ - if(setsockopt(tls_listen_fd, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS , &heartbeat, sizeof(heartbeat)) != 0) - perror("setsockopt"); - } - - { - struct sctp_rtoinfo rtoinfo; - ns_bzero(&rtoinfo, sizeof(struct sctp_rtoinfo)); - - rtoinfo.srto_max = 5000; - - /*Set rto_max*/ - if(setsockopt(tls_listen_fd, IPPROTO_SCTP, SCTP_RTOINFO , &rtoinfo, sizeof(rtoinfo)) != 0) - perror("setsockopt"); - } - server->sctp_l = evconnlistener_new(server->e->event_base, sctp_server_input_handler, server, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, From 79d68a27cb36f1b85e6ca4aa2484d3fe57be3065 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Mon, 16 Mar 2015 07:12:32 +0000 Subject: [PATCH 510/805] working on sctp --- src/apps/relay/ns_ioalib_engine_impl.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 44361c0c..0ef9de52 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -871,17 +871,18 @@ int set_socket_options_fd(evutil_socket_t fd, int tcp, int family) } else { int flag = 1; - setsockopt(fd, /* socket affected */ + if(setsockopt(fd, /* socket affected */ IPPROTO_TCP, /* set option at TCP level */ TCP_NODELAY, /* name of option */ (char*)&flag, /* value */ - sizeof(int)); /* length of option value */ + sizeof(int))<0) { /* length of option value */ - setsockopt(fd, /* socket affected */ - IPPROTO_SCTP, /* set option at TCP level */ - SCTP_NODELAY, /* name of option */ - (char*)&flag, /* value */ - sizeof(int)); /* length of option value */ + setsockopt(fd, /* socket affected */ + IPPROTO_SCTP, /* set option at TCP level */ + SCTP_NODELAY, /* name of option */ + (char*)&flag, /* value */ + sizeof(int)); /* length of option value */ + } socket_tcp_set_keepalive(fd); } From 8f821880fc73f930dba2a5fc0f02d6bb4f3f1280 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 17 Mar 2015 05:59:21 +0000 Subject: [PATCH 511/805] c++ fixes --- src/apps/stunclient/stunclient.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/stunclient/stunclient.c b/src/apps/stunclient/stunclient.c index eb1029c7..5f6e0054 100644 --- a/src/apps/stunclient/stunclient.c +++ b/src/apps/stunclient/stunclient.c @@ -67,7 +67,7 @@ static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, i err(-1, NULL); if (!addr_any(&real_local_addr)) { - if (addr_bind(udp_fd, &real_local_addr,0) < 0) + if (addr_bind(udp_fd, &real_local_addr,0,1) < 0) err(-1, NULL); } } @@ -80,7 +80,7 @@ static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, i addr_set_port(&real_local_addr, response_port); - if (addr_bind(new_udp_fd, &real_local_addr, 0) < 0) + if (addr_bind(new_udp_fd, &real_local_addr, 0, 1) < 0) err(-1, NULL); } From 6c247bbbaefa91e67a758be374b348dbfb3dcb1f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 17 Mar 2015 06:27:02 +0000 Subject: [PATCH 512/805] 'no sctp' implemented --- configure | 16 ++++++- src/apps/relay/ns_ioalib_engine_impl.c | 61 +++++++++++++++++++++----- src/apps/relay/tls_listener.c | 12 ++++- src/apps/relay/turn_admin_server.c | 31 ++----------- src/server/ns_turn_ioalib.h | 1 + 5 files changed, 81 insertions(+), 40 deletions(-) diff --git a/configure b/configure index 61a25a5c..43a9928f 100755 --- a/configure +++ b/configure @@ -1157,11 +1157,25 @@ if [ -z "${LDCONFIG}" ] ; then fi fi +############################### +# SCTP +############################### + +if [ -z "${TURN_NO_SCTP}" ] ; then + if ! [ -f "/usr/include/linux/sctp.h" ] ; then + if ! [ -f "/usr/include/netinet/sctp.h" ] ; then + TURN_NO_SCTP="-DTURN_NO_SCTP" + fi + fi +else + TURN_NO_SCTP="-DTURN_NO_SCTP" +fi + ############################### # So, what we have now: ############################### -OSCFLAGS="${OSCFLAGS} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX} -DTURNDB=${TURNDBDIR}/turndb" +OSCFLAGS="${OSCFLAGS} ${TURN_NO_SCTP} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX} -DTURNDB=${TURNDBDIR}/turndb" if ! [ -z "${TURN_ACCEPT_RPATH}" ] ; then if [ -z "${TURN_DISABLE_RPATH}" ] ; then diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 0ef9de52..0ab4b4c0 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -50,12 +50,13 @@ #include "hiredis_libevent2.h" #endif +#if !defined(TURN_NO_SCTP) #if defined(__linux__) || defined(__LINUX__) || defined(__linux) || defined(linux__) || defined(LINUX) || defined(__LINUX) || defined(LINUX__) #include #else #include #endif - +#endif /* Compilation test: #if defined(IP_RECVTTL) @@ -877,11 +878,14 @@ int set_socket_options_fd(evutil_socket_t fd, int tcp, int family) (char*)&flag, /* value */ sizeof(int))<0) { /* length of option value */ +#if defined(SCTP_NODELAY) setsockopt(fd, /* socket affected */ IPPROTO_SCTP, /* set option at TCP level */ SCTP_NODELAY, /* name of option */ (char*)&flag, /* value */ sizeof(int)); /* length of option value */ +#endif + } socket_tcp_set_keepalive(fd); @@ -921,6 +925,31 @@ int is_stream_socket(int st) { return 0; } +const char* socket_type_name(SOCKET_TYPE st) +{ + switch(st) { + case TCP_SOCKET: + return "TCP"; + case SCTP_SOCKET: + return "SCTP"; + case UDP_SOCKET: + return "UDP"; + case TLS_SOCKET: + return "TLS/TCP"; + case TLS_SCTP_SOCKET: + return "TLS/SCTP"; + case DTLS_SOCKET: + return "DTLS"; + case TENTATIVE_TCP_SOCKET: + return "TLS/TCP ?"; + case TENTATIVE_SCTP_SOCKET: + return "TLS/SCTP ?"; + default: + ; + }; + return "UNKNOWN"; +} + /* <<== Socket options helpers */ ioa_socket_handle create_unbound_relay_ioa_socket(ioa_engine_handle e, int family, SOCKET_TYPE st, SOCKET_APP_TYPE sat) @@ -2811,24 +2840,36 @@ static void eventcb_bev(struct bufferevent *bev, short events, void *arg) addr_to_string(&(s->remote_addr),(u08bits*)sraddr); if (events & BEV_EVENT_EOF) { if(server->verbose) - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: stream (TCP or SCTP) socket closed remotely %s\n",(unsigned long long)(ss->id),sraddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: %s socket closed remotely %s\n", + (unsigned long long)(ss->id),socket_type_name(s->st),sraddr); if(s == ss->client_socket) { - shutdown_client_connection(server, ss, 0, "Stream (TCP or SCTP) connection closed by client (callback)"); + char msg[256]; + snprintf(msg,sizeof(msg)-1,"%s connection closed by client (callback)",socket_type_name(s->st)); + shutdown_client_connection(server, ss, 0, msg); } else if(s == ss->alloc.relay_sessions[ALLOC_IPV4_INDEX].s) { - shutdown_client_connection(server, ss, 0, "Stream (TCP or SCTP) connection closed by peer (ipv4 callback)"); + char msg[256]; + snprintf(msg,sizeof(msg)-1,"%s connection closed by peer (ipv4 callback)",socket_type_name(s->st)); + shutdown_client_connection(server, ss, 0, msg); } else if(s == ss->alloc.relay_sessions[ALLOC_IPV6_INDEX].s) { - shutdown_client_connection(server, ss, 0, "Stream (TCP or SCTP) connection closed by peer (ipv6 callback)"); + char msg[256]; + snprintf(msg,sizeof(msg)-1,"%s connection closed by peer (ipv6 callback)",socket_type_name(s->st)); + shutdown_client_connection(server, ss, 0, msg); } else { - shutdown_client_connection(server, ss, 0, "Stream (TCP or SCTP) connection closed by remote party (callback)"); + char msg[256]; + snprintf(msg,sizeof(msg)-1,"%s connection closed by remote party (callback)",socket_type_name(s->st)); + shutdown_client_connection(server, ss, 0, msg); } } else if (events & BEV_EVENT_ERROR) { if(EVUTIL_SOCKET_ERROR()) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"session %018llu: TCP (or SCTP) socket error: %s %s\n",(unsigned long long)(ss->id), - evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()), sraddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"session %018llu: %s socket error: %s %s\n",(unsigned long long)(ss->id), + socket_type_name(s->st),evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()), sraddr); } else if(server->verbose) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: stream (TCP or SCTP) socket disconnected: %s\n",(unsigned long long)(ss->id),sraddr); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: %s socket disconnected: %s\n", + (unsigned long long)(ss->id),socket_type_name(s->st),sraddr); } - shutdown_client_connection(server, ss, 0, "Stream (TCP or SCTP) socket buffer operation error (callback)"); + char msg[256]; + snprintf(msg,sizeof(msg)-1,"%s socket buffer operation error (callback)",socket_type_name(s->st)); + shutdown_client_connection(server, ss, 0, msg); } } } diff --git a/src/apps/relay/tls_listener.c b/src/apps/relay/tls_listener.c index accdfa26..291556e1 100644 --- a/src/apps/relay/tls_listener.c +++ b/src/apps/relay/tls_listener.c @@ -121,6 +121,8 @@ static void server_input_handler(struct evconnlistener *l, evutil_socket_t fd, FUNCEND ; } +#if !defined(TURN_NO_SCTP) + static void sctp_server_input_handler(struct evconnlistener *l, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *arg) { @@ -184,6 +186,8 @@ static void sctp_server_input_handler(struct evconnlistener *l, evutil_socket_t FUNCEND ; } +#endif + ///////////////////// operations ////////////////////////// static int create_server_listener(tls_listener_relay_server_type* server) { @@ -251,6 +255,8 @@ static int create_server_listener(tls_listener_relay_server_type* server) { return 0; } +#if !defined(TURN_NO_SCTP) + static int sctp_create_server_listener(tls_listener_relay_server_type* server) { FUNCSTART; @@ -299,6 +305,8 @@ static int sctp_create_server_listener(tls_listener_relay_server_type* server) { return 0; } +#endif + static int init_server(tls_listener_relay_server_type* server, const char* ifname, const char *local_address, @@ -323,8 +331,10 @@ static int init_server(tls_listener_relay_server_type* server, server->verbose=verbose; server->e = e; - + +#if !defined(TURN_NO_SCTP) sctp_create_server_listener(server); +#endif return create_server_listener(server); } diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index f86f26c1..47264bd1 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -414,31 +414,6 @@ struct ps_arg { size_t users_number; }; -static const char* pname(SOCKET_TYPE st) -{ - switch(st) { - case TCP_SOCKET: - return "TCP"; - case SCTP_SOCKET: - return "SCTP"; - case UDP_SOCKET: - return "UDP"; - case TLS_SOCKET: - return "TLS/TCP"; - case TLS_SCTP_SOCKET: - return "TLS/SCTP"; - case DTLS_SOCKET: - return "DTLS"; - case TENTATIVE_TCP_SOCKET: - return "TLS/TCP ?"; - case TENTATIVE_SCTP_SOCKET: - return "TLS/SCTP ?"; - default: - ; - }; - return "UNKNOWN"; -} - static int print_session(ur_map_key_type key, ur_map_value_type value, void *arg) { if(key && value && arg) { @@ -518,7 +493,7 @@ static int print_session(ur_map_key_type key, ur_map_value_type value, void *arg } else { myprintf(cs," expiring in %lu secs\n",(unsigned long)(tsi->expiration_time - csarg->ct)); } - myprintf(cs," client protocol %s, relay protocol %s\n",pname(tsi->client_protocol),pname(tsi->peer_protocol)); + myprintf(cs," client protocol %s, relay protocol %s\n",socket_type_name(tsi->client_protocol),socket_type_name(tsi->peer_protocol)); { if(!tsi->local_addr_data.saddr[0]) addr_to_string(&(tsi->local_addr_data.addr),(u08bits*)tsi->local_addr_data.saddr); @@ -2247,9 +2222,9 @@ static int https_print_session(ur_map_key_type key, ur_map_value_type value, voi str_buffer_append_sz(sb,(size_t)(tsi->expiration_time - csarg->ct)); } str_buffer_append(sb,""); - str_buffer_append(sb,pname(tsi->client_protocol)); + str_buffer_append(sb,socket_type_name(tsi->client_protocol)); str_buffer_append(sb,""); - str_buffer_append(sb,pname(tsi->peer_protocol)); + str_buffer_append(sb,socket_type_name(tsi->peer_protocol)); str_buffer_append(sb,""); { if(!tsi->local_addr_data.saddr[0]) diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 75fc3ae5..51e44a58 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -231,6 +231,7 @@ int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_ int get_ioa_socket_address_family(ioa_socket_handle s); int is_stream_socket(int st); + const char* socket_type_name(SOCKET_TYPE st); const char* get_ioa_socket_cipher(ioa_socket_handle s); const char* get_ioa_socket_ssl_method(ioa_socket_handle s); SOCKET_TYPE get_ioa_socket_type(ioa_socket_handle s); From eee9dae3216ff7a594ed98d4c7dde90db97531bd Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 17 Mar 2015 06:44:37 +0000 Subject: [PATCH 513/805] sctp compilation --- configure | 13 ++++++++----- src/apps/relay/ns_ioalib_engine_impl.c | 10 ++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/configure b/configure index 43a9928f..31ad69e7 100755 --- a/configure +++ b/configure @@ -1162,10 +1162,13 @@ fi ############################### if [ -z "${TURN_NO_SCTP}" ] ; then - if ! [ -f "/usr/include/linux/sctp.h" ] ; then - if ! [ -f "/usr/include/netinet/sctp.h" ] ; then - TURN_NO_SCTP="-DTURN_NO_SCTP" - fi + if [ -z "${TURN_SCTP_INCLUDE}" ] ; then + TURN_SCTP_INCLUDE=`find /usr/include/ -name sctp.h` + if [ -z "${TURN_SCTP_INCLUDE}" ] ; then + TURN_NO_SCTP="-DTURN_NO_SCTP" + else + TURN_SCTP_INCLUDE="-DTURN_SCTP_INCLUDE=${TURN_SCTP_INCLUDE}" + fi fi else TURN_NO_SCTP="-DTURN_NO_SCTP" @@ -1175,7 +1178,7 @@ fi # So, what we have now: ############################### -OSCFLAGS="${OSCFLAGS} ${TURN_NO_SCTP} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX} -DTURNDB=${TURNDBDIR}/turndb" +OSCFLAGS="${OSCFLAGS} ${TURN_NO_SCTP} ${TURN_SCTP_INCLUDE} ${TURN_NO_THREAD_BARRIERS} ${TURN_NO_DTLS} ${TURN_NO_GCM} ${TURN_NO_TLS} -DINSTALL_PREFIX=${PREFIX} -DTURNDB=${TURNDBDIR}/turndb" if ! [ -z "${TURN_ACCEPT_RPATH}" ] ; then if [ -z "${TURN_DISABLE_RPATH}" ] ; then diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 0ab4b4c0..94f28fd0 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -50,12 +50,10 @@ #include "hiredis_libevent2.h" #endif -#if !defined(TURN_NO_SCTP) -#if defined(__linux__) || defined(__LINUX__) || defined(__linux) || defined(linux__) || defined(LINUX) || defined(__LINUX) || defined(LINUX__) -#include -#else -#include -#endif +#if !defined(TURN_NO_SCTP) && defined(TURN_SCTP_INCLUDE) +#define Q(x) #x +#define QUOTE(x) Q(x) +#include QUOTE(TURN_SCTP_INCLUDE) #endif /* Compilation test: From b3ed8d8165c4005de8ad5ade0db57f764c5c18a2 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 17 Mar 2015 06:57:10 +0000 Subject: [PATCH 514/805] sctp compilation --- configure | 2 +- src/apps/relay/ns_ioalib_engine_impl.c | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 31ad69e7..fa898ca7 100755 --- a/configure +++ b/configure @@ -1167,7 +1167,7 @@ if [ -z "${TURN_NO_SCTP}" ] ; then if [ -z "${TURN_SCTP_INCLUDE}" ] ; then TURN_NO_SCTP="-DTURN_NO_SCTP" else - TURN_SCTP_INCLUDE="-DTURN_SCTP_INCLUDE=${TURN_SCTP_INCLUDE}" + TURN_SCTP_INCLUDE="-DTURN_SCTP_INCLUDE=\"\\\"${TURN_SCTP_INCLUDE}\\\"\"" fi fi else diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 94f28fd0..7622d975 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -51,9 +51,7 @@ #endif #if !defined(TURN_NO_SCTP) && defined(TURN_SCTP_INCLUDE) -#define Q(x) #x -#define QUOTE(x) Q(x) -#include QUOTE(TURN_SCTP_INCLUDE) +#include TURN_SCTP_INCLUDE #endif /* Compilation test: From 5857afb9dc6f6a3bd78ab740cc090a8a42a87462 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 18 Mar 2015 04:39:21 +0000 Subject: [PATCH 515/805] working on sctp --- configure | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/configure b/configure index fa898ca7..c62643a6 100755 --- a/configure +++ b/configure @@ -1162,13 +1162,23 @@ fi ############################### if [ -z "${TURN_NO_SCTP}" ] ; then + if [ -z "${TURN_SCTP_INCLUDE}" ] ; then + if ! [ "${PREFIX}" = "/usr" ] ; then + if ! [ "${PREFIX}" = "/usr/local" ] ; then + TURN_SCTP_INCLUDE=`find ${PREFIX}/include/ -name sctp.h` + fi + fi + fi + if [ -z "${TURN_SCTP_INCLUDE}" ] ; then + TURN_SCTP_INCLUDE=`find /usr/local/include/ -name sctp.h` + fi if [ -z "${TURN_SCTP_INCLUDE}" ] ; then TURN_SCTP_INCLUDE=`find /usr/include/ -name sctp.h` - if [ -z "${TURN_SCTP_INCLUDE}" ] ; then - TURN_NO_SCTP="-DTURN_NO_SCTP" - else - TURN_SCTP_INCLUDE="-DTURN_SCTP_INCLUDE=\"\\\"${TURN_SCTP_INCLUDE}\\\"\"" - fi + fi + if [ -z "${TURN_SCTP_INCLUDE}" ] ; then + TURN_NO_SCTP="-DTURN_NO_SCTP" + else + TURN_SCTP_INCLUDE="-DTURN_SCTP_INCLUDE=\"\\\"${TURN_SCTP_INCLUDE}\\\"\"" fi else TURN_NO_SCTP="-DTURN_NO_SCTP" From 9b754d91f6bf13f6e4744a938b831b4326b29852 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 18 Mar 2015 04:58:34 +0000 Subject: [PATCH 516/805] working on sctp --- configure | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/configure b/configure index c62643a6..1c5aea4b 100755 --- a/configure +++ b/configure @@ -1178,7 +1178,10 @@ if [ -z "${TURN_NO_SCTP}" ] ; then if [ -z "${TURN_SCTP_INCLUDE}" ] ; then TURN_NO_SCTP="-DTURN_NO_SCTP" else - TURN_SCTP_INCLUDE="-DTURN_SCTP_INCLUDE=\"\\\"${TURN_SCTP_INCLUDE}\\\"\"" + for ip in ${TURN_SCTP_INCLUDE} ; do + TURN_SCTP_INCLUDE="-DTURN_SCTP_INCLUDE=\"\\\"${ip}\\\"\"" + break + done fi else TURN_NO_SCTP="-DTURN_NO_SCTP" From c0f2ca8ceaa78e2dd53157859f513c7764c247de Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 18 Mar 2015 05:12:05 +0000 Subject: [PATCH 517/805] working on sctp --- examples/scripts/longtermsecure/secure_sctp_client.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/scripts/longtermsecure/secure_sctp_client.sh b/examples/scripts/longtermsecure/secure_sctp_client.sh index cff79e19..e6ca3ce0 100755 --- a/examples/scripts/longtermsecure/secure_sctp_client.sh +++ b/examples/scripts/longtermsecure/secure_sctp_client.sh @@ -30,5 +30,5 @@ fi export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/ -PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -t -S -k turn_client_pkey.pem -n 1000 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -b -S -k turn_client_pkey.pem -n 1000 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 From 7a9c2fa50aeb7e67474a63f5bc98ecea342d1e20 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 18 Mar 2015 05:52:30 +0000 Subject: [PATCH 518/805] working on sctp --- configure | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/configure b/configure index 1c5aea4b..eb099eab 100755 --- a/configure +++ b/configure @@ -293,6 +293,10 @@ if [ -z "${ECHO_CMD}" ] ; then ECHO_CMD=echo fi +if [ -z "${FIND_CMD}" ] ; then + FIND_CMD=find +fi + if [ -z "${PORTNAME}" ] ; then PORTNAME=turnserver fi @@ -622,6 +626,7 @@ if [ "${SYSTEM}" = "SunOS" ] ; then # Solaris ? is this you ?! OSCFLAGS="${OSCFLAGS} -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 -DTURN_NO_GETDOMAINNAME" OSLIBS="${OSLIBS} -lnsl" + TURN_NO_SCTP=1 fi ######################### @@ -1162,26 +1167,34 @@ fi ############################### if [ -z "${TURN_NO_SCTP}" ] ; then - if [ -z "${TURN_SCTP_INCLUDE}" ] ; then - if ! [ "${PREFIX}" = "/usr" ] ; then - if ! [ "${PREFIX}" = "/usr/local" ] ; then - TURN_SCTP_INCLUDE=`find ${PREFIX}/include/ -name sctp.h` - fi - fi - fi - if [ -z "${TURN_SCTP_INCLUDE}" ] ; then - TURN_SCTP_INCLUDE=`find /usr/local/include/ -name sctp.h` - fi - if [ -z "${TURN_SCTP_INCLUDE}" ] ; then - TURN_SCTP_INCLUDE=`find /usr/include/ -name sctp.h` - fi if [ -z "${TURN_SCTP_INCLUDE}" ] ; then - TURN_NO_SCTP="-DTURN_NO_SCTP" + if [ -f /usr/include/linux/sctp.h ] ; then + TURN_SCTP_INCLUDE="-DTURN_SCTP_INCLUDE=\"\\\"/usr/include/linux/sctp.h\\\"\"" + elif [ -f /usr/include/netinet/sctp.h ] ; then + TURN_SCTP_INCLUDE="-DTURN_SCTP_INCLUDE=\"\"" else + if ! [ "${PREFIX}" = "/usr" ] ; then + if ! [ "${PREFIX}" = "/usr/local" ] ; then + TURN_SCTP_INCLUDE=`${FIND_CMD} ${PREFIX}/include/ -name sctp.h` + fi + fi + if [ -z "${TURN_SCTP_INCLUDE}" ] ; then + TURN_SCTP_INCLUDE=`${FIND_CMD} /usr/local/include/ -name sctp.h` + fi + if [ -z "${TURN_SCTP_INCLUDE}" ] ; then + TURN_SCTP_INCLUDE=`${FIND_CMD} /usr/include/ -name sctp.h` + fi + if [ -z "${TURN_SCTP_INCLUDE}" ] ; then + TURN_NO_SCTP="-DTURN_NO_SCTP" + else for ip in ${TURN_SCTP_INCLUDE} ; do - TURN_SCTP_INCLUDE="-DTURN_SCTP_INCLUDE=\"\\\"${ip}\\\"\"" - break + TURN_SCTP_INCLUDE="-DTURN_SCTP_INCLUDE=\"\\\"${ip}\\\"\"" + break done + fi + fi + else + TURN_SCTP_INCLUDE="-DTURN_SCTP_INCLUDE=\"\\\"${TURN_SCTP_INCLUDE}\\\"\"" fi else TURN_NO_SCTP="-DTURN_NO_SCTP" From c5a847b680919e8f06da1dcd0ccd3e1120ff43a2 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 18 Mar 2015 06:06:48 +0000 Subject: [PATCH 519/805] working on sctp --- src/ns_turn_defs.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 82106157..a4b686c3 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -225,7 +225,12 @@ typedef u32bits turn_time_t; #define CLIENT_STREAM_SOCKET_PROTOCOL IPPROTO_IP #define SCTP_CLIENT_STREAM_SOCKET_TYPE SOCK_STREAM + +#if !defined(TURN_NO_SCTP) #define SCTP_CLIENT_STREAM_SOCKET_PROTOCOL IPPROTO_SCTP +#else +#define SCTP_CLIENT_STREAM_SOCKET_PROTOCOL IPPROTO_IP +#endif #define RELAY_DGRAM_SOCKET_TYPE SOCK_DGRAM #define RELAY_DGRAM_SOCKET_PROTOCOL IPPROTO_IP From 6fccc65fc7627ef937d10548a7b18f4bb27443ad Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 18 Mar 2015 06:20:21 +0000 Subject: [PATCH 520/805] working on sctp --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index eb099eab..963f6606 100755 --- a/configure +++ b/configure @@ -175,6 +175,7 @@ pthread_testlib() { if [ "${SYSTEM}" = "DragonFly" ] ; then OSLIBS="${OSLIBS} -pthread" + TURN_NO_SCTP=1 fi ISBSD=`uname | grep -i bsd` From 1a21b485c10c20128d1caf7ae51555aafb89c3f9 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 18 Mar 2015 06:41:18 +0000 Subject: [PATCH 521/805] working on sctp --- src/apps/relay/tls_listener.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/apps/relay/tls_listener.c b/src/apps/relay/tls_listener.c index 291556e1..b8a101f7 100644 --- a/src/apps/relay/tls_listener.c +++ b/src/apps/relay/tls_listener.c @@ -267,8 +267,8 @@ static int sctp_create_server_listener(tls_listener_relay_server_type* server) { tls_listen_fd = socket(server->addr.ss.sa_family, SCTP_CLIENT_STREAM_SOCKET_TYPE, SCTP_CLIENT_STREAM_SOCKET_PROTOCOL); if (tls_listen_fd < 0) { - perror("socket"); - return -1; + perror("socket"); + return -1; } if(sock_bind_to_device(tls_listen_fd, (unsigned char*)server->ifname)<0) { @@ -290,7 +290,6 @@ static int sctp_create_server_listener(tls_listener_relay_server_type* server) { 1024, tls_listen_fd); if(!(server->sctp_l)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot create SCTP listener\n"); socket_closesocket(tls_listen_fd); return -1; } From fb8324fa517af29c284c79f01af085ead97b767d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 20 Mar 2015 07:00:21 +0000 Subject: [PATCH 522/805] working on encrypted passwords --- src/apps/relay/turn_admin_server.c | 2 +- src/client/ns_turn_msg.c | 92 +++++++++++++++++++++++++++++- src/client/ns_turn_msg.h | 4 ++ 3 files changed, 95 insertions(+), 3 deletions(-) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 47264bd1..70ea9573 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -3322,7 +3322,7 @@ static void handle_logon_request(ioa_socket_handle s, struct http_request* hr) password_t password; char realm[STUN_MAX_REALM_SIZE+1]="\0"; if((*(dbd->get_admin_user))((const u08bits*)uname,(u08bits*)realm,password)>=0) { - if(!strcmp(pwd,(char*)password)) { + if(!check_password(pwd,(char*)password)) { STRCPY(as->as_login,uname); STRCPY(as->as_realm,realm); as->as_eff_realm[0]=0; diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index d018d988..635ca91e 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -45,6 +45,10 @@ /////////// +static void generate_random_nonce(unsigned char *nonce, size_t sz); + +/////////// + int stun_method_str(u16bits method, char *smethod) { int ret = 0; @@ -219,6 +223,90 @@ int stun_produce_integrity_key_str(u08bits *uname, u08bits *realm, u08bits *upwd return 0; } +#define PWD_SALT_SIZE (8) + +static void readable_string(unsigned char *orig, unsigned char *out, size_t sz) +{ + size_t i = 0; + out[0]=0; + + for(i = 0; i < sz; ++i) { + sprintf((char*)(out + (i * 2)), "%02x", (unsigned int)orig[i]); + } +} + +static void generate_enc_password(const char* pwd, char *result, const unsigned char *orig_salt) +{ + unsigned char salt[PWD_SALT_SIZE+1]; + if(!orig_salt) { + generate_random_nonce(salt, PWD_SALT_SIZE); + } else { + ns_bcopy(orig_salt,salt,PWD_SALT_SIZE); + salt[PWD_SALT_SIZE]=0; + } + unsigned char rsalt[PWD_SALT_SIZE*2+1]; + readable_string(salt,rsalt,PWD_SALT_SIZE); + result[0]='$'; + result[1]='5'; + result[2]='$'; + ns_bcopy((char*)rsalt,result+3,PWD_SALT_SIZE+PWD_SALT_SIZE); + result[3+PWD_SALT_SIZE+PWD_SALT_SIZE]='$'; + unsigned char* out = (unsigned char*)(result+3+PWD_SALT_SIZE+PWD_SALT_SIZE+1); + { + EVP_MD_CTX ctx; +#if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH) + EVP_DigestInit(&ctx,EVP_sha256()); +#else + EVP_DigestInit(&ctx,EVP_sha1()); +#endif + EVP_DigestUpdate(&ctx,salt,PWD_SALT_SIZE); + EVP_DigestUpdate(&ctx,pwd,strlen(pwd)); + { + unsigned char hash[129]; + unsigned int keylen = 0; + EVP_DigestFinal(&ctx,hash,&keylen); + readable_string(hash,out,keylen); + } + EVP_MD_CTX_cleanup(&ctx); + } +} + +void generate_new_enc_password(const char* pwd, char *result) +{ + generate_enc_password(pwd, result, NULL); +} + +static int encrypted_password(const char* pin, unsigned char* salt) +{ + size_t min_len = 3+PWD_SALT_SIZE+PWD_SALT_SIZE+1+32; + if(strlen(pin)>=min_len) { + if((pin[0]=='$') && (pin[1]=='5') && (pin[2]=='$') && (pin[3+PWD_SALT_SIZE+PWD_SALT_SIZE]=='$')) { + size_t i = 0; + for(i=0;ienc_block.key_length<128)) { diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index a2faf3fa..0f96cb07 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -213,6 +213,10 @@ int convert_oauth_key_data(const oauth_key_data *oakd, oauth_key *key, char *err int decode_oauth_token(const u08bits *server_name, const encoded_oauth_token *etoken, const oauth_key *key, oauth_token *dtoken); int encode_oauth_token(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken, const u08bits *nonce); +/* Encrypted password */ +void generate_new_enc_password(const char* pwd, char *result); +int check_password(const char* pin, const char* pwd); + /////////////////////////////////////////////////////////////// #ifdef __cplusplus From 3ec05410c5417a06df291ac80ffa28ce53d5fac4 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 21 Mar 2015 06:19:12 +0000 Subject: [PATCH 523/805] turnadmin command to produce an encrypted password --- ChangeLog | 3 +++ README.turnadmin | 19 +++++++++++++++++-- man/man1/turnadmin.1 | 19 ++++++++++++++++++- man/man1/turnserver.1 | 2 +- man/man1/turnutils.1 | 2 +- src/apps/relay/mainrelay.c | 35 +++++++++++++++++++++++++++++------ 6 files changed, 69 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 60e2bcc5..e6b4821b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,9 @@ 3/15/2015 Oleg Moskalenko Version 4.4.4.1 'Ardee West': - 'native' SCTP support; + - option of encrypted passwords for web admin users; + - option of encrypted password for CLI user; + - option of encrypted shared secrets; 2/28/2015 Oleg Moskalenko Version 4.4.2.3 'Ardee West': diff --git a/README.turnadmin b/README.turnadmin index 53166f6c..e6dc1b8e 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -47,6 +47,15 @@ $ turnadmin [ -h | --help] Commands: +-P, --generate-encrypted-password Generate and print to the standard +output an encrypted form of a password (for web admin user, or shared +secret, or CLI). The value then can be used as a safe key for the password +storage on disk or in the database. Every invocation for the same password +produces a different result. The for mat of the encrypted password is: +$5$<...salt...>$<...sha256(salt+password)...>. Salt is 16 characters, +the sha256 output is 64 characters. Character 5 is the algorithm id (sha256). +Only sha256 is supported as the hash function. + -k, --key Generate key for a long-term credentials mechanism user. -a, --add Add or update a long-term user. @@ -104,8 +113,14 @@ Options with required values: --total-quota Set value of realm's total-quota parameter. --user-quota Set value of realm's user-quota parameter. -h, --help Help. - -Generate a key: + +Command examples: + +Generate an encrypted form of a password: + +$ turnadmin -P -p + +Generate a key: $ turnadmin -k -u -r -p diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 463a0b4e..08cd7733 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "15 March 2015" "" "" +.TH TURN 1 "20 March 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage @@ -66,6 +66,17 @@ $ \fIturnadmin\fP [ \fB\-h\fP | \fB\-\-help\fP] Commands: .TP .B +\fB\-P\fP, \fB\-\-generate\-encrypted\-password\fP +Generate and print to the standard +output an encrypted form of a password (for web admin user, or shared +secret, or CLI). The value then can be used as a safe key for the password +storage on disk or in the database. Every invocation for the same password +produces a different result. The for mat of the encrypted password is: +$5$<\.\.\.salt\.\.\.>$<\.\.\.sha256(salt+password)\.\.\.>. Salt is 16 characters, +the sha256 output is 64 characters. Character 5 is the algorithm id (sha256). +Only sha256 is supported as the hash function. +.TP +.B \fB\-k\fP, \fB\-\-key\fP Generate key for a long\-term credentials mechanism user. .TP @@ -203,6 +214,12 @@ Set value of realm's user\-quota parameter. Help. .TP .B +Command examples: +.PP +Generate an encrypted form of a password: +.PP +$ \fIturnadmin\fP \fB\-P\fP \fB\-p\fP +.PP Generate a key: .PP $ \fIturnadmin\fP \fB\-k\fP \fB\-u\fP \fB\-r\fP \fB\-p\fP diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 158ac135..83c9a443 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "15 March 2015" "" "" +.TH TURN 1 "20 March 2015" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index aaf9ea34..f474c0bd 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "15 March 2015" "" "" +.TH TURN 1 "20 March 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 2899e90e..9fc4d4ee 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -599,6 +599,11 @@ static char Usage[] = "Usage: turnserver [options]\n" static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" "\nCommands:\n\n" + " -P, --generate-encrypted-password Generate and print to the standard\n" + " output an encrypted form of a password\n" + " (for web admin user, or shared\n" + " secret, or CLI). See wiki, README or man\n" + " pages for more detailed description.\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-admin add/update a web admin user\n" @@ -652,7 +657,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" #define OPTIONS "c:d:p:L:E:X:i:m:l:r:u:b:B:e:M:J:N:O:q:Q:s:C:vVofhznaAS" -#define ADMIN_OPTIONS "gGORIHKYlLkaADSdb:e:M:J:N:u:r:p:s:X:o:h" +#define ADMIN_OPTIONS "PgGORIHKYlLkaADSdb:e:M:J:N:u:r:p:s:X:o:h" enum EXTRA_OPTS { NO_UDP_OPT=256, @@ -841,6 +846,7 @@ static const struct myoption long_options[] = { }; static const struct myoption admin_long_options[] = { + {"generate-encrypted-password", no_argument, NULL, 'P' }, { "key", no_argument, NULL, 'k' }, { "add", no_argument, NULL, 'a' }, { "delete", no_argument, NULL, 'd' }, @@ -1437,18 +1443,29 @@ static int adminmain(int argc, char **argv) int is_admin = 0; - u08bits user[STUN_MAX_USERNAME_SIZE+1]=""; - u08bits realm[STUN_MAX_REALM_SIZE+1]=""; - u08bits pwd[STUN_MAX_PWD_SIZE+1]=""; - u08bits secret[AUTH_SECRET_SIZE+1]=""; - u08bits origin[STUN_MAX_ORIGIN_SIZE+1]=""; + u08bits user[STUN_MAX_USERNAME_SIZE+1]="\0"; + u08bits realm[STUN_MAX_REALM_SIZE+1]="\0"; + u08bits pwd[STUN_MAX_PWD_SIZE+1]="\0"; + u08bits secret[AUTH_SECRET_SIZE+1]="\0"; + u08bits origin[STUN_MAX_ORIGIN_SIZE+1]="\0"; perf_options_t po = {(band_limit_t)-1,-1,-1}; struct uoptions uo; uo.u.m = admin_long_options; + int print_enc_password = 0; + while (((c = getopt_long(argc, argv, ADMIN_OPTIONS, uo.u.o, NULL)) != -1)) { switch (c){ + case 'P': + if(pwd[0]) { + char result[257]; + generate_new_enc_password((char*)pwd, result); + printf("%s\n",result); + exit(0); + } + print_enc_password = 1; + break; case 'g': ct = TA_SET_REALM_OPTION; break; @@ -1566,6 +1583,12 @@ static int adminmain(int argc, char **argv) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong password: %s\n",pwd); exit(-1); } + if(print_enc_password) { + char result[257]; + generate_new_enc_password((char*)pwd, result); + printf("%s\n",result); + exit(0); + } break; case 'H': if(get_bool_value(optarg)) From e40236419e57217d5f916d27791df5938c7aab2f Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 21 Mar 2015 06:28:47 +0000 Subject: [PATCH 524/805] encrypted CLI password --- src/apps/relay/turn_admin_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 70ea9573..3eebabf2 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -959,7 +959,7 @@ static int run_cli_input(struct cli_session* cs, const char *buf0, unsigned int if(sl) { cs->cmds += 1; if(cli_password[0] && !(cs->auth_completed)) { - if(strcmp(cmd,cli_password)) { + if(check_password(cmd,cli_password)) { if(cs->cmds>=CLI_PASSWORD_TRY_NUMBER) { addr_debug_print(1, &(cs->addr),"CLI authentication error"); TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"CLI authentication error\n"); From a2cf8155a63b50e00ef06bb30f917d5dbf7e70a4 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 21 Mar 2015 06:38:49 +0000 Subject: [PATCH 525/805] docs changed --- README.turnserver | 3 +++ examples/etc/turnserver.conf | 10 +++++++++- man/man1/turnserver.1 | 3 +++ src/apps/relay/mainrelay.c | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/README.turnserver b/README.turnserver index d7e9c274..ebdb9d47 100644 --- a/README.turnserver +++ b/README.turnserver @@ -536,6 +536,9 @@ Options with required values: --cli-port CLI management interface listening port. Default is 5766. --cli-password CLI access password. Default is empty (no password). + For the security reasons, it is recommended to use the encrypted + form of the password (see the -P command in the turnadmin + utility). The dollar signs in the encrypted form must be escaped. --cli-max-output-sessions Maximum number of output sessions in ps CLI command. This value can be changed on-the-fly in CLI. The default value is 256. diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 9ae0f375..2b11db7a 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -599,8 +599,16 @@ #cli-port=5766 # CLI access password. Default is empty (no password). +# For the security reasons, it is recommended to use the encrypted +# for of the password (see the -P command in the turnadmin utility). # -#cli-password=logen +# Secure form for password 'qwerty': +# +#cli-password=$5$79a316b350311570$81df9cfb9af7f5e5a76eada31e7097b663a0670f99a3c07ded3f1c8e59c5658a +# +# Or unsecure form for the same paassword: +# +#cli-password=qwerty # Server relay. NON-STANDARD AND DANGEROUS OPTION. # Only for those applications when we want to run diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 83c9a443..5c42dab8 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -770,6 +770,9 @@ CLI management interface listening port. Default is 5766. .B \fB\-\-cli\-password\fP CLI access password. Default is empty (no password). +For the security reasons, it is recommended to use the encrypted +form of the password (see the \fB\-P\fP command in the \fIturnadmin\fP +utility). The dollar signs in the encrypted form must be escaped. .TP .B \fB\-\-cli\-max\-output\-sessions\fP diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 9fc4d4ee..20bf592e 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -583,6 +583,9 @@ static char Usage[] = "Usage: turnserver [options]\n" " is 127.0.0.1.\n" " --cli-port= CLI server port. Default is 5766.\n" " --cli-password= CLI access password. Default is empty (no password).\n" +" For the security reasons, it is recommended to use the encrypted\n" +" for of the password (see the -P command in the turnadmin utility).\n" +" The dollar signs in the encrypted form must be escaped.\n" " --server-relay Server relay. NON-STANDARD AND DANGEROUS OPTION. Only for those applications\n" " when we want to run server applications on the relay endpoints.\n" " This option eliminates the IP permissions check on the packets\n" From c92e4e748064a4cb9541dd04ac524839cd8a8543 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 21 Mar 2015 07:29:00 +0000 Subject: [PATCH 526/805] encrypted admin user passwords --- INSTALL | 8 ++++++-- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/turn_admin_server.c | 5 +++-- src/apps/relay/userdb.c | 2 +- turndb/testmongosetup.sh | 4 ++-- turndb/testredisdbsetup.sh | 7 +++++-- turndb/testsqldbsetup.sql | 4 ++-- 7 files changed, 19 insertions(+), 11 deletions(-) diff --git a/INSTALL b/INSTALL index 6ec90a12..90c34bcf 100644 --- a/INSTALL +++ b/INSTALL @@ -689,7 +689,9 @@ or up to 96 characters (HEX representation of 48 bytes) for SHA384, or up to 128 characters (HEX representation of 64 bytes) for SHA512: # Table holding shared secrets for secret-based authorization -# (REST API). It can only be used together with the long-term +# (REST API). Shared secret can be stored either in unsecure open +# plain form, or in encrypted form (see turnadmin docs). +# It can only be used together with the long-term # mechanism: # CREATE TABLE turn_secret ( @@ -793,6 +795,8 @@ The oauth_key table fields meanings are: # Https access admin users. # Leave this table empty if you do not want # remote https access to the admin functions. +# Web user password can be stored either in unsecure open +# plain form, or in encrypted form (see turnadmin docs). # CREATE TABLE admin_user ( name varchar(32), @@ -900,7 +904,7 @@ The database schema for the TURN server is very minimalistic and is located in project's turndb/schema.sql file, or in the system's PREFIX/share/turnserver/schema.sql file after the turnserver installation: -$ cat turndb/schema.sql | psql -U turn turn +$ cat turndb/schema.sql | psql -U turn -d turn NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "turnusers_lt_pkey" for table "turnusers_lt" CREATE TABLE CREATE TABLE diff --git a/examples/var/db/turndb b/examples/var/db/turndb index 8802a7f5d6bc0f1fbb11b1baa598cc35253c36a3..a186ae1937dc2022f80133ff5616307cd3fd536c 100644 GIT binary patch delta 291 zcmXw!OG*Pl6h*7L2-u3?ECUln=&@ASdsWqM>;hasAX?w}BY`M_PE7B>fNOA?1b5+F z7m;xmU?Vs^TsZeE)_k$%Z^wMK9Gvsj=IY~O51DuuSbT5VuYzAL+tKT|==BdXae_4Cs);hrjH@;#Ec55O#K8QJ`4aO+=8c;b1(qas_ok) && uname && pwd) { const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->get_admin_user) { - password_t password; char realm[STUN_MAX_REALM_SIZE+1]="\0"; if((*(dbd->get_admin_user))((const u08bits*)uname,(u08bits*)realm,password)>=0) { @@ -3356,7 +3355,9 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) if(turn_params.verbose) { if(nbh) { ((char*)ioa_network_buffer_data(nbh))[ioa_network_buffer_get_size(nbh)] = 0; - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection input: %s\n", __FUNCTION__, (char*)ioa_network_buffer_data(nbh)); + if(!strstr((char*)ioa_network_buffer_data(nbh),"pwd")) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection input: %s\n", __FUNCTION__, (char*)ioa_network_buffer_data(nbh)); + } } else { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: HTTPS connection initial input\n", __FUNCTION__); } diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 07b987ac..e846cb02 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -1011,7 +1011,7 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b must_set_admin_pwd(pwd); if (dbd->set_admin_user) { password_t password; - STRCPY(password,pwd); + generate_new_enc_password((char*)pwd,(char*)password); (*dbd->set_admin_user)(user, realm, password); } } else { diff --git a/turndb/testmongosetup.sh b/turndb/testmongosetup.sh index a266cf90..884b28d9 100755 --- a/turndb/testmongosetup.sh +++ b/turndb/testmongosetup.sh @@ -20,8 +20,8 @@ db.turn_secret.insert({ realm: 'north.gov', value: 'bloody9' }); db.turn_secret.insert({ realm: 'crinna.org', value: 'north' }); db.turn_secret.insert({ realm: 'crinna.org', value: 'library' }); -db.admin_user.insert({ name: 'skarling', realm: 'north.gov', password: 'hoodless' }); -db.admin_user.insert({ name: 'bayaz', realm: '', password: 'magi' }); +db.admin_user.insert({ name: 'skarling', realm: 'north.gov', password: '$5$6fc35c3b0c7d4633$27fca7574f9b79d0cb93ae03e45379470cbbdfcacdd6401f97ebc620f31f54f2' }); +db.admin_user.insert({ name: 'bayaz', realm: '', password: '$5$e018513e9de69e73$5cbdd2e29e04ca46aeb022268a7460d3a3468de193dcb2b95f064901769f455f' }); db.realm.insert({ realm: 'north.gov', diff --git a/turndb/testredisdbsetup.sh b/turndb/testredisdbsetup.sh index 29d6d584..d19da17a 100755 --- a/turndb/testredisdbsetup.sh +++ b/turndb/testredisdbsetup.sh @@ -4,6 +4,9 @@ # gorst:password: hero # whirrun:password: sword # stranger-come-knocking:password: civilization +# +# bayaz admin user password: magi +# skarling admin user password: hoodless redis-cli < Date: Sat, 21 Mar 2015 15:41:00 +0000 Subject: [PATCH 527/805] docs fixed --- ChangeLog | 3 +-- README.turnadmin | 4 ++-- man/man1/turnadmin.1 | 6 +++--- man/man1/turnserver.1 | 2 +- man/man1/turnutils.1 | 2 +- src/apps/relay/mainrelay.c | 3 +-- 6 files changed, 9 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index e6b4821b..8ef5efb1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,8 @@ 3/15/2015 Oleg Moskalenko Version 4.4.4.1 'Ardee West': - - 'native' SCTP support; + - 'native' SCTP support (experimental); - option of encrypted passwords for web admin users; - option of encrypted password for CLI user; - - option of encrypted shared secrets; 2/28/2015 Oleg Moskalenko Version 4.4.2.3 'Ardee West': diff --git a/README.turnadmin b/README.turnadmin index e6dc1b8e..8e303687 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -48,8 +48,8 @@ $ turnadmin [ -h | --help] Commands: -P, --generate-encrypted-password Generate and print to the standard -output an encrypted form of a password (for web admin user, or shared -secret, or CLI). The value then can be used as a safe key for the password +output an encrypted form of a password (for web admin user or CLI). +The value then can be used as a safe key for the password storage on disk or in the database. Every invocation for the same password produces a different result. The for mat of the encrypted password is: $5$<...salt...>$<...sha256(salt+password)...>. Salt is 16 characters, diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 08cd7733..249d9b03 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "20 March 2015" "" "" +.TH TURN 1 "21 March 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage @@ -68,8 +68,8 @@ Commands: .B \fB\-P\fP, \fB\-\-generate\-encrypted\-password\fP Generate and print to the standard -output an encrypted form of a password (for web admin user, or shared -secret, or CLI). The value then can be used as a safe key for the password +output an encrypted form of a password (for web admin user or CLI). +The value then can be used as a safe key for the password storage on disk or in the database. Every invocation for the same password produces a different result. The for mat of the encrypted password is: $5$<\.\.\.salt\.\.\.>$<\.\.\.sha256(salt+password)\.\.\.>. Salt is 16 characters, diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 5c42dab8..7f4d0c0c 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "20 March 2015" "" "" +.TH TURN 1 "21 March 2015" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index f474c0bd..2c3e03d4 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "20 March 2015" "" "" +.TH TURN 1 "21 March 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 20bf592e..48df9acd 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -604,8 +604,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" "\nCommands:\n\n" " -P, --generate-encrypted-password Generate and print to the standard\n" " output an encrypted form of a password\n" - " (for web admin user, or shared\n" - " secret, or CLI). See wiki, README or man\n" + " (for web admin user or CLI). See wiki, README or man\n" " pages for more detailed description.\n" " -k, --key generate long-term credential mechanism key for a user\n" " -a, --add add/update a long-term mechanism user\n" From 601fda4423ca0206540cf56122e616f5c024f6e2 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 21 Mar 2015 20:04:04 +0000 Subject: [PATCH 528/805] changelog --- ChangeLog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8ef5efb1..a77b6258 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,8 @@ 3/15/2015 Oleg Moskalenko Version 4.4.4.1 'Ardee West': - 'native' SCTP support (experimental); - - option of encrypted passwords for web admin users; - - option of encrypted password for CLI user; + - option of encrypted stored passwords for web admin users; + - option of encrypted stored password for CLI user; 2/28/2015 Oleg Moskalenko Version 4.4.2.3 'Ardee West': From f23c9dccf6bff2b19fed505635c517d92f813d1a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 22 Mar 2015 03:20:47 +0000 Subject: [PATCH 529/805] comments added --- turndb/testmongosetup.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/turndb/testmongosetup.sh b/turndb/testmongosetup.sh index 884b28d9..130ad291 100755 --- a/turndb/testmongosetup.sh +++ b/turndb/testmongosetup.sh @@ -1,5 +1,13 @@ #!/bin/sh +# ninefingers:password: youhavetoberealistic +# gorst:password: hero +# whirrun:password: sword +# stranger-come-knocking:password: civilization +# +# bayaz admin user password: magi +# skarling admin user password: hoodless + mongo $* < Date: Sun, 22 Mar 2015 05:44:18 +0000 Subject: [PATCH 530/805] status updated --- STATUS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/STATUS b/STATUS index 499804ae..6afe79d5 100644 --- a/STATUS +++ b/STATUS @@ -121,6 +121,8 @@ supported in the client library). 52) Web HTTPS admin interface implemented. 53) SHA384 and SHA512 support added (experimental). + +54) native SCTP experimental support. Things to be implemented in future (the development roadmap) are described in the TODO file. From 8b3bd1e97dffb956fe2dfd9dd58cedf689188a3e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Wed, 1 Apr 2015 06:55:54 +0000 Subject: [PATCH 531/805] minor sctp fix --- ChangeLog | 4 ++++ rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/apps/relay/tls_listener.c | 2 +- src/ns_turn_defs.h | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index a77b6258..dc71c762 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +3/31/2015 Oleg Moskalenko +Version 4.4.4.2 'Ardee West': + - minor SCTP fix; + 3/15/2015 Oleg Moskalenko Version 4.4.4.1 'Ardee West': - 'native' SCTP support (experimental); diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 2ecdefda..9af5ffe2 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.4.4.1 +TURNVERSION=4.4.4.2 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index e6e630fd..c35875ed 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.4.4.1 +Version: 4.4.4.2 Release: 0%{dist} Summary: Coturn TURN Server @@ -289,6 +289,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Tue Mar 31 2015 Oleg Moskalenko + - Sync to 4.4.4.2 * Sun Mar 15 2015 Oleg Moskalenko - Sync to 4.4.4.1 * Sat Feb 28 2015 Oleg Moskalenko diff --git a/src/apps/relay/tls_listener.c b/src/apps/relay/tls_listener.c index b8a101f7..4f27cdcf 100644 --- a/src/apps/relay/tls_listener.c +++ b/src/apps/relay/tls_listener.c @@ -143,7 +143,7 @@ static void sctp_server_input_handler(struct evconnlistener *l, evutil_socket_t ns_bcopy(sa,&(server->sm.m.sm.nd.src_addr),socklen); - addr_debug_print(server->verbose, &(server->sm.m.sm.nd.src_addr),"tcp or tls connected to"); + addr_debug_print(server->verbose, &(server->sm.m.sm.nd.src_addr),"sctp or tls/sctp connected to"); SOCKET_TYPE st = TENTATIVE_SCTP_SOCKET; diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index a4b686c3..21241f6b 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.4.4.1" +#define TURN_SERVER_VERSION "4.4.4.2" #define TURN_SERVER_VERSION_NAME "Ardee West" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 8662de6d7398dd3a7208218d10b319cdd1493404 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Thu, 2 Apr 2015 05:32:46 +0000 Subject: [PATCH 532/805] sctp fixes --- src/apps/common/apputils.c | 36 +++++++++++++++++++------- src/apps/common/apputils.h | 7 ++--- src/apps/peer/udpserver.c | 2 +- src/apps/relay/dtls_listener.c | 6 ++--- src/apps/relay/ns_ioalib_engine_impl.c | 23 ++++++++-------- src/apps/relay/ns_ioalib_impl.h | 2 +- src/apps/relay/tls_listener.c | 8 +++--- src/apps/relay/turn_admin_server.c | 6 ++--- src/apps/stunclient/stunclient.c | 4 +-- src/apps/uclient/startuclient.c | 8 +++--- src/apps/uclient/uclient.c | 22 ++++++++++++++++ src/apps/uclient/uclient.h | 2 ++ 12 files changed, 85 insertions(+), 41 deletions(-) diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c index b8da9a97..c9d7b7fe 100644 --- a/src/apps/common/apputils.c +++ b/src/apps/common/apputils.c @@ -56,6 +56,10 @@ #include #include +#if !defined(TURN_NO_SCTP) && defined(TURN_SCTP_INCLUDE) +#include TURN_SCTP_INCLUDE +#endif + /************************/ int IS_TURN_SERVER = 0; @@ -119,16 +123,18 @@ int set_sock_buf_size(evutil_socket_t fd, int sz0) return 0; } -int socket_tcp_set_keepalive(evutil_socket_t fd) +int socket_tcp_set_keepalive(evutil_socket_t fd,SOCKET_TYPE st) { + UNUSED_ARG(st); + #ifdef SO_KEEPALIVE /* Set the keepalive option active */ - { - int on = 1; - setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const void*)&on, (socklen_t) sizeof(on)); - } + { + int on = 1; + setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const void*)&on, (socklen_t) sizeof(on)); + } #else - UNUSED_ARG(fd); + UNUSED_ARG(fd); #endif #ifdef SO_NOSIGPIPE @@ -141,8 +147,9 @@ int socket_tcp_set_keepalive(evutil_socket_t fd) return 0; } -int socket_set_reusable(evutil_socket_t fd, int flag) +int socket_set_reusable(evutil_socket_t fd, int flag, SOCKET_TYPE st) { + UNUSED_ARG(st); if (fd < 0) return -1; @@ -170,6 +177,17 @@ int socket_set_reusable(evutil_socket_t fd, int flag) } #endif +#if defined(SCTP_REUSE_PORT) + if (use_reuseaddr) { + if((st == SCTP_SOCKET)||(st==TLS_SCTP_SOCKET)||(st==TENTATIVE_SCTP_SOCKET)) { + int on = flag; + int ret = setsockopt(fd, IPPROTO_SCTP, SCTP_REUSE_PORT, (const void*) &on, (socklen_t) sizeof(on)); + if (ret < 0) + perror("SCTP_REUSE_PORT"); + } + } +#endif + return 0; } } @@ -229,7 +247,7 @@ int addr_connect(evutil_socket_t fd, const ioa_addr* addr, int *out_errno) } } -int addr_bind(evutil_socket_t fd, const ioa_addr* addr, int reusable, int debug) +int addr_bind(evutil_socket_t fd, const ioa_addr* addr, int reusable, int debug, SOCKET_TYPE st) { if (!addr || fd < 0) { @@ -239,7 +257,7 @@ int addr_bind(evutil_socket_t fd, const ioa_addr* addr, int reusable, int debug) int ret = -1; - socket_set_reusable(fd, reusable); + socket_set_reusable(fd, reusable, st); if (addr->ss.sa_family == AF_INET) { do { diff --git a/src/apps/common/apputils.h b/src/apps/common/apputils.h index 9d871153..dd86d673 100644 --- a/src/apps/common/apputils.h +++ b/src/apps/common/apputils.h @@ -37,6 +37,7 @@ #include "ns_turn_ioaddr.h" #include "ns_turn_msg_defs.h" +#include "ns_turn_ioalib.h" #ifdef __cplusplus extern "C" { @@ -173,14 +174,14 @@ void read_spare_buffer(evutil_socket_t fd); int set_sock_buf_size(evutil_socket_t fd, int sz); -int socket_set_reusable(evutil_socket_t fd, int reusable); +int socket_set_reusable(evutil_socket_t fd, int reusable, SOCKET_TYPE st); int sock_bind_to_device(evutil_socket_t fd, const unsigned char* ifname); int socket_set_nonblocking(evutil_socket_t fd); -int socket_tcp_set_keepalive(evutil_socket_t fd); +int socket_tcp_set_keepalive(evutil_socket_t fd, SOCKET_TYPE st); int addr_connect(evutil_socket_t fd, const ioa_addr* addr, int *out_errno); -int addr_bind(evutil_socket_t fd, const ioa_addr* addr, int reusable, int debug); +int addr_bind(evutil_socket_t fd, const ioa_addr* addr, int reusable, int debug, SOCKET_TYPE st); int addr_get_from_sock(evutil_socket_t fd, ioa_addr *addr); diff --git a/src/apps/peer/udpserver.c b/src/apps/peer/udpserver.c index d1b6b519..b95bcdba 100644 --- a/src/apps/peer/udpserver.c +++ b/src/apps/peer/udpserver.c @@ -86,7 +86,7 @@ static int udp_create_server_socket(server_type* server, set_sock_buf_size(udp_fd,UR_SERVER_SOCK_BUF_SIZE); - if(addr_bind(udp_fd,server_addr,1,1)<0) return -1; + if(addr_bind(udp_fd,server_addr,1,1,UDP_SOCKET)<0) return -1; socket_set_nonblocking(udp_fd); diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index 7c4d590f..80aeb82d 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -509,7 +509,7 @@ static int create_new_connected_udp_socket( ret->local_addr_known = 1; addr_cpy(&(ret->local_addr), &(s->local_addr)); - if (addr_bind(udp_fd,&(s->local_addr),1,1) < 0) { + if (addr_bind(udp_fd,&(s->local_addr),1,1,UDP_SOCKET) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot bind new detached udp server socket to local addr\n"); IOA_CLOSE_SOCKET(ret); @@ -773,7 +773,7 @@ static int create_server_socket(dtls_listener_relay_server_type* server, int rep int addr_bind_cycle = 0; retry_addr_bind: - if(addr_bind(udp_listen_fd,&server->addr,1,1)<0) { + if(addr_bind(udp_listen_fd,&server->addr,1,1,UDP_SOCKET)<0) { perror("Cannot bind local socket to addr"); char saddr[129]; addr_to_string(&server->addr,(u08bits*)saddr); @@ -851,7 +851,7 @@ static int reopen_server_socket(dtls_listener_relay_server_type* server, evutil_ server->ifname); } - if(addr_bind(udp_listen_fd,&server->addr,1,1)<0) { + if(addr_bind(udp_listen_fd,&server->addr,1,1,UDP_SOCKET)<0) { perror("Cannot bind local socket to addr"); char saddr[129]; addr_to_string(&server->addr,(u08bits*)saddr); diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 7622d975..2deca3e6 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -816,14 +816,14 @@ int set_raw_socket_tos_options(evutil_socket_t fd, int family) return 0; } -int set_socket_options_fd(evutil_socket_t fd, int tcp, int family) +int set_socket_options_fd(evutil_socket_t fd, SOCKET_TYPE st, int family) { if(fd<0) return 0; set_sock_buf_size(fd,UR_CLIENT_SOCK_BUF_SIZE); - if(tcp) { + if(is_stream_socket(st)) { struct linger so_linger; so_linger.l_onoff = 1; so_linger.l_linger = 0; @@ -839,7 +839,7 @@ int set_socket_options_fd(evutil_socket_t fd, int tcp, int family) socket_set_nonblocking(fd); - if (!tcp) { + if (!is_stream_socket(st)) { set_raw_socket_ttl_options(fd, family); set_raw_socket_tos_options(fd, family); @@ -868,12 +868,14 @@ int set_socket_options_fd(evutil_socket_t fd, int tcp, int family) } else { int flag = 1; - if(setsockopt(fd, /* socket affected */ + + if((st == TENTATIVE_TCP_SOCKET)||(st == TCP_SOCKET)||(st == TLS_SOCKET)) { + setsockopt(fd, /* socket affected */ IPPROTO_TCP, /* set option at TCP level */ TCP_NODELAY, /* name of option */ (char*)&flag, /* value */ - sizeof(int))<0) { /* length of option value */ - + sizeof(int)); /* length of option value */ + } else { #if defined(SCTP_NODELAY) setsockopt(fd, /* socket affected */ IPPROTO_SCTP, /* set option at TCP level */ @@ -881,10 +883,9 @@ int set_socket_options_fd(evutil_socket_t fd, int tcp, int family) (char*)&flag, /* value */ sizeof(int)); /* length of option value */ #endif - } - socket_tcp_set_keepalive(fd); + socket_tcp_set_keepalive(fd,st); } return 0; @@ -895,7 +896,7 @@ int set_socket_options(ioa_socket_handle s) if(!s || (s->parent_s)) return 0; - set_socket_options_fd(s->fd,is_stream_socket(s->st),s->family); + set_socket_options_fd(s->fd,s->st,s->family); s->default_ttl = get_raw_socket_ttl(s->fd, s->family); s->current_ttl = s->default_ttl; @@ -998,7 +999,7 @@ static int bind_ioa_socket(ioa_socket_handle s, const ioa_addr* local_addr, int if (s && s->fd >= 0 && s->e && local_addr) { - int res = addr_bind(s->fd, local_addr, reusable,1); + int res = addr_bind(s->fd, local_addr, reusable,1,s->st); if (res >= 0) { s->bound = 1; addr_cpy(&(s->local_addr), local_addr); @@ -1656,7 +1657,7 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind udp server socket to device %s\n",(char*)(s->e->relay_ifname)); } - if(addr_bind(udp_fd,&(s->local_addr),1,1)<0) { + if(addr_bind(udp_fd,&(s->local_addr),1,1,UDP_SOCKET)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind new detached udp server socket to local addr\n"); close(udp_fd); return ret; diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index 21b7fe32..f2e2cee8 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -299,7 +299,7 @@ int ssl_read(evutil_socket_t fd, SSL* ssl, ioa_network_buffer_handle nbh, int ve int set_raw_socket_ttl_options(evutil_socket_t fd, int family); int set_raw_socket_tos_options(evutil_socket_t fd, int family); -int set_socket_options_fd(evutil_socket_t fd, int tcp, int family); +int set_socket_options_fd(evutil_socket_t fd, SOCKET_TYPE st, int family); int set_socket_options(ioa_socket_handle s); int send_session_cancellation_to_relay(turnsession_id sid); diff --git a/src/apps/relay/tls_listener.c b/src/apps/relay/tls_listener.c index 4f27cdcf..bacf84d1 100644 --- a/src/apps/relay/tls_listener.c +++ b/src/apps/relay/tls_listener.c @@ -213,7 +213,7 @@ static int create_server_listener(tls_listener_relay_server_type* server) { int addr_bind_cycle = 0; retry_addr_bind: - if(addr_bind(tls_listen_fd,&server->addr,1,1)<0) { + if(addr_bind(tls_listen_fd,&server->addr,1,1,TCP_SOCKET)<0) { perror("Cannot bind local socket to addr"); char saddr[129]; addr_to_string(&server->addr,(u08bits*)saddr); @@ -228,7 +228,7 @@ static int create_server_listener(tls_listener_relay_server_type* server) { } } - socket_tcp_set_keepalive(tls_listen_fd); + socket_tcp_set_keepalive(tls_listen_fd,TCP_SOCKET); socket_set_nonblocking(tls_listen_fd); @@ -275,12 +275,12 @@ static int sctp_create_server_listener(tls_listener_relay_server_type* server) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind listener socket to device %s\n",server->ifname); } - if(addr_bind(tls_listen_fd,&server->addr,1,0)<0) { + if(addr_bind(tls_listen_fd,&server->addr,1,0,SCTP_SOCKET)<0) { close(tls_listen_fd); return -1; } - socket_tcp_set_keepalive(tls_listen_fd); + socket_tcp_set_keepalive(tls_listen_fd,SCTP_SOCKET); socket_set_nonblocking(tls_listen_fd); diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index d9c4cb4e..1e9aeeda 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1163,7 +1163,7 @@ static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd clisession->rp = get_realm(NULL); - set_socket_options_fd(fd, 1, sa->sa_family); + set_socket_options_fd(fd, TCP_SOCKET, sa->sa_family); clisession->fd = fd; @@ -1251,7 +1251,7 @@ void setup_admin_thread(void) return; } - if(addr_bind(adminserver.listen_fd,&cli_addr,1,1)<0) { + if(addr_bind(adminserver.listen_fd,&cli_addr,1,1,TCP_SOCKET)<0) { perror("Cannot bind CLI socket to addr"); char saddr[129]; addr_to_string(&cli_addr,(u08bits*)saddr); @@ -1260,7 +1260,7 @@ void setup_admin_thread(void) return; } - socket_tcp_set_keepalive(adminserver.listen_fd); + socket_tcp_set_keepalive(adminserver.listen_fd,TCP_SOCKET); socket_set_nonblocking(adminserver.listen_fd); diff --git a/src/apps/stunclient/stunclient.c b/src/apps/stunclient/stunclient.c index 5f6e0054..85457a22 100644 --- a/src/apps/stunclient/stunclient.c +++ b/src/apps/stunclient/stunclient.c @@ -263,7 +263,7 @@ static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, i err(-1, NULL); if (!addr_any(&real_local_addr)) { - if (addr_bind(udp_fd, &real_local_addr,0,1) < 0) + if (addr_bind(udp_fd, &real_local_addr,0,1,UDP_SOCKET) < 0) err(-1, NULL); } } @@ -276,7 +276,7 @@ static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, i addr_set_port(&real_local_addr, response_port); - if (addr_bind(new_udp_fd, &real_local_addr,0,1) < 0) + if (addr_bind(new_udp_fd, &real_local_addr,0,1,UDP_SOCKET) < 0) err(-1, NULL); } diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 3153dc5d..6fdd6d7a 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -259,7 +259,7 @@ static int clnet_connect(uint16_t clnet_remote_port, const char *remote_address, } } - addr_bind(clnet_fd, &local_addr, 0, 1); + addr_bind(clnet_fd, &local_addr, 0, 1, get_socket_type()); } else if (strlen(local_address) > 0) { @@ -267,7 +267,7 @@ static int clnet_connect(uint16_t clnet_remote_port, const char *remote_address, &local_addr) < 0) return -1; - addr_bind(clnet_fd, &local_addr,0,1); + addr_bind(clnet_fd, &local_addr,0,1,get_socket_type()); } if(clnet_info->is_peer) { @@ -1597,7 +1597,7 @@ void tcp_data_connect(app_ur_session *elem, u32bits cid) addr_set_port(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),0); - addr_bind(clnet_fd, &(elem->pinfo.tcp_conn[i]->tcp_data_local_addr), 1, 1); + addr_bind(clnet_fd, &(elem->pinfo.tcp_conn[i]->tcp_data_local_addr), 1, 1, TCP_SOCKET); addr_get_from_sock(clnet_fd,&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr)); @@ -1625,7 +1625,7 @@ void tcp_data_connect(app_ur_session *elem, u32bits cid) addr_set_port(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),0); - addr_bind(clnet_fd, &(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),1,1); + addr_bind(clnet_fd, &(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),1,1,TCP_SOCKET); addr_get_from_sock(clnet_fd,&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr)); diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index e73109a7..6c7ea410 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1702,5 +1702,27 @@ int check_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) return 0; } +SOCKET_TYPE get_socket_type() +{ + if(use_sctp) { + if(use_secure) { + return TLS_SCTP_SOCKET; + } else { + return SCTP_SOCKET; + } + } else if(use_tcp) { + if(use_secure) { + return TLS_SOCKET; + } else { + return TCP_SOCKET; + } + } else { + if(use_secure) { + return DTLS_SOCKET; + } else { + return UDP_SOCKET; + } + } +} /////////////////////////////////////////// diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index 995f3697..decef5ec 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -112,6 +112,8 @@ int check_integrity(app_ur_conn_info *clnet_info, stun_buffer *message); void recalculate_restapi_hmac(SHATYPE st); +SOCKET_TYPE get_socket_type(void); + //////////////////////////////////////////// #ifdef __cplusplus From 948a61d2502ed0b222ee8626095c95041349b22d Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 3 Apr 2015 06:54:10 +0000 Subject: [PATCH 533/805] SCTP fixes. --- ChangeLog | 2 +- .../longtermsecure/secure_sctp_client.sh | 2 +- src/apps/common/apputils.c | 82 +++++++++++++++++-- src/apps/relay/ns_ioalib_engine_impl.c | 51 ++---------- src/server/ns_turn_ioalib.h | 4 +- 5 files changed, 87 insertions(+), 54 deletions(-) diff --git a/ChangeLog b/ChangeLog index dc71c762..e01eebf8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ 3/31/2015 Oleg Moskalenko Version 4.4.4.2 'Ardee West': - - minor SCTP fix; + - SCTP fixes; 3/15/2015 Oleg Moskalenko Version 4.4.4.1 'Ardee West': diff --git a/examples/scripts/longtermsecure/secure_sctp_client.sh b/examples/scripts/longtermsecure/secure_sctp_client.sh index e6ca3ce0..8bdc3427 100755 --- a/examples/scripts/longtermsecure/secure_sctp_client.sh +++ b/examples/scripts/longtermsecure/secure_sctp_client.sh @@ -30,5 +30,5 @@ fi export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/ -PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -b -S -k turn_client_pkey.pem -n 1000 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -b -k turn_client_pkey.pem -n 1000 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c index c9d7b7fe..0d3b7fe4 100644 --- a/src/apps/common/apputils.c +++ b/src/apps/common/apputils.c @@ -161,13 +161,6 @@ int socket_set_reusable(evutil_socket_t fd, int flag, SOCKET_TYPE st) int use_reuseaddr = 1; #endif -#if defined(SO_REUSEPORT) - if (use_reuseaddr) { - int on = flag; - setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) &on, (socklen_t) sizeof(on)); - } -#endif - #if defined(SO_REUSEADDR) if (use_reuseaddr) { int on = flag; @@ -177,9 +170,10 @@ int socket_set_reusable(evutil_socket_t fd, int flag, SOCKET_TYPE st) } #endif +#if !defined(TURN_NO_SCTP) #if defined(SCTP_REUSE_PORT) if (use_reuseaddr) { - if((st == SCTP_SOCKET)||(st==TLS_SCTP_SOCKET)||(st==TENTATIVE_SCTP_SOCKET)) { + if(is_sctp_socket(st)) { int on = flag; int ret = setsockopt(fd, IPPROTO_SCTP, SCTP_REUSE_PORT, (const void*) &on, (socklen_t) sizeof(on)); if (ret < 0) @@ -187,6 +181,14 @@ int socket_set_reusable(evutil_socket_t fd, int flag, SOCKET_TYPE st) } } #endif +#endif + +#if defined(SO_REUSEPORT) + if (use_reuseaddr) { + int on = flag; + setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) &on, (socklen_t) sizeof(on)); + } +#endif return 0; } @@ -434,6 +436,70 @@ int set_raw_socket_tos(evutil_socket_t fd, int family, int tos) return 0; } +int is_stream_socket(int st) { + switch(st) { + case TCP_SOCKET: + case TLS_SOCKET: + case TENTATIVE_TCP_SOCKET: + case SCTP_SOCKET: + case TLS_SCTP_SOCKET: + case TENTATIVE_SCTP_SOCKET: + return 1; + default: + ; + } + return 0; +} + +int is_tcp_socket(int st) { + switch(st) { + case TCP_SOCKET: + case TLS_SOCKET: + case TENTATIVE_TCP_SOCKET: + return 1; + default: + ; + } + return 0; +} + +int is_sctp_socket(int st) { + switch(st) { + case SCTP_SOCKET: + case TLS_SCTP_SOCKET: + case TENTATIVE_SCTP_SOCKET: + return 1; + default: + ; + } + return 0; +} + +const char* socket_type_name(SOCKET_TYPE st) +{ + switch(st) { + case TCP_SOCKET: + return "TCP"; + case SCTP_SOCKET: + return "SCTP"; + case UDP_SOCKET: + return "UDP"; + case TLS_SOCKET: + return "TLS/TCP"; + case TLS_SCTP_SOCKET: + return "TLS/SCTP"; + case DTLS_SOCKET: + return "DTLS"; + case TENTATIVE_TCP_SOCKET: + return "TLS/TCP ?"; + case TENTATIVE_SCTP_SOCKET: + return "TLS/SCTP ?"; + default: + ; + }; + return "UNKNOWN"; +} + /////////////////// MTU ///////////////////////////////////////// int set_socket_df(evutil_socket_t fd, int family, int value) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 2deca3e6..4fa84a85 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -823,7 +823,7 @@ int set_socket_options_fd(evutil_socket_t fd, SOCKET_TYPE st, int family) set_sock_buf_size(fd,UR_CLIENT_SOCK_BUF_SIZE); - if(is_stream_socket(st)) { + if(is_tcp_socket(st)) { /* <<== FREEBSD fix */ struct linger so_linger; so_linger.l_onoff = 1; so_linger.l_linger = 0; @@ -869,7 +869,7 @@ int set_socket_options_fd(evutil_socket_t fd, SOCKET_TYPE st, int family) int flag = 1; - if((st == TENTATIVE_TCP_SOCKET)||(st == TCP_SOCKET)||(st == TLS_SOCKET)) { + if(is_tcp_socket(st)) { setsockopt(fd, /* socket affected */ IPPROTO_TCP, /* set option at TCP level */ TCP_NODELAY, /* name of option */ @@ -878,7 +878,7 @@ int set_socket_options_fd(evutil_socket_t fd, SOCKET_TYPE st, int family) } else { #if defined(SCTP_NODELAY) setsockopt(fd, /* socket affected */ - IPPROTO_SCTP, /* set option at TCP level */ + IPPROTO_SCTP, /* set option at SCTP level */ SCTP_NODELAY, /* name of option */ (char*)&flag, /* value */ sizeof(int)); /* length of option value */ @@ -907,46 +907,6 @@ int set_socket_options(ioa_socket_handle s) return 0; } -int is_stream_socket(int st) { - switch(st) { - case TCP_SOCKET: - case TLS_SOCKET: - case TENTATIVE_TCP_SOCKET: - case SCTP_SOCKET: - case TLS_SCTP_SOCKET: - case TENTATIVE_SCTP_SOCKET: - return 1; - default: - ; - } - return 0; -} - -const char* socket_type_name(SOCKET_TYPE st) -{ - switch(st) { - case TCP_SOCKET: - return "TCP"; - case SCTP_SOCKET: - return "SCTP"; - case UDP_SOCKET: - return "UDP"; - case TLS_SOCKET: - return "TLS/TCP"; - case TLS_SCTP_SOCKET: - return "TLS/SCTP"; - case DTLS_SOCKET: - return "DTLS"; - case TENTATIVE_TCP_SOCKET: - return "TLS/TCP ?"; - case TENTATIVE_SCTP_SOCKET: - return "TLS/SCTP ?"; - default: - ; - }; - return "UNKNOWN"; -} - /* <<== Socket options helpers */ ioa_socket_handle create_unbound_relay_ioa_socket(ioa_engine_handle e, int family, SOCKET_TYPE st, SOCKET_APP_TYPE sat) @@ -3171,6 +3131,11 @@ int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, s->tobeclosed = 1; s->broken = 1; } + /* + bufferevent_flush(s->bev, + EV_READ|EV_WRITE, + BEV_FLUSH); + */ s->in_write = 0; } else { //drop the packet diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 51e44a58..e464c0c7 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -231,7 +231,9 @@ int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_ int get_ioa_socket_address_family(ioa_socket_handle s); int is_stream_socket(int st); - const char* socket_type_name(SOCKET_TYPE st); +int is_tcp_socket(int st); +int is_sctp_socket(int st); +const char* socket_type_name(SOCKET_TYPE st); const char* get_ioa_socket_cipher(ioa_socket_handle s); const char* get_ioa_socket_ssl_method(ioa_socket_handle s); SOCKET_TYPE get_ioa_socket_type(ioa_socket_handle s); From 4d5f0cbc03b29fd08267faf5ddf60070a6f5b3e9 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 3 Apr 2015 07:02:55 +0000 Subject: [PATCH 534/805] script fixed --- examples/scripts/longtermsecure/secure_sctp_client.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/scripts/longtermsecure/secure_sctp_client.sh b/examples/scripts/longtermsecure/secure_sctp_client.sh index 8bdc3427..e6ca3ce0 100755 --- a/examples/scripts/longtermsecure/secure_sctp_client.sh +++ b/examples/scripts/longtermsecure/secure_sctp_client.sh @@ -30,5 +30,5 @@ fi export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/ -PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -b -k turn_client_pkey.pem -n 1000 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 +PATH=examples/bin/:../bin:./bin/:${PATH} turnutils_uclient -b -S -k turn_client_pkey.pem -n 1000 -m 10 -l 170 -e 127.0.0.1 -X -g -u gorst -w hero $@ ::1 From 2368f98f3c63d823cf450e4dd14fe3a63f13d976 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Tue, 7 Apr 2015 06:20:00 +0000 Subject: [PATCH 535/805] C++ and cosmetic fixes --- ChangeLog | 5 +++++ TODO | 6 ++--- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +++- src/apps/relay/mainrelay.c | 38 +++++++++++++++++++++++++++++--- src/apps/stunclient/stunclient.c | 4 ++-- src/ns_turn_defs.h | 2 +- 7 files changed, 50 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index e01eebf8..a2d0b158 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +4/6/2015 Oleg Moskalenko +Version 4.4.4.3 'Ardee West': + - C++ fixes; + - cosmetic fixes; + 3/31/2015 Oleg Moskalenko Version 4.4.4.2 'Ardee West': - SCTP fixes; diff --git a/TODO b/TODO index ec826dd9..038548f9 100644 --- a/TODO +++ b/TODO @@ -59,9 +59,9 @@ 2) Redirect draft. -3) STUN-Bis: - a. SCTP - b. New integrity attribute, algorithms +3) STUN-bis: new integrity attribute, algorithms. + +4) TURN-bis: dual allocation fixes. ================================================================== diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 9af5ffe2..5259873f 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.4.4.2 +TURNVERSION=4.4.4.3 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index c35875ed..dc507439 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.4.4.2 +Version: 4.4.4.3 Release: 0%{dist} Summary: Coturn TURN Server @@ -289,6 +289,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Mon Apr 06 2015 Oleg Moskalenko + - Sync to 4.4.4.3 * Tue Mar 31 2015 Oleg Moskalenko - Sync to 4.4.4.2 * Sun Mar 15 2015 Oleg Moskalenko diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 48df9acd..eca7c6af 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -1650,6 +1650,17 @@ static void print_features(unsigned long mfn) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\n\n==== Show him the instruments, Practical Frost: ====\n\n"); +/* + Frost stepped forward and opened the polished case with a theatrical + flourish. It was a masterful piece of craftsmanship. As the lid was + pulled back, the many trays inside lifted and fanned out, displaying + Glokta’s tools in all their gruesome glory. There were blades of every + size and shape, needles curved and straight, bottles of oil and acid, + nails and screws, clamps and pliers, saws, hammers, chisels. Metal, wood + and glass glittered in the bright lamplight, all polished to mirror + brightness and honed to a murderous sharpness. +*/ + #if !TLS_SUPPORTED TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS is not supported\n"); #else @@ -1660,14 +1671,29 @@ static void print_features(unsigned long mfn) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS is not supported\n"); #else TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS supported\n"); +#if DTLSv1_2_SUPPORTED + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS 1.2 supported\n"); +#else + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS 1.2 is not supported\n"); +#endif +#endif + +#if ALPN_SUPPORTED + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TURN/STUN ALPN supported\n"); +#else + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TURN/STUN ALPN is not supported\n"); #endif #if defined(TURN_NO_GCM) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "AEAD is not supported\n"); #else - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "AEAD supported\n"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "AEAD GCM supported\n"); #endif + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL compile-time version: %s\n",OPENSSL_VERSION_TEXT); + + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\n"); + #if !defined(TURN_NO_SQLITE) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SQLite supported, default database location is %s\n",DEFAULT_USERDB_FILE); #else @@ -1698,7 +1724,13 @@ static void print_features(unsigned long mfn) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MongoDB is not supported\n"); #endif - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL compile-time version: %s\n",OPENSSL_VERSION_TEXT); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\n"); + +#if !defined(TURN_NO_SCTP) + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SCTP supported\n"); +#else + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SCTP is not supported\n"); +#endif TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Default Net Engine version: %d (%s)\n\n=====================================================\n\n", (int)turn_params.net_engine_version, turn_params.net_engine_version_txt[(int)turn_params.net_engine_version]); @@ -2657,7 +2689,7 @@ static void openssl_setup(void) #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"); + 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()); diff --git a/src/apps/stunclient/stunclient.c b/src/apps/stunclient/stunclient.c index 85457a22..c54a4765 100644 --- a/src/apps/stunclient/stunclient.c +++ b/src/apps/stunclient/stunclient.c @@ -67,7 +67,7 @@ static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, i err(-1, NULL); if (!addr_any(&real_local_addr)) { - if (addr_bind(udp_fd, &real_local_addr,0,1) < 0) + if (addr_bind(udp_fd, &real_local_addr,0,1,UDP_SOCKET) < 0) err(-1, NULL); } } @@ -80,7 +80,7 @@ static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, i addr_set_port(&real_local_addr, response_port); - if (addr_bind(new_udp_fd, &real_local_addr, 0, 1) < 0) + if (addr_bind(new_udp_fd, &real_local_addr, 0, 1, UDP_SOCKET) < 0) err(-1, NULL); } diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 21241f6b..4f066ea8 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.4.4.2" +#define TURN_SERVER_VERSION "4.4.4.3" #define TURN_SERVER_VERSION_NAME "Ardee West" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" From 9483dec4decab416506636b17dcddbd8d8662a52 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 10 Apr 2015 07:07:18 +0000 Subject: [PATCH 536/805] turn-bis new release adjustments (dual allocation) --- ChangeLog | 5 +++-- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 6 +++--- src/apps/uclient/startuclient.c | 2 +- src/apps/uclient/uclient.c | 2 +- src/ns_turn_defs.h | 2 +- src/server/ns_turn_server.c | 4 ++-- 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index a2d0b158..ab0b7779 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ -4/6/2015 Oleg Moskalenko -Version 4.4.4.3 'Ardee West': +4/9/2015 Oleg Moskalenko +Version 4.4.5.1 'Ardee West': + - dual allocation adjusted according to the new TURN-bis draft; - C++ fixes; - cosmetic fixes; diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index 5259873f..832b8e46 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.4.4.3 +TURNVERSION=4.4.5.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index dc507439..c71d7cce 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.4.4.3 +Version: 4.4.5.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -289,8 +289,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog -* Mon Apr 06 2015 Oleg Moskalenko - - Sync to 4.4.4.3 +* Thu Apr 09 2015 Oleg Moskalenko + - Sync to 4.4.5.1 * Tue Mar 31 2015 Oleg Moskalenko - Sync to 4.4.4.2 * Sun Mar 15 2015 Oleg Moskalenko diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 6fdd6d7a..60bdaa2a 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -668,7 +668,7 @@ static int clnet_allocate(int verbose, field[1]=0; field[2]=0; field[3]=0; - stun_attr_add(&request_message, STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY, (const char*) field, 4); + stun_attr_add(&request_message, STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY, (const char*) field, 4); } } diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 6c7ea410..e55a6b30 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1247,7 +1247,7 @@ static int refresh_channel(app_ur_session* elem, u16bits method, uint32_t lt) field[1]=0; field[2]=0; field[3]=0; - stun_attr_add(&message, STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY, (const char*) field, 4); + stun_attr_add(&message, STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY, (const char*) field, 4); } } diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 4f066ea8..4222ede6 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.4.4.3" +#define TURN_SERVER_VERSION "4.4.5.1" #define TURN_SERVER_VERSION_NAME "Ardee West" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 68dc4cef..184b8866 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1519,8 +1519,8 @@ static int handle_turn_refresh(turn_turnserver *server, } } break; - case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY: /* <<== ??? */ - case STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY: { + case STUN_ATTRIBUTE_ADDITIONAL_ADDRESS_FAMILY: /* deprecated, for backward compatibility with older versions of TURN-bis */ + case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY: { int af_req = stun_get_requested_address_family(sar); { int is_err = 0; From 42b74053e14a3b80deb3cdfca24709c2fd66076a Mon Sep 17 00:00:00 2001 From: mom040267 Date: Fri, 10 Apr 2015 07:48:41 +0000 Subject: [PATCH 537/805] address error fixes (dual allocation) --- src/client/ns_turn_msg.c | 104 ++++++++++++++++++++++++++++-------- src/client/ns_turn_msg.h | 4 +- src/server/ns_turn_server.c | 8 +-- 3 files changed, 87 insertions(+), 29 deletions(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 635ca91e..723f18f7 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -441,20 +441,20 @@ int stun_is_error_response_str(const u08bits* buf, size_t len, int *err_code, u0 if(err_code) { stun_attr_ref sar = stun_attr_get_first_by_type_str(buf, len, STUN_ATTRIBUTE_ERROR_CODE); if(sar) { - if(stun_attr_get_len(sar)>=4) { - const u08bits* val = (const u08bits*)stun_attr_get_value(sar); - *err_code=(int)(val[2]*100 + val[3]); - if(err_msg && err_msg_size>0) { - err_msg[0]=0; - if(stun_attr_get_len(sar)>4) { - size_t msg_len = stun_attr_get_len(sar) - 4; - if(msg_len>(err_msg_size-1)) - msg_len=err_msg_size - 1; - ns_bcopy(val+4, err_msg, msg_len); - err_msg[msg_len]=0; - } - } - } + if(stun_attr_get_len(sar)>=4) { + const u08bits* val = (const u08bits*)stun_attr_get_value(sar); + *err_code=(int)(val[2]*100 + val[3]); + if(err_msg && err_msg_size>0) { + err_msg[0]=0; + if(stun_attr_get_len(sar)>4) { + size_t msg_len = stun_attr_get_len(sar) - 4; + if(msg_len>(err_msg_size-1)) + msg_len=err_msg_size - 1; + ns_bcopy(val+4, err_msg, msg_len); + err_msg[msg_len]=0; + } + } + } } } return 1; @@ -608,18 +608,42 @@ static void stun_init_error_response_common_str(u08bits* buf, size_t *len, case 401: reason = (const u08bits *) "Unauthorized"; break; + case 403: + reason = (const u08bits *) "Forbidden"; + break; case 404: reason = (const u08bits *) "Not Found"; break; case 420: reason = (const u08bits *) "Unknown Attribute"; break; + case 437: + reason = (const u08bits *) "Allocation Mismatch"; + break; case 438: reason = (const u08bits *) "Stale Nonce"; break; + case 440: + reason = (const u08bits *) "Address Family not Supported"; + break; + case 441: + reason = (const u08bits *) "Wrong Credentials"; + break; + case 442: + reason = (const u08bits *) "Unsupported Transport Protocol"; + break; + case 443: + reason = (const u08bits *) "Peer Address Family Mismatch"; + break; + case 486: + reason = (const u08bits *) "Allocation Quota Reached"; + break; case 500: reason = (const u08bits *) "Server Error"; break; + case 508: + reason = (const u08bits *) "Insufficient Capacity"; + break; default: reason = (const u08bits *) "Unknown Error"; break; @@ -1426,17 +1450,51 @@ int stun_attr_add_bandwidth_str(u08bits* buf, size_t *len, band_limit_t bps0) { return stun_attr_add_str(buf,len,STUN_ATTRIBUTE_NEW_BANDWIDTH,(u08bits*)(&field),sizeof(field)); } -int stun_attr_add_address_error_code(u08bits* buf, size_t *len, int requested_address_family, u08bits error_code) +int stun_attr_add_address_error_code(u08bits* buf, size_t *len, int requested_address_family, int error_code) { - u08bits field[4]; - field[0]=(u08bits)requested_address_family; - field[1]=error_code; - field[2]=0; - field[3]=0; - return stun_attr_add_str(buf,len,STUN_ATTRIBUTE_ADDRESS_ERROR_CODE,field,sizeof(field)); + const u08bits *reason = NULL; + + switch (error_code){ + case 440: + reason = (const u08bits *) "Address Family not Supported"; + break; + case 486: + reason = (const u08bits *) "Allocation Quota Reached"; + break; + case 500: + reason = (const u08bits *) "Server Error"; + break; + case 508: + reason = (const u08bits *) "Insufficient Capacity"; + break; + default: + reason = (const u08bits *) "Unknown Error"; + break; + }; + + u08bits avalue[513]; + avalue[0] = (u08bits)requested_address_family; + avalue[1] = 0; + avalue[2] = (u08bits) (error_code / 100); + avalue[3] = (u08bits) (error_code % 100); + strncpy((s08bits*) (avalue + 4), (const s08bits*) reason, sizeof(avalue)-4); + avalue[sizeof(avalue)-1]=0; + int alen = 4 + strlen((const s08bits*) (avalue+4)); + + //"Manual" padding for compatibility with classic old stun: + { + int rem = alen % 4; + if(rem) { + alen +=(4-rem); + } + } + + stun_attr_add_str(buf, len, STUN_ATTRIBUTE_ADDRESS_ERROR_CODE, (u08bits*) avalue, alen); + + return 0; } -int stun_attr_get_address_error_code(u08bits* buf, size_t len, int *requested_address_family, u08bits *error_code) +int stun_attr_get_address_error_code(u08bits* buf, size_t len, int *requested_address_family, int *error_code) { if(requested_address_family) { *requested_address_family = 0; @@ -1459,7 +1517,7 @@ int stun_attr_get_address_error_code(u08bits* buf, size_t len, int *requested_ad *requested_address_family = value[0]; } if(error_code) { - *error_code = value[1]; + *error_code = (int)(value[2]*100+value[3]); } return 0; } diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 0f96cb07..09f8ffcb 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -151,9 +151,9 @@ int stun_attr_get_addr_str(const u08bits *buf, size_t len, stun_attr_ref attr, i int stun_attr_get_first_addr_str(const u08bits *buf, size_t len, u16bits attr_type, ioa_addr* ca, const ioa_addr *default_addr); int stun_attr_add_channel_number_str(u08bits* buf, size_t *len, u16bits chnumber); int stun_attr_add_bandwidth_str(u08bits* buf, size_t *len, band_limit_t bps); -int stun_attr_add_address_error_code(u08bits* buf, size_t *len, int requested_address_family, u08bits error_code); +int stun_attr_add_address_error_code(u08bits* buf, size_t *len, int requested_address_family, int error_code); /* return +1 if present, 0 if not, -1 if error: */ -int stun_attr_get_address_error_code(u08bits* buf, size_t len, int *requested_address_family, u08bits *error_code); +int stun_attr_get_address_error_code(u08bits* buf, size_t len, int *requested_address_family, int *error_code); u16bits stun_attr_get_first_channel_number_str(const u08bits *buf, size_t len); int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int af4, int af6, u08bits transport, int mobile, const char* rt, int ep); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 184b8866..a25ea0c5 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1290,7 +1290,7 @@ static int handle_turn_allocate(turn_turnserver *server, if(af4res<0) { set_relay_session_failure(alloc,AF_INET); if(!err_code4) { - err_code4 = 437; + err_code4 = 440; } } } @@ -1303,7 +1303,7 @@ static int handle_turn_allocate(turn_turnserver *server, if(af6res<0) { set_relay_session_failure(alloc,AF_INET6); if(!err_code6) { - err_code6 = 437; + err_code6 = 440; } } } @@ -1405,12 +1405,12 @@ static int handle_turn_allocate(turn_turnserver *server, if(*resp_constructed && !(*err_code)) { if(err_code4) { size_t len = ioa_network_buffer_get_size(nbh); - stun_attr_add_address_error_code(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4, (u08bits)err_code4); + stun_attr_add_address_error_code(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4, err_code4); ioa_network_buffer_set_size(nbh,len); } if(err_code6) { size_t len = ioa_network_buffer_get_size(nbh); - stun_attr_add_address_error_code(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6, (u08bits)err_code6); + stun_attr_add_address_error_code(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6, err_code6); ioa_network_buffer_set_size(nbh,len); } } From 670b6b66177743d86e5e5e36af7b18f3bead8cd2 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 11 Apr 2015 05:45:18 +0000 Subject: [PATCH 538/805] TODO updated --- TODO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO b/TODO index 038548f9..b45b5866 100644 --- a/TODO +++ b/TODO @@ -61,7 +61,7 @@ 3) STUN-bis: new integrity attribute, algorithms. -4) TURN-bis: dual allocation fixes. +4) Third-party authorization updates. ================================================================== From ce19cf3ceeabbb5423ed38c2e0b6c3f5cc83a14b Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 11 Apr 2015 06:31:17 +0000 Subject: [PATCH 539/805] error codes cleaned --- src/client/ns_turn_msg.c | 138 ++++++++++++++++++------------------ src/client/ns_turn_msg.h | 2 + src/server/ns_turn_server.c | 29 +------- 3 files changed, 73 insertions(+), 96 deletions(-) diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 723f18f7..c562682b 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -591,63 +591,79 @@ void old_stun_init_success_response_str(u16bits method, u08bits* buf, size_t *le } } +const u08bits* get_default_reason(int error_code) +{ + const u08bits* reason = (const u08bits *) "Unknown error"; + + switch (error_code){ + case 300: + reason = (const u08bits *) "Try Alternate"; + break; + case 400: + reason = (const u08bits *) "Bad Request"; + break; + case 401: + reason = (const u08bits *) "Unauthorized"; + break; + case 403: + reason = (const u08bits *) "Forbidden"; + break; + case 404: + reason = (const u08bits *) "Not Found"; + break; + case 420: + reason = (const u08bits *) "Unknown Attribute"; + break; + case 437: + reason = (const u08bits *) "Allocation Mismatch"; + break; + case 438: + reason = (const u08bits *) "Stale Nonce"; + break; + case 440: + reason = (const u08bits *) "Address Family not Supported"; + break; + case 441: + reason = (const u08bits *) "Wrong Credentials"; + break; + case 442: + reason = (const u08bits *) "Unsupported Transport Protocol"; + break; + case 443: + reason = (const u08bits *) "Peer Address Family Mismatch"; + break; + case 446: + reason = (const u08bits *) "Connection Already Exists"; + break; + case 447: + reason = (const u08bits *) "Connection Timeout or Failure"; + break; + case 486: + reason = (const u08bits *) "Allocation Quota Reached"; + break; + case 487: + reason = (const u08bits *) "Role Conflict"; + break; + case 500: + reason = (const u08bits *) "Server Error"; + break; + case 508: + reason = (const u08bits *) "Insufficient Capacity"; + break; + default: + ; + }; + + return reason; +} + static void stun_init_error_response_common_str(u08bits* buf, size_t *len, u16bits error_code, const u08bits *reason, stun_tid* id) { if (!reason) { - - switch (error_code){ - case 300: - reason = (const u08bits *) "Try Alternate"; - break; - case 400: - reason = (const u08bits *) "Bad Request"; - break; - case 401: - reason = (const u08bits *) "Unauthorized"; - break; - case 403: - reason = (const u08bits *) "Forbidden"; - break; - case 404: - reason = (const u08bits *) "Not Found"; - break; - case 420: - reason = (const u08bits *) "Unknown Attribute"; - break; - case 437: - reason = (const u08bits *) "Allocation Mismatch"; - break; - case 438: - reason = (const u08bits *) "Stale Nonce"; - break; - case 440: - reason = (const u08bits *) "Address Family not Supported"; - break; - case 441: - reason = (const u08bits *) "Wrong Credentials"; - break; - case 442: - reason = (const u08bits *) "Unsupported Transport Protocol"; - break; - case 443: - reason = (const u08bits *) "Peer Address Family Mismatch"; - break; - case 486: - reason = (const u08bits *) "Allocation Quota Reached"; - break; - case 500: - reason = (const u08bits *) "Server Error"; - break; - case 508: - reason = (const u08bits *) "Insufficient Capacity"; - break; - default: - reason = (const u08bits *) "Unknown Error"; - break; - }; + reason = get_default_reason(error_code); } u08bits avalue[513]; @@ -1452,25 +1468,7 @@ int stun_attr_add_bandwidth_str(u08bits* buf, size_t *len, band_limit_t bps0) { int stun_attr_add_address_error_code(u08bits* buf, size_t *len, int requested_address_family, int error_code) { - const u08bits *reason = NULL; - - switch (error_code){ - case 440: - reason = (const u08bits *) "Address Family not Supported"; - break; - case 486: - reason = (const u08bits *) "Allocation Quota Reached"; - break; - case 500: - reason = (const u08bits *) "Server Error"; - break; - case 508: - reason = (const u08bits *) "Insufficient Capacity"; - break; - default: - reason = (const u08bits *) "Unknown Error"; - break; - }; + const u08bits *reason = get_default_reason(error_code); u08bits avalue[513]; avalue[0] = (u08bits)requested_address_family; diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 09f8ffcb..79494ae4 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -134,6 +134,8 @@ void stun_tid_generate_in_message_str(u08bits* buf, stun_tid* id); int stun_get_command_message_len_str(const u08bits* buf, size_t len); +const u08bits* get_default_reason(int error_code); + int stun_attr_is_addr(stun_attr_ref attr); int stun_attr_get_type(stun_attr_ref attr); int stun_attr_get_len(stun_attr_ref attr); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index a25ea0c5..ab068e83 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1047,7 +1047,6 @@ static int handle_turn_allocate(turn_turnserver *server, transport = get_transport_value(value); if (!transport) { *err_code = 442; - *reason = (const u08bits *)"Unsupported Transport Protocol"; } if((transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) && *(server->no_tcp_relay)) { *err_code = 442; @@ -1159,7 +1158,6 @@ static int handle_turn_allocate(turn_turnserver *server, break; default: *err_code = 440; - *reason = (const u08bits *)"Unsupported address family requested"; } } } @@ -1182,8 +1180,6 @@ static int handle_turn_allocate(turn_turnserver *server, } else if (*ua_num > 0) { *err_code = 420; - if(!(*reason)) - *reason = (const u08bits *)"Unknown attribute"; } else if (*err_code) { @@ -1209,7 +1205,6 @@ static int handle_turn_allocate(turn_turnserver *server, if(inc_quota(ss, username)<0) { *err_code = 486; - *reason = (const u08bits *)"Allocation Quota Reached"; } else { @@ -1561,7 +1556,6 @@ static int handle_turn_refresh(turn_turnserver *server, if (*ua_num > 0) { *err_code = 420; - *reason = (const u08bits *)"Unknown attribute"; } else if (*err_code) { @@ -1980,8 +1974,7 @@ static void tcp_peer_connection_completed_callback(int success, void *arg) addr_to_string(&(tc->peer_addr),(u08bits*)rs); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: failure to connect from %s to %s\n", __FUNCTION__, ls,rs); } - const u08bits *reason = (const u08bits *)"Connection Timeout or Failure"; - stun_init_error_response_str(STUN_METHOD_CONNECT, ioa_network_buffer_data(nbh), &len, err_code, reason, &(tc->tid)); + stun_init_error_response_str(STUN_METHOD_CONNECT, ioa_network_buffer_data(nbh), &len, err_code, NULL, &(tc->tid)); } ioa_network_buffer_set_size(nbh,len); @@ -2051,7 +2044,6 @@ static int tcp_start_connection_to_peer(turn_turnserver *server, ts_ur_super_ses tcp_connection *tc = get_tcp_connection_by_peer(a, peer_addr); if(tc) { *err_code = 446; - *reason = (const u08bits *)"Connection Already Exists"; FUNCEND; return -1; } @@ -2219,7 +2211,6 @@ static int handle_turn_connect(turn_turnserver *server, *reason = (const u08bits *)"Connect cannot be used with UDP relay"; } else if (!is_allocation_valid(a)) { *err_code = 437; - *reason = (const u08bits *)"Allocation mismatch"; } else { stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh), @@ -2258,7 +2249,6 @@ static int handle_turn_connect(turn_turnserver *server, if (*ua_num > 0) { *err_code = 420; - *reason = (const u08bits *)"Unknown attribute"; } else if (*err_code) { @@ -2296,7 +2286,6 @@ static int handle_turn_connection_bind(turn_turnserver *server, if(ss->to_be_closed) { *err_code = 400; - *reason = (const u08bits *)"Bad request"; } else if (is_allocation_valid(a)) { @@ -2343,7 +2332,6 @@ static int handle_turn_connection_bind(turn_turnserver *server, if (*ua_num > 0) { *err_code = 420; - *reason = (const u08bits *)"Unknown attribute"; } else if (*err_code) { @@ -2584,7 +2572,6 @@ static int handle_turn_channel_bind(turn_turnserver *server, if (*ua_num > 0) { *err_code = 420; - *reason = (const u08bits *)"Unknown attribute"; } else if (*err_code) { @@ -2798,7 +2785,6 @@ static int handle_turn_binding(turn_turnserver *server, if (*ua_num > 0) { *err_code = 420; - *reason = (const u08bits *)"Unknown attribute"; } else if (*err_code) { @@ -3286,7 +3272,6 @@ static int check_stun_auth(turn_turnserver *server, if(!sar) { *err_code = 401; - *reason = (const u08bits*)"Unauthorised"; return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); } @@ -3354,7 +3339,6 @@ static int check_stun_auth(turn_turnserver *server, if(!sar) { *err_code = 400; - *reason = (const u08bits*)"Bad request"; return -1; } @@ -3386,7 +3370,6 @@ static int check_stun_auth(turn_turnserver *server, if(!sar) { *err_code = 400; - *reason = (const u08bits*)"Bad request"; return -1; } @@ -3405,7 +3388,6 @@ static int check_stun_auth(turn_turnserver *server, *reason = (const u08bits*)"Allocation mismatch: wrong credentials"; } else { *err_code = 441; - *reason = (const u08bits*)"Wrong credentials"; } return -1; } @@ -3424,7 +3406,6 @@ static int check_stun_auth(turn_turnserver *server, if(!sar) { *err_code = 400; - *reason = (const u08bits*)"Bad request"; return -1; } @@ -3461,7 +3442,6 @@ static int check_stun_auth(turn_turnserver *server, "%s: Cannot find credentials of user <%s>\n", __FUNCTION__, (char*)usname); *err_code = 401; - *reason = (const u08bits*)"Unauthorised"; return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); } @@ -3480,7 +3460,6 @@ static int check_stun_auth(turn_turnserver *server, __FUNCTION__, (char*)usname); *err_code = SHA_TOO_WEAK_ERROR_CODE; *reason = SHA_TOO_WEAK_ERROR_REASON; - *reason = (const u08bits*)"Unauthorised: weak SHA function is used"; return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); } @@ -3495,7 +3474,6 @@ static int check_stun_auth(turn_turnserver *server, "%s: user %s credentials are incorrect\n", __FUNCTION__, (char*)usname); *err_code = 401; - *reason = (const u08bits*)"Unauthorised"; return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); } @@ -3528,7 +3506,6 @@ static void set_alternate_server(turn_server_addrs_list_t *asl, const ioa_addr * if(addr->ss.sa_family == local_addr->ss.sa_family) { *err_code = 300; - *reason = (const u08bits *)"Redirect"; size_t len = ioa_network_buffer_get_size(nbh); stun_init_error_response_str(method, ioa_network_buffer_data(nbh), &len, *err_code, *reason, tid); @@ -4329,7 +4306,7 @@ static int create_relay_connection(turn_turnserver* server, ioa_socket_tobeclosed(s)) { IOA_CLOSE_SOCKET(s); - *err_code = 508; + *err_code = 404; *reason = (const u08bits *)"Cannot find reserved socket"; return -1; } @@ -4389,7 +4366,7 @@ static int create_relay_connection(turn_turnserver* server, } else { IOA_CLOSE_SOCKET(newelem->s); IOA_CLOSE_SOCKET(rtcp_s); - *err_code = 508; + *err_code = 500; *reason = (const u08bits *)"Wrong reservation tokens (internal error)"; return -1; } From 4424b3c92a4f07ddbcd4cc738a7a6e43c4db7e2e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 11 Apr 2015 07:26:55 +0000 Subject: [PATCH 540/805] --sha256, --sha384, --sha512 parameters retired. --- ChangeLog | 1 + README.turnserver | 11 ----- examples/etc/turnserver.conf | 12 ----- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 19 +------- man/man1/turnutils.1 | 2 +- src/apps/relay/dbdrivers/dbd_mongo.c | 2 +- src/apps/relay/dbdrivers/dbd_mysql.c | 2 +- src/apps/relay/dbdrivers/dbd_pgsql.c | 2 +- src/apps/relay/dbdrivers/dbd_redis.c | 2 +- src/apps/relay/dbdrivers/dbd_sqlite.c | 2 +- src/apps/relay/mainrelay.c | 48 +------------------- src/apps/relay/mainrelay.h | 1 - src/apps/relay/netengine.c | 2 +- src/apps/relay/turn_admin_server.c | 32 +------------- src/apps/relay/userdb.c | 51 ++++------------------ src/apps/uclient/mainuclient.c | 2 +- src/apps/uclient/session.h | 1 - src/apps/uclient/startuclient.c | 50 --------------------- src/apps/uclient/uclient.c | 24 +++------- src/client/ns_turn_msg.c | 26 ++--------- src/client/ns_turn_msg.h | 2 +- src/client/ns_turn_msg_defs_new.h | 7 +-- src/server/ns_turn_server.c | 63 +++------------------------ src/server/ns_turn_server.h | 2 - 25 files changed, 40 insertions(+), 328 deletions(-) diff --git a/ChangeLog b/ChangeLog index ab0b7779..eca06aa9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 4/9/2015 Oleg Moskalenko Version 4.4.5.1 'Ardee West': - dual allocation adjusted according to the new TURN-bis draft; + - options sha256, sha384, sha512 retired as non-standard ones; - C++ fixes; - cosmetic fixes; diff --git a/README.turnserver b/README.turnserver index ebdb9d47..01ac596a 100644 --- a/README.turnserver +++ b/README.turnserver @@ -236,17 +236,6 @@ Flags: --no-multicast-peers Disallow peers on well-known broadcast addresses (224.0.0.0 and above, and FFXX:*). ---sha256 Require SHA256 digest function to be used for the message integrity. - By default, the server uses SHA1 hashes. With this option, the server - requires the stronger SHA256 hashes. The client application must support - SHA256 hash function if this option is used. If the server obtains a message - from the client with a weaker (SHA1) hash function then the server returns - error code 426. - ---sha384 Require SHA384 digest function to be used for the message integrity. - ---sha512 Require SHA512 digest function to be used for the message integrity. - --mobility Mobility with ICE (MICE) specs support. --no-cli Turn OFF the CLI support. By default it is always ON. diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 2b11db7a..3c2d828f 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -557,18 +557,6 @@ # #secure-stun -# Require SHA256, or SHA384, or SHA512 digest function to be used for the message -# integrity. By default, the server uses SHA1 (as per TURN standard specs). -# With this option, the server always requires the stronger SHA256, SHA384 or SHA512 -# function. The client application must support SHA256, SHA384 or SHA512 hash function -# if this option is used. If the server obtains -# a message from the client with a weaker (SHA1) hash function then the -# server returns error code 426. -# -#sha256 -#sha384 -#sha512 - # Mobility with ICE (MICE) specs support. # #mobility diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 249d9b03..9d187dcc 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "21 March 2015" "" "" +.TH TURN 1 "10 April 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 7f4d0c0c..f2361d82 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "21 March 2015" "" "" +.TH TURN 1 "10 April 2015" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -363,23 +363,6 @@ Disallow peers on well\-known broadcast addresses (224.0.0.0 and above, and FFXX:*). .TP .B -\fB\-\-sha256\fP -Require SHA256 digest function to be used for the message integrity. -By default, the server uses SHA1 hashes. With this option, the server -requires the stronger SHA256 hashes. The client application must support -SHA256 hash function if this option is used. If the server obtains a message -from the client with a weaker (SHA1) hash function then the server returns -error code 426. -.TP -.B -\fB\-\-sha384\fP -Require SHA384 digest function to be used for the message integrity. -.TP -.B -\fB\-\-sha512\fP -Require SHA512 digest function to be used for the message integrity. -.TP -.B \fB\-\-mobility\fP Mobility with ICE (MICE) specs support. .TP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 2c3e03d4..996a8dc1 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "21 March 2015" "" "" +.TH TURN 1 "10 April 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index 48a31052..abcf0b6d 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -216,7 +216,7 @@ static int mongo_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) { if (mongoc_cursor_next(cursor, &item)) { if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "hmackey") && BSON_ITER_HOLDS_UTF8(&iter)) { value = bson_iter_utf8(&iter, &length); - size_t sz = get_hmackey_size(turn_params.shatype) * 2; + size_t sz = get_hmackey_size(SHATYPE_DEFAULT) * 2; if(length < sz) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key format: string length=%d (must be %d): user %s\n", (int)length, (int)sz, usname); } else { diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 73ecfc96..7ca45cc7 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -315,7 +315,7 @@ static int mysql_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) { if(row && row[0]) { unsigned long *lengths = mysql_fetch_lengths(mres); if(lengths) { - size_t sz = get_hmackey_size(turn_params.shatype)*2; + size_t sz = get_hmackey_size(SHATYPE_DEFAULT)*2; if(lengths[0]type != REDIS_REPLY_NIL) TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type); } else { - size_t sz = get_hmackey_size(turn_params.shatype); + size_t sz = get_hmackey_size(SHATYPE_DEFAULT); if(strlen(rget->str)str,usname); } else if(convert_string_key_to_binary(rget->str, key, sz)<0) { diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 79aca9aa..8b928c2a 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -266,7 +266,7 @@ static int sqlite_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) int res = sqlite3_step(st); if (res == SQLITE_ROW) { char *kval = turn_strdup((const char*) sqlite3_column_text(st, 0)); - size_t sz = get_hmackey_size(turn_params.shatype); + size_t sz = get_hmackey_size(SHATYPE_DEFAULT); if (convert_string_key_to_binary(kval, key, sz) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key: %s, user %s\n", kval, usname); } else { diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index eca7c6af..df26bca6 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -117,7 +117,7 @@ LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,0,"", /////////////// stop server //////////////// 0, /////////////// MISC PARAMS //////////////// -0,0,0,0,0,SHATYPE_SHA1,':',0,0,TURN_CREDENTIALS_NONE,0,0,0,0,0,0, +0,0,0,0,0,':',0,0,TURN_CREDENTIALS_NONE,0,0,0,0,0,0, ///////////// Users DB ////////////// { (TURN_USERDB_TYPE)0, {"\0"}, {0,NULL, {NULL,0}} }, ///////////// CPUs ////////////////// @@ -562,15 +562,6 @@ static char Usage[] = "Usage: turnserver [options]\n" " /var/tmp/turnserver.pid .\n" " --secure-stun Require authentication of the STUN Binding request.\n" " By default, the clients are allowed anonymous access to the STUN Binding functionality.\n" -" --sha256 Require SHA256 digest function to be used for the message integrity.\n" -" By default, the server SHA1 (as per TURN standard specs).\n" -" With this option, the server\n" -" requires the stronger SHA256 function. The client application must\n" -" support SHA256 hash function if this option is used. If the server obtains\n" -" a message from the client with a weaker (SHA1) hash function then the server\n" -" returns error code 426.\n" -" --sha384 Require SHA384 digest function to be used for the message integrity.\n" -" --sha512 Require SHA512 digest function to be used for the message integrity.\n" " --proc-user User name to run the turnserver process.\n" " After the initialization, the turnserver process\n" " will make an attempt to change the current user ID to that user.\n" @@ -645,10 +636,6 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\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" #endif - " -H, --sha256 Use SHA256 digest function to be used for the message integrity.\n" - " By default, the server SHA1 (as per TURN standard specs).\n" - " -Y, --sha384 Use SHA384 digest function to be used for the message integrity.\n" - " -K, --sha512 Use SHA512 digest function to be used for the message integrity.\n" " --max-bps Set value of realm's max-bps parameter.\n" " Setting to zero value means removal of the option.\n" " --total-quota Set value of realm's total-quota parameter.\n" @@ -698,9 +685,6 @@ enum EXTRA_OPTS { SECURE_STUN_OPT, CA_FILE_OPT, DH_FILE_OPT, - SHA256_OPT, - SHA384_OPT, - SHA512_OPT, NO_STUN_OPT, PROC_USER_OPT, PROC_GROUP_OPT, @@ -823,9 +807,6 @@ static const struct myoption long_options[] = { { "secure-stun", optional_argument, NULL, SECURE_STUN_OPT }, { "CA-file", required_argument, NULL, CA_FILE_OPT }, { "dh-file", required_argument, NULL, DH_FILE_OPT }, - { "sha256", optional_argument, NULL, SHA256_OPT }, - { "sha384", optional_argument, NULL, SHA384_OPT }, - { "sha512", optional_argument, NULL, SHA512_OPT }, { "proc-user", required_argument, NULL, PROC_USER_OPT }, { "proc-group", required_argument, NULL, PROC_GROUP_OPT }, { "mobility", optional_argument, NULL, MOBILITY_OPT }, @@ -880,9 +861,6 @@ static const struct myoption admin_long_options[] = { { "user", required_argument, NULL, 'u' }, { "realm", required_argument, NULL, 'r' }, { "password", required_argument, NULL, 'p' }, - { "sha256", no_argument, NULL, 'H' }, - { "sha384", no_argument, NULL, 'Y' }, - { "sha512", no_argument, NULL, 'K' }, { "add-origin", no_argument, NULL, 'O' }, { "del-origin", no_argument, NULL, 'R' }, { "list-origins", required_argument, NULL, 'I' }, @@ -1046,18 +1024,6 @@ static void set_option(int c, char *value) case SECURE_STUN_OPT: turn_params.secure_stun = get_bool_value(value); break; - case SHA256_OPT: - if(get_bool_value(value)) - turn_params.shatype = SHATYPE_SHA256; - break; - case SHA384_OPT: - if(get_bool_value(value)) - turn_params.shatype = SHATYPE_SHA384; - break; - case SHA512_OPT: - if(get_bool_value(value)) - turn_params.shatype = SHATYPE_SHA512; - break; case NO_MULTICAST_PEERS_OPT: turn_params.no_multicast_peers = get_bool_value(value); break; @@ -1592,18 +1558,6 @@ static int adminmain(int argc, char **argv) exit(0); } break; - case 'H': - if(get_bool_value(optarg)) - turn_params.shatype = SHATYPE_SHA256; - break; - case 'Y': - if(get_bool_value(optarg)) - turn_params.shatype = SHATYPE_SHA384; - break; - case 'K': - if(get_bool_value(optarg)) - turn_params.shatype = SHATYPE_SHA512; - break; case 'h': printf("\n%s\n", AdminUsage); exit(0); diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index b2f8033e..3f2ecf74 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -291,7 +291,6 @@ typedef struct _turn_params_ { vint secure_stun; int server_relay; int fingerprint; - SHATYPE shatype; char rest_api_separator; vint stale_nonce; vint mobility; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 3f71bfb6..7daf9187 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1642,7 +1642,7 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int &turn_params.no_multicast_peers, &turn_params.no_loopback_peers, &turn_params.ip_whitelist, &turn_params.ip_blacklist, send_socket_to_relay, - &turn_params.secure_stun, turn_params.shatype, &turn_params.mobility, + &turn_params.secure_stun, &turn_params.mobility, turn_params.server_relay, send_turn_session_info, send_https_socket, diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 1e9aeeda..d3317947 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -691,16 +691,6 @@ static void cli_print_configuration(struct cli_session* cs) cli_print_str(cs,turn_params.cert_file,"Certificate file",0); cli_print_str(cs,turn_params.pkey_file,"Private Key file",0); - if(turn_params.shatype == SHATYPE_SHA256) - cli_print_str(cs,"SHA256","SHA type",0); - else if(turn_params.shatype == SHATYPE_SHA384) - cli_print_str(cs,"SHA384","SHA type",0); - else if(turn_params.shatype == SHATYPE_SHA512) - cli_print_str(cs,"SHA512","SHA type",0); - else - cli_print_str(cs,"SHA1","SHA type",0); - myprintf(cs,"\n"); - cli_print_str_array(cs,turn_params.listener.addrs,turn_params.listener.addrs_number,"Listener addr",0); if(turn_params.listener_ifname[0]) @@ -1962,15 +1952,6 @@ static void write_pc_page(ioa_socket_handle s) https_print_str(sb,turn_params.cert_file,"Certificate file",0); https_print_str(sb,turn_params.pkey_file,"Private Key file",0); - if(turn_params.shatype == SHATYPE_SHA256) - https_print_str(sb,"SHA256","SHA type",0); - else if(turn_params.shatype == SHATYPE_SHA384) - https_print_str(sb,"SHA384","SHA type",0); - else if(turn_params.shatype == SHATYPE_SHA512) - https_print_str(sb,"SHA512","SHA type",0); - else - https_print_str(sb,"SHA1","SHA type",0); - https_print_empty_row(sb,2); https_print_str_array(sb,turn_params.listener.addrs,turn_params.listener.addrs_number,"Listener addr"); @@ -2495,15 +2476,6 @@ static void write_users_page(ioa_socket_handle s, const u08bits *add_user, const str_buffer_append(sb,"\""); str_buffer_append(sb,">

\r\n"); - if(turn_params.shatype == SHATYPE_SHA256) - str_buffer_append(sb,"SHA type: SHA256
\r\n"); - else if(turn_params.shatype == SHATYPE_SHA384) - str_buffer_append(sb,"SHA type: SHA384
\r\n"); - else if(turn_params.shatype == SHATYPE_SHA512) - str_buffer_append(sb,"SHA type: SHA512
\r\n"); - else - str_buffer_append(sb,"SHA type: SHA1
\r\n"); - str_buffer_append(sb,"
"); str_buffer_append(sb,"\r\n"); @@ -3491,9 +3463,9 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) STRCPY(u,add_user); STRCPY(r,add_realm); STRCPY(p,pwd); - stun_produce_integrity_key_str(u, r, p, key, turn_params.shatype); + stun_produce_integrity_key_str(u, r, p, key, SHATYPE_DEFAULT); size_t i = 0; - size_t sz = get_hmackey_size(turn_params.shatype); + size_t sz = get_hmackey_size(SHATYPE_DEFAULT); int maxsz = (int) (sz * 2) + 1; char *s = skey; for (i = 0; (i < sz) && (maxsz > 2); i++) { diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index e846cb02..dd823383 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -484,29 +484,10 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u switch(dot.enc_block.key_length) { case SHA1SIZEBYTES: - if(turn_params.shatype != SHATYPE_SHA1) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(1): %d\n",(int)dot.enc_block.key_length); - return -1; - } break; case SHA256SIZEBYTES: - if(turn_params.shatype != SHATYPE_SHA256) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(2): %d\n",(int)dot.enc_block.key_length); - return -1; - } - break; case SHA384SIZEBYTES: - if(turn_params.shatype != SHATYPE_SHA384) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(3): %d\n",(int)dot.enc_block.key_length); - return -1; - } - break; case SHA512SIZEBYTES: - if(turn_params.shatype != SHATYPE_SHA512) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(3): %d\n",(int)dot.enc_block.key_length); - return -1; - } - break; default: TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(3): %d\n",(int)dot.enc_block.key_length); return -1; @@ -518,7 +499,7 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u ioa_network_buffer_get_size(nbh), dot.enc_block.mac_key, pwdtmp, - turn_params.shatype,NULL)>0) { + SHATYPE_DEFAULT)>0) { turn_time_t lifetime = (turn_time_t)(dot.enc_block.lifetime); if(lifetime) { @@ -578,25 +559,11 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u int sarlen = stun_attr_get_len(sar); switch(sarlen) { case SHA1SIZEBYTES: - if(turn_params.shatype != SHATYPE_SHA1) - return -1; hmac_len = SHA1SIZEBYTES; break; case SHA256SIZEBYTES: - if(turn_params.shatype != SHATYPE_SHA256) - return -1; - hmac_len = SHA256SIZEBYTES; - break; case SHA384SIZEBYTES: - if(turn_params.shatype != SHATYPE_SHA384) - return -1; - hmac_len = SHA384SIZEBYTES; - break; case SHA512SIZEBYTES: - if(turn_params.shatype != SHATYPE_SHA512) - return -1; - hmac_len = SHA512SIZEBYTES; - break; default: return -1; }; @@ -606,7 +573,7 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u const char* secret = get_secrets_list_elem(&sl,sll); if(secret) { - if(stun_calculate_hmac(usname, strlen((char*)usname), (const u08bits*)secret, strlen(secret), hmac, &hmac_len, turn_params.shatype)>=0) { + if(stun_calculate_hmac(usname, strlen((char*)usname), (const u08bits*)secret, strlen(secret), hmac, &hmac_len, SHATYPE_DEFAULT)>=0) { size_t pwd_length = 0; char *pwd = base64_encode(hmac,hmac_len,&pwd_length); @@ -614,14 +581,14 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u if(pwd_length<1) { turn_free(pwd,strlen(pwd)+1); } else { - if(stun_produce_integrity_key_str((u08bits*)usname, realm, (u08bits*)pwd, key, turn_params.shatype)>=0) { + if(stun_produce_integrity_key_str((u08bits*)usname, realm, (u08bits*)pwd, key, SHATYPE_DEFAULT)>=0) { if(stun_check_message_integrity_by_key_str(TURN_CREDENTIALS_LONG_TERM, ioa_network_buffer_data(nbh), ioa_network_buffer_get_size(nbh), key, pwdtmp, - turn_params.shatype,NULL)>0) { + SHATYPE_DEFAULT)>0) { ret = 0; } @@ -650,7 +617,7 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u ur_string_map_unlock(turn_params.default_users_db.ram_db.static_accounts); if(ret==0) { - size_t sz = get_hmackey_size(turn_params.shatype); + size_t sz = get_hmackey_size(SHATYPE_DEFAULT); ns_bcopy(ukey,key,sz); return 0; } @@ -762,7 +729,7 @@ int add_static_user_account(char *user) hmackey_t *key = (hmackey_t*)turn_malloc(sizeof(hmackey_t)); if(strstr(s,"0x")==s) { char *keysource = s + 2; - size_t sz = get_hmackey_size(turn_params.shatype); + size_t sz = get_hmackey_size(SHATYPE_DEFAULT); if(strlen(keysource)options.name, (u08bits*)s, *key, turn_params.shatype); + stun_produce_integrity_key_str((u08bits*)usname, (u08bits*)get_realm(NULL)->options.name, (u08bits*)s, *key, SHATYPE_DEFAULT); } { ur_string_map_lock(turn_params.default_users_db.ram_db.static_accounts); @@ -973,9 +940,9 @@ int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08b must_set_admin_pwd(pwd); { - stun_produce_integrity_key_str(user, realm, pwd, key, turn_params.shatype); + stun_produce_integrity_key_str(user, realm, pwd, key, SHATYPE_DEFAULT); size_t i = 0; - size_t sz = get_hmackey_size(turn_params.shatype); + size_t sz = get_hmackey_size(SHATYPE_DEFAULT); int maxsz = (int) (sz * 2) + 1; char *s = skey; for (i = 0; (i < sz) && (maxsz > 2); i++) { diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index d7ef3554..53f45f9d 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -84,7 +84,7 @@ int negative_protocol_test = 0; int dos = 0; int random_disconnect = 0; -SHATYPE shatype = SHATYPE_SHA1; +SHATYPE shatype = SHATYPE_DEFAULT; int mobility = 0; diff --git a/src/apps/uclient/session.h b/src/apps/uclient/session.h index a4149865..6e394c88 100644 --- a/src/apps/uclient/session.h +++ b/src/apps/uclient/session.h @@ -91,7 +91,6 @@ typedef struct { app_tcp_conn_info **tcp_conn; size_t tcp_conn_number; int is_peer; - SHATYPE shatype; char s_mobile_id[33]; } app_ur_conn_info; diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 60bdaa2a..74d6a978 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -526,16 +526,6 @@ static int clnet_allocate(int verbose, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { - if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { - clnet_info->shatype = SHATYPE_SHA256; - recalculate_restapi_hmac(clnet_info->shatype); - } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) { - clnet_info->shatype = SHATYPE_SHA384; - recalculate_restapi_hmac(clnet_info->shatype); - } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA384)) { - clnet_info->shatype = SHATYPE_SHA512; - recalculate_restapi_hmac(clnet_info->shatype); - } goto beg_allocate; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { @@ -730,16 +720,6 @@ static int clnet_allocate(int verbose, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { - if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { - clnet_info->shatype = SHATYPE_SHA256; - recalculate_restapi_hmac(clnet_info->shatype); - } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) { - clnet_info->shatype = SHATYPE_SHA384; - recalculate_restapi_hmac(clnet_info->shatype); - } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA384)) { - clnet_info->shatype = SHATYPE_SHA512; - recalculate_restapi_hmac(clnet_info->shatype); - } goto beg_refresh; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { refresh_received = 1; @@ -834,16 +814,6 @@ static int turn_channel_bind(int verbose, uint16_t *chn, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { - if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { - clnet_info->shatype = SHATYPE_SHA256; - recalculate_restapi_hmac(clnet_info->shatype); - } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) { - clnet_info->shatype = SHATYPE_SHA384; - recalculate_restapi_hmac(clnet_info->shatype); - } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA384)) { - clnet_info->shatype = SHATYPE_SHA512; - recalculate_restapi_hmac(clnet_info->shatype); - } goto beg_bind; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { cb_received = 1; @@ -948,16 +918,6 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { - if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { - clnet_info->shatype = SHATYPE_SHA256; - recalculate_restapi_hmac(clnet_info->shatype); - } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) { - clnet_info->shatype = SHATYPE_SHA384; - recalculate_restapi_hmac(clnet_info->shatype); - } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA384)) { - clnet_info->shatype = SHATYPE_SHA512; - recalculate_restapi_hmac(clnet_info->shatype); - } goto beg_cp; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { cp_received = 1; @@ -1533,16 +1493,6 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { - if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) { - clnet_info->shatype = SHATYPE_SHA256; - recalculate_restapi_hmac(clnet_info->shatype); - } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) { - clnet_info->shatype = SHATYPE_SHA384; - recalculate_restapi_hmac(clnet_info->shatype); - } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA384)) { - clnet_info->shatype = SHATYPE_SHA512; - recalculate_restapi_hmac(clnet_info->shatype); - } goto beg_cb; } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { cb_received = 1; diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index e55a6b30..6a32fd0d 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -119,7 +119,6 @@ static app_ur_session* init_app_session(app_ur_session *ss) { if(ss) { ns_bzero(ss,sizeof(app_ur_session)); ss->pinfo.fd=-1; - ss->pinfo.shatype = shatype; } return ss; } @@ -751,17 +750,6 @@ static int client_read(app_ur_session *elem, int is_tcp_data, app_tcp_conn_info &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { - if(err_code == SHA_TOO_WEAK_ERROR_CODE && (elem->pinfo.shatype == SHATYPE_SHA1)) { - elem->pinfo.shatype = SHATYPE_SHA256; - recalculate_restapi_hmac(elem->pinfo.shatype); - } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (elem->pinfo.shatype == SHATYPE_SHA256)) { - elem->pinfo.shatype = SHATYPE_SHA384; - recalculate_restapi_hmac(elem->pinfo.shatype); - } else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (elem->pinfo.shatype == SHATYPE_SHA384)) { - elem->pinfo.shatype = SHATYPE_SHA512; - recalculate_restapi_hmac(elem->pinfo.shatype); - } - if(is_TCP_relay() && (stun_get_method(&(elem->in_buffer)) == STUN_METHOD_CONNECT)) { turn_tcp_connect(clnet_verbose, &(elem->pinfo), &(elem->pinfo.peer_addr)); } else if(stun_get_method(&(elem->in_buffer)) == STUN_METHOD_REFRESH) { @@ -1008,7 +996,6 @@ static int start_client(const char *remote_address, int port, app_ur_conn_info clnet_info_probe; /* for load balancing probe */ ns_bzero(&clnet_info_probe,sizeof(clnet_info_probe)); clnet_info_probe.fd = -1; - clnet_info_probe.shatype = shatype; app_ur_conn_info *clnet_info=&(ss->pinfo); app_ur_conn_info *clnet_info_rtcp=NULL; @@ -1103,7 +1090,6 @@ static int start_c2c(const char *remote_address, int port, app_ur_conn_info clnet_info_probe; /* for load balancing probe */ ns_bzero(&clnet_info_probe,sizeof(clnet_info_probe)); clnet_info_probe.fd = -1; - clnet_info_probe.shatype = shatype; app_ur_conn_info *clnet_info1=&(ss1->pinfo); app_ur_conn_info *clnet_info1_rtcp=NULL; @@ -1652,7 +1638,7 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) } if(stun_attr_add_integrity_by_key_str(message->buf, (size_t*)&(message->len), (u08bits*)okey_array[cok].kid, - clnet_info->realm, clnet_info->key, clnet_info->nonce, clnet_info->shatype)<0) { + clnet_info->realm, clnet_info->key, clnet_info->nonce, shatype)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot add integrity to the message\n"); return -1; } @@ -1661,14 +1647,14 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) { 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) { + message->buf, (size_t)(message->len), clnet_info->key, pwd, shatype)<1) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR," Self-test of integrity does not comple correctly !\n"); return -1; } } } else { if(stun_attr_add_integrity_by_user_str(message->buf, (size_t*)&(message->len), g_uname, - clnet_info->realm, g_upwd, clnet_info->nonce, clnet_info->shatype)<0) { + clnet_info->realm, g_upwd, clnet_info->nonce, shatype)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot add integrity to the message\n"); return -1; } @@ -1680,14 +1666,14 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) int check_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) { - SHATYPE sht = clnet_info->shatype; + SHATYPE sht = shatype; if(oauth && clnet_info->oauth) { 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); + message->buf, (size_t)(message->len), clnet_info->key, pwd, sht); } else { diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index c562682b..c90dd4f9 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -467,7 +467,7 @@ int stun_is_challenge_response_str(const u08bits* buf, size_t len, int *err_code { int ret = stun_is_error_response_str(buf, len, err_code, err_msg, err_msg_size); - if(ret && (((*err_code) == 401) || ((*err_code) == 438) || ((*err_code) == SHA_TOO_WEAK_ERROR_CODE))) { + if(ret && (((*err_code) == 401) || ((*err_code) == 438) )) { stun_attr_ref sar = stun_attr_get_first_by_type_str(buf,len,STUN_ATTRIBUTE_REALM); if(sar) { @@ -1801,7 +1801,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, 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 res = 0; u08bits new_hmac[MAXSHASIZE]; @@ -1817,41 +1817,21 @@ int stun_check_message_integrity_by_key_str(turn_credential_type ct, u08bits *bu switch(sarlen) { case SHA256SIZEBYTES: shasize = SHA256SIZEBYTES; - if(shatype > SHATYPE_SHA256) { - if(too_weak) - *too_weak = 1; - return -1; - } if(shatype != SHATYPE_SHA256) return -1; break; case SHA384SIZEBYTES: shasize = SHA384SIZEBYTES; - if(shatype > SHATYPE_SHA384) { - if(too_weak) - *too_weak = 1; - return -1; - } if(shatype != SHATYPE_SHA384) return -1; break; case SHA512SIZEBYTES: shasize = SHA512SIZEBYTES; - if(shatype > SHATYPE_SHA512) { - if(too_weak) - *too_weak = 1; - return -1; - } if(shatype != SHATYPE_SHA512) return -1; break; case SHA1SIZEBYTES: shasize = SHA1SIZEBYTES; - if(shatype > SHATYPE_SHA1) { - if(too_weak) - *too_weak = 1; - return -1; - } if(shatype != SHATYPE_SHA1) return -1; break; @@ -1903,7 +1883,7 @@ int stun_check_message_integrity_str(turn_credential_type ct, u08bits *buf, size else if (stun_produce_integrity_key_str(uname, realm, upwd, key, shatype) < 0) return -1; - return stun_check_message_integrity_by_key_str(ct, buf, len, key, pwd, shatype, NULL); + return stun_check_message_integrity_by_key_str(ct, buf, len, key, pwd, shatype); } /* RFC 5780 */ diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 79494ae4..17d34851 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -181,7 +181,7 @@ 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, 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 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, 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); diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 9e5d2cf5..81bb51ab 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -44,7 +44,7 @@ /* <<== Bandwidth */ -/* SHA AGILITY ==>> */ +/* SHA ==>> */ #define SHA1SIZEBYTES (20) #define SHA256SIZEBYTES (32) @@ -66,10 +66,7 @@ typedef enum _SHATYPE SHATYPE; #define shatype_name(sht) ((sht == SHATYPE_SHA1) ? "SHA1" : ((sht == SHATYPE_SHA256) ? "SHA256" : ((sht == SHATYPE_SHA384) ? "SHA384" : "SHA512"))) -#define SHA_TOO_WEAK_ERROR_CODE (426) -#define SHA_TOO_WEAK_ERROR_REASON ((const u08bits*)("credentials too weak")) - -/* <<== SHA AGILITY */ +/* <<== SHA */ /* OAUTH TOKEN ENC ALG ==> */ diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index ab068e83..3cd62ca3 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1717,7 +1717,7 @@ static int handle_turn_refresh(turn_turnserver *server, } if(message_integrity) { - stun_attr_add_integrity_str(server->ct,ioa_network_buffer_data(nbh),&len,ss->hmackey,ss->pwd,server->shatype); + stun_attr_add_integrity_str(server->ct,ioa_network_buffer_data(nbh),&len,ss->hmackey,ss->pwd,SHATYPE_DEFAULT); ioa_network_buffer_set_size(nbh,len); } @@ -1980,7 +1980,7 @@ static void tcp_peer_connection_completed_callback(int success, void *arg) ioa_network_buffer_set_size(nbh,len); if(need_stun_authentication(server, ss)) { - stun_attr_add_integrity_str(server->ct,ioa_network_buffer_data(nbh),&len,ss->hmackey,ss->pwd,server->shatype); + stun_attr_add_integrity_str(server->ct,ioa_network_buffer_data(nbh),&len,ss->hmackey,ss->pwd,SHATYPE_DEFAULT); ioa_network_buffer_set_size(nbh,len); } @@ -2462,7 +2462,7 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co if(message_integrity && ss) { size_t len = ioa_network_buffer_get_size(nbh); - stun_attr_add_integrity_str(server->ct,ioa_network_buffer_data(nbh),&len,ss->hmackey,ss->pwd,server->shatype); + stun_attr_add_integrity_str(server->ct,ioa_network_buffer_data(nbh),&len,ss->hmackey,ss->pwd,SHATYPE_DEFAULT); ioa_network_buffer_set_size(nbh,len); } @@ -3280,49 +3280,10 @@ static int check_stun_auth(turn_turnserver *server, switch(sarlen) { case SHA1SIZEBYTES: - if(server->shatype > SHATYPE_SHA1) { - *err_code = SHA_TOO_WEAK_ERROR_CODE; - *reason = SHA_TOO_WEAK_ERROR_REASON; - return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); - } - if(server->shatype != SHATYPE_SHA1) { - *err_code = 401; - return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); - } break; case SHA256SIZEBYTES: - if(server->shatype > SHATYPE_SHA256) { - *err_code = SHA_TOO_WEAK_ERROR_CODE; - *reason = SHA_TOO_WEAK_ERROR_REASON; - return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); - } - if(server->shatype != SHATYPE_SHA256) { - *err_code = 401; - return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); - } - break; case SHA384SIZEBYTES: - if(server->shatype > SHATYPE_SHA384) { - *err_code = SHA_TOO_WEAK_ERROR_CODE; - *reason = SHA_TOO_WEAK_ERROR_REASON; - return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); - } - if(server->shatype != SHATYPE_SHA384) { - *err_code = 401; - return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); - } - break; case SHA512SIZEBYTES: - if(server->shatype > SHATYPE_SHA512) { - *err_code = SHA_TOO_WEAK_ERROR_CODE; - *reason = SHA_TOO_WEAK_ERROR_REASON; - return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); - } - if(server->shatype != SHATYPE_SHA512) { - *err_code = 401; - return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); - } - break; default: *err_code = 401; return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); @@ -3446,22 +3407,11 @@ static int check_stun_auth(turn_turnserver *server, } /* Check integrity */ - int too_weak = 0; if(stun_check_message_integrity_by_key_str(server->ct,ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh), ss->hmackey, ss->pwd, - server->shatype, - &too_weak)<1) { - - if(too_weak) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, - "%s: user %s credentials are incorrect: SHA function is too weak\n", - __FUNCTION__, (char*)usname); - *err_code = SHA_TOO_WEAK_ERROR_CODE; - *reason = SHA_TOO_WEAK_ERROR_REASON; - return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method); - } + SHATYPE_DEFAULT)<1) { if(can_resume) { (server->userkeycb)(server->id, server->ct, server->oauth, &(ss->oauth), usname, realm, resume_processing_after_username_check, in_buffer, ss->id, postpone_reply); @@ -3907,7 +3857,7 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss, if(message_integrity) { size_t len = ioa_network_buffer_get_size(nbh); - stun_attr_add_integrity_str(server->ct,ioa_network_buffer_data(nbh),&len,ss->hmackey,ss->pwd,server->shatype); + stun_attr_add_integrity_str(server->ct,ioa_network_buffer_data(nbh),&len,ss->hmackey,ss->pwd,SHATYPE_DEFAULT); ioa_network_buffer_set_size(nbh,len); } @@ -4840,7 +4790,7 @@ void init_turn_server(turn_turnserver* server, vintp no_multicast_peers, vintp no_loopback_peers, ip_range_list_t* ip_whitelist, ip_range_list_t* ip_blacklist, send_socket_to_relay_cb send_socket_to_relay, - vintp secure_stun, SHATYPE shatype, vintp mobility, int server_relay, + vintp secure_stun, 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, @@ -4864,7 +4814,6 @@ void init_turn_server(turn_turnserver* server, server->no_multicast_peers = no_multicast_peers; server->no_loopback_peers = no_loopback_peers; server->secure_stun = secure_stun; - server->shatype = shatype; server->mobility = mobility; server->server_relay = server_relay; server->send_turn_session_info = send_turn_session_info; diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index 1a767391..e976a070 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -118,7 +118,6 @@ struct _turn_turnserver { vintp stun_only; vintp no_stun; vintp secure_stun; - SHATYPE shatype; turn_credential_type ct; get_alt_addr_cb alt_addr_cb; send_message_cb sm_cb; @@ -197,7 +196,6 @@ void init_turn_server(turn_turnserver* server, ip_range_list_t* ip_blacklist, 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, From 676843bf0942b661f7268c7a58aed875c54f0c4e Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sat, 11 Apr 2015 07:53:30 +0000 Subject: [PATCH 541/805] retiring --sha256, etc --- INSTALL | 19 ++------------ README.turnadmin | 5 ---- README.turnutils | 7 ----- man/man1/turnadmin.1 | 16 +----------- man/man1/turnserver.1 | 2 +- man/man1/turnutils.1 | 15 +---------- src/apps/uclient/mainuclient.c | 48 +--------------------------------- src/apps/uclient/uclient.h | 2 -- 8 files changed, 6 insertions(+), 108 deletions(-) diff --git a/INSTALL b/INSTALL index 90c34bcf..8e1a285e 100644 --- a/INSTALL +++ b/INSTALL @@ -470,7 +470,7 @@ libevent2 from their web site. It was tested with older *NIXes NOTE: SQLite must be of version 3.x. -NOTE: For extra security features (DTLS and SHA256 and and SHA384 and SHA512) +NOTE: For extra security features (like DTLS) support, OpenSSL version 1.0.0a or newer is recommended. Older versions do not support DTLS, reliably, in some cases. For example, the Debian 'Squeeze' Linux supplies 0.9.8 version of OpenSSL, that does not work correctly with @@ -683,10 +683,7 @@ security reasons. Storing only the HMAC key has its own implications - if you change the realm, you will have to update the HMAC keys of all users, because the realm is used for the HMAC key generation. -The key must be up to 32 characters (HEX representation of 16 bytes) for SHA1, -or up to 64 characters (HEX representation of 32 bytes) for SHA256, -or up to 96 characters (HEX representation of 48 bytes) for SHA384, -or up to 128 characters (HEX representation of 64 bytes) for SHA512: +The key must be up to 32 characters (HEX representation of 16 bytes) for SHA1: # Table holding shared secrets for secret-based authorization # (REST API). Shared secret can be stored either in unsecure open @@ -827,9 +824,6 @@ Fill in users, for example: $ bin/turnadmin -a -b "/var/db/turndb" -u gorst -r north.gov -p hero $ bin/turnadmin -a -b "/var/db/turndb" -u ninefingers -r north.gov -p youhavetoberealistic - Long-term credentials mechanism with SHA256 extension: - $ bin/turnadmin -a -b "/var/db/turndb" -u bethod -r north.gov -p king-of-north --sha256 - Admin users: $ bin/turnadmin -A -b "/var/db/turndb" -u gorst -p hero @@ -954,9 +948,6 @@ Fill in users, for example: $ bin/turnadmin -a -e "host=localhost dbname=coturn user=turn password=turn" -u gorst -r north.gov -p hero $ bin/turnadmin -a -e "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic - 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 - Admin users: $ bin/turnadmin -A -e "host=localhost dbname=coturn user=turn password=turn" -u gorst -p hero @@ -1009,9 +1000,6 @@ the root account. $ bin/turnadmin -a -M "host=localhost dbname=coturn user=turn password=turn" -u gorst -r north.gov -p hero $ bin/turnadmin -a -M "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic - 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 - Admin users: $ bin/turnadmin -A -M "host=localhost dbname=coturn user=turn password=turn" -u gorst -p hero @@ -1138,9 +1126,6 @@ Redis TURN admin commands: $ bin/turnadmin -a -N "host=localhost dbname=2 user=turn password=turn" -u gorst -r north.gov -p hero $ bin/turnadmin -a -N "host=localhost dbname=2 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic - 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 - Admin users: $ bin/turnadmin -A -N "host=localhost dbname=2 user=turn password=turn" -u gorst -p hero diff --git a/README.turnadmin b/README.turnadmin index 8e303687..f76aaeef 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -104,11 +104,6 @@ Options with required values: -r, --realm Realm. -p, --password Password. -o, --origin Origin --H, --sha256 Use SHA256 as the keys hash function (a non-standard feature). - By default, MD5 is used for the key storage encryption - (as required by the current STUN/TURNstandards). --Y, --sha384 Use SHA384 as the keys hash function (a non-standard feature). --K, --sha512 Use SHA512 as the keys hash function (a non-standard feature). --max-bps Set value of realm's max-bps parameter. --total-quota Set value of realm's total-quota parameter. --user-quota Set value of realm's user-quota parameter. diff --git a/README.turnutils b/README.turnutils index 65c332bb..bb4ed688 100644 --- a/README.turnutils +++ b/README.turnutils @@ -94,13 +94,6 @@ Flags: -R do negative protocol tests. -O DOS attack mode. - --H SHA256 digest function for message integrity calculation. - Without this option, by default, SHA1 is used. - --Y SHA384 digest function for message integrity calculation. - --K SHA512 digest function for message integrity calculation. -M Use TURN ICE Mobility. diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 9d187dcc..54a36fc0 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "10 April 2015" "" "" +.TH TURN 1 "11 April 2015" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage @@ -184,20 +184,6 @@ Password. Origin .TP .B -\fB\-H\fP, \fB\-\-sha256\fP -Use SHA256 as the keys hash function (a non\-standard feature). -By default, MD5 is used for the key storage encryption -(as required by the current STUN/TURNstandards). -.TP -.B -\fB\-Y\fP, \fB\-\-sha384\fP -Use SHA384 as the keys hash function (a non\-standard feature). -.TP -.B -\fB\-K\fP, \fB\-\-sha512\fP -Use SHA512 as the keys hash function (a non\-standard feature). -.TP -.B \fB\-\-max\-bps\fP Set value of realm's max\-bps parameter. .TP diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index f2361d82..a05d8369 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "10 April 2015" "" "" +.TH TURN 1 "11 April 2015" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 996a8dc1..6148da32 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "10 April 2015" "" "" +.TH TURN 1 "11 April 2015" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -143,19 +143,6 @@ do negative protocol tests. DOS attack mode. .TP .B -\fB\-H\fP -SHA256 digest function for message integrity calculation. -Without this option, by default, SHA1 is used. -.TP -.B -\fB\-Y\fP -SHA384 digest function for message integrity calculation. -.TP -.B -\fB\-K\fP -SHA512 digest function for message integrity calculation. -.TP -.B \fB\-M\fP Use TURN ICE Mobility. .TP diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 53f45f9d..a16cb43d 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -131,10 +131,6 @@ static char Usage[] = " -N Negative tests (some limited cases only).\n" " -R Negative protocol tests.\n" " -O DOS attack mode (quick connect and exit).\n" - " -H SHA256 digest function for message integrity calculation.\n" - " Without this option, by default, SHA1 is used.\n" - " -Y SHA384 digest function for message integrity calculation.\n" - " -K SHA512 digest function for message integrity calculation.\n" " -M ICE Mobility engaged.\n" " -I Do not set permissions on TURN relay endpoints\n" " (for testing the non-standard server relay functionality).\n" @@ -166,39 +162,6 @@ static char Usage[] = ////////////////////////////////////////////////// -void recalculate_restapi_hmac(SHATYPE st) { - - if (g_use_auth_secret_with_timestamp) { - - u08bits hmac[MAXSHASIZE]; - unsigned int hmac_len = 0; - - if(st == SHATYPE_SHA256) - hmac_len = SHA256SIZEBYTES; - else if(st == SHATYPE_SHA384) - hmac_len = SHA384SIZEBYTES; - else if(st == SHATYPE_SHA512) - hmac_len = SHA512SIZEBYTES; - - hmac[0] = 0; - - if (stun_calculate_hmac(g_uname, strlen((char*) g_uname), - (u08bits*) g_auth_secret, strlen(g_auth_secret), hmac, - &hmac_len, st) >= 0) { - size_t pwd_length = 0; - char *pwd = base64_encode(hmac, hmac_len, &pwd_length); - - if (pwd) { - if (pwd_length > 0) { - ns_bcopy(pwd,g_upwd,pwd_length); - g_upwd[pwd_length] = 0; - } - } - turn_free(pwd,strlen(pwd)+1); - } - } -} - int main(int argc, char **argv) { int port = 0; @@ -220,7 +183,7 @@ int main(int argc, char **argv) ns_bzero(local_addr, sizeof(local_addr)); - while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:bZvsyhcxXgtTSAPDNOUHYKMRIGBJ")) != -1) { + while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:bZvsyhcxXgtTSAPDNOUMRIGBJ")) != -1) { switch (c){ case 'J': { @@ -271,15 +234,6 @@ int main(int argc, char **argv) case 'M': mobility = 1; break; - case 'H': - shatype = SHATYPE_SHA256; - break; - case 'Y': - shatype = SHATYPE_SHA384; - break; - case 'K': - shatype = SHATYPE_SHA512; - break; case 'E': { char* fn = find_config_file(optarg,1); diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index decef5ec..5531a33c 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -110,8 +110,6 @@ turn_credential_type get_turn_credentials_type(void); int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message); int check_integrity(app_ur_conn_info *clnet_info, stun_buffer *message); -void recalculate_restapi_hmac(SHATYPE st); - SOCKET_TYPE get_socket_type(void); //////////////////////////////////////////// From 86f40b4bd9ff5e186be0f180f94607a91ec140e8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 19 Apr 2015 06:18:28 +0000 Subject: [PATCH 542/805] working on third-party auth --- ChangeLog | 4 +- INSTALL | 25 +- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/common/apputils.c | 2 - src/apps/common/apputils.h | 2 - src/apps/relay/dbdrivers/dbd_mongo.c | 28 +-- src/apps/relay/dbdrivers/dbd_mysql.c | 65 +++--- src/apps/relay/dbdrivers/dbd_pgsql.c | 40 ++-- src/apps/relay/dbdrivers/dbd_redis.c | 18 +- src/apps/relay/dbdrivers/dbd_sqlite.c | 38 ++- src/apps/relay/dbdrivers/dbdriver.h | 2 +- src/apps/relay/turn_admin_server.c | 162 ++----------- src/apps/relay/userdb.c | 20 +- src/apps/rfc5769/rfc5769check.c | 38 +-- src/apps/uclient/mainuclient.c | 6 +- src/client/ns_turn_msg.c | 323 +++++++------------------- src/client/ns_turn_msg_defs_new.h | 32 +-- src/server/ns_turn_server.c | 1 - turndb/schema.sql | 2 - turndb/schema.userdb.redis | 25 +- turndb/testmongosetup.sh | 14 +- turndb/testredisdbsetup.sh | 6 +- turndb/testsqldbsetup.sql | 6 +- 23 files changed, 226 insertions(+), 633 deletions(-) diff --git a/ChangeLog b/ChangeLog index eca06aa9..5509140e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,9 @@ 4/9/2015 Oleg Moskalenko Version 4.4.5.1 'Ardee West': - dual allocation adjusted according to the new TURN-bis draft; - - options sha256, sha384, sha512 retired as non-standard ones; + - options sha256, sha384, sha512 retired as non-standard; + - third-party authorization (oAuth) updated according to the + version 14 of the draft; - C++ fixes; - cosmetic fixes; diff --git a/INSTALL b/INSTALL index 8e1a285e..46433d92 100644 --- a/INSTALL +++ b/INSTALL @@ -743,10 +743,8 @@ CREATE TABLE oauth_key ( 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) ); @@ -764,30 +762,17 @@ The oauth_key table fields meanings are: lifetime - (optional) the key lifetime in seconds; the default value is 0 - unlimited lifetime. - - hkdf_hash_func - (optional) hash function for HKDF procedure; the - valid values are SHA-1, SHA-256, SHA-384 and SHA-512, - with SHA-256 as default. The hkdf_hash_func is not needed - if the as_rs_key and auth_key are defined explicitly - in the database; as_rs_alg - oAuth token encryption algorithm; the valid values are - "AES-128-CBC" and "AES-256-CBC", , "AEAD-AES-128-GCM", - "AEAD-AES-256-GCM". - The default value is "AES-256-CBC"; + "A256GCMKW", "A128GCMKW" (see + http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#section-4.1). + The default value is "A256GCMKW"; as_rs_key - (optional) base64-encoded AS-RS key. If not defined, then - calculated with ikm_key and hkdf_hash_func. The as_rs_key length - is defined by as_rs_alg. - - auth_alg - (optional) oAuth token authentication algorithm; the valid values are - "HMAC-SHA-256-128", "HMAC-SHA-256", "HMAC-SHA-384", - "HMAC-SHA-512" and "HMAC-SHA-1". - The default value is "HMAC-SHA-256-128". + calculated with ikm_key. 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. + calculated with ikm_key. Not used for AEAD algorithms. # Https access admin users. # Leave this table empty if you do not want diff --git a/examples/var/db/turndb b/examples/var/db/turndb index a186ae1937dc2022f80133ff5616307cd3fd536c..9b08dba57bc97b1b5f25a9a3ee567059c8ddc824 100644 GIT binary patch delta 416 zcmZqJz}T>Xae}nqP6h@BF(76IVkQuKqK+}+&W#DH`8kDwTp=K4-^?iShIx?)3m-3# z$ILu~f%y*e9_AUF1$nxdGnAM)B z!{wMb#35=*^D^`E65YcplZ*mw9Sw~v!179r9O9~AGxG9_N-`pi+$xjY!^)D||>{1s0%R zgC;imDK*K8vWv^hGq!M+Bqrsg<|mexWW;BuR>B$VlWYAXg|ahK6v`5dk~0#EG=Ton z)Zv=E%1?3f89$lHFM(LkUuklnzcLF*_vE#Ha-s!AnYoEYl?p(U6f}UEHMukm#U`Kk LH((T66u8Rp>0yqbWkrY zg1sq*{0F^y*hay-2anP}p=ZIPAPAygy4s`P%ftKYdw8Dr>;jx!fDg&*=NN`_d z2%CPk0M0L8e%v6VsEr`3O+ocLoW#TY2Lf!eosQFJ4xx;}&+r|T@gFF@TzXZU1_iXa zdLZq43fT9(J3#Zj9LW0~|GEe%CPfg*+w>kiv`pJlEAmJao|YO_kr#@0#m9{>@#Tl* zYE3Nj;kcL=1e{_+8c)---EHZ;zUk=ABYDs)$gfsZ@e%)zUn$p0fMWI*Qao+hj%zf9 zCl5wiMLyL|O8?Uf_4C3#3Y`Jr9D_gMH#mp0Fs3`PPw;?PUKm^EMNdKoEG~jHWWmZL zPC$lS$kTWni(+F8zllGGU%?@mV`Gr;z5aB3@E(L}YvQ#C^K3t0YpLLVo!fn5Z$ufE z1#fv*)w;T^4qZd(=%ZD!8O-X5IN32<+^Omu8>*8=#xq%p41U#j02w5u?JU_f+q!G^ zbk4L~{X}=Tmflu}U6;$Dk4C4}Rt$AuDD9zj9K4Vch}MvHBcwV|oI&ureruf!g@Yq0 hwXD!=i|jjQPjyBd^24Q(gAA3)$AX!Z12-mz#9y(loS^^! diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c index 0d3b7fe4..eecfcbc7 100644 --- a/src/apps/common/apputils.c +++ b/src/apps/common/apputils.c @@ -1125,8 +1125,6 @@ void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *o oakd->lifetime = raw->lifetime; ns_bcopy(raw->as_rs_alg,oakd->as_rs_alg,sizeof(oakd->as_rs_alg)); - ns_bcopy(raw->auth_alg,oakd->auth_alg,sizeof(oakd->auth_alg)); - ns_bcopy(raw->hkdf_hash_func,oakd->hkdf_hash_func,sizeof(oakd->hkdf_hash_func)); ns_bcopy(raw->kid,oakd->kid,sizeof(oakd->kid)); if(raw->ikm_key[0]) { diff --git a/src/apps/common/apputils.h b/src/apps/common/apputils.h index dd86d673..4b93d861 100644 --- a/src/apps/common/apputils.h +++ b/src/apps/common/apputils.h @@ -141,10 +141,8 @@ struct _oauth_key_data_raw { char ikm_key[OAUTH_KEY_SIZE+1]; u64bits timestamp; u32bits lifetime; - char hkdf_hash_func[OAUTH_HASH_FUNC_SIZE+1]; char as_rs_alg[OAUTH_ALG_SIZE+1]; char as_rs_key[OAUTH_KEY_SIZE+1]; - char auth_alg[OAUTH_ALG_SIZE+1]; char auth_key[OAUTH_KEY_SIZE+1]; }; diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index abcf0b6d..853a5524 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -256,9 +256,7 @@ static int mongo_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { BSON_APPEND_INT32(&fields, "timestamp", 1); BSON_APPEND_INT32(&fields, "as_rs_alg", 1); BSON_APPEND_INT32(&fields, "as_rs_key", 1); - BSON_APPEND_INT32(&fields, "auth_alg", 1); BSON_APPEND_INT32(&fields, "auth_key", 1); - BSON_APPEND_INT32(&fields, "hkdf_hash_func", 1); BSON_APPEND_INT32(&fields, "ikm_key", 1); mongoc_cursor_t * cursor; @@ -284,18 +282,12 @@ static int mongo_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "as_rs_key") && BSON_ITER_HOLDS_UTF8(&iter)) { STRCPY(key->as_rs_key,bson_iter_utf8(&iter, &length)); } - if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "auth_alg") && BSON_ITER_HOLDS_UTF8(&iter)) { - STRCPY(key->auth_alg,bson_iter_utf8(&iter, &length)); - } if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "auth_key") && BSON_ITER_HOLDS_UTF8(&iter)) { STRCPY(key->auth_key,bson_iter_utf8(&iter, &length)); } if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "ikm_key") && BSON_ITER_HOLDS_UTF8(&iter)) { STRCPY(key->ikm_key,bson_iter_utf8(&iter, &length)); } - if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "hkdf_hash_func") && BSON_ITER_HOLDS_UTF8(&iter)) { - STRCPY(key->hkdf_hash_func,bson_iter_utf8(&iter, &length)); - } if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "timestamp") && BSON_ITER_HOLDS_INT64(&iter)) { key->timestamp = (u64bits)bson_iter_int64(&iter); } @@ -358,9 +350,7 @@ static int mongo_set_oauth_key(oauth_key_data_raw *key) { BSON_APPEND_UTF8(&doc, "kid", (const char *)key->kid); BSON_APPEND_UTF8(&doc, "as_rs_alg", (const char *)key->as_rs_alg); BSON_APPEND_UTF8(&doc, "as_rs_key", (const char *)key->as_rs_key); - BSON_APPEND_UTF8(&doc, "auth_alg", (const char *)key->auth_alg); BSON_APPEND_UTF8(&doc, "auth_key", (const char *)key->auth_key); - BSON_APPEND_UTF8(&doc, "hkdf_hash_func", (const char *)key->hkdf_hash_func); BSON_APPEND_UTF8(&doc, "ikm_key", (const char *)key->ikm_key); BSON_APPEND_INT64(&doc, "timestamp", (int64_t)key->timestamp); BSON_APPEND_INT32(&doc, "lifetime", (int32_t)key->lifetime); @@ -497,7 +487,7 @@ static int mongo_list_users(u08bits *realm, secrets_list_t *users, secrets_list_ return ret; } -static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas,secrets_list_t *tss,secrets_list_t *lts) { +static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts) { const char * collection_name = "oauth_key"; mongoc_collection_t * collection = mongo_get_collection(collection_name); @@ -522,9 +512,7 @@ static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr BSON_APPEND_INT32(&fields, "timestamp", 1); BSON_APPEND_INT32(&fields, "as_rs_alg", 1); BSON_APPEND_INT32(&fields, "as_rs_key", 1); - BSON_APPEND_INT32(&fields, "auth_alg", 1); BSON_APPEND_INT32(&fields, "auth_key", 1); - BSON_APPEND_INT32(&fields, "hkdf_hash_func", 1); BSON_APPEND_INT32(&fields, "ikm_key", 1); mongoc_cursor_t * cursor; @@ -552,18 +540,12 @@ static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "as_rs_key") && BSON_ITER_HOLDS_UTF8(&iter)) { STRCPY(key->as_rs_key,bson_iter_utf8(&iter, &length)); } - if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "auth_alg") && BSON_ITER_HOLDS_UTF8(&iter)) { - STRCPY(key->auth_alg,bson_iter_utf8(&iter, &length)); - } if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "auth_key") && BSON_ITER_HOLDS_UTF8(&iter)) { STRCPY(key->auth_key,bson_iter_utf8(&iter, &length)); } if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "ikm_key") && BSON_ITER_HOLDS_UTF8(&iter)) { STRCPY(key->ikm_key,bson_iter_utf8(&iter, &length)); } - if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "hkdf_hash_func") && BSON_ITER_HOLDS_UTF8(&iter)) { - STRCPY(key->hkdf_hash_func,bson_iter_utf8(&iter, &length)); - } if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "timestamp") && BSON_ITER_HOLDS_INT64(&iter)) { key->timestamp = (u64bits)bson_iter_int64(&iter); } @@ -572,9 +554,7 @@ static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr } 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); @@ -586,9 +566,9 @@ static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr 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); + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key=%s, auth_key=%s\n", + key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, + key->as_rs_alg, key->as_rs_key, key->auth_key); } } mongoc_cursor_destroy(cursor); diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 7ca45cc7..de7fda11 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -343,7 +343,7 @@ static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { int ret = -1; char statement[TURN_LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key from oauth_key where kid='%s'",(const char*)kid); + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key from oauth_key where kid='%s'",(const char*)kid); MYSQL * myc = get_mydb_connection(); if(myc) { @@ -354,7 +354,7 @@ static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { MYSQL_RES *mres = mysql_store_result(myc); if(!mres) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc)); - } else if(mysql_field_count(myc)!=8) { + } else if(mysql_field_count(myc)!=6) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement); } else { MYSQL_ROW row = mysql_fetch_row(mres); @@ -375,20 +375,14 @@ static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { slifetime[lengths[2]]=0; key->lifetime = (u32bits)strtoul(slifetime,NULL,10); - ns_bcopy(row[3],key->hkdf_hash_func,lengths[3]); - key->hkdf_hash_func[lengths[3]]=0; + ns_bcopy(row[3],key->as_rs_alg,lengths[3]); + key->as_rs_alg[lengths[3]]=0; - ns_bcopy(row[4],key->as_rs_alg,lengths[4]); - key->as_rs_alg[lengths[4]]=0; + ns_bcopy(row[4],key->as_rs_key,lengths[4]); + key->as_rs_key[lengths[4]]=0; - ns_bcopy(row[5],key->as_rs_key,lengths[5]); - key->as_rs_key[lengths[5]]=0; - - ns_bcopy(row[6],key->auth_alg,lengths[6]); - key->auth_alg[lengths[6]]=0; - - ns_bcopy(row[7],key->auth_key,lengths[7]); - key->auth_key[lengths[7]]=0; + ns_bcopy(row[5],key->auth_key,lengths[5]); + key->auth_key[lengths[5]]=0; ret = 0; } @@ -402,13 +396,13 @@ static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { return ret; } -static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas,secrets_list_t *tss,secrets_list_t *lts) { +static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts) { oauth_key_data_raw key_; oauth_key_data_raw *key=&key_; int ret = -1; char statement[TURN_LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key,kid from oauth_key order by kid"); + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key,kid from oauth_key order by kid"); MYSQL * myc = get_mydb_connection(); if(myc) { @@ -419,7 +413,7 @@ static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr 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)!=9) { + } else if(mysql_field_count(myc)!=7) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement); } else { MYSQL_ROW row = mysql_fetch_row(mres); @@ -440,28 +434,21 @@ static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr slifetime[lengths[2]]=0; key->lifetime = (u32bits)strtoul(slifetime,NULL,10); - ns_bcopy(row[3],key->hkdf_hash_func,lengths[3]); - key->hkdf_hash_func[lengths[3]]=0; - ns_bcopy(row[4],key->as_rs_alg,lengths[4]); - key->as_rs_alg[lengths[4]]=0; + ns_bcopy(row[3],key->as_rs_alg,lengths[3]); + key->as_rs_alg[lengths[3]]=0; - ns_bcopy(row[5],key->as_rs_key,lengths[5]); - key->as_rs_key[lengths[5]]=0; + ns_bcopy(row[4],key->as_rs_key,lengths[4]); + key->as_rs_key[lengths[4]]=0; - ns_bcopy(row[6],key->auth_alg,lengths[6]); - key->auth_alg[lengths[6]]=0; + ns_bcopy(row[5],key->auth_key,lengths[5]); + key->auth_key[lengths[5]]=0; - ns_bcopy(row[7],key->auth_key,lengths[7]); - key->auth_key[lengths[7]]=0; - - ns_bcopy(row[8],key->kid,lengths[8]); - key->kid[lengths[8]]=0; + ns_bcopy(row[6],key->kid,lengths[6]); + key->kid[lengths[6]]=0; 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); @@ -473,9 +460,9 @@ static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr 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); + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key=%s, auth_key=%s\n", + key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, + key->as_rs_alg, key->as_rs_key, key->auth_key); } } row = mysql_fetch_row(mres); @@ -519,13 +506,13 @@ static int mysql_set_oauth_key(oauth_key_data_raw *key) char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); if(myc) { - snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s','%s','%s')", + snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s')", 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); + key->as_rs_alg,key->as_rs_key,key->auth_key); int res = mysql_query(myc, statement); if(res) { - snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, hkdf_hash_func = '%s', as_rs_alg='%s',as_rs_key='%s',auth_alg='%s',auth_key='%s' where kid='%s'",key->ikm_key,(unsigned 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,key->kid); + snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, as_rs_alg='%s',as_rs_key='%s',auth_key='%s' where kid='%s'",key->ikm_key,(unsigned long)key->timestamp,(unsigned long)key->lifetime, + key->as_rs_alg,key->as_rs_key,key->auth_key,key->kid); res = mysql_query(myc, statement); if(res) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating oauth key information: %s\n",mysql_error(myc)); diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index 3ac152b0..6716de8b 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -158,7 +158,7 @@ static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { int ret = -1; char statement[TURN_LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key from oauth_key where kid='%s'",(const char*)kid); + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key from oauth_key where kid='%s'",(const char*)kid); PGconn * pqc = get_pqdb_connection(); if(pqc) { @@ -170,11 +170,9 @@ static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { 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(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->as_rs_alg,PQgetvalue(res,0,3)); + STRCPY(key->as_rs_key,PQgetvalue(res,0,4)); + STRCPY(key->auth_key,PQgetvalue(res,0,5)); STRCPY(key->kid,kid); ret = 0; } @@ -187,7 +185,7 @@ static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { return ret; } -static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas,secrets_list_t *tss,secrets_list_t *lts) { +static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts) { oauth_key_data_raw key_; oauth_key_data_raw *key=&key_; @@ -195,7 +193,7 @@ static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr int ret = -1; char statement[TURN_LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key,kid from oauth_key order by kid"); + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key,kid from oauth_key order by kid"); PGconn * pqc = get_pqdb_connection(); if(pqc) { @@ -210,18 +208,14 @@ static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr 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(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)); + STRCPY(key->as_rs_alg,PQgetvalue(res,i,3)); + STRCPY(key->as_rs_key,PQgetvalue(res,i,4)); + STRCPY(key->auth_key,PQgetvalue(res,i,5)); + STRCPY(key->kid,PQgetvalue(res,i,6)); 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); @@ -233,9 +227,9 @@ static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr 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); + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key=%s, auth_key=%s\n", + key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, + key->as_rs_alg, key->as_rs_key, key->auth_key); } ret = 0; @@ -283,17 +277,17 @@ static int pgsql_set_oauth_key(oauth_key_data_raw *key) { char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); if(pqc) { - snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s','%s','%s')", + snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s')", 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); + key->as_rs_alg,key->as_rs_key,key->auth_key); PGresult *res = PQexec(pqc, statement); if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { if(res) { PQclear(res); } - snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, hkdf_hash_func = '%s', as_rs_alg='%s',as_rs_key='%s',auth_alg='%s',auth_key='%s' where kid='%s'",key->ikm_key,(unsigned 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,key->kid); + snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, as_rs_alg='%s',as_rs_key='%s',auth_key='%s' where kid='%s'",key->ikm_key,(unsigned long)key->timestamp,(unsigned long)key->lifetime, + key->as_rs_alg,key->as_rs_key,key->auth_key,key->kid); res = PQexec(pqc, statement); if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating oauth_key information: %s\n",PQerrorMessage(pqc)); diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index 1d3809e4..c315522a 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -481,12 +481,8 @@ static int redis_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { STRCPY(key->as_rs_key,val); } else if(!strcmp(kw,"auth_key")) { STRCPY(key->auth_key,val); - } else if(!strcmp(kw,"auth_alg")) { - STRCPY(key->auth_alg,val); } else if(!strcmp(kw,"ikm_key")) { STRCPY(key->ikm_key,val); - } else if(!strcmp(kw,"hkdf_hash_func")) { - STRCPY(key->hkdf_hash_func,val); } else if(!strcmp(kw,"timestamp")) { key->timestamp = (u64bits)strtoull(val,NULL,10); } else if(!strcmp(kw,"lifetime")) { @@ -520,8 +516,8 @@ static int redis_set_oauth_key(oauth_key_data_raw *key) { redisContext *rc = get_redis_connection(); if(rc) { char statement[TURN_LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"hmset turn/oauth/kid/%s ikm_key %s 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); + snprintf(statement,sizeof(statement),"hmset turn/oauth/kid/%s ikm_key %s as_rs_alg %s as_rs_key %s auth_key %s timestamp %llu lifetime %lu", + key->kid,key->ikm_key,key->as_rs_alg,key->as_rs_key,key->auth_key,(unsigned long long)key->timestamp,(unsigned long)key->lifetime); turnFreeRedisReply(redisCommand(rc, statement)); turnFreeRedisReply(redisCommand(rc, "save")); ret = 0; @@ -637,7 +633,7 @@ static int redis_list_users(u08bits *realm, secrets_list_t *users, secrets_list_ return ret; } -static int redis_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas,secrets_list_t *tss,secrets_list_t *lts) { +static int redis_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts) { int ret = -1; redisContext *rc = get_redis_connection(); secrets_list_t keys; @@ -675,9 +671,7 @@ static int redis_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr if(redis_get_oauth_key((const u08bits*)s,key) == 0) { 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); @@ -689,9 +683,9 @@ static int redis_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secr 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); + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key=%s, auth_key=%s\n", + key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, + key->as_rs_alg, key->as_rs_key, key->auth_key); } } } diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 8b928c2a..5a9dac15 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -154,7 +154,7 @@ static void init_sqlite_database(sqlite3 *sqliteconnection) { "CREATE TABLE denied_peer_ip (realm varchar(127) default '', ip_range varchar(256), primary key (realm,ip_range))", "CREATE TABLE turn_origin_to_realm (origin varchar(127),realm varchar(127),primary key (origin))", "CREATE TABLE turn_realm_option (realm varchar(127) default '', opt varchar(32), value varchar(128), primary key (realm,opt))", - "CREATE TABLE oauth_key (kid varchar(128),ikm_key varchar(256) 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 oauth_key (kid varchar(128),ikm_key varchar(256) default '',timestamp bigint default 0,lifetime integer default 0,as_rs_alg varchar(64) default '',as_rs_key varchar(256) default '',auth_key varchar(256) default '',primary key (kid))", "CREATE TABLE admin_user (name varchar(32), realm varchar(127), password varchar(127), primary key (name))", NULL }; @@ -293,7 +293,7 @@ static int sqlite_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { char statement[TURN_LONG_STRING_SIZE]; sqlite3_stmt *st = NULL; int rc = 0; - snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key from oauth_key where kid='%s'",(const char*)kid); + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key from oauth_key where kid='%s'",(const char*)kid); sqlite3 *sqliteconnection = get_sqlite_connection(); if(sqliteconnection) { @@ -308,11 +308,9 @@ static int sqlite_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { 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(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->as_rs_alg,sqlite3_column_text(st, 3)); + STRCPY(key->as_rs_key,sqlite3_column_text(st, 4)); + STRCPY(key->auth_key,sqlite3_column_text(st, 5)); STRCPY(key->kid,kid); ret = 0; } @@ -329,7 +327,7 @@ static int sqlite_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { return ret; } -static int sqlite_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas,secrets_list_t *tss,secrets_list_t *lts) { +static int sqlite_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts) { oauth_key_data_raw key_; oauth_key_data_raw *key=&key_; @@ -341,7 +339,7 @@ static int sqlite_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,sec char statement[TURN_LONG_STRING_SIZE]; sqlite3_stmt *st = NULL; int rc = 0; - snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key,kid from oauth_key order by kid"); + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key,kid from oauth_key order by kid"); sqlite3 *sqliteconnection = get_sqlite_connection(); if(sqliteconnection) { @@ -358,18 +356,14 @@ static int sqlite_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,sec 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(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)); + STRCPY(key->as_rs_alg,sqlite3_column_text(st, 3)); + STRCPY(key->as_rs_key,sqlite3_column_text(st, 4)); + STRCPY(key->auth_key,sqlite3_column_text(st, 5)); + STRCPY(key->kid,sqlite3_column_text(st, 6)); 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); @@ -381,9 +375,9 @@ static int sqlite_list_oauth_keys(secrets_list_t *kids,secrets_list_t *hkdfs,sec 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); + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key=%s, auth_key=%s\n", + key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, + key->as_rs_alg, key->as_rs_key, key->auth_key); } } else if (res == SQLITE_DONE) { @@ -453,8 +447,8 @@ static int sqlite_set_oauth_key(oauth_key_data_raw *key) snprintf( statement, sizeof(statement), - "insert or replace into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s','%s','%s')", - 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, + "insert or replace into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s')", + key->kid, key->ikm_key, (unsigned long long) key->timestamp, (unsigned long) key->lifetime, key->as_rs_alg, key->as_rs_key, key->auth_key); sqlite_lock(1); diff --git a/src/apps/relay/dbdrivers/dbdriver.h b/src/apps/relay/dbdrivers/dbdriver.h index 5b745f33..1ab87a27 100644 --- a/src/apps/relay/dbdrivers/dbdriver.h +++ b/src/apps/relay/dbdrivers/dbdriver.h @@ -68,7 +68,7 @@ typedef struct _turn_dbdriver_t { int (*set_oauth_key)(oauth_key_data_raw *key); int (*get_oauth_key)(const u08bits *kid, oauth_key_data_raw *key); int (*del_oauth_key)(const u08bits *kid); - int (*list_oauth_keys)(secrets_list_t *kids,secrets_list_t *hkdfs,secrets_list_t *teas,secrets_list_t *aas,secrets_list_t *tss,secrets_list_t *lts); + int (*list_oauth_keys)(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts); int (*get_admin_user)(const u08bits *usname, u08bits *realm, password_t pwd); int (*set_admin_user)(const u08bits *usname, const u08bits *realm, const password_t pwd); int (*del_admin_user)(const u08bits *usname); diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index d3317947..699876cc 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1374,9 +1374,7 @@ typedef enum _AS_FORM AS_FORM; #define HR_ADD_OAUTH_IKM "oauth_ikm" #define HR_ADD_OAUTH_RS_KEY "oauth_rs_key" #define HR_ADD_OAUTH_AUTH_KEY "oauth_auth_key" -#define HR_ADD_OAUTH_HKDF "oauth_hkdf" #define HR_ADD_OAUTH_TEA "oauth_tea" -#define HR_ADD_OAUTH_AA "oauth_aa" #define HR_DELETE_OAUTH_KID "oauth_kid_del" #define HR_OAUTH_KID "kid" @@ -2775,14 +2773,12 @@ static size_t https_print_oauth_keys(struct str_buffer* sb) size_t ret = 0; const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->list_oauth_keys) { - secrets_list_t kids,hkdfs,teas,aas,tss,lts; + secrets_list_t kids,teas,tss,lts; init_secrets_list(&kids); - init_secrets_list(&hkdfs); init_secrets_list(&teas); - init_secrets_list(&aas); init_secrets_list(&tss); init_secrets_list(<s); - dbd->list_oauth_keys(&kids,&hkdfs,&teas,&aas,&tss,<s); + dbd->list_oauth_keys(&kids,&teas,&tss,<s); size_t sz = get_secrets_list_size(&kids); size_t i; @@ -2809,14 +2805,8 @@ static size_t https_print_oauth_keys(struct str_buffer* sb) str_buffer_append(sb,get_secrets_list_elem(<s,i)); str_buffer_append(sb,""); str_buffer_append(sb,""); - str_buffer_append(sb,get_secrets_list_elem(&hkdfs,i)); - str_buffer_append(sb,""); - str_buffer_append(sb,""); str_buffer_append(sb,get_secrets_list_elem(&teas,i)); str_buffer_append(sb,""); - str_buffer_append(sb,""); - str_buffer_append(sb,get_secrets_list_elem(&aas,i)); - str_buffer_append(sb,""); { str_buffer_append(sb,"
\r\n"); } - str_buffer_append(sb,""); + str_buffer_append(sb,"\r\n"); - { - str_buffer_append(sb,"
Hash key derivation function (optional):
\r\n"); - - if(!add_hkdf_hash_func || !add_hkdf_hash_func[0]) - add_hkdf_hash_func = "SHA-256"; - - str_buffer_append(sb,"SHA-1\r\n
\r\n"); - - str_buffer_append(sb,"SHA-256\r\n
\r\n"); - - str_buffer_append(sb,"SHA-384\r\n
\r\n"); - - str_buffer_append(sb,"SHA-512\r\n
\r\n"); - } - - str_buffer_append(sb,""); + str_buffer_append(sb,""); { if(!add_ikm) add_ikm = ""; @@ -3049,39 +2998,23 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,"
Token encryption algorithm (required):
\r\n"); if(!add_tea || !add_tea[0]) - add_tea = "AES-256-CBC"; + add_tea = "A256GCMKW"; str_buffer_append(sb,"AES-128-CBC\r\n
\r\n"); + str_buffer_append(sb,">A128GCMKW\r\n
\r\n"); str_buffer_append(sb,"AES-256-CBC\r\n
\r\n"); - - str_buffer_append(sb,"AEAD-AES-128-GCM\r\n
\r\n"); - - str_buffer_append(sb,"AEAD-AES-256-GCM\r\n
\r\n"); + str_buffer_append(sb,">A256GCMKW\r\n
\r\n"); } str_buffer_append(sb,""); @@ -3097,56 +3030,9 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,"
\r\n"); } - str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,"\r\n"); - { - str_buffer_append(sb,"
Token authentication algorithm (required if no AEAD used):
\r\n"); - - if(!add_aa || !add_aa[0]) - add_aa = "HMAC-SHA-256-128"; - - str_buffer_append(sb,"HMAC-SHA-256-128\r\n
\r\n"); - - str_buffer_append(sb,"HMAC-SHA-256\r\n
\r\n"); - - str_buffer_append(sb,"HMAC-SHA-384\r\n
\r\n"); - - str_buffer_append(sb,"HMAC-SHA-512\r\n
\r\n"); - - str_buffer_append(sb,"HMAC-SHA-1\r\n
\r\n"); - } - - str_buffer_append(sb,""); + str_buffer_append(sb,""); { if(!add_auth_key) add_auth_key = ""; @@ -3172,9 +3058,7 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,"NKIDkeys"); str_buffer_append(sb,"Timestamp, secs"); str_buffer_append(sb,"Lifetime,secs"); - str_buffer_append(sb,"Hash key derivation function"); str_buffer_append(sb,"Token encryption algorithm"); - str_buffer_append(sb,"Token authentication algorithm"); str_buffer_append(sb," "); str_buffer_append(sb,"\r\n"); @@ -3663,9 +3547,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) const char* add_ikm = ""; const char *add_rs_key = ""; const char *add_auth_key = ""; - const char* add_hkdf_hash_func = ""; const char* add_tea = ""; - const char* add_aa = ""; const char* msg = ""; add_kid = get_http_header_value(hr,HR_ADD_OAUTH_KID,""); @@ -3675,16 +3557,12 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) add_auth_key = get_http_header_value(hr,HR_ADD_OAUTH_AUTH_KEY,""); add_ts = get_http_header_value(hr,HR_ADD_OAUTH_TS,""); add_lt = get_http_header_value(hr,HR_ADD_OAUTH_LT,""); - add_hkdf_hash_func = get_http_header_value(hr,HR_ADD_OAUTH_HKDF,""); add_tea = get_http_header_value(hr,HR_ADD_OAUTH_TEA,""); - add_aa = get_http_header_value(hr,HR_ADD_OAUTH_AA,""); int keys_ok = 0; - if(add_ikm[0] && add_hkdf_hash_func[0]) { + if(add_rs_key[0] && add_auth_key[0]) { keys_ok = 1; - } else if(add_rs_key[0] && add_auth_key[0]) { - keys_ok = 1; - } else if(strstr(add_tea,"AEAD") && add_rs_key[0]) { + } else if(strstr(add_tea,"GCM") && add_rs_key[0]) { keys_ok = 1; } if(!keys_ok) { @@ -3709,14 +3587,10 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } STRCPY(key.ikm_key,add_ikm); - STRCPY(key.hkdf_hash_func,add_hkdf_hash_func); STRCPY(key.as_rs_alg,add_tea); - STRCPY(key.auth_alg,add_aa); STRCPY(key.as_rs_key,add_rs_key); STRCPY(key.auth_key,add_auth_key); - if(strstr(key.as_rs_alg,"AEAD")) key.auth_alg[0]=0; - const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->set_oauth_key) { if((*dbd->set_oauth_key)(&key)<0) { @@ -3726,9 +3600,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) add_ts = "0"; add_lt = "0"; add_ikm = ""; - add_hkdf_hash_func = ""; add_tea = ""; - add_aa = ""; add_rs_key = ""; add_auth_key = ""; } @@ -3736,7 +3608,7 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } } - write_https_oauth_page(s,add_kid,add_ikm,add_hkdf_hash_func,add_tea,add_aa,add_ts,add_lt,add_rs_key,add_auth_key,msg); + write_https_oauth_page(s,add_kid,add_ikm,add_tea,add_ts,add_lt,add_rs_key,add_auth_key,msg); } break; } diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index dd823383..8e5acf76 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -1018,17 +1018,15 @@ void run_db_test(void) oauth_key_data_raw key_; oauth_key_data_raw *key=&key_; dbd->get_oauth_key((const u08bits*)"north",key); - 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); + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key=%s, auth_key=%s\n", + key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, + key->as_rs_alg, key->as_rs_key, key->auth_key); printf("DB TEST 3:\n"); STRCPY(key->as_rs_alg,"as_rs_alg"); STRCPY(key->as_rs_key,"as_rs_key"); - STRCPY(key->auth_alg,"auth_alg"); STRCPY(key->auth_key,"auth_key"); - STRCPY(key->hkdf_hash_func,"hkdf"); STRCPY(key->ikm_key,"ikm_key"); STRCPY(key->kid,"kid"); key->timestamp = 123; @@ -1039,9 +1037,9 @@ void run_db_test(void) printf("DB TEST 4:\n"); dbd->get_oauth_key((const u08bits*)"kid",key); - 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); + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key=%s, auth_key=%s\n", + key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, + key->as_rs_alg, key->as_rs_key, key->auth_key); printf("DB TEST 5:\n"); dbd->del_oauth_key((const u08bits*)"kid"); @@ -1053,9 +1051,9 @@ void run_db_test(void) oauth_key_data oakd; convert_oauth_key_data_raw(key, &oakd); - printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, hkdf_hash_func=%s, as_rs_alg=%s, as_rs_key_size=%d, auth_alg=%s, auth_key_size=%d\n", - oakd.kid, oakd.ikm_key, (unsigned long long)oakd.timestamp, (unsigned long)oakd.lifetime, oakd.hkdf_hash_func, - oakd.as_rs_alg, (int)oakd.as_rs_key_size, oakd.auth_alg, (int)oakd.auth_key_size); + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key_size=%d, auth_key_size=%d\n", + oakd.kid, oakd.ikm_key, (unsigned long long)oakd.timestamp, (unsigned long)oakd.lifetime, + oakd.as_rs_alg, (int)oakd.as_rs_key_size, (int)oakd.auth_key_size); oauth_key oak; char err_msg[1025]; diff --git a/src/apps/rfc5769/rfc5769check.c b/src/apps/rfc5769/rfc5769check.c index 36cde6db..712483b4 100644 --- a/src/apps/rfc5769/rfc5769check.c +++ b/src/apps/rfc5769/rfc5769check.c @@ -41,33 +41,11 @@ //////////// OAUTH ////////////////// -static const char* shas[]={"SHA1", -#if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH) - "SHA256", -#endif -#if !defined(OPENSSL_NO_SHA384) && defined(SHA384_DIGEST_LENGTH) - "SHA384", -#endif -#if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH) - "SHA512", -#endif - NULL}; -static const char* encs[]={"AES-256-CBC","AES-128-CBC", +static const char* encs[]={ #if !defined(TURN_NO_GCM) - "AEAD_AES_128_GCM", "AEAD_AES_256_GCM", + "A128GCMKW", "A256GCMKW", #endif NULL}; -static const char* hmacs[]={"HMAC-SHA-1", -#if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH) - "HMAC-SHA-256","HMAC-SHA-256-128", -#endif -#if !defined(OPENSSL_NO_SHA384) && defined(SHA384_DIGEST_LENGTH) - "HMAC-SHA-384", -#endif -#if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH) - "HMAC-SHA-512", -#endif - NULL}; static int print_extra = 0; @@ -86,7 +64,7 @@ static int check_oauth(void) { const char server_name[33] = "blackdow.carleon.gov"; - size_t i_hmacs,i_shas,i_encs; + size_t i_encs; const char long_term_key[33] = "HGkj32KJGiuy098sdfaqbNjOiaz71923"; @@ -107,18 +85,18 @@ static int check_oauth(void) { const char aead_nonce[OAUTH_AEAD_NONCE_SIZE+1] = "h4j3k2l2n4b5"; - for (i_hmacs = 0; hmacs[i_hmacs]; ++i_hmacs) { - - for (i_shas = 0; shas[i_shas]; ++i_shas) { + { + { for (i_encs = 0; encs[i_encs]; ++i_encs) { - printf("oauth token %s:%s:%s:",hmacs[i_hmacs],shas[i_shas],encs[i_encs]); + printf("oauth token %s:",encs[i_encs]); if(print_extra) printf("\n"); oauth_token ot; + ns_bzero(&ot,sizeof(ot)); ot.enc_block.key_length = (uint16_t)mac_key_length; STRCPY(ot.enc_block.mac_key,mac_key); ot.enc_block.timestamp = token_timestamp; @@ -140,8 +118,6 @@ static int check_oauth(void) { STRCPY(okdr.kid,kid); STRCPY(okdr.ikm_key,base64encoded_ltp); STRCPY(okdr.as_rs_alg, encs[i_encs]); - STRCPY(okdr.auth_alg, hmacs[i_hmacs]); - STRCPY(okdr.hkdf_hash_func, shas[i_shas]); okdr.timestamp = key_timestamp; okdr.lifetime = key_lifetime; diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index a16cb43d..c172ee31 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -102,9 +102,9 @@ int oauth = 0; oauth_key okey_array[3]; static oauth_key_data_raw okdr_array[3] = { - {"north","Y2FybGVvbg==",0,0,"SHA-256","AES-256-CBC","","HMAC-SHA-256-128",""}, - {"union","aGVyb2Q=",0,0,"SHA-256","AES-256-CBC","","HMAC-SHA-512",""}, - {"oldempire","YXVsY3Vz",0,0,"SHA-256","AEAD-AES-256-GCM","","",""} + {"north","Y2FybGVvbg==",0,0,"A256GCMKW","",""}, + {"union","aGVyb2Q=",0,0,"A128GCMKW","",""}, + {"oldempire","YXVsY3Vz",0,0,"A256GCMKW","",""} }; //////////////// local definitions ///////////////// diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index c90dd4f9..51454c6e 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -662,7 +662,7 @@ static void stun_init_error_response_common_str(u08bits* buf, size_t *len, stun_tid* id) { - if (!reason) { + if (!reason || !strcmp((const char*)reason,"Unknown error")) { reason = get_default_reason(error_code); } @@ -2002,8 +2002,7 @@ static void normalize_algorithm(char *s) static size_t calculate_enc_key_length(ENC_ALG a) { switch(a) { - case AES_128_CBC: - case AEAD_AES_128_GCM: + case A128GCMKW: return 16; default: break; @@ -2012,105 +2011,27 @@ static size_t calculate_enc_key_length(ENC_ALG a) return 32; } -static size_t calculate_auth_key_length(AUTH_ALG a) +static size_t calculate_auth_key_length(ENC_ALG a) { switch(a) { - case AUTH_ALG_HMAC_SHA_1: - return 20; - case AUTH_ALG_HMAC_SHA_256_128: - return 32; - case AUTH_ALG_HMAC_SHA_256: - return 32; - case AUTH_ALG_HMAC_SHA_384: - return 48; - case AUTH_ALG_HMAC_SHA_512: - return 64; +#if !defined(TURN_NO_GCM) + case A256GCMKW: + case A128GCMKW: + return 0; +#endif default: break; }; - return 32; -} - -static size_t calculate_auth_output_length(AUTH_ALG a) -{ - switch(a) { - case AUTH_ALG_HMAC_SHA_1: - return 20; - case AUTH_ALG_HMAC_SHA_256_128: - return 16; - case AUTH_ALG_HMAC_SHA_256: - return 32; - case AUTH_ALG_HMAC_SHA_384: - return 48; - case AUTH_ALG_HMAC_SHA_512: - return 64; - default: - break; - }; - - return 32; + return 0; } static int calculate_key(char *key, size_t key_size, - char *new_key, size_t new_key_size, - SHATYPE shatype, - char *err_msg, size_t err_msg_size, - const char *info) + char *new_key, size_t new_key_size) { - //Extract: - u08bits prk[128]; - unsigned int prk_len = 0; - stun_calculate_hmac((const u08bits *)key, key_size, (const u08bits *)"", 0, prk, &prk_len, shatype); + UNUSED_ARG(key_size); - //Expand: - size_t info_len = strlen(info); - u08bits buf[256]; - ns_bcopy(info,buf,info_len); - buf[info_len]=0x01; - u08bits hmac1[128]; - unsigned int hmac1_len = 0; - stun_calculate_hmac((const u08bits *)buf, info_len+1, prk, prk_len, hmac1, &hmac1_len, shatype); - ns_bcopy(hmac1,new_key,hmac1_len); - - //Check - if(new_key_size>hmac1_len) { - ns_bcopy(hmac1,buf,hmac1_len); - ns_bcopy(info,buf+hmac1_len,info_len); - buf[hmac1_len+info_len]=0x02; - u08bits hmac2[128]; - unsigned int hmac2_len = 0; - stun_calculate_hmac((const u08bits *)buf, hmac1_len+info_len+1, prk, prk_len, hmac2, &hmac2_len, shatype); - ns_bcopy(hmac2,new_key+hmac1_len,hmac2_len); - if(new_key_size > (hmac1_len + hmac2_len)) { - - ns_bcopy(hmac2,buf,hmac2_len); - ns_bcopy(info,buf+hmac2_len,info_len); - buf[hmac2_len+info_len]=0x03; - u08bits hmac3[128]; - unsigned int hmac3_len = 0; - stun_calculate_hmac((const u08bits *)buf, hmac2_len+info_len+1, prk, prk_len, hmac3, &hmac3_len, shatype); - ns_bcopy(hmac3,new_key+hmac1_len+hmac2_len,hmac3_len); - if(new_key_size > (hmac1_len + hmac2_len + hmac3_len)) { - - ns_bcopy(hmac3,buf,hmac3_len); - ns_bcopy(info,buf+hmac3_len,info_len); - buf[hmac3_len+info_len]=0x04; - u08bits hmac4[128]; - unsigned int hmac4_len = 0; - stun_calculate_hmac((const u08bits *)buf, hmac3_len+info_len+1, prk, prk_len, hmac4, &hmac4_len, shatype); - ns_bcopy(hmac4,new_key+hmac1_len+hmac2_len+hmac3_len,hmac4_len); - if(new_key_size > (hmac1_len + hmac2_len + hmac3_len + hmac4_len)) { - - if(err_msg) { - snprintf(err_msg,err_msg_size,"Wrong HKDF procedure (key sizes): output.sz=%lu, hmac(1)=%lu, hmac(2)=%lu",(unsigned long)new_key_size,(unsigned long)hmac1_len,(unsigned long)hmac2_len); - } - OAUTH_ERROR("Wrong HKDF procedure (key sizes): output.sz=%lu, hmac(1)=%lu, hmac(2)=%lu",(unsigned long)new_key_size,(unsigned long)hmac1_len,(unsigned long)hmac2_len); - return -1; - } - } - } - } + ns_bcopy(key,new_key,new_key_size); return 0; } @@ -2138,13 +2059,9 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er remove_spaces(oakd->kid); - remove_spaces(oakd->hkdf_hash_func); remove_spaces(oakd->as_rs_alg); - remove_spaces(oakd->auth_alg); - normalize_algorithm(oakd->hkdf_hash_func); normalize_algorithm(oakd->as_rs_alg); - normalize_algorithm(oakd->auth_alg); if(!(oakd->kid[0])) { if(err_msg) { @@ -2171,57 +2088,19 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er if(!(key->timestamp)) key->timestamp = OAUTH_DEFAULT_TIMESTAMP; if(!(key->lifetime)) key->lifetime = OAUTH_DEFAULT_LIFETIME; - key->hkdf_hash_func = SHATYPE_SHA256; - if(!strcmp(oakd->hkdf_hash_func,"SHA1") || !strcmp(oakd->hkdf_hash_func,"SHA-1")) { - key->hkdf_hash_func = SHATYPE_SHA1; - } else if(!strcmp(oakd->hkdf_hash_func,"SHA256") || !strcmp(oakd->hkdf_hash_func,"SHA-256")) { - key->hkdf_hash_func = SHATYPE_SHA256; - } else if(!strcmp(oakd->hkdf_hash_func,"SHA384") || !strcmp(oakd->hkdf_hash_func,"SHA-384")) { - key->hkdf_hash_func = SHATYPE_SHA384; - } else if(!strcmp(oakd->hkdf_hash_func,"SHA512") || !strcmp(oakd->hkdf_hash_func,"SHA-512")) { - key->hkdf_hash_func = SHATYPE_SHA512; - } else if(oakd->hkdf_hash_func[0]) { - if(err_msg) { - snprintf(err_msg,err_msg_size,"Wrong HKDF hash function algorithm: %s",oakd->hkdf_hash_func); - } - OAUTH_ERROR("Wrong HKDF hash function algorithm: %s\n",oakd->hkdf_hash_func); - return -1; - } - - key->auth_alg = AUTH_ALG_DEFAULT; - if(!strcmp(oakd->auth_alg,"HMAC-SHA-1") || !strcmp(oakd->auth_alg,"HMAC-SHA1")) { - key->auth_alg = AUTH_ALG_HMAC_SHA_1; - } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256")) { - key->auth_alg = AUTH_ALG_HMAC_SHA_256; - } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-384")) { - key->auth_alg = AUTH_ALG_HMAC_SHA_384; - } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-512")) { - key->auth_alg = AUTH_ALG_HMAC_SHA_512; - } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256-128")) { - key->auth_alg = AUTH_ALG_HMAC_SHA_256_128; - } else if(oakd->auth_alg[0]) { - if(err_msg) { - snprintf(err_msg,err_msg_size,"Wrong oAuth token hash algorithm: %s (1)\n",oakd->auth_alg); - } - 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; - if(!strcmp(oakd->as_rs_alg,"AES-128-CBC")) { - key->as_rs_alg = AES_128_CBC; - } else if(!strcmp(oakd->as_rs_alg,"AES-256-CBC")) { - 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 !defined(TURN_NO_GCM) + if(!strcmp(oakd->as_rs_alg,"A128GCMKW")) { + key->as_rs_alg = A128GCMKW; + key->auth_key_size = 0; + key->auth_key[0] = 0; + } else if(!strcmp(oakd->as_rs_alg,"A256GCMKW")) { + key->as_rs_alg = A256GCMKW; + key->auth_key_size = 0; + key->auth_key[0] = 0; + } else if(oakd->as_rs_alg[0]) +#endif + { if(err_msg) { snprintf(err_msg,err_msg_size,"Wrong oAuth token encryption algorithm: %s (2)\n",oakd->as_rs_alg); } @@ -2229,20 +2108,18 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er return -1; } - if(key->auth_alg == AUTH_ALG_UNDEFINED) { - //AEAD - key->auth_key_size = 0; - key->auth_key[0] = 0; - } else if(!(key->auth_key_size)) { - key->auth_key_size = calculate_auth_key_length(key->auth_alg); - if(calculate_key(key->ikm_key,key->ikm_key_size,key->auth_key,key->auth_key_size,key->hkdf_hash_func,err_msg,err_msg_size,"AUTH key")<0) { - return -1; + if(!(key->auth_key_size)) { + key->auth_key_size = calculate_auth_key_length(key->as_rs_alg); + if(key->auth_key_size) { + if(calculate_key(key->ikm_key,key->ikm_key_size,key->auth_key,key->auth_key_size)<0) { + return -1; + } } } if(!(key->as_rs_key_size)) { key->as_rs_key_size = calculate_enc_key_length(key->as_rs_alg); - if(calculate_key(key->ikm_key,key->ikm_key_size,key->as_rs_key,key->as_rs_key_size,key->hkdf_hash_func,err_msg,err_msg_size,"AS-RS key")<0) { + if(calculate_key(key->ikm_key,key->ikm_key_size,key->as_rs_key,key->as_rs_key_size)<0) { return -1; } } @@ -2254,14 +2131,10 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er static const EVP_CIPHER *get_cipher_type(ENC_ALG enc_alg) { switch(enc_alg) { - case AES_256_CBC: - return EVP_aes_256_cbc(); - case AES_128_CBC: - return EVP_aes_128_cbc(); #if !defined(TURN_NO_GCM) - case AEAD_AES_128_GCM: + case A128GCMKW: return EVP_aes_128_gcm(); - case AEAD_AES_256_GCM: + case A256GCMKW: return EVP_aes_256_gcm(); #endif default: @@ -2271,44 +2144,6 @@ static const EVP_CIPHER *get_cipher_type(ENC_ALG enc_alg) return NULL; } -static const EVP_MD *get_auth_type(AUTH_ALG aa) -{ - switch(aa) { - case AUTH_ALG_HMAC_SHA_1: - return EVP_sha1(); -#if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH) - case AUTH_ALG_HMAC_SHA_256_128: - case AUTH_ALG_HMAC_SHA_256: - return EVP_sha256(); -#endif -#if !defined(OPENSSL_NO_SHA384) && defined(SHA384_DIGEST_LENGTH) - case AUTH_ALG_HMAC_SHA_384: - return EVP_sha384(); -#endif -#if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH) - case AUTH_ALG_HMAC_SHA_512: - return EVP_sha512(); -#endif - default: - break; - }; - OAUTH_ERROR("%s: Unknown auth algorithm: %d\n",__FUNCTION__,(int)aa); - return NULL; -} - -static void update_hmac_len(AUTH_ALG aa, unsigned int *hmac_len) -{ - if(hmac_len) { - switch(aa) { - case AUTH_ALG_HMAC_SHA_256_128: - *hmac_len = 16; - break; - default: - break; - }; - } -} - static int my_EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl) { @@ -2357,8 +2192,15 @@ void print_field(const char* name, const unsigned char* f, size_t len) { printf("\n<<==field %s\n",name); } -static int encode_oauth_token_normal(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken) +int encode_oauth_token_normal(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken); +int encode_oauth_token_normal(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken) { + UNUSED_ARG(server_name); + UNUSED_ARG(etoken); + UNUSED_ARG(key); + UNUSED_ARG(dtoken); + + /* if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<=128)) { unsigned char orig_field[MAX_ENCODED_OAUTH_TOKEN_SIZE]; @@ -2420,11 +2262,19 @@ static int encode_oauth_token_normal(const u08bits *server_name, encoded_oauth_t return 0; } + */ return -1; } -static int decode_oauth_token_normal(const u08bits *server_name, const encoded_oauth_token *etoken, const oauth_key *key, oauth_token *dtoken) +int decode_oauth_token_normal(const u08bits *server_name, const encoded_oauth_token *etoken, const oauth_key *key, oauth_token *dtoken); +int decode_oauth_token_normal(const u08bits *server_name, const encoded_oauth_token *etoken, const oauth_key *key, oauth_token *dtoken) { + UNUSED_ARG(server_name); + UNUSED_ARG(etoken); + UNUSED_ARG(key); + UNUSED_ARG(dtoken); + + /* if(server_name && etoken && key && dtoken) { size_t mac_size = calculate_auth_output_length(key->auth_alg); @@ -2498,6 +2348,7 @@ static int decode_oauth_token_normal(const u08bits *server_name, const encoded_o return 0; } + */ return -1; } @@ -2512,14 +2363,27 @@ static void generate_random_nonce(unsigned char *nonce, size_t sz) { #if !defined(TURN_NO_GCM) -static int encode_oauth_token_aead(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken, const u08bits* nonce0) -{ - if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<128)) { +static int encode_oauth_token_aead(const u08bits *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken, const u08bits* nonce0) { + if(server_name && etoken && key && dtoken && (dtoken->enc_block.key_length<=MAXSHASIZE)) { unsigned char orig_field[MAX_ENCODED_OAUTH_TOKEN_SIZE]; ns_bzero(orig_field,sizeof(orig_field)); + unsigned char nonce[OAUTH_AEAD_NONCE_SIZE]; + if(nonce0) { + ns_bcopy(nonce0,nonce,sizeof(nonce)); + } else { + generate_random_nonce(nonce, sizeof(nonce)); + } + size_t len = 0; + + *((uint16_t*)(orig_field+len)) = nswap16(OAUTH_AEAD_NONCE_SIZE); + len +=2; + + ns_bcopy(nonce,orig_field+len,OAUTH_AEAD_NONCE_SIZE); + len += OAUTH_AEAD_NONCE_SIZE; + *((uint16_t*)(orig_field+len)) = nswap16(dtoken->enc_block.key_length); len +=2; @@ -2536,15 +2400,6 @@ static int encode_oauth_token_aead(const u08bits *server_name, encoded_oauth_tok if(!cipher) return -1; - unsigned char *encoded_field = (unsigned char*)etoken->token; - - unsigned char nonce[OAUTH_AEAD_NONCE_SIZE]; - if(nonce0) { - ns_bcopy(nonce0,nonce,sizeof(nonce)); - } else { - generate_random_nonce(nonce, sizeof(nonce)); - } - EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); @@ -2572,8 +2427,13 @@ static int encode_oauth_token_aead(const u08bits *server_name, encoded_oauth_tok return -1; outl=0; + unsigned char *encoded_field = (unsigned char*)etoken->token; + ns_bcopy(orig_field,encoded_field,OAUTH_AEAD_NONCE_SIZE + 2); + encoded_field += OAUTH_AEAD_NONCE_SIZE + 2; + unsigned char *start_field = orig_field + OAUTH_AEAD_NONCE_SIZE + 2; + len -= OAUTH_AEAD_NONCE_SIZE + 2; - if(1 != my_EVP_EncryptUpdate(&ctx, encoded_field, &outl, orig_field, (int)len)) + if(1 != my_EVP_EncryptUpdate(&ctx, encoded_field, &outl, start_field, (int)len)) return -1; int tmp_outl = 0; @@ -2583,10 +2443,7 @@ static int encode_oauth_token_aead(const u08bits *server_name, encoded_oauth_tok EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, OAUTH_AEAD_TAG_SIZE, encoded_field + outl); outl += OAUTH_AEAD_TAG_SIZE; - ns_bcopy(nonce, encoded_field + outl, OAUTH_AEAD_NONCE_SIZE); - outl += OAUTH_AEAD_NONCE_SIZE; //encoded+tag+hmac - - etoken->size = outl; + etoken->size = 2 + OAUTH_AEAD_NONCE_SIZE + outl; EVP_CIPHER_CTX_cleanup(&ctx); @@ -2599,18 +2456,24 @@ static int decode_oauth_token_aead(const u08bits *server_name, const encoded_oau { if(server_name && etoken && key && dtoken) { - size_t min_encoded_field_size = 2+4+8+OAUTH_AEAD_NONCE_SIZE+OAUTH_AEAD_TAG_SIZE+1; + unsigned char snl[2]; + ns_bcopy((const unsigned char*)(etoken->token),snl,2); + const unsigned char *csnl = snl; + + uint16_t nonce_len = nswap16(*((const uint16_t*)csnl)); + + size_t min_encoded_field_size = 2+4+8+nonce_len+2+OAUTH_AEAD_TAG_SIZE+1; if(etoken->size < min_encoded_field_size) { OAUTH_ERROR("%s: token size too small: %d\n",__FUNCTION__,(int)etoken->size); return -1; } - const unsigned char* encoded_field = (const unsigned char*)etoken->token; - unsigned int encoded_field_size = (unsigned int)etoken->size-OAUTH_AEAD_NONCE_SIZE - OAUTH_AEAD_TAG_SIZE; - const unsigned char* nonce = ((const unsigned char*)etoken->token) + encoded_field_size + OAUTH_AEAD_TAG_SIZE; + const unsigned char* encoded_field = (const unsigned char*)(etoken->token + nonce_len + 2); + unsigned int encoded_field_size = (unsigned int)etoken->size - nonce_len - 2 - OAUTH_AEAD_TAG_SIZE; + const unsigned char* nonce = ((const unsigned char*)etoken->token + 2); unsigned char tag[OAUTH_AEAD_TAG_SIZE]; - ns_bcopy(((const unsigned char*)etoken->token) + encoded_field_size, tag ,sizeof(tag)); + ns_bcopy(((const unsigned char*)etoken->token) + nonce_len + 2 + encoded_field_size, tag ,sizeof(tag)); unsigned char decoded_field[MAX_ENCODED_OAUTH_TOKEN_SIZE]; @@ -2631,7 +2494,7 @@ static int decode_oauth_token_aead(const u08bits *server_name, const encoded_oau //EVP_CIPHER_CTX_set_padding(&ctx,1); /* Set IV length if default 12 bytes (96 bits) is not appropriate */ - if(1 != EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, OAUTH_AEAD_NONCE_SIZE, NULL)) { + if(1 != EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, nonce_len, NULL)) { OAUTH_ERROR("%s: Cannot set nonce length\n",__FUNCTION__); return -1; } @@ -2697,12 +2560,9 @@ int encode_oauth_token(const u08bits *server_name, encoded_oauth_token *etoken, UNUSED_ARG(nonce); if(server_name && etoken && key && dtoken) { switch(key->as_rs_alg) { - case AES_256_CBC: - case AES_128_CBC: - return encode_oauth_token_normal(server_name, etoken,key,dtoken); #if !defined(TURN_NO_GCM) - case AEAD_AES_128_GCM: - case AEAD_AES_256_GCM: + case A256GCMKW: + case A128GCMKW: return encode_oauth_token_aead(server_name, etoken,key,dtoken,nonce); #endif default: @@ -2717,12 +2577,9 @@ int decode_oauth_token(const u08bits *server_name, const encoded_oauth_token *et { if(server_name && etoken && key && dtoken) { switch(key->as_rs_alg) { - case AES_256_CBC: - case AES_128_CBC: - return decode_oauth_token_normal(server_name, etoken,key,dtoken); #if !defined(TURN_NO_GCM) - case AEAD_AES_128_GCM: - case AEAD_AES_256_GCM: + case A256GCMKW: + case A128GCMKW: return decode_oauth_token_aead(server_name, etoken,key,dtoken); #endif default: diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 81bb51ab..f23493de 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -73,10 +73,10 @@ typedef enum _SHATYPE SHATYPE; enum _ENC_ALG { ENC_ALG_ERROR=-1, ENC_ALG_DEFAULT=0, - AES_256_CBC=ENC_ALG_DEFAULT, - AES_128_CBC, - AEAD_AES_128_GCM, - AEAD_AES_256_GCM, +#if !defined(TURN_NO_GCM) + A256GCMKW=ENC_ALG_DEFAULT, + A128GCMKW, +#endif ENG_ALG_NUM }; @@ -84,23 +84,6 @@ typedef enum _ENC_ALG ENC_ALG; /* <<== OAUTH TOKEN ENC ALG */ -/* OAUTH TOKEN AUTH ALG ==> */ - -enum _AUTH_ALG { - AUTH_ALG_ERROR = -1, - AUTH_ALG_UNDEFINED = 0, - AUTH_ALG_DEFAULT = 1, - AUTH_ALG_HMAC_SHA_256_128 = AUTH_ALG_DEFAULT, - AUTH_ALG_HMAC_SHA_1, - AUTH_ALG_HMAC_SHA_256, - AUTH_ALG_HMAC_SHA_384, - AUTH_ALG_HMAC_SHA_512 -}; - -typedef enum _AUTH_ALG AUTH_ALG; - -/* <<== OAUTH TOKEN AUTH ALG */ - /** * oAuth struct */ @@ -113,6 +96,7 @@ typedef enum _AUTH_ALG AUTH_ALG; #define OAUTH_ALG_SIZE (64) #define OAUTH_KEY_SIZE (256) #define OAUTH_AEAD_NONCE_SIZE (12) +#define OAUTH_MAX_NONCE_SIZE (256) #define OAUTH_AEAD_TAG_SIZE (16) #define OAUTH_ENC_ALG_BLOCK_SIZE (16) @@ -127,11 +111,9 @@ struct _oauth_key_data { size_t ikm_key_size; turn_time_t timestamp; turn_time_t lifetime; - char hkdf_hash_func[OAUTH_HASH_FUNC_SIZE+1]; char as_rs_alg[OAUTH_ALG_SIZE+1]; char as_rs_key[OAUTH_KEY_SIZE+1]; size_t as_rs_key_size; - char auth_alg[OAUTH_ALG_SIZE+1]; char auth_key[OAUTH_KEY_SIZE+1]; size_t auth_key_size; }; @@ -144,11 +126,9 @@ struct _oauth_key { size_t ikm_key_size; turn_time_t timestamp; turn_time_t lifetime; - SHATYPE hkdf_hash_func; ENC_ALG as_rs_alg; char as_rs_key[OAUTH_KEY_SIZE+1]; size_t as_rs_key_size; - AUTH_ALG auth_alg; char auth_key[OAUTH_KEY_SIZE+1]; size_t auth_key_size; }; @@ -156,6 +136,8 @@ struct _oauth_key { typedef struct _oauth_key oauth_key; struct _oauth_encrypted_block { + uint16_t nonce_length; + uint8_t nonce[OAUTH_MAX_NONCE_SIZE]; uint16_t key_length; uint8_t mac_key[MAXSHASIZE]; uint64_t timestamp; diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 3cd62ca3..203f69d1 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -3398,7 +3398,6 @@ static int check_stun_auth(turn_turnserver *server, } } - /* 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); diff --git a/turndb/schema.sql b/turndb/schema.sql index b44f1bec..25ee800f 100644 --- a/turndb/schema.sql +++ b/turndb/schema.sql @@ -42,10 +42,8 @@ CREATE TABLE oauth_key ( 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) ); diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis index 31bc8b51..00810404 100644 --- a/turndb/schema.userdb.redis +++ b/turndb/schema.userdb.redis @@ -43,30 +43,18 @@ and they will be almost immediately "seen" by the turnserver process. lifetime - (optional) the key lifetime in seconds; the default value is 0 - unlimited lifetime. - - hkdf_hash_func - (optional) hash function for HKDF procedure; the - valid values are SHA-1, SHA-256, SHA-384 and SHA-512, - with SHA-256 as default. The hkdf_hash_func is not needed - if the as_rs_key and auth_key are defined explicitly - in the database; as_rs_alg - oAuth token encryption algorithm; the valid values are - "AES-128-CBC" and "AES-256-CBC", , "AEAD-AES-128-GCM", - "AEAD-AES-256-GCM". - The default value is "AES-256-CBC"; + "A256GCMKW", "A128GCMKW" (see + http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#section-4.1). + The default value is "A256GCMKW"; as_rs_key - (optional) base64-encoded AS-RS key. If not defined, then - calculated with ikm_key and hkdf_hash_func. The as_rs_key length + calculated with ikm_key. The as_rs_key length is defined by as_rs_alg. - auth_alg - (optional) oAuth token authentication algorithm; the valid values are - "HMAC-SHA-256-128", "HMAC-SHA-256", "HMAC-SHA-384", - "HMAC-SHA-512" and "HMAC-SHA-1". - The default value is "HMAC-SHA-256-128". - 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. + calculated with ikm_key. Not used with AEAD algorithms. 5) admin users (over https interface) are maintained as keys of form: "turn/admin_user/ with hash members "password" and, @@ -137,8 +125,7 @@ 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/oldempire ikm_key 'YXVsY3Vz' hkdf_hash_func 'SHA-256' as_rs_alg 'AEAD-AES-256-GCM' +hmset turn/oauth/kid/oldempire ikm_key 'YXVsY3Vz' as_rs_alg 'A256GCMKW' hmset turn/admin_user/skarling realm 'north.gov' password 'hoodless' hmset turn/admin_user/bayaz password 'magi' diff --git a/turndb/testmongosetup.sh b/turndb/testmongosetup.sh index 130ad291..23ab9573 100755 --- a/turndb/testmongosetup.sh +++ b/turndb/testmongosetup.sh @@ -56,21 +56,13 @@ db.realm.insert({ db.oauth_key.insert({ kid: 'north', ikm_key: 'Y2FybGVvbg==', - hkdf_hash_func: 'SHA-256', - as_rs_alg: 'AES-256-CBC', - auth_alg: 'HMAC-SHA-256-128' }); - + as_rs_alg: 'A256GCMKW'}); db.oauth_key.insert({ kid: 'union', ikm_key: 'aGVyb2Q=', - hkdf_hash_func: 'SHA-256', - as_rs_alg: 'AES-256-CBC', - auth_alg: 'HMAC-SHA-512' }); - + as_rs_alg: 'A128GCMKW'}); db.oauth_key.insert({ kid: 'oldempire', ikm_key: 'YXVsY3Vz', - hkdf_hash_func: 'SHA-256', - as_rs_alg: 'AEAD-AES-256-GCM', - auth_alg: '' }); + as_rs_alg: 'A256GCMKW'}); exit diff --git a/turndb/testredisdbsetup.sh b/turndb/testredisdbsetup.sh index d19da17a..08696e56 100755 --- a/turndb/testredisdbsetup.sh +++ b/turndb/testredisdbsetup.sh @@ -38,9 +38,9 @@ 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/union ikm_key 'aGVyb2Q=' hkdf_hash_func 'SHA-256' as_rs_alg 'AES-256-CBC' auth_alg 'HMAC-SHA-512' -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==' as_rs_alg 'A256GCMKW' +hmset turn/oauth/kid/union ikm_key 'aGVyb2Q=' as_rs_alg 'A128GCMKW' +hmset turn/oauth/kid/oldempire ikm_key 'YXVsY3Vz' as_rs_alg 'A256GCMKW' hmset turn/admin_user/skarling realm 'north.gov' password '\$5\$6fc35c3b0c7d4633\$27fca7574f9b79d0cb93ae03e45379470cbbdfcacdd6401f97ebc620f31f54f2' hmset turn/admin_user/bayaz password '\$5\$e018513e9de69e73\$5cbdd2e29e04ca46aeb022268a7460d3a3468de193dcb2b95f064901769f455f' diff --git a/turndb/testsqldbsetup.sql b/turndb/testsqldbsetup.sql index 54648bd2..a7e77ccf 100644 --- a/turndb/testsqldbsetup.sql +++ b/turndb/testsqldbsetup.sql @@ -31,6 +31,6 @@ insert into denied_peer_ip (ip_range) values('123::45'); insert into denied_peer_ip (realm,ip_range) values('north.gov','172.17.17.133-172.17.19.56'); insert into denied_peer_ip (realm,ip_range) values('crinna.org','123::77'); -insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('north','Y2FybGVvbg==',0,0,'SHA-256','AES-256-CBC','','HMAC-SHA-256-128',''); -insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('union','aGVyb2Q=',0,0,'SHA-256','AES-256-CBC','','HMAC-SHA-512',''); -insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('oldempire','YXVsY3Vz',0,0,'SHA-256','AEAD-AES-256-GCM','','',''); +insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key) values('north','Y2FybGVvbg==',0,0,'A256GCMKW','',''); +insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key) values('union','aGVyb2Q=',0,0,'A128GCMKW','',''); +insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key) values('oldempire','YXVsY3Vz',0,0,'A256GCMKW','',''); From 6dbee00b74ca960e28b8f14e7808eb6f9b5971d8 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 19 Apr 2015 07:37:12 +0000 Subject: [PATCH 543/805] working on new third-party auth draft --- INSTALL | 10 ---- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/common/apputils.c | 21 -------- src/apps/common/apputils.h | 2 - src/apps/relay/dbdrivers/dbd_mongo.c | 22 +------- src/apps/relay/dbdrivers/dbd_mysql.c | 34 ++++-------- src/apps/relay/dbdrivers/dbd_pgsql.c | 22 ++++---- src/apps/relay/dbdrivers/dbd_redis.c | 12 ++--- src/apps/relay/dbdrivers/dbd_sqlite.c | 21 +++----- src/apps/relay/turn_admin_server.c | 74 ++------------------------ src/apps/relay/userdb.c | 17 +++--- src/apps/uclient/mainuclient.c | 6 +-- src/client/ns_turn_msg.c | 33 ++++-------- src/client/ns_turn_msg_defs_new.h | 4 -- turndb/schema.sql | 2 - turndb/schema.userdb.redis | 15 ++---- turndb/testsqldbsetup.sql | 6 +-- 17 files changed, 62 insertions(+), 239 deletions(-) diff --git a/INSTALL b/INSTALL index 46433d92..ed19d6fc 100644 --- a/INSTALL +++ b/INSTALL @@ -744,8 +744,6 @@ CREATE TABLE oauth_key ( timestamp bigint default 0, lifetime integer default 0, as_rs_alg varchar(64) default '', - as_rs_key varchar(256) default '', - auth_key varchar(256) default '', primary key (kid) ); @@ -754,8 +752,6 @@ The oauth_key table fields meanings are: kid: the kid of the key; ikm_key - (optional) base64-encoded key ("input keying material"); - The ikm_key is not needed if the as_rs_key and auth_key are defined - explicitly in the database; timestamp - (optional) the timestamp (in seconds) when the key lifetime starts; @@ -767,12 +763,6 @@ The oauth_key table fields meanings are: "A256GCMKW", "A128GCMKW" (see http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#section-4.1). The default value is "A256GCMKW"; - - as_rs_key - (optional) base64-encoded AS-RS key. If not defined, then - calculated with ikm_key. - - auth_key - (optional) base64-encoded AUTH key. If not defined, then - calculated with ikm_key. Not used for AEAD algorithms. # Https access admin users. # Leave this table empty if you do not want diff --git a/examples/var/db/turndb b/examples/var/db/turndb index 9b08dba57bc97b1b5f25a9a3ee567059c8ddc824..2c30dc868a4c890c65c92fb31f8a9a632d5ce921 100644 GIT binary patch delta 170 zcmZqJz}T>Xae}nqJ_ZH`F(76IVkRJ#n5bjSxNl>^GI5T149xeK4=~T$EXXr~*+YSu zOi*@=w>o7;SDFfvY`*ciaXs4%h7k*hI6lwDk2p0TNZ O@^-&{n|JxUaR305F)yXae}nqP6h@BF(76IVkQuKqK+}+&W#Dn#5ra#FyCR`!#rcNAWs*wpAs{N zyetQYJTGs4PD*NSL1s~EWJFkTq;Xi4qmikZyR)x%xEvFQI7CfpUS@t?qI+0nl2M?o zqoI)nSYC;dLtGVX#^z_zx(3W^na@saEZE%UbAypFXkw!uSCgzLySThOV+-fxKYshn y6N}@EisQ3WD;3HTi;^=Ei!^{XX)2_orX`lu@EOmSmu-*u2I+gaZHo%RoN> diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c index eecfcbc7..9b91d891 100644 --- a/src/apps/common/apputils.c +++ b/src/apps/common/apputils.c @@ -1136,27 +1136,6 @@ void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *o turn_free(ikm_key,ikm_key_size); } } - - if(raw->as_rs_key[0]) { - size_t as_rs_key_size = 0; - char *as_rs_key = (char*)base64_decode(raw->as_rs_key,strlen(raw->as_rs_key),&as_rs_key_size); - if(as_rs_key) { - ns_bcopy(as_rs_key,oakd->as_rs_key,as_rs_key_size); - oakd->as_rs_key_size = as_rs_key_size; - turn_free(as_rs_key,as_rs_key_size); - } - } - - if(raw->auth_key[0]) { - size_t auth_key_size = 0; - char *auth_key = (char*)base64_decode(raw->auth_key,strlen(raw->auth_key),&auth_key_size); - if(auth_key) { - ns_bcopy(auth_key,oakd->auth_key,auth_key_size); - oakd->auth_key_size = auth_key_size; - turn_free(auth_key,auth_key_size); - } - } - } } diff --git a/src/apps/common/apputils.h b/src/apps/common/apputils.h index 4b93d861..6ff61bfd 100644 --- a/src/apps/common/apputils.h +++ b/src/apps/common/apputils.h @@ -142,8 +142,6 @@ struct _oauth_key_data_raw { u64bits timestamp; u32bits lifetime; char as_rs_alg[OAUTH_ALG_SIZE+1]; - char as_rs_key[OAUTH_KEY_SIZE+1]; - char auth_key[OAUTH_KEY_SIZE+1]; }; typedef struct _oauth_key_data_raw oauth_key_data_raw; diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index 853a5524..e06127e8 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -255,8 +255,6 @@ static int mongo_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { BSON_APPEND_INT32(&fields, "lifetime", 1); BSON_APPEND_INT32(&fields, "timestamp", 1); BSON_APPEND_INT32(&fields, "as_rs_alg", 1); - BSON_APPEND_INT32(&fields, "as_rs_key", 1); - BSON_APPEND_INT32(&fields, "auth_key", 1); BSON_APPEND_INT32(&fields, "ikm_key", 1); mongoc_cursor_t * cursor; @@ -279,12 +277,6 @@ static int mongo_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "as_rs_alg") && BSON_ITER_HOLDS_UTF8(&iter)) { STRCPY(key->as_rs_alg,bson_iter_utf8(&iter, &length)); } - if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "as_rs_key") && BSON_ITER_HOLDS_UTF8(&iter)) { - STRCPY(key->as_rs_key,bson_iter_utf8(&iter, &length)); - } - if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "auth_key") && BSON_ITER_HOLDS_UTF8(&iter)) { - STRCPY(key->auth_key,bson_iter_utf8(&iter, &length)); - } if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "ikm_key") && BSON_ITER_HOLDS_UTF8(&iter)) { STRCPY(key->ikm_key,bson_iter_utf8(&iter, &length)); } @@ -349,8 +341,6 @@ static int mongo_set_oauth_key(oauth_key_data_raw *key) { bson_init(&doc); BSON_APPEND_UTF8(&doc, "kid", (const char *)key->kid); BSON_APPEND_UTF8(&doc, "as_rs_alg", (const char *)key->as_rs_alg); - BSON_APPEND_UTF8(&doc, "as_rs_key", (const char *)key->as_rs_key); - BSON_APPEND_UTF8(&doc, "auth_key", (const char *)key->auth_key); BSON_APPEND_UTF8(&doc, "ikm_key", (const char *)key->ikm_key); BSON_APPEND_INT64(&doc, "timestamp", (int64_t)key->timestamp); BSON_APPEND_INT32(&doc, "lifetime", (int32_t)key->lifetime); @@ -511,8 +501,6 @@ static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre BSON_APPEND_INT32(&fields, "lifetime", 1); BSON_APPEND_INT32(&fields, "timestamp", 1); BSON_APPEND_INT32(&fields, "as_rs_alg", 1); - BSON_APPEND_INT32(&fields, "as_rs_key", 1); - BSON_APPEND_INT32(&fields, "auth_key", 1); BSON_APPEND_INT32(&fields, "ikm_key", 1); mongoc_cursor_t * cursor; @@ -537,12 +525,6 @@ static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "as_rs_alg") && BSON_ITER_HOLDS_UTF8(&iter)) { STRCPY(key->as_rs_alg,bson_iter_utf8(&iter, &length)); } - if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "as_rs_key") && BSON_ITER_HOLDS_UTF8(&iter)) { - STRCPY(key->as_rs_key,bson_iter_utf8(&iter, &length)); - } - if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "auth_key") && BSON_ITER_HOLDS_UTF8(&iter)) { - STRCPY(key->auth_key,bson_iter_utf8(&iter, &length)); - } if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "ikm_key") && BSON_ITER_HOLDS_UTF8(&iter)) { STRCPY(key->ikm_key,bson_iter_utf8(&iter, &length)); } @@ -566,9 +548,9 @@ static int mongo_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre add_to_secrets_list(lts,lt); } } else { - printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key=%s, auth_key=%s\n", + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s\n", key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, - key->as_rs_alg, key->as_rs_key, key->auth_key); + key->as_rs_alg); } } mongoc_cursor_destroy(cursor); diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index de7fda11..ca2189d7 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -343,7 +343,7 @@ static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { int ret = -1; char statement[TURN_LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key from oauth_key where kid='%s'",(const char*)kid); + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg from oauth_key where kid='%s'",(const char*)kid); MYSQL * myc = get_mydb_connection(); if(myc) { @@ -354,7 +354,7 @@ static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { MYSQL_RES *mres = mysql_store_result(myc); if(!mres) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc)); - } else if(mysql_field_count(myc)!=6) { + } else if(mysql_field_count(myc)!=4) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement); } else { MYSQL_ROW row = mysql_fetch_row(mres); @@ -378,12 +378,6 @@ static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { ns_bcopy(row[3],key->as_rs_alg,lengths[3]); key->as_rs_alg[lengths[3]]=0; - ns_bcopy(row[4],key->as_rs_key,lengths[4]); - key->as_rs_key[lengths[4]]=0; - - ns_bcopy(row[5],key->auth_key,lengths[5]); - key->auth_key[lengths[5]]=0; - ret = 0; } } @@ -402,7 +396,7 @@ static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre oauth_key_data_raw *key=&key_; int ret = -1; char statement[TURN_LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key,kid from oauth_key order by kid"); + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,kid from oauth_key order by kid"); MYSQL * myc = get_mydb_connection(); if(myc) { @@ -413,7 +407,7 @@ static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre MYSQL_RES *mres = mysql_store_result(myc); if(!mres) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc)); - } else if(mysql_field_count(myc)!=7) { + } else if(mysql_field_count(myc)!=5) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement); } else { MYSQL_ROW row = mysql_fetch_row(mres); @@ -437,14 +431,8 @@ static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre ns_bcopy(row[3],key->as_rs_alg,lengths[3]); key->as_rs_alg[lengths[3]]=0; - ns_bcopy(row[4],key->as_rs_key,lengths[4]); - key->as_rs_key[lengths[4]]=0; - - ns_bcopy(row[5],key->auth_key,lengths[5]); - key->auth_key[lengths[5]]=0; - ns_bcopy(row[6],key->kid,lengths[6]); - key->kid[lengths[6]]=0; + key->kid[lengths[4]]=0; if(kids) { add_to_secrets_list(kids,key->kid); @@ -460,9 +448,9 @@ static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre add_to_secrets_list(lts,lt); } } else { - printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key=%s, auth_key=%s\n", + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s\n", key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, - key->as_rs_alg, key->as_rs_key, key->auth_key); + key->as_rs_alg); } } row = mysql_fetch_row(mres); @@ -506,13 +494,13 @@ static int mysql_set_oauth_key(oauth_key_data_raw *key) char statement[TURN_LONG_STRING_SIZE]; MYSQL * myc = get_mydb_connection(); if(myc) { - snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s')", + snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg) values('%s','%s',%llu,%lu,'%s')", key->kid,key->ikm_key,(unsigned long long)key->timestamp,(unsigned long)key->lifetime, - key->as_rs_alg,key->as_rs_key,key->auth_key); + key->as_rs_alg); int res = mysql_query(myc, statement); if(res) { - snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, as_rs_alg='%s',as_rs_key='%s',auth_key='%s' where kid='%s'",key->ikm_key,(unsigned long)key->timestamp,(unsigned long)key->lifetime, - key->as_rs_alg,key->as_rs_key,key->auth_key,key->kid); + snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, as_rs_alg='%s' where kid='%s'",key->ikm_key,(unsigned long)key->timestamp,(unsigned long)key->lifetime, + key->as_rs_alg,key->kid); res = mysql_query(myc, statement); if(res) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating oauth key information: %s\n",mysql_error(myc)); diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index 6716de8b..cfb0187e 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -158,7 +158,7 @@ static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { int ret = -1; char statement[TURN_LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key from oauth_key where kid='%s'",(const char*)kid); + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg from oauth_key where kid='%s'",(const char*)kid); PGconn * pqc = get_pqdb_connection(); if(pqc) { @@ -171,8 +171,6 @@ static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { key->timestamp = (u64bits)strtoll(PQgetvalue(res,0,1),NULL,10); key->lifetime = (u32bits)strtol(PQgetvalue(res,0,2),NULL,10); STRCPY(key->as_rs_alg,PQgetvalue(res,0,3)); - STRCPY(key->as_rs_key,PQgetvalue(res,0,4)); - STRCPY(key->auth_key,PQgetvalue(res,0,5)); STRCPY(key->kid,kid); ret = 0; } @@ -193,7 +191,7 @@ static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre int ret = -1; char statement[TURN_LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key,kid from oauth_key order by kid"); + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,kid from oauth_key order by kid"); PGconn * pqc = get_pqdb_connection(); if(pqc) { @@ -209,9 +207,7 @@ static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre key->timestamp = (u64bits)strtoll(PQgetvalue(res,i,1),NULL,10); key->lifetime = (u32bits)strtol(PQgetvalue(res,i,2),NULL,10); STRCPY(key->as_rs_alg,PQgetvalue(res,i,3)); - STRCPY(key->as_rs_key,PQgetvalue(res,i,4)); - STRCPY(key->auth_key,PQgetvalue(res,i,5)); - STRCPY(key->kid,PQgetvalue(res,i,6)); + STRCPY(key->kid,PQgetvalue(res,i,4)); if(kids) { add_to_secrets_list(kids,key->kid); @@ -227,9 +223,9 @@ static int pgsql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre add_to_secrets_list(lts,lt); } } else { - printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key=%s, auth_key=%s\n", + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s\n", key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, - key->as_rs_alg, key->as_rs_key, key->auth_key); + key->as_rs_alg); } ret = 0; @@ -277,17 +273,17 @@ static int pgsql_set_oauth_key(oauth_key_data_raw *key) { char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); if(pqc) { - snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s')", + snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg) values('%s','%s',%llu,%lu,'%s')", key->kid,key->ikm_key,(unsigned long long)key->timestamp,(unsigned long)key->lifetime, - key->as_rs_alg,key->as_rs_key,key->auth_key); + key->as_rs_alg); PGresult *res = PQexec(pqc, statement); if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { if(res) { PQclear(res); } - snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, as_rs_alg='%s',as_rs_key='%s',auth_key='%s' where kid='%s'",key->ikm_key,(unsigned long)key->timestamp,(unsigned long)key->lifetime, - key->as_rs_alg,key->as_rs_key,key->auth_key,key->kid); + snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, as_rs_alg='%s' where kid='%s'",key->ikm_key,(unsigned long)key->timestamp,(unsigned long)key->lifetime, + key->as_rs_alg,key->kid); res = PQexec(pqc, statement); if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating oauth_key information: %s\n",PQerrorMessage(pqc)); diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index c315522a..3619f816 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -477,10 +477,6 @@ static int redis_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { if(kw) { if(!strcmp(kw,"as_rs_alg")) { STRCPY(key->as_rs_alg,val); - } else if(!strcmp(kw,"as_rs_key")) { - STRCPY(key->as_rs_key,val); - } else if(!strcmp(kw,"auth_key")) { - STRCPY(key->auth_key,val); } else if(!strcmp(kw,"ikm_key")) { STRCPY(key->ikm_key,val); } else if(!strcmp(kw,"timestamp")) { @@ -516,8 +512,8 @@ static int redis_set_oauth_key(oauth_key_data_raw *key) { redisContext *rc = get_redis_connection(); if(rc) { char statement[TURN_LONG_STRING_SIZE]; - snprintf(statement,sizeof(statement),"hmset turn/oauth/kid/%s ikm_key %s as_rs_alg %s as_rs_key %s auth_key %s timestamp %llu lifetime %lu", - key->kid,key->ikm_key,key->as_rs_alg,key->as_rs_key,key->auth_key,(unsigned long long)key->timestamp,(unsigned long)key->lifetime); + snprintf(statement,sizeof(statement),"hmset turn/oauth/kid/%s ikm_key %s as_rs_alg %s timestamp %llu lifetime %lu", + key->kid,key->ikm_key,key->as_rs_alg,(unsigned long long)key->timestamp,(unsigned long)key->lifetime); turnFreeRedisReply(redisCommand(rc, statement)); turnFreeRedisReply(redisCommand(rc, "save")); ret = 0; @@ -683,9 +679,9 @@ static int redis_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre add_to_secrets_list(lts,lt); } } else { - printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key=%s, auth_key=%s\n", + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s\n", key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, - key->as_rs_alg, key->as_rs_key, key->auth_key); + key->as_rs_alg); } } } diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 5a9dac15..6d216a5f 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -154,7 +154,7 @@ static void init_sqlite_database(sqlite3 *sqliteconnection) { "CREATE TABLE denied_peer_ip (realm varchar(127) default '', ip_range varchar(256), primary key (realm,ip_range))", "CREATE TABLE turn_origin_to_realm (origin varchar(127),realm varchar(127),primary key (origin))", "CREATE TABLE turn_realm_option (realm varchar(127) default '', opt varchar(32), value varchar(128), primary key (realm,opt))", - "CREATE TABLE oauth_key (kid varchar(128),ikm_key varchar(256) default '',timestamp bigint default 0,lifetime integer default 0,as_rs_alg varchar(64) default '',as_rs_key varchar(256) default '',auth_key varchar(256) default '',primary key (kid))", + "CREATE TABLE oauth_key (kid varchar(128),ikm_key varchar(256) default '',timestamp bigint default 0,lifetime integer default 0,as_rs_alg varchar(64) default '',primary key (kid))", "CREATE TABLE admin_user (name varchar(32), realm varchar(127), password varchar(127), primary key (name))", NULL }; @@ -293,7 +293,7 @@ static int sqlite_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { char statement[TURN_LONG_STRING_SIZE]; sqlite3_stmt *st = NULL; int rc = 0; - snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key from oauth_key where kid='%s'",(const char*)kid); + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg from oauth_key where kid='%s'",(const char*)kid); sqlite3 *sqliteconnection = get_sqlite_connection(); if(sqliteconnection) { @@ -309,8 +309,6 @@ static int sqlite_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) { key->timestamp = (u64bits)strtoll((const char*)sqlite3_column_text(st, 1),NULL,10); key->lifetime = (u32bits)strtol((const char*)sqlite3_column_text(st, 2),NULL,10); STRCPY(key->as_rs_alg,sqlite3_column_text(st, 3)); - STRCPY(key->as_rs_key,sqlite3_column_text(st, 4)); - STRCPY(key->auth_key,sqlite3_column_text(st, 5)); STRCPY(key->kid,kid); ret = 0; } @@ -339,7 +337,7 @@ static int sqlite_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secr char statement[TURN_LONG_STRING_SIZE]; sqlite3_stmt *st = NULL; int rc = 0; - snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key,kid from oauth_key order by kid"); + snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,as_rs_alg,kid from oauth_key order by kid"); sqlite3 *sqliteconnection = get_sqlite_connection(); if(sqliteconnection) { @@ -357,9 +355,7 @@ static int sqlite_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secr key->timestamp = (u64bits)strtoll((const char*)sqlite3_column_text(st, 1),NULL,10); key->lifetime = (u32bits)strtol((const char*)sqlite3_column_text(st, 2),NULL,10); STRCPY(key->as_rs_alg,sqlite3_column_text(st, 3)); - STRCPY(key->as_rs_key,sqlite3_column_text(st, 4)); - STRCPY(key->auth_key,sqlite3_column_text(st, 5)); - STRCPY(key->kid,sqlite3_column_text(st, 6)); + STRCPY(key->kid,sqlite3_column_text(st, 4)); if(kids) { add_to_secrets_list(kids,key->kid); @@ -375,9 +371,9 @@ static int sqlite_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secr add_to_secrets_list(lts,lt); } } else { - printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key=%s, auth_key=%s\n", + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s\n", key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, - key->as_rs_alg, key->as_rs_key, key->auth_key); + key->as_rs_alg); } } else if (res == SQLITE_DONE) { @@ -447,9 +443,8 @@ static int sqlite_set_oauth_key(oauth_key_data_raw *key) snprintf( statement, sizeof(statement), - "insert or replace into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s')", - key->kid, key->ikm_key, (unsigned long long) key->timestamp, (unsigned long) key->lifetime, key->as_rs_alg, key->as_rs_key, - key->auth_key); + "insert or replace into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg) values('%s','%s',%llu,%lu,'%s')", + key->kid, key->ikm_key, (unsigned long long) key->timestamp, (unsigned long) key->lifetime, key->as_rs_alg); sqlite_lock(1); diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 699876cc..dfdb8d2e 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1372,8 +1372,6 @@ typedef enum _AS_FORM AS_FORM; #define HR_ADD_OAUTH_TS "oauth_ts" #define HR_ADD_OAUTH_LT "oauth_lt" #define HR_ADD_OAUTH_IKM "oauth_ikm" -#define HR_ADD_OAUTH_RS_KEY "oauth_rs_key" -#define HR_ADD_OAUTH_AUTH_KEY "oauth_auth_key" #define HR_ADD_OAUTH_TEA "oauth_tea" #define HR_DELETE_OAUTH_KID "oauth_kid_del" #define HR_OAUTH_KID "kid" @@ -2878,28 +2876,6 @@ static void write_https_oauth_show_keys(ioa_socket_handle s, const char* kid) str_buffer_append(sb,"\r\n"); } - if(okey.as_rs_key_size) { - size_t as_rs_key_size = 0; - char *as_rs_key = (char*)base64_encode((unsigned char*)okey.as_rs_key,okey.as_rs_key_size,&as_rs_key_size); - if(as_rs_key) { - str_buffer_append(sb,"AS-RS key:"); - str_buffer_append(sb,as_rs_key); - str_buffer_append(sb,"\r\n"); - turn_free(as_rs_key,as_rs_key_size); - } - } - - if(okey.auth_key_size) { - size_t auth_key_size = 0; - char *auth_key = (char*)base64_encode((unsigned char*)okey.auth_key,okey.auth_key_size,&auth_key_size); - if(auth_key) { - str_buffer_append(sb,"AUTH key:"); - str_buffer_append(sb,auth_key); - str_buffer_append(sb,"\r\n"); - turn_free(auth_key,auth_key_size); - } - } - str_buffer_append(sb,"\r\n"); } } @@ -2914,7 +2890,6 @@ static void write_https_oauth_show_keys(ioa_socket_handle s, const char* kid) static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, const char* add_ikm, const char* add_tea, const char *add_ts, const char* add_lt, - const char *add_rs_key, const char *add_auth_key, const char* msg) { if(s && !ioa_socket_tobeclosed(s)) { @@ -3017,35 +2992,7 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,">A256GCMKW\r\n
\r\n"); } - str_buffer_append(sb,""); - - { - if(!add_rs_key) add_rs_key = ""; - - str_buffer_append(sb,"
Base64-encoded AS-RS key (optional):
"); - str_buffer_append(sb,"
\r\n"); - } - - str_buffer_append(sb,"\r\n"); - - str_buffer_append(sb,""); - - { - if(!add_auth_key) add_auth_key = ""; - - str_buffer_append(sb,"
Base64-encoded AUTH key (optional):
"); - str_buffer_append(sb,"
\r\n"); - } - - str_buffer_append(sb,"\r\n"); + str_buffer_append(sb,"\r\n\r\n"); str_buffer_append(sb,"
"); @@ -3545,28 +3492,19 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) const char* add_ts = "0"; const char* add_lt = "0"; const char* add_ikm = ""; - const char *add_rs_key = ""; - const char *add_auth_key = ""; const char* add_tea = ""; const char* msg = ""; add_kid = get_http_header_value(hr,HR_ADD_OAUTH_KID,""); if(add_kid[0]) { add_ikm = get_http_header_value(hr,HR_ADD_OAUTH_IKM,""); - add_rs_key = get_http_header_value(hr,HR_ADD_OAUTH_RS_KEY,""); - add_auth_key = get_http_header_value(hr,HR_ADD_OAUTH_AUTH_KEY,""); add_ts = get_http_header_value(hr,HR_ADD_OAUTH_TS,""); add_lt = get_http_header_value(hr,HR_ADD_OAUTH_LT,""); add_tea = get_http_header_value(hr,HR_ADD_OAUTH_TEA,""); - int keys_ok = 0; - if(add_rs_key[0] && add_auth_key[0]) { - keys_ok = 1; - } else if(strstr(add_tea,"GCM") && add_rs_key[0]) { - keys_ok = 1; - } + int keys_ok = (add_ikm[0] != 0); if(!keys_ok) { - msg = "Provided information is insufficient for the oAuth key generation."; + msg = "You must enter the key value."; } else { oauth_key_data_raw key; ns_bzero(&key,sizeof(key)); @@ -3588,8 +3526,6 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) STRCPY(key.ikm_key,add_ikm); STRCPY(key.as_rs_alg,add_tea); - STRCPY(key.as_rs_key,add_rs_key); - STRCPY(key.auth_key,add_auth_key); const turn_dbdriver_t * dbd = get_dbdriver(); if (dbd && dbd->set_oauth_key) { @@ -3601,14 +3537,12 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) add_lt = "0"; add_ikm = ""; add_tea = ""; - add_rs_key = ""; - add_auth_key = ""; } } } } - write_https_oauth_page(s,add_kid,add_ikm,add_tea,add_ts,add_lt,add_rs_key,add_auth_key,msg); + write_https_oauth_page(s,add_kid,add_ikm,add_tea,add_ts,add_lt,msg); } break; } diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 8e5acf76..26f6cde2 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -1018,15 +1018,12 @@ void run_db_test(void) oauth_key_data_raw key_; oauth_key_data_raw *key=&key_; dbd->get_oauth_key((const u08bits*)"north",key); - printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key=%s, auth_key=%s\n", - key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, - key->as_rs_alg, key->as_rs_key, key->auth_key); + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s\n", + key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, key->as_rs_alg); printf("DB TEST 3:\n"); STRCPY(key->as_rs_alg,"as_rs_alg"); - STRCPY(key->as_rs_key,"as_rs_key"); - STRCPY(key->auth_key,"auth_key"); STRCPY(key->ikm_key,"ikm_key"); STRCPY(key->kid,"kid"); key->timestamp = 123; @@ -1037,9 +1034,8 @@ void run_db_test(void) printf("DB TEST 4:\n"); dbd->get_oauth_key((const u08bits*)"kid",key); - printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key=%s, auth_key=%s\n", - key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, - key->as_rs_alg, key->as_rs_key, key->auth_key); + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s\n", + key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, key->as_rs_alg); printf("DB TEST 5:\n"); dbd->del_oauth_key((const u08bits*)"kid"); @@ -1051,9 +1047,8 @@ void run_db_test(void) oauth_key_data oakd; convert_oauth_key_data_raw(key, &oakd); - printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s, as_rs_key_size=%d, auth_key_size=%d\n", - oakd.kid, oakd.ikm_key, (unsigned long long)oakd.timestamp, (unsigned long)oakd.lifetime, - oakd.as_rs_alg, (int)oakd.as_rs_key_size, (int)oakd.auth_key_size); + printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, as_rs_alg=%s\n", + oakd.kid, oakd.ikm_key, (unsigned long long)oakd.timestamp, (unsigned long)oakd.lifetime, oakd.as_rs_alg); oauth_key oak; char err_msg[1025]; diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index c172ee31..264d2422 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -102,9 +102,9 @@ int oauth = 0; oauth_key okey_array[3]; static oauth_key_data_raw okdr_array[3] = { - {"north","Y2FybGVvbg==",0,0,"A256GCMKW","",""}, - {"union","aGVyb2Q=",0,0,"A128GCMKW","",""}, - {"oldempire","YXVsY3Vz",0,0,"A256GCMKW","",""} + {"north","Y2FybGVvbg==",0,0,"A256GCMKW"}, + {"union","aGVyb2Q=",0,0,"A128GCMKW"}, + {"oldempire","YXVsY3Vz",0,0,"A256GCMKW"} }; //////////////// local definitions ///////////////// diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 51454c6e..f8f2ddb7 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -2045,15 +2045,8 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er oauth_key_data *oakd = &oakd_obj; if(!(oakd->ikm_key_size)) { - if(!(oakd->as_rs_key_size)) { - if(err_msg) { - snprintf(err_msg,err_msg_size,"AS-RS key is not defined"); - } - OAUTH_ERROR("AS-RS key is not defined\n"); - return -1; - } - if(!(oakd->auth_key_size)) { - //AEAD ? + if(err_msg) { + snprintf(err_msg,err_msg_size,"key is not defined"); } } @@ -2075,10 +2068,6 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er STRCPY(key->kid,oakd->kid); - ns_bcopy(oakd->as_rs_key,key->as_rs_key,sizeof(key->as_rs_key)); - key->as_rs_key_size = oakd->as_rs_key_size; - ns_bcopy(oakd->auth_key,key->auth_key,sizeof(key->auth_key)); - key->auth_key_size = oakd->auth_key_size; ns_bcopy(oakd->ikm_key,key->ikm_key,sizeof(key->ikm_key)); key->ikm_key_size = oakd->ikm_key_size; @@ -2108,20 +2097,16 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er return -1; } - if(!(key->auth_key_size)) { - key->auth_key_size = calculate_auth_key_length(key->as_rs_alg); - if(key->auth_key_size) { - if(calculate_key(key->ikm_key,key->ikm_key_size,key->auth_key,key->auth_key_size)<0) { - return -1; - } + key->auth_key_size = calculate_auth_key_length(key->as_rs_alg); + if(key->auth_key_size) { + if(calculate_key(key->ikm_key,key->ikm_key_size,key->auth_key,key->auth_key_size)<0) { + return -1; } } - if(!(key->as_rs_key_size)) { - key->as_rs_key_size = calculate_enc_key_length(key->as_rs_alg); - if(calculate_key(key->ikm_key,key->ikm_key_size,key->as_rs_key,key->as_rs_key_size)<0) { - return -1; - } + key->as_rs_key_size = calculate_enc_key_length(key->as_rs_alg); + if(calculate_key(key->ikm_key,key->ikm_key_size,key->as_rs_key,key->as_rs_key_size)<0) { + return -1; } } diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index f23493de..9a0d3732 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -112,10 +112,6 @@ struct _oauth_key_data { turn_time_t timestamp; turn_time_t lifetime; char as_rs_alg[OAUTH_ALG_SIZE+1]; - char as_rs_key[OAUTH_KEY_SIZE+1]; - size_t as_rs_key_size; - char auth_key[OAUTH_KEY_SIZE+1]; - size_t auth_key_size; }; typedef struct _oauth_key_data oauth_key_data; diff --git a/turndb/schema.sql b/turndb/schema.sql index 25ee800f..b35463a2 100644 --- a/turndb/schema.sql +++ b/turndb/schema.sql @@ -43,8 +43,6 @@ CREATE TABLE oauth_key ( timestamp bigint default 0, lifetime integer default 0, as_rs_alg varchar(64) default '', - as_rs_key varchar(256) default '', - auth_key varchar(256) default '', primary key (kid) ); diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis index 00810404..d79ccf6e 100644 --- a/turndb/schema.userdb.redis +++ b/turndb/schema.userdb.redis @@ -34,12 +34,10 @@ and they will be almost immediately "seen" by the turnserver process. 4) For the oAuth authentication, there is a hash structure with the key "turn/oauth/kid/". The kid structure fields are: - ikm_key - (optional) base64-encoded key ("input keying material"); - The ikm_key is not needed if the as_rs_key and auth_key are defined - explicitly in the database; + ikm_key - (optional) base64-encoded key ("input keying material"). timestamp - (optional) the timestamp (in seconds) when the key - lifetime started; + lifetime started. lifetime - (optional) the key lifetime in seconds; the default value is 0 - unlimited lifetime. @@ -47,14 +45,7 @@ and they will be almost immediately "seen" by the turnserver process. as_rs_alg - oAuth token encryption algorithm; the valid values are "A256GCMKW", "A128GCMKW" (see http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#section-4.1). - The default value is "A256GCMKW"; - - as_rs_key - (optional) base64-encoded AS-RS key. If not defined, then - calculated with ikm_key. The as_rs_key length - is defined by as_rs_alg. - - auth_key - (optional) base64-encoded AUTH key. If not defined, then - calculated with ikm_key. Not used with AEAD algorithms. + The default value is "A256GCMKW". 5) admin users (over https interface) are maintained as keys of form: "turn/admin_user/ with hash members "password" and, diff --git a/turndb/testsqldbsetup.sql b/turndb/testsqldbsetup.sql index a7e77ccf..ce7d7d57 100644 --- a/turndb/testsqldbsetup.sql +++ b/turndb/testsqldbsetup.sql @@ -31,6 +31,6 @@ insert into denied_peer_ip (ip_range) values('123::45'); insert into denied_peer_ip (realm,ip_range) values('north.gov','172.17.17.133-172.17.19.56'); insert into denied_peer_ip (realm,ip_range) values('crinna.org','123::77'); -insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key) values('north','Y2FybGVvbg==',0,0,'A256GCMKW','',''); -insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key) values('union','aGVyb2Q=',0,0,'A128GCMKW','',''); -insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg,as_rs_key,auth_key) values('oldempire','YXVsY3Vz',0,0,'A256GCMKW','',''); +insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg) values('north','Y2FybGVvbg==',0,0,'A256GCMKW'); +insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg) values('union','aGVyb2Q=',0,0,'A128GCMKW'); +insert into oauth_key (kid,ikm_key,timestamp,lifetime,as_rs_alg) values('oldempire','YXVsY3Vz',0,0,'A256GCMKW'); From 31b25414b4ca3a3b9a6ccbacd59f0d8ec261f9e0 Mon Sep 17 00:00:00 2001 From: mom040267 Date: Sun, 19 Apr 2015 08:14:29 +0000 Subject: [PATCH 544/805] working on oauth --- INSTALL | 2 +- examples/var/db/turndb | Bin 22528 -> 22528 bytes src/apps/relay/dbdrivers/dbd_mysql.c | 2 +- src/apps/relay/dbdrivers/dbd_sqlite.c | 2 +- src/apps/relay/turn_admin_server.c | 6 +++--- src/apps/uclient/mainuclient.c | 6 +++--- turndb/schema.sql | 2 +- turndb/schema.userdb.redis | 5 +++-- turndb/testmongosetup.sh | 6 +++--- turndb/testredisdbsetup.sh | 6 +++--- turndb/testsqldbsetup.sql | 6 +++--- 11 files changed, 22 insertions(+), 21 deletions(-) diff --git a/INSTALL b/INSTALL index ed19d6fc..1318c3d8 100644 --- a/INSTALL +++ b/INSTALL @@ -740,7 +740,7 @@ CREATE TABLE turn_realm_option ( # CREATE TABLE oauth_key ( kid varchar(128), - ikm_key varchar(256) default '', + ikm_key varchar(256), timestamp bigint default 0, lifetime integer default 0, as_rs_alg varchar(64) default '', diff --git a/examples/var/db/turndb b/examples/var/db/turndb index 2c30dc868a4c890c65c92fb31f8a9a632d5ce921..2459c11e5e392d51963f22ca17f75e5b079dafed 100644 GIT binary patch delta 322 zcmZqJz}T>Xae}nqQ3eJEF(76IVkRJ#ny6#UcywdJGI1_52IhUtHOyvAH#at(VPcG( z*ce&w!ptV0%E2L@pOccBTaa0l>Ko!&<>wM=g(cK>01?O=$Dmj;veEz;hW`a z;1?2U?C+9Y4pisuXk=>U?(FLw?!d$*4l<=QFEc-nfG)V{{vp}kPL75~77!yCAx7lo z7nNiXYXnf8_vY`?;u=iMZ#OFnoML9=*nHdFf`$1n^Vx}w1)JM^ZZI+~n%EdHdA*;r fC@?f`12G6R`iioP%gZx1WlsL%7rr^pe-Q@&nq*+5 delta 207 zcmZqJz}T>Xae}nqJ_ZH`F(76IVkRJ#n5bjSxNl>^GI5T149xeK4=~T$EXXr~IZ}a{ zOx3-TYlzTw}AMz(wZG_uWlcm_IR}o!D5g zxy|PWBjfamjRBL_`#EzpMu@VD%gZx1)lX*k59d}$Nli;E%_&h(SKl1xzlZ|>hwD6Y diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index ca2189d7..a7eb317d 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -431,7 +431,7 @@ static int mysql_list_oauth_keys(secrets_list_t *kids,secrets_list_t *teas,secre ns_bcopy(row[3],key->as_rs_alg,lengths[3]); key->as_rs_alg[lengths[3]]=0; - ns_bcopy(row[6],key->kid,lengths[6]); + ns_bcopy(row[4],key->kid,lengths[4]); key->kid[lengths[4]]=0; if(kids) { diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 6d216a5f..222a4bb6 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -154,7 +154,7 @@ static void init_sqlite_database(sqlite3 *sqliteconnection) { "CREATE TABLE denied_peer_ip (realm varchar(127) default '', ip_range varchar(256), primary key (realm,ip_range))", "CREATE TABLE turn_origin_to_realm (origin varchar(127),realm varchar(127),primary key (origin))", "CREATE TABLE turn_realm_option (realm varchar(127) default '', opt varchar(32), value varchar(128), primary key (realm,opt))", - "CREATE TABLE oauth_key (kid varchar(128),ikm_key varchar(256) default '',timestamp bigint default 0,lifetime integer default 0,as_rs_alg varchar(64) default '',primary key (kid))", + "CREATE TABLE oauth_key (kid varchar(128),ikm_key varchar(256),timestamp bigint default 0,lifetime integer default 0,as_rs_alg varchar(64) default '',primary key (kid))", "CREATE TABLE admin_user (name varchar(32), realm varchar(127), password varchar(127), primary key (name))", NULL }; diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index dfdb8d2e..05754a05 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -2871,7 +2871,7 @@ static void write_https_oauth_show_keys(ioa_socket_handle s, const char* kid) str_buffer_append(sb,"\r\n"); if(key.ikm_key[0]) { - str_buffer_append(sb,"\r\n"); } @@ -2959,7 +2959,7 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con { if(!add_ikm) add_ikm = ""; - str_buffer_append(sb,"
Base64-encoded input keying material (optional):
Input Keying Material:"); + str_buffer_append(sb,"
Base64-encoded Input Keying Material:"); str_buffer_append(sb,key.ikm_key); str_buffer_append(sb,"