Преглед на файлове

Imported Upstream version 4.5.0.5

Oleg Moskalenko преди 9 години
родител
ревизия
b604bbd4ae
променени са 46 файла, в които са добавени 1645 реда и са изтрити 150 реда
  1. 7 3
      AUTHORS
  2. 10 0
      ChangeLog
  3. 3 3
      INSTALL
  4. 20 2
      Makefile.in
  5. 2 0
      README.turnadmin
  6. 18 5
      README.turnserver
  7. 124 2
      README.turnutils
  8. 26 5
      examples/etc/turnserver.conf
  9. 2 2
      examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh
  10. 2 2
      examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh
  11. 0 38
      examples/scripts/longtermsecuredb/secure_relay_with_db_psql_test.sh
  12. 17 0
      examples/scripts/oauth.sh
  13. 5 3
      make-man.sh
  14. 3 1
      man/man1/turnadmin.1
  15. 27 8
      man/man1/turnserver.1
  16. 190 6
      man/man1/turnutils.1
  17. 1 0
      man/man1/turnutils_natdiscovery.1
  18. 1 0
      man/man1/turnutils_oauth.1
  19. 1 1
      rpm/build.settings.sh
  20. 8 1
      rpm/turnserver.spec
  21. 1 1
      src/apps/common/apputils.h
  22. 50 0
      src/apps/common/ns_turn_openssl.h
  23. 2 2
      src/apps/common/stun_buffer.c
  24. 1 1
      src/apps/common/stun_buffer.h
  25. 521 0
      src/apps/natdiscovery/natdiscovery.c
  26. 482 0
      src/apps/oauth/oauth.c
  27. 5 0
      src/apps/relay/dbdrivers/dbd_mysql.c
  28. 1 4
      src/apps/relay/dtls_listener.c
  29. 54 5
      src/apps/relay/mainrelay.c
  30. 4 8
      src/apps/relay/mainrelay.h
  31. 3 0
      src/apps/relay/netengine.c
  32. 1 1
      src/apps/relay/ns_ioalib_engine_impl.c
  33. 1 1
      src/apps/relay/ns_ioalib_impl.h
  34. 2 2
      src/apps/stunclient/stunclient.c
  35. 1 3
      src/apps/uclient/mainuclient.c
  36. 1 1
      src/apps/uclient/session.h
  37. 1 1
      src/apps/uclient/startuclient.c
  38. 1 2
      src/apps/uclient/uclient.c
  39. 1 3
      src/apps/uclient/uclient.h
  40. 1 1
      src/client++/TurnMsgLib.h
  41. 11 11
      src/client/ns_turn_msg.c
  42. 2 2
      src/client/ns_turn_msg.h
  43. 4 4
      src/client/ns_turn_msg_defs.h
  44. 1 1
      src/ns_turn_defs.h
  45. 20 14
      src/server/ns_turn_server.c
  46. 6 0
      src/server/ns_turn_server.h

+ 7 - 3
AUTHORS

@@ -40,14 +40,18 @@ Peter Dunkley <[email protected]> :
 	CentOS/Fedora port
 	(since v2.6.6.1)
 
-Mutsutoshi Yoshimoto <[email protected]>
+Mutsutoshi Yoshimoto <[email protected]> :
 	TCP routing: testing and bug fixes
 	(since v3.2.2.7)
 
-Federico Pinna <[email protected]>
+Federico Pinna <[email protected]> :
 	MongoDB support
 	(since v4.1.0.1)
 
-Bradley T. Hughes <[email protected]>
+Bradley T. Hughes <[email protected]> :
 	FreeBSD port
 	(since v4.1.2.1)
+
+Mészáros Mihály <[email protected]> :
+        OAuth utility, NAT behavior Discovery
+        (since v4.5.0.4)

+ 10 - 0
ChangeLog

@@ -1,3 +1,13 @@
+08/27/2016 Oleg Moskalenko <[email protected]>
+Version 4.5.0.5 'dan Eider':
+	- Typos in the text fixed.
+	- LibreSSL compatibility fixed.
+	- "read_timeout" option support for MySQL.
+	- new NAT behavior discovery utilty. 
+	- new OAuth access_token encrypt/decrypt utilty.
+	- improved configurability: added parameters for
+	allocate, channel and permission lifetimes (by Richard Garnier).
+
 08/20/2016 Oleg Moskalenko <[email protected]>
 Version 4.5.0.4 'dan Eider':
 	- OpenSSL 1.1.0 support added.

+ 3 - 3
INSTALL

@@ -1006,18 +1006,18 @@ have such a feature as "connection string", the TURN server parses the
 connection string and converts it into MySQL database connection parameter. 
 The format of the MySQL connection string is:
 
-"host=<host> dbname=<database-name> user=<database-user> password=<database-user-password> port=<port> connect_timeout=<seconds>"
+"host=<host> dbname=<database-name> user=<database-user> password=<database-user-password> port=<port> connect_timeout=<seconds> read_timeout=<seconds>"
 
 (all parameters are optional)
 
 So, an example of the MySQL database parameter in the TURN server command 
 line would be:
 
---mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30"
+--mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30 read_timeout=30"
 
 Or in the turnserver.conf file:
 
-mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30"
+mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30 read_timeout=30"
 
 If you have to use a secure MySQL connection (SSL) then you have to use also
 the optional connection string parameters for the secure communications:

+ 20 - 2
Makefile.in

@@ -16,7 +16,7 @@ SERVERTURN_HEADERS = src/server/ns_turn_allocation.h src/server/ns_turn_ioalib.h
 SERVERTURN_DEPS = ${LIBCLIENTTURN_HEADERS} ${SERVERTURN_HEADERS} ${MAKE_DEPS} 
 SERVERTURN_MODS = ${LIBCLIENTTURN_MODS} src/server/ns_turn_allocation.c src/server/ns_turn_maps_rtcp.c src/server/ns_turn_maps.c src/server/ns_turn_server.c
 
-COMMON_HEADERS = src/apps/common/apputils.h src/apps/common/ns_turn_utils.h src/apps/common/stun_buffer.h
+COMMON_HEADERS = src/apps/common/apputils.h src/apps/common/ns_turn_openssl.h src/apps/common/ns_turn_utils.h src/apps/common/stun_buffer.h
 COMMON_MODS = src/apps/common/apputils.c src/apps/common/ns_turn_utils.c src/apps/common/stun_buffer.c
 COMMON_DEPS = ${LIBCLIENTTURN_DEPS} ${COMMON_MODS} ${COMMON_HEADERS}
 
@@ -34,7 +34,7 @@ SERVERAPP_HEADERS = src/apps/relay/userdb.h src/apps/relay/tls_listener.h src/ap
 SERVERAPP_MODS = src/apps/relay/mainrelay.c src/apps/relay/netengine.c src/apps/relay/libtelnet.c src/apps/relay/turn_admin_server.c src/apps/relay/userdb.c src/apps/relay/tls_listener.c src/apps/relay/dtls_listener.c ${HIREDIS_MODS} ${USERDB_MODS}
 SERVERAPP_DEPS = ${SERVERTURN_MODS} ${SERVERTURN_DEPS} ${SERVERAPP_MODS} ${SERVERAPP_HEADERS} ${COMMON_DEPS} ${IMPL_DEPS} lib/libturnclient.a
 
-TURN_BUILD_RESULTS = bin/turnutils_stunclient bin/turnutils_rfc5769check bin/turnutils_uclient bin/turnserver bin/turnutils_peer lib/libturnclient.a include/turn/ns_turn_defs.h sqlite_empty_db
+TURN_BUILD_RESULTS = bin/turnutils_oauth bin/turnutils_natdiscovery bin/turnutils_stunclient bin/turnutils_rfc5769check bin/turnutils_uclient bin/turnserver bin/turnutils_peer lib/libturnclient.a include/turn/ns_turn_defs.h sqlite_empty_db
 
 all:	${TURN_BUILD_RESULTS}
 
@@ -54,6 +54,16 @@ bin/turnutils_uclient:	${COMMON_DEPS} src/apps/uclient/session.h lib/libturnclie
 	${MKBUILDDIR} bin
 	${CC} ${CPPFLAGS} ${CFLAGS} src/apps/uclient/uclient.c src/apps/uclient/startuclient.c src/apps/uclient/mainuclient.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS}  
 
+bin/turnutils_natdiscovery:	${COMMON_DEPS} lib/libturnclient.a src/apps/natdiscovery/natdiscovery.c
+	pwd
+	${MKBUILDDIR} bin
+	${CC} ${CPPFLAGS} ${CFLAGS} src/apps/natdiscovery/natdiscovery.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS}
+
+bin/turnutils_oauth:	${COMMON_DEPS} lib/libturnclient.a src/apps/oauth/oauth.c
+	pwd
+	${MKBUILDDIR} bin
+	${CC} ${CPPFLAGS} ${CFLAGS} src/apps/oauth/oauth.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS}
+
 bin/turnutils_stunclient:	${COMMON_DEPS} lib/libturnclient.a src/apps/stunclient/stunclient.c 
 	pwd
 	${MKBUILDDIR} bin
@@ -125,11 +135,15 @@ install:	all ${MAKE_DEPS}
 	${INSTALL_PROGRAM} bin/turnutils_uclient ${DESTDIR}${BINDIR}
 	${INSTALL_PROGRAM} bin/turnutils_peer ${DESTDIR}${BINDIR}
 	${INSTALL_PROGRAM} bin/turnutils_stunclient ${DESTDIR}${BINDIR}
+	${INSTALL_PROGRAM} bin/turnutils_oauth ${DESTDIR}${BINDIR}
+	${INSTALL_PROGRAM} bin/turnutils_natdiscovery ${DESTDIR}${BINDIR}
 	${INSTALL_MAN} man/man1/turnserver.1 ${DESTDIR}${MANPREFIX}/man/man1/
 	${INSTALL_MAN} man/man1/turnadmin.1 ${DESTDIR}${MANPREFIX}/man/man1/
 	${INSTALL_MAN} man/man1/turnutils.1 ${DESTDIR}${MANPREFIX}/man/man1/
 	${INSTALL_MAN} man/man1/turnutils_uclient.1 ${DESTDIR}${MANPREFIX}/man/man1/
 	${INSTALL_MAN} man/man1/turnutils_stunclient.1 ${DESTDIR}${MANPREFIX}/man/man1/
+	${INSTALL_MAN} man/man1/turnutils_oauth.1 ${DESTDIR}${MANPREFIX}/man/man1/
+	${INSTALL_MAN} man/man1/turnutils_natdiscovery.1 ${DESTDIR}${MANPREFIX}/man/man1/
 	${INSTALL_MAN} man/man1/turnutils_peer.1 ${DESTDIR}${MANPREFIX}/man/man1/
 	${INSTALL_MAN} man/man1/coturn.1 ${DESTDIR}${MANPREFIX}/man/man1/
 	${INSTALL_STATIC_LIB} lib/libturnclient.a ${DESTDIR}${LIBDIR}
@@ -169,11 +183,15 @@ deinstall:	${MAKE_DEPS}
 	${RMCMD} ${DESTDIR}${BINDIR}/turnutils_peer
 	${RMCMD} ${DESTDIR}${BINDIR}/turnutils_uclient
 	${RMCMD} ${DESTDIR}${BINDIR}/turnutils_stunclient
+	${RMCMD} ${DESTDIR}${BINDIR}/turnutils_oauth
+	${RMCMD} ${DESTDIR}${BINDIR}/turnutils_natdiscovery
 	${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnserver.1
 	${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnadmin.1
 	${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils.1
 	${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_uclient.1
 	${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_stunclient.1
+	${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_oauth.1
+	${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_natdiscovery.1
 	${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_peer.1
 	${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/coturn.1
 	${RMCMD} ${DESTDIR}${LIBDIR}/libturnclient.a

+ 2 - 0
README.turnadmin

@@ -252,3 +252,5 @@ to see the man page.
 	Federico Pinna <[email protected]>
 
 	Bradley T. Hughes <[email protected]>
+
+        Mihaly Meszaros <[email protected]>

+ 18 - 5
README.turnserver

@@ -108,7 +108,7 @@ User database settings:
 		secret-based timed authentication in TURN RESP API.
 		The connection string format is like that:
 		 
-		"host=<host> dbname=<dbname> user=<db-user> password=<db-user-password> connect_timeout=<seconds>"
+		"host=<host> dbname=<dbname> user=<db-user> password=<db-user-password> connect_timeout=<seconds> read_timeout=<seconds>"
 
 		See the INSTALL file for more explanations and examples.
 		
@@ -207,8 +207,6 @@ Flags:
 --no-tcp-relay		Do not allow TCP relay endpoints defined in RFC 6062, 
 			use only UDP relay endpoints as defined in RFC 5766. 
 
---stale-nonce		Use extra security with nonce value having limited lifetime (600 secs). 
-
 --no-stdout-log		Flag to prevent stdout log messages.
 			By default, all log messages are going to both stdout and to
 			the configured log file. With this option everything will be going to 
@@ -259,7 +257,20 @@ Flags:
 
 -h			Help.
     
-Options with required values:  
+Options with values:  
+
+--stale-nonce[=<value>]		Use extra security with nonce value having
+							limited lifetime, in seconds (default 600 secs).
+
+--max-allocate-lifetime		Set the maximum value for the allocation lifetime.
+							Default to 3600 secs.
+
+--channel-lifetime 	Set the lifetime for channel binding, default to 600 secs.
+					This value MUST not be changed for production purposes.
+
+--permission-lifetime	Set the value for the lifetime of the permission.
+					Default to 300 secs.
+					This MUST not be changed for production purposes.
 
 -d, --listening-device	Listener interface device.
 			(NOT RECOMMENDED. Optional functionality, Linux only). 
@@ -360,7 +371,7 @@ Options with required values:
 
 -u, --user		Long-term security mechanism credentials user account, 
 			in the column-separated form username:key. 
-			Multiple user accounts may used in the command line.
+			Multiple user accounts may be used in the command line.
 			The key is either the user password, or
 			the key is generated
 			by turnadmin command. In the second case,
@@ -948,3 +959,5 @@ https://groups.google.com/forum/?fromgroups=#!forum/turn-server-project-rfc5766-
 	Federico Pinna <[email protected]>
 
 	Bradley T. Hughes <[email protected]>
+
+        Mihaly Meszaros <[email protected]>

+ 124 - 2
README.turnutils

@@ -25,7 +25,6 @@ The compiled binary image of this program is located in bin/ subdirectory.
 STUN/TURN protocol implementation. This utility is used only for the compilation
 check procedure, it is not copied to the installation destination.
 
-
 In the "examples/scripts" subdirectory, you will find the examples of command lines to be used 
 to run the programs. The scripts are meant to be run from examples/ subdirectory, for example:
 
@@ -33,6 +32,22 @@ $ cd examples
 
 $ ./scripts/secure_relay.sh
 
+5.	turnutils_natdiscovery: a utility that provides NAT behavior discovery 
+according RFC5780. This utility discovers the actual NAT Mapping and Filtering 
+behavior. Be aweare that at least two different listening IP addresses should 
+be configured to be able to work properly!
+
+6.	turnutils_oauth: a utility that provides OAuth access_token 
+generation(AEAD encryption), validation and decryption. This utility inputs 
+all the keys and lifetimes and any related informations that needed for 
+creation and validationi of an access_token. It outputs a JSON with all OAuth 
+PoP parameters that need to pass to the client. Output is generated accoriding 
+RFC7635 Appendix B, Figure 8. 
+
+For more details, and for the access_token structure, read rfc7635, and see
+script in examples/scripts/oauth.sh.
+
+
 =====================================
     
   NAME
@@ -161,7 +176,7 @@ See the examples in the "examples/scripts" directory.
     
 turnutils_peer - a simple UDP-only echo backend server.  
   
-  SYNOPSYS
+  SYNOPSIS
 
 $ turnutils_peer [-v] [options]
   
@@ -230,6 +245,111 @@ Usage:
 
 $ turnutils_rfc5769check
 
+=====================================
+
+  NAME
+
+turnutils_natdiscovery - a utility that discovers NAT mapping and filtering 
+behavior according RFC5780.
+
+  SYNOPSIS
+
+$ turnutils_natdiscovery [options] <STUN-Server-FQDN-or-IP-address>
+
+  DESCRIPTION
+
+turnutils_natdiscovery discovers the NAT Mapping and Filtering behavior, to 
+determine if that NAT is currently using Endpoint-Independent, 
+Address-Dependent, or Address and Port-Dependent Mapping and/or to determine if 
+that NAT is currently using Endpoint-Independent, Address-Dependent, or Address 
+and Port-Dependent Filtering. 
+
+Use either -m and/or -f flag to discover NAT Mapping and/or Filtering.
+
+Flags:
+
+-m  NAT mapping behavior discovery
+
+-f  NAT filtering behavior discovery
+
+Options with required values:
+
+-p  STUN server port (Default: 3478)
+
+-L  Local address to use (optional)
+
+Usage:
+
+$ turnutils_natdiscovery -m -f stun.example.com
+
+=====================================
+
+  NAME
+
+turnutils_oauth - a utility that helps OAuth access_token generation/encryption and validation/decyption
+
+  SYNOPSIS
+
+$ turnutils_oauth [options]
+
+  DESCRIPTION
+
+turnutils_oauth utilitiy provides help in OAuth access_token encryption and/or 
+decryption with AEAD (Atuthenticated Encryption with Associated Data). It helps 
+for an Auth Server in access_token creation, and also for debuging purposes it 
+helps the access_token validation and decryption. This utility inputs all the 
+keys and lifetimes and any related informations that are needed for encryption 
+or decryption of an access_token. It outputs a JSON with all OAuth PoP 
+parameters that need to pass to the client. Output is generated accoriding 
+RFC7635 Appendix B, Figure 8. This utility could help to build an Auth Server 
+service, but be awere that this utility does not generate "session key" / 
+"mac_key" and not verifies lifetime of "session key" / "mac_key" or "Auth key".
+For more details, and for the access_token structure, read rfc7635, and see
+the example in examples/scripts/oauth.sh.
+
+Use either -e and/or -d flag to encrypt or decrypt access_token.
+
+Flags:
+
+-h, --help     usage
+
+-v, --verbose  verbose mode
+
+-e, --encrypt  encrypt token
+
+-d, --decrypt  decrypt validate token
+
+Options with required values:
+
+-i, --server-name              server name (max. 255 char)
+
+-j, --auth-key-id              Auth key id (max. 32 char)
+
+-k, --auth-key                 base64 encoded Auth key
+
+-l  --auth-key-timestamp       Auth key timestamp (sec since epoch)
+
+-m, --auth-key-lifetime        Auth key lifetime in sec
+
+-n, --auth-key-as-rs-alg       Authorization Server(AS) - Resource Server(RS) encryption algorithm
+
+-o, --token-nonce              base64 encoded nonce base64(12 octet) = 16 char
+
+-p, --token-mac-key            base64 encoded MAC key base64(32 octet) = 44 char
+
+-q, --token-timestamp          timestamp in format 64 bit unsigned (Native format - Unix),
+                               so 48 bit for secs since epoch UTC + 16 bit for 1/64000 fractions of a second.
+                               e.g.: the actual unixtimestamp 16 bit left shifted. (Default: actual gmtime)
+-r, --token-lifetime           lifetime in sec (Default: 3600)
+
+-t, --token                    base64 encoded encrypted token for validation and decryption
+
+-u, --hmac-alg                 stun client hmac algorithm
+
+Usage:
+
+$ turnutils_natdiscovery
+
 ===================================
  
 DOCS
@@ -335,3 +455,5 @@ SEE ALSO
 	Federico Pinna <[email protected]>
 
 	Bradley T. Hughes <[email protected]>
+
+        Mihaly Meszaros <[email protected]>

+ 26 - 5
examples/etc/turnserver.conf

@@ -274,7 +274,7 @@
 #
 # Use string format as below (space separated parameters, all optional):
 #
-#mysql-userdb="host=<host> dbname=<database-name> user=<database-user> password=<database-user-password> port=<port> connect_timeout=<seconds>"
+#mysql-userdb="host=<host> dbname=<database-name> user=<database-user> password=<database-user-password> port=<port> connect_timeout=<seconds> read_timeout=<seconds>"
 
 # MongoDB database connection string in the case that we are using MongoDB
 # as the user database.
@@ -373,13 +373,34 @@
 #no-tcp-relay
 
 # Uncomment if extra security is desired,
-# with nonce value having limited lifetime (600 secs).
+# with nonce value having limited lifetime.
 # By default, the nonce value is unique for a session,
-# but it has unlimited lifetime. With this option,
-# the nonce lifetime is limited to 600 seconds, after that 
+# and has unlimited lifetime. 
+# Set this option to limit the nonce lifetime. 
+# It defaults to 600 secs (10 min) if no value is provided. After that delay, 
 # the client will get 438 error and will have to re-authenticate itself.
 #
-#stale-nonce
+#stale-nonce=600
+
+# Uncomment if you want to set the maximum allocation
+# time before it has to be refreshed.
+# Default is 3600s.
+#
+#max-allocate-lifetime=3600
+
+
+# Uncomment to set the lifetime for the channel.
+# Default value is 600 secs (10 minutes).
+# This value MUST not be changed for production purposes.
+#
+#channel-lifetime=600
+
+# Uncomment to set the permission lifetime.
+# Default to 300 secs (5 minutes).
+# In production this value MUST not be changed,
+# however it can be useful for test purposes.
+#
+#permission-lifetime=300
 
 # Certificate file.
 # Use an absolute path or path relative to the 

+ 2 - 2
examples/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh

@@ -15,7 +15,7 @@
 # 3) use 3 relay threads (-m 3)
 # 4) use min UDP relay port 32355 and max UDP relay port 65535
 # 5) "-r north.gov" means "use authentication realm north.gov"
-# 6) --mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" 
+# 6) --mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30 read_timeout=30" 
 # means that local MySQL database "coturn" will be used, with database user "turn" and 
 # database user password "turn", and connection timeout 30 seconds.
 # 7) "--cert=example_turn_server_cert.pem" sets the OpenSSL certificate file name. 
@@ -32,4 +32,4 @@ fi
 export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
 export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
 
-PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL --oauth $@
+PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30 read_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL --oauth $@

+ 2 - 2
examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh

@@ -15,7 +15,7 @@
 # 3) use 3 relay threads (-m 3)
 # 4) use min UDP relay port 32355 and max UDP relay port 65535
 # 5) "-r north.gov" means "use authentication realm north.gov"
-# 6) --mysql-userdb="host=localhost dbname=coturn user=turn password=turn cipher=DHE-RSA-AES256-SHA connect_timeout=30" 
+# 6) --mysql-userdb="host=localhost dbname=coturn user=turn password=turn cipher=DHE-RSA-AES256-SHA connect_timeout=30 read_timeout=30" 
 # means that local MySQL database "coturn" will be used, with database user "turn" and 
 # database user password "turn", and with SSL connection with cipher DHE-RSA-AES256-SHA, 
 # and connection timeout 30 seconds.
@@ -33,4 +33,4 @@ fi
 export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
 export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
 
-PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --mysql-userdb="host=localhost dbname=coturn user=turn password=turn cipher=DHE-RSA-AES256-SHA connect_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL --oauth $@
+PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --mysql-userdb="host=localhost dbname=coturn user=turn password=turn cipher=DHE-RSA-AES256-SHA connect_timeout=30 read_timeout=30" --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL --oauth $@

+ 0 - 38
examples/scripts/longtermsecuredb/secure_relay_with_db_psql_test.sh

@@ -1,38 +0,0 @@
-#!/bin/sh
-#
-# This is an example how to start a TURN Server in
-# secure mode with Postgres database for users
-# with the long-term credentials mechanism.
-#
-# We start here a TURN Server listening on IPv4 address
-# 127.0.0.1 and on IPv6 address ::1. We use 127.0.0.1 as
-# IPv4 relay address, and we use ::1 as IPv6 relay address.
-#
-# Other options:
-#
-# 1) set bandwidth limit on client session 3000000 bytes per second (--max-bps).
-# 2) use fingerprints (-f)
-# 3) use 3 relay threads (-m 3)
-# 4) use min UDP relay port 32355 and max UDP relay port 65535
-# 5) "-r north.gov" means "use authentication realm north.gov"
-# 6) --psql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30" 
-# means that local database "coturn" will be used, with database user "turn" and database user 
-# password "turn".
-# 7) "--cert=example_turn_server_cert.pem" sets the OpenSSL certificate file name. 
-# 8) "--pkey=example_turn_server_pkey.pem" sets the OpenSSL private key name.
-# 9) "--log-file=stdout" means that all log output will go to the stdout.
-# 10) --cipher-list=ALL means that we support all OpenSSL ciphers
-# 11) --oauth - support oAuth security dialog
-# Other parameters (config file name, etc) are default.
-
-if [ -d examples ] ; then
-       cd examples
-fi
-
-export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
-export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/usr/local/lib/:/usr/local/mysql/lib/
-
-PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL --oauth $@ 
-
-# Newer PostgreSQL style connection string example:
-# PATH="./bin/:../bin/:../../bin/:${PATH}" turnserver --server-name="blackdow.carleon.gov" -v --syslog -a -L 127.0.0.1 -L ::1 -E 127.0.0.1 -E ::1 --max-bps=3000000 -f -m 3 --min-port=32355 --max-port=65535 -r north.gov --psql-userdb=postgresql://turn:turn@/turn --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout --cipher-list=ALL --oauth $@

+ 17 - 0
examples/scripts/oauth.sh

@@ -0,0 +1,17 @@
+#!/bin/bash
+
+OAUTH_UTILITY=bin/turnutils_oauth
+
+echo "--------------create an access_token---------------"
+$OAUTH_UTILITY -e --server-name example.com --auth-key-id 1234 --auth-key SEdrajMyS0pHaXV5MDk4c2RmYXFiTmpPaWF6NzE5MjM= --auth-key-timestamp 249213600 --auth-key-lifetime 21600 --token-mac-key WmtzanB3ZW9peFhtdm42NzUzNG0=  --token-timestamp 16333642137600 --token-lifetime=3600
+
+echo "---------------create and validate and print out the decoded access_token---------------"
+$OAUTH_UTILITY -v -d -e --server-name example.com --auth-key-id 1234 --auth-key SEdrajMyS0pHaXV5MDk4c2RmYXFiTmpPaWF6NzE5MjM= --auth-key-timestamp 249213600 --auth-key-lifetime 21600 --token-mac-key WmtzanB3ZW9peFhtdm42NzUzNG0=  --token-timestamp 16333642137600 --token-lifetime=3600
+
+echo -e "\n---------------just validate only the access_token---------------"
+$OAUTH_UTILITY -d --server-name example.com --auth-key-id 1234 --auth-key SEdrajMyS0pHaXV5MDk4c2RmYXFiTmpPaWF6NzE5MjM= --auth-key-timestamp 249213600 --auth-key-lifetime 21600 --token AAy1JBYVLo16iq9gFdHyyknmx5T/Lq9YlbxgUdLcStOFS0H8xhHceHOL2f49qxp4uBpGuuLeLqk+RcAa5uP2EQ== --token-lifetime=3600
+
+echo -e "\n---------------validate and print out the decoded access_token---------------"
+$OAUTH_UTILITY -v -d --server-name example.com --auth-key-id 1234 --auth-key SEdrajMyS0pHaXV5MDk4c2RmYXFiTmpPaWF6NzE5MjM= --auth-key-timestamp 249213600 --auth-key-lifetime 21600 --token AAy1JBYVLo16iq9gFdHyyknmx5T/Lq9YlbxgUdLcStOFS0H8xhHceHOL2f49qxp4uBpGuuLeLqk+RcAa5uP2EQ== --token-lifetime=3600
+
+

+ 5 - 3
make-man.sh

@@ -2,14 +2,16 @@
 
 rm -rf man/man1/*
 
-txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -B "TURN Server" README.turnserver | sed -e 's/-/\\-/g' > man/man1/turnserver.1
+txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -I turnutils_natdiscovery -I turnutils_oauth -B "TURN Server" README.turnserver | sed -e 's/-/\\-/g' > man/man1/turnserver.1
 
-txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -B "TURN Server" README.turnadmin | sed -e 's/-/\\-/g'> man/man1/turnadmin.1
+txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -I turnutils_natdiscovery -I turnutils_oauth -B "TURN Server" README.turnadmin | sed -e 's/-/\\-/g'> man/man1/turnadmin.1
 
-txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -B "TURN Server" README.turnutils | sed -e 's/-/\\-/g' > man/man1/turnutils.1
+txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -I turnutils_natdiscovery -I turnutils_oauth -B "TURN Server" README.turnutils | sed -e 's/-/\\-/g' > man/man1/turnutils.1
 
 cd man/man1; ln -s turnutils.1 turnutils_uclient.1;cd ../..
 cd man/man1; ln -s turnutils.1 turnutils_peer.1;cd ../..
 cd man/man1; ln -s turnutils.1 turnutils_stunclient.1;cd ../..
+cd man/man1; ln -s turnutils.1 turnutils_natdiscovery.1;cd ../..
+cd man/man1; ln -s turnutils.1 turnutils_oauth.1;cd ../..
 cd man/man1; ln -s turnserver.1 coturn.1;cd ../..
 

+ 3 - 1
man/man1/turnadmin.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "29 November 2015" "" ""
+.TH TURN 1 "25 September 2016" "" ""
 .SH GENERAL INFORMATION
 
 \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage 
@@ -340,3 +340,5 @@ Mutsutoshi Yoshimoto <[email protected]>
 Federico Pinna <[email protected]>
 .PP
 Bradley T. Hughes <[email protected]>
+.PP
+Mihaly Meszaros <[email protected]>

+ 27 - 8
man/man1/turnserver.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "29 November 2015" "" ""
+.TH TURN 1 "25 September 2016" "" ""
 .SH GENERAL INFORMATION
 
 The \fBTURN Server\fP project contains the source code of a TURN server and TURN client 
@@ -166,7 +166,7 @@ secret\-based timed authentication in TURN RESP API.
 The connection string format is like that:
 .RS
 .PP
-"host=<host> dbname=<dbname> user=<db\-user> password=<db\-user\-password> connect_timeout=<seconds>"
+"host=<host> dbname=<dbname> user=<db\-user> password=<db\-user\-password> connect_timeout=<seconds> read_timeout=<seconds>"
 .PP
 See the INSTALL file for more explanations and examples.
 .PP
@@ -314,10 +314,6 @@ Do not allow TCP relay endpoints defined in RFC 6062,
 use only UDP relay endpoints as defined in RFC 5766. 
 .TP
 .B
-\fB\-\-stale\-nonce\fP
-Use extra security with nonce value having limited lifetime (600 secs). 
-.TP
-.B
 \fB\-\-no\-stdout\-log\fP
 Flag to prevent stdout log messages.
 By default, all log messages are going to both stdout and to
@@ -396,7 +392,28 @@ initially used by the session).
 Help.
 .TP
 .B
-Options with required values:
+Options with values:
+.TP
+.B
+\fB\-\-stale\-nonce\fP[=<value>]
+Use extra security with nonce value having
+limited lifetime, in seconds (default 600 secs).
+.TP
+.B
+\fB\-\-max\-allocate\-lifetime\fP
+Set the maximum value for the allocation lifetime.
+Default to 3600 secs.
+.TP
+.B
+\fB\-\-channel\-lifetime\fP
+Set the lifetime for channel binding, default to 600 secs.
+This value MUST not be changed for production purposes.
+.TP
+.B
+\fB\-\-permission\-lifetime\fP
+Set the value for the lifetime of the permission.
+Default to 300 secs.
+This MUST not be changed for production purposes.
 .TP
 .B
 \fB\-d\fP, \fB\-\-listening\-device\fP
@@ -529,7 +546,7 @@ Default value is 65535, according to RFC 5766.
 \fB\-u\fP, \fB\-\-user\fP
 Long\-term security mechanism credentials user account, 
 in the column\-separated form username:key. 
-Multiple user accounts may used in the command line.
+Multiple user accounts may be used in the command line.
 The key is either the user password, or
 the key is generated
 by \fIturnadmin\fP command. In the second case,
@@ -1189,3 +1206,5 @@ Mutsutoshi Yoshimoto <[email protected]>
 Federico Pinna <[email protected]>
 .PP
 Bradley T. Hughes <[email protected]>
+.PP
+Mihaly Meszaros <[email protected]>

+ 190 - 6
man/man1/turnutils.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "29 November 2015" "" ""
+.TH TURN 1 "25 September 2016" "" ""
 .SH GENERAL INFORMATION
 
 A set of turnutils_* programs provides some utility functionality to be used
@@ -34,17 +34,36 @@ The compiled binary image of this program is located in bin/ subdirectory.
 \fIturnutils_rfc5769check\fP: a utility that checks the correctness of the 
 STUN/TURN protocol implementation. This utility is used only for the compilation
 check procedure, it is not copied to the installation destination.
-.RE
 .PP
-
-.RS
 In the "examples/scripts" subdirectory, you will find the examples of command lines to be used 
 to run the programs. The scripts are meant to be run from examples/ subdirectory, for example:
 .PP
 $ cd examples
 .PP
 $ ./scripts/secure_relay.sh
+.TP
+.B
+5.
+\fIturnutils_natdiscovery\fP: a utility that provides NAT behavior discovery 
+according RFC5780. This utility discovers the actual NAT Mapping and Filtering 
+behavior. Be aweare that at least two different listening IP addresses should 
+be configured to be able to work properly!
+.TP
+.B
+6.
+\fIturnutils_oauth\fP: a utility that provides OAuth access_token 
+\fBgeneration\fP(AEAD encryption), validation and decryption. This utility inputs 
+all the keys and lifetimes and any related informations that needed for 
+creation and validationi of an access_token. It outputs a JSON with all OAuth 
+PoP parameters that need to pass to the client. Output is generated accoriding 
+RFC7635 Appendix B, Figure 8. 
 .PP
+For more details, and for the access_token structure, read rfc7635, and see
+script in examples/scripts/oauth.sh.
+.RE
+.PP
+
+.RS
 =====================================
 .SS  NAME
 \fB
@@ -258,9 +277,16 @@ See the examples in the "examples/scripts" directory.
 \fB
 \fBturnutils_peer \fP\- a simple UDP\-only echo backend server.
 \fB
-.SS  SYNOPSYS
+.SS  SYNOPSIS
+.nf
+.fam C
 
-$ \fIturnutils_peer\fP [\fB\-v\fP] [options]
+$ \fIturnutils_peer\fP [\fB\-v\fP] [\fIoptions\fP]
+
+.fam T
+.fi
+.fam T
+.fi
 .SS  DESCRIPTION
 
 This application is used for the test purposes only, as a peer for the \fIturnutils_uclient\fP application.
@@ -353,6 +379,162 @@ Usage:
 .PP
 $ \fIturnutils_rfc5769check\fP
 .PP
+=====================================
+.SS  NAME
+\fB
+\fBturnutils_natdiscovery \fP\- a utility that discovers NAT mapping and filtering
+\fBbehavior according RFC5780.
+\fB
+.SS  SYNOPSIS
+.nf
+.fam C
+
+$ \fIturnutils_natdiscovery\fP [\fIoptions\fP] <STUN\-Server\-FQDN\-or\-IP\-address>
+
+.fam T
+.fi
+.fam T
+.fi
+.SS  DESCRIPTION
+
+\fIturnutils_natdiscovery\fP discovers the NAT Mapping and Filtering behavior, to 
+determine if that NAT is currently using Endpoint\-Independent, 
+Address\-Dependent, or Address and Port\-Dependent Mapping and/or to determine if 
+that NAT is currently using Endpoint\-Independent, Address\-Dependent, or Address 
+and Port\-Dependent Filtering. 
+.PP
+Use either \fB\-m\fP and/or \fB\-f\fP flag to discover NAT Mapping and/or Filtering.
+.PP
+Flags:
+.TP
+.B
+\fB\-m\fP
+NAT mapping behavior discovery
+.TP
+.B
+\fB\-f\fP
+NAT filtering behavior discovery
+.PP
+Options with required values:
+.TP
+.B
+\fB\-p\fP
+STUN server port (Default: 3478)
+.TP
+.B
+\fB\-L\fP
+Local address to use (optional)
+.PP
+Usage:
+.PP
+$ \fIturnutils_natdiscovery\fP \fB\-m\fP \fB\-f\fP stun.example.com
+.PP
+=====================================
+.SS  NAME
+\fB
+\fBturnutils_oauth \fP\- a utility that helps OAuth access_token generation/encryption and validation/decyption
+\fB
+.SS  SYNOPSIS
+.nf
+.fam C
+
+$ \fIturnutils_oauth\fP [\fIoptions\fP]
+
+.fam T
+.fi
+.fam T
+.fi
+.SS  DESCRIPTION
+
+\fIturnutils_oauth\fP utilitiy provides help in OAuth access_token encryption and/or 
+decryption with AEAD (Atuthenticated Encryption with Associated Data). It helps 
+for an Auth Server in access_token creation, and also for debuging purposes it 
+helps the access_token validation and decryption. This utility inputs all the 
+keys and lifetimes and any related informations that are needed for encryption 
+or decryption of an access_token. It outputs a JSON with all OAuth PoP 
+parameters that need to pass to the client. Output is generated accoriding 
+RFC7635 Appendix B, Figure 8. This utility could help to build an Auth Server 
+service, but be awere that this utility does not generate "session key" / 
+"mac_key" and not verifies lifetime of "session key" / "mac_key" or "Auth key".
+For more details, and for the access_token structure, read rfc7635, and see
+the example in examples/scripts/oauth.sh.
+.PP
+Use either \fB\-e\fP and/or \fB\-d\fP flag to encrypt or decrypt access_token.
+.PP
+Flags:
+.TP
+.B
+\fB\-h\fP, \fB\-\-help\fP
+usage
+.TP
+.B
+\fB\-v\fP, \fB\-\-verbose\fP
+verbose mode
+.TP
+.B
+\fB\-e\fP, \fB\-\-encrypt\fP
+encrypt token
+.TP
+.B
+\fB\-d\fP, \fB\-\-decrypt\fP
+decrypt validate token
+.PP
+Options with required values:
+.TP
+.B
+\fB\-i\fP, \fB\-\-server\-name\fP
+server name (max. 255 char)
+.TP
+.B
+\fB\-j\fP, \fB\-\-auth\-key\-id\fP
+Auth key id (max. 32 char)
+.TP
+.B
+\fB\-k\fP, \fB\-\-auth\-key\fP
+base64 encoded Auth key
+.TP
+.B
+\fB\-l\fP
+\fB\-\-auth\-key\-timestamp\fP       Auth key timestamp (sec since epoch)
+.TP
+.B
+\fB\-m\fP, \fB\-\-auth\-key\-lifetime\fP
+Auth key lifetime in sec
+.TP
+.B
+\fB\-n\fP, \fB\-\-auth\-key\-as\-rs\-alg\fP
+Authorization \fBServer\fP(AS) \- Resource \fBServer\fP(RS) encryption algorithm
+.TP
+.B
+\fB\-o\fP, \fB\-\-token\-nonce\fP
+base64 encoded nonce \fBbase64\fP(12 octet) = 16 char
+.TP
+.B
+\fB\-p\fP, \fB\-\-token\-mac\-key\fP
+base64 encoded MAC key \fBbase64\fP(32 octet) = 44 char
+.TP
+.B
+\fB\-q\fP, \fB\-\-token\-timestamp\fP
+timestamp in format 64 bit unsigned (Native format \- Unix),
+so 48 bit for secs since epoch UTC + 16 bit for 1/64000 fractions of a second.
+e.g.: the actual unixtimestamp 16 bit left shifted. (Default: actual gmtime)
+.TP
+.B
+\fB\-r\fP, \fB\-\-token\-lifetime\fP
+lifetime in sec (Default: 3600)
+.TP
+.B
+\fB\-t\fP, \fB\-\-token\fP
+base64 encoded encrypted token for validation and decryption
+.TP
+.B
+\fB\-u\fP, \fB\-\-hmac\-alg\fP
+stun client hmac algorithm
+.PP
+Usage:
+.PP
+$ \fIturnutils_natdiscovery\fP
+.PP
 ===================================
 .SH DOCS
 
@@ -453,3 +635,5 @@ Mutsutoshi Yoshimoto <[email protected]>
 Federico Pinna <[email protected]>
 .PP
 Bradley T. Hughes <[email protected]>
+.PP
+Mihaly Meszaros <[email protected]>

+ 1 - 0
man/man1/turnutils_natdiscovery.1

@@ -0,0 +1 @@
+turnutils.1

+ 1 - 0
man/man1/turnutils_oauth.1

@@ -0,0 +1 @@
+turnutils.1

+ 1 - 1
rpm/build.settings.sh

@@ -2,7 +2,7 @@
 
 # Common settings script.
 
-TURNVERSION=4.5.0.4
+TURNVERSION=4.5.0.5
 BUILDDIR=~/rpmbuild
 ARCH=`uname -p`
 TURNSERVER_GIT_URL=https://github.com/coturn/coturn.git

+ 8 - 1
rpm/turnserver.spec

@@ -1,5 +1,5 @@
 Name:		turnserver
-Version:	4.5.0.4
+Version:	4.5.0.5
 Release:	0%{dist}
 Summary:	Coturn TURN Server
 
@@ -202,6 +202,7 @@ fi
 %{_datadir}/%{name}/etc/turnserver.conf
 %dir %{_datadir}/%{name}/scripts
 %{_datadir}/%{name}/scripts/peer.sh
+%{_datadir}/%{name}/scripts/oauth.sh
 %{_datadir}/%{name}/scripts/readme.txt
 %dir %{_datadir}/%{name}/scripts/basic
 %{_datadir}/%{name}/scripts/basic/dos_attack.sh
@@ -261,10 +262,14 @@ fi
 %{_bindir}/turnutils_peer
 %{_bindir}/turnutils_stunclient
 %{_bindir}/turnutils_uclient
+%{_bindir}/turnutils_oauth
+%{_bindir}/turnutils_natdiscovery
 %{_mandir}/man1/turnutils.1.gz
 %{_mandir}/man1/turnutils_peer.1.gz
 %{_mandir}/man1/turnutils_stunclient.1.gz
 %{_mandir}/man1/turnutils_uclient.1.gz
+%{_mandir}/man1/turnutils_oauth.1.gz
+%{_mandir}/man1/turnutils_natdiscovery.1.gz
 %dir %{_docdir}/%{name}
 %{_docdir}/%{name}/LICENSE
 %{_docdir}/%{name}/README.turnutils
@@ -290,6 +295,8 @@ fi
 %{_includedir}/turn/client/TurnMsgLib.h
 
 %changelog
+* Sat Aug 27 2016 Oleg Moskalenko <[email protected]>
+  - Sync to 4.5.0.5
 * Sat Aug 20 2016 Oleg Moskalenko <[email protected]>
   - Sync to 4.5.0.4
 * Sun Oct 11 2015 Oleg Moskalenko <[email protected]>

+ 1 - 1
src/apps/common/apputils.h

@@ -33,7 +33,7 @@
 
 #include <event2/event.h>
 
-#include <openssl/ssl.h>
+#include "ns_turn_openssl.h"
 
 #include "ns_turn_ioaddr.h"
 #include "ns_turn_msg_defs.h"

+ 50 - 0
src/apps/common/ns_turn_openssl.h

@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011, 2012, 2013 Citrix Systems
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __NST_OPENSSL_LIB__
+#define __NST_OPENSSL_LIB__
+
+#include <openssl/md5.h>
+#include <openssl/hmac.h>
+#include <openssl/ssl.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/crypto.h>
+#include <openssl/opensslv.h>
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+
+#if (defined LIBRESSL_VERSION_NUMBER && OPENSSL_VERSION_NUMBER == 0x20000000L)
+#undef OPENSSL_VERSION_NUMBER
+#define OPENSSL_VERSION_NUMBER 0x1000107FL
+#endif
+
+#endif //__NST_OPENSSL_LIB__

+ 2 - 2
src/apps/common/stun_buffer.c

@@ -160,12 +160,12 @@ int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int af4, int a
 int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid, 
 			       const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2,
 			       const ioa_addr *reflexive_addr,
-			       u32bits lifetime, int error_code, const u08bits *reason,
+			       u32bits lifetime, u32bits max_lifetime, int error_code, const u08bits *reason,
 			       u64bits reservation_token, char *mobile_id) {
 
   return stun_set_allocate_response_str(buf->buf, (size_t*)(&(buf->len)), tid, 
 					relayed_addr1, relayed_addr2, reflexive_addr,
-					lifetime, error_code, reason,
+					lifetime, max_lifetime, error_code, reason,
 					reservation_token, mobile_id);
 
 }

+ 1 - 1
src/apps/common/stun_buffer.h

@@ -105,7 +105,7 @@ int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int af4, int a
 int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid, 
 			       const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2,
 			       const ioa_addr *reflexive_addr,
-			       u32bits lifetime,
+			       u32bits lifetime, u32bits max_lifetime,
 			       int error_code, const u08bits *reason,
 			       u64bits reservation_token, char *mobile_id);
 

+ 521 - 0
src/apps/natdiscovery/natdiscovery.c

@@ -0,0 +1,521 @@
+/*
+ * Copyright (C) 2011, 2012, 2013 Citrix Systems
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "ns_turn_utils.h"
+#include "apputils.h"
+#include "stun_buffer.h"
+
+#ifdef __cplusplus
+#include "TurnMsgLib.h"
+#endif
+
+////////////////////////////////////////////////////
+
+static int udp_fd = -1;
+static ioa_addr real_local_addr;
+static int counter = 0;
+
+#ifdef __cplusplus
+
+static int run_stunclient(ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int response_port, int change_ip, int change_port, int padding)
+{
+	int ret=0;
+
+	if (response_port >= 0) {
+		addr_set_port(&real_local_addr, response_port);
+	}
+	udp_fd = socket(remote_addr->ss.sa_family, SOCK_DGRAM, 0);
+	if (udp_fd < 0)
+		err(-1, NULL);
+
+	if (!addr_any(&real_local_addr)) {
+		if (addr_bind(udp_fd, &real_local_addr,0,1,UDP_SOCKET) < 0)
+			err(-1, NULL);
+	}
+
+
+
+
+	turn::StunMsgRequest req(STUN_METHOD_BINDING);
+
+	req.constructBindingRequest();
+
+	if (response_port >= 0) {
+	  turn::StunAttrResponsePort rpa;
+		rpa.setResponsePort((u16bits)response_port);
+		try {
+			req.addAttr(rpa);
+		} catch(turn::WrongStunAttrFormatException &ex1) {
+			printf("Wrong rp attr format\n");
+			exit(-1);
+		} catch(turn::WrongStunBufferFormatException &ex2) {
+			printf("Wrong stun buffer format (1)\n");
+			exit(-1);
+		} catch(...) {
+			printf("Wrong something (1)\n");
+			exit(-1);
+		}
+	}
+	if (change_ip || change_port) {
+		turn::StunAttrChangeRequest cra;
+		cra.setChangeIp(change_ip);
+		cra.setChangePort(change_port);
+		try {
+			req.addAttr(cra);
+		} catch(turn::WrongStunAttrFormatException &ex1) {
+			printf("Wrong cr attr format\n");
+			exit(-1);
+		} catch(turn::WrongStunBufferFormatException &ex2) {
+			printf("Wrong stun buffer format (2)\n");
+			exit(-1);
+		} catch(...) {
+			printf("Wrong something (2)\n");
+			exit(-1);
+		}
+	}
+	if (padding) {
+		turn::StunAttrPadding pa;
+		pa.setPadding(1500);
+		try {
+			req.addAttr(pa);
+		} catch(turn::WrongStunAttrFormatException &ex1) {
+			printf("Wrong p attr format\n");
+			exit(-1);
+		} catch(turn::WrongStunBufferFormatException &ex2) {
+			printf("Wrong stun buffer format (3)\n");
+			exit(-1);
+		} catch(...) {
+			printf("Wrong something (3)\n");
+			exit(-1);
+		}
+	}
+
+	{
+		int len = 0;
+		int slen = get_ioa_addr_len(remote_addr);
+
+		do {
+			len = sendto(udp_fd, req.getRawBuffer(), req.getSize(), 0, (struct sockaddr*) remote_addr, (socklen_t) slen);
+		} while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN)));
+
+		if (len < 0)
+			err(-1, NULL);
+
+	}
+
+	if (addr_get_from_sock(udp_fd, &real_local_addr) < 0) {
+		printf("%s: Cannot get address from local socket\n", __FUNCTION__);
+	} else {
+		*port = addr_get_port(&real_local_addr);
+	}
+
+	{
+		int len = 0;
+		stun_buffer buf;
+		u08bits *ptr = buf.buf;
+		int recvd = 0;
+		const int to_recv = sizeof(buf.buf);
+		struct timeval tv;
+
+		tv.tv_sec = 3;  /* 3 Secs Timeout */
+		tv.tv_usec = 0;  // Not init'ing this can cause strange errors
+
+		setsockopt(udp_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
+
+		do {
+			len = recv(udp_fd, ptr, to_recv - recvd, 0);
+			if (len > 0) {
+				recvd += len;
+				ptr += len;
+				break;
+			}
+		} while (len < 0 && (errno == EINTR));
+
+		if (recvd > 0)
+			len = recvd;
+		buf.len = len;
+
+		try {
+			turn::StunMsgResponse res(buf.buf, sizeof(buf.buf), (size_t)buf.len, true);
+
+			if (res.isCommand()) {
+
+				if(res.isSuccess()) {
+
+					if (res.isBindingResponse()) {
+
+						turn::StunAttrIterator iter(res,STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS);
+						if (!iter.eof()) {
+
+							turn::StunAttrAddr addr(iter);
+							addr.getAddr(*reflexive_addr);
+
+							turn::StunAttrIterator iter1(res,STUN_ATTRIBUTE_OTHER_ADDRESS);
+							if (!iter1.eof()) {
+								*rfc5780 = 1;
+								printf("\n========================================\n");
+								printf("RFC 5780 response %d\n",++counter);
+								turn::StunAttrAddr addr1(iter1);
+								addr1.getAddr(*other_addr);
+								turn::StunAttrIterator iter2(res,STUN_ATTRIBUTE_RESPONSE_ORIGIN);
+								if (!iter2.eof()) {
+									ioa_addr response_origin;
+									turn::StunAttrAddr addr2(iter2);
+									addr2.getAddr(response_origin);
+									addr_debug_print(1, &response_origin, "Response origin: ");
+								}
+								addr_debug_print(1, other_addr, "Other addr: ");
+							}
+							addr_debug_print(1, reflexive_addr, "UDP reflexive addr");
+
+						} else {
+							printf("Cannot read the response\n");
+						}
+					} else {
+						printf("Wrong type of response\n");
+					}
+				} else {
+					int err_code = res.getError();
+					std::string reason = res.getReason();
+
+					printf("The response is an error %d (%s)\n", err_code, reason.c_str());
+				}
+			} else {
+				printf("The response is not a reponse message\n");
+			}
+		} catch(...) {
+			if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
+				printf("STUN receive timeout..\n");
+			}else{
+				printf("The response is not a well formed STUN message\n");
+			}
+                        ret=1;
+		}
+	}
+	close(udp_fd);
+
+	return ret;
+}
+
+#else
+
+static int run_stunclient(ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int response_port, int change_ip, int change_port, int padding)
+{
+	int ret=0;
+	stun_buffer buf;
+
+	udp_fd = socket(remote_addr->ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL);
+	if (udp_fd < 0)
+		err(-1, NULL);
+
+	if (!addr_any(&real_local_addr)) {
+		if (response_port >= 0) {
+			addr_set_port(&real_local_addr, response_port);
+                } 
+		if (addr_bind(udp_fd, &real_local_addr,0,1,UDP_SOCKET) < 0) {
+			err(-1, NULL);
+                }
+	}
+
+
+	stun_prepare_binding_request(&buf);
+
+	if (response_port >= 0) {
+		stun_attr_add_response_port_str((u08bits*) (buf.buf), (size_t*) &(buf.len), (u16bits) response_port);
+	}
+	if (change_ip || change_port) {
+		stun_attr_add_change_request_str((u08bits*) buf.buf, (size_t*) &(buf.len), change_ip, change_port);
+	}
+	if (padding) {
+		if(stun_attr_add_padding_str((u08bits*) buf.buf, (size_t*) &(buf.len), 1500)<0) {
+			printf("%s: ERROR: Cannot add padding\n",__FUNCTION__);
+		}
+	}
+
+	{
+		int len = 0;
+		int slen = get_ioa_addr_len(remote_addr);
+
+		do {
+			len = sendto(udp_fd, buf.buf, buf.len, 0, (struct sockaddr*) remote_addr, (socklen_t) slen);
+		} while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN)));
+
+		if (len < 0)
+			err(-1, NULL);
+
+	}
+
+	if (addr_get_from_sock(udp_fd, &real_local_addr) < 0) {
+		printf("%s: Cannot get address from local socket\n", __FUNCTION__);
+	} else {
+		*port = addr_get_port(&real_local_addr);
+	}
+
+	
+	{
+		int len = 0;
+		u08bits *ptr = buf.buf;
+		int recvd = 0;
+		const int to_recv = sizeof(buf.buf);
+		struct timeval tv;
+
+		tv.tv_sec = 3;  /* 3 Secs Timeout */
+		tv.tv_usec = 0;  // Not init'ing this can cause strange errors
+
+		setsockopt(udp_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
+
+		do {
+			len = recv(udp_fd, ptr, to_recv - recvd, 0);
+			if (len > 0) {
+				recvd += len;
+				ptr += len;
+				break;
+			}
+		} while (len < 0 && (errno == EINTR));
+
+		if (recvd > 0)
+			len = recvd;
+		buf.len = len;
+
+		if (stun_is_command_message(&buf)) {
+
+			if (stun_is_response(&buf)) {
+
+				if (stun_is_success_response(&buf)) {
+
+					if (stun_is_binding_response(&buf)) {
+
+						addr_set_any(reflexive_addr);
+						if (stun_attr_get_first_addr(&buf, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, reflexive_addr, NULL) >= 0) {
+
+							stun_attr_ref sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_OTHER_ADDRESS);
+							if (sar) {
+								*rfc5780 = 1;
+								printf("\n========================================\n");
+								printf("RFC 5780 response %d\n",++counter);
+								stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, other_addr, NULL);
+								sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_RESPONSE_ORIGIN);
+								if (sar) {
+									ioa_addr response_origin;
+									stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, &response_origin, NULL);
+									addr_debug_print(1, &response_origin, "Response origin: ");
+								}
+								addr_debug_print(1, other_addr, "Other addr: ");
+							}
+							addr_debug_print(1, reflexive_addr, "UDP reflexive addr");
+
+						} else {
+							printf("Cannot read the response\n");
+						}
+					} else {
+						printf("Wrong type of response\n");
+					}
+				} else {
+					int err_code = 0;
+					u08bits err_msg[1025] = "\0";
+					size_t err_msg_size = sizeof(err_msg);
+					if (stun_is_error_response(&buf, &err_code, err_msg, err_msg_size)) {
+						printf("The response is an error %d (%s)\n", err_code, (char*) err_msg);
+					} else {
+						printf("The response is an unrecognized error\n");
+					}
+				}
+			} else {
+				printf("The response is not a reponse message\n");
+				ret=1;
+			}
+		} else {
+			if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
+				printf("STUN receive timeout..\n");
+			}else{
+				printf("The response is not a STUN message\n");
+			}
+			ret=1;
+		}
+	}
+
+	socket_closesocket(udp_fd);
+	return ret;
+}
+#endif
+
+//////////////// local definitions /////////////////
+
+static char Usage[] =
+  "Usage: natdiscovery [options] address\n"
+  "Options:\n"
+  "        -m      NAT mapping behavior discovery\n"
+  "        -f      NAT filtering behavior discovery\n"
+  "        -p      STUN server port (Default: 3478)\n"
+  "        -L      Local address to use (optional)\n";
+
+//////////////////////////////////////////////////
+
+static void init(ioa_addr *real_local_addr,ioa_addr *remote_addr,int *local_port,int port, int *rfc5780, char* local_addr, char* remote_param)
+{
+  addr_set_any(real_local_addr);
+
+  if(local_addr[0]) {
+      if(make_ioa_addr((const u08bits*)local_addr, 0, real_local_addr)<0) {
+        err(-1,NULL);
+      }
+  }
+
+  *local_port = -1;
+  *rfc5780 = 0;
+
+  if (make_ioa_addr((const u08bits*)remote_param, port, remote_addr) < 0)
+		err(-1, NULL);
+}
+
+static void discoveryresult(const char *decision){
+	printf("\n========================================\n");
+	printf("%s",decision);
+	printf("\n========================================\n");
+}
+
+int main(int argc, char **argv)
+{
+  int port = DEFAULT_STUN_PORT;
+  char local_addr[256]="\0";
+  int c=0;
+  int mapping = 0;
+  int filtering = 0;
+  int local_port, rfc5780;
+  ioa_addr other_addr, reflexive_addr, tmp_addr, remote_addr;
+  
+
+  set_logfile("stdout");
+  set_system_parameters(0);
+  
+  ns_bzero(local_addr, sizeof(local_addr));
+  addr_set_any(&remote_addr);
+  addr_set_any(&other_addr);
+  addr_set_any(&reflexive_addr);
+  addr_set_any(&tmp_addr);
+
+  while ((c = getopt(argc, argv, "mfp:L:")) != -1) {
+    switch(c) {
+    case 'm':
+      mapping=1;
+      break;
+    case 'f':
+      filtering=1;
+      break;
+    case 'p':
+      port = atoi(optarg);
+      break;
+    case 'L':
+      STRCPY(local_addr, optarg);
+      break;
+    default:
+      fprintf(stderr,"%s\n", Usage);
+      exit(1);
+    }
+  }
+
+  if(optind>=argc) {
+    fprintf(stderr, "%s\n", Usage);
+    exit(-1);
+  }
+
+  init(&real_local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr, argv[optind]);
+
+  if (mapping) {
+	run_stunclient(&remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0);
+	if (addr_eq(&real_local_addr,&reflexive_addr)){
+		discoveryresult("No NAT! (Endpoint Independent Mapping)");
+	}
+	if(rfc5780) {
+		if(!addr_any(&other_addr)){
+			addr_cpy(&tmp_addr, &reflexive_addr);
+
+			addr_cpy(&remote_addr, &other_addr);
+			addr_set_port(&remote_addr, port);
+
+			run_stunclient(&remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0);
+
+			if(addr_eq(&tmp_addr,&reflexive_addr)){
+				discoveryresult("NAT with Enpoint Independent Mapping!"); 
+			} else {
+				addr_cpy(&tmp_addr, &reflexive_addr);
+				addr_cpy(&remote_addr, &other_addr);
+				run_stunclient(&remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0);
+				if(addr_eq(&tmp_addr,&reflexive_addr)){
+					discoveryresult("NAT with Address Dependent Mapping!"); 
+				} else {
+					discoveryresult("NAT with Address and Port Dependent Mapping!"); 
+				}
+			};
+
+		  }
+	  }
+  }
+  
+  init(&real_local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr, argv[optind]);
+
+  if (filtering) {
+  	run_stunclient(&remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0);
+	if (addr_eq(&real_local_addr,&reflexive_addr)){
+		discoveryresult("No NAT! (Endpoint Independent Mapping)");
+	}
+	if(rfc5780) {
+		if(!addr_any(&other_addr)){
+			int res=0;
+			res=run_stunclient(&remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,1,1,0);
+			if (!res) {
+				discoveryresult("NAT with Enpoint Independent Filtering!"); 
+			} else {
+				res=0;
+				res=run_stunclient(&remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,1,0);
+				if(!res){
+					discoveryresult("NAT with Address Dependent Filtering!"); 
+				} else {
+					discoveryresult("NAT with Address and Port Dependent Filtering!"); 
+				}
+			};
+
+		  }
+	  }
+  }
+  if (!filtering && !mapping) {
+  	printf("Please use either -f or -m parameter for Filtering or Mapping behavior discovery.\n");
+  }
+  socket_closesocket(udp_fd);
+
+  return 0;
+}

+ 482 - 0
src/apps/oauth/oauth.c

@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2011, 2012, 2013 Citrix Systems
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <stddef.h>
+
+#include "ns_turn_utils.h"
+#include "apputils.h"
+#include "stun_buffer.h"
+
+////////////////////////////////////////////////////
+
+#define OAUTH_TOKEN_SIZE 1000 //TODO: find insted of 1000 the real max of encoded token length 
+#define OAUTH_MAC_KEY_SIZE 32
+#define OAUTH_LTK_ID_SIZE 32
+#define OAUTH_LTK_SIZE 32
+#define OAUTH_LTK_BASE64ENCODED_SIZE 44
+#define OAUTH_TOKEN_LIFETIME 3600
+#define OAUTH_AS_RS_ALG_SIZE 7 
+#define OAUTH_SERVER_NAME_SIZE 255 
+#define OAUTH_GCM_NONCE_BASE64ENCODED_SIZE 16 
+#define OAUTH_HMAC_ALG_SIZE 20
+
+
+static int setup_ikm_key(const char *kid, 
+                        const char *ikm_key, 
+                        const turn_time_t key_timestamp, 
+                        const turn_time_t key_lifetime, 
+                        const char *as_rs_alg, 
+                        oauth_key *key) { 
+
+        ns_bzero(key,sizeof(*key));
+
+        oauth_key_data okd;
+        ns_bzero(&okd,sizeof(okd));
+
+        {
+                oauth_key_data_raw okdr;
+                ns_bzero(&okdr,sizeof(okdr));
+
+                STRCPY(okdr.kid,kid);
+                STRCPY(okdr.ikm_key,ikm_key);
+                STRCPY(okdr.as_rs_alg,as_rs_alg);
+                okdr.timestamp = key_timestamp;
+                okdr.lifetime = key_lifetime;
+
+                convert_oauth_key_data_raw(&okdr, &okd);
+        }        
+
+        char err_msg[1025] = "\0";
+        size_t err_msg_size = sizeof(err_msg) - 1;
+
+        if (convert_oauth_key_data(&okd, key, err_msg, err_msg_size) < 0) {
+                        fprintf(stderr, "%s\n", err_msg);
+                        return -1;
+        }         
+
+        return 0;
+}
+
+
+
+static int encode_token(const char* server_name,
+                        const char* gcm_nonce,
+                        const char* mac_key,
+                        const uint64_t token_timestamp,
+                        const uint32_t token_lifetime,
+                        const oauth_key key,
+                        char* base64encoded_etoken) {
+
+
+        oauth_token ot;
+        ns_bzero(&ot,sizeof(ot));
+
+        const size_t mac_key_length=strlen(mac_key);
+        ot.enc_block.key_length = (uint16_t)mac_key_length;
+        STRCPY(ot.enc_block.mac_key,mac_key);
+        ot.enc_block.timestamp = token_timestamp;
+        ot.enc_block.lifetime = token_lifetime;
+
+        encoded_oauth_token etoken;
+        ns_bzero(&etoken,sizeof(etoken));
+
+        // TODO: avoid this hack
+        if (!*gcm_nonce) gcm_nonce=NULL;
+
+        if (encode_oauth_token((const u08bits *) server_name, &etoken, &key, &ot,(const u08bits *) gcm_nonce) < 0) {
+                fprintf(stderr, "%s: cannot encode oauth token\n",
+                                __FUNCTION__);
+                return -1;
+        }
+
+        size_t base64encoded_etoken_length;
+        const char *tmp=base64_encode((unsigned char *)(etoken.token), etoken.size, &base64encoded_etoken_length);
+        STRCPY(base64encoded_etoken,tmp);
+
+        return 0;
+}
+
+static int validate_decode_token(const char* server_name, 
+                        const oauth_key key,
+                        const char* base64encoded_etoken, oauth_token* dot) {
+
+        
+        ns_bzero((dot),sizeof(*dot));
+
+        encoded_oauth_token etoken;
+        ns_bzero(&etoken,sizeof(etoken));
+
+        const size_t base64encoded_etoken_length=strlen(base64encoded_etoken);
+        const unsigned char *tmp = base64_decode(base64encoded_etoken,base64encoded_etoken_length,&etoken.size);
+        memcpy(etoken.token,tmp,etoken.size);
+                        
+        if (decode_oauth_token((const u08bits *) server_name, &etoken, &key, dot) < 0) {
+                fprintf(stderr, "%s: cannot decode oauth token\n",
+                                __FUNCTION__);
+                return -1;
+        } else {
+                return 0;
+        };
+}
+
+static void print_token_body(oauth_token* dot) {
+        printf("\n");
+        printf("Token non-encrpyted body:\n");
+        printf("{\n");
+        size_t base64encoded_nonce_length;
+        const char *base64encoded_nonce = base64_encode((unsigned char *)dot->enc_block.nonce, dot->enc_block.nonce_length,&base64encoded_nonce_length); 
+        printf("    nonce: %s\n", base64encoded_nonce);
+        printf("    nonce length: %d\n", (int) dot->enc_block.nonce_length);
+        printf("Token encrpyted body:\n");
+        printf("{\n");
+        printf("    mac key: %s\n", (char*) dot->enc_block.mac_key);
+        printf("    mac key length: %d\n", (int) dot->enc_block.key_length);
+        time_t time=dot->enc_block.timestamp>>16;
+        unsigned msec=(dot->enc_block.timestamp & 0xFFFF)*64;
+        printf("    timestamp:\n");
+        printf("        unixtime: %u (localtime: %s )", (unsigned int)time, ctime(&time));
+        printf("        msec:%u\n", msec);
+        printf("    lifetime: %lu\n", (unsigned long) dot->enc_block.lifetime);
+        printf("}\n");
+}
+
+//////////////// local definitions /////////////////
+
+const char Usage[] =
+  "Usage: oauth [ -e / -d ] [options]\n"
+  "Options:\n"
+  "\n"
+  "        -h, --help                       usage\n\n"
+  "        -v, --verbose                    verbose mode\n\n"
+  "        -e, --encrypt                    encrypt token\n"
+  "        -d, --decrypt                    decrypt validate token\n\n"
+  "        -i, --server-name                server name (max. 255 char)\n"
+  "        -j, --auth-key-id                Auth key id (max. 32 char)\n"
+  "        -k, --auth-key                   base64 encoded Auth key\n"
+  "        -l  --auth-key-timestamp         Auth key timestamp (sec since epoch)\n"
+  "        -m, --auth-key-lifetime          Auth key lifetime in sec\n"
+  "        -n, --auth-key-as-rs-alg         Authorization Server(AS) - Resource Server (RS) encryption algorithm\n"
+  "        -o, --token-nonce                base64 encoded nonce base64(12 octet) = 16 char\n"
+  "        -p, --token-mac-key              base64 encoded MAC key base64(32 octet) = 44 char\n"
+  "        -q, --token-timestamp            timestamp in format 64 bit unsigned (Native format - Unix),\n" 
+  "                                         so 48 bit for secs since epoch UTC + 16 bit for 1/64000 fractions of a second.\n" 
+  "                                         e.g.: the actual unixtimestamp 16 bit left shifted. (Default: actual gmtime)\n"
+  "        -r, --token-lifetime             lifetime in sec (Default: 3600)\n"
+  "        -t, --token                      base64 encoded encrypted token for validation and decryption\n"
+  "        -u, --hmac-alg                   stun client hmac algorithm\n";
+
+//////////////////////////////////////////////////
+
+
+int main(int argc, char **argv)
+{
+
+  oauth_key key;
+
+  //init vars with default values
+  char gcm_nonce[OAUTH_GCM_NONCE_SIZE+1]="";
+
+  char mac_key[OAUTH_MAC_KEY_SIZE+1]="";
+
+  time_t current_time = time(NULL);
+  struct tm* gmt = gmtime(&current_time);
+  uint64_t token_timestamp = (unsigned long long)mktime(gmt) << 16;
+  uint32_t token_lifetime = OAUTH_TOKEN_LIFETIME;
+ 
+  //oauth_key
+  char kid[OAUTH_LTK_ID_SIZE+1] = "";
+  char base64encoded_ltk[OAUTH_LTK_BASE64ENCODED_SIZE+1]="";
+  turn_time_t key_timestamp = 0;
+  turn_time_t key_lifetime = 0;
+  char as_rs_alg[OAUTH_AS_RS_ALG_SIZE+1]="A256GCM";
+  char server_name[OAUTH_SERVER_NAME_SIZE+1] = "";
+
+  char base64encoded_etoken[OAUTH_TOKEN_SIZE]=""; 
+
+  //TODO: replace SHA1 with an option. Actualy both big browser chrome and mozilla supports AFAIU implemented only SHA1.
+  char hmac_alg[OAUTH_HMAC_ALG_SIZE+1]="HMAC-SHA1";
+
+  static int verbose_flag=0;
+  static int encrypt_flag=0;
+  static int decrypt_flag=0;
+
+  static struct option long_options[] =
+   {
+     /* These options set a flag. */
+     {"verbose",                  no_argument,       &verbose_flag, 1},
+     {"encrypt",                  no_argument,       &encrypt_flag, 1},
+     {"decrypt",                  no_argument,       &decrypt_flag, 1},
+     {"help",                     no_argument,       0, 'h'},
+     {"server-name",              required_argument, 0, 'i'},
+     {"auth-key-id",         required_argument, 0, 'j'},
+     {"auth-key",            required_argument, 0, 'k'},
+     {"auth-key-timestamp",  required_argument, 0, 'l'},
+     {"auth-key-lifetime",   required_argument, 0, 'm'},
+     {"auth-key-as-rs-alg",  required_argument, 0, 'n'},
+     {"token-nonce",              required_argument, 0, 'o'},
+     {"token-mac-key",            required_argument, 0, 'p'},
+     {"token-timestamp",          required_argument, 0, 'q'},
+     {"token-lifetime",           required_argument, 0, 'r'},
+     {"token",                    required_argument, 0, 't'},
+     {"hmac-alg",                 required_argument, 0, 'u'},
+     {0, 0, 0, 0}
+   };
+  /* getopt_long stores the option index here. */
+  int option_index = 0;
+
+  //tmp vars
+  size_t nonce_size=0;
+  char *nonce_val;
+
+  size_t mac_key_size;
+  char *mac_key_val;
+
+
+  int i;
+  int c=0;
+
+  set_logfile("stdout");
+  set_system_parameters(0);
+
+  while ((c = getopt_long(argc, argv, "hvedi:j:k:l:m:n:o:p:q:r:t:u:",long_options, &option_index)) != -1) {
+    switch(c) {
+    case 'h':
+      fprintf(stderr, "%s\n", Usage);
+      exit(1); 
+      break;
+    case 'v':
+      verbose_flag=1;
+      break;
+    case 'e':
+      encrypt_flag=1;
+      break;
+    case 'd':
+      decrypt_flag=1;
+      break;
+    case 'i':
+      //server-name
+      if ( strlen(optarg) <= OAUTH_SERVER_NAME_SIZE ) {
+        STRCPY(server_name,optarg);
+      } else {
+        fprintf(stderr,"Server-name must not exceed %d!\n", OAUTH_LTK_ID_SIZE );
+        exit(1);
+      }
+      break;
+   case 'j':
+      //auth-key-id
+      if ( strlen(optarg) <= OAUTH_LTK_ID_SIZE ) {
+        STRCPY(kid,optarg);
+      } else {
+        fprintf(stderr,"Key ID must not exceed %d!\n", OAUTH_LTK_ID_SIZE );
+        exit(1);
+      }
+      break;
+    case 'k':
+      //auth-key
+      if ( strlen(optarg) <= OAUTH_LTK_BASE64ENCODED_SIZE ) {
+        STRCPY(base64encoded_ltk,optarg);
+      } else {
+        fprintf(stderr,"Key must not exceed %d!\n", OAUTH_LTK_BASE64ENCODED_SIZE );
+        exit(1);
+      }
+      break;
+    case 'l':
+      //auth-key-timestamp
+      key_timestamp = atoi(optarg);
+      break;
+    case 'm':
+      //auth-key-lifetime
+      key_lifetime=atoi(optarg);
+      break;
+    case 'n':
+      //auth-key-as-rs-alg
+      if ( strlen(optarg) <= OAUTH_AS_RS_ALG_SIZE ) {
+        STRCPY(as_rs_alg,optarg);
+      } else {
+        fprintf(stderr,"AS-RS Alg must not exceed %d!\n", OAUTH_AS_RS_ALG_SIZE );
+        exit(1);
+      }
+      break;
+    case 'o':
+      //token-nonce
+      nonce_val = (char*)base64_decode(optarg,strlen(optarg),&nonce_size);
+      if (nonce_size > OAUTH_GCM_NONCE_SIZE){
+        nonce_size=OAUTH_GCM_NONCE_SIZE;
+      } 
+      strncpy(gcm_nonce,nonce_val,nonce_size);
+      gcm_nonce[ nonce_size + 1 ]='\0';
+      break;
+    case 'p':
+      //token-mac-key
+      mac_key_val = (char*)base64_decode(optarg,strlen(optarg),&mac_key_size);
+      if (mac_key_size > OAUTH_MAC_KEY_SIZE){
+        mac_key_size=OAUTH_MAC_KEY_SIZE;
+      } 
+      strncpy(mac_key,mac_key_val,mac_key_size);
+      mac_key[mac_key_size+1]='\0';
+      break;
+    case 'q':
+      //token-timestamp
+      token_timestamp=strtoull(optarg,0,10);
+      break;
+    case 'r':
+      //token-lifetime
+      token_lifetime=atoi(optarg);
+      break;
+    case 't':
+      if ( strlen(optarg) <= OAUTH_TOKEN_SIZE ) {
+        STRCPY(base64encoded_etoken,optarg);
+      } else {
+        fprintf(stderr,"base64 encoded encrypted token must not exceed %d!\n", OAUTH_TOKEN_SIZE );
+        exit(1);
+      }
+      break;
+    case 'u':
+      //hmac-alg
+      if ( strlen(optarg) <= OAUTH_HMAC_ALG_SIZE ) {
+        STRCPY(hmac_alg,optarg);
+      } else {
+        fprintf(stderr,"STUN client HMAC Alg must not exceed %d!\n", OAUTH_HMAC_ALG_SIZE );
+        exit(1);
+      }
+      break;
+    default:
+      fprintf(stderr,"%s\n", Usage);
+      exit(1);
+      break;
+    }
+  }
+
+  for (i = optind; i < argc; i++)
+    printf ("Non-option argument %s\n", argv[i]);
+
+  if(optind>argc) {
+    fprintf(stderr, "%s\n", Usage);
+    exit(-1);
+  }
+
+  if (!(encrypt_flag || decrypt_flag)){
+        fprintf(stderr, "Use either encrypt or decrypt.\nPlease use -h or --help for the detailed help\n");
+         exit(-1);
+  }
+ 
+  //check if we have required params 
+  //TODO: more compact warnning handling
+  if (encrypt_flag || decrypt_flag){
+    if (strlen(server_name) == 0) { 
+        fprintf(stderr, "For encode/decode  --server-name/-i is mandatory \n");
+         exit(-1);
+    }
+    
+    if (strlen(kid) == 0){
+        fprintf(stderr, "For encode/decode  --auth-key-id/-j is mandatory \n");
+        exit(-1);
+    }
+     if (strlen(base64encoded_ltk) == 0){
+        fprintf(stderr, "For encode/decode  --auth-key/-k is mandatory \n");
+        exit(-1);
+    }
+    if (key_timestamp == 0){
+        fprintf(stderr, "For encode/decode  --auth-key-timestamp/-l is mandatory \n");
+        exit(-1);
+    }
+    if (key_lifetime == 0){
+        fprintf(stderr, "For encode/decode  --auth-key-lifetime/-m is mandatory \n");
+        exit(-1);
+    }
+
+    if (encrypt_flag && strlen(mac_key) == 0) { 
+        fprintf(stderr, "For encode --token-mac-key/-p is mandatory \n");
+        exit(-1);
+    }
+    
+    if (!encrypt_flag && decrypt_flag && strlen(base64encoded_etoken) == 0) { 
+        fprintf(stderr, "For decode --token/-t is mandatory \n");
+        exit(-1);
+    }
+    
+    // Expiry warnings
+    if ( (unsigned long long)key_timestamp<<16 > token_timestamp  +((unsigned long long)token_lifetime << 16)  ) {
+        fprintf(stderr,"\nWARNING: Token expiry is earlear then Auth key life time start timestamp!!\n\n");
+    } else {
+        if( (unsigned long long)key_timestamp<<16 > token_timestamp) {
+            fprintf(stderr,"\nWARNING: Token life time start timestamp is earlier then Auth key start timestamp!!\n\n");
+        }
+    }
+    if( (unsigned long long)( key_timestamp + key_lifetime )<<16 < token_timestamp ) {
+        fprintf(stderr,"\nWARNING: Auth key will expire before token lifetime start timestamp!!\n\n");
+    } else {
+        if( (unsigned long long)( key_timestamp + key_lifetime)<<16 < token_timestamp + ((unsigned long long)token_lifetime << 16) ) {
+            fprintf(stderr,"\nWARNING: Auth key will expire before token expiry!!\n\n");
+        }  
+    }
+
+    if ( setup_ikm_key(kid, base64encoded_ltk, key_timestamp, key_lifetime, as_rs_alg, &key) == 0 ) {
+          if(encrypt_flag) {
+          if (encode_token(server_name, gcm_nonce, mac_key, token_timestamp, token_lifetime, key, base64encoded_etoken) == 0 ) {
+            printf("{\n");
+            printf("    \"access_token\":\"%s\",\n",base64encoded_etoken);
+            printf("    \"token_type\":\"pop\",\n");
+            printf("    \"expires_in\":%d,\n",token_lifetime);
+            printf("    \"kid\":\"%s\",\n",kid);
+            printf("    \"key\":\"%s\",\n",mac_key);
+            printf("    \"alg\":\"%s\"\n",hmac_alg);
+            printf("}\n");
+          } else {
+            fprintf(stderr, "Error during token encode\n");
+            exit(-1);
+          }
+        }
+        if (decrypt_flag) {
+          oauth_token dot;
+          if ( validate_decode_token(server_name, key, base64encoded_etoken,&dot) == 0) {
+            printf("-=Valid token!=-\n");
+              if (verbose_flag) print_token_body(&dot);
+          } else {
+            fprintf(stderr, "Error during token validation and decoding\n");
+            exit(-1);
+          }
+        }
+     } else {
+        fprintf(stderr, "Error during key setup\n");
+         exit(-1);
+    }
+
+  }
+
+  return 0;
+}

+ 5 - 0
src/apps/relay/dbdrivers/dbd_mysql.c

@@ -46,6 +46,7 @@ struct _Myconninfo {
 	char *password;
 	unsigned int port;
 	unsigned int connect_timeout;
+	unsigned int read_timeout;
 	/* SSL ==>> */
 	char *key;
 	char *ca;
@@ -139,6 +140,8 @@ static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) {
 				co->connect_timeout = (unsigned int)atoi(seq+1);
 			else if(!strcmp(s,"timeout"))
 				co->connect_timeout = (unsigned int)atoi(seq+1);
+			else if(!strcmp(s,"read_timeout"))
+				co->read_timeout = (unsigned int)atoi(seq+1);
 			else if(!strcmp(s,"key"))
 				co->key = turn_strdup(seq+1);
 			else if(!strcmp(s,"ssl-key"))
@@ -226,6 +229,8 @@ static MYSQL *get_mydb_connection(void) {
 			} else {
 				if(co->connect_timeout)
 					mysql_options(mydbconnection,MYSQL_OPT_CONNECT_TIMEOUT,&(co->connect_timeout));
+				if(co->read_timeout)
+					mysql_options(mydbconnection,MYSQL_OPT_READ_TIMEOUT,&(co->read_timeout));
 				if(co->ca || co->capath || co->cert || co->cipher || co->key) {
 					mysql_ssl_set(mydbconnection, co->key, co->cert, co->ca, co->capath, co->cipher);
 				}

+ 1 - 4
src/apps/relay/dtls_listener.c

@@ -34,10 +34,7 @@
 #include "dtls_listener.h"
 #include "ns_ioalib_impl.h"
 
-#include <openssl/ssl.h>
-#include <openssl/bio.h>
-#include <openssl/err.h>
-#include <openssl/rand.h>
+#include "ns_turn_openssl.h"
 
 #include <pthread.h>
 

+ 54 - 5
src/apps/relay/mainrelay.c

@@ -30,6 +30,11 @@
 
 #include "mainrelay.h"
 
+#if (defined LIBRESSL_VERSION_NUMBER && OPENSSL_VERSION_NUMBER == 0x20000000L)
+#undef OPENSSL_VERSION_NUMBER
+#define OPENSSL_VERSION_NUMBER 0x1000107FL
+#endif
+
 ////// TEMPORARY data //////////
 
 static int use_lt_credentials = 0;
@@ -119,7 +124,24 @@ LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,0,"",
 /////////////// stop server ////////////////
 0,
 /////////////// MISC PARAMS ////////////////
-0,0,0,0,0,':',0,0,TURN_CREDENTIALS_NONE,0,0,0,0,0,0,
+0, /* stun_only */
+0, /* no_stun */
+0, /* secure_stun */
+0, /* server_relay */
+0, /* fingerprint */
+':', /* rest_api_separator */
+STUN_DEFAULT_NONCE_EXPIRATION_TIME, /* stale_nonce */
+STUN_DEFAULT_MAX_ALLOCATE_LIFETIME, /* max_allocate_lifetime */
+STUN_DEFAULT_CHANNEL_LIFETIME, /* channel_lifetime */
+STUN_DEFAULT_PERMISSION_LIFETIME, /* permission_lifetime */
+0, /* mobility */
+TURN_CREDENTIALS_NONE, /* ct */
+0, /* use_auth_secret_with_timestamp */
+0, /* max_bps */
+0, /* bps_capacity */
+0, /* bps_capacity_allocated */
+0, /* total_quota */
+0, /* user_quota */
 ///////////// Users DB //////////////
 { (TURN_USERDB_TYPE)0, {"\0"}, {0,NULL, {NULL,0}} },
 ///////////// CPUs //////////////////
@@ -457,7 +479,7 @@ static char Usage[] = "Usage: turnserver [options]\n"
 "	                                	This database can be used for long-term credentials mechanism users,\n"
 "		                                and it can store the secret value(s) for secret-based timed authentication in TURN RESP API.\n"
 "						The connection string my be space-separated list of parameters:\n"
-"	        	          		\"host=<ip-addr> dbname=<database-name> user=<database-user> \\\n								password=<database-user-password> port=<db-port> connect_timeout=<seconds>\".\n\n"
+"	        	          		\"host=<ip-addr> dbname=<database-name> user=<database-user> \\\n								password=<database-user-password> port=<db-port> connect_timeout=<seconds> read_timeout=<seconds>\".\n\n"
 "						The connection string parameters for the secure communications (SSL):\n"
 "						ca, capath, cert, key, cipher\n"
 "						(see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the\n"
@@ -542,7 +564,12 @@ static char Usage[] = "Usage: turnserver [options]\n"
 " --simple-log					This flag means that no log file rollover will be used, and the log file\n"
 "						name will be constructed as-is, without PID and date appendage.\n"
 "						This option can be used, for example, together with the logrotate tool.\n"
-" --stale-nonce					Use extra security with nonce value having limited lifetime (600 secs).\n"
+" --stale-nonce[=<value>]			Use extra security with nonce value having limited lifetime (default 600 secs).\n"
+" --max-allocate-lifetime	<value>		Set the maximum value for the allocation lifetime. Default to 3600 secs.\n"
+" --channel-lifetime		<value>		Set the lifetime for channel binding, default to 600 secs.\n"
+"						This value MUST not be changed for production purposes.\n"
+" --permission-lifetime		<value>		Set the value for the lifetime of the permission. Default to 300 secs.\n"
+"						This MUST not be changed for production purposes.\n"
 " -S, --stun-only				Option to set standalone STUN operation only, all TURN requests will be ignored.\n"
 "     --no-stun					Option to suppress STUN functionality, only TURN requests will be processed.\n"
 " --alternate-server		<ip:port>	Set the TURN server to redirect the allocate requests (UDP and TCP services).\n"
@@ -665,6 +692,9 @@ enum EXTRA_OPTS {
 	MIN_PORT_OPT,
 	MAX_PORT_OPT,
 	STALE_NONCE_OPT,
+	MAX_ALLOCATE_LIFETIME_OPT,
+	CHANNEL_LIFETIME_OPT,
+	PERMISSION_LIFETIME_OPT,
 	AUTH_SECRET_OPT,
 	DEL_ALL_AUTH_SECRETS_OPT,
 	STATIC_AUTH_SECRET_VAL_OPT,
@@ -782,6 +812,9 @@ static const struct myoption long_options[] = {
 				{ "no-udp-relay", optional_argument, NULL, NO_UDP_RELAY_OPT },
 				{ "no-tcp-relay", optional_argument, NULL, NO_TCP_RELAY_OPT },
 				{ "stale-nonce", optional_argument, NULL, STALE_NONCE_OPT },
+				{ "max-allocate-lifetime", optional_argument, NULL, MAX_ALLOCATE_LIFETIME_OPT },
+				{ "channel-lifetime", optional_argument, NULL, CHANNEL_LIFETIME_OPT },
+				{ "permission-lifetime", optional_argument, NULL, PERMISSION_LIFETIME_OPT },
 				{ "stun-only", optional_argument, NULL, 'S' },
 				{ "no-stun", optional_argument, NULL, NO_STUN_OPT },
 				{ "cert", required_argument, NULL, CERT_FILE_OPT },
@@ -873,6 +906,13 @@ static const struct myoption admin_long_options[] = {
 				{ NULL, no_argument, NULL, 0 }
 };
 
+static int get_int_value(const char* s, int default_value)
+{
+	if (!s || !(s[0]))
+		return default_value;
+	return atoi(s);
+}
+
 static int get_bool_value(const char* s)
 {
 	if(!s || !(s[0])) return 1;
@@ -1034,7 +1074,16 @@ static void set_option(int c, char *value)
 		turn_params.no_loopback_peers = get_bool_value(value);
 		break;
 	case STALE_NONCE_OPT:
-		turn_params.stale_nonce = get_bool_value(value);
+		turn_params.stale_nonce = get_int_value(value, STUN_DEFAULT_NONCE_EXPIRATION_TIME);
+		break;
+	case MAX_ALLOCATE_LIFETIME_OPT:
+		turn_params.max_allocate_lifetime = get_int_value(value, STUN_DEFAULT_MAX_ALLOCATE_LIFETIME);
+		break;
+	case CHANNEL_LIFETIME_OPT:
+		turn_params.channel_lifetime = get_int_value(value, STUN_DEFAULT_CHANNEL_LIFETIME);
+		break;
+	case PERMISSION_LIFETIME_OPT:
+		turn_params.permission_lifetime = get_int_value(value, STUN_DEFAULT_PERMISSION_LIFETIME);
 		break;
 	case MAX_ALLOCATE_TIMEOUT_OPT:
 		TURN_MAX_ALLOCATE_TIMEOUT = atoi(value);
@@ -1662,7 +1711,7 @@ static void print_features(unsigned long mfn)
 #endif
 	}
 
-	TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL compile-time version: %s\n",OPENSSL_VERSION_TEXT);
+	TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL compile-time version: %s (0x%lx)\n",OPENSSL_VERSION_TEXT,OPENSSL_VERSION_NUMBER);
 
 	TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\n");
 

+ 4 - 8
src/apps/relay/mainrelay.h

@@ -59,14 +59,7 @@
 #include <event2/bufferevent.h>
 #include <event2/buffer.h>
 
-#include <openssl/ssl.h>
-#include <openssl/bio.h>
-#include <openssl/err.h>
-#include <openssl/rand.h>
-#include <openssl/crypto.h>
-#include <openssl/opensslv.h>
-#include <openssl/dh.h>
-#include <openssl/bn.h>
+#include "ns_turn_openssl.h"
 
 #include "ns_turn_utils.h"
 #include "ns_turn_khash.h"
@@ -292,6 +285,9 @@ typedef struct _turn_params_ {
   int fingerprint;
   char rest_api_separator;
   vint stale_nonce;
+  vint max_allocate_lifetime;
+  vint channel_lifetime;
+  vint permission_lifetime;
   vint mobility;
   turn_credential_type ct;
   int use_auth_secret_with_timestamp;

+ 3 - 0
src/apps/relay/netengine.c

@@ -1633,6 +1633,9 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int
 			 &turn_params.no_tcp_relay,
 			 &turn_params.no_udp_relay,
 			 &turn_params.stale_nonce,
+			 &turn_params.max_allocate_lifetime,
+			 &turn_params.channel_lifetime,
+			 &turn_params.permission_lifetime,
 			 &turn_params.stun_only,
 			 &turn_params.no_stun,
 			 &turn_params.alternate_servers_list,

+ 1 - 1
src/apps/relay/ns_ioalib_engine_impl.c

@@ -44,7 +44,7 @@
 
 #include <event2/listener.h>
 
-#include <openssl/err.h>
+#include "ns_turn_openssl.h"
 
 #if !defined(TURN_NO_HIREDIS)
 #include "hiredis_libevent2.h"

+ 1 - 1
src/apps/relay/ns_ioalib_impl.h

@@ -41,7 +41,7 @@
 
 #include <event2/thread.h>
 
-#include <openssl/ssl.h>
+#include "ns_turn_openssl.h"
 
 #include "ns_turn_ioalib.h"
 #include "turn_ports.h"

+ 2 - 2
src/apps/stunclient/stunclient.c

@@ -234,7 +234,7 @@ static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, i
 					printf("The response is an error %d (%s)\n", err_code, reason.c_str());
 				}
 			} else {
-				printf("The response is not a reponse message\n");
+				printf("The response is not a response message\n");
 			}
 		} catch(...) {
 			printf("The response is not a well formed STUN message\n");
@@ -386,7 +386,7 @@ static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, i
 					}
 				}
 			} else {
-				printf("The response is not a reponse message\n");
+				printf("The response is not a response message\n");
 			}
 		} else {
 			printf("The response is not a STUN message\n");

+ 1 - 3
src/apps/uclient/mainuclient.c

@@ -44,9 +44,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#include <openssl/ssl.h>
-#include <openssl/opensslv.h>
-#include <openssl/rand.h>
+#include "ns_turn_openssl.h"
 
 /////////////// extern definitions /////////////////////
 

+ 1 - 1
src/apps/uclient/session.h

@@ -40,7 +40,7 @@
 #include "stun_buffer.h"
 #include "apputils.h"
 
-#include <openssl/ssl.h>
+#include "ns_turn_openssl.h"
 
 #ifdef __cplusplus
 extern "C" {

+ 1 - 1
src/apps/uclient/startuclient.c

@@ -37,7 +37,7 @@
 #include "uclient.h"
 #include "session.h"
 
-#include <openssl/err.h>
+#include "ns_turn_openssl.h"
 
 /////////////////////////////////////////
 

+ 1 - 2
src/apps/uclient/uclient.c

@@ -37,8 +37,7 @@
 #include <unistd.h>
 #include <time.h>
 
-#include <openssl/err.h>
-#include <openssl/rand.h>
+#include "ns_turn_openssl.h"
 
 #include <sys/select.h>
 

+ 1 - 3
src/apps/uclient/uclient.h

@@ -35,9 +35,7 @@
 #include "stun_buffer.h"
 #include "session.h"
 
-#include <openssl/ssl.h>
-#include <openssl/dh.h>
-#include <openssl/bn.h>
+#include "ns_turn_openssl.h"
 
 #ifdef __cplusplus
 extern "C" {

+ 1 - 1
src/client++/TurnMsgLib.h

@@ -1021,7 +1021,7 @@ public:
 		stun_set_allocate_response_str(_buffer, &_sz, &tid,
 						   &relayed_addr1, &relayed_addr2,
 						   &reflexive_addr,
-						   lifetime, error_code, reason,
+						   lifetime, STUN_DEFAULT_MAX_ALLOCATE_LIFETIME, error_code, reason,
 						   reservation_token, mobile_id);
 	}
 

+ 11 - 11
src/client/ns_turn_msg.c

@@ -33,11 +33,7 @@
 
 ///////////// Security functions implementation from ns_turn_msg.h ///////////
 
-#include <openssl/md5.h>
-#include <openssl/hmac.h>
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include <openssl/rand.h>
+#include "ns_turn_openssl.h"
 
 ///////////
 
@@ -176,15 +172,16 @@ int stun_produce_integrity_key_str(u08bits *uname, u08bits *realm, u08bits *upwd
 	str[strl]=0;
 
 	if(shatype == SHATYPE_SHA256) {
-		unsigned int keylen = 0;
 #if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH)
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
+		unsigned int keylen = 0;
 		EVP_MD_CTX ctx;
 		EVP_DigestInit(&ctx,EVP_sha256());
 		EVP_DigestUpdate(&ctx,str,strl);
 		EVP_DigestFinal(&ctx,key,&keylen);
 		EVP_MD_CTX_cleanup(&ctx);
 #else
+		unsigned int keylen = 0;
 		EVP_MD_CTX *ctx = EVP_MD_CTX_new();
 		EVP_DigestInit(ctx,EVP_sha256());
 		EVP_DigestUpdate(ctx,str,strl);
@@ -1024,7 +1021,7 @@ int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, i
 int stun_set_allocate_response_str(u08bits* buf, size_t *len, stun_tid* tid, 
 				   const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2,
 				   const ioa_addr *reflexive_addr,
-				   u32bits lifetime, int error_code, const u08bits *reason,
+				   u32bits lifetime, u32bits max_lifetime, int error_code, const u08bits *reason,
 				   u64bits reservation_token, char* mobile_id) {
 
   if(!error_code) {
@@ -1050,7 +1047,7 @@ int stun_set_allocate_response_str(u08bits* buf, size_t *len, stun_tid* tid,
 
     {
       if(lifetime<1) lifetime=STUN_DEFAULT_ALLOCATE_LIFETIME;
-      else if(lifetime>STUN_MAX_ALLOCATE_LIFETIME) lifetime = STUN_MAX_ALLOCATE_LIFETIME;
+      else if(lifetime>max_lifetime) lifetime = max_lifetime;
 
       u32bits field=nswap32(lifetime);
       if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_LIFETIME,(u08bits*)(&field),sizeof(field))<0) return -1;
@@ -1218,11 +1215,11 @@ void stun_tid_generate_in_message_str(u08bits* buf, stun_tid* id) {
 
 /////////////////// TIME ////////////////////////////////////////////////////////
 
-turn_time_t stun_adjust_allocate_lifetime(turn_time_t lifetime, turn_time_t max_lifetime) {
+turn_time_t stun_adjust_allocate_lifetime(turn_time_t lifetime, turn_time_t max_allowed_lifetime, turn_time_t max_lifetime) {
 
   if(!lifetime) lifetime = STUN_DEFAULT_ALLOCATE_LIFETIME;
   else if(lifetime<STUN_MIN_ALLOCATE_LIFETIME) lifetime = STUN_MIN_ALLOCATE_LIFETIME;
-  else if(lifetime>STUN_MAX_ALLOCATE_LIFETIME) lifetime = STUN_MAX_ALLOCATE_LIFETIME;
+  else if(lifetime>max_allowed_lifetime) lifetime = max_allowed_lifetime;
 
   if(max_lifetime && (max_lifetime < lifetime)) {
   	lifetime = max_lifetime;
@@ -1442,7 +1439,8 @@ int stun_attr_get_addr_str(const u08bits *buf, size_t len, stun_attr_ref attr, i
   stun_tid_from_message_str(buf, len, &tid);
   ioa_addr public_addr;
 
-  ns_bzero(ca,sizeof(ioa_addr));
+  addr_set_any(ca);
+  addr_set_any(&public_addr);
 
   int attr_type = stun_attr_get_type(attr);
   if(attr_type<0) return -1;
@@ -2514,6 +2512,7 @@ static int decode_oauth_token_gcm(const u08bits *server_name, const encoded_oaut
 		const unsigned char *csnl = snl;
 
 		uint16_t nonce_len = nswap16(*((const uint16_t*)csnl));
+                dtoken->enc_block.nonce_length = nonce_len;
 
 		size_t min_encoded_field_size = 2+4+8+nonce_len+2+OAUTH_GCM_TAG_SIZE+1;
 		if(etoken->size < min_encoded_field_size) {
@@ -2524,6 +2523,7 @@ static int decode_oauth_token_gcm(const u08bits *server_name, const encoded_oaut
 		const unsigned char* encoded_field = (const unsigned char*)(etoken->token + nonce_len + 2);
 		unsigned int encoded_field_size = (unsigned int)etoken->size - nonce_len - 2 - OAUTH_GCM_TAG_SIZE;
 		const unsigned char* nonce = ((const unsigned char*)etoken->token + 2);
+                ns_bcopy(nonce,dtoken->enc_block.nonce,nonce_len);
 
 		unsigned char tag[OAUTH_GCM_TAG_SIZE];
 		ns_bcopy(((const unsigned char*)etoken->token) + nonce_len + 2 + encoded_field_size, tag ,sizeof(tag));

+ 2 - 2
src/client/ns_turn_msg.h

@@ -86,7 +86,7 @@ u16bits stun_make_error_response(u16bits method);
 
 ///////////////////////////////////////////////////////////////
 
-turn_time_t stun_adjust_allocate_lifetime(turn_time_t lifetime, turn_time_t max_lifetime);
+turn_time_t stun_adjust_allocate_lifetime(turn_time_t lifetime, turn_time_t max_allowed_lifetime, turn_time_t max_lifetime);
 
 ///////////// STR ////////////////////////////////////////////////
 
@@ -162,7 +162,7 @@ int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, i
 int stun_set_allocate_response_str(u08bits* buf, size_t *len, stun_tid* tid, 
 				   const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2,
 				   const ioa_addr *reflexive_addr,
-				   u32bits lifetime, int error_code, const u08bits *reason,
+				   u32bits lifetime, u32bits max_lifetime, int error_code, const u08bits *reason,
 				   u64bits reservation_token, char *mobile_id);
 
 u16bits stun_set_channel_bind_request_str(u08bits* buf, size_t *len,

+ 4 - 4
src/client/ns_turn_msg_defs.h

@@ -62,10 +62,10 @@
 /* Lifetimes: */
 #define STUN_DEFAULT_ALLOCATE_LIFETIME (600)
 #define STUN_MIN_ALLOCATE_LIFETIME STUN_DEFAULT_ALLOCATE_LIFETIME
-#define STUN_MAX_ALLOCATE_LIFETIME (3600)
-#define STUN_CHANNEL_LIFETIME (600)
-#define STUN_PERMISSION_LIFETIME (300)
-#define STUN_NONCE_EXPIRATION_TIME (600)
+#define STUN_DEFAULT_MAX_ALLOCATE_LIFETIME (3600)
+#define STUN_DEFAULT_CHANNEL_LIFETIME (600)
+#define STUN_DEFAULT_NONCE_EXPIRATION_TIME (600)
+#define STUN_DEFAULT_PERMISSION_LIFETIME (300)
 /**/
 
 #define STUN_METHOD_BINDING (0x0001)

+ 1 - 1
src/ns_turn_defs.h

@@ -31,7 +31,7 @@
 #ifndef __IOADEFS__
 #define __IOADEFS__
 
-#define TURN_SERVER_VERSION "4.5.0.4"
+#define TURN_SERVER_VERSION "4.5.0.5"
 #define TURN_SERVER_VERSION_NAME "dan Eider"
 #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'"
 

+ 20 - 14
src/server/ns_turn_server.c

@@ -848,7 +848,7 @@ static int update_turn_permission_lifetime(ts_ur_super_session *ss, turn_permiss
 
 		if (server) {
 
-			if(!time_delta) time_delta = STUN_PERMISSION_LIFETIME;
+			if(!time_delta) time_delta = *(server->permission_lifetime);
 			tinfo->expiration_time = server->ctime + time_delta;
 
 			IOA_EVENT_DEL(tinfo->lifetime_ev);
@@ -883,13 +883,13 @@ static int update_channel_lifetime(ts_ur_super_session *ss, ch_info* chn)
 
 			if (server) {
 
-				if (update_turn_permission_lifetime(ss, tinfo, STUN_CHANNEL_LIFETIME) < 0)
+				if (update_turn_permission_lifetime(ss, tinfo, *(server->channel_lifetime)) < 0)
 					return -1;
 
-				chn->expiration_time = server->ctime + STUN_CHANNEL_LIFETIME;
+				chn->expiration_time = server->ctime + *(server->channel_lifetime);
 
 				IOA_EVENT_DEL(chn->lifetime_ev);
-				chn->lifetime_ev = set_ioa_timer(server->e, STUN_CHANNEL_LIFETIME, 0,
+				chn->lifetime_ev = set_ioa_timer(server->e, *(server->channel_lifetime), 0,
 								client_ss_channel_timeout_handler,
 								chn, 0,
 								"client_ss_channel_timeout_handler");
@@ -977,7 +977,7 @@ static int handle_turn_allocate(turn_turnserver *server,
 							tid,
 							pxor_relayed_addr1, pxor_relayed_addr2,
 							get_remote_addr_from_ioa_socket(ss->client_socket),
-							lifetime, 0, NULL, 0,
+							lifetime,*(server->max_allocate_lifetime), 0, NULL, 0,
 							ss->s_mobile_id);
 				ioa_network_buffer_set_size(nbh,len);
 				*resp_constructed = 1;
@@ -1205,7 +1205,7 @@ static int handle_turn_allocate(turn_turnserver *server,
 				}
 			}
 
-			lifetime = stun_adjust_allocate_lifetime(lifetime, ss->max_session_time_auth);
+			lifetime = stun_adjust_allocate_lifetime(lifetime, *(server->max_allocate_lifetime), ss->max_session_time_auth);
 			u64bits out_reservation_token = 0;
 
 			if(inc_quota(ss, username)<0) {
@@ -1373,7 +1373,7 @@ static int handle_turn_allocate(turn_turnserver *server,
 						stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid,
 									pxor_relayed_addr1, pxor_relayed_addr2,
 									get_remote_addr_from_ioa_socket(ss->client_socket), lifetime,
-									0,NULL,
+									*(server->max_allocate_lifetime),0,NULL,
 									out_reservation_token,
 									ss->s_mobile_id);
 
@@ -1398,7 +1398,7 @@ static int handle_turn_allocate(turn_turnserver *server,
 		}
 
 		size_t len = ioa_network_buffer_get_size(nbh);
-		stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid, NULL, NULL, NULL, 0, *err_code, *reason, 0, ss->s_mobile_id);
+		stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid, NULL, NULL, NULL, 0, *(server->max_allocate_lifetime), *err_code, *reason, 0, ss->s_mobile_id);
 		ioa_network_buffer_set_size(nbh,len);
 		*resp_constructed = 1;
 	}
@@ -1644,7 +1644,7 @@ static int handle_turn_refresh(turn_turnserver *server,
 							if (to_delete)
 								lifetime = 0;
 							else {
-								lifetime = stun_adjust_allocate_lifetime(lifetime, ss->max_session_time_auth);
+								lifetime = stun_adjust_allocate_lifetime(lifetime, *(server->max_allocate_lifetime), ss->max_session_time_auth);
 							}
 
 							if (af4c && refresh_relay_connection(server, orig_ss, lifetime, 0, 0, 0,
@@ -1757,7 +1757,7 @@ static int handle_turn_refresh(turn_turnserver *server,
 			if (to_delete)
 				lifetime = 0;
 			else {
-				lifetime = stun_adjust_allocate_lifetime(lifetime, ss->max_session_time_auth);
+				lifetime = stun_adjust_allocate_lifetime(lifetime, *(server->max_allocate_lifetime), ss->max_session_time_auth);
 			}
 
 			if(!af4 && !af6) {
@@ -2610,7 +2610,7 @@ static int handle_turn_channel_bind(turn_turnserver *server,
 					} else {
 						if (!addr_eq_no_port(&peer_addr, &(tinfo->addr))) {
 							*err_code = 500;
-							*reason = (const u08bits *)"Wrong permission info and peer addr conbination";
+							*reason = (const u08bits *)"Wrong permission info and peer addr combination";
 						} else if (chn->port != addr_get_port(&peer_addr)) {
 							*err_code = 500;
 							*reason = (const u08bits *)"Wrong port number";
@@ -3271,7 +3271,7 @@ static int check_stun_auth(turn_turnserver *server,
 					snprintf((s08bits*)s, NONCE_MAX_SIZE-4*i, "%04x",(unsigned int)rand);
 				}
 			}
-			ss->nonce_expiration_time = server->ctime + STUN_NONCE_EXPIRATION_TIME;
+			ss->nonce_expiration_time = server->ctime + *(server->stale_nonce);
 		}
 	}
 
@@ -4350,8 +4350,8 @@ static int create_relay_connection(turn_turnserver* server,
 
 		if (lifetime<1)
 			lifetime = STUN_DEFAULT_ALLOCATE_LIFETIME;
-		else if(lifetime>STUN_MAX_ALLOCATE_LIFETIME)
-			lifetime = STUN_MAX_ALLOCATE_LIFETIME;
+		else if(lifetime>(u32bits)*(server->max_allocate_lifetime))
+			lifetime = (u32bits)*(server->max_allocate_lifetime);
 
 		ioa_timer_handle ev = set_ioa_timer(server->e, lifetime, 0,
 				client_ss_allocation_timeout_handler, newelem, 0,
@@ -4796,6 +4796,9 @@ void init_turn_server(turn_turnserver* server,
 		vintp no_tcp_relay,
 		vintp no_udp_relay,
 		vintp stale_nonce,
+		vintp max_allocate_lifetime,
+		vintp channel_lifetime,
+		vintp permission_lifetime,
 		vintp stun_only,
 		vintp no_stun,
 		turn_server_addrs_list_t *alternate_servers_list,
@@ -4851,6 +4854,9 @@ void init_turn_server(turn_turnserver* server,
 	server->self_udp_balance = self_udp_balance;
 
 	server->stale_nonce = stale_nonce;
+	server->max_allocate_lifetime = max_allocate_lifetime;
+	server->channel_lifetime = channel_lifetime;
+	server->permission_lifetime = permission_lifetime;
 	server->stun_only = stun_only;
 	server->no_stun = no_stun;
 

+ 6 - 0
src/server/ns_turn_server.h

@@ -115,6 +115,9 @@ struct _turn_turnserver {
 	int rfc5780;
 	vintp check_origin;
 	vintp stale_nonce;
+        vintp max_allocate_lifetime;
+        vintp channel_lifetime;
+        vintp permission_lifetime;
 	vintp stun_only;
 	vintp no_stun;
 	vintp secure_stun;
@@ -184,6 +187,9 @@ void init_turn_server(turn_turnserver* server,
 				    vintp no_tcp_relay,
 				    vintp no_udp_relay,
 				    vintp stale_nonce,
+                                    vintp max_allocate_lifetime,
+                                    vintp channel_lifetime,
+                                    vintp permission_lifetime,
 				    vintp stun_only,
 				    vintp no_stun,
 				    turn_server_addrs_list_t *alternate_servers_list,