From 24556a8a574bddb368f533f810400e37015c1af3 Mon Sep 17 00:00:00 2001 From: Oleg Moskalenko Date: Mon, 23 Mar 2015 23:26:19 -0700 Subject: [PATCH] Imported Upstream version 4.4.4.1 --- ChangeLog | 6 + INSTALL | 19 +- README.turnadmin | 19 +- README.turnserver | 3 + README.turnutils | 7 +- STATUS | 2 + configure | 45 +++- examples/etc/turnserver.conf | 10 +- .../longtermsecure/secure_sctp_client.sh | 34 +++ examples/var/db/turndb | Bin 22528 -> 22528 bytes man/man1/turnadmin.1 | 19 +- man/man1/turnserver.1 | 5 +- man/man1/turnutils.1 | 11 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 5 +- src/apps/common/apputils.c | 14 +- src/apps/common/apputils.h | 2 +- src/apps/peer/udpserver.c | 4 +- src/apps/relay/dtls_listener.c | 24 +- src/apps/relay/mainrelay.c | 39 +++- src/apps/relay/netengine.c | 16 +- src/apps/relay/ns_ioalib_engine_impl.c | 209 +++++++++++++++--- src/apps/relay/tls_listener.c | 137 +++++++++++- src/apps/relay/turn_admin_server.c | 46 ++-- src/apps/relay/userdb.c | 2 +- src/apps/stunclient/stunclient.c | 12 +- src/apps/uclient/mainuclient.c | 10 +- src/apps/uclient/startuclient.c | 16 +- src/apps/uclient/uclient.h | 1 + src/client/ns_turn_msg.c | 92 +++++++- src/client/ns_turn_msg.h | 4 + src/ns_turn_defs.h | 26 ++- src/server/ns_turn_ioalib.h | 7 +- src/server/ns_turn_server.c | 16 +- turndb/testmongosetup.sh | 12 +- turndb/testredisdbsetup.sh | 7 +- turndb/testsqldbsetup.sql | 4 +- 37 files changed, 729 insertions(+), 158 deletions(-) create mode 100755 examples/scripts/longtermsecure/secure_sctp_client.sh diff --git a/ChangeLog b/ChangeLog index 0a5a39c5..a77b6258 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +3/15/2015 Oleg Moskalenko +Version 4.4.4.1 'Ardee West': + - 'native' SCTP support (experimental); + - 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': - bandwidth control fixed; diff --git a/INSTALL b/INSTALL index 8edc407a..90c34bcf 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) @@ -688,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 ( @@ -792,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), @@ -899,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 @@ -1191,4 +1196,12 @@ 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 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.turnadmin b/README.turnadmin index 53166f6c..8e303687 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 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/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/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/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. diff --git a/configure b/configure index fbb02442..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` @@ -293,6 +294,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 +627,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 ######################### @@ -1157,12 +1163,49 @@ if [ -z "${LDCONFIG}" ] ; then fi fi +############################### +# SCTP +############################### + +if [ -z "${TURN_NO_SCTP}" ] ; then + if [ -z "${TURN_SCTP_INCLUDE}" ] ; then + 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 + done + fi + fi + else + TURN_SCTP_INCLUDE="-DTURN_SCTP_INCLUDE=\"\\\"${TURN_SCTP_INCLUDE}\\\"\"" + 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_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/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/examples/scripts/longtermsecure/secure_sctp_client.sh b/examples/scripts/longtermsecure/secure_sctp_client.sh new file mode 100755 index 00000000..e6ca3ce0 --- /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 -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 + 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(q$<\.\.\.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 12ddcd14..7f4d0c0c 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 "21 March 2015" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -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/man/man1/turnutils.1 b/man/man1/turnutils.1 index e381670b..2c3e03d4 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 "21 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 0150ec91..2ecdefda 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.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 32e4ae8d..e6e630fd 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.4.2.3 +Version: 4.4.4.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -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 @@ -288,6 +289,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Sun Mar 15 2015 Oleg Moskalenko + - 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/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 9e6e3fde..d1b6b519 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; @@ -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 0762fbc8..7c4d590f 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", @@ -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); @@ -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; @@ -773,17 +773,17 @@ 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); - 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) @@ -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; @@ -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); @@ -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 035caf8e..48df9acd 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" @@ -599,6 +602,10 @@ 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 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 +659,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 +848,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 +1445,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 +1585,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)) @@ -1614,7 +1639,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; 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;ist){ + case SCTP_SOCKET: + case TLS_SCTP_SOCKET: + case TCP_SOCKET: case TLS_SOCKET: + if (s->bev) { struct evbuffer *evb = bufferevent_get_output(s->bev); @@ -810,7 +818,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 +866,23 @@ int set_socket_options_fd(evutil_socket_t fd, int tcp, int family) #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"); + if(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 */ + +#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); } @@ -879,7 +895,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; @@ -890,16 +906,56 @@ 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_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 +963,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; @@ -942,7 +998,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); @@ -1016,7 +1072,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 +1108,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 +1280,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; @@ -1284,7 +1340,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) { @@ -1590,7 +1646,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__); @@ -1600,7 +1656,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; @@ -2211,7 +2267,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)) { @@ -2297,6 +2353,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: @@ -2310,7 +2434,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); @@ -2320,7 +2444,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); @@ -2333,7 +2457,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)) { @@ -2652,7 +2776,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; } @@ -2712,24 +2836,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: TCP 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, "TCP 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, "TCP 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, "TCP 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, "TCP 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 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: TCP 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, "TCP 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); } } } @@ -3005,7 +3141,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)) { @@ -3109,7 +3245,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)) { @@ -3182,6 +3318,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, @@ -3199,6 +3336,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) { @@ -3222,6 +3360,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 03208b4a..b8a101f7 100644 --- a/src/apps/relay/tls_listener.c +++ b/src/apps/relay/tls_listener.c @@ -50,6 +50,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; @@ -120,6 +121,73 @@ 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) +{ + + 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 ; +} + +#endif + ///////////////////// operations ////////////////////////// static int create_server_listener(tls_listener_relay_server_type* server) { @@ -130,7 +198,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; @@ -145,17 +213,17 @@ 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); - 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 +255,57 @@ 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; + + 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)<0) { + close(tls_listen_fd); + return -1; + } + + socket_tcp_set_keepalive(tls_listen_fd); + + socket_set_nonblocking(tls_listen_fd); + + server->sctp_l = evconnlistener_new(server->e->event_base, + sctp_server_input_handler, server, + LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, + 1024, tls_listen_fd); + + if(!(server->sctp_l)) { + 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; +} + +#endif + static int init_server(tls_listener_relay_server_type* server, const char* ifname, const char *local_address, @@ -211,7 +330,11 @@ 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 af616aa8..d9c4cb4e 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -414,25 +414,6 @@ struct ps_arg { 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) { @@ -451,13 +432,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) @@ -512,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); @@ -978,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"); @@ -1263,14 +1244,14 @@ 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"); 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); @@ -2195,13 +2176,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) @@ -2241,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]) @@ -3337,11 +3318,10 @@ static void handle_logon_request(ioa_socket_handle s, struct http_request* hr) if(!(as->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+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; @@ -3375,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/src/apps/stunclient/stunclient.c b/src/apps/stunclient/stunclient.c index d7ff4c81..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); } @@ -258,25 +258,25 @@ 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); 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); } } 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); 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/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 c8e2e138..3153dc5d 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_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); @@ -257,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) { @@ -265,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) { @@ -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); @@ -1595,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)); @@ -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); @@ -1623,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)); 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/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 diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index d5af888d..a4b686c3 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.4.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 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 + +#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 +#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..51e44a58 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 }; @@ -206,7 +209,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); @@ -227,6 +230,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); +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); 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); diff --git a/turndb/testmongosetup.sh b/turndb/testmongosetup.sh index a266cf90..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 $* <