From 07e4b759a74798feb7ca5744e8e640646fa26517 Mon Sep 17 00:00:00 2001 From: Oleg Moskalenko Date: Sun, 8 Feb 2015 13:03:27 -0800 Subject: [PATCH] Imported Upstream version 4.4.2.1 --- ChangeLog | 7 + INSTALL | 41 +++--- README.turnadmin | 4 +- README.turnserver | 4 + README.turnutils | 4 + STATUS | 2 + TODO | 2 +- examples/etc/turnserver.conf | 12 +- examples/var/db/turndb | Bin 22528 -> 22528 bytes man/man1/turnadmin.1 | 10 +- man/man1/turnserver.1 | 10 +- man/man1/turnutils.1 | 10 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +- src/apps/common/apputils.c | 125 ++++++++++++++++++ src/apps/common/apputils.h | 8 ++ src/apps/relay/dtls_listener.c | 14 +- src/apps/relay/mainrelay.c | 32 ++++- src/apps/relay/ns_ioalib_engine_impl.c | 138 +------------------ src/apps/relay/turn_admin_server.c | 46 ++++++- src/apps/relay/userdb.c | 22 ++++ src/apps/rfc5769/rfc5769check.c | 20 ++- src/apps/uclient/mainuclient.c | 42 ++++-- src/apps/uclient/startuclient.c | 43 +++++- src/apps/uclient/uclient.c | 15 ++- src/apps/uclient/uclient.h | 4 +- src/client/ns_turn_msg.c | 176 +++++++++++++++++++++---- src/client/ns_turn_msg_defs.h | 2 +- src/client/ns_turn_msg_defs_new.h | 13 +- src/ns_turn_defs.h | 2 +- src/server/ns_turn_allocation.c | 6 + src/server/ns_turn_allocation.h | 2 + src/server/ns_turn_server.c | 44 ++++++- turndb/schema.sql | 2 +- turndb/schema.userdb.redis | 10 +- turndb/testmongosetup.sh | 6 + turndb/testredisdbsetup.sh | 1 + turndb/testsqldbsetup.sql | 1 + 38 files changed, 657 insertions(+), 229 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2c739d2e..d6f247bd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2/3/2015 Oleg Moskalenko +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 Version 4.4.1.2 'Ardee West': - SSODA updates according to turnbis specs; diff --git a/INSTALL b/INSTALL index 1706efb4..23059ca6 100644 --- a/INSTALL +++ b/INSTALL @@ -470,14 +470,15 @@ libevent2 from their web site. It was tested with older *NIXes NOTE: SQLite must be of version 3.x. -NOTE: For extra security features (DTLS and SHA256) support, OpenSSL version -1.0.0a or newer is recommended. Older versions do not support DTLS, reliably, -in some cases. For example, the Debian 'Squeeze' Linux supplies 0.9.8 version -of OpenSSL, that does not work correctly with DTLS over IPv6. If your system -already has an older version of OpenSSL installed (usually in directory /usr) -then you may want to install your newer OpenSSL "over" the old one (because it -will most probably will not allow removal of the old one). When installing -the newer OpenSSL, run the OpenSSL's configure command like this: +NOTE: For extra security features (DTLS and SHA256 and 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 diff --git a/README.turnadmin b/README.turnadmin index b10f2379..53166f6c 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -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. diff --git a/README.turnserver b/README.turnserver index 5fb0b495..22f1a505 100644 --- a/README.turnserver +++ b/README.turnserver @@ -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. diff --git a/README.turnutils b/README.turnutils index a39fa889..a23ddbbb 100644 --- a/README.turnutils +++ b/README.turnutils @@ -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. diff --git a/STATUS b/STATUS index c3f1b1b3..499804ae 100644 --- a/STATUS +++ b/STATUS @@ -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. diff --git a/TODO b/TODO index cc38d831..8fe61eb1 100644 --- a/TODO +++ b/TODO @@ -90,7 +90,7 @@ ================================================================== -1) Peer for TCP relay. +1) Peer app for TCP relay. ================================================================== diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index e4209026..9ae0f375 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -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. # diff --git a/examples/var/db/turndb b/examples/var/db/turndb index bd93f071598d22131933274dbff1ab2600efefe8..bad666cb7f6e5ca5436b9114b6b46a5982458457 100644 GIT binary patch delta 589 zcmYjMO=uHA7@gT~^3ye;+az`?o4OlxAqu@p*5z>^*n1ux=JFB0(9VsC<1C#yu?$K(6v9o~D>?c;7A-ShX9bsi~G- zH!Zul8s$Kiyi2WH?TTSpwa%$246-;D4Xdu3%y66XE`1b%eFCW1|P2VY>1 zsZZhRG)YMKUzX9R*qYrTF_IAflf4YsPh<&?5rJhJ=f{d>*@)@8a;BIhxA(E_@JD58500X2;RaPl(?U4K5RQn94((S zaK?31TydSFIO{s|GYi0rv%#R03?B-&%!XxZg;J-IyG*|o;;@j-(Y3-oW;R6d3wB@# zpGU(!{0ihC3mrlDvyk_m01qX|`rG{jw{^|9t+X|}x~kc8+1$w^N=?6|wTz~c nN~L*)p{*G$oxWaXae}nq31WA@|; zKGKYAlh^o2PrhiVF!`B}(Bx-EB9q_ivvHLr=9H#ta%q~fO_ugGVPxMNqrXCgkBPaL zf%zbFFLM~P3e)9{jb2QXW888k2JkVuPHc4HEd_cQ28<>)8cx>GH<{e)UJlgvl7aa< z^GoK3KzMVrqQD_$Q4Xj|6ngSYZ)rYO#sCH;38rY~vy1_Z_cu1$F>Vg<-M|F^1Z0Ts diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 2dd8022a..be71dfd8 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "31 January 2015" "" "" +.TH TURN 1 "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 diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index d471c104..7b3b475f 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "31 January 2015" "" "" +.TH TURN 1 "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 diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index a43fd9b8..83f28d48 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "31 January 2015" "" "" +.TH TURN 1 "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 diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index c5c3ea19..7b0ed997 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.4.1.2 +TURNVERSION=4.4.2.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index fe251e84..9f1cd82b 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -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 + - Sync to 4.4.2.1 * Sun Feb 1 2015 Oleg Moskalenko - Sync to 4.4.1.2 * Sat Jan 24 2015 Oleg Moskalenko diff --git a/src/apps/common/apputils.c b/src/apps/common/apputils.c index a8ec8ef3..690c60d4 100644 --- a/src/apps/common/apputils.c +++ b/src/apps/common/apputils.c @@ -289,6 +289,131 @@ int addr_get_from_sock(evutil_socket_t fd, ioa_addr *addr) } } +int get_raw_socket_ttl(evutil_socket_t fd, int family) +{ + int ttl = 0; + + if(family == AF_INET6) { +#if !defined(IPV6_UNICAST_HOPS) + UNUSED_ARG(fd); + do { return TTL_IGNORE; } while(0); +#else + socklen_t slen = (socklen_t)sizeof(ttl); + if(getsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,&slen)<0) { + perror("get HOPLIMIT on socket"); + return TTL_IGNORE; + } +#endif + } else { +#if !defined(IP_TTL) + UNUSED_ARG(fd); + do { return TTL_IGNORE; } while(0); +#else + socklen_t slen = (socklen_t)sizeof(ttl); + if(getsockopt(fd, IPPROTO_IP, IP_TTL, &ttl,&slen)<0) { + perror("get TTL on socket"); + return TTL_IGNORE; + } +#endif + } + + CORRECT_RAW_TTL(ttl); + + return ttl; +} + +int get_raw_socket_tos(evutil_socket_t fd, int family) +{ + int tos = 0; + + if(family == AF_INET6) { +#if !defined(IPV6_TCLASS) + UNUSED_ARG(fd); + do { return TOS_IGNORE; } while(0); +#else + socklen_t slen = (socklen_t)sizeof(tos); + if(getsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos,&slen)<0) { + perror("get TCLASS on socket"); + return -1; + } +#endif + } else { +#if !defined(IP_TOS) + UNUSED_ARG(fd); + do { return TOS_IGNORE; } while(0); +#else + socklen_t slen = (socklen_t)sizeof(tos); + if(getsockopt(fd, IPPROTO_IP, IP_TOS, &tos,&slen)<0) { + perror("get TOS on socket"); + return -1; + } +#endif + } + + CORRECT_RAW_TOS(tos); + + return tos; +} + +int set_raw_socket_ttl(evutil_socket_t fd, int family, int ttl) +{ + + if(family == AF_INET6) { +#if !defined(IPV6_UNICAST_HOPS) + UNUSED_ARG(fd); + UNUSED_ARG(ttl); +#else + CORRECT_RAW_TTL(ttl); + if(setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,sizeof(ttl))<0) { + perror("set HOPLIMIT on socket"); + return -1; + } +#endif + } else { +#if !defined(IP_TTL) + UNUSED_ARG(fd); + UNUSED_ARG(ttl); +#else + CORRECT_RAW_TTL(ttl); + if(setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl,sizeof(ttl))<0) { + perror("set TTL on socket"); + return -1; + } +#endif + } + + return 0; +} + +int set_raw_socket_tos(evutil_socket_t fd, int family, int tos) +{ + + if(family == AF_INET6) { +#if !defined(IPV6_TCLASS) + UNUSED_ARG(fd); + UNUSED_ARG(tos); +#else + CORRECT_RAW_TOS(tos); + if(setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos,sizeof(tos))<0) { + perror("set TCLASS on socket"); + return -1; + } +#endif + } else { +#if !defined(IP_TOS) + UNUSED_ARG(fd); + UNUSED_ARG(tos); +#else + if(setsockopt(fd, IPPROTO_IP, IP_TOS, &tos,sizeof(tos))<0) { + perror("set TOS on socket"); + return -1; + } +#endif + } + + return 0; +} + /////////////////// MTU ///////////////////////////////////////// int set_socket_df(evutil_socket_t fd, int family, int value) diff --git a/src/apps/common/apputils.h b/src/apps/common/apputils.h index adb38b69..fb3133b1 100644 --- a/src/apps/common/apputils.h +++ b/src/apps/common/apputils.h @@ -186,6 +186,14 @@ int addr_get_from_sock(evutil_socket_t fd, ioa_addr *addr); int handle_socket_error(void); +#define CORRECT_RAW_TTL(ttl) do { if(ttl<0 || ttl>255) ttl=TTL_DEFAULT; } while(0) +#define CORRECT_RAW_TOS(tos) do { if(tos<0 || tos>255) tos=TOS_DEFAULT; } while(0) + +int set_raw_socket_tos(evutil_socket_t fd, int family, int tos); +int set_raw_socket_ttl(evutil_socket_t fd, int family, int ttl); +int get_raw_socket_tos(evutil_socket_t fd, int family); +int get_raw_socket_ttl(evutil_socket_t fd, int family); + /////////////////////// SYS ///////////////////// void ignore_sigpipe(void); diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index cddd0768..2d591c45 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -638,14 +638,14 @@ static void udp_server_input_handler(evutil_socket_t fd, short what, void* arg) addr_set_any(&(server->sm.m.sm.nd.src_addr)); - int slen = server->slen0; ssize_t bsize = 0; - int flags = 0; + int flags = MSG_DONTWAIT; - do { - bsize = recvfrom(fd, ioa_network_buffer_data(elem), ioa_network_buffer_get_capacity_udp(), flags, (struct sockaddr*) &(server->sm.m.sm.nd.src_addr), (socklen_t*) &slen); - } while (bsize < 0 && (errno == EINTR)); + bsize = udp_recvfrom(fd, &(server->sm.m.sm.nd.src_addr), &(server->addr), + (s08bits*)ioa_network_buffer_data(elem), (int)ioa_network_buffer_get_capacity_udp(), + &(server->sm.m.sm.nd.recv_ttl), &(server->sm.m.sm.nd.recv_tos), + server->e->cmsg, flags, NULL); int conn_reset = is_connreset(); int to_block = would_block(); @@ -668,6 +668,7 @@ static void udp_server_input_handler(evutil_socket_t fd, short what, void* arg) ioa_addr orig_addr; int ttl = 0; int tos = 0; + int slen = server->slen0; udp_recvfrom(fd, &orig_addr, &(server->addr), buffer, (int) sizeof(buffer), &ttl, &tos, server->e->cmsg, eflags, &errcode); @@ -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; diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 7dd1e65d..829842b0 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -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 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); diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 34027854..87c2eaed 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -355,16 +355,16 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm, #if !defined(CMSG_SPACE) TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "On this platform, I am using alternative behavior of TTL/TOS according to RFC 5766.\n"); #endif -#if !defined(IP_RECVTTL) +#if !defined(IP_RECVTTL) || !defined(IP_TTL) TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv4: On this platform, I am using alternative behavior of TTL according to RFC 5766.\n"); #endif -#if !defined(IPV6_RECVHOPLIMIT) +#if !defined(IPV6_RECVHOPLIMIT) || !defined(IPV6_HOPLIMIT) TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv6: On this platform, I am using alternative behavior of TTL (HOPLIMIT) according to RFC 6156.\n"); #endif -#if !defined(IP_RECVTOS) +#if !defined(IP_RECVTOS) || !defined(IP_TOS) TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv4: On this platform, I am using alternative behavior of TOS according to RFC 5766.\n"); #endif -#if !defined(IPV6_RECVTCLASS) +#if !defined(IPV6_RECVTCLASS) || !defined(IPV6_TCLASS) TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "IPv6: On this platform, I am using alternative behavior of TRAFFIC CLASS according to RFC 6156.\n"); #endif } @@ -706,134 +706,6 @@ int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_ /* Socket options helpers ==>> */ -#define CORRECT_RAW_TTL(ttl) do { if(ttl<0 || ttl>255) ttl=TTL_DEFAULT; } while(0) -#define CORRECT_RAW_TOS(tos) do { if(tos<0 || tos>255) tos=TOS_DEFAULT; } while(0) - -static int get_raw_socket_ttl(evutil_socket_t fd, int family) -{ - int ttl = 0; - - if(family == AF_INET6) { -#if !defined(IPV6_RECVHOPLIMIT) - UNUSED_ARG(fd); - do { return TTL_IGNORE; } while(0); -#else - socklen_t slen = (socklen_t)sizeof(ttl); - if(getsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,&slen)<0) { - perror("get HOPLIMIT on socket"); - return TTL_IGNORE; - } -#endif - } else { -#if !defined(IP_RECVTTL) - UNUSED_ARG(fd); - do { return TTL_IGNORE; } while(0); -#else - socklen_t slen = (socklen_t)sizeof(ttl); - if(getsockopt(fd, IPPROTO_IP, IP_TTL, &ttl,&slen)<0) { - perror("get TTL on socket"); - return TTL_IGNORE; - } -#endif - } - - CORRECT_RAW_TTL(ttl); - - return ttl; -} - -static int get_raw_socket_tos(evutil_socket_t fd, int family) -{ - int tos = 0; - - if(family == AF_INET6) { -#if !defined(IPV6_RECVTCLASS) - UNUSED_ARG(fd); - do { return TOS_IGNORE; } while(0); -#else - socklen_t slen = (socklen_t)sizeof(tos); - if(getsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos,&slen)<0) { - perror("get TCLASS on socket"); - return -1; - } -#endif - } else { -#if !defined(IP_RECVTOS) - UNUSED_ARG(fd); - do { return TOS_IGNORE; } while(0); -#else - socklen_t slen = (socklen_t)sizeof(tos); - if(getsockopt(fd, IPPROTO_IP, IP_TOS, &tos,&slen)<0) { - perror("get TOS on socket"); - return -1; - } -#endif - } - - CORRECT_RAW_TOS(tos); - - return tos; -} - -static int set_raw_socket_ttl(evutil_socket_t fd, int family, int ttl) -{ - - if(family == AF_INET6) { -#if !defined(IPV6_RECVHOPLIMIT) - UNUSED_ARG(fd); - UNUSED_ARG(ttl); -#else - CORRECT_RAW_TTL(ttl); - if(setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,sizeof(ttl))<0) { - perror("set HOPLIMIT on socket"); - return -1; - } -#endif - } else { -#if !defined(IP_RECVTTL) - UNUSED_ARG(fd); - UNUSED_ARG(ttl); -#else - CORRECT_RAW_TTL(ttl); - if(setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl,sizeof(ttl))<0) { - perror("set TTL on socket"); - return -1; - } -#endif - } - - return 0; -} - -static int set_raw_socket_tos(evutil_socket_t fd, int family, int tos) -{ - - if(family == AF_INET6) { -#if !defined(IPV6_RECVTCLASS) - UNUSED_ARG(fd); - UNUSED_ARG(tos); -#else - CORRECT_RAW_TOS(tos); - if(setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos,sizeof(tos))<0) { - perror("set TCLASS on socket"); - return -1; - } -#endif - } else { -#if !defined(IPV6_RECVTOS) - UNUSED_ARG(fd); - UNUSED_ARG(tos); -#else - if(setsockopt(fd, IPPROTO_IP, IP_TOS, &tos,sizeof(tos))<0) { - perror("set TOS on socket"); - return -1; - } -#endif - } - - return 0; -} - static int set_socket_ttl(ioa_socket_handle s, int ttl) { if(s->default_ttl < 0) //Unsupported @@ -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); diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 6bba4eb7..ec61235f 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -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
\r\n"); + else if(turn_params.shatype == SHATYPE_SHA384) + str_buffer_append(sb,"SHA type: SHA384
\r\n"); + else if(turn_params.shatype == SHATYPE_SHA512) + str_buffer_append(sb,"SHA type: SHA512
\r\n"); else str_buffer_append(sb,"SHA type: SHA1
\r\n"); @@ -3043,10 +3055,26 @@ static void write_https_oauth_page(ioa_socket_handle s, const char* add_kid, con str_buffer_append(sb,"SHA-256\r\n
\r\n"); + + str_buffer_append(sb,"SHA-384\r\n
\r\n"); + + str_buffer_append(sb,"SHA-512\r\n
\r\n"); } str_buffer_append(sb,""); @@ -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
\r\n"); + str_buffer_append(sb,"HMAC-SHA-384\r\n
\r\n"); + + str_buffer_append(sb,"HMAC-SHA-512\r\n
\r\n"); + str_buffer_append(sb,">\n",name,(unsigned long)len); size_t i; for(i = 0;i= 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; }; diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index d26cd718..c8e2e138 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -242,6 +242,9 @@ static int clnet_connect(uint16_t clnet_remote_port, const char *remote_address, set_sock_buf_size(clnet_fd, UR_CLIENT_SOCK_BUF_SIZE); + set_raw_socket_tos(clnet_fd, remote_addr.ss.sa_family, 0x22); + set_raw_socket_ttl(clnet_fd, remote_addr.ss.sa_family, 47); + if(clnet_info->is_peer && (*local_address==0)) { if(remote_addr.ss.sa_family == AF_INET6) { @@ -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))) { diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 1f3d9c07..e73109a7 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -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; } diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index e68de6ee..fe930f3f 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -88,7 +88,7 @@ extern int dual_allocation; extern char origin[STUN_MAX_ORIGIN_SIZE+1]; extern int oauth; -extern oauth_key okey_array[2]; +extern oauth_key okey_array[3]; #define UCLIENT_SESSION_LIFETIME (777) #define OAUTH_SESSION_LIFETIME (555) @@ -109,7 +109,7 @@ turn_credential_type get_turn_credentials_type(void); int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message); int check_integrity(app_ur_conn_info *clnet_info, stun_buffer *message); -void recalculate_restapi_hmac(void); +void recalculate_restapi_hmac(SHATYPE st); //////////////////////////////////////////// diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index 4df6f5fb..d018d988 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -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; diff --git a/src/client/ns_turn_msg_defs.h b/src/client/ns_turn_msg_defs.h index f0a22ee6..78653e05 100644 --- a/src/client/ns_turn_msg_defs.h +++ b/src/client/ns_turn_msg_defs.h @@ -44,7 +44,7 @@ #define STUN_MAX_REALM_SIZE (127) #define STUN_MAX_NONCE_SIZE (127) #define STUN_MAX_SERVER_NAME_SIZE (1025) -#define STUN_MAX_PWD_SIZE (127) +#define STUN_MAX_PWD_SIZE (256) #define AUTH_SECRET_SIZE STUN_MAX_PWD_SIZE #define STUN_MAGIC_COOKIE (0x2112A442) diff --git a/src/client/ns_turn_msg_defs_new.h b/src/client/ns_turn_msg_defs_new.h index 99709b3a..9e5d2cf5 100644 --- a/src/client/ns_turn_msg_defs_new.h +++ b/src/client/ns_turn_msg_defs_new.h @@ -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; diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 570e1fdc..b3d091ab 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.4.1.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 "'" diff --git a/src/server/ns_turn_allocation.c b/src/server/ns_turn_allocation.c index 26980dde..7fef9b1e 100644 --- a/src/server/ns_turn_allocation.c +++ b/src/server/ns_turn_allocation.c @@ -172,6 +172,12 @@ void turn_permission_clean(turn_permission_info* tinfo) { if (tinfo && tinfo->allocated) { + if(tinfo->verbose) { + char s[257]="\0"; + addr_to_string(&(tinfo->addr),(u08bits*)s); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: peer %s deleted\n",tinfo->session_id,s); + } + if(!(tinfo->lifetime_ev)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: strange (1) permission to be cleaned\n",__FUNCTION__); } diff --git a/src/server/ns_turn_allocation.h b/src/server/ns_turn_allocation.h index 96da5684..ff3d4594 100644 --- a/src/server/ns_turn_allocation.h +++ b/src/server/ns_turn_allocation.h @@ -147,6 +147,8 @@ typedef struct _turn_permission_info { turn_time_t expiration_time; ioa_timer_handle lifetime_ev; void* owner; //a + int verbose; + unsigned long long session_id; } turn_permission_info; typedef struct _turn_permission_slot { diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index acde670c..55bc3b85 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -856,6 +856,14 @@ static int update_turn_permission_lifetime(ts_ur_super_session *ss, turn_permiss client_ss_perm_timeout_handler, tinfo, 0, "client_ss_channel_timeout_handler"); + if(server->verbose) { + tinfo->verbose = 1; + tinfo->session_id = ss->id; + char s[257]="\0"; + addr_to_string(&(tinfo->addr),(u08bits*)s); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: peer %s lifetime updated: %lu\n",(unsigned long long)ss->id,s,(unsigned long)time_delta); + } + return 0; } } @@ -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); } diff --git a/turndb/schema.sql b/turndb/schema.sql index 2b2edd2e..b44f1bec 100644 --- a/turndb/schema.sql +++ b/turndb/schema.sql @@ -8,7 +8,7 @@ CREATE TABLE turnusers_lt ( CREATE TABLE turn_secret ( realm varchar(127) default '', - value varchar(127), + value varchar(256), primary key (realm,value) ); diff --git a/turndb/schema.userdb.redis b/turndb/schema.userdb.redis index bcb5c4ff..31bc8b51 100644 --- a/turndb/schema.userdb.redis +++ b/turndb/schema.userdb.redis @@ -45,9 +45,10 @@ and they will be almost immediately "seen" by the turnserver process. is 0 - unlimited lifetime. hkdf_hash_func - (optional) hash function for HKDF procedure; the - valid values are SHA-1 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 diff --git a/turndb/testmongosetup.sh b/turndb/testmongosetup.sh index b6a8779c..a266cf90 100755 --- a/turndb/testmongosetup.sh +++ b/turndb/testmongosetup.sh @@ -51,6 +51,12 @@ db.oauth_key.insert({ kid: 'north', hkdf_hash_func: 'SHA-256', as_rs_alg: 'AES-256-CBC', auth_alg: 'HMAC-SHA-256-128' }); + +db.oauth_key.insert({ kid: 'union', + ikm_key: 'aGVyb2Q=', + hkdf_hash_func: 'SHA-256', + as_rs_alg: 'AES-256-CBC', + auth_alg: 'HMAC-SHA-512' }); db.oauth_key.insert({ kid: 'oldempire', ikm_key: 'YXVsY3Vz', diff --git a/turndb/testredisdbsetup.sh b/turndb/testredisdbsetup.sh index 1fe32ece..29d6d584 100755 --- a/turndb/testredisdbsetup.sh +++ b/turndb/testredisdbsetup.sh @@ -36,6 +36,7 @@ sadd turn/realm/north.gov/denied-peer-ip "172.17.13.133-172.17.14.56" "172.17.17 sadd turn/realm/crinna.org/denied-peer-ip "123::77" hmset turn/oauth/kid/north ikm_key 'Y2FybGVvbg==' hkdf_hash_func 'SHA-256' as_rs_alg 'AES-256-CBC' auth_alg 'HMAC-SHA-256-128' +hmset turn/oauth/kid/union ikm_key 'aGVyb2Q=' hkdf_hash_func 'SHA-256' as_rs_alg 'AES-256-CBC' auth_alg 'HMAC-SHA-512' hmset turn/oauth/kid/oldempire ikm_key 'YXVsY3Vz' hkdf_hash_func 'SHA-256' as_rs_alg 'AEAD-AES-256-GCM' hmset turn/admin_user/skarling realm 'north.gov' password 'hoodless' diff --git a/turndb/testsqldbsetup.sql b/turndb/testsqldbsetup.sql index b20dec5e..8bd0c7a7 100644 --- a/turndb/testsqldbsetup.sql +++ b/turndb/testsqldbsetup.sql @@ -32,4 +32,5 @@ insert into denied_peer_ip (realm,ip_range) values('north.gov','172.17.17.133-17 insert into denied_peer_ip (realm,ip_range) values('crinna.org','123::77'); insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('north','Y2FybGVvbg==',0,0,'SHA-256','AES-256-CBC','','HMAC-SHA-256-128',''); +insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('union','aGVyb2Q=',0,0,'SHA-256','AES-256-CBC','','HMAC-SHA-512',''); insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('oldempire','YXVsY3Vz',0,0,'SHA-256','AEAD-AES-256-GCM','','','');