Imported Upstream version 4.4.4.1

upstream/latest upstream/4.4.4.1
Oleg Moskalenko 11 years ago
parent 51dbe81aaa
commit 24556a8a57
  1. 6
      ChangeLog
  2. 19
      INSTALL
  3. 19
      README.turnadmin
  4. 3
      README.turnserver
  5. 7
      README.turnutils
  6. 2
      STATUS
  7. 45
      configure
  8. 10
      examples/etc/turnserver.conf
  9. 34
      examples/scripts/longtermsecure/secure_sctp_client.sh
  10. BIN
      examples/var/db/turndb
  11. 19
      man/man1/turnadmin.1
  12. 5
      man/man1/turnserver.1
  13. 11
      man/man1/turnutils.1
  14. 2
      rpm/build.settings.sh
  15. 5
      rpm/turnserver.spec
  16. 14
      src/apps/common/apputils.c
  17. 2
      src/apps/common/apputils.h
  18. 4
      src/apps/peer/udpserver.c
  19. 24
      src/apps/relay/dtls_listener.c
  20. 39
      src/apps/relay/mainrelay.c
  21. 16
      src/apps/relay/netengine.c
  22. 209
      src/apps/relay/ns_ioalib_engine_impl.c
  23. 137
      src/apps/relay/tls_listener.c
  24. 46
      src/apps/relay/turn_admin_server.c
  25. 2
      src/apps/relay/userdb.c
  26. 12
      src/apps/stunclient/stunclient.c
  27. 10
      src/apps/uclient/mainuclient.c
  28. 16
      src/apps/uclient/startuclient.c
  29. 1
      src/apps/uclient/uclient.h
  30. 92
      src/client/ns_turn_msg.c
  31. 4
      src/client/ns_turn_msg.h
  32. 26
      src/ns_turn_defs.h
  33. 7
      src/server/ns_turn_ioalib.h
  34. 16
      src/server/ns_turn_server.c
  35. 12
      turndb/testmongosetup.sh
  36. 7
      turndb/testredisdbsetup.sh
  37. 4
      turndb/testsqldbsetup.sql

@ -1,3 +1,9 @@
3/15/2015 Oleg Moskalenko <mom040267@gmail.com>
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 <mom040267@gmail.com>
Version 4.4.2.3 'Ardee West':
- bandwidth control fixed;

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

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

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

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

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

45
configure vendored

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

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

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

Binary file not shown.

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

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

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

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

@ -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 <mom040267@gmail.com>
- Sync to 4.4.4.1
* Sat Feb 28 2015 Oleg Moskalenko <mom040267@gmail.com>
- Sync to 4.4.2.3
* Wed Feb 18 2015 Oleg Moskalenko <mom040267@gmail.com>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Loading…
Cancel
Save