Browse Source

Merge branch 'master' into PR288

Mészáros Mihály 4 years ago
parent
commit
05ecf28a95

+ 38 - 3
.travis.yml

@@ -66,11 +66,46 @@ matrix:
         - libhiredis-dev
   - os: osx
     osx_image: xcode11.3
-  - os: osx
-    osx_image: xcode11.6
+ # - os: osx
+ #   osx_image: xcode11.6
   - os: osx
     osx_image: xcode12
-
+  - os: linux
+    arch: ppc64le
+    dist: xenial
+    sudo: required
+    addons:
+      apt:
+        packages:
+        - mysql-client
+        - debhelper
+        - dpkg-dev
+        - libssl-dev
+        - libevent-dev
+        - sqlite3
+        - libsqlite3-dev
+        - postgresql-client
+        - libpq-dev
+        - libmysqlclient-dev
+        - libhiredis-dev
+  - os: linux
+    arch: ppc64le
+    dist: bionic
+    sudo: required
+    addons:
+      apt:
+        packages:
+        - mysql-client
+        - debhelper
+        - dpkg-dev
+        - libssl-dev
+        - libevent-dev
+        - sqlite3
+        - libsqlite3-dev
+        - postgresql-client
+        - libpq-dev
+        - libmysqlclient-dev
+        - libhiredis-dev
 
 notifications:
   slack:

+ 30 - 1
ChangeLog

@@ -1,8 +1,37 @@
 24/06/2020 Oleg Moskalenko <[email protected]> Mihály Mészáros <[email protected]>
 Version 4.5.2 'dan Eider':
 	- fix null pointer dereference in case of out of memory. (thanks to Thomas Moeller for the report)
-    - merge PR #517 (by wolmi)
+	- merge PR #517 (by wolmi)
 		* add prometheus metrics
+	- merge PR #637 (by David Florness)
+	    * Delete trailing whitespace in example configuration files
+	- merge PR #631 (by Debabrata Deka)
+	    * Add architecture ppc64le to travis build
+	- merge PR #627 (by Samuel)
+		* Fix misleading option in doc (prometheus)
+	- merge PR #643 (by tupelo-schneck)
+		* Allow RFC6062 TCP relay data to look like TLS
+	- merge PR #655 (by plinss)
+		* Add support for proxy protocol V1 
+	- merge PR #618 (by Paul Wayper)
+		* Print full date and time in logs
+		* Add new options: "new-log-timestamp" and "new-log-timestamp-format"
+	- merge PR #599 (by Cédric Krier)
+		* Do not use FIPS and remove hardcode OPENSSL_VERSION_NUMBER with LibreSSL
+	- update Docker mongoDB and fix with workaround the missing systemctl
+	- merge PR #660 (by Camden Narzt)
+		* fix compilation on macOS Big Sur
+	- merge PR #546 (by jelmd)
+		* Add ACME redirect url
+	- merge PR #551 (by jelmd)
+		* support of --acme-redirect <URL>
+	- merge PR #672 further acme fixes (by jemld)
+		* fix acme security, redundancy, consistency
+	- Disable binding request logging to avoid DoS attacks. (Breaking change!)
+		* Add new --log-binding option to enable binding request logging
+	- Fix stale-nonce documentation. Resolves #604
+	- Version number is changed to semver 2.0
+
 24/06/2020 Oleg Moskalenko <[email protected]> Mihály Mészáros <[email protected]>
 Version 4.5.1.3 'dan Eider':
 	- merge PR #575: (by osterik)

+ 1 - 1
Makefile.in

@@ -21,7 +21,7 @@ COMMON_MODS = src/apps/common/apputils.c src/apps/common/ns_turn_utils.c src/app
 COMMON_DEPS = ${LIBCLIENTTURN_DEPS} ${COMMON_MODS} ${COMMON_HEADERS}
 
 IMPL_HEADERS = src/apps/relay/ns_ioalib_impl.h src/apps/relay/ns_sm.h src/apps/relay/turn_ports.h
-IMPL_MODS = src/apps/relay/ns_ioalib_engine_impl.c src/apps/relay/turn_ports.c src/apps/relay/http_server.c
+IMPL_MODS = src/apps/relay/ns_ioalib_engine_impl.c src/apps/relay/turn_ports.c src/apps/relay/http_server.c src/apps/relay/acme.c
 IMPL_DEPS = ${COMMON_DEPS} ${IMPL_HEADERS} ${IMPL_MODS}
 
 HIREDIS_HEADERS = src/apps/common/hiredis_libevent2.h

+ 2 - 1
README.md

@@ -121,7 +121,8 @@ Contact information:
 
 https://groups.google.com/forum/#!forum/turn-server-project-rfc5766-turn-server
 
-email:[email protected]
+email:[email protected]
+      [email protected]
 
 ### Feedback is very welcome (bugs, issues, suggestions, stories, questions). ###
 

+ 5 - 1
README.turnadmin

@@ -271,4 +271,8 @@ to see the man page.
 
 	Bradley T. Hughes <[email protected]>
 
-        Mihaly Meszaros <[email protected]>
+	Mihály Mészáros <[email protected]>
+
+  ACTIVE MAINTAINERS
+
+	Mihály Mészáros <[email protected]>

+ 20 - 3
README.turnserver

@@ -225,6 +225,12 @@ Flags:
 			name will be constructed as-is, without PID and date appendage.
 			This option can be used, for example, together with the logrotate tool.
 
+--new-log-timestamp				Enable full ISO-8601 timestamp in all logs.
+
+--new-log-timestamp-format    	<format>	Set timestamp format (in strftime(1) format)
+
+--log-binding					Log STUN binding request. It is now disabled by default to avoid DoS attacks.
+
 --secure-stun		Require authentication of the STUN Binding request.
 			By default, the clients are allowed anonymous access to the STUN Binding functionality.
 
@@ -265,8 +271,8 @@ Flags:
 			check: across the session, all requests must have the same
 			main ORIGIN attribute value (if the ORIGIN was
 			initially used by the session).
- --no-prometheus	Disable prometheus metrics. By default it is
-			enabled and listening on port 9641 unther the path /metrics
+ --prometheus		Enable prometheus metrics. By default it is
+			disabled. Would listen on port 9641 unther the path /metrics
 			also the path / on this port can be used as a health check
 
 -h			Help.
@@ -275,6 +281,7 @@ Options with values:
 
 --stale-nonce[=<value>]		Use extra security with nonce value having
 							limited lifetime, in seconds (default 600 secs).
+							Set it to 0 for unlimited nonce lifetime.
 
 --max-allocate-lifetime		Set the maximum value for the allocation lifetime.
 							Default to 3600 secs.
@@ -543,6 +550,12 @@ Options with values:
 			Default is /var/run/turnserver.pid (if superuser account is used) or
 			/var/tmp/turnserver.pid .
 
+--acme-redirect  <URL>	Redirect ACME/RFC8555 (like Let's Encrypt challenge) requests, i.e.
+			HTTP GET requests matching '^/.well-known/acme-challenge/(.*)'
+			to <URL>$1 with $1 == (.*). No validation of <URL> will be done,
+			so make sure you do not forget the trailing slash. If <URL> is an empty
+			string (the default value), no special handling of such requests will be done.
+
 --proc-user		User name to run the process. After the initialization, the turnserver process
 			will make an attempt to change the current user ID to that user.
 
@@ -997,4 +1010,8 @@ https://groups.google.com/forum/?fromgroups=#!forum/turn-server-project-rfc5766-
 
 	Bradley T. Hughes <[email protected]>
 
-        Mihaly Meszaros <[email protected]>
+    Mihály Mészáros <[email protected]>
+
+  ACTIVE MAINTAINERS
+
+	Mihály Mészáros <[email protected]>

+ 5 - 1
README.turnutils

@@ -474,4 +474,8 @@ SEE ALSO
 
 	Bradley T. Hughes <[email protected]>
 
-        Mihaly Meszaros <[email protected]>
+	Mihály Mészáros <[email protected]>
+
+  ACTIVE MAINTAINERS
+
+	Mihály Mészáros <[email protected]>

+ 11 - 0
configure

@@ -423,6 +423,17 @@ if [ "${SYSTEM}" = "NetBSD" ] ; then
 	fi
 fi
 
+# If acme_redirect does not work, send_data_from_ioa_socket_nbh() probably
+# does not work. Set LIBEV_OK=1 to use a workaround for it.
+if [ -z "${LIBEV_OK}" ]; then
+	LIBEV_OK=1
+	if [ "${SYSTEM}" = "Linux" ]; then
+		OS=$( lsb_release -si 2>/dev/null )
+		[ "${OS}" = "Ubuntu" ] && LIBEV_OK=0
+	fi
+fi
+[ "${LIBEV_OK}" = "1" ] && OSCFLAGS="${OSCFLAGS} -DLIBEV_OK"
+
 ###########################
 # Install shell commands
 ###########################

+ 7 - 4
docker/coturn/Dockerfile

@@ -13,7 +13,7 @@ WORKDIR ${BUILD_PREFIX}
 RUN git clone https://github.com/coturn/coturn.git
 
 # Build Coturn
-WORKDIR coturn
+WORKDIR ${BUILD_PREFIX}/coturn
 RUN ./configure
 RUN make
 
@@ -34,14 +34,17 @@ COPY --from=coturn-build ${BUILD_PREFIX}/coturn/turndb ${INSTALL_PREFIX}/turndb
 # Install lib dependencies
 RUN export DEBIAN_FRONTEND=noninteractive && \
 	apt-get update && \
-	apt-get install -y libc6>=2.15 libevent-core-2.1-6>=libevent-core-2.1-6 libevent-extra-2.1-6>=2.1.8-stable-4 libevent-openssl-2.1-6>=2.1.8-stable-4 libevent-pthreads-2.1-6>=2.1.8-stable-4 libhiredis0.14>=0.14.0 libmariadbclient-dev>=10.3.17 libpq5>=8.4~ libsqlite3-0>=3.6.0 libssl1.1>=1.1.0 libmongoc-1.0 libbson-1.0
+	apt-get install -y libc6 libevent-core-2.1-6 libevent-extra-2.1-6 libevent-openssl-2.1-6 libevent-pthreads-2.1-6 libhiredis0.14 libmariadbclient-dev libpq5 libsqlite3-0 libssl1.1 libmongoc-1.0-0 libbson-1.0-0
 RUN apt-get install -y default-mysql-client postgresql-client redis-tools
 
+# Workaround for MongoDB
+RUN ln -s /bin/echo /bin/systemctl
+
 # Install MongoDB
 RUN apt-get update && \
   apt-get install -y wget gnupg && \
-  wget -qO - https://www.mongodb.org/static/pgp/server-4.0.asc | apt-key add - && \
-  echo "deb http://repo.mongodb.org/apt/debian stretch/mongodb-org/4.0 main" | tee /etc/apt/sources.list.d/mongodb-org-4.0.list && \
+  wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | apt-key add - && \
+  echo "deb http://repo.mongodb.org/apt/debian stretch/mongodb-org/4.4 main" | tee /etc/apt/sources.list.d/mongodb-org-4.4.list && \
   echo "deb http://deb.debian.org/debian/ stretch main" | tee /etc/apt/sources.list.d/debian-stretch.list && \
   apt-get update && \
   apt-get install -y libcurl3 mongodb-org mongodb-org-server mongodb-org

+ 95 - 95
docker/coturn/turnserver.conf

@@ -1,45 +1,45 @@
 # Coturn TURN SERVER configuration file
 #
 # Boolean values note: where a boolean value is supposed to be used,
-# you can use '0', 'off', 'no', 'false', or 'f' as 'false, 
-# and you can use '1', 'on', 'yes', 'true', or 't' as 'true' 
+# you can use '0', 'off', 'no', 'false', or 'f' as 'false,
+# and you can use '1', 'on', 'yes', 'true', or 't' as 'true'
 # If the value is missing, then it means 'true' by default.
 #
 
 # Listener interface device (optional, Linux only).
-# NOT RECOMMENDED. 
+# NOT RECOMMENDED.
 #
 #listening-device=eth0
 
 # TURN listener port for UDP and TCP (Default: 3478).
-# Note: actually, TLS & DTLS sessions can connect to the 
+# Note: actually, TLS & DTLS sessions can connect to the
 # "plain" TCP & UDP port(s), too - if allowed by configuration.
 #
 listening-port=3478
 
 # TURN listener port for TLS (Default: 5349).
 # Note: actually, "plain" TCP & UDP sessions can connect to the TLS & DTLS
-# port(s), too - if allowed by configuration. The TURN server 
+# port(s), too - if allowed by configuration. The TURN server
 # "automatically" recognizes the type of traffic. Actually, two listening
 # endpoints (the "plain" one and the "tls" one) are equivalent in terms of
 # functionality; but Coturn keeps both endpoints to satisfy the RFC 5766 specs.
-# For secure TCP connections, Coturn currently supports SSL version 3 and 
+# For secure TCP connections, Coturn currently supports SSL version 3 and
 # TLS version 1.0, 1.1 and 1.2.
 # For secure UDP connections, Coturn supports DTLS version 1.
 #
 tls-listening-port=5349
 
 # Alternative listening port for UDP and TCP listeners;
-# default (or zero) value means "listening port plus one". 
+# default (or zero) value means "listening port plus one".
 # This is needed for RFC 5780 support
-# (STUN extension specs, NAT behavior discovery). The TURN Server 
-# supports RFC 5780 only if it is started with more than one 
+# (STUN extension specs, NAT behavior discovery). The TURN Server
+# supports RFC 5780 only if it is started with more than one
 # listening IP address of the same family (IPv4 or IPv6).
 # RFC 5780 is supported only by UDP protocol, other protocols
 # are listening to that endpoint only for "symmetry".
 #
 #alt-listening-port=0
-							 
+
 # Alternative listening port for TLS and DTLS protocols.
 # Default (or zero) value means "TLS listening port plus one".
 #
@@ -52,9 +52,9 @@ tls-listening-port=5349
 # (https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)
 #
 #tcp-proxy-port=5555
-	
+
 # Listener IP address of relay server. Multiple listeners can be specified.
-# If no IP(s) specified in the config file or in the command line options, 
+# If no IP(s) specified in the config file or in the command line options,
 # then all IPv4 and IPv6 system IPs will be used for listening.
 #
 #listening-ip=172.17.19.101
@@ -69,7 +69,7 @@ tls-listening-port=5349
 # they do not support STUN RFC 5780 functionality (CHANGE REQUEST).
 #
 # 2) Auxiliary servers also are never returning ALTERNATIVE-SERVER reply.
-# 
+#
 # Valid formats are 1.2.3.4:5555 for IPv4 and [1:2::3:4]:5555 for IPv6.
 #
 # There may be multiple aux-server options, each will be used for listening
@@ -81,7 +81,7 @@ tls-listening-port=5349
 # (recommended for older Linuxes only)
 # Automatically balance UDP traffic over auxiliary servers (if configured).
 # The load balancing is using the ALTERNATE-SERVER mechanism.
-# The TURN client must support 300 ALTERNATE-SERVER response for this 
+# The TURN client must support 300 ALTERNATE-SERVER response for this
 # functionality.
 #
 #udp-self-balance
@@ -91,13 +91,13 @@ tls-listening-port=5349
 #
 #relay-device=eth1
 
-# Relay address (the local IP address that will be used to relay the 
+# Relay address (the local IP address that will be used to relay the
 # packets to the peer).
 # Multiple relay addresses may be used.
 # The same IP(s) can be used as both listening IP(s) and relay IP(s).
 #
 # If no relay IP(s) specified, then the turnserver will apply the default
-# policy: it will decide itself which relay addresses to be used, and it 
+# policy: it will decide itself which relay addresses to be used, and it
 # will always be using the client socket IP address as the relay IP address
 # of the TURN session (if the requested relay address family is the same
 # as the family of the client socket).
@@ -120,7 +120,7 @@ tls-listening-port=5349
 # that option must be used several times, each entry must
 # have form "-X <public-ip/private-ip>", to map all involved addresses.
 # RFC5780 NAT discovery STUN functionality will work correctly,
-# if the addresses are mapped properly, even when the TURN server itself 
+# if the addresses are mapped properly, even when the TURN server itself
 # is behind A NAT.
 #
 # By default, this value is empty, and no address mapping is used.
@@ -135,18 +135,18 @@ external-ip=193.224.22.37
 
 # Number of the relay threads to handle the established connections
 # (in addition to authentication thread and the listener thread).
-# If explicitly set to 0 then application runs relay process in a 
-# single thread, in the same thread with the listener process 
+# If explicitly set to 0 then application runs relay process in a
+# single thread, in the same thread with the listener process
 # (the authentication thread will still be a separate thread).
 #
-# If this parameter is not set, then the default OS-dependent 
+# If this parameter is not set, then the default OS-dependent
 # thread pattern algorithm will be employed. Usually the default
 # algorithm is optimal, so you have to change this option
-# if you want to make some fine tweaks. 
+# if you want to make some fine tweaks.
 #
 # In the older systems (Linux kernel before 3.9),
 # the number of UDP threads is always one thread per network listening
-# endpoint - including the auxiliary endpoints - unless 0 (zero) or 
+# endpoint - including the auxiliary endpoints - unless 0 (zero) or
 # 1 (one) value is set.
 #
 #relay-threads=0
@@ -156,15 +156,15 @@ external-ip=193.224.22.37
 #
 min-port=49152
 max-port=65535
-	
+
 # Uncomment to run TURN server in 'normal' 'moderate' verbose mode.
 # By default the verbose mode is off.
 verbose
-	
+
 # Uncomment to run TURN server in 'extra' verbose mode.
 # This mode is very annoying and produces lots of output.
 # Not recommended under normal circumstances.
-#	
+#
 #Verbose
 
 # Uncomment to use fingerprints in the TURN messages.
@@ -177,10 +177,10 @@ fingerprint
 #
 lt-cred-mech
 
-# This option is the opposite of lt-cred-mech. 
+# This option is the opposite of lt-cred-mech.
 # (TURN Server with no-auth option allows anonymous access).
 # If neither option is defined, and no users are defined,
-# then no-auth is default. If at least one user is defined, 
+# then no-auth is default. If at least one user is defined,
 # in this file, in command line or in usersdb file, then
 # lt-cred-mech is default.
 #
@@ -191,11 +191,11 @@ lt-cred-mech
 # Flag that sets a special authorization option that is based upon authentication secret.
 #
 # This feature's purpose is to support "TURN Server REST API", see
-# "TURN REST API" link in the project's page 
+# "TURN REST API" link in the project's page
 # https://github.com/coturn/coturn/
 #
 # This option is used with timestamp:
-# 
+#
 # usercombo -> "timestamp:userid"
 # turn user -> usercombo
 # turn password -> base64(hmac(secret key, usercombo))
@@ -205,7 +205,7 @@ lt-cred-mech
 # This option is enabled by turning on secret-based authentication.
 # The actual value of the secret is defined either by the option static-auth-secret,
 # or can be found in the turn_secret table in the database (see below).
-# 
+#
 # Read more about it:
 #  - https://tools.ietf.org/html/draft-uberti-behave-turn-rest-00
 #  - https://www.ietf.org/proceedings/87/slides/slides-87-behave-10.pdf
@@ -217,13 +217,13 @@ lt-cred-mech
 #
 # Note that you can use only one auth mechanism at the same time! This is because,
 # both mechanisms conduct username and password validation in different ways.
-# 
+#
 # Use either lt-cred-mech or use-auth-secret in the conf
 # to avoid any confusion.
 #
 #use-auth-secret
 
-# 'Static' authentication secret value (a string) for TURN REST API only. 
+# 'Static' authentication secret value (a string) for TURN REST API only.
 # If not set, then the turn server
 # will try to use the 'dynamic' value in the turn_secret table
 # in the user database (if present). The database-stored  value can be changed on-the-fly
@@ -243,7 +243,7 @@ lt-cred-mech
 
 # 'Static' user accounts for the long term credentials mechanism, only.
 # This option cannot be used with TURN REST API.
-# 'Static' user accounts are NOT dynamically checked by the turnserver process, 
+# 'Static' user accounts are NOT dynamically checked by the turnserver process,
 # so they can NOT be changed while the turnserver is running.
 #
 #user=username1:key1
@@ -262,7 +262,7 @@ lt-cred-mech
 # password. If it has 0x then it is a key, otherwise it is a password).
 #
 # The corresponding user account entry in the config file will be:
-# 
+#
 #user=ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee
 # Or, equivalently, with open clear password (less secure):
 #user=ninefingers:youhavetoberealistic
@@ -272,15 +272,15 @@ lt-cred-mech
 #
 # The default file name is /var/db/turndb or /usr/local/var/db/turndb or
 # /var/lib/turn/turndb.
-# 
+#
 #userdb=/var/db/turndb
 
 # PostgreSQL database connection string in the case that you are using PostgreSQL
 # as the user database.
 # This database can be used for the long-term credential mechanism
-# and it can store the secret value for secret-based timed authentication in TURN REST API. 
+# and it can store the secret value for secret-based timed authentication in TURN REST API.
 # See http://www.postgresql.org/docs/8.4/static/libpq-connect.html for 8.x PostgreSQL
-# versions connection string format, see 
+# versions connection string format, see
 # http://www.postgresql.org/docs/9.2/static/libpq-connect.html#LIBPQ-CONNSTRING
 # for 9.x and newer connection string formats.
 #
@@ -291,9 +291,9 @@ lt-cred-mech
 # This database can be used for the long-term credential mechanism
 # and it can store the secret value for secret-based timed authentication in TURN REST API.
 #
-# Optional connection string parameters for the secure communications (SSL): 
-# ca, capath, cert, key, cipher 
-# (see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the 
+# Optional connection string parameters for the secure communications (SSL):
+# ca, capath, cert, key, cipher
+# (see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the
 # command options description).
 #
 # Use the string format below (space separated parameters, all optional):
@@ -303,7 +303,7 @@ mysql-userdb="host=mysql dbname=coturn user=coturn password=CHANGE_ME port=3306
 # If you want to use an encrypted password in the MySQL connection string,
 # then set the MySQL password encryption secret key file with this option.
 #
-# Warning: If this option is set, then the mysql password must be set in "mysql-userdb" in an encrypted format! 
+# Warning: If this option is set, then the mysql password must be set in "mysql-userdb" in an encrypted format!
 # If you want to use a cleartext password then do not set this option!
 #
 # This is the file path for the aes encrypted secret key used for password encryption.
@@ -313,7 +313,7 @@ mysql-userdb="host=mysql dbname=coturn user=coturn password=CHANGE_ME port=3306
 # MongoDB database connection string in the case that you are using MongoDB
 # as the user database.
 # This database can be used for long-term credential mechanism
-# and it can store the secret value for secret-based timed authentication in TURN REST API. 
+# and it can store the secret value for secret-based timed authentication in TURN REST API.
 # Use the string format described at http://hergert.me/docs/mongo-c-driver/mongoc_uri.html
 #
 #mongo-userdb="mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]"
@@ -321,7 +321,7 @@ mysql-userdb="host=mysql dbname=coturn user=coturn password=CHANGE_ME port=3306
 # Redis database connection string in the case that you are using Redis
 # as the user database.
 # This database can be used for long-term credential mechanism
-# and it can store the secret value for secret-based timed authentication in TURN REST API. 
+# and it can store the secret value for secret-based timed authentication in TURN REST API.
 # Use the string format below (space separated parameters, all optional):
 #
 #redis-userdb="ip=<ip-address> dbname=<database-number> password=<database-user-password> port=<port> connect_timeout=<seconds>"
@@ -329,15 +329,15 @@ mysql-userdb="host=mysql dbname=coturn user=coturn password=CHANGE_ME port=3306
 # Redis status and statistics database connection string, if used (default - empty, no Redis stats DB used).
 # This database keeps allocations status information, and it can be also used for publishing
 # and delivering traffic and allocation event notifications.
-# The connection string has the same parameters as redis-userdb connection string. 
+# The connection string has the same parameters as redis-userdb connection string.
 # Use the string format below (space separated parameters, all optional):
 #
 #redis-statsdb="ip=<ip-address> dbname=<database-number> password=<database-user-password> port=<port> connect_timeout=<seconds>"
 
-# The default realm to be used for the users when no explicit 
+# The default realm to be used for the users when no explicit
 # origin/realm relationship is found in the database, or if the TURN
 # server is not using any database (just the commands-line settings
-# and the userdb file). Must be used with long-term credentials 
+# and the userdb file). Must be used with long-term credentials
 # mechanism or with TURN REST API.
 #
 # Note: If the default realm is not specified, then realm falls back to the host domain name.
@@ -345,7 +345,7 @@ mysql-userdb="host=mysql dbname=coturn user=coturn password=CHANGE_ME port=3306
 #
 realm=example.org
 
-# This flag sets the origin consistency 
+# This flag sets the origin consistency
 # check. Across the session, all requests must have the same
 # main ORIGIN attribute value (if the ORIGIN was
 # initially used by the session).
@@ -411,10 +411,10 @@ realm=example.org
 
 # Uncomment if extra security is desired,
 # with nonce value having a limited lifetime.
-# By default, the nonce value is unique for a session,
-# and has an 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 nonce value is unique for a session.
+# Set this option to limit the nonce lifetime.
+# Set it to 0 for unlimited 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=600
@@ -440,14 +440,14 @@ realm=example.org
 #permission-lifetime=300
 
 # Certificate file.
-# Use an absolute path or path relative to the 
+# Use an absolute path or path relative to the
 # configuration file.
 # Use PEM file format.
 #
 cert=/etc/ssl/certs/cert.pem
 
 # Private key file.
-# Use an absolute path or path relative to the 
+# Use an absolute path or path relative to the
 # configuration file.
 # Use PEM file format.
 #
@@ -463,7 +463,7 @@ pkey=/etc/ssl/private/privkey.pem
 #
 #cipher-list="DEFAULT"
 
-# CA file in OpenSSL format. 
+# CA file in OpenSSL format.
 # Forces TURN server to verify the client SSL certificates.
 # By default this is not set: there is no default value and the client
 # certificate is not checked.
@@ -471,8 +471,8 @@ pkey=/etc/ssl/private/privkey.pem
 # Example:
 #CA-file=/etc/ssh/id_rsa.cert
 
-# Curve name for EC ciphers, if supported by OpenSSL 
-# library (TLS and DTLS). The default value is prime256v1, 
+# Curve name for EC ciphers, if supported by OpenSSL
+# library (TLS and DTLS). The default value is prime256v1,
 # if pre-OpenSSL 1.0.2 is used. With OpenSSL 1.0.2+,
 # an optimal curve will be automatically calculated, if not defined
 # by this option.
@@ -493,21 +493,21 @@ pkey=/etc/ssl/private/privkey.pem
 #dh-file=<DH-PEM-file-name>
 
 # Flag to prevent stdout log messages.
-# By default, all log messages go to both stdout and to 
-# the configured log file. With this option everything will 
+# By default, all log messages go to both stdout and to
+# the configured log file. With this option everything will
 # go to the configured log only (unless the log file itself is stdout).
 #
 #no-stdout-log
 
 # Option to set the log file name.
-# By default, the turnserver tries to open a log file in 
+# By default, the turnserver tries to open a log file in
 # /var/log, /var/tmp, /tmp and the current directory
 # (Whichever file open operation succeeds first will be used).
 # With this option you can set the definite log file name.
-# The special names are "stdout" and "-" - they will force everything 
+# The special names are "stdout" and "-" - they will force everything
 # to the stdout. Also, the "syslog" name will force everything to
-# the system log (syslog). 
-# In the runtime, the logfile can be reset with the SIGHUP signal 
+# the system log (syslog).
+# In the runtime, the logfile can be reset with the SIGHUP signal
 # to the turnserver process.
 #
 #log-file=/var/tmp/turn.log
@@ -523,40 +523,40 @@ syslog
 #simple-log
 
 # Option to set the "redirection" mode. The value of this option
-# will be the address of the alternate server for UDP & TCP service in the form of 
+# will be the address of the alternate server for UDP & TCP service in the form of
 # <ip>[:<port>]. The server will send this value in the attribute
 # ALTERNATE-SERVER, with error 300, on ALLOCATE request, to the client.
 # Client will receive only values with the same address family
-# as the client network endpoint address family. 
-# See RFC 5389 and RFC 5766 for the description of ALTERNATE-SERVER functionality. 
+# as the client network endpoint address family.
+# See RFC 5389 and RFC 5766 for the description of ALTERNATE-SERVER functionality.
 # The client must use the obtained value for subsequent TURN communications.
 # If more than one --alternate-server option is provided, then the functionality
-# can be more accurately described as "load-balancing" than a mere "redirection". 
-# If the port number is omitted, then the default port 
+# can be more accurately described as "load-balancing" than a mere "redirection".
+# If the port number is omitted, then the default port
 # number 3478 for the UDP/TCP protocols will be used.
-# Colon (:) characters in IPv6 addresses may conflict with the syntax of 
-# the option. To alleviate this conflict, literal IPv6 addresses are enclosed 
-# in square brackets in such resource identifiers, for example: 
-# [2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478 . 
+# Colon (:) characters in IPv6 addresses may conflict with the syntax of
+# the option. To alleviate this conflict, literal IPv6 addresses are enclosed
+# in square brackets in such resource identifiers, for example:
+# [2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478 .
 # Multiple alternate servers can be set. They will be used in the
-# round-robin manner. All servers in the pool are considered of equal weight and 
-# the load will be distributed equally. For example, if you have 4 alternate servers, 
-# then each server will receive 25% of ALLOCATE requests. A alternate TURN server 
-# address can be used more than one time with the alternate-server option, so this 
+# round-robin manner. All servers in the pool are considered of equal weight and
+# the load will be distributed equally. For example, if you have 4 alternate servers,
+# then each server will receive 25% of ALLOCATE requests. A alternate TURN server
+# address can be used more than one time with the alternate-server option, so this
 # can emulate "weighting" of the servers.
 #
-# Examples: 
+# Examples:
 #alternate-server=1.2.3.4:5678
 #alternate-server=11.22.33.44:56789
 #alternate-server=5.6.7.8
 #alternate-server=[2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478
-			
-# Option to set alternative server for TLS & DTLS services in form of 
-# <ip>:<port>. If the port number is omitted, then the default port 
-# number 5349 for the TLS/DTLS protocols will be used. See the previous 
+
+# Option to set alternative server for TLS & DTLS services in form of
+# <ip>:<port>. If the port number is omitted, then the default port
+# number 5349 for the TLS/DTLS protocols will be used. See the previous
 # option for the functionality description.
 #
-# Examples: 
+# Examples:
 #tls-alternate-server=1.2.3.4:5678
 #tls-alternate-server=11.22.33.44:56789
 #tls-alternate-server=[2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478
@@ -584,7 +584,7 @@ syslog
 
 # This is the timestamp/username separator symbol (character) in TURN REST API.
 # The default value is ':'.
-# rest-api-separator=:	
+# rest-api-separator=:
 
 # Flag that can be used to allow peers on the loopback addresses (127.x.x.x and ::1).
 # This is an extra security measure.
@@ -592,9 +592,9 @@ syslog
 # (To avoid any security issue that allowing loopback access may raise,
 # the no-loopback-peers option is replaced by allow-loopback-peers.)
 #
-# Allow it only for testing in a development environment! 
-# In production it adds a possible security vulnerability, so for security reasons 
-# it is not allowed using it together with empty cli-password. 
+# Allow it only for testing in a development environment!
+# In production it adds a possible security vulnerability, so for security reasons
+# it is not allowed using it together with empty cli-password.
 #
 #allow-loopback-peers
 
@@ -603,18 +603,18 @@ syslog
 #
 #no-multicast-peers
 
-# Option to set the max time, in seconds, allowed for full allocation establishment. 
+# Option to set the max time, in seconds, allowed for full allocation establishment.
 # Default is 60 seconds.
 #
 #max-allocate-timeout=60
 
-# Option to allow or ban specific ip addresses or ranges of ip addresses. 
-# If an ip address is specified as both allowed and denied, then the ip address is 
-# considered to be allowed. This is useful when you wish to ban a range of ip 
+# Option to allow or ban specific ip addresses or ranges of ip addresses.
+# If an ip address is specified as both allowed and denied, then the ip address is
+# considered to be allowed. This is useful when you wish to ban a range of ip
 # addresses, except for a few specific ips within that range.
 #
 # This can be used when you do not want users of the turn server to be able to access
-# machines reachable by the turn server, but would otherwise be unreachable from the 
+# machines reachable by the turn server, but would otherwise be unreachable from the
 # internet (e.g. when the turn server is sitting behind a NAT)
 #
 # Examples:
@@ -636,8 +636,8 @@ syslog
 #
 #mobility
 
-# Allocate Address Family according 
-# If enabled then TURN server allocates address family according  the TURN 
+# Allocate Address Family according
+# If enabled then TURN server allocates address family according  the TURN
 # Client <=> Server communication address family.
 # (By default Coturn works according RFC 6156.)
 # !!Warning: Enabling this option breaks RFC6156 section-4.2 (violates use default IPv4)!!
@@ -701,10 +701,10 @@ cli-password=CHANGE_ME
 #
 #web-admin-listen-on-workers
 
-# Server relay. NON-STANDARD AND DANGEROUS OPTION. 
-# Only for those applications when you want to run 
+# Server relay. NON-STANDARD AND DANGEROUS OPTION.
+# Only for those applications when you want to run
 # server applications on the relay endpoints.
-# This option eliminates the IP permissions check on 
+# This option eliminates the IP permissions check on
 # the packets incoming to the relay endpoints.
 #
 #server-relay

+ 108 - 94
examples/etc/turnserver.conf

@@ -1,25 +1,25 @@
 # Coturn TURN SERVER configuration file
 #
 # Boolean values note: where a boolean value is supposed to be used,
-# you can use '0', 'off', 'no', 'false', or 'f' as 'false, 
-# and you can use '1', 'on', 'yes', 'true', or 't' as 'true' 
+# you can use '0', 'off', 'no', 'false', or 'f' as 'false,
+# and you can use '1', 'on', 'yes', 'true', or 't' as 'true'
 # If the value is missing, then it means 'true' by default.
 #
 
 # Listener interface device (optional, Linux only).
-# NOT RECOMMENDED. 
+# NOT RECOMMENDED.
 #
 #listening-device=eth0
 
 # TURN listener port for UDP and TCP (Default: 3478).
-# Note: actually, TLS & DTLS sessions can connect to the 
+# Note: actually, TLS & DTLS sessions can connect to the
 # "plain" TCP & UDP port(s), too - if allowed by configuration.
 #
 #listening-port=3478
 
 # TURN listener port for TLS (Default: 5349).
 # Note: actually, "plain" TCP & UDP sessions can connect to the TLS & DTLS
-# port(s), too - if allowed by configuration. The TURN server 
+# port(s), too - if allowed by configuration. The TURN server
 # "automatically" recognizes the type of traffic. Actually, two listening
 # endpoints (the "plain" one and the "tls" one) are equivalent in terms of
 # functionality; but Coturn keeps both endpoints to satisfy the RFC 5766 specs.
@@ -30,16 +30,16 @@
 #tls-listening-port=5349
 
 # Alternative listening port for UDP and TCP listeners;
-# default (or zero) value means "listening port plus one". 
+# default (or zero) value means "listening port plus one".
 # This is needed for RFC 5780 support
-# (STUN extension specs, NAT behavior discovery). The TURN Server 
-# supports RFC 5780 only if it is started with more than one 
+# (STUN extension specs, NAT behavior discovery). The TURN Server
+# supports RFC 5780 only if it is started with more than one
 # listening IP address of the same family (IPv4 or IPv6).
 # RFC 5780 is supported only by UDP protocol, other protocols
 # are listening to that endpoint only for "symmetry".
 #
 #alt-listening-port=0
-							 
+
 # Alternative listening port for TLS and DTLS protocols.
 # Default (or zero) value means "TLS listening port plus one".
 #
@@ -52,9 +52,9 @@
 # (https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)
 #
 #tcp-proxy-port=5555
-	
+
 # Listener IP address of relay server. Multiple listeners can be specified.
-# If no IP(s) specified in the config file or in the command line options, 
+# If no IP(s) specified in the config file or in the command line options,
 # then all IPv4 and IPv6 system IPs will be used for listening.
 #
 #listening-ip=172.17.19.101
@@ -69,7 +69,7 @@
 # they do not support STUN RFC 5780 functionality (CHANGE REQUEST).
 #
 # 2) Auxiliary servers also are never returning ALTERNATIVE-SERVER reply.
-# 
+#
 # Valid formats are 1.2.3.4:5555 for IPv4 and [1:2::3:4]:5555 for IPv6.
 #
 # There may be multiple aux-server options, each will be used for listening
@@ -81,7 +81,7 @@
 # (recommended for older Linuxes only)
 # Automatically balance UDP traffic over auxiliary servers (if configured).
 # The load balancing is using the ALTERNATE-SERVER mechanism.
-# The TURN client must support 300 ALTERNATE-SERVER response for this 
+# The TURN client must support 300 ALTERNATE-SERVER response for this
 # functionality.
 #
 #udp-self-balance
@@ -91,13 +91,13 @@
 #
 #relay-device=eth1
 
-# Relay address (the local IP address that will be used to relay the 
+# Relay address (the local IP address that will be used to relay the
 # packets to the peer).
 # Multiple relay addresses may be used.
 # The same IP(s) can be used as both listening IP(s) and relay IP(s).
 #
 # If no relay IP(s) specified, then the turnserver will apply the default
-# policy: it will decide itself which relay addresses to be used, and it 
+# policy: it will decide itself which relay addresses to be used, and it
 # will always be using the client socket IP address as the relay IP address
 # of the TURN session (if the requested relay address family is the same
 # as the family of the client socket).
@@ -120,7 +120,7 @@
 # that option must be used several times, each entry must
 # have form "-X <public-ip/private-ip>", to map all involved addresses.
 # RFC5780 NAT discovery STUN functionality will work correctly,
-# if the addresses are mapped properly, even when the TURN server itself 
+# if the addresses are mapped properly, even when the TURN server itself
 # is behind A NAT.
 #
 # By default, this value is empty, and no address mapping is used.
@@ -135,18 +135,18 @@
 
 # Number of the relay threads to handle the established connections
 # (in addition to authentication thread and the listener thread).
-# If explicitly set to 0 then application runs relay process in a 
-# single thread, in the same thread with the listener process 
+# If explicitly set to 0 then application runs relay process in a
+# single thread, in the same thread with the listener process
 # (the authentication thread will still be a separate thread).
 #
-# If this parameter is not set, then the default OS-dependent 
+# If this parameter is not set, then the default OS-dependent
 # thread pattern algorithm will be employed. Usually the default
 # algorithm is optimal, so you have to change this option
-# if you want to make some fine tweaks. 
+# if you want to make some fine tweaks.
 #
 # In the older systems (Linux kernel before 3.9),
 # the number of UDP threads is always one thread per network listening
-# endpoint - including the auxiliary endpoints - unless 0 (zero) or 
+# endpoint - including the auxiliary endpoints - unless 0 (zero) or
 # 1 (one) value is set.
 #
 #relay-threads=0
@@ -156,15 +156,15 @@
 #
 #min-port=49152
 #max-port=65535
-	
+
 # Uncomment to run TURN server in 'normal' 'moderate' verbose mode.
 # By default the verbose mode is off.
 #verbose
-	
+
 # Uncomment to run TURN server in 'extra' verbose mode.
 # This mode is very annoying and produces lots of output.
 # Not recommended under normal circumstances.
-#	
+#
 #Verbose
 
 # Uncomment to use fingerprints in the TURN messages.
@@ -177,10 +177,10 @@
 #
 #lt-cred-mech
 
-# This option is the opposite of lt-cred-mech. 
+# This option is the opposite of lt-cred-mech.
 # (TURN Server with no-auth option allows anonymous access).
 # If neither option is defined, and no users are defined,
-# then no-auth is default. If at least one user is defined, 
+# then no-auth is default. If at least one user is defined,
 # in this file, in command line or in usersdb file, then
 # lt-cred-mech is default.
 #
@@ -203,11 +203,11 @@
 # Flag that sets a special authorization option that is based upon authentication secret.
 #
 # This feature's purpose is to support "TURN Server REST API", see
-# "TURN REST API" link in the project's page 
+# "TURN REST API" link in the project's page
 # https://github.com/coturn/coturn/
 #
 # This option is used with timestamp:
-# 
+#
 # usercombo -> "timestamp:userid"
 # turn user -> usercombo
 # turn password -> base64(hmac(secret key, usercombo))
@@ -217,7 +217,7 @@
 # This option is enabled by turning on secret-based authentication.
 # The actual value of the secret is defined either by the option static-auth-secret,
 # or can be found in the turn_secret table in the database (see below).
-# 
+#
 # Read more about it:
 #  - https://tools.ietf.org/html/draft-uberti-behave-turn-rest-00
 #  - https://www.ietf.org/proceedings/87/slides/slides-87-behave-10.pdf
@@ -229,13 +229,13 @@
 #
 # Note that you can use only one auth mechanism at the same time! This is because,
 # both mechanisms conduct username and password validation in different ways.
-# 
+#
 # Use either lt-cred-mech or use-auth-secret in the conf
 # to avoid any confusion.
 #
 #use-auth-secret
 
-# 'Static' authentication secret value (a string) for TURN REST API only. 
+# 'Static' authentication secret value (a string) for TURN REST API only.
 # If not set, then the turn server
 # will try to use the 'dynamic' value in the turn_secret table
 # in the user database (if present). The database-stored  value can be changed on-the-fly
@@ -255,7 +255,7 @@
 
 # 'Static' user accounts for the long term credentials mechanism, only.
 # This option cannot be used with TURN REST API.
-# 'Static' user accounts are NOT dynamically checked by the turnserver process, 
+# 'Static' user accounts are NOT dynamically checked by the turnserver process,
 # so they can NOT be changed while the turnserver is running.
 #
 #user=username1:key1
@@ -274,7 +274,7 @@
 # password. If it has 0x then it is a key, otherwise it is a password).
 #
 # The corresponding user account entry in the config file will be:
-# 
+#
 #user=ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee
 # Or, equivalently, with open clear password (less secure):
 #user=ninefingers:youhavetoberealistic
@@ -284,15 +284,15 @@
 #
 # The default file name is /var/db/turndb or /usr/local/var/db/turndb or
 # /var/lib/turn/turndb.
-# 
+#
 #userdb=/var/db/turndb
 
 # PostgreSQL database connection string in the case that you are using PostgreSQL
 # as the user database.
 # This database can be used for the long-term credential mechanism
-# and it can store the secret value for secret-based timed authentication in TURN REST API. 
+# and it can store the secret value for secret-based timed authentication in TURN REST API.
 # See http://www.postgresql.org/docs/8.4/static/libpq-connect.html for 8.x PostgreSQL
-# versions connection string format, see 
+# versions connection string format, see
 # http://www.postgresql.org/docs/9.2/static/libpq-connect.html#LIBPQ-CONNSTRING
 # for 9.x and newer connection string formats.
 #
@@ -303,9 +303,9 @@
 # This database can be used for the long-term credential mechanism
 # and it can store the secret value for secret-based timed authentication in TURN REST API.
 #
-# Optional connection string parameters for the secure communications (SSL): 
-# ca, capath, cert, key, cipher 
-# (see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the 
+# Optional connection string parameters for the secure communications (SSL):
+# ca, capath, cert, key, cipher
+# (see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the
 # command options description).
 #
 # Use the string format below (space separated parameters, all optional):
@@ -315,7 +315,7 @@
 # If you want to use an encrypted password in the MySQL connection string,
 # then set the MySQL password encryption secret key file with this option.
 #
-# Warning: If this option is set, then the mysql password must be set in "mysql-userdb" in an encrypted format! 
+# Warning: If this option is set, then the mysql password must be set in "mysql-userdb" in an encrypted format!
 # If you want to use a cleartext password then do not set this option!
 #
 # This is the file path for the aes encrypted secret key used for password encryption.
@@ -325,7 +325,7 @@
 # MongoDB database connection string in the case that you are using MongoDB
 # as the user database.
 # This database can be used for long-term credential mechanism
-# and it can store the secret value for secret-based timed authentication in TURN REST API. 
+# and it can store the secret value for secret-based timed authentication in TURN REST API.
 # Use the string format described at http://hergert.me/docs/mongo-c-driver/mongoc_uri.html
 #
 #mongo-userdb="mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]"
@@ -333,7 +333,7 @@
 # Redis database connection string in the case that you are using Redis
 # as the user database.
 # This database can be used for long-term credential mechanism
-# and it can store the secret value for secret-based timed authentication in TURN REST API. 
+# and it can store the secret value for secret-based timed authentication in TURN REST API.
 # Use the string format below (space separated parameters, all optional):
 #
 #redis-userdb="ip=<ip-address> dbname=<database-number> password=<database-user-password> port=<port> connect_timeout=<seconds>"
@@ -341,15 +341,15 @@
 # Redis status and statistics database connection string, if used (default - empty, no Redis stats DB used).
 # This database keeps allocations status information, and it can be also used for publishing
 # and delivering traffic and allocation event notifications.
-# The connection string has the same parameters as redis-userdb connection string. 
+# The connection string has the same parameters as redis-userdb connection string.
 # Use the string format below (space separated parameters, all optional):
 #
 #redis-statsdb="ip=<ip-address> dbname=<database-number> password=<database-user-password> port=<port> connect_timeout=<seconds>"
 
-# The default realm to be used for the users when no explicit 
+# The default realm to be used for the users when no explicit
 # origin/realm relationship is found in the database, or if the TURN
 # server is not using any database (just the commands-line settings
-# and the userdb file). Must be used with long-term credentials 
+# and the userdb file). Must be used with long-term credentials
 # mechanism or with TURN REST API.
 #
 # Note: If the default realm is not specified, then realm falls back to the host domain name.
@@ -357,7 +357,7 @@
 #
 #realm=mycompany.org
 
-# This flag sets the origin consistency 
+# This flag sets the origin consistency
 # check. Across the session, all requests must have the same
 # main ORIGIN attribute value (if the ORIGIN was
 # initially used by the session).
@@ -423,10 +423,10 @@
 
 # Uncomment if extra security is desired,
 # with nonce value having a limited lifetime.
-# By default, the nonce value is unique for a session,
-# and has an 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 nonce value is unique for a session.
+# Set this option to limit the nonce lifetime.
+# Set it to 0 for unlimited 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=600
@@ -452,14 +452,14 @@
 #permission-lifetime=300
 
 # Certificate file.
-# Use an absolute path or path relative to the 
+# Use an absolute path or path relative to the
 # configuration file.
 # Use PEM file format.
 #
 #cert=/usr/local/etc/turn_server_cert.pem
 
 # Private key file.
-# Use an absolute path or path relative to the 
+# Use an absolute path or path relative to the
 # configuration file.
 # Use PEM file format.
 #
@@ -475,7 +475,7 @@
 #
 #cipher-list="DEFAULT"
 
-# CA file in OpenSSL format. 
+# CA file in OpenSSL format.
 # Forces TURN server to verify the client SSL certificates.
 # By default this is not set: there is no default value and the client
 # certificate is not checked.
@@ -483,8 +483,8 @@
 # Example:
 #CA-file=/etc/ssh/id_rsa.cert
 
-# Curve name for EC ciphers, if supported by OpenSSL 
-# library (TLS and DTLS). The default value is prime256v1, 
+# Curve name for EC ciphers, if supported by OpenSSL
+# library (TLS and DTLS). The default value is prime256v1,
 # if pre-OpenSSL 1.0.2 is used. With OpenSSL 1.0.2+,
 # an optimal curve will be automatically calculated, if not defined
 # by this option.
@@ -505,21 +505,21 @@
 #dh-file=<DH-PEM-file-name>
 
 # Flag to prevent stdout log messages.
-# By default, all log messages go to both stdout and to 
-# the configured log file. With this option everything will 
+# By default, all log messages go to both stdout and to
+# the configured log file. With this option everything will
 # go to the configured log only (unless the log file itself is stdout).
 #
 #no-stdout-log
 
 # Option to set the log file name.
-# By default, the turnserver tries to open a log file in 
+# By default, the turnserver tries to open a log file in
 # /var/log, /var/tmp, /tmp and the current directory
 # (Whichever file open operation succeeds first will be used).
 # With this option you can set the definite log file name.
-# The special names are "stdout" and "-" - they will force everything 
+# The special names are "stdout" and "-" - they will force everything
 # to the stdout. Also, the "syslog" name will force everything to
-# the system log (syslog). 
-# In the runtime, the logfile can be reset with the SIGHUP signal 
+# the system log (syslog).
+# In the runtime, the logfile can be reset with the SIGHUP signal
 # to the turnserver process.
 #
 #log-file=/var/tmp/turn.log
@@ -534,41 +534,51 @@
 #
 #simple-log
 
+# Enable full ISO-8601 timestamp in all logs.
+#new-log-timestamp
+
+# Set timestamp format (in strftime(1) format)
+#new-log-timestamp-format "%FT%T%z"
+
+# Disabled by default binding logging in verbose log mode to avoid DoS attacks.
+# Enable binding logging and UDP endpoint logs in verbose log mode.
+#log-binding
+
 # Option to set the "redirection" mode. The value of this option
-# will be the address of the alternate server for UDP & TCP service in the form of 
+# will be the address of the alternate server for UDP & TCP service in the form of
 # <ip>[:<port>]. The server will send this value in the attribute
 # ALTERNATE-SERVER, with error 300, on ALLOCATE request, to the client.
 # Client will receive only values with the same address family
-# as the client network endpoint address family. 
-# See RFC 5389 and RFC 5766 for the description of ALTERNATE-SERVER functionality. 
+# as the client network endpoint address family.
+# See RFC 5389 and RFC 5766 for the description of ALTERNATE-SERVER functionality.
 # The client must use the obtained value for subsequent TURN communications.
 # If more than one --alternate-server option is provided, then the functionality
-# can be more accurately described as "load-balancing" than a mere "redirection". 
-# If the port number is omitted, then the default port 
+# can be more accurately described as "load-balancing" than a mere "redirection".
+# If the port number is omitted, then the default port
 # number 3478 for the UDP/TCP protocols will be used.
-# Colon (:) characters in IPv6 addresses may conflict with the syntax of 
-# the option. To alleviate this conflict, literal IPv6 addresses are enclosed 
-# in square brackets in such resource identifiers, for example: 
-# [2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478 . 
+# Colon (:) characters in IPv6 addresses may conflict with the syntax of
+# the option. To alleviate this conflict, literal IPv6 addresses are enclosed
+# in square brackets in such resource identifiers, for example:
+# [2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478 .
 # Multiple alternate servers can be set. They will be used in the
-# round-robin manner. All servers in the pool are considered of equal weight and 
-# the load will be distributed equally. For example, if you have 4 alternate servers, 
-# then each server will receive 25% of ALLOCATE requests. A alternate TURN server 
-# address can be used more than one time with the alternate-server option, so this 
+# round-robin manner. All servers in the pool are considered of equal weight and
+# the load will be distributed equally. For example, if you have 4 alternate servers,
+# then each server will receive 25% of ALLOCATE requests. A alternate TURN server
+# address can be used more than one time with the alternate-server option, so this
 # can emulate "weighting" of the servers.
 #
-# Examples: 
+# Examples:
 #alternate-server=1.2.3.4:5678
 #alternate-server=11.22.33.44:56789
 #alternate-server=5.6.7.8
 #alternate-server=[2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478
-			
-# Option to set alternative server for TLS & DTLS services in form of 
-# <ip>:<port>. If the port number is omitted, then the default port 
-# number 5349 for the TLS/DTLS protocols will be used. See the previous 
+
+# Option to set alternative server for TLS & DTLS services in form of
+# <ip>:<port>. If the port number is omitted, then the default port
+# number 5349 for the TLS/DTLS protocols will be used. See the previous
 # option for the functionality description.
 #
-# Examples: 
+# Examples:
 #tls-alternate-server=1.2.3.4:5678
 #tls-alternate-server=11.22.33.44:56789
 #tls-alternate-server=[2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478
@@ -596,7 +606,7 @@
 
 # This is the timestamp/username separator symbol (character) in TURN REST API.
 # The default value is ':'.
-# rest-api-separator=:	
+# rest-api-separator=:
 
 # Flag that can be used to allow peers on the loopback addresses (127.x.x.x and ::1).
 # This is an extra security measure.
@@ -604,9 +614,9 @@
 # (To avoid any security issue that allowing loopback access may raise,
 # the no-loopback-peers option is replaced by allow-loopback-peers.)
 #
-# Allow it only for testing in a development environment! 
-# In production it adds a possible security vulnerability, so for security reasons 
-# it is not allowed using it together with empty cli-password. 
+# Allow it only for testing in a development environment!
+# In production it adds a possible security vulnerability, so for security reasons
+# it is not allowed using it together with empty cli-password.
 #
 #allow-loopback-peers
 
@@ -615,18 +625,18 @@
 #
 #no-multicast-peers
 
-# Option to set the max time, in seconds, allowed for full allocation establishment. 
+# Option to set the max time, in seconds, allowed for full allocation establishment.
 # Default is 60 seconds.
 #
 #max-allocate-timeout=60
 
-# Option to allow or ban specific ip addresses or ranges of ip addresses. 
-# If an ip address is specified as both allowed and denied, then the ip address is 
-# considered to be allowed. This is useful when you wish to ban a range of ip 
+# Option to allow or ban specific ip addresses or ranges of ip addresses.
+# If an ip address is specified as both allowed and denied, then the ip address is
+# considered to be allowed. This is useful when you wish to ban a range of ip
 # addresses, except for a few specific ips within that range.
 #
 # This can be used when you do not want users of the turn server to be able to access
-# machines reachable by the turn server, but would otherwise be unreachable from the 
+# machines reachable by the turn server, but would otherwise be unreachable from the
 # internet (e.g. when the turn server is sitting behind a NAT)
 #
 # Examples:
@@ -648,8 +658,8 @@
 #
 #mobility
 
-# Allocate Address Family according 
-# If enabled then TURN server allocates address family according  the TURN 
+# Allocate Address Family according
+# If enabled then TURN server allocates address family according  the TURN
 # Client <=> Server communication address family.
 # (By default Coturn works according RFC 6156.)
 # !!Warning: Enabling this option breaks RFC6156 section-4.2 (violates use default IPv4)!!
@@ -713,10 +723,14 @@
 #
 #web-admin-listen-on-workers
 
-# Server relay. NON-STANDARD AND DANGEROUS OPTION. 
-# Only for those applications when you want to run 
+#acme-redirect=http://redirectserver/.well-known/acme-challenge/
+# Redirect ACME, i.e. HTTP GET requests matching '^/.well-known/acme-challenge/(.*)' to '<URL>$1'.
+# Default is '', i.e. no special handling for such requests.
+
+# Server relay. NON-STANDARD AND DANGEROUS OPTION.
+# Only for those applications when you want to run
 # server applications on the relay endpoints.
-# This option eliminates the IP permissions check on 
+# This option eliminates the IP permissions check on
 # the packets incoming to the relay endpoints.
 #
 #server-relay

+ 1 - 1
examples/scripts/pack.sh

@@ -2,7 +2,7 @@
 
 # Run it from the root of the coturn source tree
 
-V=4.5.1.3
+V=4.5.2
 
 PACKDIR=`pwd`/../coturn-releases/
 SRCDIR=`pwd`

+ 21 - 16
man/man1/turnadmin.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "03 August 2020" "" ""
+.TH TURN 1 "05 January 2021" "" ""
 .SH GENERAL INFORMATION
 
 \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage
@@ -48,8 +48,8 @@ is equivalent to:
 .fi
 You have always the use the \fB\-r\fP <realm> option with commands for long term credentials \-
 because data for multiple realms can be stored in the same database.
-.SH =====================================
-
+.PP
+=====================================
 .SS  NAME
 \fB
 \fBturnadmin \fP\- a TURN relay administration tool.
@@ -288,8 +288,8 @@ $ \fIturnadmin\fP \fB\-\-file\-key\-path\fP <key\-file> \fB\-v\fP <encrypted>
 Help:
 .PP
 $ \fIturnadmin\fP \fB\-h\fP
-.SH =======================================
-
+.PP
+=======================================
 .SS  DOCS
 
 After installation, run the \fIcommand\fP:
@@ -301,8 +301,8 @@ or in the project root directory:
 $ man \fB\-M\fP man \fIturnadmin\fP
 .PP
 to see the man page.
-.SH =====================================
-
+.PP
+=====================================
 .SS  FILES
 
 /etc/turnserver.conf
@@ -314,8 +314,8 @@ to see the man page.
 /var/lib/turn/turndb
 .PP
 /usr/local/etc/turnserver.conf
-.SH =====================================
-
+.PP
+=====================================
 .SS  DIRECTORIES
 
 /usr/local/share/\fIturnserver\fP
@@ -323,13 +323,14 @@ to see the man page.
 /usr/local/share/doc/\fIturnserver\fP
 .PP
 /usr/local/share/examples/\fIturnserver\fP
-.SH ======================================
-
+.PP
+======================================
 .SS  SEE ALSO
 
 \fIturnserver\fP, \fIturnutils\fP
-.SH ======================================
-
+.RE
+.PP
+======================================
 .SS  WEB RESOURCES
 
 project page:
@@ -343,8 +344,9 @@ https://github.com/coturn/coturn/wiki
 forum:
 .PP
 https://groups.google.com/forum/?fromgroups=#!forum/turn\-server\-project\-rfc5766\-turn\-server/
-.SH ======================================
-
+.RE
+.PP
+======================================
 .SS  AUTHORS
 
 Oleg Moskalenko <[email protected]>
@@ -373,4 +375,7 @@ Federico Pinna <[email protected]>
 .PP
 Bradley T. Hughes <[email protected]>
 .PP
-Mihaly Meszaros <[email protected]>
+Mihály Mészáros <[email protected]>
+.SS  ACTIVE MAINTAINERS
+
+Mihály Mészáros <[email protected]>

+ 69 - 43
man/man1/turnserver.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "03 August 2020" "" ""
+.TH TURN 1 "05 January 2021" "" ""
 .SH GENERAL INFORMATION
 
 The \fBTURN Server\fP project contains the source code of a TURN server and TURN client
@@ -78,8 +78,7 @@ is equivalent to:
 
 .fam T
 .fi
-.SH =====================================
-
+=====================================
 .SS  NAME
 \fB
 \fBturnserver \fP\- a TURN relay server implementation.
@@ -338,6 +337,18 @@ name will be constructed as\-is, without PID and date appendage.
 This option can be used, for example, together with the logrotate tool.
 .TP
 .B
+\fB\-\-new\-log\-timestamp\fP
+Enable full ISO\-8601 timestamp in all logs.
+.TP
+.B
+\fB\-\-new\-log\-timestamp\-format\fP
+<format>        Set timestamp format (in \fBstrftime\fP(1) format)
+.TP
+.B
+\fB\-\-log\-binding\fP
+Log STUN binding request. It is now disabled by default to avoid DoS attacks.
+.TP
+.B
 \fB\-\-secure\-stun\fP
 Require authentication of the STUN Binding request.
 By default, the clients are allowed anonymous access to the STUN Binding functionality.
@@ -400,9 +411,9 @@ initially used by the session).
 .RS
 .TP
 .B
-\fB\-\-no\-prometheus\fP
-Disable prometheus metrics. By default it is
-enabled and listening on port 9641 unther the path /metrics
+\fB\-\-prometheus\fP
+Enable prometheus metrics. By default it is
+disabled. Would listen on port 9641 unther the path /metrics
 also the path / on this port can be used as a health check
 .RE
 .TP
@@ -416,6 +427,7 @@ Options with values:
 \fB\-\-stale\-nonce\fP[=<value>]
 Use extra security with nonce value having
 limited lifetime, in seconds (default 600 secs).
+Set it to 0 for unlimited nonce lifetime.
 .TP
 .B
 \fB\-\-max\-allocate\-lifetime\fP
@@ -780,6 +792,14 @@ Default is /var/run/turnserver.pid (if superuser account is used) or
 /var/tmp/turnserver.pid .
 .TP
 .B
+\fB\-\-acme\-redirect\fP
+<URL>  Redirect ACME/RFC8555 (like Let's Encrypt challenge) requests, i.e.
+HTTP GET requests matching '^/.well\-known/acme\-challenge/(.*)'
+to <URL>$1 with $1 == (.*). No validation of <URL> will be done,
+so make sure you do not forget the trailing slash. If <URL> is an empty
+string (the default value), no special handling of such requests will be done.
+.TP
+.B
 \fB\-\-proc\-user\fP
 User name to run the process. After the initialization, the \fIturnserver\fP process
 will make an attempt to change the current user ID to that user.
@@ -840,15 +860,15 @@ By default it is disabled for security resons!
 .B
 \fB\-\-ne\fP=[1|2|3]
 Set network engine type for the process (for internal purposes).
-.SH ==================================
-
+.PP
+==================================
 .SH LOAD BALANCE AND PERFORMANCE TUNING
 
 This topic is covered in the wiki page:
 .PP
 https://github.com/coturn/coturn/wiki/turn_performance_and_load_balance
-.SH ===================================
-
+.PP
+===================================
 .SH WEBRTC USAGE
 
 This is a set of notes for the WebRTC users:
@@ -885,8 +905,8 @@ Usually WebRTC uses fingerprinting (\fB\-f\fP).
 .IP 5) 4
 \fB\-\-min\-port\fP and \fB\-\-max\-port\fP may be needed if you want to limit the relay endpoints ports
 number range.
-.SH ===================================
-
+.PP
+===================================
 .SH TURN REST API
 
 In WebRTC, the browser obtains the TURN connection information from the web
@@ -1024,8 +1044,8 @@ examples/scripts/restapi/shared_secret_maintainer.pl .
 .PP
 A very important thing is that the nonce must be totally random and it must be
 different for different clients and different sessions.
-.SH ===================================
-
+.PP
+===================================
 .SH DATABASES
 
 For the user database, the \fIturnserver\fP has the following \fIoptions\fP:
@@ -1088,8 +1108,8 @@ it will set the users for you (see the \fIturnadmin\fP manuals). If you are usin
 \fIturnserver\fP or \fIturnadmin\fP will initialize the empty database, for you, when started. The
 TURN server installation process creates an empty initialized SQLite database in the default
 location (/var/db/turndb or /usr/local/var/db/turndb or /var/lib/turn/turndb, depending on the system).
-.SH =================================
-
+.PP
+=================================
 .SH ALPN
 
 The server supports ALPNs "stun.turn" and "stun.nat\-discovery", when
@@ -1098,16 +1118,16 @@ ClientHello message that contains one or both of those ALPNs, then the
 server chooses the first stun.* label and sends it back (in the ServerHello)
 in the ALPN extension field. If no stun.* label is found, then the server
 does not include the ALPN information into the ServerHello.
-.SH =================================
-
+.PP
+=================================
 .SH LIBRARIES
 
 In the lib/ sub\-directory the build process will create TURN client messaging library.
 In the include/ sub\-directory, the necessary include files will be placed.
 The C++ wrapper for the messaging functionality is located in TurnMsgLib.h header.
 An example of C++ code can be found in stunclient.c file.
-.SH =================================
-
+.PP
+=================================
 .SH DOCS
 
 After installation, run the command:
@@ -1122,8 +1142,8 @@ to see the man page.
 .PP
 In the docs/html subdirectory of the original archive tree, you will find the client library
 reference. After the installation, it will be placed in PREFIX/share/doc/\fIturnserver\fP/html.
-.SH =================================
-
+.PP
+=================================
 .SH LOGS
 
 When the \fBTURN Server\fP starts, it makes efforts to create a log file turn_<pid>.log
@@ -1146,8 +1166,8 @@ log messages are sent only to the standard output of the process.
 .PP
 This behavior can be controlled by \fB\-\-log\-file\fP, \fB\-\-syslog\fP and \fB\-\-no\-stdout\-log\fP
 \fIoptions\fP.
-.SH =================================
-
+.PP
+=================================
 .SH HTTPS MANAGEMENT INTERFACE
 
 The \fIturnserver\fP process provides an HTTPS Web access as statistics and basic
@@ -1160,8 +1180,8 @@ populated with the admin user \fBaccount\fP(s). An admin user can be a superuser
 (if not assigned to a particular realm) or a restricted user (if assigned to
 a realm). The restricted admin users can perform only limited actions, within
 their corresponding realms.
-.SH =================================
-
+.PP
+=================================
 .SH TELNET CLI
 
 The \fIturnserver\fP process provides a telnet CLI access as statistics and basic management
@@ -1169,8 +1189,8 @@ interface. By default, the \fIturnserver\fP starts a telnet CLI listener on IP 1
 port 5766. That can be changed by the command\-cline \fIoptions\fP of the \fIturnserver\fP process
 (see \fB\-\-cli\-ip\fP and \fB\-\-cli\-port\fP \fIoptions\fP). The full list of telnet CLI commands is provided
 in "help" command output in the telnet CLI.
-.SH =================================
-
+.PP
+=================================
 .SH CLUSTERS
 
 \fBTURN Server\fP can be a part of the cluster installation. But, to support the "even port" functionality
@@ -1179,8 +1199,8 @@ in "help" command output in the telnet CLI.
 the RTP and RTCP relaying endpoints must be allocated on the same relay IP. It would be possible
 to design a scheme with the application\-level requests forwarding (and we may do that later) but
 it would affect the performance.
-.SH =================================
-
+.PP
+=================================
 .SH FILES
 
 /etc/turnserver.conf
@@ -1192,8 +1212,8 @@ it would affect the performance.
 /var/lib/turn/turndb
 .PP
 /usr/local/etc/turnserver.conf
-.SH =================================
-
+.PP
+=================================
 .SH DIRECTORIES
 
 /usr/local/share/\fIturnserver\fP
@@ -1201,15 +1221,16 @@ it would affect the performance.
 /usr/local/share/doc/\fIturnserver\fP
 .PP
 /usr/local/share/examples/\fIturnserver\fP
-.SH =================================
-
+.PP
+=================================
 .SH STANDARDS
 
 obsolete STUN RFC 3489
 .PP
 new STUN RFC 5389
-.SH TURN RFC 5766
-
+.PP
+TURN RFC 5766
+.PP
 TURN\-TCP extension RFC 6062
 .PP
 TURN IPv6 extension RFC 6156
@@ -1217,13 +1238,14 @@ TURN IPv6 extension RFC 6156
 STUN/TURN test vectors RFC 5769
 .PP
 STUN NAT behavior discovery RFC 5780
-.SH =================================
-
+.PP
+=================================
 .SH SEE ALSO
 
 \fIturnadmin\fP, \fIturnutils\fP
-.SH ======================================
-
+.RE
+.PP
+======================================
 .SS  WEB RESOURCES
 
 project page:
@@ -1237,8 +1259,8 @@ https://github.com/coturn/coturn/wiki
 forum:
 .PP
 https://groups.google.com/forum/?fromgroups=#!forum/turn\-server\-project\-rfc5766\-turn\-server
-.SH ======================================
-
+.PP
+======================================
 .SS  AUTHORS
 
 Oleg Moskalenko <[email protected]>
@@ -1266,5 +1288,9 @@ Mutsutoshi Yoshimoto <[email protected]>
 Federico Pinna <[email protected]>
 .PP
 Bradley T. Hughes <[email protected]>
+.RE
 .PP
-Mihaly Meszaros <[email protected]>
+Mihály Mészáros <[email protected]>
+.SS  ACTIVE MAINTAINERS
+
+Mihály Mészáros <[email protected]>

+ 36 - 30
man/man1/turnutils.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "03 August 2020" "" ""
+.TH TURN 1 "05 January 2021" "" ""
 .SH GENERAL INFORMATION
 
 A set of turnutils_* programs provides some utility functionality to be used
@@ -63,8 +63,8 @@ script in examples/scripts/oauth.sh.
 .RE
 .PP
 
-.SH =====================================
-
+.RS
+=====================================
 .SS  NAME
 \fB
 \fBturnutils_uclient \fP\- this client emulation application is supplied for the test purposes only.
@@ -276,8 +276,8 @@ the ORIGIN STUN attribute value.
 Bandwidth for the bandwidth request in ALLOCATE. The default value is zero.
 .PP
 See the examples in the "examples/scripts" directory.
-.SH ======================================
-
+.PP
+======================================
 .SS  NAME
 \fB
 \fBturnutils_peer \fP\- a simple UDP\-only echo backend server.
@@ -314,8 +314,8 @@ If no listener \fBaddress\fP(es) defined, then it listens on all IPv4 and IPv6 a
 .B
 \fB\-v\fP
 Verbose
-.SH ========================================
-
+.PP
+========================================
 .SS  NAME
 \fB
 \fBturnutils_stunclient \fP\- a basic STUN client.
@@ -354,8 +354,8 @@ and if it finds that the STUN server supports RFC 5780
 requests with different parameters, to demonstrate the NAT discovery capabilities.
 .PP
 This utility does not support the "old" "classic" STUN protocol (RFC 3489).
-.SH =====================================
-
+.PP
+=====================================
 .SS  NAME
 \fB
 \fBturnutils_rfc5769check \fP\- a utility that tests the correctness of STUN protocol implementation.
@@ -380,8 +380,8 @@ check procedure, it is not copied to the installation destination.
 Usage:
 .PP
 $ \fIturnutils_rfc5769check\fP
-.SH =====================================
-
+.PP
+=====================================
 .SS  NAME
 \fB
 \fBturnutils_natdiscovery \fP\- a utility that discovers NAT mapping and filtering
@@ -462,8 +462,8 @@ Used by mapping lifetime behavior discovery
 Usage:
 .PP
 $ \fIturnutils_natdiscovery\fP \fB\-m\fP \fB\-f\fP stun.example.com
-.SH =====================================
-
+.PP
+=====================================
 .SS  NAME
 \fB
 \fBturnutils_oauth \fP\- a utility that helps OAuth access_token generation/encryption and validation/decyption
@@ -568,8 +568,8 @@ stun client hmac algorithm
 Usage:
 .PP
 $ \fIturnutils_natdiscovery\fP
-.SH ===================================
-
+.PP
+===================================
 .SH DOCS
 
 After installation, run the command:
@@ -581,8 +581,8 @@ or in the project root directory:
 $ man \fB\-M\fP man \fIturnutils\fP
 .PP
 to see the man page.
-.SH =====================================
-
+.PP
+=====================================
 .SH FILES
 
 /etc/turnserver.conf
@@ -594,8 +594,8 @@ to see the man page.
 /var/lib/turn/turndb
 .PP
 /usr/local/etc/turnserver.conf
-.SH =================================
-
+.PP
+=================================
 .SH DIRECTORIES
 
 /usr/local/share/\fIturnserver\fP
@@ -603,13 +603,14 @@ to see the man page.
 /usr/local/share/doc/\fIturnserver\fP
 .PP
 /usr/local/share/examples/\fIturnserver\fP
-.SH ===================================
-
+.PP
+===================================
 .SH STANDARDS
 
 new STUN RFC 5389
-.SH TURN RFC 5766
-
+.PP
+TURN RFC 5766
+.PP
 TURN\-TCP extension RFC 6062
 .PP
 TURN IPv6 extension RFC 6156
@@ -617,13 +618,14 @@ TURN IPv6 extension RFC 6156
 STUN/TURN test vectors RFC 5769
 .PP
 STUN NAT behavior discovery RFC 5780
-.SH ====================================
-
+.PP
+====================================
 .SH SEE ALSO
 
 \fIturnserver\fP, \fIturnadmin\fP
-.SH ======================================
-
+.RE
+.PP
+======================================
 .SS  WEB RESOURCES
 
 project page:
@@ -637,8 +639,9 @@ https://github.com/coturn/coturn/wiki
 forum:
 .PP
 https://groups.google.com/forum/?fromgroups=#!forum/turn\-server\-project\-rfc5766\-turn\-server/
-.SH ======================================
-
+.RE
+.PP
+======================================
 .SS  AUTHORS
 
 Oleg Moskalenko <[email protected]>
@@ -667,4 +670,7 @@ Federico Pinna <[email protected]>
 .PP
 Bradley T. Hughes <[email protected]>
 .PP
-Mihaly Meszaros <[email protected]>
+Mihály Mészáros <[email protected]>
+.SS  ACTIVE MAINTAINERS
+
+Mihály Mészáros <[email protected]>

+ 1 - 1
rpm/build.settings.sh

@@ -2,7 +2,7 @@
 
 # Common settings script.
 
-TURNVERSION=4.5.1.3
+TURNVERSION=4.5.2
 BUILDDIR=~/rpmbuild
 ARCH=`uname -p`
 

+ 1 - 1
rpm/turnserver.spec

@@ -1,5 +1,5 @@
 Name:		turnserver
-Version:	4.5.1.3
+Version:	4.5.2
 Release:	0%{dist}
 Summary:	Coturn TURN Server
 

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

@@ -42,9 +42,4 @@
 #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__

+ 27 - 51
src/apps/common/ns_turn_utils.c

@@ -158,42 +158,16 @@ void set_no_stdout_log(int val)
 	no_stdout_log = val;
 }
 
-void turn_log_func_default(TURN_LOG_LEVEL level, const char* format, ...)
-{
-#if !defined(TURN_LOG_FUNC_IMPL)
-	{
-		va_list args;
-		va_start(args,format);
-		vrtpprintf(level, format, args);
-		va_end(args);
-	}
-#endif
+#define MAX_LOG_TIMESTAMP_FORMAT_LEN 48
+static char turn_log_timestamp_format[MAX_LOG_TIMESTAMP_FORMAT_LEN] = "%FT%T%z";
 
-	{
-		va_list args;
-		va_start(args,format);
-#if defined(TURN_LOG_FUNC_IMPL)
-		TURN_LOG_FUNC_IMPL(level,format,args);
-#else
-#define MAX_RTPPRINTF_BUFFER_SIZE (1024)
-		char s[MAX_RTPPRINTF_BUFFER_SIZE+1];
-#undef MAX_RTPPRINTF_BUFFER_SIZE
-		if (level == TURN_LOG_LEVEL_ERROR) {
-			snprintf(s,sizeof(s)-100,"%lu: ERROR: ",(unsigned long)log_time());
-			size_t slen = strlen(s);
-			vsnprintf(s+slen,sizeof(s)-slen-1,format, args);
-			fwrite(s,strlen(s),1,stdout);
-		} else if(!no_stdout_log) {
-			snprintf(s,sizeof(s)-100,"%lu: ",(unsigned long)log_time());
-			size_t slen = strlen(s);
-			vsnprintf(s+slen,sizeof(s)-slen-1,format, args);
-			fwrite(s,strlen(s),1,stdout);
-		}
-#endif
-		va_end(args);
-	}
+void set_turn_log_timestamp_format(char* new_format)
+{
+	strncpy(turn_log_timestamp_format, new_format, MAX_LOG_TIMESTAMP_FORMAT_LEN-1);
 }
 
+int use_new_log_timestamp_format = 0;
+
 void addr_debug_print(int verbose, const ioa_addr *addr, const char* s)
 {
 	if (verbose) {
@@ -512,20 +486,29 @@ static int get_syslog_level(TURN_LOG_LEVEL level)
 	return LOG_INFO;
 }
 
-int vrtpprintf(TURN_LOG_LEVEL level, const char *format, va_list args)
+void turn_log_func_default(TURN_LOG_LEVEL level, const char* format, ...)
 {
+	va_list args;
+	va_start(args,format);
+#if defined(TURN_LOG_FUNC_IMPL)
+	TURN_LOG_FUNC_IMPL(level,format,args);
+#else
 	/* Fix for Issue 24, raised by John Selbie: */
 #define MAX_RTPPRINTF_BUFFER_SIZE (1024)
 	char s[MAX_RTPPRINTF_BUFFER_SIZE+1];
 #undef MAX_RTPPRINTF_BUFFER_SIZE
-
-	size_t sz;
-
-	snprintf(s, sizeof(s), "%lu: ",(unsigned long)log_time());
-	sz=strlen(s);
-	vsnprintf(s+sz, sizeof(s)-1-sz, format, args);
-	s[sizeof(s)-1]=0;
-
+	size_t so_far = 0;
+	if (use_new_log_timestamp_format) {
+		time_t now = time(NULL);
+		so_far += strftime(s, sizeof(s), turn_log_timestamp_format, localtime(&now));
+	} else {
+		so_far += snprintf(s, sizeof(s), "%lu: ", (unsigned long)log_time());
+	}
+	so_far += snprintf(s + so_far, sizeof(s)-100, (level == TURN_LOG_LEVEL_ERROR) ? ": ERROR: " : ": ");
+	so_far += vsnprintf(s + so_far,sizeof(s) - (so_far+1), format, args);
+	/* always write to stdout */
+	fwrite(s, so_far, 1, stdout);
+	/* write to syslog or to log file */
 	if(to_syslog) {
 		syslog(get_syslog_level(level),"%s",s);
 	} else {
@@ -538,16 +521,9 @@ int vrtpprintf(TURN_LOG_LEVEL level, const char *format, va_list args)
 		}
 		log_unlock();
 	}
+#endif
+	va_end(args);
 
-	return 0;
-}
-
-void rtpprintf(const char *format, ...)
-{
-	va_list args;
-	va_start (args, format);
-	vrtpprintf(TURN_LOG_LEVEL_INFO, format, args);
-	va_end (args);
 }
 
 ///////////// ORIGIN ///////////////////

+ 3 - 0
src/apps/common/ns_turn_utils.h

@@ -61,6 +61,8 @@ void set_no_stdout_log(int val);
 void set_log_to_syslog(int val);
 void set_simple_log(int val);
 
+void set_turn_log_timestamp_format(char* new_format);
+
 void turn_log_func_default(TURN_LOG_LEVEL level, const char* format, ...);
 
 void addr_debug_print(int verbose, const ioa_addr *addr, const char* s);
@@ -69,6 +71,7 @@ void addr_debug_print(int verbose, const ioa_addr *addr, const char* s);
 
 extern volatile int _log_time_value_set;
 extern volatile turn_time_t _log_time_value;
+extern int use_new_log_timestamp_format;
 
 void rtpprintf(const char *format, ...);
 int vrtpprintf(TURN_LOG_LEVEL level, const char *format, va_list args);

+ 92 - 0
src/apps/relay/acme.c

@@ -0,0 +1,92 @@
+
+/*
+ * Copyright (C) 2020 Jens Elkner.  All rights reserved.
+ *
+ * License: MIT - see https://opensource.org/licenses/MIT
+ */
+
+#include "acme.h"
+#include "ns_ioalib_impl.h"
+
+#define GET_ACME_PREFIX "GET /.well-known/acme-challenge/"
+#define GET_ACME_PREFIX_LEN 32
+
+static int is_acme_req(char *req, size_t len) {
+	static const char *A = "                                             -  0123456789       ABCDEFGHIJKLMNOPQRSTUVWXYZ    _ abcdefghijklmnopqrstuvwxyz     ";
+	int c, i, k;
+
+	// Check first request line. Should be like: GET path HTTP/1.x
+	if (strncmp(req, GET_ACME_PREFIX, GET_ACME_PREFIX_LEN))
+		return -1;
+	// Usually (for LE) the "method path" is 32 + 43 = 55 chars. But other
+	// implementations may choose longer pathes. We define PATHMAX = 127 chars
+	// to be prepared for "DoS" attacks (STUN msg size max. is ~ 64K).
+	len =- 21;					// min size of trailing headers
+	if (len > 131)
+		len = 131;
+	for (i=GET_ACME_PREFIX_LEN; i < (int) len; i++) {
+		// find the end of the path
+		if (req[i] != ' ')
+			continue;
+		// consider path < 10 chars invalid. Also we wanna see a "trailer".
+		if (i < (GET_ACME_PREFIX_LEN + 10) || strncmp(req + i, " HTTP/1.", 8))
+			return -2;
+		// finally check for allowed chars
+		for (k=GET_ACME_PREFIX_LEN; k < i; k++) {
+			c = req[k];
+			if ((c > 127) || (A[c] == ' '))
+				return -3;
+		}
+		// all checks passed: sufficient for us to answer with a redirect
+		return i;
+	}
+	return -4;		// end of path not found
+}
+
+int try_acme_redirect(char *req, size_t len, const char *url,
+	ioa_socket_handle s)
+{
+	static const char *HTML = 
+		"<html><head><title>301 Moved Permanently</title></head>\
+		<body><h1>301 Moved Permanently</h1></body></html>";
+	char http_response[1024];
+	size_t plen, rlen;
+
+	if (url == NULL || url[0] == '\0' || req == NULL || s == 0 )
+		return 1;
+	if (len < (GET_ACME_PREFIX_LEN + 32) || len > (512 - GET_ACME_PREFIX_LEN)
+			|| (plen = is_acme_req(req, len)) < (GET_ACME_PREFIX_LEN + 1))
+		return 2;
+
+	req[plen] = '\0';
+
+	snprintf(http_response, sizeof(http_response) - 1,
+		"HTTP/1.1 301 Moved Permanently\r\n"
+		"Content-Type: text/html\r\n"
+		"Content-Length: %ld\r\n"
+		"Connection: close\r\n"
+		"Location: %s%s\r\n"
+		"\r\n%s", strlen(HTML), url, req + GET_ACME_PREFIX_LEN, HTML);
+
+	rlen = strlen(http_response);
+
+#ifdef LIBEV_OK
+	ioa_network_buffer_handle nbh_acme = ioa_network_buffer_allocate(s->e);
+	uint8_t *data = ioa_network_buffer_data(nbh_acme);
+	bcopy(http_response, data, rlen);
+	ioa_network_buffer_set_size(nbh_acme, rlen);
+	send_data_from_ioa_socket_nbh(s, NULL, nbh_acme, TTL_IGNORE, TOS_IGNORE, NULL);
+#else
+	if (write(s->fd, http_response, rlen) == -1) {
+		TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,
+			"Sending redirect to '%s%s' failed",url, req + GET_ACME_PREFIX_LEN);
+	} else if (((turn_turnserver *)s->session->server)->verbose) {
+		TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "ACME redirected to %s%s\n",
+			url, req + GET_ACME_PREFIX_LEN);
+	}
+#endif
+
+	req[plen] = ' ';
+
+	return 0;
+}

+ 57 - 0
src/apps/relay/acme.h

@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011, 2012, 2013, 2014 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 __TURN_ACME__
+#define __TURN_ACME__
+
+#include "ns_turn_utils.h"
+#include "ns_turn_server.h"
+#include "apputils.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////// ACME /////////////////////
+
+int try_acme_redirect(char *req, size_t len, const char *url, ioa_socket_handle s);
+
+///////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/// __TURN_ACME__ ///
+

+ 1 - 1
src/apps/relay/dbdrivers/dbd_mongo.c

@@ -1124,7 +1124,7 @@ static void mongo_reread_realms(secrets_list_t * realms_list) {
 								ur_string_map_value_type value =
 										(ur_string_map_value_type) (rval);
 								ur_string_map_put(o_to_realm_new,
-										(const ur_string_map_key_type) _origin,
+										(ur_string_map_key_type) _origin,
 										value);
 								free(_origin);
 							}

+ 1 - 1
src/apps/relay/dbdrivers/dbd_mysql.c

@@ -1048,7 +1048,7 @@ static void mysql_reread_realms(secrets_list_t * realms_list) {
 									char *rval=strdup(row[1]);
 									get_realm(rval);
 									ur_string_map_value_type value = (ur_string_map_value_type)rval;
-									ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) oval, value);
+									ur_string_map_put(o_to_realm_new, (ur_string_map_key_type) oval, value);
 								}
 							}
 						}

+ 1 - 1
src/apps/relay/dbdrivers/dbd_pgsql.c

@@ -758,7 +758,7 @@ static void pgsql_reread_realms(secrets_list_t * realms_list) {
 						if(rval) {
 							get_realm(rval);
 							ur_string_map_value_type value = strdup(rval);
-							ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) oval, value);
+							ur_string_map_put(o_to_realm_new, (ur_string_map_key_type) oval, value);
 						}
 					}
 				}

+ 1 - 1
src/apps/relay/dbdrivers/dbd_redis.c

@@ -1161,7 +1161,7 @@ static void redis_reread_realms(secrets_list_t * realms_list) {
 					} else {
 						get_realm(rget->str);
 						ur_string_map_value_type value = strdup(rget->str);
-						ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) origin, value);
+						ur_string_map_put(o_to_realm_new, (ur_string_map_key_type) origin, value);
 					}
 					turnFreeRedisReply(rget);
 				}

+ 1 - 1
src/apps/relay/dbdrivers/dbd_sqlite.c

@@ -1038,7 +1038,7 @@ static void sqlite_reread_realms(secrets_list_t * realms_list)
 
 						get_realm(rval);
 						ur_string_map_value_type value = rval;
-						ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) oval, value);
+						ur_string_map_put(o_to_realm_new, (ur_string_map_key_type) oval, value);
 
 						free(oval);
 

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

@@ -456,7 +456,7 @@ static int handle_udp_packet(dtls_listener_relay_server_type *server,
 		sm->m.sm.s = s;
 
 		if (s) {
-			if(verbose) {
+			if(verbose && turn_params.log_binding) {
 				uint8_t saddr[129];
 				uint8_t rsaddr[129];
 				addr_to_string(get_local_addr_from_ioa_socket(s),saddr);

+ 251 - 212
src/apps/relay/mainrelay.c

@@ -114,7 +114,7 @@ NULL, PTHREAD_MUTEX_INITIALIZER,
 
 //////////////// Common params ////////////////////
 TURN_VERBOSE_NONE,0,0,0,0,
-"/var/run/turnserver.pid",
+"/var/run/turnserver.pid","",
 DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,0,1,
 0,0,0,0,0,
 "",
@@ -168,7 +168,9 @@ DEFAULT_CPUS_NUMBER,
 0,  /* keep_address_family */
 0,  /* no_auth_pings */
 0,  /* no_dynamic_ip_list */
-0   /* no_dynamic_realms */
+0,  /* no_dynamic_realms */
+
+0   /* log_binding */
 };
 
 //////////////// OpenSSL Init //////////////////////
@@ -603,6 +605,9 @@ 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"
+" --new-log-timestamp				Enable full ISO-8601 timestamp in all logs.\n"
+" --new-log-timestamp-format    	<format>	Set timestamp format (in strftime(1) format)\n"
+" --log-binding					Log STUN binding request. It is now disabled by default to avoid DoS attacks.\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"
@@ -627,6 +632,8 @@ static char Usage[] = "Usage: turnserver [options]\n"
 " --pidfile <\"pid-file-name\">			File name to store the pid of the process.\n"
 "						Default is /var/run/turnserver.pid (if superuser account is used) or\n"
 "						/var/tmp/turnserver.pid .\n"
+" --acme-redirect <URL>				Redirect ACME, i.e. HTTP GET requests matching '^/.well-known/acme-challenge/(.*)' to '<URL>$1'.\n"
+"						Default is '', i.e. no special handling for such requests.\n"
 " --secure-stun					Require authentication of the STUN Binding request.\n"
 "						By default, the clients are allowed anonymous access to the STUN Binding functionality.\n"
 " --proc-user <user-name>			User name to run the turnserver process.\n"
@@ -662,10 +669,6 @@ static char Usage[] = "Usage: turnserver [options]\n"
 "						This value can be changed on-the-fly in CLI. The default value is 256.\n"
 " --ne=[1|2|3]					Set network engine type for the process (for internal purposes).\n"
 " -h						Help\n"
-"\n"
-" For more information, see the wiki pages:\n"
-"\n"
-"	https://github.com/coturn/coturn/wiki/\n"
 "\n";
 
 static char AdminUsage[] = "Usage: turnadmin [command] [options]\n"
@@ -761,6 +764,8 @@ enum EXTRA_OPTS {
 	NO_STDOUT_LOG_OPT,
 	SYSLOG_OPT,
 	SIMPLE_LOG_OPT,
+	NEW_LOG_TIMESTAMP_OPT,
+	NEW_LOG_TIMESTAMP_FORMAT_OPT,
 	AUX_SERVER_OPT,
 	UDP_SELF_BALANCE_OPT,
 	ALTERNATE_SERVER_OPT,
@@ -806,7 +811,9 @@ enum EXTRA_OPTS {
 	OAUTH_OPT,
 	NO_SOFTWARE_ATTRIBUTE_OPT,
 	NO_HTTP_OPT,
-	SECRET_KEY_OPT
+	SECRET_KEY_OPT,
+	ACME_REDIRECT_OPT,
+	LOG_BINDING_OPT
 };
 
 struct myoption {
@@ -899,6 +906,8 @@ static const struct myoption long_options[] = {
 				{ "no-stdout-log", optional_argument, NULL, NO_STDOUT_LOG_OPT },
 				{ "syslog", optional_argument, NULL, SYSLOG_OPT },
 				{ "simple-log", optional_argument, NULL, SIMPLE_LOG_OPT },
+				{ "new-log-timestamp", optional_argument, NULL, NEW_LOG_TIMESTAMP_OPT },
+				{ "new-log-timestamp-format", required_argument, NULL, NEW_LOG_TIMESTAMP_FORMAT_OPT },
 				{ "aux-server", required_argument, NULL, AUX_SERVER_OPT },
 				{ "udp-self-balance", optional_argument, NULL, UDP_SELF_BALANCE_OPT },
 				{ "alternate-server", required_argument, NULL, ALTERNATE_SERVER_OPT },
@@ -938,6 +947,9 @@ static const struct myoption long_options[] = {
 				{ "no-tlsv1_2", optional_argument, NULL, NO_TLSV1_2_OPT },
 				{ "secret-key-file", required_argument, NULL, SECRET_KEY_OPT },
 				{ "keep-address-family", optional_argument, NULL, 'K' },
+				{ "acme-redirect", required_argument, NULL, ACME_REDIRECT_OPT },
+				{ "log-binding", optional_argument, NULL, LOG_BINDING_OPT },
+
 				{ NULL, no_argument, NULL, 0 }
 };
 
@@ -1161,7 +1173,7 @@ static void set_option(int c, char *value)
 	  STRCPY(turn_params.oauth_server_name,value);
 	  break;
   case OAUTH_OPT:
-	  if(!ENC_ALG_NUM) {
+	  if( ENC_ALG_NUM == 0) {
 		  TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: option --oauth is not supported; ignored.\n");
 	  } else {
 		  turn_params.oauth = get_bool_value(value);
@@ -1362,6 +1374,8 @@ static void set_option(int c, char *value)
 						TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"-X : Wrong address format: %s\n",div);
 					} else {
 						ioa_addr_add_mapping(&apub,&apriv);
+						if (add_ip_list_range((const char *)div, NULL, &turn_params.ip_whitelist) == 0)
+							TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Whitelisting external-ip private part: %s\n", div);
 					}
 				}
 				free(nval);
@@ -1581,16 +1595,25 @@ static void set_option(int c, char *value)
 	case PIDFILE_OPT:
 		STRCPY(turn_params.pidfile,value);
 		break;
+	case ACME_REDIRECT_OPT:
+		STRCPY(turn_params.acme_redirect,value);
+		break;
 	case 'C':
 		if(value && *value) {
 			turn_params.rest_api_separator=*value;
 		}
 		break;
+	case LOG_BINDING_OPT:
+		turn_params.log_binding = get_bool_value(value);
+		break;
+
 	/* these options have been already taken care of before: */
 	case 'l':
 	case NO_STDOUT_LOG_OPT:
 	case SYSLOG_OPT:
 	case SIMPLE_LOG_OPT:
+	case NEW_LOG_TIMESTAMP_OPT:
+	case NEW_LOG_TIMESTAMP_FORMAT_OPT:
 	case 'c':
 	case 'n':
 	case 'h':
@@ -1653,25 +1676,25 @@ static void read_config_file(int argc, char **argv, int pass)
 
 	if(pass == 0) {
 
-	  if (argv) {
-	    int i = 0;
-	    for (i = 0; i < argc; i++) {
-	      if (!strcmp(argv[i], "-c")) {
-		if (i < argc - 1) {
-		  STRCPY(config_file, argv[i + 1]);
-		} else {
-		  TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "Wrong usage of -c option\n");
+		if (argv) {
+			int i = 0;
+			for (i = 0; i < argc; i++) {
+				if (!strcmp(argv[i], "-c")) {
+					if (i < argc - 1) {
+						STRCPY(config_file, argv[i + 1]);
+					} else {
+						TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "Wrong usage of -c option\n");
+					}
+				} else if (!strcmp(argv[i], "-n")) {
+					turn_params.do_not_use_config_file = 1;
+					config_file[0]=0;
+					return;
+				} else if (!strcmp(argv[i], "-h")) {
+					printf("\n%s\n",Usage);
+					exit(0);
+				}
+			}
 		}
-	      } else if (!strcmp(argv[i], "-n")) {
-		turn_params.do_not_use_config_file = 1;
-		config_file[0]=0;
-		return;
-	      } else if (!strcmp(argv[i], "-h")) {
-		printf("\n%s\n",Usage);
-		exit(0);
-	      }
-	    }
-	  }
 	}
 
 	if (!turn_params.do_not_use_config_file && config_file[0]) {
@@ -1708,7 +1731,7 @@ static void read_config_file(int argc, char **argv, int pass)
 					STRCPY(sarg, s);
 					if (parse_arg_string(sarg, &c, &value) < 0) {
 						TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "Bad configuration format: %s\n",
-							sarg);
+								sarg);
 					} else if((pass == 0) && (c == 'l')) {
 						set_logfile(value);
 					} else if((pass==0) && (c==NO_STDOUT_LOG_OPT)) {
@@ -1717,10 +1740,14 @@ static void read_config_file(int argc, char **argv, int pass)
 						set_log_to_syslog(get_bool_value(value));
 					} else if((pass==0) && (c==SIMPLE_LOG_OPT)) {
 						set_simple_log(get_bool_value(value));
-					} else if((pass == 0) && (c != 'u')) {
-					  set_option(c, value);
-					} else if((pass > 0) && (c == 'u')) {
-					  set_option(c, value);
+					} else if ((pass==0) && (c==NEW_LOG_TIMESTAMP_OPT)) {
+						use_new_log_timestamp_format=1;
+					} else if ((pass==0) && (c==NEW_LOG_TIMESTAMP_FORMAT_OPT)) {
+						set_turn_log_timestamp_format(value);
+					} else if((pass == 1) && (c != 'u')) {
+						set_option(c, value);
+					} else if((pass == 2) && (c == 'u')) {
+						set_option(c, value);
 					}
 					if (s[slen - 1] == 59) {
 						TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "Check config! The following line ends with semicolon: \"%s\" \n",s);
@@ -1733,7 +1760,7 @@ static void read_config_file(int argc, char **argv, int pass)
 
 		} else
 			TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: Cannot find config file: %s. Default and command-line settings will be used.\n",
-				config_file);
+					config_file);
 
 		if (full_path_to_config_file) {
 			free(full_path_to_config_file);
@@ -1746,7 +1773,7 @@ static int disconnect_database(void)
 {
 	const turn_dbdriver_t * dbd = get_dbdriver();
 	if (dbd && dbd->disconnect) {
-			dbd->disconnect();
+		dbd->disconnect();
 	}
 	return 0;
 }
@@ -1777,183 +1804,183 @@ static int adminmain(int argc, char **argv)
 
 	while (((c = getopt_long(argc, argv, ADMIN_OPTIONS, uo.u.o, NULL)) != -1)) {
 		switch (c){
-        case 'P':
-            if(pwd[0]) {
-                char result[257];
-                generate_new_enc_password((char*)pwd, result);
-                printf("%s\n",result);
-                exit(0);
-            }
-            print_enc_password = 1;
-            break;
-        case 'E':
-            print_enc_aes_password = 1;
-            break;
-        case 'g':
-            ct = TA_SET_REALM_OPTION;
-            break;
-        case 'G':
-            ct = TA_LIST_REALM_OPTIONS;
-            break;
-        case ADMIN_USER_QUOTA_OPT:
-            po.user_quota = (vint)atoi(optarg);
-            break;
-        case ADMIN_TOTAL_QUOTA_OPT:
-            po.total_quota = (vint)atoi(optarg);
-            break;
-        case ADMIN_MAX_BPS_OPT:
-            po.max_bps = (vint)atoi(optarg);
-            break;
-        case 'O':
-            ct = TA_ADD_ORIGIN;
-            break;
-        case 'R':
-            ct = TA_DEL_ORIGIN;
-            break;
-        case 'I':
-            ct = TA_LIST_ORIGINS;
-            break;
-        case 'o':
-            STRCPY(origin,optarg);
-            break;
-        case 'k':
-            ct = TA_PRINT_KEY;
-            break;
-        case 'a':
-            ct = TA_UPDATE_USER;
-            break;
-        case 'd':
-            ct = TA_DELETE_USER;
-            break;
-        case 'A':
-            ct = TA_UPDATE_USER;
-            is_admin = 1;
-            break;
-        case 'D':
-            ct = TA_DELETE_USER;
-            is_admin = 1;
-            break;
-        case 'l':
-            ct = TA_LIST_USERS;
-            break;
-        case 'L':
-            ct = TA_LIST_USERS;
-            is_admin = 1;
-            break;
-        case 's':
-            ct = TA_SET_SECRET;
-            STRCPY(secret,optarg);
-            break;
-        case 'S':
-            ct = TA_SHOW_SECRET;
-            break;
-        case 'X':
-            ct = TA_DEL_SECRET;
-            if(optarg)
-                STRCPY(secret,optarg);
-            break;
-        case DEL_ALL_AUTH_SECRETS_OPT:
-            ct = TA_DEL_SECRET;
-            break;
+			case 'P':
+				if(pwd[0]) {
+					char result[257];
+					generate_new_enc_password((char*)pwd, result);
+					printf("%s\n",result);
+					exit(0);
+				}
+				print_enc_password = 1;
+				break;
+			case 'E':
+				print_enc_aes_password = 1;
+				break;
+			case 'g':
+				ct = TA_SET_REALM_OPTION;
+				break;
+			case 'G':
+				ct = TA_LIST_REALM_OPTIONS;
+				break;
+			case ADMIN_USER_QUOTA_OPT:
+				po.user_quota = (vint)atoi(optarg);
+				break;
+			case ADMIN_TOTAL_QUOTA_OPT:
+				po.total_quota = (vint)atoi(optarg);
+				break;
+			case ADMIN_MAX_BPS_OPT:
+				po.max_bps = (vint)atoi(optarg);
+				break;
+			case 'O':
+				ct = TA_ADD_ORIGIN;
+				break;
+			case 'R':
+				ct = TA_DEL_ORIGIN;
+				break;
+			case 'I':
+				ct = TA_LIST_ORIGINS;
+				break;
+			case 'o':
+				STRCPY(origin,optarg);
+				break;
+			case 'k':
+				ct = TA_PRINT_KEY;
+				break;
+			case 'a':
+				ct = TA_UPDATE_USER;
+				break;
+			case 'd':
+				ct = TA_DELETE_USER;
+				break;
+			case 'A':
+				ct = TA_UPDATE_USER;
+				is_admin = 1;
+				break;
+			case 'D':
+				ct = TA_DELETE_USER;
+				is_admin = 1;
+				break;
+			case 'l':
+				ct = TA_LIST_USERS;
+				break;
+			case 'L':
+				ct = TA_LIST_USERS;
+				is_admin = 1;
+				break;
+			case 's':
+				ct = TA_SET_SECRET;
+				STRCPY(secret,optarg);
+				break;
+			case 'S':
+				ct = TA_SHOW_SECRET;
+				break;
+			case 'X':
+				ct = TA_DEL_SECRET;
+				if(optarg)
+					STRCPY(secret,optarg);
+				break;
+			case DEL_ALL_AUTH_SECRETS_OPT:
+				ct = TA_DEL_SECRET;
+				break;
 #if !defined(TURN_NO_SQLITE)
-		case 'b':
-		  STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg);
-		  turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_SQLITE;
-		  break;
+			case 'b':
+				STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg);
+				turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_SQLITE;
+				break;
 #endif
 #if !defined(TURN_NO_PQ)
-		case 'e':
-		  STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg);
-		  turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_PQ;
-		  break;
+			case 'e':
+				STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg);
+				turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_PQ;
+				break;
 #endif
 #if !defined(TURN_NO_MYSQL)
-		case 'M':
-		  STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg);
-		  turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MYSQL;
-		  break;
+			case 'M':
+				STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg);
+				turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MYSQL;
+				break;
 #endif
 #if !defined(TURN_NO_MONGO)
-		case 'J':
-		  STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg);
-		  turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MONGO;
-		  break;
+			case 'J':
+				STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg);
+				turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MONGO;
+				break;
 #endif
 #if !defined(TURN_NO_HIREDIS)
-		case 'N':
-		  STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg);
-		  turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_REDIS;
-		  break;
-#endif
-        case 'u':
-            STRCPY(user,optarg);
-            if(!is_secure_string((uint8_t*)user,1)) {
-                TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong user name structure or symbols, choose another name: %s\n",user);
-                exit(-1);
-            }
-            if(SASLprep((uint8_t*)user)<0) {
-                TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong user name: %s\n",user);
-                exit(-1);
-            }
-            break;
-        case 'r':
-            set_default_realm_name(optarg);
-            STRCPY(realm,optarg);
-            if(SASLprep((uint8_t*)realm)<0) {
-                TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong realm: %s\n",realm);
-                exit(-1);
-            }
-            break;
-        case 'p':
-            STRCPY(pwd,optarg);
-            if(SASLprep((uint8_t*)pwd)<0) {
-                TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong password: %s\n",pwd);
-                exit(-1);
-            }
-            if(print_enc_password) {
-                char result[257];
-                generate_new_enc_password((char*)pwd, result);
-                printf("%s\n",result);
-                exit(0);
-            }
-            if(print_enc_aes_password){
-				encrypt_aes_128(pwd, generated_key);
-                exit(0);
-            }
-            break;
-        case 'x':
-            generate_aes_128_key(optarg, generated_key);
-            exit(0);
-            break;
-        case 'f':
-            fptr = fopen((char*)optarg, "r");
-            if(fptr == NULL){
-                printf("No such file like %s\n", (char*)optarg);
-            }
-            else{
-				fseek (fptr, 0, SEEK_SET);
-				rc = fread(generated_key, sizeof(char), 16, fptr);
-				if( rc == 0 ){
-					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: Secret-Key file is empty\n",__FUNCTION__);
+			case 'N':
+				STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg);
+				turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_REDIS;
+				break;
+#endif
+			case 'u':
+				STRCPY(user,optarg);
+				if(!is_secure_string((uint8_t*)user,1)) {
+					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong user name structure or symbols, choose another name: %s\n",user);
+					exit(-1);
+				}
+				if(SASLprep((uint8_t*)user)<0) {
+					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong user name: %s\n",user);
+					exit(-1);
+				}
+				break;
+			case 'r':
+				set_default_realm_name(optarg);
+				STRCPY(realm,optarg);
+				if(SASLprep((uint8_t*)realm)<0) {
+					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong realm: %s\n",realm);
+					exit(-1);
+				}
+				break;
+			case 'p':
+				STRCPY(pwd,optarg);
+				if(SASLprep((uint8_t*)pwd)<0) {
+					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong password: %s\n",pwd);
+					exit(-1);
+				}
+				if(print_enc_password) {
+					char result[257];
+					generate_new_enc_password((char*)pwd, result);
+					printf("%s\n",result);
+					exit(0);
+				}
+				if(print_enc_aes_password){
+					encrypt_aes_128(pwd, generated_key);
+					exit(0);
+				}
+				break;
+			case 'x':
+				generate_aes_128_key(optarg, generated_key);
+				exit(0);
+				break;
+			case 'f':
+				fptr = fopen((char*)optarg, "r");
+				if(fptr == NULL){
+					printf("No such file like %s\n", (char*)optarg);
 				}
 				else{
-					if( rc != 16 ){
-						TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: Secret-Key length is not enough\n",__FUNCTION__);
+					fseek (fptr, 0, SEEK_SET);
+					rc = fread(generated_key, sizeof(char), 16, fptr);
+					if( rc == 0 ){
+						TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: Secret-Key file is empty\n",__FUNCTION__);
+					}
+					else{
+						if( rc != 16 ){
+							TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: Secret-Key length is not enough\n",__FUNCTION__);
+						}
 					}
+					fclose (fptr);
 				}
-				fclose (fptr);
-            }
-            break;
-        case 'v':
-			decrypt_aes_128((char*)optarg, generated_key);
-            exit(0);
-        case 'h':
-            printf("\n%s\n", AdminUsage);
-            exit(0);
-            break;
-        default:
-            fprintf(stderr,"\n%s\n", AdminUsage);
-            exit(-1);
+				break;
+			case 'v':
+				decrypt_aes_128((char*)optarg, generated_key);
+				exit(0);
+			case 'h':
+				printf("\n%s\n", AdminUsage);
+				exit(0);
+				break;
+			default:
+				fprintf(stderr,"\n%s\n", AdminUsage);
+				exit(-1);
 		}
 	}
 
@@ -1997,16 +2024,16 @@ static void print_features(unsigned long mfn)
 
 	TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "\n\n==== Show him the instruments, Practical Frost: ====\n\n");
 
-/*
-	Frost stepped forward and opened the polished case with a theatrical
-	flourish. It was a masterful piece of craftsmanship. As the lid was
-	pulled back, the many trays inside lifted and fanned out, displaying
-	Glokta’s tools in all their gruesome glory. There were blades of every
-	size and shape, needles curved and straight, bottles of oil and acid,
-	nails and screws, clamps and pliers, saws, hammers, chisels. Metal, wood
-	and glass glittered in the bright lamplight, all polished to mirror
-	brightness and honed to a murderous sharpness.
-*/
+	/*
+	   Frost stepped forward and opened the polished case with a theatrical
+	   flourish. It was a masterful piece of craftsmanship. As the lid was
+	   pulled back, the many trays inside lifted and fanned out, displaying
+	   Glokta’s tools in all their gruesome glory. There were blades of every
+	   size and shape, needles curved and straight, bottles of oil and acid,
+	   nails and screws, clamps and pliers, saws, hammers, chisels. Metal, wood
+	   and glass glittered in the bright lamplight, all polished to mirror
+	   brightness and honed to a murderous sharpness.
+	   */
 
 #if !TLS_SUPPORTED
 	TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS is not supported\n");
@@ -2031,7 +2058,7 @@ static void print_features(unsigned long mfn)
 	TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TURN/STUN ALPN is not supported\n");
 #endif
 
-	if(!ENC_ALG_NUM) {
+	if(ENC_ALG_NUM == 0) {
 		TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Third-party authorization (oAuth) is not supported\n");
 	} else {
 		TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Third-party authorization (oAuth) supported\n");
@@ -2197,6 +2224,12 @@ int main(int argc, char **argv)
 			case SIMPLE_LOG_OPT:
 				set_simple_log(get_bool_value(optarg));
 				break;
+			case NEW_LOG_TIMESTAMP_OPT:
+				use_new_log_timestamp_format=1;
+				break;
+			case NEW_LOG_TIMESTAMP_FORMAT_OPT:
+				set_turn_log_timestamp_format(optarg);
+				break;
 			default:
 				;
 			}
@@ -2233,8 +2266,10 @@ int main(int argc, char **argv)
 
 	if(strstr(argv[0],"turnadmin"))
 		return adminmain(argc,argv);
-
+	// Zero pass apply the log options.
 	read_config_file(argc,argv,0);
+	// First pass read other config options
+	read_config_file(argc,argv,1);
 
 	struct uoptions uo;
 	uo.u.m = long_options;
@@ -2244,7 +2279,8 @@ int main(int argc, char **argv)
 			set_option(c,optarg);
 	}
 
-	read_config_file(argc,argv,1);
+	// Second pass read -u options
+	read_config_file(argc,argv,2);
 
 	{
 		unsigned long mfn = set_system_parameters(1);
@@ -2259,6 +2295,9 @@ int main(int argc, char **argv)
 	TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Domain name: %s\n",turn_params.domain);
 	TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Default realm: %s\n",get_realm(NULL)->options.name);
 
+	if(turn_params.acme_redirect[0]) {
+		TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "ACME redirect URL: %s\n",turn_params.acme_redirect);
+	}
 	if(turn_params.oauth && turn_params.oauth_server_name[0]) {
 		TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "oAuth server name: %s\n",turn_params.oauth_server_name);
 	}
@@ -2554,7 +2593,7 @@ static int THREAD_setup(void) {
 
 	mutex_buf_initialized = 1;
 
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER <= OPENSSL_VERSION_1_1_1
 	CRYPTO_THREADID_set_callback(coturn_id_function);
 #else
 	CRYPTO_set_id_callback(coturn_id_function);
@@ -2576,7 +2615,7 @@ int THREAD_cleanup(void) {
   if (!mutex_buf_initialized)
     return 0;
 
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER <= OPENSSL_VERSION_1_1_1
 	CRYPTO_THREADID_set_callback(NULL);
 #else
 	CRYPTO_set_id_callback(NULL);

+ 3 - 0
src/apps/relay/mainrelay.h

@@ -219,6 +219,7 @@ typedef struct _turn_params_ {
   int do_not_use_config_file;
 
   char pidfile[1025];
+  char acme_redirect[1025];
 
   ////////////////  Listener server /////////////////
 
@@ -332,6 +333,8 @@ typedef struct _turn_params_ {
   int no_dynamic_ip_list;
   int no_dynamic_realms;
 
+  vint log_binding;
+  
 } turn_params_t;
 
 extern turn_params_t turn_params;

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

@@ -1667,7 +1667,9 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int
 			 allocate_bps,
 			 turn_params.oauth,
 			 turn_params.oauth_server_name,
-			 turn_params.keep_address_family);
+			 turn_params.acme_redirect,
+			 turn_params.keep_address_family,
+			 &turn_params.log_binding);
 	
 	if(to_set_rfc5780) {
 		set_rfc5780(&(rs->server), get_alt_addr, send_message_from_listener_to_client);

+ 109 - 4
src/apps/relay/ns_ioalib_engine_impl.c

@@ -1833,7 +1833,7 @@ int ssl_read(evutil_socket_t fd, SSL* ssl, ioa_network_buffer_handle nbh, int ve
 	BIO* rbio = BIO_new_mem_buf(buffer, old_buffer_len);
 	BIO_set_mem_eof_return(rbio, -1);
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
 	ssl->rbio = rbio;
 #else
 	SSL_set0_rbio(ssl,rbio);
@@ -1928,7 +1928,7 @@ int ssl_read(evutil_socket_t fd, SSL* ssl, ioa_network_buffer_handle nbh, int ve
 	if(ret>0) {
 		ioa_network_buffer_add_offset_size(nbh, (uint16_t)buf_size, 0, (size_t)ret);
 	}
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
 	ssl->rbio = NULL;
 	BIO_free(rbio);
 #else
@@ -2166,6 +2166,101 @@ static TURN_TLS_TYPE check_tentative_tls(ioa_socket_raw fd)
 }
 #endif
 
+
+static size_t proxy_string_field(char *field, size_t max, uint8_t *buf, size_t index, size_t len)
+{
+	size_t count = 0;
+	while((index < len) && (count < max)) {
+		if((0x20 == buf[index]) || (0x0D == buf[index])) {
+			field[count] = 0x00;
+			return ++index;
+		}
+		field[count++] = buf[index++];
+	}
+	return 0;
+}
+
+static ssize_t socket_parse_proxy_v1(ioa_socket_handle s, uint8_t *buf, size_t len)
+{
+	if(len < 11) {
+		return 0 ;
+	}
+
+	/* Check for proxy-v1 magic field */
+	char magic[] = {0x50, 0x52, 0x4F, 0x58, 0x59, 0x20};
+	if(memcmp(magic, buf, sizeof(magic))) {
+		return -1;
+	}
+
+	/* Read family */
+	char tcp4[] = {0x54, 0x43, 0x50, 0x34, 0x20};
+	char tcp6[] = {0x54, 0x43, 0x50, 0x36, 0x20};
+	int family;
+	if(0 == memcmp(tcp4, &buf[6], sizeof(tcp4))) { /* IPv4 */
+		family = AF_INET;
+	} else if(0 == memcmp(tcp6, &buf[6], sizeof(tcp6))) { /* IPv6 */
+		family = AF_INET6;
+	} else {
+		return -1;
+	}
+
+	char saddr[40];
+	char daddr[40];
+	char sport[6];
+	char dport[6];
+
+	size_t tlen = 11;
+	/* Read source address */
+	tlen = proxy_string_field(saddr, sizeof(saddr), buf, tlen, len);
+	if(0 == tlen) return -1;
+
+	/* Read dest address */
+	tlen = proxy_string_field(daddr, sizeof(daddr), buf, tlen, len);
+	if(0 == tlen) return -1;
+
+	/* Read source port */
+	tlen = proxy_string_field(sport, sizeof(sport), buf, tlen, len);
+	if(0 == tlen) return -1;
+
+	/* Read dest port */
+	tlen = proxy_string_field(dport, sizeof(dport), buf, tlen, len);
+	if(0 == tlen) return -1;
+
+	/* Final line feed */
+	if ((len <= tlen) || (0x0A != buf[tlen])) return -1;
+
+	tlen++;
+
+	int sport_int = atoi(sport);
+	int dport_int = atoi(dport);
+	if((sport_int < 0) || (0xFFFF < sport_int)) return -1;
+	if((dport_int < 0) || (0xFFFF < dport_int)) return -1;
+
+	if (AF_INET == family) {
+		struct sockaddr_in remote, local;
+		remote.sin_family = local.sin_family = AF_INET;
+		if(1 != inet_pton(AF_INET, saddr, &remote.sin_addr.s_addr)) return -1;
+		if(1 != inet_pton(AF_INET, daddr, &local.sin_addr.s_addr)) return -1;
+		remote.sin_port = htons((uint16_t)sport_int);
+		local.sin_port = htons((uint16_t)dport_int);
+
+		addr_cpy4(&(s->local_addr),  &local);
+		addr_cpy4(&(s->remote_addr), &remote);
+
+	} else {
+		struct sockaddr_in6 remote, local;
+		remote.sin6_family = local.sin6_family = AF_INET6;
+		if(1 != inet_pton(AF_INET6, saddr, &remote.sin6_addr.s6_addr)) return -1;
+		if(1 != inet_pton(AF_INET6, daddr, &local.sin6_addr.s6_addr)) return -1;
+		remote.sin6_port = htons((uint16_t)sport_int);
+		local.sin6_port = htons((uint16_t)dport_int);
+
+		addr_cpy6(&(s->local_addr),  &local);
+		addr_cpy6(&(s->remote_addr), &remote);
+	}
+	return tlen;
+}
+
 static ssize_t socket_parse_proxy_v2(ioa_socket_handle s, uint8_t *buf, size_t len)
 {
 	if(len < 16){
@@ -2227,6 +2322,16 @@ static ssize_t socket_parse_proxy_v2(ioa_socket_handle s, uint8_t *buf, size_t l
 	return tlen;
 }
 
+static ssize_t socket_parse_proxy(ioa_socket_handle s, uint8_t *buf, size_t len)
+{
+	ssize_t tlen = socket_parse_proxy_v2(s, buf, len);
+	if(-1 == tlen) {
+		tlen = socket_parse_proxy_v1(s, buf, len);
+	}
+
+	return tlen;
+}
+
 static int socket_input_worker(ioa_socket_handle s)
 {
 	int len = 0;
@@ -2450,7 +2555,7 @@ static int socket_input_worker(ioa_socket_handle s)
 				  blen=(ev_ssize_t)STUN_BUFFER_SIZE;
 
 				if(s->st == TCP_SOCKET_PROXY){
-					ssize_t tlen = socket_parse_proxy_v2(s, buf_elem->buf.buf, blen);
+					ssize_t tlen = socket_parse_proxy(s, buf_elem->buf.buf, blen);
 					blen = 0;
 					if (tlen < 0){
 						s->tobeclosed = 1;
@@ -3374,7 +3479,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in
 						}
 					} else {
 #if TLS_SUPPORTED
-						if(check_tentative_tls(s->fd)) {
+						if((s->sat != TCP_CLIENT_DATA_SOCKET) && (s->sat != TCP_RELAY_DATA_SOCKET) && check_tentative_tls(s->fd)) {
 							s->tobeclosed = 1;
 							return -1;
 						}

+ 41 - 55
src/client++/TurnMsgLib.h

@@ -75,7 +75,7 @@ public:
 	/**
 	 * Iterator constructor: creates iterator on raw messagebuffer.
 	 */
-	StunAttrIterator(uint8_t *buf, size_t sz) throw (WrongStunBufferFormatException) :
+	StunAttrIterator(uint8_t *buf, size_t sz) :
 		_buf(buf), _sz(sz)  {
 		if(!stun_is_command_message_str(_buf, _sz)) {
 			throw WrongStunBufferFormatException();
@@ -87,7 +87,7 @@ public:
 	 * Iterator constructor: create iterator over message.
 	 */
 	template<class T>
-	StunAttrIterator(T &msg) throw (WrongStunBufferFormatException) :
+	StunAttrIterator(T &msg) :
 		_buf(msg.getRawBuffer()), _sz(msg.getSize())  {
 		if(!stun_is_command_message_str(_buf, _sz)) {
 			throw WrongStunBufferFormatException();
@@ -99,7 +99,7 @@ public:
 	 * Iterator constructor: creates iterator over raw buffer, starting from first
 	 * location of an attribute of particular type.
 	 */
-	StunAttrIterator(uint8_t *buf, size_t sz, uint16_t attr_type) throw (WrongStunBufferFormatException) :
+	StunAttrIterator(uint8_t *buf, size_t sz, uint16_t attr_type) :
 			_buf(buf), _sz(sz)  {
 		if(!stun_is_command_message_str(_buf, _sz)) {
 			throw WrongStunBufferFormatException();
@@ -112,7 +112,7 @@ public:
 	 * location of an attribute of particular type.
 	 */
 	template<class T>
-	StunAttrIterator(T &msg, uint16_t attr_type) throw (WrongStunBufferFormatException) :
+	StunAttrIterator(T &msg, uint16_t attr_type) :
 			_buf(msg.getRawBuffer()), _sz(msg.getSize())  {
 		if(!stun_is_command_message_str(_buf, _sz)) {
 			throw WrongStunBufferFormatException();
@@ -123,7 +123,7 @@ public:
 	/**
 	 * Moves iterator to next attribute location
 	 */
-	void next() throw(EndOfStunMsgException) {
+	void next() {
 		if(!_sar) {
 			throw EndOfStunMsgException();
 		}
@@ -167,7 +167,7 @@ public:
 	 * Return raw memroy field of the attribute value.
 	 * If the attribute value length is zero (0), then return NULL.
 	 */
-	const uint8_t *getRawBuffer(size_t &sz) const throw(WrongStunAttrFormatException) {
+	const uint8_t *getRawBuffer(size_t &sz) const {
 		int len = stun_attr_get_len(_sar);
 		if(len<0)
 			throw WrongStunAttrFormatException();
@@ -196,7 +196,7 @@ public:
 	/**
 	 * Constructs attribute from iterator
 	 */
-	StunAttr(const StunAttrIterator &iter) throw(WrongStunAttrFormatException, EndOfStunMsgException) {
+	StunAttr(const StunAttrIterator &iter) {
 		if(iter.eof()) {
 			throw EndOfStunMsgException();
 		}
@@ -219,7 +219,7 @@ public:
 	 */
 	virtual ~StunAttr() {
 		if(_value)
-			free(_value,_sz);
+			free(_value);
 	}
 
 	/**
@@ -233,11 +233,11 @@ public:
 	/**
 	 * Set raw data value
 	 */
-	void setRawValue(uint8_t *value, size_t sz) throw(WrongStunAttrFormatException) {
+	void setRawValue(uint8_t *value, size_t sz) {
 		if(sz>0xFFFF)
 			throw WrongStunAttrFormatException();
 		if(_value)
-			free(_value,_sz);
+			free(_value);
 		_sz = sz;
 		_value=(uint8_t*)malloc(_sz);
 		if(value)
@@ -262,7 +262,7 @@ public:
 	 * Add attribute to a message
 	 */
 	template<class T>
-	int addToMsg(T &msg) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
+	int addToMsg(T &msg) {
 		if(!_attr_type)
 			throw WrongStunAttrFormatException();
 		uint8_t *buffer = msg.getRawBuffer();
@@ -281,7 +281,7 @@ protected:
 	/**
 	 * Virtual function member to add attribute to a raw buffer
 	 */
-	virtual int addToBuffer(uint8_t *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
+	virtual int addToBuffer(uint8_t *buffer, size_t &sz) {
 		if(buffer) {
 			if(!_value)
 				throw WrongStunAttrFormatException();
@@ -313,8 +313,7 @@ public:
 	StunAttrChannelNumber() : _cn(0) {
 		setType(STUN_ATTRIBUTE_CHANNEL_NUMBER);
 	}
-	StunAttrChannelNumber(const StunAttrIterator &iter)
-		throw(WrongStunAttrFormatException, EndOfStunMsgException) :
+	StunAttrChannelNumber(const StunAttrIterator &iter) :
 		StunAttr(iter) {
 
 		if(iter.eof())
@@ -331,7 +330,7 @@ public:
 		_cn = cn;
 	}
 protected:
-	virtual int addToBuffer(uint8_t *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
+	virtual int addToBuffer(uint8_t *buffer, size_t &sz) {
 		return stun_attr_add_channel_number_str(buffer,&sz,_cn);
 	}
 private:
@@ -346,8 +345,7 @@ public:
 	StunAttrEvenPort() : _ep(0) {
 		setType(STUN_ATTRIBUTE_EVEN_PORT);
 	}
-	StunAttrEvenPort(const StunAttrIterator &iter)
-		throw(WrongStunAttrFormatException, EndOfStunMsgException) :
+	StunAttrEvenPort(const StunAttrIterator &iter) :
 		StunAttr(iter) {
 
 		if(iter.eof())
@@ -362,7 +360,7 @@ public:
 		_ep = ep;
 	}
 protected:
-	virtual int addToBuffer(uint8_t *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
+	virtual int addToBuffer(uint8_t *buffer, size_t &sz) {
 		return stun_attr_add_str(buffer, &sz, STUN_ATTRIBUTE_EVEN_PORT, &_ep, 1);
 	}
 private:
@@ -377,8 +375,7 @@ public:
 	StunAttrReservationToken() : _rt(0) {
 		setType(STUN_ATTRIBUTE_RESERVATION_TOKEN);
 	}
-	StunAttrReservationToken(const StunAttrIterator &iter)
-		throw(WrongStunAttrFormatException, EndOfStunMsgException) :
+	StunAttrReservationToken(const StunAttrIterator &iter) :
 		StunAttr(iter) {
 
 		if(iter.eof())
@@ -393,7 +390,7 @@ public:
 		_rt = rt;
 	}
 protected:
-	virtual int addToBuffer(uint8_t *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
+	virtual int addToBuffer(uint8_t *buffer, size_t &sz) {
 		uint64_t reservation_token = ioa_ntoh64(_rt);
 		return stun_attr_add_str(buffer, &sz, STUN_ATTRIBUTE_RESERVATION_TOKEN, (uint8_t*) (&reservation_token), 8);
 	}
@@ -410,8 +407,7 @@ public:
 		addr_set_any(&_addr);
 		setType(attr_type);
 	}
-	StunAttrAddr(const StunAttrIterator &iter)
-		throw(WrongStunAttrFormatException, EndOfStunMsgException) :
+	StunAttrAddr(const StunAttrIterator &iter) :
 		StunAttr(iter) {
 
 		if(iter.eof())
@@ -430,7 +426,7 @@ public:
 		addr_cpy(&_addr,&addr);
 	}
 protected:
-	virtual int addToBuffer(uint8_t *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
+	virtual int addToBuffer(uint8_t *buffer, size_t &sz) {
 		return stun_attr_add_addr_str(buffer, &sz, getType(), &_addr);
 	}
 private:
@@ -445,8 +441,7 @@ public:
 	StunAttrChangeRequest() : _changeIp(0), _changePort(0) {
 		setType(STUN_ATTRIBUTE_CHANGE_REQUEST);
 	}
-	StunAttrChangeRequest(const StunAttrIterator &iter)
-		throw(WrongStunAttrFormatException, EndOfStunMsgException) :
+	StunAttrChangeRequest(const StunAttrIterator &iter) :
 		StunAttr(iter) {
 
 		if(iter.eof())
@@ -476,7 +471,7 @@ public:
 			_changePort = 0;
 	}
 protected:
-	virtual int addToBuffer(uint8_t *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
+	virtual int addToBuffer(uint8_t *buffer, size_t &sz) {
 		return stun_attr_add_change_request_str(buffer, &sz, _changeIp, _changePort);
 	}
 private:
@@ -492,8 +487,7 @@ public:
 	StunAttrResponsePort() : _rp(0) {
 		setType(STUN_ATTRIBUTE_RESPONSE_PORT);
 	}
-	StunAttrResponsePort(const StunAttrIterator &iter)
-		throw(WrongStunAttrFormatException, EndOfStunMsgException) :
+	StunAttrResponsePort(const StunAttrIterator &iter) :
 		StunAttr(iter) {
 
 		if(iter.eof())
@@ -513,7 +507,7 @@ public:
 		_rp = p;
 	}
 protected:
-	virtual int addToBuffer(uint8_t *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
+	virtual int addToBuffer(uint8_t *buffer, size_t &sz) {
 		return stun_attr_add_response_port_str(buffer, &sz, _rp);
 	}
 private:
@@ -528,8 +522,7 @@ public:
 	StunAttrPadding() : _p(0) {
 		setType(STUN_ATTRIBUTE_PADDING);
 	}
-	StunAttrPadding(const StunAttrIterator &iter)
-		throw(WrongStunAttrFormatException, EndOfStunMsgException) :
+	StunAttrPadding(const StunAttrIterator &iter) :
 		StunAttr(iter) {
 
 		if(iter.eof())
@@ -552,7 +545,7 @@ public:
 		_p = p;
 	}
 protected:
-	virtual int addToBuffer(uint8_t *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
+	virtual int addToBuffer(uint8_t *buffer, size_t &sz) {
 		return stun_attr_add_padding_str(buffer, &sz, _p);
 	}
 private:
@@ -588,7 +581,7 @@ public:
 	 */
 	virtual ~StunMsg() {
 		if(_deallocate && _buffer) {
-			free(_buffer, _allocated_sz);
+			free(_buffer);
 		}
 	}
 
@@ -623,7 +616,7 @@ public:
 	/**
 	 * Set message size
 	 */
-	void setSize(size_t sz) throw(WrongStunBufferFormatException) {
+	void setSize(size_t sz) {
 		if(sz>_allocated_sz)
 			throw WrongStunBufferFormatException();
 		_sz = sz;
@@ -700,14 +693,14 @@ public:
 	/**
 	 * Add attribute to the message
 	 */
-	int addAttr(StunAttr &attr) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
+	int addAttr(StunAttr &attr) {
 		return attr.addToMsg(*this);
 	}
 
 	/**
 	 * Get transaction ID
 	 */
-	virtual stun_tid getTid() const throw(WrongStunBufferFormatException) {
+	virtual stun_tid getTid() const {
 		if(!_constructed || !isCommand())
 			throw WrongStunBufferFormatException();
 		stun_tid tid;
@@ -718,7 +711,7 @@ public:
 	/**
 	 * Set transaction ID
 	 */
-	virtual void setTid(stun_tid &tid) throw(WrongStunBufferFormatException) {
+	virtual void setTid(stun_tid &tid) {
 		if(!_constructed || !isCommand())
 			throw WrongStunBufferFormatException();
 		stun_tid_message_cpy(_buffer, &tid);
@@ -727,7 +720,7 @@ public:
 	/**
 	 * Add fingerprint to the message
 	 */
-	void addFingerprint() throw(WrongStunBufferFormatException) {
+	void addFingerprint() {
 		if(!_constructed || !isCommand())
 			throw WrongStunBufferFormatException();
 		stun_attr_add_fingerprint_str(_buffer,&_sz);
@@ -736,8 +729,7 @@ public:
 	/**
 	 * Check message integrity, in secure communications.
 	 */
-	bool checkMessageIntegrity(turn_credential_type ct, std::string &uname, std::string &realm, std::string &upwd) const
-		throw(WrongStunBufferFormatException) {
+	bool checkMessageIntegrity(turn_credential_type ct, std::string &uname, std::string &realm, std::string &upwd) const {
 		if(!_constructed || !isCommand())
 			throw WrongStunBufferFormatException();
 		uint8_t *suname=(uint8_t*)strdup(uname.c_str());
@@ -754,8 +746,7 @@ public:
 	/**
 	 * Adds long-term message integrity data to the message.
 	 */
-	void addLTMessageIntegrity(std::string &uname, std::string &realm, std::string &upwd, std::string &nonce)
-		throw(WrongStunBufferFormatException) {
+	void addLTMessageIntegrity(std::string &uname, std::string &realm, std::string &upwd, std::string &nonce) {
 
 		if(!_constructed || !isCommand())
 			throw WrongStunBufferFormatException();
@@ -776,8 +767,7 @@ public:
 	/**
 	 * Adds short-term message integrity data to the message.
 	 */
-	void addSTMessageIntegrity(std::string &uname, std::string &upwd)
-		throw(WrongStunBufferFormatException) {
+	void addSTMessageIntegrity(std::string &uname, std::string &upwd) {
 
 		if(!_constructed || !isCommand())
 			throw WrongStunBufferFormatException();
@@ -808,8 +798,7 @@ protected:
 class StunMsgRequest : public StunMsg {
 public:
 	StunMsgRequest(uint16_t method) : _method(method) {};
-	StunMsgRequest(uint8_t *buffer, size_t total_sz, size_t sz, bool constructed)
-		throw(WrongStunBufferFormatException) :
+	StunMsgRequest(uint8_t *buffer, size_t total_sz, size_t sz, bool constructed) :
 			StunMsg(buffer,total_sz,sz,constructed),_method(0) {
 
 		if(constructed) {
@@ -893,8 +882,7 @@ public:
 		_method(method), _err(error_code), _reason(reason), _tid(tid) {
 
 	};
-	StunMsgResponse(uint8_t *buffer, size_t total_sz, size_t sz, bool constructed)
-		throw(WrongStunBufferFormatException) :
+	StunMsgResponse(uint8_t *buffer, size_t total_sz, size_t sz, bool constructed) :
 			StunMsg(buffer,total_sz,sz,constructed),_method(0),_err(0),_reason("") {
 
 		if(constructed) {
@@ -949,14 +937,14 @@ public:
 	/**
 	 * Set transaction ID
 	 */
-	void setTid(stun_tid &tid) throw(WrongStunBufferFormatException) {
+	void setTid(stun_tid &tid) {
 		_tid = tid;
 	}
 
 	/**
 	 * Get transaction ID
 	 */
-	virtual stun_tid getTid() const throw(WrongStunBufferFormatException) {
+	virtual stun_tid getTid() const {
 		return _tid;
 	}
 
@@ -1074,8 +1062,7 @@ private:
 class StunMsgIndication : public StunMsg {
 public:
 	StunMsgIndication(uint16_t method) : _method(method) {};
-	StunMsgIndication(uint8_t *buffer, size_t total_sz, size_t sz, bool constructed)
-		throw(WrongStunBufferFormatException) :
+	StunMsgIndication(uint8_t *buffer, size_t total_sz, size_t sz, bool constructed) :
 			StunMsg(buffer,total_sz,sz,constructed),_method(0) {
 
 		if(constructed) {
@@ -1123,8 +1110,7 @@ private:
 class StunMsgChannel : public StunMsg {
 public:
 	StunMsgChannel(uint16_t cn, int length) : _cn(cn), _len(length) {};
-	StunMsgChannel(uint8_t *buffer, size_t total_sz, size_t sz, bool constructed)
-		throw(WrongStunBufferFormatException) :
+	StunMsgChannel(uint8_t *buffer, size_t total_sz, size_t sz, bool constructed) :
 			StunMsg(buffer,total_sz,sz,constructed),_cn(0) {
 
 		if(constructed) {

+ 2 - 2
src/client/ns_turn_msg.c

@@ -244,7 +244,7 @@ int stun_produce_integrity_key_str(const uint8_t *uname, const uint8_t *realm, c
 		unsigned int keylen = 0;
 		EVP_MD_CTX ctx;
 		EVP_MD_CTX_init(&ctx);
-#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
+#if defined EVP_MD_CTX_FLAG_NON_FIPS_ALLOW && !defined(LIBRESSL_VERSION_NUMBER)
 		if (FIPS_mode()) {
 			EVP_MD_CTX_set_flags(&ctx,EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
 		}
@@ -256,7 +256,7 @@ int stun_produce_integrity_key_str(const uint8_t *uname, const uint8_t *realm, c
 #else
 		unsigned int keylen = 0;
 		EVP_MD_CTX *ctx = EVP_MD_CTX_new();
-#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
+#if defined EVP_MD_CTX_FLAG_NON_FIPS_ALLOW && ! defined(LIBRESSL_VERSION_NUMBER)
 		if (FIPS_mode()) {
 			EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
 		}

+ 5 - 1
src/ns_turn_defs.h

@@ -31,7 +31,7 @@
 #ifndef __IOADEFS__
 #define __IOADEFS__
 
-#define TURN_SERVER_VERSION "4.5.1.3"
+#define TURN_SERVER_VERSION "4.5.2"
 #define TURN_SERVER_VERSION_NAME "dan Eider"
 #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'"
 
@@ -39,6 +39,10 @@
 #include <sys/param.h>
 #endif
 
+#if defined(__APPLE__) || defined(__DARWIN__) || defined(__MACH__)
+#define __APPLE_USE_RFC_3542
+#endif
+
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>

+ 8 - 0
src/server/ns_turn_ioalib.h

@@ -286,6 +286,14 @@ int get_default_protocol_port(const char* scheme, size_t slen);
 
 void handle_http_echo(ioa_socket_handle s);
 
+///////////// ACME /////////////////////
+
+int try_acme_redirect(char *req, size_t len, const char *url, ioa_socket_handle s);
+
+///////////// ACME /////////////////////
+
+int try_acme_redirect(char *req, size_t len, const char *url, ioa_socket_handle s);
+
 ///////////////////////////////////////
 
 #ifdef __cplusplus

+ 28 - 10
src/server/ns_turn_server.c

@@ -3832,13 +3832,13 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss,
 							&dest_changed, &response_destination,
 							0, 0);
 
-				if(server->verbose) {
+				if(server->verbose && server->log_binding) {
 				  log_method(ss, "BINDING", err_code, reason);
 				}
 
 				if(*resp_constructed && !err_code && (origin_changed || dest_changed)) {
 
-					if (server->verbose) {
+					if (server->verbose && server->log_binding) {
 						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "RFC 5780 request successfully processed\n");
 					}
 
@@ -4014,7 +4014,7 @@ static int handle_old_stun_command(turn_turnserver *server, ts_ur_super_session
 						&dest_changed, &response_destination,
 						cookie,1);
 
-			if(server->verbose) {
+			if(server->verbose && *(server->log_binding)) {
 			  log_method(ss, "OLD BINDING", err_code, reason);
 			}
 
@@ -4624,14 +4624,27 @@ static int read_client_connection(turn_turnserver *server,
 	} else {
 		SOCKET_TYPE st = get_ioa_socket_type(ss->client_socket);
 		if(is_stream_socket(st)) {
-			if(is_http((char*)ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh))) {
+			if(is_http((char*)ioa_network_buffer_data(in_buffer->nbh),
+			ioa_network_buffer_get_size(in_buffer->nbh))) {
+
 				const char *proto = "HTTP";
-				ioa_network_buffer_data(in_buffer->nbh)[ioa_network_buffer_get_size(in_buffer->nbh)] = 0;
-				if (*server->web_admin_listen_on_workers) {
+				if ((st == TCP_SOCKET) &&
+					(
+						try_acme_redirect(
+							(char*)ioa_network_buffer_data(in_buffer->nbh),
+							ioa_network_buffer_get_size(in_buffer->nbh),
+							server->acme_redirect,
+							ss->client_socket
+						) == 0
+					)
+				) {
+					ss->to_be_closed = 1;
+					return 0;
+				} else if (*server->web_admin_listen_on_workers) {
 					if(st==TLS_SOCKET) {
 						proto = "HTTPS";
 						set_ioa_socket_app_type(ss->client_socket,HTTPS_CLIENT_SOCKET);
-						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s (%s %s) request: %s\n", __FUNCTION__, proto, get_ioa_socket_cipher(ss->client_socket), get_ioa_socket_ssl_method(ss->client_socket), (char*)ioa_network_buffer_data(in_buffer->nbh));
+						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s (%s %s) request: %s\n", __FUNCTION__, proto, get_ioa_socket_cipher(ss->client_socket), get_ioa_socket_ssl_method(ss->client_socket), ioa_network_buffer_get_size(in_buffer->nbh));
 						if(server->send_https_socket) {
 							TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s socket to be detached: 0x%lx, st=%d, sat=%d\n", __FUNCTION__,(long)ss->client_socket, get_ioa_socket_type(ss->client_socket), get_ioa_socket_app_type(ss->client_socket));
 							ioa_socket_handle new_s = detach_ioa_socket(ss->client_socket);
@@ -4644,7 +4657,7 @@ static int read_client_connection(turn_turnserver *server,
 					} else {
 						set_ioa_socket_app_type(ss->client_socket,HTTP_CLIENT_SOCKET);
 						if(server->verbose) {
-							TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s request: %s\n", __FUNCTION__, proto, (char*)ioa_network_buffer_data(in_buffer->nbh));
+							TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s request: %s\n", __FUNCTION__, proto, ioa_network_buffer_get_size(in_buffer->nbh));
 						}
 						handle_http_echo(ss->client_socket);
 					}
@@ -4901,7 +4914,7 @@ void init_turn_server(turn_turnserver* server,
 		vintp stun_only,
 		vintp no_stun,
 		vintp no_software_attribute,
-    vintp web_admin_listen_on_workers,
+		vintp web_admin_listen_on_workers,
 		turn_server_addrs_list_t *alternate_servers_list,
 		turn_server_addrs_list_t *tls_alternate_servers_list,
 		turn_server_addrs_list_t *aux_servers_list,
@@ -4915,7 +4928,9 @@ void init_turn_server(turn_turnserver* server,
 		allocate_bps_cb allocate_bps_func,
 		int oauth,
 		const char* oauth_server_name,
-		int keep_address_family) {
+		const char* acme_redirect,
+		int keep_address_family,
+		vintp log_binding) {
 
 	if (!server)
 		return;
@@ -4944,6 +4959,7 @@ void init_turn_server(turn_turnserver* server,
 		server->oauth_server_name = oauth_server_name;
 	if(mobility)
 		server->mobile_connections_map = ur_map_create();
+	server->acme_redirect = acme_redirect;
 
 	TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"turn server id=%d created\n",(int)id);
 
@@ -4986,6 +5002,8 @@ void init_turn_server(turn_turnserver* server,
 	server->keep_address_family = keep_address_family;
 
 	set_ioa_timer(server->e, 1, 0, timer_timeout_handler, server, 1, "timer_timeout_handler");
+
+	server->log_binding = log_binding;
 }
 
 ioa_engine_handle turn_server_get_engine(turn_turnserver *s) {

+ 9 - 1
src/server/ns_turn_server.h

@@ -171,8 +171,14 @@ struct _turn_turnserver {
 	int oauth;
 	const char* oauth_server_name;
 
+	/* ACME redirect URL */
+	const char* acme_redirect;
+
 	/* Keep Address Family */
 	int keep_address_family;
+
+	/* Log Binding Requrest */
+	vintp log_binding;
 };
 
 const char * get_version(turn_turnserver *server);
@@ -218,7 +224,9 @@ void init_turn_server(turn_turnserver* server,
 				    allocate_bps_cb allocate_bps_func,
 				    int oauth,
 				    const char* oauth_server_name,
-					int keep_address_family);
+					const char* acme_redirect,
+					int keep_address_family,
+					vintp log_binding);
 
 ioa_engine_handle turn_server_get_engine(turn_turnserver *s);