diff --git a/AUTHORS b/AUTHORS index 5d2b4538..fffbc68d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -52,6 +52,6 @@ Bradley T. Hughes : FreeBSD port (since v4.1.2.1) -Mészáros Mihály : +Mészáros Mihály : OAuth utility, NAT behavior Discovery (since v4.5.0.4) diff --git a/ChangeLog b/ChangeLog index d9821135..8a5767b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +27/09/2018 Oleg Moskalenko Mihály Mészáros +Version 4.5.0.9 'dan Eider': + +27/09/2018 Oleg Moskalenko Mihály Mészáros +Version 4.5.0.8 'dan Eider': + - Travis CI integration + - to avoid warnings add compiler comment hint to fallthrough + - reload-tls-certs PR#236 (by Arne Georg Gisnås Gleditsch) + - minor fixes PR#223 (by Pavel Kretov) + move rm Makefile to distclean + list all phony targets + - Fix typo PR#253 (by Orsiris de Jong) + - Fix stuck IPv6 connections. (issue #217) + THX to damencho, vol4iniche + - Spelling fixes. + - Add a warning if --lt-cred-mech and --use-auth-secret both presents. + - Revert "Add the realm parameter in the example config file (by Domenico)" + - Fix for Verbose config file option -v cli option override + - Add a Notice to config about realm default value is the domain name. + - Update total allocation usage on client shutdown + - Fix total and user quota mix-up + - Fixed typos in postinstall.txt (by Prashanth Rajaram) + - MySQL password encryption (by Mustafa Bingül & Erdem Duman) + - Do not write to log before logging configuration is read from a config file (by eiver) + - Add more explanation on use-auth-secret / REST in example config (by Krithin Sitaram) + - Add a Warning if lines in config file ends with semicolon (by heyheyjc) + - Fix --prod pointer bug + - Fix auth server thread detach race (by weishuyin) + - New Feature: Add -K --keep-address-family + Be aware if you enable it, then it breaks rfc6156 section 4.2 (default IPv4 family fallback) + - Fix dtls double free crash + - Fix compilation errors and warnings (by Oleg) + 12/10/2017 Oleg Moskalenko Version 4.5.0.7 'dan Eider': - Misc security improvements. diff --git a/INSTALL b/INSTALL index 7e2cf991..6b7a4ba9 100644 --- a/INSTALL +++ b/INSTALL @@ -965,7 +965,7 @@ the root account. 4) Create database 'coturn' (for example) and grant privileges to user 'turn': - > create database coturn; + > create database coturn character set latin1; > grant all on coturn.* to 'turn'@'localhost'; > flush privileges; Ctrl-D diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..a01e8052 --- /dev/null +++ b/Makefile @@ -0,0 +1,261 @@ +################################# +# Generated by configure script # +################################# +ECHO_CMD = echo +CC = cc +LDFLAGS += -L/usr/local/lib/ -L/usr/local/lib/ -lrt -lintl -pthread -lcrypto -lssl -levent_core -levent_extra -levent_openssl -levent_pthreads -lsqlite3 -Wl,-rpath,/usr/local/lib/ -Wl,-rpath,/usr/local/lib/ -Wl,-rpath,/usr/local/lib/postgresql -Wl,-rpath,/usr/local/lib/postgresql -Wl,-rpath,/usr/local/lib/mysql -Wl,-rpath,/usr/local/lib/mysql -Wl,-rpath,/usr/local/lib +DBLIBS += -lsqlite3 -L/usr/local/lib/ -L/usr/local/lib/ -lrt -lintl -pthread -lcrypto -lssl -levent_core -levent_extra -levent_openssl -levent_pthreads -lsqlite3 -L/usr/local/lib/postgresql -L/usr/local/lib/postgresql -lpq -L/usr/local/lib/ -L/usr/local/lib/ -lrt -lintl -pthread -lcrypto -lssl -levent_core -levent_extra -levent_openssl -levent_pthreads -lsqlite3 -L/usr/local/lib/mysql -L/usr/local/lib/mysql -lmysqlclient -lmongoc-1.0 -lbson-1.0 -lhiredis +CFLAGS += -g -Wall -Wno-deprecated-declarations -Wextra -Wformat-security -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wcast-qual -I/usr/local/include -I/usr/local/include/ -I/usr/local/include -DTURN_HAS_SIN_LEN -DTURN_HAS_DAEMON -DTURN_SCTP_INCLUDE="" -DINSTALL_PREFIX=/usr/local -DTURNDB=/usr/local/var/db/turndb +CPPFLAGS = +DBCFLAGS += -I/usr/local/pgsql/include -I/usr/local/include/pgsql/ -I/usr/local/include/postgres/ -I/usr/local/postgres/include/ -I/usr/local/include/postgresql/ -I/usr/local/postgresql/include/ -I/usr/local/pgsql/include -I/usr/local/include/pgsql/ -I/usr/local/include/postgres/ -I/usr/local/postgres/include/ -I/usr/local/include/postgresql/ -I/usr/local/postgresql/include/ -I/usr/pgsql/include -I/usr/include/pgsql/ -I/usr/include/postgres/ -I/usr/postgres/include/ -I/usr/include/postgresql/ -I/usr/postgresql/include/ -I/usr/local/mysql/include -I/usr/local/include/mysql/ -I/usr/local/mysql/include -I/usr/local/include/mysql/ -I/usr/mysql/include -I/usr/include/mysql/ -I/usr/local/include/libmongoc-1.0 -I/usr/local/include/libbson-1.0 -I/usr/local/include/libmongoc-1.0 -I/usr/local/include/libbson-1.0 -I/usr/local/include/hiredis -I/usr/local/include/hiredis +# +PORTNAME = turnserver +PREFIX = /usr/local +prefix = /usr/local +BINDIR = /usr/local/bin +bindir = /usr/local/bin +LOCALSTATEDIR = /usr/local/var +localstatedir = /usr/local/var +TURNDBDIR = /usr/local/var/db +turndbdir = /usr/local/var/db +CONFDIR = /usr/local/etc +confdir = /usr/local/etc +MANPREFIX = /usr/local +manprefix = /usr/local +EXAMPLESDIR = /usr/local/share/examples/turnserver +examplesdir = /usr/local/share/examples/turnserver +DOCSDIR = /usr/local/share/doc/turnserver +docsdir = /usr/local/share/doc/turnserver +LIBDIR = /usr/local/lib +libdir = /usr/local/lib +SCHEMADIR = /usr/local/share/turnserver +schemadir = /usr/local/share/turnserver +INCLUDEDIR = /usr/local/include +includedir = /usr/local/include +TURNINCLUDEDIR = /usr/local/include/turn +turnincludedir = /usr/local/include/turn +# +ARCHIVERCMD = ar -r +MKDIR = install -d +SQLITE_CMD = sqlite3 +INSTALL_PROGRAM = install +PKILL_PROGRAM = pkill +INSTALL_MAN = install +INSTALL_SCRIPT = install +INSTALL_SHARED_LIB = install +INSTALL_STATIC_LIB = install +INSTALL_DATA = install +INSTALL_DIR = cp -rpf +MKBUILDDIR = mkdir -p +RMCMD = rm -rf +MORECMD = cat +LDCONFIG=ldconfig -m +################################ + + +LIBEVENT_INCLUDE = -I${PREFIX}/include/ -I/usr/local/include/ + +INCFLAGS = -Isrc -Isrc/apps/common -Isrc/server -Isrc/client -Isrc/client++ ${LIBEVENT_INCLUDE} + +CFLAGS += ${INCFLAGS} + +MAKE_DEPS = Makefile + +LIBCLIENTTURN_HEADERS = src/ns_turn_defs.h src/client++/TurnMsgLib.h src/client/ns_turn_ioaddr.h src/client/ns_turn_msg.h src/client/ns_turn_msg_defs.h src/client/ns_turn_msg_defs_experimental.h src/client/ns_turn_msg_addr.h +LIBCLIENTTURN_MODS = src/client/ns_turn_ioaddr.c src/client/ns_turn_msg_addr.c src/client/ns_turn_msg.c +LIBCLIENTTURN_DEPS = ${LIBCLIENTTURN_HEADERS} ${MAKE_DEPS} +LIBCLIENTTURN_OBJS = build/obj/ns_turn_ioaddr.o build/obj/ns_turn_msg_addr.o build/obj/ns_turn_msg.o + +SERVERTURN_HEADERS = src/server/ns_turn_allocation.h src/server/ns_turn_ioalib.h src/server/ns_turn_khash.h src/server/ns_turn_maps_rtcp.h src/server/ns_turn_maps.h src/server/ns_turn_server.h src/server/ns_turn_session.h +SERVERTURN_DEPS = ${LIBCLIENTTURN_HEADERS} ${SERVERTURN_HEADERS} ${MAKE_DEPS} +SERVERTURN_MODS = ${LIBCLIENTTURN_MODS} src/server/ns_turn_allocation.c src/server/ns_turn_maps_rtcp.c src/server/ns_turn_maps.c src/server/ns_turn_server.c + +COMMON_HEADERS = src/apps/common/apputils.h src/apps/common/ns_turn_openssl.h src/apps/common/ns_turn_utils.h src/apps/common/stun_buffer.h +COMMON_MODS = src/apps/common/apputils.c src/apps/common/ns_turn_utils.c src/apps/common/stun_buffer.c +COMMON_DEPS = ${LIBCLIENTTURN_DEPS} ${COMMON_MODS} ${COMMON_HEADERS} + +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_DEPS = ${COMMON_DEPS} ${IMPL_HEADERS} ${IMPL_MODS} + +HIREDIS_HEADERS = src/apps/common/hiredis_libevent2.h +HIREDIS_MODS = src/apps/common/hiredis_libevent2.c + +USERDB_HEADERS = src/apps/relay/dbdrivers/dbdriver.h src/apps/relay/dbdrivers/dbd_sqlite.h src/apps/relay/dbdrivers/dbd_pgsql.h src/apps/relay/dbdrivers/dbd_mysql.h src/apps/relay/dbdrivers/dbd_mongo.h src/apps/relay/dbdrivers/dbd_redis.h +USERDB_MODS = src/apps/relay/dbdrivers/dbdriver.c src/apps/relay/dbdrivers/dbd_sqlite.c src/apps/relay/dbdrivers/dbd_pgsql.c src/apps/relay/dbdrivers/dbd_mysql.c src/apps/relay/dbdrivers/dbd_mongo.c src/apps/relay/dbdrivers/dbd_redis.c + +SERVERAPP_HEADERS = src/apps/relay/userdb.h src/apps/relay/tls_listener.h src/apps/relay/mainrelay.h src/apps/relay/turn_admin_server.h src/apps/relay/dtls_listener.h src/apps/relay/libtelnet.h ${HIREDIS_HEADERS} ${USERDB_HEADERS} +SERVERAPP_MODS = src/apps/relay/mainrelay.c src/apps/relay/netengine.c src/apps/relay/libtelnet.c src/apps/relay/turn_admin_server.c src/apps/relay/userdb.c src/apps/relay/tls_listener.c src/apps/relay/dtls_listener.c ${HIREDIS_MODS} ${USERDB_MODS} +SERVERAPP_DEPS = ${SERVERTURN_MODS} ${SERVERTURN_DEPS} ${SERVERAPP_MODS} ${SERVERAPP_HEADERS} ${COMMON_DEPS} ${IMPL_DEPS} lib/libturnclient.a + +TURN_BUILD_RESULTS = bin/turnutils_oauth bin/turnutils_natdiscovery bin/turnutils_stunclient bin/turnutils_rfc5769check bin/turnutils_uclient bin/turnserver bin/turnutils_peer lib/libturnclient.a include/turn/ns_turn_defs.h sqlite_empty_db + +.PHONY: all test check clean distclean sqlite_empty_db install deinstall uninstall reinstall + +all: ${TURN_BUILD_RESULTS} + +test: check + +check: bin/turnutils_rfc5769check + bin/turnutils_rfc5769check + +include/turn/ns_turn_defs.h: src/ns_turn_defs.h + ${RMCMD} include + ${MKBUILDDIR} include/turn/client + cp -pf src/client/*.h include/turn/client/ + cp -pf src/client++/*.h include/turn/client/ + cp -pf src/ns_turn_defs.h include/turn/ + +bin/turnutils_uclient: ${COMMON_DEPS} src/apps/uclient/session.h lib/libturnclient.a src/apps/uclient/mainuclient.c src/apps/uclient/uclient.c src/apps/uclient/uclient.h src/apps/uclient/startuclient.c src/apps/uclient/startuclient.h + ${MKBUILDDIR} bin + ${CC} ${CPPFLAGS} ${CFLAGS} src/apps/uclient/uclient.c src/apps/uclient/startuclient.c src/apps/uclient/mainuclient.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS} + +bin/turnutils_natdiscovery: ${COMMON_DEPS} lib/libturnclient.a src/apps/natdiscovery/natdiscovery.c + pwd + ${MKBUILDDIR} bin + ${CC} ${CPPFLAGS} ${CFLAGS} src/apps/natdiscovery/natdiscovery.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS} + +bin/turnutils_oauth: ${COMMON_DEPS} lib/libturnclient.a src/apps/oauth/oauth.c + pwd + ${MKBUILDDIR} bin + ${CC} ${CPPFLAGS} ${CFLAGS} src/apps/oauth/oauth.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS} + +bin/turnutils_stunclient: ${COMMON_DEPS} lib/libturnclient.a src/apps/stunclient/stunclient.c + pwd + ${MKBUILDDIR} bin + ${CC} ${CPPFLAGS} ${CFLAGS} src/apps/stunclient/stunclient.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS} + +bin/turnutils_rfc5769check: ${COMMON_DEPS} lib/libturnclient.a src/apps/rfc5769/rfc5769check.c + pwd + ${MKBUILDDIR} bin + ${CC} ${CPPFLAGS} ${CFLAGS} src/apps/rfc5769/rfc5769check.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS} + +bin/turnserver: ${SERVERAPP_DEPS} + ${MKBUILDDIR} bin + ${RMCMD} bin/turnadmin + ${CC} ${CPPFLAGS} ${CFLAGS} ${DBCFLAGS} ${IMPL_MODS} -Ilib ${SERVERAPP_MODS} ${COMMON_MODS} ${SERVERTURN_MODS} -o $@ ${DBLIBS} ${LDFLAGS} + cd bin; ln -s turnserver turnadmin + +bin/turnutils_peer: ${COMMON_DEPS} ${LIBCLIENTTURN_MODS} ${LIBCLIENTTURN_DEPS} lib/libturnclient.a src/apps/peer/mainudpserver.c src/apps/peer/udpserver.h src/apps/peer/udpserver.c + ${MKBUILDDIR} bin + ${CC} ${CPPFLAGS} ${CFLAGS} src/apps/peer/mainudpserver.c src/apps/peer/udpserver.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS} + +### Client Library: + +lib/libturnclient.a: ${LIBCLIENTTURN_OBJS} ${LIBCLIENTTURN_DEPS} + ${MKBUILDDIR} lib + ${ARCHIVERCMD} $@ ${LIBCLIENTTURN_OBJS} + +build/obj/ns_turn_ioaddr.o: src/client/ns_turn_ioaddr.c ${LIBCLIENTTURN_DEPS} + ${MKBUILDDIR} build/obj + ${CC} ${CPPFLAGS} ${CFLAGS} -c src/client/ns_turn_ioaddr.c -o $@ + +build/obj/ns_turn_msg_addr.o: src/client/ns_turn_msg_addr.c ${LIBCLIENTTURN_DEPS} + ${MKBUILDDIR} build/obj + ${CC} ${CPPFLAGS} ${CFLAGS} -c src/client/ns_turn_msg_addr.c -o $@ + +build/obj/ns_turn_msg.o: src/client/ns_turn_msg.c ${LIBCLIENTTURN_DEPS} + ${MKBUILDDIR} build/obj + ${CC} ${CPPFLAGS} ${CFLAGS} -c src/client/ns_turn_msg.c -o $@ + +### Clean all: + +clean: + ${RMCMD} bin build lib obj *bak *~ */*~ */*/*~ */*/*/*~ *core */*core */*/*core include tmp sqlite + +distclean: clean + ${RMCMD} Makefile + +### SQLite empty database: +sqlite_empty_db : sqlite/turndb + +sqlite/turndb : turndb/schema.sql + ${MKDIR} sqlite + ${RMCMD} sqlite/turndb + ${SQLITE_CMD} sqlite/turndb < turndb/schema.sql + +### Install all: + +install: all ${MAKE_DEPS} + ${MKDIR} ${DESTDIR}${PREFIX} + ${MKDIR} ${DESTDIR}${BINDIR} + ${MKDIR} ${DESTDIR}${TURNDBDIR} + ${MKDIR} ${DESTDIR}${MANPREFIX}/man/man1 + ${MKDIR} ${DESTDIR}${CONFDIR} + ${MKDIR} ${DESTDIR}${LIBDIR} + ${MKDIR} ${DESTDIR}${EXAMPLESDIR} + ${MKDIR} ${DESTDIR}${DOCSDIR} + ${MKDIR} ${DESTDIR}${SCHEMADIR} + ${MKDIR} ${DESTDIR}${TURNINCLUDEDIR} + ${INSTALL_PROGRAM} bin/turnserver ${DESTDIR}${BINDIR} + ${INSTALL_PROGRAM} bin/turnadmin ${DESTDIR}${BINDIR} + ${INSTALL_PROGRAM} bin/turnutils_uclient ${DESTDIR}${BINDIR} + ${INSTALL_PROGRAM} bin/turnutils_peer ${DESTDIR}${BINDIR} + ${INSTALL_PROGRAM} bin/turnutils_stunclient ${DESTDIR}${BINDIR} + ${INSTALL_PROGRAM} bin/turnutils_oauth ${DESTDIR}${BINDIR} + ${INSTALL_PROGRAM} bin/turnutils_natdiscovery ${DESTDIR}${BINDIR} + ${INSTALL_MAN} man/man1/turnserver.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_MAN} man/man1/turnadmin.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_MAN} man/man1/turnutils.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_MAN} man/man1/turnutils_uclient.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_MAN} man/man1/turnutils_stunclient.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_MAN} man/man1/turnutils_oauth.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_MAN} man/man1/turnutils_natdiscovery.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_MAN} man/man1/turnutils_peer.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_MAN} man/man1/coturn.1 ${DESTDIR}${MANPREFIX}/man/man1/ + ${INSTALL_STATIC_LIB} lib/libturnclient.a ${DESTDIR}${LIBDIR} + ${INSTALL_DATA} LICENSE ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} README.turnserver ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} README.turnadmin ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} README.turnutils ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} INSTALL ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} postinstall.txt ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} turndb/schema.sql ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} turndb/schema.sql ${DESTDIR}${SCHEMADIR} + ${INSTALL_DATA} turndb/schema.mongo.sh ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} turndb/schema.mongo.sh ${DESTDIR}${SCHEMADIR} + ${INSTALL_DATA} turndb/testredisdbsetup.sh ${DESTDIR}${SCHEMADIR} + ${INSTALL_DATA} turndb/testmongosetup.sh ${DESTDIR}${SCHEMADIR} + ${INSTALL_DATA} turndb/testsqldbsetup.sql ${DESTDIR}${SCHEMADIR} + ${INSTALL_DATA} turndb/schema.userdb.redis ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} turndb/schema.userdb.redis ${DESTDIR}${SCHEMADIR} + ${INSTALL_DATA} turndb/schema.stats.redis ${DESTDIR}${DOCSDIR} + ${INSTALL_DATA} turndb/schema.stats.redis ${DESTDIR}${SCHEMADIR} + if [ -f sqlite/turndb ] ; then ${INSTALL_DATA} sqlite/turndb ${DESTDIR}${TURNDBDIR}/turndb; fi + ${INSTALL_DATA} examples/etc/turnserver.conf ${DESTDIR}${CONFDIR}/turnserver.conf.default + ${INSTALL_DIR} examples/etc ${DESTDIR}${EXAMPLESDIR} + ${INSTALL_DIR} examples/scripts ${DESTDIR}${EXAMPLESDIR} + ${RMCMD} ${DESTDIR}${EXAMPLESDIR}/scripts/rfc5769.sh + ${INSTALL_DIR} include/turn/client ${DESTDIR}${TURNINCLUDEDIR} + ${INSTALL_DATA} include/turn/ns_turn_defs.h ${DESTDIR}${TURNINCLUDEDIR} + ${MORECMD} ${DESTDIR}${DOCSDIR}/postinstall.txt + +deinstall: ${MAKE_DEPS} + ${PKILL_PROGRAM} turnserver || ${ECHO_CMD} OK + ${RMCMD} ${DESTDIR}${TURNDBDIR}/turndb + ${RMCMD} ${DESTDIR}${DOCSDIR} + ${RMCMD} ${DESTDIR}${SCHEMADIR} + ${RMCMD} ${DESTDIR}${BINDIR}/turnserver + ${RMCMD} ${DESTDIR}${BINDIR}/turnadmin + ${RMCMD} ${DESTDIR}${BINDIR}/turnutils_peer + ${RMCMD} ${DESTDIR}${BINDIR}/turnutils_uclient + ${RMCMD} ${DESTDIR}${BINDIR}/turnutils_stunclient + ${RMCMD} ${DESTDIR}${BINDIR}/turnutils_oauth + ${RMCMD} ${DESTDIR}${BINDIR}/turnutils_natdiscovery + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnserver.1 + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnadmin.1 + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils.1 + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_uclient.1 + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_stunclient.1 + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_oauth.1 + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_natdiscovery.1 + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_peer.1 + ${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/coturn.1 + ${RMCMD} ${DESTDIR}${LIBDIR}/libturnclient.a + ${RMCMD} ${DESTDIR}${EXAMPLESDIR} + ${RMCMD} ${DESTDIR}${CONFDIR}/turnserver.conf.default + ${RMCMD} ${DESTDIR}${TURNINCLUDEDIR} + +uninstall: deinstall + +reinstall: deinstall install diff --git a/Makefile.in b/Makefile.in index be993d6c..078f50c3 100755 --- a/Makefile.in +++ b/Makefile.in @@ -36,6 +36,8 @@ SERVERAPP_DEPS = ${SERVERTURN_MODS} ${SERVERTURN_DEPS} ${SERVERAPP_MODS} ${SERVE TURN_BUILD_RESULTS = bin/turnutils_oauth bin/turnutils_natdiscovery bin/turnutils_stunclient bin/turnutils_rfc5769check bin/turnutils_uclient bin/turnserver bin/turnutils_peer lib/libturnclient.a include/turn/ns_turn_defs.h sqlite_empty_db +.PHONY: all test check clean distclean sqlite_empty_db install deinstall uninstall reinstall + all: ${TURN_BUILD_RESULTS} test: check @@ -90,24 +92,25 @@ lib/libturnclient.a: ${LIBCLIENTTURN_OBJS} ${LIBCLIENTTURN_DEPS} ${MKBUILDDIR} lib ${ARCHIVERCMD} $@ ${LIBCLIENTTURN_OBJS} -build/obj/ns_turn_ioaddr.o: src/client/ns_turn_ioaddr.c ${LUBCLIENTTURN_DEPS} +build/obj/ns_turn_ioaddr.o: src/client/ns_turn_ioaddr.c ${LIBCLIENTTURN_DEPS} ${MKBUILDDIR} build/obj ${CC} ${CPPFLAGS} ${CFLAGS} -c src/client/ns_turn_ioaddr.c -o $@ -build/obj/ns_turn_msg_addr.o: src/client/ns_turn_msg_addr.c ${LUBCLIENTTURN_DEPS} +build/obj/ns_turn_msg_addr.o: src/client/ns_turn_msg_addr.c ${LIBCLIENTTURN_DEPS} ${MKBUILDDIR} build/obj ${CC} ${CPPFLAGS} ${CFLAGS} -c src/client/ns_turn_msg_addr.c -o $@ -build/obj/ns_turn_msg.o: src/client/ns_turn_msg.c ${LUBCLIENTTURN_DEPS} +build/obj/ns_turn_msg.o: src/client/ns_turn_msg.c ${LIBCLIENTTURN_DEPS} ${MKBUILDDIR} build/obj ${CC} ${CPPFLAGS} ${CFLAGS} -c src/client/ns_turn_msg.c -o $@ ### Clean all: clean: - ${RMCMD} bin build lib obj *bak *~ */*~ */*/*~ */*/*/*~ *core */*core */*/*core include Makefile tmp sqlite + ${RMCMD} bin build lib obj *bak *~ */*~ */*/*~ */*/*/*~ *core */*core */*/*core include tmp sqlite distclean: clean + ${RMCMD} Makefile ### SQLite empty database: sqlite_empty_db : sqlite/turndb diff --git a/README.md b/README.md index 9a6b99be..a4d8ff7d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Build Status](https://travis-ci.org/coturn/coturn.svg?branch=master)](https://travis-ci.org/coturn/coturn) + **_This project evolved from rfc5766-turn-server project (https://code.google.com/p/rfc5766-turn-server/). There are many new advanced TURN specs which are going far beyond the original RFC 5766 document. This project takes the code of rfc5766-turn-server as the starter, and adds new advanced features to it._** [Downloads page](https://github.com/coturn/coturn/wiki/Downloads) diff --git a/README.turnadmin b/README.turnadmin index ec07197a..3cb375b2 100644 --- a/README.turnadmin +++ b/README.turnadmin @@ -86,6 +86,8 @@ Only sha256 is supported as the hash function. -g, --set-realm-option Set realm params: max-bps, total-quota, user-quota. -G, --list-realm-options List realm params. +-E, --generate-encrypted-password-aes Generate and print to the standard output + an encrypted form of password with AES-128 Options with required values: @@ -103,6 +105,9 @@ Options with required values: -u, --user User name. -r, --realm Realm. -p, --password Password. +-x, --key-path Generates a 128 bit key into the given path. +-f, --file-key-path Contains a 128 bit key in the given path. +-v, --verify Verify a given base64 encrypted type password. -o, --origin Origin --max-bps Set value of realm's max-bps parameter. --total-quota Set value of realm's total-quota parameter. @@ -158,7 +163,20 @@ $ turnadmin --redis-userdb="" -I List the origin-to-realm relations in PostgreSQL DB for a single realm: $ turnadmin --psql-userdb="" -I -r - + +Create new key file for mysql password encryption: + +$ turnadmin -E --key-path + +Create encrypted mysql password: + +$ turnadmin -E --file-key-path -p + +Verify/decrypt encrypted password: + +$ turnadmin --file-key-path -v + + Help: $ turnadmin -h @@ -253,4 +271,4 @@ to see the man page. Bradley T. Hughes - Mihaly Meszaros + Mihaly Meszaros diff --git a/README.turnserver b/README.turnserver index ba0c72b5..465fcd0c 100644 --- a/README.turnserver +++ b/README.turnserver @@ -120,6 +120,11 @@ User database settings: (see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the command options description). +--secret-key-file This is the file path which contain secret key of aes encryption while using MySQL password encryption. + If you want to use in the MySQL connection string the password in encrypted format, + then set in this option the file path of the secret key. The key which is used to encrypt MySQL password. + Warning: If this option is set, then MySQL password must be set in "mysql-userdb" option in encrypted format! + If you want to use cleartext password then do not set this option! -J, --mongo-userdb User database connection string for MongoDB. This database can be used for long-term credentials mechanism, and it can store the secret value @@ -526,7 +531,11 @@ Options with values: --proc-group Group name to run the process. After the initialization, the turnserver process will make an attempt to change the current group ID to that group. - + +-K, --keep-address-family TURN server allocates address family according TURN + Client <=> Server communication address family. + !! It breaks RFC6156 section-4.2 (violates default IPv4) !! + --cli-ip Local system IP address to be used for CLI management interface. The turnserver process can be accessed for management with telnet, at this IP address and on the CLI port (see the next parameter). @@ -962,4 +971,4 @@ https://groups.google.com/forum/?fromgroups=#!forum/turn-server-project-rfc5766- Bradley T. Hughes - Mihaly Meszaros + Mihaly Meszaros diff --git a/README.turnutils b/README.turnutils index 76f9c8a1..39fda214 100644 --- a/README.turnutils +++ b/README.turnutils @@ -314,7 +314,7 @@ $ turnutils_oauth [options] turnutils_oauth utilitiy provides help in OAuth access_token encryption and/or decryption with AEAD (Atuthenticated Encryption with Associated Data). It helps -for an Auth Server in access_token creation, and also for debuging purposes it +for an Auth Server in access_token creation, and also for debugging purposes it helps the access_token validation and decryption. This utility inputs all the keys and lifetimes and any related information that are needed for encryption or decryption of an access_token. It outputs a JSON with all OAuth PoP @@ -474,4 +474,4 @@ SEE ALSO Bradley T. Hughes - Mihaly Meszaros + Mihaly Meszaros diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 1eaefe4f..0fcb17cb 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -179,9 +179,10 @@ #no-auth # TURN REST API flag. +# (Time Limited Long Term Credential) # Flag that sets a special authorization option that is based upon authentication secret. -# This feature can be used with the long-term authentication mechanism, only. -# This feature purpose is to support "TURN Server REST API", see +# +# This feature's purpose is to support "TURN Server REST API", see # "TURN REST API" link in the project's page # https://github.com/coturn/coturn/ # @@ -197,6 +198,22 @@ # The actual value of the secret is defined either by 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 +# +# Be aware that use-auth-secret overrides some part of lt-cred-mech. +# Notice that this feature depends internally on lt-cred-mech, so if you set +# use-auth-secret then it enables internally automatically lt-cred-mech option +# like if you enable both. +# +# You can use only one of the to auth mechanisms in the same time because, +# both mechanism use the username and password validation in different way. +# +# This way be aware that you can't use both auth mechnaism in the same time! +# Use in config either the lt-cred-mech or the use-auth-secret +# to avoid any confusion. +# #use-auth-secret # 'Static' authentication secret value (a string) for TURN REST API only. @@ -217,15 +234,8 @@ # #oauth -#The default realm to be used for the users when no explicit origin/realm -#relationship was found in the database. Must be used with long-term -#credentials mechanism or with TURN REST API. -# -#realm=realm - # 'Static' user accounts for long term credentials mechanism, only. # This option cannot be used with TURN REST API. -# This option require a realm. # 'Static' user accounts are NOT dynamically checked by the turnserver process, # so that they can NOT be changed while the turnserver is running. # @@ -283,6 +293,16 @@ # #mysql-userdb="host= dbname= user= password= port= connect_timeout= read_timeout=" +# If you want to use in the MySQL connection string the password in encrypted format, +# then set in this option the MySQL password encryption secret key file. +# +# Warning: If this option is set, then mysql password must be set in "mysql-userdb" in encrypted format! +# If you want to use cleartext password then do not set this option! +# +# This is the file path which contain secret key of aes encryption while using password encryption. +# +#secret-key-file=/path/ + # MongoDB database connection string in the case that we are using MongoDB # as the user database. # This database can be used for long-term credential mechanism @@ -313,6 +333,9 @@ # and the userdb file). Must be used with long-term credentials # mechanism or with TURN REST API. # +# Note: If default realm is not specified at all, then realm falls back to the host domain name. +# If domain name is empty string, or '(None)', then it is initialized to am empty string. +# #realm=mycompany.org # The flag that sets the origin consistency @@ -589,6 +612,15 @@ # #mobility +# 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)!! +# +#keep-address-family + + # 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. # @@ -622,7 +654,7 @@ # #cli-password=$5$79a316b350311570$81df9cfb9af7f5e5a76eada31e7097b663a0670f99a3c07ded3f1c8e59c5658a # -# Or unsecure form for the same paassword: +# Or unsecure form for the same password: # #cli-password=qwerty diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 9ffb8a08..ea359b05 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "29 September 2017" "" "" +.TH TURN 1 "27 September 2018" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage @@ -139,6 +139,11 @@ Set realm params: max\-bps, total\-quota, user\-quota. List realm params. .TP .B +\fB\-E\fP, \fB\-\-generate\-encrypted\-password\-aes\fP +Generate and print to the standard output +an encrypted form of password with AES\-128 +.TP +.B Options with required values: .TP .B @@ -180,6 +185,18 @@ Realm. Password. .TP .B +\fB\-x\fP, \fB\-\-key\-path\fP +Generates a 128 bit key into the given path. +.TP +.B +\fB\-f\fP, \fB\-\-file\-key\-path\fP +Contains a 128 bit key in the given path. +.TP +.B +\fB\-v\fP, \fB\-\-verify\fP +Verify a given base64 encrypted type password. +.TP +.B \fB\-o\fP, \fB\-\-origin\fP Origin .TP @@ -249,6 +266,22 @@ $ \fIturnadmin\fP \fB\-\-redis\-userdb\fP="" \fB\-I\fP List the origin\-to\-realm relations in PostgreSQL DB for a single realm: .PP $ \fIturnadmin\fP \fB\-\-psql\-userdb\fP="" \fB\-I\fP \fB\-r\fP +.PP +Create new key file for mysql password encryption: +.PP +$ \fIturnadmin\fP \fB\-E\fP \fB\-\-key\-path\fP +.PP +Create encrypted mysql password: +.PP +$ \fIturnadmin\fP \fB\-E\fP \fB\-\-file\-key\-path\fP \fB\-p\fP +.PP +Verify/decrypt encrypted password: +.PP +$ \fIturnadmin\fP \fB\-\-file\-key\-path\fP \fB\-v\fP +.RE +.PP + +.RS .TP .B Help: @@ -341,4 +374,4 @@ Federico Pinna .PP Bradley T. Hughes .PP -Mihaly Meszaros +Mihaly Meszaros diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 70258b14..e898593c 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "29 September 2017" "" "" +.TH TURN 1 "27 September 2018" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -180,6 +180,14 @@ command \fIoptions\fP description). .RE .TP .B +\fB\-\-secret\-key\-file\fP +This is the file path which contain secret key of aes encryption while using MySQL password encryption. +If you want to use in the MySQL connection string the password in encrypted format, +then set in this option the file path of the secret key. The key which is used to encrypt MySQL password. +Warning: If this option is set, then MySQL password must be set in "mysql\-userdb" option in encrypted format! +If you want to use cleartext password then do not set this option! +.TP +.B \fB\-J\fP, \fB\-\-mongo\-userdb\fP User database connection string for MongoDB. This database can be used for long\-term credentials mechanism, @@ -756,6 +764,12 @@ Group name to run the process. After the initialization, the \fIturnserver\fP pr will make an attempt to change the current group ID to that group. .TP .B +\fB\-K\fP, \fB\-\-keep\-address\-family\fP +TURN server allocates address family according TURN +Client <=> Server communication address family. +!! It breaks RFC6156 section\-4.2 (violates default IPv4) !! +.TP +.B \fB\-\-cli\-ip\fP Local system IP address to be used for CLI management interface. The \fIturnserver\fP process can be accessed for management with telnet, @@ -1211,4 +1225,4 @@ Federico Pinna .PP Bradley T. Hughes .PP -Mihaly Meszaros +Mihaly Meszaros diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index fc9c9ec0..f52dfb0e 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "29 September 2017" "" "" +.TH TURN 1 "27 September 2018" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -482,7 +482,7 @@ $ \fIturnutils_oauth\fP [\fIoptions\fP] \fIturnutils_oauth\fP utilitiy provides help in OAuth access_token encryption and/or decryption with AEAD (Atuthenticated Encryption with Associated Data). It helps -for an Auth Server in access_token creation, and also for debuging purposes it +for an Auth Server in access_token creation, and also for debugging purposes it helps the access_token validation and decryption. This utility inputs all the keys and lifetimes and any related information that are needed for encryption or decryption of an access_token. It outputs a JSON with all OAuth PoP @@ -669,6 +669,5 @@ Mutsutoshi Yoshimoto Federico Pinna .PP Bradley T. Hughes -.RE .PP -Mihaly Meszaros +Mihaly Meszaros diff --git a/netarch.txt b/netarch.txt index 5774b39a..d0dfd2a6 100644 --- a/netarch.txt +++ b/netarch.txt @@ -18,7 +18,7 @@ sockets, and relaying those packets, through the relay sockets, to the Peer appl relay sockets, and relaying those packets, through the Client sockets, to the Client application. -There are other, secondary, interations: +There are other, secondary, interactions: 1) Communications with the database servers. 2) Communications with the telnet admin console. @@ -50,8 +50,8 @@ open_client_connection_session() and where and how it is called in various cases for reference. The listeners (and the relay servers) configuration is initiated in the function -setup_servers() in netengine.c. First, setup_listener() creates the necessary generic -data structures for the listeners. Second, network-engine-specific functions accosiate +setup_server() in netengine.c. First, setup_listener() creates the necessary generic +data structures for the listeners. Second, network-engine-specific functions associate listeners with the execution threads and with the relay servers. There may be multiple listeners in the server, and they may be running in different diff --git a/postinstall.txt b/postinstall.txt index 471dda4f..a73dd287 100644 --- a/postinstall.txt +++ b/postinstall.txt @@ -1,8 +1,8 @@ ================================================================== -1) If you system supports automatic start-up system daemon services, -the, to enable the turnserver as an automatically started system -service, you have to: +1) If your system supports automatic start-up system daemon services, +then to enable the turnserver as a system service that is automatically +started, you have to: a) Create and edit /etc/turnserver.conf or /usr/local/etc/turnserver.conf . diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index cf95b46e..0ae0ad32 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.5.0.7 +TURNVERSION=4.5.0.8 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_GIT_URL=https://github.com/coturn/coturn.git diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 516b7934..77a03ae1 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.5.0.7 +Version: 4.5.0.8 Release: 0%{dist} Summary: Coturn TURN Server @@ -295,6 +295,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Thu Sep 27 2018 Oleg Moskalenko + - Sync to 4.5.0.8 * Sun Dec 10 2017 Oleg Moskalenko - Sync to 4.5.0.7 * Mon Oct 17 2016 Oleg Moskalenko diff --git a/src/apps/natdiscovery/natdiscovery.c b/src/apps/natdiscovery/natdiscovery.c index a8080c23..31bde9d4 100644 --- a/src/apps/natdiscovery/natdiscovery.c +++ b/src/apps/natdiscovery/natdiscovery.c @@ -246,7 +246,7 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex printf("The response is an error %d (%s)\n", err_code, reason.c_str()); } } else { - printf("The response is not a reponse message\n"); + printf("The response is not a response message\n"); } } catch(...) { turn::StunMsgRequest msg(buf.buf, sizeof(buf.buf), (size_t)buf.len, true); @@ -474,7 +474,7 @@ static int stunclient_receive(stun_buffer *buf, int sockfd, ioa_addr *local_addr } else if (stun_is_request(buf)) { printf("Received a request (maybe a successful hairpinning)\n"); } else { - printf("The response is not a reponse message\n"); + printf("The response is not a response message\n"); ret=1; } } else { diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index f9eaa719..d54542a6 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -35,6 +35,7 @@ #if !defined(TURN_NO_MYSQL) #include + /////////////////////////////////////////////////////////////////////////////////////////////////////////// static int donot_print_connection_success = 0; @@ -73,6 +74,34 @@ static void MyconninfoFree(Myconninfo *co) { } } +char* decryptPassword(char* in, const unsigned char* mykey){ + + char *out; + unsigned char iv[8] = {0}; //changed + AES_KEY key; + unsigned char outdata[256]; //changed + AES_set_encrypt_key(mykey, 128, &key); + int newTotalSize=decodedTextSize(in); + int bytes_to_decode = strlen(in); + unsigned char *encryptedText = base64decode(in, bytes_to_decode); //changed + char last[1024]=""; + struct ctr_state state; + init_ctr(&state, iv); + memset(outdata,'\0', sizeof(outdata)); + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + CRYPTO_ctr128_encrypt(encryptedText, outdata, newTotalSize, &key, state.ivec, state.ecount, &state.num,(block128_f)AES_encrypt); +#else + AES_ctr128_encrypt(encryptedText, outdata, newTotalSize, &key, state.ivec, state.ecount, &state.num); +#endif + + strcat(last,(char*)outdata); + out=(char*)malloc(sizeof(char)*strlen(last)); + strcpy(out,last); + return out; +} + + static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) { Myconninfo *co = (Myconninfo*)turn_malloc(sizeof(Myconninfo)); ns_bzero(co,sizeof(Myconninfo)); @@ -234,6 +263,11 @@ static MYSQL *get_mydb_connection(void) { if(co->ca || co->capath || co->cert || co->cipher || co->key) { mysql_ssl_set(mydbconnection, co->key, co->cert, co->ca, co->capath, co->cipher); } + + if(turn_params.secret_key_file[0]){ + co->password = decryptPassword(co->password, turn_params.secret_key); + } + MYSQL *conn = mysql_real_connect(mydbconnection, co->host, co->user, co->password, co->dbname, co->port, NULL, CLIENT_IGNORE_SIGPIPE); if(!conn) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection: <%s>, runtime error\n",pud->userdb); @@ -245,6 +279,12 @@ static MYSQL *get_mydb_connection(void) { mydbconnection=NULL; } else if(!donot_print_connection_success) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MySQL DB connection success: %s\n",pud->userdb); + if(turn_params.secret_key_file[0]) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Encryption with AES is activated.\n"); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Connection is secure.\n"); + } + else + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Connection is not secure.\n"); donot_print_connection_success = 1; } } diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 9089b263..66e2bab5 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -39,6 +39,10 @@ static int use_lt_credentials = 0; static int anon_credentials = 0; +//long term credential +static int use_ltc = 0; +//timelimited long term credential +static int use_tltc = 0; ////// ALPN ////////// @@ -100,6 +104,8 @@ DH_1066, "", "", "", 0, #endif +NULL, PTHREAD_MUTEX_INITIALIZER, + TURN_VERBOSE_NONE,0,0,0, "/var/run/turnserver.pid", DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,1, @@ -110,7 +116,7 @@ DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,1, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,NULL,NULL,NULL }, {NULL, 0},{NULL, 0}, -NEV_UNKNOWN, +NEV_UNKNOWN, { "Unknown", "UDP listening socket per session", "UDP thread per network endpoint", "UDP thread per CPU core" }, //////////////// Relay servers ////////////////////////////////// LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,0,"", @@ -145,7 +151,11 @@ TURN_CREDENTIALS_NONE, /* ct */ ///////////// Users DB ////////////// { (TURN_USERDB_TYPE)0, {"\0"}, {0,NULL, {NULL,0}} }, ///////////// CPUs ////////////////// -DEFAULT_CPUS_NUMBER +DEFAULT_CPUS_NUMBER, +///////// Encryption ///////// +"", /* secret_key_file */ +"", /* secret_key */ +0 /* keep_address_family */ }; //////////////// OpenSSL Init ////////////////////// @@ -171,6 +181,7 @@ static char procgroupname[1025]="\0"; ////////////// Configuration functionality //////////////////////////////// static void read_config_file(int argc, char **argv, int pass); +static void reload_ssl_certs(evutil_socket_t sock, short events, void *args); ////////////////////////////////////////////////// @@ -480,12 +491,17 @@ static char Usage[] = "Usage: turnserver [options]\n" " This database can be used for long-term credentials mechanism users,\n" " and it can store the secret value(s) for secret-based timed authentication in TURN RESP API.\n" " The connection string my be space-separated list of parameters:\n" -" \"host= dbname= user= \\\n password= port= connect_timeout= read_timeout=\".\n\n" +" \"host= dbname= user= \\\n password= port= connect_timeout= read_timeout=\".\n\n" " The connection string parameters for the secure communications (SSL):\n" " ca, capath, cert, key, cipher\n" " (see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the\n" " command options description).\n\n" " All connection-string parameters are optional.\n\n" +" --secret-key-file This is the file path which contain secret key of aes encryption while using MySQL password encryption.\n" +" If you want to use in the MySQL connection string the password in encrypted format,\n" +" then set in this option the file path of the secret key. The key which is used to encrypt MySQL password.\n" +" Warning: If this option is set, then MySQL password must be set in \"mysql-userdb\" option in encrypted format!\n" +" If you want to use cleartext password then do not set this option!\n" #endif #if !defined(TURN_NO_MONGO) " -J, --mongo-userdb MongoDB connection string, if used (default - empty, no MongoDB used).\n" @@ -581,10 +597,10 @@ static char Usage[] = "Usage: turnserver [options]\n" " See the docs for more information.\n" " -C, --rest-api-separator This is the timestamp/username separator symbol (character) in TURN REST API.\n" " The default value is ':'.\n" -" --max-allocate-timeout= Max time, in seconds, allowed for full allocation establishment. Default is 60.\n" -" --allowed-peer-ip= Specifies an ip or range of ips that are explicitly allowed to connect to the \n" +" --max-allocate-timeout= Max time, in seconds, allowed for full allocation establishment. Default is 60.\n" +" --allowed-peer-ip= Specifies an ip or range of ips that are explicitly allowed to connect to the \n" " turn server. Multiple allowed-peer-ip can be set.\n" -" --denied-peer-ip= Specifies an ip or range of ips that are not allowed to connect to the turn server.\n" +" --denied-peer-ip= Specifies an ip or range of ips that are not allowed to connect to the turn server.\n" " Multiple denied-peer-ip can be set.\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" @@ -599,6 +615,9 @@ static char Usage[] = "Usage: turnserver [options]\n" " will make an attempt to change the current group ID to that group.\n" " --mobility Mobility with ICE (MICE) specs support.\n" " --no-http Turn OFF the HTTP-Admin-Interface. By default it is always ON.\n" +" -K, --keep-address-family TURN server allocates address family according TURN\n" +" Client <=> Server communication address family. \n" +" !! It breaks RFC6156 section-4.2 (violates default IPv4) !!\n" " --no-cli Turn OFF the CLI support. By default it is always ON.\n" " --cli-ip= Local system IP address to be used for CLI server endpoint. Default value\n" " is 127.0.0.1.\n" @@ -643,6 +662,8 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" " -I, --list-origins List origin-to-realm relations.\n" " -g, --set-realm-option Set realm params: max-bps, total-quota, user-quota.\n" " -G, --list-realm-options List realm params.\n" + " -E, --generate-encrypted-password-aes Generate and print to the standard\n" + " output an encrypted form of password with AES-128\n" "\nOptions with mandatory values:\n\n" #if !defined(TURN_NO_SQLITE) " -b, --db, --userdb SQLite database file, default value is /var/db/turndb or\n" @@ -663,6 +684,9 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" " -u, --user Username\n" " -r, --realm Realm\n" " -p, --password Password\n" + " -x, --key-path Generates a 128 bit key into the given path.\n" + " -f, --file-key-path Contains a 128 bit key in the given path.\n" + " -v, --verify Verify a given base64 encrypted type password.\n" #if !defined(TURN_NO_SQLITE) || !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS) " -o, --origin Origin\n" #endif @@ -674,9 +698,9 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n" " Setting to zero value means removal of the option.\n" " -h, --help Help\n"; -#define OPTIONS "c:d:p:L:E:X:i:m:l:r:u:b:B:e:M:J:N:O:q:Q:s:C:vVofhznaAS" - -#define ADMIN_OPTIONS "PgGORIHKYlLkaADSdb:e:M:J:N:u:r:p:s:X:o:h" +#define OPTIONS "c:d:p:L:E:X:i:m:l:r:u:b:B:e:M:J:N:O:q:Q:s:C:K:vVofhznaAS" + +#define ADMIN_OPTIONS "PEgGORIHKYlLkaADSdb:e:M:J:N:u:r:p:s:X:o:h:x:v:f:" enum EXTRA_OPTS { NO_UDP_OPT=256, @@ -744,7 +768,8 @@ enum EXTRA_OPTS { SERVER_NAME_OPT, OAUTH_OPT, PROD_OPT, - NO_HTTP_OPT + NO_HTTP_OPT, + SECRET_KEY_OPT }; struct myoption { @@ -863,11 +888,14 @@ static const struct myoption long_options[] = { { "no-tlsv1", optional_argument, NULL, NO_TLSV1_OPT }, { "no-tlsv1_1", optional_argument, NULL, NO_TLSV1_1_OPT }, { "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' }, { NULL, no_argument, NULL, 0 } }; static const struct myoption admin_long_options[] = { {"generate-encrypted-password", no_argument, NULL, 'P' }, + {"generate-encrypted-password-aes", no_argument, NULL, 'E'}, { "key", no_argument, NULL, 'k' }, { "add", no_argument, NULL, 'a' }, { "delete", no_argument, NULL, 'd' }, @@ -899,6 +927,9 @@ static const struct myoption admin_long_options[] = { { "user", required_argument, NULL, 'u' }, { "realm", required_argument, NULL, 'r' }, { "password", required_argument, NULL, 'p' }, + { "file-key-path", required_argument, NULL, 'f' }, + { "verify", required_argument, NULL, 'v' }, + { "key-path", required_argument, NULL, 'x'}, { "add-origin", no_argument, NULL, 'O' }, { "del-origin", no_argument, NULL, 'R' }, { "list-origins", required_argument, NULL, 'I' }, @@ -912,6 +943,143 @@ static const struct myoption admin_long_options[] = { { NULL, no_argument, NULL, 0 } }; +int init_ctr(struct ctr_state *state, const unsigned char iv[8]){ + state->num = 0; + memset(state->ecount, 0, 16); + memset(state->ivec + 8, 0, 8); + memcpy(state->ivec, iv, 8); + return 1; +} + +unsigned char *base64encode (const void *b64_encode_this, int encode_this_many_bytes){ + BIO *b64_bio, *mem_bio; //Declares two OpenSSL BIOs: a base64 filter and a memory BIO. + BUF_MEM *mem_bio_mem_ptr; //Pointer to a "memory BIO" structure holding our base64 data. + b64_bio = BIO_new(BIO_f_base64()); //Initialize our base64 filter BIO. + mem_bio = BIO_new(BIO_s_mem()); //Initialize our memory sink BIO. + BIO_push(b64_bio, mem_bio); //Link the BIOs by creating a filter-sink BIO chain. + BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL); //No newlines every 64 characters or less. + BIO_write(b64_bio, b64_encode_this, encode_this_many_bytes); //Records base64 encoded data. + (void)BIO_flush(b64_bio); //Flush data. Necessary for b64 encoding, because of pad characters. + BIO_get_mem_ptr(mem_bio, &mem_bio_mem_ptr); //Store address of mem_bio's memory structure. + (void)BIO_set_close(mem_bio, BIO_NOCLOSE); //Permit access to mem_ptr after BIOs are destroyed. + BIO_free_all(b64_bio); //Destroys all BIOs in chain, starting with b64 (i.e. the 1st one). + BUF_MEM_grow(mem_bio_mem_ptr, (*mem_bio_mem_ptr).length + 1); //Makes space for end null. + (*mem_bio_mem_ptr).data[(*mem_bio_mem_ptr).length] = '\0'; //Adds null-terminator to tail. + return (unsigned char*)(*mem_bio_mem_ptr).data; //Returns base-64 encoded data. (See: "buf_mem_st" struct). +} +void encrypt_aes_128(unsigned char* in, const unsigned char* mykey){ + + int j=0,k=0; + int totalSize=0; + AES_KEY key; + unsigned char iv[8] = {0}; //changed + unsigned char out[1024]; //changed + AES_set_encrypt_key(mykey, 128, &key); + char total[256]; + int size=0; + struct ctr_state state; + init_ctr(&state, iv); + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + CRYPTO_ctr128_encrypt(in, out, strlen((char*)in), &key, state.ivec, state.ecount, &state.num, (block128_f)AES_encrypt); +#else + AES_ctr128_encrypt(in, out, strlen((char*)in), &key, state.ivec, state.ecount, &state.num); +#endif + + totalSize += strlen((char*)in); + size = strlen((char*)in); + for (j = 0; j< size; j++) { + total[k++]=out[j]; + } + + unsigned char *base64_encoded = base64encode(total, totalSize); + printf("%s\n",base64_encoded); + +} +void generate_aes_128_key(char* filePath, unsigned char* returnedKey){ + int i; + int part; + FILE* fptr; + char key[16]; + struct timespec times; + clock_gettime(CLOCK_REALTIME,×); + srand(times.tv_nsec); + + for (i = 0; i < 16; i++) { + part = (rand() % 3); + if(part == 0){ + key[i] = (rand() % 10) + 48; + } + + else if(part == 1){ + key[i] = (rand() % 26) + 65; + } + + else if(part == 2){ + key[i] = (rand() % 26) + 97; + } + } + fptr = fopen(filePath, "w"); + for(i = 0; i < 16; i++){ + fputc(key[i], fptr); + } + strcpy((char*)returnedKey, key); + fclose(fptr); + + +} + +unsigned char *base64decode (const void *b64_decode_this, int decode_this_many_bytes){ + BIO *b64_bio, *mem_bio; //Declares two OpenSSL BIOs: a base64 filter and a memory BIO. + unsigned char *base64_decoded = (unsigned char*)calloc( (decode_this_many_bytes*3)/4+1, sizeof(char) ); //+1 = null. + b64_bio = BIO_new(BIO_f_base64()); //Initialize our base64 filter BIO. + mem_bio = BIO_new(BIO_s_mem()); //Initialize our memory source BIO. + BIO_write(mem_bio, b64_decode_this, decode_this_many_bytes); //Base64 data saved in source. + BIO_push(b64_bio, mem_bio); //Link the BIOs by creating a filter-source BIO chain. + BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines. + int decoded_byte_index = 0; //Index where the next base64_decoded byte should be written. + while ( 0 < BIO_read(b64_bio, base64_decoded+decoded_byte_index, 1) ){ //Read byte-by-byte. + decoded_byte_index++; //Increment the index until read of BIO decoded data is complete. + } //Once we're done reading decoded data, BIO_read returns -1 even though there's no error. + BIO_free_all(b64_bio); //Destroys all BIOs in chain, starting with b64 (i.e. the 1st one). + return base64_decoded; //Returns base-64 decoded data with trailing null terminator. +} +int decodedTextSize(char *input){ + int i=0; + int result=0,padding=0; + int size=strlen(input); + for (i = 0; i < size; ++i) { + if(input[i]=='='){ + padding++; + } + } + result=(strlen(input)/4*3)-padding; + return result; +} +void decrypt_aes_128(char* in, const unsigned char* mykey){ + + unsigned char iv[8] = {0}; + AES_KEY key; + unsigned char outdata[256]; + AES_set_encrypt_key(mykey, 128, &key); + int newTotalSize=decodedTextSize(in); + int bytes_to_decode = strlen(in); + unsigned char *encryptedText = base64decode(in, bytes_to_decode); + char last[1024]=""; + struct ctr_state state; + init_ctr(&state, iv); + memset(outdata,'\0', sizeof(outdata)); + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + CRYPTO_ctr128_encrypt(encryptedText,outdata,newTotalSize,&key, state.ivec, state.ecount, &state.num, (block128_f)AES_encrypt); +#else + AES_ctr128_encrypt(encryptedText, outdata, newTotalSize, &key, state.ivec, state.ecount, &state.num); +#endif + + strcat(last,(char*)outdata); + printf("%s\n",last); +} + static int get_int_value(const char* s, int default_value) { if (!s || !(s[0])) @@ -938,6 +1106,9 @@ static void set_option(int c, char *value) } switch (c) { + case 'K': + turn_params.keep_address_family = get_bool_value(value); + break; case SERVER_NAME_OPT: STRCPY(turn_params.oauth_server_name,value); break; @@ -1144,10 +1315,12 @@ static void set_option(int c, char *value) } break; case 'v': - if(get_bool_value(value)) { - turn_params.verbose = TURN_VERBOSE_NORMAL; - } else { - turn_params.verbose = TURN_VERBOSE_NONE; + if(turn_params.verbose != TURN_VERBOSE_EXTRA){ + if(get_bool_value(value)) { + turn_params.verbose = TURN_VERBOSE_NORMAL; + } else { + turn_params.verbose = TURN_VERBOSE_NONE; + } } break; case 'V': @@ -1162,6 +1335,7 @@ static void set_option(int c, char *value) if (get_bool_value(value)) { turn_params.ct = TURN_CREDENTIALS_LONG_TERM; use_lt_credentials=1; + use_ltc=1; } else { turn_params.ct = TURN_CREDENTIALS_UNDEFINED; use_lt_credentials=0; @@ -1223,12 +1397,14 @@ static void set_option(int c, char *value) #endif case AUTH_SECRET_OPT: turn_params.use_auth_secret_with_timestamp = 1; + use_tltc = 1; turn_params.ct = TURN_CREDENTIALS_LONG_TERM; use_lt_credentials = 1; break; case STATIC_AUTH_SECRET_VAL_OPT: add_to_secrets_list(&turn_params.default_users_db.ram_db.static_auth_secrets,value); turn_params.use_auth_secret_with_timestamp = 1; + use_tltc = 1; turn_params.ct = TURN_CREDENTIALS_LONG_TERM; use_lt_credentials = 1; break; @@ -1238,12 +1414,12 @@ static void set_option(int c, char *value) case 'r': set_default_realm_name(value); break; - case 'Q': - turn_params.total_quota = (vint)atoi(value); - get_realm(NULL)->options.perf_options.user_quota = atoi(value); - break; case 'q': turn_params.user_quota = (vint)atoi(value); + get_realm(NULL)->options.perf_options.user_quota = atoi(value); + break; + case 'Q': + turn_params.total_quota = (vint)atoi(value); get_realm(NULL)->options.perf_options.total_quota = atoi(value); break; case 's': @@ -1293,6 +1469,9 @@ static void set_option(int c, char *value) case DH_FILE_OPT: STRCPY(turn_params.dh_file,value); break; + case SECRET_KEY_OPT: + STRCPY(turn_params.secret_key_file,value); + break; case PKEY_FILE_OPT: STRCPY(turn_params.pkey_file,value); break; @@ -1421,7 +1600,7 @@ static void read_config_file(int argc, char **argv, int pass) FILE *f = NULL; char *full_path_to_config_file = NULL; - full_path_to_config_file = find_config_file(config_file, 1); + full_path_to_config_file = find_config_file(config_file, pass); if (full_path_to_config_file) f = fopen(full_path_to_config_file, "r"); @@ -1462,6 +1641,10 @@ static void read_config_file(int argc, char **argv, int pass) } else if((pass > 0) && (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); + } + } } @@ -1480,6 +1663,8 @@ static int adminmain(int argc, char **argv) TURNADMIN_COMMAND_TYPE ct = TA_COMMAND_UNKNOWN; int is_admin = 0; + FILE* fptr; + unsigned char generated_key[16]; //changed u08bits user[STUN_MAX_USERNAME_SIZE+1]="\0"; u08bits realm[STUN_MAX_REALM_SIZE+1]="\0"; @@ -1492,84 +1677,88 @@ static int adminmain(int argc, char **argv) uo.u.m = admin_long_options; int print_enc_password = 0; + int print_enc_aes_password = 0; while (((c = getopt_long(argc, argv, ADMIN_OPTIONS, uo.u.o, NULL)) != -1)) { switch (c){ - case 'P': - if(pwd[0]) { - char result[257]; - generate_new_enc_password((char*)pwd, result); - printf("%s\n",result); - exit(0); - } - print_enc_password = 1; - break; - case 'g': - ct = TA_SET_REALM_OPTION; - break; - 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); @@ -1600,45 +1789,67 @@ static int adminmain(int argc, char **argv) turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_REDIS; break; #endif - case 'u': - STRCPY(user,optarg); - if(!is_secure_username((u08bits*)user)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong user name structure or symbols, choose another name: %s\n",user); - exit(-1); - } - if(SASLprep((u08bits*)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((u08bits*)realm)<0) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong realm: %s\n",realm); - exit(-1); - } - break; - case 'p': - STRCPY(pwd,optarg); - if(SASLprep((u08bits*)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); - } - break; - case 'h': - printf("\n%s\n", AdminUsage); - exit(0); - break; - default: - fprintf(stderr,"\n%s\n", AdminUsage); - exit(-1); + case 'u': + STRCPY(user,optarg); + if(!is_secure_username((u08bits*)user)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong user name structure or symbols, choose another name: %s\n",user); + exit(-1); + } + if(SASLprep((u08bits*)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((u08bits*)realm)<0) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong realm: %s\n",realm); + exit(-1); + } + break; + case 'p': + STRCPY(pwd,optarg); + if(SASLprep((u08bits*)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); + fread (generated_key, sizeof(char), 16, 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); } } @@ -1914,12 +2125,6 @@ int main(int argc, char **argv) if(strstr(argv[0],"turnadmin")) return adminmain(argc,argv); - { - unsigned long mfn = set_system_parameters(1); - - print_features(mfn); - } - read_config_file(argc,argv,0); struct uoptions uo; @@ -1932,12 +2137,19 @@ int main(int argc, char **argv) read_config_file(argc,argv,1); + { + unsigned long mfn = set_system_parameters(1); + + print_features(mfn); + } + if(!get_realm(NULL)->options.name[0]) { STRCPY(get_realm(NULL)->options.name,turn_params.domain); } 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.oauth && turn_params.oauth_server_name[0]) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "oAuth server name: %s\n",turn_params.oauth_server_name); } @@ -1989,6 +2201,12 @@ int main(int argc, char **argv) exit(-1); } + if(use_ltc && use_tltc) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "\nCONFIGURATION ALERT: You specified --lt-cred-mech and --use-auth-secret in the same time.\n" + "Be aware that you could not mix the username/password and the shared secret based auth methohds. \n" + "Shared secret overrides username/password based auth method. Check your configuration!\n"); + } + if(!use_lt_credentials && !anon_credentials) { if(turn_params.default_users_db.ram_db.users_number) { TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "\nCONFIGURATION ALERT: you specified long-term user accounts, (-u option) \n but you did not specify the long-term credentials option\n (-a or --lt-cred-mech option).\n I am turning --lt-cred-mech ON for you, but double-check your configuration.\n"); @@ -2140,6 +2358,9 @@ int main(int argc, char **argv) setup_server(); + struct event *ev = evsignal_new(turn_params.listener.event_base, SIGUSR2, reload_ssl_certs, NULL); + event_add(ev, NULL); + drop_privileges(); run_listener_server(&(turn_params.listener)); @@ -2477,8 +2698,10 @@ static int ServerALPNCallback(SSL *ssl, #endif -static void set_ctx(SSL_CTX* ctx, const char *protocol) +static void set_ctx(SSL_CTX** out, const char *protocol, const SSL_METHOD* method) { + SSL_CTX* ctx = SSL_CTX_new(method); + int err = 0; #if ALPN_SUPPORTED SSL_CTX_set_alpn_select_cb(ctx, ServerALPNCallback, NULL); #endif @@ -2495,6 +2718,7 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) if (!SSL_CTX_use_certificate_chain_file(ctx, turn_params.cert_file)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: no certificate found\n", protocol); + err = 1; } else { print_abs_file_name(protocol, ": Certificate", turn_params.cert_file); } @@ -2502,6 +2726,7 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) if (!SSL_CTX_use_PrivateKey_file(ctx, turn_params.pkey_file, SSL_FILETYPE_PEM)) { if (!SSL_CTX_use_RSAPrivateKey_file(ctx, turn_params.pkey_file, SSL_FILETYPE_PEM)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: no valid private key found, or invalid private key password provided\n", protocol); + err = 1; } else { print_abs_file_name(protocol, ": Private RSA key", turn_params.pkey_file); } @@ -2511,12 +2736,14 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) if (!SSL_CTX_check_private_key(ctx)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: invalid private key\n", protocol); + err = 1; } if(turn_params.ca_cert_file[0]) { if (!SSL_CTX_load_verify_locations(ctx, turn_params.ca_cert_file, NULL )) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot load CA from file: %s\n", turn_params.ca_cert_file); + err = 1; } SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(turn_params.ca_cert_file)); @@ -2614,15 +2841,32 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) */ if(!dh) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot allocate DH suite\n",__FUNCTION__); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot allocate DH suite\n",__FUNCTION__); + err = 1; } else { if (1 != SSL_CTX_set_tmp_dh (ctx, dh)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot set DH\n",__FUNCTION__); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot set DH\n",__FUNCTION__); + err = 1; } DH_free (dh); } } + {//secret key + + if(turn_params.secret_key_file[0]) { + FILE *f = fopen(turn_params.secret_key_file, "r"); + + if (!f) { + perror("Cannot open Secret-Key file"); + } else { + fseek (f, 0, SEEK_SET); + fread (turn_params.secret_key, sizeof(char), 16, f); + fclose (f); + } + } + } + { int op = 0; @@ -2671,8 +2915,17 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) SSL_CTX_set_options(ctx, op); } + + if (*out == NULL) { + // Always initialize, even if issues were encountered + *out = ctx; + } else if (!err) { + SSL_CTX_free(*out); + *out = ctx; + } } +static void openssl_load_certificates(void); static void openssl_setup(void) { THREAD_setup(); @@ -2702,22 +2955,24 @@ static void openssl_setup(void) adjust_key_file_names(); } + openssl_load_certificates(); +} + +static void openssl_load_certificates(void) +{ + pthread_mutex_lock(&turn_params.tls_mutex); if(!turn_params.no_tls) { - turn_params.tls_ctx_ssl23 = SSL_CTX_new(SSLv23_server_method()); /*compatibility mode */ - set_ctx(turn_params.tls_ctx_ssl23,"SSL23"); + set_ctx(&turn_params.tls_ctx_ssl23,"SSL23",SSLv23_server_method()); /*compatibility mode */ if(!turn_params.no_tlsv1) { - turn_params.tls_ctx_v1_0 = SSL_CTX_new(TLSv1_server_method()); - set_ctx(turn_params.tls_ctx_v1_0,"TLS1.0"); + set_ctx(&turn_params.tls_ctx_v1_0,"TLS1.0",TLSv1_server_method()); } #if TLSv1_1_SUPPORTED if(!turn_params.no_tlsv1_1) { - turn_params.tls_ctx_v1_1 = SSL_CTX_new(TLSv1_1_server_method()); - set_ctx(turn_params.tls_ctx_v1_1,"TLS1.1"); + set_ctx(&turn_params.tls_ctx_v1_1,"TLS1.1",TLSv1_1_server_method()); } #if TLSv1_2_SUPPORTED if(!turn_params.no_tlsv1_2) { - turn_params.tls_ctx_v1_2 = SSL_CTX_new(TLSv1_2_server_method()); - set_ctx(turn_params.tls_ctx_v1_2,"TLS1.2"); + set_ctx(&turn_params.tls_ctx_v1_2,"TLS1.2",TLSv1_2_server_method()); } #endif #endif @@ -2733,20 +2988,31 @@ static void openssl_setup(void) } #if DTLSv1_2_SUPPORTED - turn_params.dtls_ctx = SSL_CTX_new(DTLS_server_method()); - turn_params.dtls_ctx_v1_2 = SSL_CTX_new(DTLSv1_2_server_method()); - set_ctx(turn_params.dtls_ctx_v1_2,"DTLS1.2"); + set_ctx(&turn_params.dtls_ctx,"DTLS",DTLS_server_method()); + set_ctx(&turn_params.dtls_ctx_v1_2,"DTLS1.2",DTLSv1_2_server_method()); SSL_CTX_set_read_ahead(turn_params.dtls_ctx_v1_2, 1); #else - turn_params.dtls_ctx = SSL_CTX_new(DTLSv1_server_method()); + set_ctx(&turn_params.dtls_ctx,"DTLS",DTLSv1_server_method()); #endif - set_ctx(turn_params.dtls_ctx,"DTLS"); SSL_CTX_set_read_ahead(turn_params.dtls_ctx, 1); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS cipher suite: %s\n",turn_params.cipher_list); #endif } + pthread_mutex_unlock(&turn_params.tls_mutex); +} + +static void reload_ssl_certs(evutil_socket_t sock, short events, void *args) +{ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Reloading TLS certificates and keys\n"); + openssl_load_certificates(); + if (turn_params.tls_ctx_update_ev != NULL) + event_active(turn_params.tls_ctx_update_ev, EV_READ, 0); + + UNUSED_ARG(sock); + UNUSED_ARG(events); + UNUSED_ARG(args); } /////////////////////////////// diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index 544a3bc7..21375d58 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -77,6 +77,14 @@ #include "ns_ioalib_impl.h" +#include +#include +#include + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + #include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -198,6 +206,9 @@ typedef struct _turn_params_ { int no_tls; int no_dtls; + struct event *tls_ctx_update_ev; + pthread_mutex_t tls_mutex; + //////////////// Common params //////////////////// int verbose; @@ -306,6 +317,11 @@ typedef struct _turn_params_ { unsigned long cpus; + ///////// Encryption ///////// + char secret_key_file[1025]; + unsigned char secret_key[1025]; + int keep_address_family; + } turn_params_t; extern turn_params_t turn_params; @@ -354,6 +370,24 @@ void set_bps_capacity(band_limit_t value); band_limit_t get_max_bps(void); void set_max_bps(band_limit_t value); +///////// AES ENCRYPTION AND DECRYPTION //////// + +struct ctr_state { + unsigned char ivec[16]; + unsigned int num; + unsigned char ecount[16]; +}; +void generate_aes_128_key(char* filePath, unsigned char* returnedKey); +unsigned char *base64encode (const void *b64_encode_this, int encode_this_many_bytes); +void encrypt_aes_128(unsigned char* in, const unsigned char* mykey); +unsigned char *base64decode (const void *b64_decode_this, int decode_this_many_bytes); +void decrypt_aes_128(char* in, const unsigned char* mykey); +int decodedTextSize(char *input); +char* decryptPassword(char* in, const unsigned char* mykey); +int init_ctr(struct ctr_state *state, const unsigned char iv[8]); + + + /////////////////////////////// #ifdef __cplusplus diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index d7d98cf8..bf0eecf8 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -298,6 +298,63 @@ void del_tls_alternate_server(const char *saddr) ////////////////////////////////////////////////// +typedef struct update_ssl_ctx_cb_args { + ioa_engine_handle engine; + turn_params_t *params; + struct event *next; +} update_ssl_ctx_cb_args_t; + +static void update_ssl_ctx(evutil_socket_t sock, short events, update_ssl_ctx_cb_args_t *args) +{ + ioa_engine_handle e = args->engine; + turn_params_t *params = args->params; + + pthread_mutex_lock(&turn_params.tls_mutex); + e->tls_ctx_ssl23 = params->tls_ctx_ssl23; + e->tls_ctx_v1_0 = params->tls_ctx_v1_0; +#if TLSv1_1_SUPPORTED + e->tls_ctx_v1_1 = params->tls_ctx_v1_1; +#if TLSv1_2_SUPPORTED + e->tls_ctx_v1_2 = params->tls_ctx_v1_2; +#endif +#endif +#if DTLS_SUPPORTED + e->dtls_ctx = params->dtls_ctx; +#endif +#if DTLSv1_2_SUPPORTED + e->dtls_ctx_v1_2 = params->dtls_ctx_v1_2; +#endif + struct event *next = args->next; + pthread_mutex_unlock(&turn_params.tls_mutex); + + if (next != NULL) + event_active(next, EV_READ, 0); + + UNUSED_ARG(sock); + UNUSED_ARG(events); +} + +static void set_ssl_ctx(ioa_engine_handle e, turn_params_t *params) +{ + update_ssl_ctx_cb_args_t *args = (update_ssl_ctx_cb_args_t *)turn_malloc(sizeof(update_ssl_ctx_cb_args_t)); + args->engine = e; + args->params = params; + args->next = NULL; + + update_ssl_ctx(-1, 0, args); + + struct event_base *base = e->event_base; + if (base != NULL) { + struct event *ev = event_new(base, -1, EV_PERSIST, (event_callback_fn)update_ssl_ctx, (void *)args); + pthread_mutex_lock(&turn_params.tls_mutex); + args->next = params->tls_ctx_update_ev; + params->tls_ctx_update_ev = ev; + pthread_mutex_unlock(&turn_params.tls_mutex); + } +} + +////////////////////////////////////////////////// + void add_listener_addr(const char* addr) { ioa_addr baddr; if(make_ioa_addr((const u08bits*)addr,0,&baddr)<0) { @@ -962,20 +1019,7 @@ static ioa_engine_handle create_new_listener_engine(void) ,turn_params.redis_statsdb #endif ); - set_ssl_ctx(e, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0 -#if TLSv1_1_SUPPORTED - ,turn_params.tls_ctx_v1_1 -#if TLSv1_2_SUPPORTED - ,turn_params.tls_ctx_v1_2 -#endif -#endif -#if DTLS_SUPPORTED - ,turn_params.dtls_ctx -#endif -#if DTLSv1_2_SUPPORTED - ,turn_params.dtls_ctx_v1_2 -#endif - ); + set_ssl_ctx(e, &turn_params); ioa_engine_set_rtcp_map(e, turn_params.listener.rtcpmap); return e; } @@ -1018,23 +1062,8 @@ static void setup_listener(void) if(!turn_params.listener.ioa_eng) exit(-1); - set_ssl_ctx(turn_params.listener.ioa_eng, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0 -#if TLSv1_1_SUPPORTED - ,turn_params.tls_ctx_v1_1 -#if TLSv1_2_SUPPORTED - ,turn_params.tls_ctx_v1_2 -#endif -#endif -#if DTLS_SUPPORTED - ,turn_params.dtls_ctx -#endif -#if DTLSv1_2_SUPPORTED - ,turn_params.dtls_ctx_v1_2 -#endif - ); - + set_ssl_ctx(turn_params.listener.ioa_eng, &turn_params); turn_params.listener.rtcpmap = rtcp_map_create(turn_params.listener.ioa_eng); - ioa_engine_set_rtcp_map(turn_params.listener.ioa_eng, turn_params.listener.rtcpmap); { @@ -1592,20 +1621,7 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int ,turn_params.redis_statsdb #endif ); - set_ssl_ctx(rs->ioa_eng, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0 -#if TLSv1_1_SUPPORTED - ,turn_params.tls_ctx_v1_1 -#if TLSv1_2_SUPPORTED - ,turn_params.tls_ctx_v1_2 -#endif -#endif -#if DTLS_SUPPORTED - ,turn_params.dtls_ctx -#endif -#if DTLSv1_2_SUPPORTED - ,turn_params.dtls_ctx_v1_2 -#endif - ); + set_ssl_ctx(rs->ioa_eng, &turn_params); ioa_engine_set_rtcp_map(rs->ioa_eng, turn_params.listener.rtcpmap); } @@ -1651,7 +1667,10 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int send_turn_session_info, send_https_socket, allocate_bps, - turn_params.oauth, turn_params.oauth_server_name, use_http); + turn_params.oauth, + turn_params.oauth_server_name, + use_http, + turn_params.keep_address_family); if(to_set_rfc5780) { set_rfc5780(&(rs->server), get_alt_addr, send_message_from_listener_to_client); @@ -1770,11 +1789,13 @@ static void* run_auth_server_thread(void *arg) static void setup_auth_server(struct auth_server *as) { - if(pthread_create(&(as->thr), NULL, run_auth_server_thread, as)) { + pthread_attr_t attr; + if(pthread_attr_init(&attr) || + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) || + pthread_create(&(as->thr), &attr, run_auth_server_thread, as)) { perror("Cannot create auth thread\n"); exit(-1); } - pthread_detach(as->thr); } static void* run_admin_server_thread(void *arg) diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 825f4736..02eba0a8 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -436,39 +436,6 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm, } } -void set_ssl_ctx(ioa_engine_handle e, - SSL_CTX *tls_ctx_ssl23, - SSL_CTX *tls_ctx_v1_0 -#if TLSv1_1_SUPPORTED - ,SSL_CTX *tls_ctx_v1_1 -#if TLSv1_2_SUPPORTED - ,SSL_CTX *tls_ctx_v1_2 -#endif -#endif -#if DTLS_SUPPORTED - ,SSL_CTX *dtls_ctx -#endif -#if DTLSv1_2_SUPPORTED - ,SSL_CTX *dtls_ctx_v1_2 -#endif -) -{ - e->tls_ctx_ssl23 = tls_ctx_ssl23; - e->tls_ctx_v1_0 = tls_ctx_v1_0; -#if TLSv1_1_SUPPORTED - e->tls_ctx_v1_1 = tls_ctx_v1_1; -#if TLSv1_2_SUPPORTED - e->tls_ctx_v1_2 = tls_ctx_v1_2; -#endif -#endif -#if DTLS_SUPPORTED - e->dtls_ctx = dtls_ctx; -#endif -#if DTLSv1_2_SUPPORTED - e->dtls_ctx_v1_2 = dtls_ctx_v1_2; -#endif -} - void ioa_engine_set_rtcp_map(ioa_engine_handle e, rtcp_map *rtcpmap) { if(e) @@ -1953,10 +1920,9 @@ 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, (u16bits)buf_size, 0, (size_t)ret); } - - BIO_free(rbio); #if OPENSSL_VERSION_NUMBER < 0x10100000L ssl->rbio = NULL; + BIO_free(rbio); #else SSL_set0_rbio(ssl,NULL); #endif @@ -3611,14 +3577,14 @@ void turn_report_allocation_delete(void *a) } } -void turn_report_session_usage(void *session) +void turn_report_session_usage(void *session, int force_invalid) { if(session) { ts_ur_super_session *ss = (ts_ur_super_session *)session; turn_turnserver *server = (turn_turnserver*)ss->server; - if(server && (ss->received_packets || ss->sent_packets)) { + if(server && (ss->received_packets || ss->sent_packets || force_invalid)) { ioa_engine_handle e = turn_server_get_engine(server); - if(((ss->received_packets+ss->sent_packets)&2047)==0) { + if(((ss->received_packets+ss->sent_packets)&2047)==0 || force_invalid) { if(e && e->verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"session %018llu: usage: realm=<%s>, username=<%s>, rp=%lu, rb=%lu, sp=%lu, sb=%lu\n", (unsigned long long)(ss->id), (char*)ss->realm_options.name, (char*)ss->username, (unsigned long)(ss->received_packets), (unsigned long)(ss->received_bytes),(unsigned long)(ss->sent_packets),(unsigned long)(ss->sent_bytes)); } @@ -3648,7 +3614,7 @@ void turn_report_session_usage(void *session) } } - report_turn_session_info(server,ss,0); + report_turn_session_info(server,ss,force_invalid); ss->received_packets=0; ss->received_bytes=0; diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index cfb393a7..7b9acabe 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -258,23 +258,6 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm, #endif ); -void set_ssl_ctx(ioa_engine_handle e, - SSL_CTX *tls_ctx_ssl23, - SSL_CTX *tls_ctx_v1_0 -#if TLSv1_1_SUPPORTED - ,SSL_CTX *tls_ctx_v1_1 -#if TLSv1_2_SUPPORTED - ,SSL_CTX *tls_ctx_v1_2 -#endif -#endif -#if DTLS_SUPPORTED - ,SSL_CTX *dtls_ctx -#endif -#if DTLSv1_2_SUPPORTED - ,SSL_CTX *dtls_ctx_v1_2 -#endif -); - void ioa_engine_set_rtcp_map(ioa_engine_handle e, rtcp_map *rtcpmap); ioa_socket_handle create_ioa_socket_from_fd(ioa_engine_handle e, ioa_socket_raw fd, ioa_socket_handle parent_s, SOCKET_TYPE st, SOCKET_APP_TYPE sat, const ioa_addr *remote_addr, const ioa_addr *local_addr); diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 14c3ae9b..6c68c47f 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1413,7 +1413,7 @@ static char *get_bold_admin_title(void) if(as->as_ok) { if(as->as_login[0]) { char *dst=sbat+strlen(sbat); - snprintf(dst,ADMIN_USER_MAX_LENGTH*2," admin user: %s
\r\n",as->as_login); + snprintf(dst,ADMIN_USER_MAX_LENGTH*2+2," admin user: %s
\r\n",as->as_login); } if(as->as_realm[0]) { char *dst=sbat+strlen(sbat); diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 5606f685..c4495ad2 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -328,13 +328,15 @@ int main(int argc, char **argv) passive_tcp = 1; /* implies 'T': */ /* no break */ + /* Falls through. */ case 'T': relay_transport = STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE; break; case 'U': - use_null_cipher = 1; - /* implies 'S' */ - /* no break */ + use_null_cipher = 1; + /* implies 'S' */ + /* no break */ + /* Falls through. */ case 'S': use_secure = 1; break; diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index b842bfef..ecd61bdf 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -261,6 +261,7 @@ int send_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int data_con TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Socket write error 111.666: \n"); if (handle_socket_error()) break; + /* Falls through. */ case SSL_ERROR_SSL: { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SSL write error: \n"); @@ -270,6 +271,7 @@ int send_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int data_con ERR_error_string(ERR_get_error(),buf), SSL_get_error(ssl, len)); } + /* Falls through. */ default: clnet_info->broken = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Unexpected error while writing!\n"); @@ -457,6 +459,7 @@ int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, in "Socket read error 111.999: \n"); if (handle_socket_error()) break; + /* Falls through. */ case SSL_ERROR_SSL: { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SSL write error: \n"); char buf[1024]; @@ -464,6 +467,7 @@ int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, in ERR_error_string(ERR_get_error(), buf), SSL_get_error(ssl, rc)); } + /* Falls through. */ default: clnet_info->broken = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, @@ -525,6 +529,7 @@ int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, in "Socket read error 111.999: \n"); if (handle_socket_error()) break; + /* Falls through. */ case SSL_ERROR_SSL: { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SSL write error: \n"); char buf[1024]; @@ -532,6 +537,7 @@ int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, in ERR_error_string(ERR_get_error(), buf), SSL_get_error(ssl, rc)); } + /* Falls through. */ default: clnet_info->broken = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index 225968c5..5b50d945 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.5.0.7" +#define TURN_SERVER_VERSION "4.5.0.8" #define TURN_SERVER_VERSION_NAME "dan Eider" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'" diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index cf4fd12e..32c7aa9f 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -187,7 +187,7 @@ void ioa_network_buffer_delete(ioa_engine_handle e, ioa_network_buffer_handle nb */ void turn_report_allocation_set(void *a, turn_time_t lifetime, int refresh); void turn_report_allocation_delete(void *a); -void turn_report_session_usage(void *session); +void turn_report_session_usage(void *session, int force_invalid); /* * Network event handler callback diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index fa957e68..5eaf6172 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -34,6 +34,7 @@ #include "ns_turn_allocation.h" #include "ns_turn_msg_addr.h" #include "ns_turn_ioalib.h" +#include "../apps/relay/ns_ioalib_impl.h" /////////////////////////////////////////// @@ -42,14 +43,19 @@ //////////////////////////////////////////////// -static inline int get_family(int stun_family) { +static inline int get_family(int stun_family, ioa_engine_handle e, ioa_socket_handle client_socket) { switch(stun_family) { case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4: return AF_INET; + break; case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6: return AF_INET6; + break; case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT: - return AF_INET; + if(e->default_relays && get_ioa_socket_address_family(client_socket) == AF_INET6) + return AF_INET6; + else + return AF_INET; default: return AF_INET; }; @@ -58,7 +64,7 @@ static inline int get_family(int stun_family) { //////////////////////////////////////////////// const char * get_version(turn_turnserver *server) { - if(server && !server->prod) { + if(server && !*server->prod) { return (const char *) TURN_SOFTWARE; } else { return (const char *) "None"; @@ -1146,6 +1152,7 @@ static int handle_turn_allocate(turn_turnserver *server, *reason = (const u08bits *)"Even Port cannot be used with Dual Allocation"; break; } + /* Falls through. */ case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY: { if(in_reservation_token) { *err_code = 400; @@ -1252,12 +1259,25 @@ static int handle_turn_allocate(turn_turnserver *server, if(!(*err_code)) { if(!af4 && !af6) { - int af4res = create_relay_connection(server, ss, lifetime, - STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT, transport, - even_port, in_reservation_token, &out_reservation_token, - err_code, reason, - tcp_peer_accept_connection); - if(af4res<0) { + int a_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT; + if (server->keep_address_family) { + switch(get_ioa_socket_address_family(ss->client_socket)) { + case AF_INET6 : + a_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; + break; + case AF_INET : + a_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4; + break; + } + } + + int res = create_relay_connection(server, ss, lifetime, + a_family, transport, + even_port, in_reservation_token, &out_reservation_token, + err_code, reason, + tcp_peer_accept_connection); + + if(res<0) { set_relay_session_failure(alloc,AF_INET); if(!(*err_code)) { *err_code = 437; @@ -1851,7 +1871,7 @@ static void tcp_deliver_delayed_buffer(unsent_buffer *ub, ioa_socket_handle s, t } else { ++(ss->sent_packets); ss->sent_bytes += bytes; - turn_report_session_usage(ss); + turn_report_session_usage(ss, 0); } pop_unsent_buffer(ub); } while(!ioa_socket_tobeclosed(s) && ((i++)sent_packets); ss->sent_bytes += bytes; - turn_report_session_usage(ss); + turn_report_session_usage(ss, 0); } } @@ -1929,7 +1949,7 @@ static void tcp_client_input_handler_rfc6062data(ioa_socket_handle s, int event_ set_ioa_socket_tobeclosed(s); } - turn_report_session_usage(ss); + turn_report_session_usage(ss, 0); } static void tcp_conn_bind_timeout_handler(ioa_engine_handle e, void *arg) @@ -4082,7 +4102,7 @@ int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, if (!ss) return -1; - report_turn_session_info(server,ss,1); + turn_report_session_usage(ss, 1); dec_quota(ss); dec_bps(ss); @@ -4217,7 +4237,7 @@ static int write_client_connection(turn_turnserver *server, ts_ur_super_session* if(!skip) { ++(ss->sent_packets); ss->sent_bytes += (u32bits)ioa_network_buffer_get_size(nbh); - turn_report_session_usage(ss); + turn_report_session_usage(ss, 0); } FUNCEND; @@ -4306,8 +4326,10 @@ static int create_relay_connection(turn_turnserver* server, addr_debug_print(server->verbose, get_local_addr_from_ioa_socket(newelem->s), "Local relay addr (RTCP)"); } else { + int family = get_family(address_family,server->e,ss->client_socket); + + newelem = get_relay_session_ss(ss,family); - newelem = get_relay_session_ss(ss,get_family(address_family)); IOA_CLOSE_SOCKET(newelem->s); @@ -4427,7 +4449,7 @@ static int read_client_connection(turn_turnserver *server, if(count_usage) { ++(ss->received_packets); ss->received_bytes += (u32bits)ioa_network_buffer_get_size(in_buffer->nbh); - turn_report_session_usage(ss); + turn_report_session_usage(ss, 0); } if (eve(server->verbose)) { @@ -4827,7 +4849,10 @@ void init_turn_server(turn_turnserver* server, send_turn_session_info_cb send_turn_session_info, send_https_socket_cb send_https_socket, allocate_bps_cb allocate_bps_func, - int oauth, const char* oauth_server_name, int use_http) { + int oauth, + const char* oauth_server_name, + int use_http, + int keep_address_family) { if (!server) return; @@ -4896,6 +4921,8 @@ void init_turn_server(turn_turnserver* server, server->use_http = use_http; + server->keep_address_family = keep_address_family; + set_ioa_timer(server->e, 1, 0, timer_timeout_handler, server, 1, "timer_timeout_handler"); } diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index 4c419421..1f21d3f6 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -172,6 +172,9 @@ struct _turn_turnserver { /* HTTP-Admin-Server: */ int use_http; + + /* Keep Address Family */ + int keep_address_family; }; const char * get_version(turn_turnserver *server); @@ -216,7 +219,8 @@ void init_turn_server(turn_turnserver* server, allocate_bps_cb allocate_bps_func, int oauth, const char* oauth_server_name, - int use_http); + int use_http, + int keep_address_family); ioa_engine_handle turn_server_get_engine(turn_turnserver *s);