1
0
Эх сурвалжийг харах

Imported Upstream version 4.4.4.1

Oleg Moskalenko 10 жил өмнө
parent
commit
24556a8a57

+ 6 - 0
ChangeLog

@@ -1,3 +1,9 @@
+3/15/2015 Oleg Moskalenko <[email protected]>
+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 <[email protected]>
 Version 4.4.2.3 'Ardee West':
 	- bandwidth control fixed;

+ 16 - 3
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.
-  
+
+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.

+ 17 - 2
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 <password>
+
+Generate a key:
 
 $ turnadmin -k -u <username> -r <realm> -p <password>
   

+ 3 - 0
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.

+ 5 - 2
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.
 

+ 2 - 0
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.

+ 44 - 1
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=\"</usr/include/netinet/sctp.h>\""
+	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

+ 9 - 1
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 

+ 34 - 0
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
+

BIN
examples/var/db/turndb


+ 18 - 1
man/man1/turnadmin.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
 
 \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 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 <password>
+.PP
 Generate a key:
 .PP
 $ \fIturnadmin\fP \fB\-k\fP \fB\-u\fP <username> \fB\-r\fP <realm> \fB\-p\fP <password>

+ 4 - 1
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

+ 8 - 3
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

+ 1 - 1
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

+ 4 - 1
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 <[email protected]>
+  - Sync to 4.4.4.1
 * Sat Feb 28 2015 Oleg Moskalenko <[email protected]>
   - Sync to 4.4.2.3
 * Wed Feb 18 2015 Oleg Moskalenko <[email protected]>

+ 8 - 6
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;
 	}

+ 1 - 1
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);
 

+ 2 - 2
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);
 

+ 12 - 12
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++<max_binding_time) {
-				  TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Trying to bind UDP/DTLS listener socket to addr %s, again...\n",saddr);
+				  TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Trying to bind DTLS/UDP listener socket to addr %s, again...\n",saddr);
 				  sleep(1);
 				  goto retry_addr_bind;
 			  }
-			  TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Fatal final failure: cannot bind UDP/DTLS listener socket to addr %s\n",saddr);
+			  TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Fatal final failure: cannot bind DTLS/UDP listener socket to addr %s\n",saddr);
 			  exit(-1);
 		  }
 	  }
@@ -797,7 +797,7 @@ static int create_server_socket(dtls_listener_relay_server_type* server, int rep
 
   if(report_creation) {
 	  if(!turn_params.no_udp && !turn_params.no_dtls)
-		  addr_debug_print(server->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;
   }
 

+ 32 - 7
src/apps/relay/mainrelay.c

@@ -583,6 +583,9 @@ static char Usage[] = "Usage: turnserver [options]\n"
 "						is 127.0.0.1.\n"
 " --cli-port=<port>				CLI server port. Default is 5766.\n"
 " --cli-password=<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;

+ 10 - 6
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;i<tot;i++) {
-			if(!(general_relay_servers[i])) {
-				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"General server %d is not initialized !\n",(int)i);
+		if(tot) {
+			TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Total General servers: %d\n",(int)tot);
+			int i;
+			for(i = 0;i<tot;i++) {
+				if(!(general_relay_servers[i])) {
+					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"General server %d is not initialized !\n",(int)i);
+				}
 			}
 		}
 	}

+ 174 - 35
src/apps/relay/ns_ioalib_engine_impl.c

@@ -50,6 +50,10 @@
 #include "hiredis_libevent2.h"
 #endif
 
+#if !defined(TURN_NO_SCTP) && defined(TURN_SCTP_INCLUDE)
+#include TURN_SCTP_INCLUDE
+#endif
+
 /* Compilation test:
 #if defined(IP_RECVTTL)
 #undef IP_RECVTTL
@@ -121,8 +125,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);
@@ -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) {

+ 130 - 7
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++<max_binding_time) {
-  		  TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Trying to bind TCP/TLS listener socket to addr %s, again...\n",saddr);
+  		  TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Trying to bind TLS/TCP listener socket to addr %s, again...\n",saddr);
   		  sleep(1);
   		  goto retry_addr_bind;
   		}
-  		TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Fatal final failure: cannot bind TCP/TLS listener socket to addr %s\n",saddr);
+  		TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Fatal final failure: cannot bind TLS/TCP listener socket to addr %s\n",saddr);
   		exit(-1);
   	 }
    }
@@ -176,7 +244,7 @@ static int create_server_listener(tls_listener_relay_server_type* server) {
   }
 
   if(!turn_params.no_tcp && !turn_params.no_tls)
-	  addr_debug_print(server->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);
 }
 

+ 14 - 32
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,"</td><td>");
-			str_buffer_append(sb,pname(tsi->client_protocol));
+			str_buffer_append(sb,socket_type_name(tsi->client_protocol));
 			str_buffer_append(sb,"</td><td>");
-			str_buffer_append(sb,pname(tsi->peer_protocol));
+			str_buffer_append(sb,socket_type_name(tsi->peer_protocol));
 			str_buffer_append(sb,"</td><td>");
 			{
 				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__);
 		}

+ 1 - 1
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 {

+ 6 - 6
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);
 	}
 

+ 8 - 2
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': */

+ 9 - 7
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));
 

+ 1 - 0
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];

+ 90 - 2
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;i<PWD_SALT_SIZE;++i) {
+				const char* c = pin+3+i+i;
+				char sc[3];
+				sc[0]=c[0];
+				sc[1]=c[1];
+				sc[2]=0;
+				salt[i] = (unsigned char)strtoul(sc,NULL,16);
+			}
+			return 1;
+		}
+	}
+	return 0;
+}
+
+int check_password(const char* pin, const char* pwd)
+{
+	unsigned char salt[PWD_SALT_SIZE];
+	if(!encrypted_password(pwd,salt)) {
+		return strcmp(pin,pwd);
+	}
+	char enc_pin[257];
+	generate_enc_password(pin, enc_pin, salt);
+	return strcmp(enc_pin,pwd);
+}
+
 /////////////////////////////////////////////////////////////////
 
 static u32bits ns_crc32(const u08bits *buffer, u32bits len);
@@ -2377,8 +2465,6 @@ static int decode_oauth_token_normal(const u08bits *server_name, const encoded_o
 	return -1;
 }
 
-#if !defined(TURN_NO_GCM)
-
 static void generate_random_nonce(unsigned char *nonce, size_t sz) {
 	if(!RAND_bytes(nonce, sz)) {
 		size_t i;
@@ -2388,6 +2474,8 @@ 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)) {

+ 4 - 0
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

+ 25 - 1
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

+ 6 - 1
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);

+ 8 - 8
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);

+ 10 - 2
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 $* <<EOF
 
 use coturn;
@@ -20,8 +28,8 @@ db.turn_secret.insert({ realm: 'north.gov', value: 'bloody9' });
 db.turn_secret.insert({ realm: 'crinna.org', value: 'north' });
 db.turn_secret.insert({ realm: 'crinna.org', value: 'library' });
 
-db.admin_user.insert({ name: 'skarling', realm: 'north.gov', password: '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',

+ 5 - 2
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 <<!
 
@@ -39,8 +42,8 @@ hmset turn/oauth/kid/north ikm_key 'Y2FybGVvbg==' hkdf_hash_func 'SHA-256' as_rs
 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'
-hmset turn/admin_user/bayaz password 'magi'
+hmset turn/admin_user/skarling realm 'north.gov' password '\$5\$6fc35c3b0c7d4633\$27fca7574f9b79d0cb93ae03e45379470cbbdfcacdd6401f97ebc620f31f54f2'
+hmset turn/admin_user/bayaz password '\$5\$e018513e9de69e73\$5cbdd2e29e04ca46aeb022268a7460d3a3468de193dcb2b95f064901769f455f'
 
 save
 

+ 2 - 2
turndb/testsqldbsetup.sql

@@ -9,8 +9,8 @@ insert into turn_secret (realm,value) values('north.gov','bloody9');
 insert into turn_secret (realm,value) values('crinna.org','north');
 insert into turn_secret (realm,value) values('crinna.org','library');
 
-insert into admin_user (name, realm, password) values('skarling','north.gov','hoodless');
-insert into admin_user (name, realm, password) values('bayaz','','magi');
+insert into admin_user (name, realm, password) values('skarling','north.gov','$5$6fc35c3b0c7d4633$27fca7574f9b79d0cb93ae03e45379470cbbdfcacdd6401f97ebc620f31f54f2');
+insert into admin_user (name, realm, password) values('bayaz','','$5$e018513e9de69e73$5cbdd2e29e04ca46aeb022268a7460d3a3468de193dcb2b95f064901769f455f');
 
 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');