Imported Upstream version 4.4.2.1

upstream/latest upstream/4.4.2.1
Oleg Moskalenko 11 years ago
parent 0a724b06bb
commit 07e4b759a7
  1. 7
      ChangeLog
  2. 41
      INSTALL
  3. 4
      README.turnadmin
  4. 4
      README.turnserver
  5. 4
      README.turnutils
  6. 2
      STATUS
  7. 2
      TODO
  8. 12
      examples/etc/turnserver.conf
  9. BIN
      examples/var/db/turndb
  10. 10
      man/man1/turnadmin.1
  11. 10
      man/man1/turnserver.1
  12. 10
      man/man1/turnutils.1
  13. 2
      rpm/build.settings.sh
  14. 4
      rpm/turnserver.spec
  15. 125
      src/apps/common/apputils.c
  16. 8
      src/apps/common/apputils.h
  17. 14
      src/apps/relay/dtls_listener.c
  18. 32
      src/apps/relay/mainrelay.c
  19. 138
      src/apps/relay/ns_ioalib_engine_impl.c
  20. 46
      src/apps/relay/turn_admin_server.c
  21. 22
      src/apps/relay/userdb.c
  22. 20
      src/apps/rfc5769/rfc5769check.c
  23. 42
      src/apps/uclient/mainuclient.c
  24. 43
      src/apps/uclient/startuclient.c
  25. 15
      src/apps/uclient/uclient.c
  26. 4
      src/apps/uclient/uclient.h
  27. 176
      src/client/ns_turn_msg.c
  28. 2
      src/client/ns_turn_msg_defs.h
  29. 13
      src/client/ns_turn_msg_defs_new.h
  30. 2
      src/ns_turn_defs.h
  31. 6
      src/server/ns_turn_allocation.c
  32. 2
      src/server/ns_turn_allocation.h
  33. 44
      src/server/ns_turn_server.c
  34. 2
      turndb/schema.sql
  35. 10
      turndb/schema.userdb.redis
  36. 6
      turndb/testmongosetup.sh
  37. 1
      turndb/testredisdbsetup.sh
  38. 1
      turndb/testsqldbsetup.sql

@ -1,3 +1,10 @@
2/3/2015 Oleg Moskalenko <mom040267@gmail.com>
Version 4.4.2.1 'Ardee West':
- (HMAC-)SHA-512 and -384 algorithms added;
- TOS (DiffServer) and TTL IP header field handling fixed;
- updates according to the new third-party-auth draft (oauth);
- peer logging added;
2/1/2015 Oleg Moskalenko <mom040267@gmail.com>
Version 4.4.1.2 'Ardee West':
- SSODA updates according to turnbis specs;

@ -470,14 +470,15 @@ libevent2 from their web site. It was tested with older *NIXes
NOTE: SQLite must be of version 3.x.
NOTE: For extra security features (DTLS and SHA256) support, OpenSSL version
1.0.0a or newer is recommended. Older versions do not support DTLS, reliably,
in some cases. For example, the Debian 'Squeeze' Linux supplies 0.9.8 version
of OpenSSL, that does not work correctly with DTLS over IPv6. If your system
already has an older version of OpenSSL installed (usually in directory /usr)
then you may want to install your newer OpenSSL "over" the old one (because it
will most probably will not allow removal of the old one). When installing
the newer OpenSSL, run the OpenSSL's configure command like this:
NOTE: For extra security features (DTLS and SHA256 and and SHA384 and SHA512)
support, OpenSSL version 1.0.0a or newer is recommended. Older versions do
not support DTLS, reliably, in some cases. For example, the Debian 'Squeeze'
Linux supplies 0.9.8 version of OpenSSL, that does not work correctly with
DTLS over IPv6. If your system already has an older version of OpenSSL
installed (usually in directory /usr) then you may want to install your
newer OpenSSL "over" the old one (because it will most probably will not allow
removal of the old one). When installing the newer OpenSSL, run the OpenSSL's
configure command like this:
$ ./config --prefix=/usr
@ -676,13 +677,15 @@ CREATE TABLE turnusers_lt (
);
The field hmackey contains HEX string representation of the key.
We do not store the user open passwords for long-term credentials, for security reasons.
Storing only the HMAC key has its own implications - if you change the realm,
you will have to update the HMAC keys of all users, because the realm is
used for the HMAC key generation.
We do not store the user open passwords for long-term credentials, for
security reasons. Storing only the HMAC key has its own implications -
if you change the realm, you will have to update the HMAC keys of all
users, because the realm is used for the HMAC key generation.
The key must be 32 characters (HEX representation of 16 bytes) for SHA1,
or 64 characters (HEX representation of 32 bytes) for SHA256.
The key must be up to 32 characters (HEX representation of 16 bytes) for SHA1,
or up to 64 characters (HEX representation of 32 bytes) for SHA256,
or up to 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
@ -763,9 +766,10 @@ The oauth_key table fields meanings are:
is 0 - unlimited lifetime.
hkdf_hash_func - (optional) hash function for HKDF procedure; the
valid values are SHA-1 and SHA-256, with SHA-256 as default;
The hkdf_hash_func is not needed if the as_rs_key and auth_key
are defined explicitly in the database;
valid values are SHA-1, SHA-256, SHA-384 and SHA-512,
with SHA-256 as default. The hkdf_hash_func is not needed
if the as_rs_key and auth_key are defined explicitly
in the database;
as_rs_alg - oAuth token encryption algorithm; the valid values are
"AES-128-CBC" and "AES-256-CBC", , "AEAD-AES-128-GCM",
@ -777,7 +781,8 @@ The oauth_key table fields meanings are:
is defined by as_rs_alg.
auth_alg - (optional) oAuth token authentication algorithm; the valid values are
"HMAC-SHA-256-128", "HMAC-SHA-256" and "HMAC-SHA-1".
"HMAC-SHA-256-128", "HMAC-SHA-256", "HMAC-SHA-384",
"HMAC-SHA-512" and "HMAC-SHA-1".
The default value is "HMAC-SHA-256-128".
auth_key - (optional) base64-encoded AUTH key. If not defined, then

@ -95,9 +95,11 @@ Options with required values:
-r, --realm Realm.
-p, --password Password.
-o, --origin Origin
-H, --sha256 Use SHA256 as the keys hash function (a non-standard feature).
-H, --sha256 Use SHA256 as the keys hash function (a non-standard feature).
By default, MD5 is used for the key storage encryption
(as required by the current STUN/TURNstandards).
-Y, --sha384 Use SHA384 as the keys hash function (a non-standard feature).
-K, --sha512 Use SHA512 as the keys hash function (a non-standard feature).
--max-bps Set value of realm's max-bps parameter.
--total-quota Set value of realm's total-quota parameter.
--user-quota Set value of realm's user-quota parameter.

@ -242,6 +242,10 @@ Flags:
SHA256 hash function if this option is used. If the server obtains a message
from the client with a weaker (SHA1) hash function then the server returns
error code 426.
--sha384 Require SHA384 digest function to be used for the message integrity.
--sha512 Require SHA512 digest function to be used for the message integrity.
--mobility Mobility with ICE (MICE) specs support.

@ -94,6 +94,10 @@ Flags:
-H SHA256 digest function for message integrity calculation.
Without this option, by default, SHA1 is used.
-Y SHA384 digest function for message integrity calculation.
-K SHA512 digest function for message integrity calculation.
-M Use TURN ICE Mobility.

@ -119,6 +119,8 @@ compatibility.
supported in the client library).
52) Web HTTPS admin interface implemented.
53) SHA384 and SHA512 support added (experimental).
Things to be implemented in future (the development roadmap)
are described in the TODO file.

@ -90,7 +90,7 @@
==================================================================
1) Peer for TCP relay.
1) Peer app for TCP relay.
==================================================================

@ -557,15 +557,17 @@
#
#secure-stun
# Require SHA256 digest function to be used for the message integrity.
# By default, the server uses SHA1 (as per TURN standard specs).
# With this option, the server
# always requires the stronger SHA256 function. The client application
# must support SHA256 hash function if this option is used. If the server obtains
# Require SHA256, or SHA384, or SHA512 digest function to be used for the message
# integrity. By default, the server uses SHA1 (as per TURN standard specs).
# With this option, the server always requires the stronger SHA256, SHA384 or SHA512
# function. The client application must support SHA256, SHA384 or SHA512 hash function
# if this option is used. If the server obtains
# a message from the client with a weaker (SHA1) hash function then the
# server returns error code 426.
#
#sha256
#sha384
#sha512
# Mobility with ICE (MICE) specs support.
#

Binary file not shown.

@ -1,5 +1,5 @@
.\" Text automatically generated by txt2man
.TH TURN 1 "31 January 2015" "" ""
.TH TURN 1 "06 February 2015" "" ""
.SH GENERAL INFORMATION
\fIturnadmin\fP is a TURN administration tool. This tool can be used to manage
@ -179,6 +179,14 @@ By default, MD5 is used for the key storage encryption
(as required by the current STUN/TURNstandards).
.TP
.B
\fB\-Y\fP, \fB\-\-sha384\fP
Use SHA384 as the keys hash function (a non\-standard feature).
.TP
.B
\fB\-K\fP, \fB\-\-sha512\fP
Use SHA512 as the keys hash function (a non\-standard feature).
.TP
.B
\fB\-\-max\-bps\fP
Set value of realm's max\-bps parameter.
.TP

@ -1,5 +1,5 @@
.\" Text automatically generated by txt2man
.TH TURN 1 "31 January 2015" "" ""
.TH TURN 1 "06 February 2015" "" ""
.SH GENERAL INFORMATION
The \fBTURN Server\fP project contains the source code of a TURN server and TURN client
@ -372,6 +372,14 @@ from the client with a weaker (SHA1) hash function then the server returns
error code 426.
.TP
.B
\fB\-\-sha384\fP
Require SHA384 digest function to be used for the message integrity.
.TP
.B
\fB\-\-sha512\fP
Require SHA512 digest function to be used for the message integrity.
.TP
.B
\fB\-\-mobility\fP
Mobility with ICE (MICE) specs support.
.TP

@ -1,5 +1,5 @@
.\" Text automatically generated by txt2man
.TH TURN 1 "31 January 2015" "" ""
.TH TURN 1 "06 February 2015" "" ""
.SH GENERAL INFORMATION
A set of turnutils_* programs provides some utility functionality to be used
@ -143,6 +143,14 @@ SHA256 digest function for message integrity calculation.
Without this option, by default, SHA1 is used.
.TP
.B
\fB\-Y\fP
SHA384 digest function for message integrity calculation.
.TP
.B
\fB\-K\fP
SHA512 digest function for message integrity calculation.
.TP
.B
\fB\-M\fP
Use TURN ICE Mobility.
.TP

@ -2,7 +2,7 @@
# Common settings script.
TURNVERSION=4.4.1.2
TURNVERSION=4.4.2.1
BUILDDIR=~/rpmbuild
ARCH=`uname -p`
TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn

@ -1,5 +1,5 @@
Name: turnserver
Version: 4.4.1.2
Version: 4.4.2.1
Release: 0%{dist}
Summary: Coturn TURN Server
@ -288,6 +288,8 @@ fi
%{_includedir}/turn/client/TurnMsgLib.h
%changelog
* Tue Feb 3 2015 Oleg Moskalenko <mom040267@gmail.com>
- Sync to 4.4.2.1
* Sun Feb 1 2015 Oleg Moskalenko <mom040267@gmail.com>
- Sync to 4.4.1.2
* Sat Jan 24 2015 Oleg Moskalenko <mom040267@gmail.com>

@ -289,6 +289,131 @@ int addr_get_from_sock(evutil_socket_t fd, ioa_addr *addr)
}
}
int get_raw_socket_ttl(evutil_socket_t fd, int family)
{
int ttl = 0;
if(family == AF_INET6) {
#if !defined(IPV6_UNICAST_HOPS)
UNUSED_ARG(fd);
do { return TTL_IGNORE; } while(0);
#else
socklen_t slen = (socklen_t)sizeof(ttl);
if(getsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,&slen)<0) {
perror("get HOPLIMIT on socket");
return TTL_IGNORE;
}
#endif
} else {
#if !defined(IP_TTL)
UNUSED_ARG(fd);
do { return TTL_IGNORE; } while(0);
#else
socklen_t slen = (socklen_t)sizeof(ttl);
if(getsockopt(fd, IPPROTO_IP, IP_TTL, &ttl,&slen)<0) {
perror("get TTL on socket");
return TTL_IGNORE;
}
#endif
}
CORRECT_RAW_TTL(ttl);
return ttl;
}
int get_raw_socket_tos(evutil_socket_t fd, int family)
{
int tos = 0;
if(family == AF_INET6) {
#if !defined(IPV6_TCLASS)
UNUSED_ARG(fd);
do { return TOS_IGNORE; } while(0);
#else
socklen_t slen = (socklen_t)sizeof(tos);
if(getsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos,&slen)<0) {
perror("get TCLASS on socket");
return -1;
}
#endif
} else {
#if !defined(IP_TOS)
UNUSED_ARG(fd);
do { return TOS_IGNORE; } while(0);
#else
socklen_t slen = (socklen_t)sizeof(tos);
if(getsockopt(fd, IPPROTO_IP, IP_TOS, &tos,&slen)<0) {
perror("get TOS on socket");
return -1;
}
#endif
}
CORRECT_RAW_TOS(tos);
return tos;
}
int set_raw_socket_ttl(evutil_socket_t fd, int family, int ttl)
{
if(family == AF_INET6) {
#if !defined(IPV6_UNICAST_HOPS)
UNUSED_ARG(fd);
UNUSED_ARG(ttl);
#else
CORRECT_RAW_TTL(ttl);
if(setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,sizeof(ttl))<0) {
perror("set HOPLIMIT on socket");
return -1;
}
#endif
} else {
#if !defined(IP_TTL)
UNUSED_ARG(fd);
UNUSED_ARG(ttl);
#else
CORRECT_RAW_TTL(ttl);
if(setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl,sizeof(ttl))<0) {
perror("set TTL on socket");
return -1;
}
#endif
}
return 0;
}
int set_raw_socket_tos(evutil_socket_t fd, int family, int tos)
{
if(family == AF_INET6) {
#if !defined(IPV6_TCLASS)
UNUSED_ARG(fd);
UNUSED_ARG(tos);
#else
CORRECT_RAW_TOS(tos);
if(setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos,sizeof(tos))<0) {
perror("set TCLASS on socket");
return -1;
}
#endif
} else {
#if !defined(IP_TOS)
UNUSED_ARG(fd);
UNUSED_ARG(tos);
#else
if(setsockopt(fd, IPPROTO_IP, IP_TOS, &tos,sizeof(tos))<0) {
perror("set TOS on socket");
return -1;
}
#endif
}
return 0;
}
/////////////////// MTU /////////////////////////////////////////
int set_socket_df(evutil_socket_t fd, int family, int value)

@ -186,6 +186,14 @@ int addr_get_from_sock(evutil_socket_t fd, ioa_addr *addr);
int handle_socket_error(void);
#define CORRECT_RAW_TTL(ttl) do { if(ttl<0 || ttl>255) ttl=TTL_DEFAULT; } while(0)
#define CORRECT_RAW_TOS(tos) do { if(tos<0 || tos>255) tos=TOS_DEFAULT; } while(0)
int set_raw_socket_tos(evutil_socket_t fd, int family, int tos);
int set_raw_socket_ttl(evutil_socket_t fd, int family, int ttl);
int get_raw_socket_tos(evutil_socket_t fd, int family);
int get_raw_socket_ttl(evutil_socket_t fd, int family);
/////////////////////// SYS /////////////////////
void ignore_sigpipe(void);

@ -638,14 +638,14 @@ static void udp_server_input_handler(evutil_socket_t fd, short what, void* arg)
addr_set_any(&(server->sm.m.sm.nd.src_addr));
int slen = server->slen0;
ssize_t bsize = 0;
int flags = 0;
int flags = MSG_DONTWAIT;
do {
bsize = recvfrom(fd, ioa_network_buffer_data(elem), ioa_network_buffer_get_capacity_udp(), flags, (struct sockaddr*) &(server->sm.m.sm.nd.src_addr), (socklen_t*) &slen);
} while (bsize < 0 && (errno == EINTR));
bsize = udp_recvfrom(fd, &(server->sm.m.sm.nd.src_addr), &(server->addr),
(s08bits*)ioa_network_buffer_data(elem), (int)ioa_network_buffer_get_capacity_udp(),
&(server->sm.m.sm.nd.recv_ttl), &(server->sm.m.sm.nd.recv_tos),
server->e->cmsg, flags, NULL);
int conn_reset = is_connreset();
int to_block = would_block();
@ -668,6 +668,7 @@ static void udp_server_input_handler(evutil_socket_t fd, short what, void* arg)
ioa_addr orig_addr;
int ttl = 0;
int tos = 0;
int slen = server->slen0;
udp_recvfrom(fd, &orig_addr, &(server->addr), buffer,
(int) sizeof(buffer), &ttl, &tos, server->e->cmsg, eflags,
&errcode);
@ -762,6 +763,9 @@ static int create_server_socket(dtls_listener_relay_server_type* server, int rep
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind listener socket to device %s\n",server->ifname);
}
set_raw_socket_ttl_options(udp_listen_fd, server->addr.ss.sa_family);
set_raw_socket_tos_options(udp_listen_fd, server->addr.ss.sa_family);
{
const int max_binding_time = 60;
int addr_bind_cycle = 0;

@ -569,6 +569,8 @@ static char Usage[] = "Usage: turnserver [options]\n"
" support SHA256 hash function if this option is used. If the server obtains\n"
" a message from the client with a weaker (SHA1) hash function then the server\n"
" returns error code 426.\n"
" --sha384 Require SHA384 digest function to be used for the message integrity.\n"
" --sha512 Require SHA512 digest function to be used for the message integrity.\n"
" --proc-user <user-name> User name to run the turnserver process.\n"
" After the initialization, the turnserver process\n"
" will make an attempt to change the current user ID to that user.\n"
@ -638,6 +640,8 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n"
#endif
" -H, --sha256 Use SHA256 digest function to be used for the message integrity.\n"
" By default, the server SHA1 (as per TURN standard specs).\n"
" -Y, --sha384 Use SHA384 digest function to be used for the message integrity.\n"
" -K, --sha512 Use SHA512 digest function to be used for the message integrity.\n"
" --max-bps Set value of realm's max-bps parameter.\n"
" Setting to zero value means removal of the option.\n"
" --total-quota Set value of realm's total-quota parameter.\n"
@ -648,7 +652,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n"
#define OPTIONS "c:d:p:L:E:X:i:m:l:r:u:b:B:e:M:J:N:O:q:Q:s:C:vVofhznaAS"
#define ADMIN_OPTIONS "gGORIHlLkaADSdb:e:M:J:N:u:r:p:s:X:o:h"
#define ADMIN_OPTIONS "gGORIHKYlLkaADSdb:e:M:J:N:u:r:p:s:X:o:h"
enum EXTRA_OPTS {
NO_UDP_OPT=256,
@ -688,6 +692,8 @@ enum EXTRA_OPTS {
CA_FILE_OPT,
DH_FILE_OPT,
SHA256_OPT,
SHA384_OPT,
SHA512_OPT,
NO_STUN_OPT,
PROC_USER_OPT,
PROC_GROUP_OPT,
@ -811,6 +817,8 @@ static const struct myoption long_options[] = {
{ "CA-file", required_argument, NULL, CA_FILE_OPT },
{ "dh-file", required_argument, NULL, DH_FILE_OPT },
{ "sha256", optional_argument, NULL, SHA256_OPT },
{ "sha384", optional_argument, NULL, SHA384_OPT },
{ "sha512", optional_argument, NULL, SHA512_OPT },
{ "proc-user", required_argument, NULL, PROC_USER_OPT },
{ "proc-group", required_argument, NULL, PROC_GROUP_OPT },
{ "mobility", optional_argument, NULL, MOBILITY_OPT },
@ -865,6 +873,8 @@ static const struct myoption admin_long_options[] = {
{ "realm", required_argument, NULL, 'r' },
{ "password", required_argument, NULL, 'p' },
{ "sha256", no_argument, NULL, 'H' },
{ "sha384", no_argument, NULL, 'Y' },
{ "sha512", no_argument, NULL, 'K' },
{ "add-origin", no_argument, NULL, 'O' },
{ "del-origin", no_argument, NULL, 'R' },
{ "list-origins", required_argument, NULL, 'I' },
@ -1031,8 +1041,14 @@ static void set_option(int c, char *value)
case SHA256_OPT:
if(get_bool_value(value))
turn_params.shatype = SHATYPE_SHA256;
else
turn_params.shatype = SHATYPE_SHA1;
break;
case SHA384_OPT:
if(get_bool_value(value))
turn_params.shatype = SHATYPE_SHA384;
break;
case SHA512_OPT:
if(get_bool_value(value))
turn_params.shatype = SHATYPE_SHA512;
break;
case NO_MULTICAST_PEERS_OPT:
turn_params.no_multicast_peers = get_bool_value(value);
@ -1554,8 +1570,14 @@ static int adminmain(int argc, char **argv)
case 'H':
if(get_bool_value(optarg))
turn_params.shatype = SHATYPE_SHA256;
else
turn_params.shatype = SHATYPE_SHA1;
break;
case 'Y':
if(get_bool_value(optarg))
turn_params.shatype = SHATYPE_SHA384;
break;
case 'K':
if(get_bool_value(optarg))
turn_params.shatype = SHATYPE_SHA512;
break;
case 'h':
printf("\n%s\n", AdminUsage);

@ -355,16 +355,16 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm,
#if !defined(CMSG_SPACE)
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "On this platform, I am using alternative behavior of TTL/TOS according to RFC 5766.\n");
#endif
#if !defined(IP_RECVTTL)
#if !defined(IP_RECVTTL) || !defined(IP_TTL)
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv4: On this platform, I am using alternative behavior of TTL according to RFC 5766.\n");
#endif
#if !defined(IPV6_RECVHOPLIMIT)
#if !defined(IPV6_RECVHOPLIMIT) || !defined(IPV6_HOPLIMIT)
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv6: On this platform, I am using alternative behavior of TTL (HOPLIMIT) according to RFC 6156.\n");
#endif
#if !defined(IP_RECVTOS)
#if !defined(IP_RECVTOS) || !defined(IP_TOS)
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv4: On this platform, I am using alternative behavior of TOS according to RFC 5766.\n");
#endif
#if !defined(IPV6_RECVTCLASS)
#if !defined(IPV6_RECVTCLASS) || !defined(IPV6_TCLASS)
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv6: On this platform, I am using alternative behavior of TRAFFIC CLASS according to RFC 6156.\n");
#endif
}
@ -706,134 +706,6 @@ int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_
/* Socket options helpers ==>> */
#define CORRECT_RAW_TTL(ttl) do { if(ttl<0 || ttl>255) ttl=TTL_DEFAULT; } while(0)
#define CORRECT_RAW_TOS(tos) do { if(tos<0 || tos>255) tos=TOS_DEFAULT; } while(0)
static int get_raw_socket_ttl(evutil_socket_t fd, int family)
{
int ttl = 0;
if(family == AF_INET6) {
#if !defined(IPV6_RECVHOPLIMIT)
UNUSED_ARG(fd);
do { return TTL_IGNORE; } while(0);
#else
socklen_t slen = (socklen_t)sizeof(ttl);
if(getsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,&slen)<0) {
perror("get HOPLIMIT on socket");
return TTL_IGNORE;
}
#endif
} else {
#if !defined(IP_RECVTTL)
UNUSED_ARG(fd);
do { return TTL_IGNORE; } while(0);
#else
socklen_t slen = (socklen_t)sizeof(ttl);
if(getsockopt(fd, IPPROTO_IP, IP_TTL, &ttl,&slen)<0) {
perror("get TTL on socket");
return TTL_IGNORE;
}
#endif
}
CORRECT_RAW_TTL(ttl);
return ttl;
}
static int get_raw_socket_tos(evutil_socket_t fd, int family)
{
int tos = 0;
if(family == AF_INET6) {
#if !defined(IPV6_RECVTCLASS)
UNUSED_ARG(fd);
do { return TOS_IGNORE; } while(0);
#else
socklen_t slen = (socklen_t)sizeof(tos);
if(getsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos,&slen)<0) {
perror("get TCLASS on socket");
return -1;
}
#endif
} else {
#if !defined(IP_RECVTOS)
UNUSED_ARG(fd);
do { return TOS_IGNORE; } while(0);
#else
socklen_t slen = (socklen_t)sizeof(tos);
if(getsockopt(fd, IPPROTO_IP, IP_TOS, &tos,&slen)<0) {
perror("get TOS on socket");
return -1;
}
#endif
}
CORRECT_RAW_TOS(tos);
return tos;
}
static int set_raw_socket_ttl(evutil_socket_t fd, int family, int ttl)
{
if(family == AF_INET6) {
#if !defined(IPV6_RECVHOPLIMIT)
UNUSED_ARG(fd);
UNUSED_ARG(ttl);
#else
CORRECT_RAW_TTL(ttl);
if(setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,sizeof(ttl))<0) {
perror("set HOPLIMIT on socket");
return -1;
}
#endif
} else {
#if !defined(IP_RECVTTL)
UNUSED_ARG(fd);
UNUSED_ARG(ttl);
#else
CORRECT_RAW_TTL(ttl);
if(setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl,sizeof(ttl))<0) {
perror("set TTL on socket");
return -1;
}
#endif
}
return 0;
}
static int set_raw_socket_tos(evutil_socket_t fd, int family, int tos)
{
if(family == AF_INET6) {
#if !defined(IPV6_RECVTCLASS)
UNUSED_ARG(fd);
UNUSED_ARG(tos);
#else
CORRECT_RAW_TOS(tos);
if(setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos,sizeof(tos))<0) {
perror("set TCLASS on socket");
return -1;
}
#endif
} else {
#if !defined(IPV6_RECVTOS)
UNUSED_ARG(fd);
UNUSED_ARG(tos);
#else
if(setsockopt(fd, IPPROTO_IP, IP_TOS, &tos,sizeof(tos))<0) {
perror("set TOS on socket");
return -1;
}
#endif
}
return 0;
}
static int set_socket_ttl(ioa_socket_handle s, int ttl)
{
if(s->default_ttl < 0) //Unsupported
@ -1733,6 +1605,8 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s)
close(udp_fd);
return ret;
}
set_raw_socket_ttl_options(udp_fd, s->local_addr.ss.sa_family);
set_raw_socket_tos_options(udp_fd, s->local_addr.ss.sa_family);
}
detach_socket_net_data(s);

@ -712,6 +712,10 @@ static void cli_print_configuration(struct cli_session* cs)
if(turn_params.shatype == SHATYPE_SHA256)
cli_print_str(cs,"SHA256","SHA type",0);
else if(turn_params.shatype == SHATYPE_SHA384)
cli_print_str(cs,"SHA384","SHA type",0);
else if(turn_params.shatype == SHATYPE_SHA512)
cli_print_str(cs,"SHA512","SHA type",0);
else
cli_print_str(cs,"SHA1","SHA type",0);
myprintf(cs,"\n");
@ -1979,6 +1983,10 @@ static void write_pc_page(ioa_socket_handle s)
if(turn_params.shatype == SHATYPE_SHA256)
https_print_str(sb,"SHA256","SHA type",0);
else if(turn_params.shatype == SHATYPE_SHA384)
https_print_str(sb,"SHA384","SHA type",0);
else if(turn_params.shatype == SHATYPE_SHA512)
https_print_str(sb,"SHA512","SHA type",0);
else
https_print_str(sb,"SHA1","SHA type",0);
@ -2508,6 +2516,10 @@ static void write_users_page(ioa_socket_handle s, const u08bits *add_user, const
if(turn_params.shatype == SHATYPE_SHA256)
str_buffer_append(sb,"SHA type: SHA256<br>\r\n");
else if(turn_params.shatype == SHATYPE_SHA384)
str_buffer_append(sb,"SHA type: SHA384<br>\r\n");
else if(turn_params.shatype == SHATYPE_SHA512)
str_buffer_append(sb,"SHA type: SHA512<br>\r\n");
else
str_buffer_append(sb,"SHA type: SHA1<br>\r\n");
@ -3043,10 +3055,26 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con
str_buffer_append(sb,"<input type=\"radio\" name=\"");
str_buffer_append(sb,HR_ADD_OAUTH_HKDF);
str_buffer_append(sb,"\" value=\"SHA-256\" ");
if(strcmp("SHA-1",add_hkdf_hash_func)) {
if(!strcmp("SHA-256",add_hkdf_hash_func)) {
str_buffer_append(sb," checked ");
}
str_buffer_append(sb,">SHA-256\r\n<br>\r\n");
str_buffer_append(sb,"<input type=\"radio\" name=\"");
str_buffer_append(sb,HR_ADD_OAUTH_HKDF);
str_buffer_append(sb,"\" value=\"SHA-384\" ");
if(!strcmp("SHA-384",add_hkdf_hash_func)) {
str_buffer_append(sb," checked ");
}
str_buffer_append(sb,">SHA-384\r\n<br>\r\n");
str_buffer_append(sb,"<input type=\"radio\" name=\"");
str_buffer_append(sb,HR_ADD_OAUTH_HKDF);
str_buffer_append(sb,"\" value=\"SHA-512\" ");
if(!strcmp("SHA-512",add_hkdf_hash_func)) {
str_buffer_append(sb," checked ");
}
str_buffer_append(sb,">SHA-512\r\n<br>\r\n");
}
str_buffer_append(sb,"</td><td colspan=\"2\">");
@ -3140,6 +3168,22 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con
}
str_buffer_append(sb,">HMAC-SHA-256\r\n<br>\r\n");
str_buffer_append(sb,"<input type=\"radio\" name=\"");
str_buffer_append(sb,HR_ADD_OAUTH_AA);
str_buffer_append(sb,"\" value=\"HMAC-SHA-384\" ");
if(!strcmp("HMAC-SHA-384",add_aa)) {
str_buffer_append(sb," checked ");
}
str_buffer_append(sb,">HMAC-SHA-384\r\n<br>\r\n");
str_buffer_append(sb,"<input type=\"radio\" name=\"");
str_buffer_append(sb,HR_ADD_OAUTH_AA);
str_buffer_append(sb,"\" value=\"HMAC-SHA-512\" ");
if(!strcmp("HMAC-SHA-512",add_aa)) {
str_buffer_append(sb," checked ");
}
str_buffer_append(sb,">HMAC-SHA-512\r\n<br>\r\n");
str_buffer_append(sb,"<input type=\"radio\" name=\"");
str_buffer_append(sb,HR_ADD_OAUTH_AA);
str_buffer_append(sb,"\" value=\"HMAC-SHA-1\" ");

@ -495,6 +495,18 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u
return -1;
}
break;
case SHA384SIZEBYTES:
if(turn_params.shatype != SHATYPE_SHA384) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(3): %d\n",(int)dot.enc_block.key_length);
return -1;
}
break;
case SHA512SIZEBYTES:
if(turn_params.shatype != SHATYPE_SHA512) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(3): %d\n",(int)dot.enc_block.key_length);
return -1;
}
break;
default:
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong size of the MAC key in oAuth token(3): %d\n",(int)dot.enc_block.key_length);
return -1;
@ -575,6 +587,16 @@ int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *u
return -1;
hmac_len = SHA256SIZEBYTES;
break;
case SHA384SIZEBYTES:
if(turn_params.shatype != SHATYPE_SHA384)
return -1;
hmac_len = SHA384SIZEBYTES;
break;
case SHA512SIZEBYTES:
if(turn_params.shatype != SHATYPE_SHA512)
return -1;
hmac_len = SHA512SIZEBYTES;
break;
default:
return -1;
};

@ -44,6 +44,12 @@
static const char* shas[]={"SHA1",
#if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH)
"SHA256",
#endif
#if !defined(OPENSSL_NO_SHA384) && defined(SHA384_DIGEST_LENGTH)
"SHA384",
#endif
#if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH)
"SHA512",
#endif
NULL};
static const char* encs[]={"AES-256-CBC","AES-128-CBC",
@ -54,6 +60,12 @@ static const char* encs[]={"AES-256-CBC","AES-128-CBC",
static const char* hmacs[]={"HMAC-SHA-1",
#if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH)
"HMAC-SHA-256","HMAC-SHA-256-128",
#endif
#if !defined(OPENSSL_NO_SHA384) && defined(SHA384_DIGEST_LENGTH)
"HMAC-SHA-384",
#endif
#if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH)
"HMAC-SHA-512",
#endif
NULL};
@ -65,7 +77,7 @@ void print_field5769(const char* name, const void* f0, size_t len) {
printf("\nfield %s %lu==>>\n",name,(unsigned long)len);
size_t i;
for(i = 0;i<len;++i) {
printf("\\x%x",(unsigned int)f[i]);
printf("\\x%02x",(unsigned int)f[i]);
}
printf("\n<<==field %s\n",name);
}
@ -76,12 +88,12 @@ static int check_oauth(void) {
size_t i_hmacs,i_shas,i_encs;
const char long_term_password[33] = "HGkj32KJGiuy098sdfaqbNjOiaz71923";
const char long_term_key[33] = "HGkj32KJGiuy098sdfaqbNjOiaz71923";
size_t ltp_output_length=0;
const char* base64encoded_ltp = base64_encode((const unsigned char *)long_term_password,
strlen(long_term_password),
const char* base64encoded_ltp = base64_encode((const unsigned char *)long_term_key,
strlen(long_term_key),
&ltp_output_length);
const char mac_key[33] = "ZksjpweoixXmvn67534m";

@ -98,10 +98,11 @@ band_limit_t bps = 0;
int dual_allocation = 0;
int oauth = 0;
oauth_key okey_array[2];
oauth_key okey_array[3];
static oauth_key_data_raw okdr_array[2] = {
static oauth_key_data_raw okdr_array[3] = {
{"north","Y2FybGVvbg==",0,0,"SHA-256","AES-256-CBC","","HMAC-SHA-256-128",""},
{"union","aGVyb2Q=",0,0,"SHA-256","AES-256-CBC","","HMAC-SHA-512",""},
{"oldempire","YXVsY3Vz",0,0,"SHA-256","AEAD-AES-256-GCM","","",""}
};
@ -130,6 +131,8 @@ static char Usage[] =
" -O DOS attack mode (quick connect and exit).\n"
" -H SHA256 digest function for message integrity calculation.\n"
" Without this option, by default, SHA1 is used.\n"
" -Y SHA384 digest function for message integrity calculation.\n"
" -K SHA512 digest function for message integrity calculation.\n"
" -M ICE Mobility engaged.\n"
" -I Do not set permissions on TURN relay endpoints\n"
" (for testing the non-standard server relay functionality).\n"
@ -161,20 +164,25 @@ static char Usage[] =
//////////////////////////////////////////////////
void recalculate_restapi_hmac(void) {
void recalculate_restapi_hmac(SHATYPE st) {
if (g_use_auth_secret_with_timestamp) {
u08bits hmac[MAXSHASIZE];
unsigned int hmac_len;
unsigned int hmac_len = 0;
hmac_len = SHA256SIZEBYTES;
if(st == SHATYPE_SHA256)
hmac_len = SHA256SIZEBYTES;
else if(st == SHATYPE_SHA384)
hmac_len = SHA384SIZEBYTES;
else if(st == SHATYPE_SHA512)
hmac_len = SHA512SIZEBYTES;
hmac[0] = 0;
if (stun_calculate_hmac(g_uname, strlen((char*) g_uname),
(u08bits*) g_auth_secret, strlen(g_auth_secret), hmac,
&hmac_len, SHATYPE_SHA256) >= 0) {
&hmac_len, st) >= 0) {
size_t pwd_length = 0;
char *pwd = base64_encode(hmac, hmac_len, &pwd_length);
@ -210,15 +218,16 @@ int main(int argc, char **argv)
ns_bzero(local_addr, sizeof(local_addr));
while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:ZvsyhcxXgtTSAPDNOUHMRIGBJ")) != -1) {
while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:ZvsyhcxXgtTSAPDNOUHYKMRIGBJ")) != -1) {
switch (c){
case 'J': {
oauth = 1;
oauth_key_data okd_array[2];
oauth_key_data okd_array[3];
convert_oauth_key_data_raw(&okdr_array[0], &okd_array[0]);
convert_oauth_key_data_raw(&okdr_array[1], &okd_array[1]);
convert_oauth_key_data_raw(&okdr_array[2], &okd_array[2]);
char err_msg[1025] = "\0";
size_t err_msg_size = sizeof(err_msg) - 1;
@ -232,6 +241,11 @@ int main(int argc, char **argv)
fprintf(stderr, "%s\n", err_msg);
exit(-1);
}
if (convert_oauth_key_data(&okd_array[2], &okey_array[2], err_msg, err_msg_size) < 0) {
fprintf(stderr, "%s\n", err_msg);
exit(-1);
}
}
break;
case 'a':
@ -258,6 +272,12 @@ int main(int argc, char **argv)
case 'H':
shatype = SHATYPE_SHA256;
break;
case 'Y':
shatype = SHATYPE_SHA384;
break;
case 'K':
shatype = SHATYPE_SHA512;
break;
case 'E':
{
char* fn = find_config_file(optarg,1);
@ -416,6 +436,12 @@ int main(int argc, char **argv)
case SHATYPE_SHA256:
hmac_len = SHA256SIZEBYTES;
break;
case SHATYPE_SHA384:
hmac_len = SHA384SIZEBYTES;
break;
case SHATYPE_SHA512:
hmac_len = SHA512SIZEBYTES;
break;
default:
hmac_len = SHA1SIZEBYTES;
};

@ -242,6 +242,9 @@ static int clnet_connect(uint16_t clnet_remote_port, const char *remote_address,
set_sock_buf_size(clnet_fd, UR_CLIENT_SOCK_BUF_SIZE);
set_raw_socket_tos(clnet_fd, remote_addr.ss.sa_family, 0x22);
set_raw_socket_ttl(clnet_fd, remote_addr.ss.sa_family, 47);
if(clnet_info->is_peer && (*local_address==0)) {
if(remote_addr.ss.sa_family == AF_INET6) {
@ -523,7 +526,13 @@ static int clnet_allocate(int verbose,
clnet_info->server_name, &(clnet_info->oauth))) {
if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) {
clnet_info->shatype = SHATYPE_SHA256;
recalculate_restapi_hmac();
recalculate_restapi_hmac(clnet_info->shatype);
} else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) {
clnet_info->shatype = SHATYPE_SHA384;
recalculate_restapi_hmac(clnet_info->shatype);
} else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA384)) {
clnet_info->shatype = SHATYPE_SHA512;
recalculate_restapi_hmac(clnet_info->shatype);
}
goto beg_allocate;
} else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) {
@ -721,7 +730,13 @@ static int clnet_allocate(int verbose,
clnet_info->server_name, &(clnet_info->oauth))) {
if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) {
clnet_info->shatype = SHATYPE_SHA256;
recalculate_restapi_hmac();
recalculate_restapi_hmac(clnet_info->shatype);
} else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) {
clnet_info->shatype = SHATYPE_SHA384;
recalculate_restapi_hmac(clnet_info->shatype);
} else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA384)) {
clnet_info->shatype = SHATYPE_SHA512;
recalculate_restapi_hmac(clnet_info->shatype);
}
goto beg_refresh;
} else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) {
@ -819,7 +834,13 @@ static int turn_channel_bind(int verbose, uint16_t *chn,
clnet_info->server_name, &(clnet_info->oauth))) {
if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) {
clnet_info->shatype = SHATYPE_SHA256;
recalculate_restapi_hmac();
recalculate_restapi_hmac(clnet_info->shatype);
} else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) {
clnet_info->shatype = SHATYPE_SHA384;
recalculate_restapi_hmac(clnet_info->shatype);
} else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA384)) {
clnet_info->shatype = SHATYPE_SHA512;
recalculate_restapi_hmac(clnet_info->shatype);
}
goto beg_bind;
} else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) {
@ -927,7 +948,13 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info,
clnet_info->server_name, &(clnet_info->oauth))) {
if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) {
clnet_info->shatype = SHATYPE_SHA256;
recalculate_restapi_hmac();
recalculate_restapi_hmac(clnet_info->shatype);
} else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) {
clnet_info->shatype = SHATYPE_SHA384;
recalculate_restapi_hmac(clnet_info->shatype);
} else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA384)) {
clnet_info->shatype = SHATYPE_SHA512;
recalculate_restapi_hmac(clnet_info->shatype);
}
goto beg_cp;
} else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) {
@ -1506,7 +1533,13 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a
clnet_info->server_name, &(clnet_info->oauth))) {
if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1)) {
clnet_info->shatype = SHATYPE_SHA256;
recalculate_restapi_hmac();
recalculate_restapi_hmac(clnet_info->shatype);
} else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA256)) {
clnet_info->shatype = SHATYPE_SHA384;
recalculate_restapi_hmac(clnet_info->shatype);
} else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA384)) {
clnet_info->shatype = SHATYPE_SHA512;
recalculate_restapi_hmac(clnet_info->shatype);
}
goto beg_cb;
} else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) {

@ -753,7 +753,13 @@ static int client_read(app_ur_session *elem, int is_tcp_data, app_tcp_conn_info
clnet_info->server_name, &(clnet_info->oauth))) {
if(err_code == SHA_TOO_WEAK_ERROR_CODE && (elem->pinfo.shatype == SHATYPE_SHA1)) {
elem->pinfo.shatype = SHATYPE_SHA256;
recalculate_restapi_hmac();
recalculate_restapi_hmac(elem->pinfo.shatype);
} else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (elem->pinfo.shatype == SHATYPE_SHA256)) {
elem->pinfo.shatype = SHATYPE_SHA384;
recalculate_restapi_hmac(elem->pinfo.shatype);
} else if(err_code == SHA_TOO_WEAK_ERROR_CODE && (elem->pinfo.shatype == SHATYPE_SHA384)) {
elem->pinfo.shatype = SHATYPE_SHA512;
recalculate_restapi_hmac(elem->pinfo.shatype);
}
if(is_TCP_relay() && (stun_get_method(&(elem->in_buffer)) == STUN_METHOD_CONNECT)) {
@ -1609,8 +1615,7 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message)
if(((method == STUN_METHOD_ALLOCATE) || (method == STUN_METHOD_REFRESH)) || !(clnet_info->key_set))
{
cok=(random())%2;
if(cok<0) cok=-cok;
cok=((unsigned short)random())%3;
clnet_info->cok = cok;
oauth_token otoken;
encoded_oauth_token etoken;
@ -1627,6 +1632,10 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message)
otoken.enc_block.timestamp = ((uint64_t)turn_time()) << 16;
if(shatype == SHATYPE_SHA256) {
otoken.enc_block.key_length = 32;
} else if(shatype == SHATYPE_SHA384) {
otoken.enc_block.key_length = 48;
} else if(shatype == SHATYPE_SHA512) {
otoken.enc_block.key_length = 64;
} else {
otoken.enc_block.key_length = 20;
}

@ -88,7 +88,7 @@ extern int dual_allocation;
extern char origin[STUN_MAX_ORIGIN_SIZE+1];
extern int oauth;
extern oauth_key okey_array[2];
extern oauth_key okey_array[3];
#define UCLIENT_SESSION_LIFETIME (777)
#define OAUTH_SESSION_LIFETIME (555)
@ -109,7 +109,7 @@ turn_credential_type get_turn_credentials_type(void);
int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message);
int check_integrity(app_ur_conn_info *clnet_info, stun_buffer *message);
void recalculate_restapi_hmac(void);
void recalculate_restapi_hmac(SHATYPE st);
////////////////////////////////////////////

@ -125,6 +125,24 @@ int stun_calculate_hmac(const u08bits *buf, size_t len, const u08bits *key, size
#else
fprintf(stderr,"SHA256 is not supported\n");
return -1;
#endif
} else if(shatype == SHATYPE_SHA384) {
#if !defined(OPENSSL_NO_SHA384) && defined(SHA384_DIGEST_LENGTH)
if (!HMAC(EVP_sha384(), key, keylen, buf, len, hmac, hmac_len)) {
return -1;
}
#else
fprintf(stderr,"SHA384 is not supported\n");
return -1;
#endif
} else if(shatype == SHATYPE_SHA512) {
#if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH)
if (!HMAC(EVP_sha512(), key, keylen, buf, len, hmac, hmac_len)) {
return -1;
}
#else
fprintf(stderr,"SHA512 is not supported\n");
return -1;
#endif
} else
if (!HMAC(EVP_sha1(), key, keylen, buf, len, hmac, hmac_len)) {
@ -164,6 +182,30 @@ int stun_produce_integrity_key_str(u08bits *uname, u08bits *realm, u08bits *upwd
#else
fprintf(stderr,"SHA256 is not supported\n");
return -1;
#endif
} else if(shatype == SHATYPE_SHA384) {
#if !defined(OPENSSL_NO_SHA384) && defined(SHA384_DIGEST_LENGTH)
unsigned int keylen = 0;
EVP_MD_CTX ctx;
EVP_DigestInit(&ctx,EVP_sha384());
EVP_DigestUpdate(&ctx,str,strl);
EVP_DigestFinal(&ctx,key,&keylen);
EVP_MD_CTX_cleanup(&ctx);
#else
fprintf(stderr,"SHA384 is not supported\n");
return -1;
#endif
} else if(shatype == SHATYPE_SHA512) {
#if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH)
unsigned int keylen = 0;
EVP_MD_CTX ctx;
EVP_DigestInit(&ctx,EVP_sha512());
EVP_DigestUpdate(&ctx,str,strl);
EVP_DigestFinal(&ctx,key,&keylen);
EVP_MD_CTX_cleanup(&ctx);
#else
fprintf(stderr,"SHA512 is not supported\n");
return -1;
#endif
} else {
MD5_CTX ctx;
@ -1517,6 +1559,10 @@ size_t get_hmackey_size(SHATYPE shatype)
{
if(shatype == SHATYPE_SHA256)
return 32;
if(shatype == SHATYPE_SHA384)
return 48;
if(shatype == SHATYPE_SHA512)
return 64;
return 16;
}
@ -1540,6 +1586,12 @@ int stun_attr_add_integrity_str(turn_credential_type ct, u08bits *buf, size_t *l
case SHATYPE_SHA256:
shasize = SHA256SIZEBYTES;
break;
case SHATYPE_SHA384:
shasize = SHA384SIZEBYTES;
break;
case SHATYPE_SHA512:
shasize = SHA512SIZEBYTES;
break;
default:
shasize = SHA1SIZEBYTES;
};
@ -1621,16 +1673,43 @@ int stun_check_message_integrity_by_key_str(turn_credential_type ct, u08bits *bu
switch(sarlen) {
case SHA256SIZEBYTES:
shasize = SHA256SIZEBYTES;
if(shatype > SHATYPE_SHA256) {
if(too_weak)
*too_weak = 1;
return -1;
}
if(shatype != SHATYPE_SHA256)
return -1;
break;
case SHA384SIZEBYTES:
shasize = SHA384SIZEBYTES;
if(shatype > SHATYPE_SHA384) {
if(too_weak)
*too_weak = 1;
return -1;
}
if(shatype != SHATYPE_SHA384)
return -1;
break;
case SHA512SIZEBYTES:
shasize = SHA512SIZEBYTES;
if(shatype > SHATYPE_SHA512) {
if(too_weak)
*too_weak = 1;
return -1;
}
if(shatype != SHATYPE_SHA512)
return -1;
break;
case SHA1SIZEBYTES:
shasize = SHA1SIZEBYTES;
if(shatype != SHATYPE_SHA1) {
if(shatype > SHATYPE_SHA1) {
if(too_weak)
*too_weak = 1;
return -1;
}
if(shatype != SHATYPE_SHA1)
return -1;
break;
default:
return -1;
@ -1818,6 +1897,10 @@ static size_t calculate_auth_key_length(AUTH_ALG a)
return 32;
case AUTH_ALG_HMAC_SHA_256:
return 32;
case AUTH_ALG_HMAC_SHA_384:
return 48;
case AUTH_ALG_HMAC_SHA_512:
return 64;
default:
break;
};
@ -1834,6 +1917,10 @@ static size_t calculate_auth_output_length(AUTH_ALG a)
return 16;
case AUTH_ALG_HMAC_SHA_256:
return 32;
case AUTH_ALG_HMAC_SHA_384:
return 48;
case AUTH_ALG_HMAC_SHA_512:
return 64;
default:
break;
};
@ -1841,8 +1928,11 @@ static size_t calculate_auth_output_length(AUTH_ALG a)
return 32;
}
static int calculate_key(char *key, size_t key_size, char *new_key, size_t new_key_size, SHATYPE shatype,
char *err_msg, size_t err_msg_size)
static int calculate_key(char *key, size_t key_size,
char *new_key, size_t new_key_size,
SHATYPE shatype,
char *err_msg, size_t err_msg_size,
const char *info)
{
//Extract:
u08bits prk[128];
@ -1850,27 +1940,51 @@ static int calculate_key(char *key, size_t key_size, char *new_key, size_t new_k
stun_calculate_hmac((const u08bits *)key, key_size, (const u08bits *)"", 0, prk, &prk_len, shatype);
//Expand:
u08bits buf[128];
buf[0]=1;
u08bits hmac[128];
unsigned int hmac_len = 0;
stun_calculate_hmac((const u08bits *)buf, 1, prk, prk_len, hmac, &hmac_len, shatype);
ns_bcopy(hmac,new_key,hmac_len);
size_t info_len = strlen(info);
u08bits buf[256];
ns_bcopy(info,buf,info_len);
buf[info_len]=0x01;
u08bits hmac1[128];
unsigned int hmac1_len = 0;
stun_calculate_hmac((const u08bits *)buf, info_len+1, prk, prk_len, hmac1, &hmac1_len, shatype);
ns_bcopy(hmac1,new_key,hmac1_len);
//Check
if(new_key_size>hmac_len) {
ns_bcopy(hmac,buf,hmac_len);
buf[hmac_len]=2;
u08bits hmac1[128];
unsigned int hmac1_len = 0;
stun_calculate_hmac((const u08bits *)buf, hmac_len+1, prk, prk_len, hmac1, &hmac1_len, shatype);
ns_bcopy(hmac1,new_key+hmac_len,hmac1_len);
if(new_key_size > (hmac_len + hmac1_len)) {
if(err_msg) {
snprintf(err_msg,err_msg_size,"Wrong HKDF procedure (key sizes): output.sz=%lu, hmac(1)=%lu, hmac(2)=%lu",(unsigned long)new_key_size,(unsigned long)hmac_len,(unsigned long)hmac1_len);
if(new_key_size>hmac1_len) {
ns_bcopy(hmac1,buf,hmac1_len);
ns_bcopy(info,buf+hmac1_len,info_len);
buf[hmac1_len+info_len]=0x02;
u08bits hmac2[128];
unsigned int hmac2_len = 0;
stun_calculate_hmac((const u08bits *)buf, hmac1_len+info_len+1, prk, prk_len, hmac2, &hmac2_len, shatype);
ns_bcopy(hmac2,new_key+hmac1_len,hmac2_len);
if(new_key_size > (hmac1_len + hmac2_len)) {
ns_bcopy(hmac2,buf,hmac2_len);
ns_bcopy(info,buf+hmac2_len,info_len);
buf[hmac2_len+info_len]=0x03;
u08bits hmac3[128];
unsigned int hmac3_len = 0;
stun_calculate_hmac((const u08bits *)buf, hmac2_len+info_len+1, prk, prk_len, hmac3, &hmac3_len, shatype);
ns_bcopy(hmac3,new_key+hmac1_len+hmac2_len,hmac3_len);
if(new_key_size > (hmac1_len + hmac2_len + hmac3_len)) {
ns_bcopy(hmac3,buf,hmac3_len);
ns_bcopy(info,buf+hmac3_len,info_len);
buf[hmac3_len+info_len]=0x04;
u08bits hmac4[128];
unsigned int hmac4_len = 0;
stun_calculate_hmac((const u08bits *)buf, hmac3_len+info_len+1, prk, prk_len, hmac4, &hmac4_len, shatype);
ns_bcopy(hmac4,new_key+hmac1_len+hmac2_len+hmac3_len,hmac4_len);
if(new_key_size > (hmac1_len + hmac2_len + hmac3_len + hmac4_len)) {
if(err_msg) {
snprintf(err_msg,err_msg_size,"Wrong HKDF procedure (key sizes): output.sz=%lu, hmac(1)=%lu, hmac(2)=%lu",(unsigned long)new_key_size,(unsigned long)hmac1_len,(unsigned long)hmac2_len);
}
OAUTH_ERROR("Wrong HKDF procedure (key sizes): output.sz=%lu, hmac(1)=%lu, hmac(2)=%lu",(unsigned long)new_key_size,(unsigned long)hmac1_len,(unsigned long)hmac2_len);
return -1;
}
}
OAUTH_ERROR("Wrong HKDF procedure (key sizes): output.sz=%lu, hmac(1)=%lu, hmac(2)=%lu",(unsigned long)new_key_size,(unsigned long)hmac_len,(unsigned long)hmac1_len);
return -1;
}
}
@ -1938,6 +2052,10 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er
key->hkdf_hash_func = SHATYPE_SHA1;
} else if(!strcmp(oakd->hkdf_hash_func,"SHA256") || !strcmp(oakd->hkdf_hash_func,"SHA-256")) {
key->hkdf_hash_func = SHATYPE_SHA256;
} else if(!strcmp(oakd->hkdf_hash_func,"SHA384") || !strcmp(oakd->hkdf_hash_func,"SHA-384")) {
key->hkdf_hash_func = SHATYPE_SHA384;
} else if(!strcmp(oakd->hkdf_hash_func,"SHA512") || !strcmp(oakd->hkdf_hash_func,"SHA-512")) {
key->hkdf_hash_func = SHATYPE_SHA512;
} else if(oakd->hkdf_hash_func[0]) {
if(err_msg) {
snprintf(err_msg,err_msg_size,"Wrong HKDF hash function algorithm: %s",oakd->hkdf_hash_func);
@ -1951,6 +2069,10 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er
key->auth_alg = AUTH_ALG_HMAC_SHA_1;
} else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256")) {
key->auth_alg = AUTH_ALG_HMAC_SHA_256;
} else if(!strcmp(oakd->auth_alg,"HMAC-SHA-384")) {
key->auth_alg = AUTH_ALG_HMAC_SHA_384;
} else if(!strcmp(oakd->auth_alg,"HMAC-SHA-512")) {
key->auth_alg = AUTH_ALG_HMAC_SHA_512;
} else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256-128")) {
key->auth_alg = AUTH_ALG_HMAC_SHA_256_128;
} else if(oakd->auth_alg[0]) {
@ -1989,14 +2111,14 @@ int convert_oauth_key_data(const oauth_key_data *oakd0, oauth_key *key, char *er
key->auth_key[0] = 0;
} else if(!(key->auth_key_size)) {
key->auth_key_size = calculate_auth_key_length(key->auth_alg);
if(calculate_key(key->ikm_key,key->ikm_key_size,key->auth_key,key->auth_key_size,key->hkdf_hash_func,err_msg,err_msg_size)<0) {
if(calculate_key(key->ikm_key,key->ikm_key_size,key->auth_key,key->auth_key_size,key->hkdf_hash_func,err_msg,err_msg_size,"AUTH key")<0) {
return -1;
}
}
if(!(key->as_rs_key_size)) {
key->as_rs_key_size = calculate_enc_key_length(key->as_rs_alg);
if(calculate_key(key->ikm_key,key->ikm_key_size,key->as_rs_key,key->as_rs_key_size,key->hkdf_hash_func,err_msg,err_msg_size)<0) {
if(calculate_key(key->ikm_key,key->ikm_key_size,key->as_rs_key,key->as_rs_key_size,key->hkdf_hash_func,err_msg,err_msg_size,"AS-RS key")<0) {
return -1;
}
}
@ -2034,6 +2156,14 @@ static const EVP_MD *get_auth_type(AUTH_ALG aa)
case AUTH_ALG_HMAC_SHA_256_128:
case AUTH_ALG_HMAC_SHA_256:
return EVP_sha256();
#endif
#if !defined(OPENSSL_NO_SHA384) && defined(SHA384_DIGEST_LENGTH)
case AUTH_ALG_HMAC_SHA_384:
return EVP_sha384();
#endif
#if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH)
case AUTH_ALG_HMAC_SHA_512:
return EVP_sha512();
#endif
default:
break;

@ -44,7 +44,7 @@
#define STUN_MAX_REALM_SIZE (127)
#define STUN_MAX_NONCE_SIZE (127)
#define STUN_MAX_SERVER_NAME_SIZE (1025)
#define STUN_MAX_PWD_SIZE (127)
#define STUN_MAX_PWD_SIZE (256)
#define AUTH_SECRET_SIZE STUN_MAX_PWD_SIZE
#define STUN_MAGIC_COOKIE (0x2112A442)

@ -48,6 +48,8 @@
#define SHA1SIZEBYTES (20)
#define SHA256SIZEBYTES (32)
#define SHA384SIZEBYTES (48)
#define SHA512SIZEBYTES (64)
#define MAXSHASIZE (128)
@ -55,14 +57,17 @@ enum _SHATYPE {
SHATYPE_ERROR = -1,
SHATYPE_DEFAULT=0,
SHATYPE_SHA1=SHATYPE_DEFAULT,
SHATYPE_SHA256
SHATYPE_SHA256,
SHATYPE_SHA384,
SHATYPE_SHA512
};
typedef enum _SHATYPE SHATYPE;
#define shatype_name(sht) ((sht == SHATYPE_SHA1) ? "SHA1" : ((sht == SHATYPE_SHA256) ? "SHA256" : "SHA UNKNOWN"))
#define shatype_name(sht) ((sht == SHATYPE_SHA1) ? "SHA1" : ((sht == SHATYPE_SHA256) ? "SHA256" : ((sht == SHATYPE_SHA384) ? "SHA384" : "SHA512")))
#define SHA_TOO_WEAK_ERROR_CODE (426)
#define SHA_TOO_WEAK_ERROR_REASON ((const u08bits*)("credentials too weak"))
/* <<== SHA AGILITY */
@ -90,7 +95,9 @@ enum _AUTH_ALG {
AUTH_ALG_DEFAULT = 1,
AUTH_ALG_HMAC_SHA_256_128 = AUTH_ALG_DEFAULT,
AUTH_ALG_HMAC_SHA_1,
AUTH_ALG_HMAC_SHA_256
AUTH_ALG_HMAC_SHA_256,
AUTH_ALG_HMAC_SHA_384,
AUTH_ALG_HMAC_SHA_512
};
typedef enum _AUTH_ALG AUTH_ALG;

@ -31,7 +31,7 @@
#ifndef __IOADEFS__
#define __IOADEFS__
#define TURN_SERVER_VERSION "4.4.1.2"
#define TURN_SERVER_VERSION "4.4.2.1"
#define TURN_SERVER_VERSION_NAME "Ardee West"
#define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'"

@ -172,6 +172,12 @@ void turn_permission_clean(turn_permission_info* tinfo)
{
if (tinfo && tinfo->allocated) {
if(tinfo->verbose) {
char s[257]="\0";
addr_to_string(&(tinfo->addr),(u08bits*)s);
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: peer %s deleted\n",tinfo->session_id,s);
}
if(!(tinfo->lifetime_ev)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: strange (1) permission to be cleaned\n",__FUNCTION__);
}

@ -147,6 +147,8 @@ typedef struct _turn_permission_info {
turn_time_t expiration_time;
ioa_timer_handle lifetime_ev;
void* owner; //a
int verbose;
unsigned long long session_id;
} turn_permission_info;
typedef struct _turn_permission_slot {

@ -856,6 +856,14 @@ static int update_turn_permission_lifetime(ts_ur_super_session *ss, turn_permiss
client_ss_perm_timeout_handler, tinfo, 0,
"client_ss_channel_timeout_handler");
if(server->verbose) {
tinfo->verbose = 1;
tinfo->session_id = ss->id;
char s[257]="\0";
addr_to_string(&(tinfo->addr),(u08bits*)s);
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: peer %s lifetime updated: %lu\n",(unsigned long long)ss->id,s,(unsigned long)time_delta);
}
return 0;
}
}
@ -3284,19 +3292,52 @@ static int check_stun_auth(turn_turnserver *server,
{
int sarlen = stun_attr_get_len(sar);
switch(sarlen) {
case SHA1SIZEBYTES:
if(server->shatype != SHATYPE_SHA1) {
if(server->shatype > SHATYPE_SHA1) {
*err_code = SHA_TOO_WEAK_ERROR_CODE;
*reason = SHA_TOO_WEAK_ERROR_REASON;
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
}
if(server->shatype != SHATYPE_SHA1) {
*err_code = 401;
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
}
break;
case SHA256SIZEBYTES:
if(server->shatype > SHATYPE_SHA256) {
*err_code = SHA_TOO_WEAK_ERROR_CODE;
*reason = SHA_TOO_WEAK_ERROR_REASON;
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
}
if(server->shatype != SHATYPE_SHA256) {
*err_code = 401;
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
}
break;
case SHA384SIZEBYTES:
if(server->shatype > SHATYPE_SHA384) {
*err_code = SHA_TOO_WEAK_ERROR_CODE;
*reason = SHA_TOO_WEAK_ERROR_REASON;
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
}
if(server->shatype != SHATYPE_SHA384) {
*err_code = 401;
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
}
break;
case SHA512SIZEBYTES:
if(server->shatype > SHATYPE_SHA512) {
*err_code = SHA_TOO_WEAK_ERROR_CODE;
*reason = SHA_TOO_WEAK_ERROR_REASON;
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
}
if(server->shatype != SHATYPE_SHA512) {
*err_code = 401;
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
}
break;
default:
*err_code = 401;
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
@ -3438,6 +3479,7 @@ static int check_stun_auth(turn_turnserver *server,
"%s: user %s credentials are incorrect: SHA function is too weak\n",
__FUNCTION__, (char*)usname);
*err_code = SHA_TOO_WEAK_ERROR_CODE;
*reason = SHA_TOO_WEAK_ERROR_REASON;
*reason = (const u08bits*)"Unauthorised: weak SHA function is used";
return create_challenge_response(ss,tid,resp_constructed,err_code,reason,nbh,method);
}

@ -8,7 +8,7 @@ CREATE TABLE turnusers_lt (
CREATE TABLE turn_secret (
realm varchar(127) default '',
value varchar(127),
value varchar(256),
primary key (realm,value)
);

@ -45,9 +45,10 @@ and they will be almost immediately "seen" by the turnserver process.
is 0 - unlimited lifetime.
hkdf_hash_func - (optional) hash function for HKDF procedure; the
valid values are SHA-1 and SHA-256, with SHA-256 as default;
The hkdf_hash_func is not needed if the as_rs_key and auth_key
are defined explicitly in the database;
valid values are SHA-1, SHA-256, SHA-384 and SHA-512,
with SHA-256 as default. The hkdf_hash_func is not needed
if the as_rs_key and auth_key are defined explicitly
in the database;
as_rs_alg - oAuth token encryption algorithm; the valid values are
"AES-128-CBC" and "AES-256-CBC", , "AEAD-AES-128-GCM",
@ -59,7 +60,8 @@ and they will be almost immediately "seen" by the turnserver process.
is defined by as_rs_alg.
auth_alg - (optional) oAuth token authentication algorithm; the valid values are
"HMAC-SHA-256-128", "HMAC-SHA-256" and "HMAC-SHA-1".
"HMAC-SHA-256-128", "HMAC-SHA-256", "HMAC-SHA-384",
"HMAC-SHA-512" and "HMAC-SHA-1".
The default value is "HMAC-SHA-256-128".
auth_key - (optional) base64-encoded AUTH key. If not defined, then

@ -51,6 +51,12 @@ db.oauth_key.insert({ kid: 'north',
hkdf_hash_func: 'SHA-256',
as_rs_alg: 'AES-256-CBC',
auth_alg: 'HMAC-SHA-256-128' });
db.oauth_key.insert({ kid: 'union',
ikm_key: 'aGVyb2Q=',
hkdf_hash_func: 'SHA-256',
as_rs_alg: 'AES-256-CBC',
auth_alg: 'HMAC-SHA-512' });
db.oauth_key.insert({ kid: 'oldempire',
ikm_key: 'YXVsY3Vz',

@ -36,6 +36,7 @@ sadd turn/realm/north.gov/denied-peer-ip "172.17.13.133-172.17.14.56" "172.17.17
sadd turn/realm/crinna.org/denied-peer-ip "123::77"
hmset turn/oauth/kid/north ikm_key 'Y2FybGVvbg==' hkdf_hash_func 'SHA-256' as_rs_alg 'AES-256-CBC' auth_alg 'HMAC-SHA-256-128'
hmset turn/oauth/kid/union ikm_key 'aGVyb2Q=' hkdf_hash_func 'SHA-256' as_rs_alg 'AES-256-CBC' auth_alg 'HMAC-SHA-512'
hmset turn/oauth/kid/oldempire ikm_key 'YXVsY3Vz' hkdf_hash_func 'SHA-256' as_rs_alg 'AEAD-AES-256-GCM'
hmset turn/admin_user/skarling realm 'north.gov' password 'hoodless'

@ -32,4 +32,5 @@ insert into denied_peer_ip (realm,ip_range) values('north.gov','172.17.17.133-17
insert into denied_peer_ip (realm,ip_range) values('crinna.org','123::77');
insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('north','Y2FybGVvbg==',0,0,'SHA-256','AES-256-CBC','','HMAC-SHA-256-128','');
insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('union','aGVyb2Q=',0,0,'SHA-256','AES-256-CBC','','HMAC-SHA-512','');
insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('oldempire','YXVsY3Vz',0,0,'SHA-256','AEAD-AES-256-GCM','','','');

Loading…
Cancel
Save