1
0
Эх сурвалжийг харах

Imported Upstream version 4.1.2.1

Oleg Moskalenko 11 жил өмнө
parent
commit
f746731b8d

+ 10 - 1
ChangeLog

@@ -1,6 +1,15 @@
+08/14/2014 Oleg Moskalenko <[email protected]>
+Version 4.1.2.1 'Vitari':
+	- The origin attribute is verified in the subsequent 
+	session messages (server flag --check-origin-consistency).
+	- MySQL SSL connection support.
+	- Crash fixed when the DB connection string is incorrect.
+	- Minor docs fixes.
+	
 07/29/2014 Oleg Moskalenko <[email protected]>
 Version 4.1.1.1 'Vitari':
-	- Forceful session concellation (TODO).
+	- Forceful server-side session cancellation implemented
+	(in telnet console).
 	
 07/22/2014 Oleg Moskalenko <[email protected]>
 Version 4.1.0.2 'Vitari':

+ 7 - 2
INSTALL

@@ -232,8 +232,7 @@ The following platforms have been used in the development:
 	- FreeBSD 8.x, i386
 	- PC-BSD 9.x, x86_64
 	- Solaris 11, x86_64
-	- Linux CentOS / Red Hat Enterprise Edition 6.3, x86_64 (amd64)
-	- Linux CentOS / Red Hat Enterprise Edition 6.4, x86_32 (i386)
+	- Linux CentOS / Red Hat Enterprise Edition 6.x-7.0, x86_64 (i386 & amd64)
 	- Linux Debian 'Squeeze', i386
 	- Linux Mint 14.1 'Nadia', i386
 	- Linux Mint 16 'Petra', i386
@@ -898,6 +897,12 @@ Or in the turnserver.conf file:
 
 mysql-userdb="host=localhost dbname=turn user=turn password=turn connect_timeout=30"
 
+If you have to use a secure MySQL connection (SSL) then you have to use also
+the optional connection string parameters for the secure communications:
+ca, capath, cert, key, cipher (see 
+http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the 
+command options description).
+
 XVI. MongoDB setup
 
 The MongoDB setup is well documented on their site http://docs.mongodb.org/manual/. 

+ 17 - 6
README.turnserver

@@ -118,6 +118,11 @@ User database settings:
 		Also, see http://www.mysql.org or http://mariadb.org 
 		for full MySQL documentation.
 		
+		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).
+		
 -J, --mongo-userdb	User database connection string for MongoDB. 
 		This database can be used for long-term and short-term 
 		credentials mechanisms, and it can store the secret value 
@@ -222,8 +227,9 @@ Flags:
 			
 --syslog		With this flag, all log will be redirected to the system log (syslog).
 
---simple-log	This flag means that no log file rollover will be used, and the log file
-				name will be constructed as-is, without PID and date appendage.
+--simple-log		This flag means that no log file rollover will be used, and the log file
+			name will be constructed as-is, without PID and date appendage.
+			This option can be used, for example, together with the logrotate tool.
 				
 --secure-stun		Require authentication of the STUN Binding request.
 			By default, the clients are allowed anonymous access to the STUN Binding functionality.
@@ -263,6 +269,11 @@ Flags:
 			(if configured). The load balancing is using the 
 			ALTERNATE-SERVER mechanism. The TURN client must support 
 			300 ALTERNATE-SERVER response for this functionality.
+			
+--check-origin-consistency	The flag that 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).
 
 -h			Help.
     
@@ -305,7 +316,7 @@ Options with required values:
 			on that endpoint only for "symmetry".
 
 --alt-tls-listening-port	Alternative listening port for TLS and DTLS protocols.
-				Default (or zero) value means "TLS listening port plus one".
+			Default (or zero) value means "TLS listening port plus one".
 				
 --aux-server		Auxiliary STUN/TURN server listening endpoint.
 			Aux servers have almost full TURN and STUN functionality.
@@ -382,8 +393,8 @@ Options with required values:
 			and the userdb file). Must be used with long-term credentials 
 			mechanism or with TURN REST API.
 
--C, --rest-api-separator	This is the timestamp/username separator symbol (character) in TURN REST API.
-				The default value is :.
+-C, --rest-api-separator	This is the timestamp/username separator symbol 
+			(character) in TURN REST API. The default value is :.
 
 -q, --user-quota	Per-user allocations quota: how many concurrent 
 			allocations a user can create. This option can also be set 
@@ -527,7 +538,7 @@ Options with required values:
 --cli-max-output-sessions	Maximum number of output sessions in ps CLI command.
 			This value can be changed on-the-fly in CLI. The default value is 256.
 
---ne=[1|2|3]			Set network engine type for the process (for internal purposes).
+--ne=[1|2|3]		Set network engine type for the process (for internal purposes).
 
 ==================================
 

+ 2 - 0
STATUS

@@ -102,6 +102,8 @@ compatibility.
 43) MongoDB support added.
 
 44) Double (dual) allocation added (SSODA draft).
+
+45) Secure MySQL connection implemented.
  
 Things to be implemented in future (the development roadmap) 
 are described in the TODO file.

+ 2 - 4
TODO

@@ -47,7 +47,7 @@
 
 ==================================================================
 
-1) RADIUS integration ?
+1) New security oAuth draft.
 
 ==================================================================
 
@@ -63,9 +63,7 @@
 
 4) Redirect draft.
 
-5) New security oAuth draft.
-
-6) DTLS 1.2 (when available).
+5) DTLS 1.2 (when available).
 
 ==================================================================
 

+ 16 - 1
examples/etc/turnserver.conf

@@ -263,7 +263,13 @@
 # MySQL database connection string in the case that we are using MySQL
 # as the user database.
 # This database can be used for long-term and short-term credential mechanisms
-# and it can store the secret value for secret-based timed authentication in TURN RESP API. 
+# and it can store the secret value for secret-based timed authentication in TURN RESP 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 
+# command options description).
+#
 # Use string format as below (space separated parameters, all optional):
 #
 #mysql-userdb="host=<host> dbname=<database-name> user=<database-user> password=<database-user-password> port=<port> connect_timeout=<seconds>"
@@ -300,6 +306,13 @@
 #
 #realm=mycompany.org
 
+# The flag that 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).
+#
+#check-origin-consistency
+
 # Per-user allocation quota.
 # default value is 0 (no quota, unlimited number of sessions per user).
 # This option can also be set through the database, for a particular realm.
@@ -441,6 +454,8 @@
 
 # This flag means that no log file rollover will be used, and the log file
 # name will be constructed as-is, without PID and date appendage.
+# This option can be used, for example, together with the logrotate tool.
+#
 #simple-log
 
 # Option to set the "redirection" mode. The value of this option

+ 35 - 0
examples/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh

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

+ 1 - 1
man/man1/turnadmin.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "22 July 2014" "" ""
+.TH TURN 1 "18 August 2014" "" ""
 .SH GENERAL INFORMATION
 
 \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage 

+ 16 - 3
man/man1/turnserver.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "22 July 2014" "" ""
+.TH TURN 1 "18 August 2014" "" ""
 .SH GENERAL INFORMATION
 
 The \fBTURN Server\fP project contains the source code of a TURN server and TURN client 
@@ -175,6 +175,11 @@ See the INSTALL file for more explanations and examples.
 .PP
 Also, see http://www.mysql.org or http://mariadb.org 
 for full MySQL documentation.
+.PP
+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 \fIoptions\fP description).
 .RE
 .TP
 .B
@@ -343,6 +348,7 @@ With this flag, all log will be redirected to the system log (syslog).
 \fB\-\-simple\-log\fP
 This flag means that no log file rollover will be used, and the log file
 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\-\-secure\-stun\fP
@@ -404,6 +410,13 @@ ALTERNATE\-SERVER mechanism. The TURN client must support
 300 ALTERNATE\-SERVER response for this functionality.
 .TP
 .B
+\fB\-\-check\-origin\-consistency\fP
+The flag that 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).
+.TP
+.B
 \fB\-h\fP
 Help.
 .TP
@@ -560,8 +573,8 @@ mechanism or with TURN REST API.
 .TP
 .B
 \fB\-C\fP, \fB\-\-rest\-api\-separator\fP
-This is the timestamp/username separator symbol (character) in TURN REST API.
-The default value is :.
+This is the timestamp/username separator symbol 
+(character) in TURN REST API. The default value is :.
 .TP
 .B
 \fB\-q\fP, \fB\-\-user\-quota\fP

+ 1 - 1
man/man1/turnutils.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "22 July 2014" "" ""
+.TH TURN 1 "18 August 2014" "" ""
 .SH GENERAL INFORMATION
 
 A set of turnutils_* programs provides some utility functionality to be used

+ 1 - 1
rpm/build.settings.sh

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

+ 4 - 1
rpm/turnserver.spec

@@ -1,5 +1,5 @@
 Name:		turnserver
-Version:	4.1.1.1
+Version:	4.1.2.1
 Release:	0%{dist}
 Summary:	Coturn TURN Server
 
@@ -235,6 +235,7 @@ fi
 %{_datadir}/%{name}/scripts/longtermsecure/secure_udp_client.sh
 %dir %{_datadir}/%{name}/scripts/longtermsecuredb
 %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_mysql.sh
+%{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_mysql_ssl.sh
 %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_mongo.sh
 %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_psql.sh
 %{_datadir}/%{name}/scripts/longtermsecuredb/secure_relay_with_db_redis.sh
@@ -293,6 +294,8 @@ fi
 %{_includedir}/turn/client/TurnMsgLib.h
 
 %changelog
+* Thu Aug 14 2014 Oleg Moskalenko <[email protected]>
+  - Sync to 4.1.2.1
 * Tue Jul 29 2014 Oleg Moskalenko <[email protected]>
   - Sync to 4.1.1.1
 * Tue Jul 22 2014 Oleg Moskalenko <[email protected]>

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

@@ -124,7 +124,7 @@ static mongoc_collection_t * mongo_get_collection(const char * name) {
 	MONGO * mc = get_mongodb_connection();
 
 	if(!mc) {
-		TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error gettting a connection to MongoDB\n");
+		TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error getting a connection to MongoDB\n");
 		return NULL;
 	}
     

+ 45 - 8
src/apps/relay/dbdrivers/dbd_mysql.c

@@ -46,6 +46,13 @@ struct _Myconninfo {
 	char *password;
 	unsigned int port;
 	unsigned int connect_timeout;
+	/* SSL ==>> */
+	char *key;
+	char *ca;
+	char *cert;
+	char *capath;
+	char *cipher;
+	/* <<== SSL : see http://dev.mysql.com/doc/refman/5.0/en/mysql-ssl-set.html */
 };
 
 typedef struct _Myconninfo Myconninfo;
@@ -56,6 +63,11 @@ static void MyconninfoFree(Myconninfo *co) {
 		if(co->dbname) turn_free(co->dbname, strlen(co->dbname)+1);
 		if(co->user) turn_free(co->user, strlen(co->user)+1);
 		if(co->password) turn_free(co->password, strlen(co->password)+1);
+		if(co->key) turn_free(co->key, strlen(co->key)+1);
+		if(co->ca) turn_free(co->ca, strlen(co->ca)+1);
+		if(co->cert) turn_free(co->cert, strlen(co->cert)+1);
+		if(co->capath) turn_free(co->capath, strlen(co->capath)+1);
+		if(co->cipher) turn_free(co->cipher, strlen(co->cipher)+1);
 		ns_bzero(co,sizeof(Myconninfo));
 	}
 }
@@ -127,6 +139,26 @@ static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) {
 				co->connect_timeout = (unsigned int)atoi(seq+1);
 			else if(!strcmp(s,"timeout"))
 				co->connect_timeout = (unsigned int)atoi(seq+1);
+			else if(!strcmp(s,"key"))
+				co->key = strdup(seq+1);
+			else if(!strcmp(s,"ssl-key"))
+				co->key = strdup(seq+1);
+			else if(!strcmp(s,"ca"))
+				co->ca = strdup(seq+1);
+			else if(!strcmp(s,"ssl-ca"))
+				co->ca = strdup(seq+1);
+			else if(!strcmp(s,"capath"))
+				co->capath = strdup(seq+1);
+			else if(!strcmp(s,"ssl-capath"))
+				co->capath = strdup(seq+1);
+			else if(!strcmp(s,"cert"))
+				co->cert = strdup(seq+1);
+			else if(!strcmp(s,"ssl-cert"))
+				co->cert = strdup(seq+1);
+			else if(!strcmp(s,"cipher"))
+				co->cipher = strdup(seq+1);
+			else if(!strcmp(s,"ssl-cipher"))
+				co->cipher = strdup(seq+1);
 			else {
 				MyconninfoFree(co);
 				co = NULL;
@@ -142,14 +174,16 @@ static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) {
 		turn_free(s0, strlen(s0)+1);
 	}
 
-	if(!(co->dbname))
-		co->dbname=strdup("0");
-	if(!(co->host))
-		co->host=strdup("127.0.0.1");
-	if(!(co->user))
-		co->user=strdup("");
-	if(!(co->password))
-		co->password=strdup("");
+	if(co) {
+		if(!(co->dbname))
+			co->dbname=strdup("0");
+		if(!(co->host))
+			co->host=strdup("127.0.0.1");
+		if(!(co->user))
+			co->user=strdup("");
+		if(!(co->password))
+			co->password=strdup("");
+	}
 
 	return co;
 }
@@ -190,6 +224,9 @@ static MYSQL *get_mydb_connection(void) {
 			} else {
 				if(co->connect_timeout)
 					mysql_options(mydbconnection,MYSQL_OPT_CONNECT_TIMEOUT,&(co->connect_timeout));
+				if(co->ca || co->capath || co->cert || co->cipher || co->key) {
+					mysql_ssl_set(mydbconnection, co->key, co->cert, co->ca, co->capath, co->cipher);
+				}
 				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);

+ 8 - 6
src/apps/relay/dbdrivers/dbd_redis.c

@@ -148,12 +148,14 @@ static Ryconninfo *RyconninfoParse(const char *userdb, char **errmsg) {
 		turn_free(s0, strlen(s0)+1);
 	}
 
-	if(!(co->dbname))
-		co->dbname=strdup("0");
-	if(!(co->host))
-		co->host=strdup("127.0.0.1");
-	if(!(co->password))
-		co->password=strdup("");
+	if(co) {
+		if(!(co->dbname))
+			co->dbname=strdup("0");
+		if(!(co->host))
+			co->host=strdup("127.0.0.1");
+		if(!(co->password))
+			co->password=strdup("");
+	}
 
 	return co;
 }

+ 21 - 6
src/apps/relay/mainrelay.c

@@ -81,7 +81,7 @@ DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,1,
 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,"",
+LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,0,"",
 0,NULL,0,NULL,DEFAULT_GENERAL_RELAY_SERVERS_NUMBER,0,
 ////////////// Auth server /////////////////////////////////////
 {NULL,NULL,NULL,0,NULL},
@@ -361,7 +361,8 @@ static char Usage[] = "Usage: turnserver [options]\n"
 " -X, --external-ip  <public-ip[/private-ip]>	TURN Server public/private address mapping, if the server is behind NAT.\n"
 "						In that situation, if a -X is used in form \"-X ip\" then that ip will be reported\n"
 "						as relay IP address of all allocations. This scenario works only in a simple case\n"
-"						when one single relay address is be used, and no STUN CHANGE_REQUEST functionality is required.\n"
+"						when one single relay address is be used, and no STUN CHANGE_REQUEST\n"
+"						functionality is required.\n"
 "						That single relay address must be mapped by NAT to the 'external' IP.\n"
 "						For that 'external' IP, NAT must forward ports directly (relayed port 12345\n"
 "						must be always mapped to the same 'external' port 12345).\n"
@@ -396,6 +397,10 @@ static char Usage[] = "Usage: turnserver [options]\n"
 "						server is not using any database (just the commands-line settings\n"
 "						and the userdb file). Must be used with long-term credentials \n"
 "						mechanism or with TURN REST API.\n"
+" --check-origin-consistency			The flag that sets the origin consistency check:\n"
+"						across the session, all requests must have the same\n"
+"						main ORIGIN attribute value (if the ORIGIN was\n"
+"						initially used by the session).\n"
 " -q, --user-quota		<number>	Per-user allocation quota: how many concurrent allocations a user can create.\n"
 "						This option can also be set through the database, for a particular realm.\n"
 " -Q, --total-quota		<number>	Total allocations quota: global limit on concurrent allocations.\n"
@@ -424,8 +429,12 @@ static char Usage[] = "Usage: turnserver [options]\n"
 "	                                	This database can be used for long-term and short-term credentials mechanisms,\n"
 "		                                and it can store the secret value(s) for secret-based timed authentication in TURN RESP API.\n"
 "						The connection string my be space-separated list of parameters:\n"
-"	        	          		\"host=<ip-addr> dbname=<database-name> user=<database-user> \\\n								password=<database-user-password> port=<db-port> connect_timeout=<seconds>\".\n"
-"	        	          		All parameters are optional.\n"
+"	        	          		\"host=<ip-addr> dbname=<database-name> user=<database-user> \\\n								password=<database-user-password> port=<db-port> connect_timeout=<seconds>\".\n\n"
+"						The connection string parameters for the secure communications (SSL):\n"
+"						ca, capath, cert, key, cipher\n"
+"						(see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the\n"
+"						command options description).\n\n"
+"	        	          		All connection-string parameters are optional.\n\n"
 #endif
 #if !defined(TURN_NO_MONGO)
 " -J, --mongo-userdb	<connection-string>	MongoDB connection string, if used (default - empty, no MongoDB used).\n"
@@ -437,8 +446,8 @@ static char Usage[] = "Usage: turnserver [options]\n"
 "	                                	This database can be used for long-term and short-term credentials mechanisms,\n"
 "		                                and it can store the secret value(s) for secret-based timed authentication in TURN RESP API.\n"
 "						The connection string my be space-separated list of parameters:\n"
-"	        	          		\"host=<ip-addr> dbname=<db-number> \\\n								password=<database-user-password> port=<db-port> connect_timeout=<seconds>\".\n"
-"	        	          		All parameters are optional.\n"
+"	        	          		\"host=<ip-addr> dbname=<db-number> \\\n								password=<database-user-password> port=<db-port> connect_timeout=<seconds>\".\n\n"
+"	        	          		All connection-string parameters are optional.\n\n"
 " -O, --redis-statsdb	<connection-string>	Redis status and statistics database connection string, if used \n"
 "						(default - empty, no Redis stats DB used).\n"
 "	                                	This database keeps allocations status information, and it can be also used for publishing\n"
@@ -499,6 +508,7 @@ static char Usage[] = "Usage: turnserver [options]\n"
 " --syslog					Output all log information into the system log (syslog), do not use the file output.\n"
 " --simple-log					This flag means that no log file rollover will be used, and the log file\n"
 "						name will be constructed as-is, without PID and date appendage.\n"
+"						This option can be used, for example, together with the logrotate tool.\n"
 " --stale-nonce					Use extra security with nonce value having limited lifetime (600 secs).\n"
 " -S, --stun-only				Option to set standalone STUN operation only, all TURN requests will be ignored.\n"
 "     --no-stun					Option to suppress STUN functionality, only TURN requests will be processed.\n"
@@ -664,6 +674,7 @@ enum EXTRA_OPTS {
 	NO_TLSV1_OPT,
 	NO_TLSV1_1_OPT,
 	NO_TLSV1_2_OPT,
+	CHECK_ORIGIN_CONSISTENCY_OPT,
 	ADMIN_MAX_BPS_OPT,
 	ADMIN_TOTAL_QUOTA_OPT,
 	ADMIN_USER_QUOTA_OPT
@@ -728,6 +739,7 @@ static const struct myoption long_options[] = {
 				{ "Verbose", optional_argument, NULL, 'V' },
 				{ "daemon", optional_argument, NULL, 'o' },
 				{ "fingerprint", optional_argument, NULL, 'f' },
+				{ "check-origin-consistency", optional_argument, NULL, CHECK_ORIGIN_CONSISTENCY_OPT },
 				{ "no-udp", optional_argument, NULL, NO_UDP_OPT },
 				{ "no-tcp", optional_argument, NULL, NO_TCP_OPT },
 				{ "no-tls", optional_argument, NULL, NO_TLS_OPT },
@@ -1146,6 +1158,9 @@ static void set_option(int c, char *value)
 		turn_params.bps_capacity = (band_limit_t)atoi(value);
 		TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%lu bytes per second allowed, combined server capacity\n",(unsigned long)turn_params.bps_capacity);
 		break;
+	case CHECK_ORIGIN_CONSISTENCY_OPT:
+		turn_params.check_origin = get_bool_value(value);
+		break;
 	case NO_UDP_OPT:
 		turn_params.no_udp = get_bool_value(value);
 		break;

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

@@ -250,6 +250,8 @@ typedef struct _turn_params_ {
   u16bits min_port;
   u16bits max_port;
 
+  vint check_origin;
+
   vint no_multicast_peers;
   vint no_loopback_peers;
 

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

@@ -1574,6 +1574,7 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int
 			 check_new_allocation_quota,
 			 release_allocation_quota,
 			 turn_params.external_ip,
+			 &turn_params.check_origin,
 			 &turn_params.no_tcp_relay,
 			 &turn_params.no_udp_relay,
 			 &turn_params.stale_nonce,

+ 22 - 7
src/apps/uclient/startuclient.c

@@ -302,6 +302,17 @@ int read_mobility_ticket(app_ur_conn_info *clnet_info, stun_buffer *message)
 	return ret;
 }
 
+void add_origin(stun_buffer *message)
+{
+	if(message && origin[0]) {
+		const char* some_origin = "https://carleon.gov:443";
+		stun_attr_add(message, STUN_ATTRIBUTE_ORIGIN, some_origin, strlen(some_origin));
+		stun_attr_add(message, STUN_ATTRIBUTE_ORIGIN, origin, strlen(origin));
+		some_origin = "ftp://uffrith.net";
+		stun_attr_add(message, STUN_ATTRIBUTE_ORIGIN, some_origin, strlen(some_origin));
+	}
+}
+
 static int clnet_allocate(int verbose,
 		app_ur_conn_info *clnet_info,
 		ioa_addr *relay_addr,
@@ -372,13 +383,7 @@ static int clnet_allocate(int verbose,
 		  }
 		}
 
-		if(origin[0]) {
-			const char* some_origin = "https://carleon.gov:443";
-			stun_attr_add(&message, STUN_ATTRIBUTE_ORIGIN, some_origin, strlen(some_origin));
-			stun_attr_add(&message, STUN_ATTRIBUTE_ORIGIN, origin, strlen(origin));
-			some_origin = "ftp://uffrith.net";
-			stun_attr_add(&message, STUN_ATTRIBUTE_ORIGIN, some_origin, strlen(some_origin));
-		}
+		add_origin(&message);
 
 		if(add_integrity(clnet_info, &message)<0) return -1;
 
@@ -645,6 +650,8 @@ static int clnet_allocate(int verbose,
 				stun_attr_add(&message, STUN_ATTRIBUTE_MOBILITY_TICKET, (const char*)clnet_info->s_mobile_id, strlen(clnet_info->s_mobile_id));
 			}
 
+			add_origin(&message);
+
 			if(add_integrity(clnet_info, &message)<0) return -1;
 
 			stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len));
@@ -734,6 +741,8 @@ static int turn_channel_bind(int verbose, uint16_t *chn,
 			*chn = stun_set_channel_bind_request(&message, peer_addr, *chn);
 		}
 
+		add_origin(&message);
+
 		if(add_integrity(clnet_info, &message)<0) return -1;
 
 		stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len));
@@ -845,6 +854,8 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info,
 			}
 		}
 
+		add_origin(&message);
+
 		if(add_integrity(clnet_info, &message)<0) return -1;
 
 		stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len));
@@ -1388,6 +1399,8 @@ int turn_tcp_connect(int verbose, app_ur_conn_info *clnet_info, ioa_addr *peer_a
 		stun_init_request(STUN_METHOD_CONNECT, &message);
 		stun_attr_add_addr(&message, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, peer_addr);
 
+		add_origin(&message);
+
 		if(add_integrity(clnet_info, &message)<0) return -1;
 
 		stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len));
@@ -1427,6 +1440,8 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a
 
 		stun_attr_add(&message, STUN_ATTRIBUTE_CONNECTION_ID, (const s08bits*)&cid,4);
 
+		add_origin(&message);
+
 		if(add_integrity(clnet_info, &message)<0) return -1;
 
 		stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len));

+ 2 - 0
src/apps/uclient/startuclient.h

@@ -43,6 +43,8 @@ extern "C" {
 int rare_event(void);
 int not_rare_event(void);
 
+void add_origin(stun_buffer *message);
+
 int start_c2c_connection(uint16_t clnet_remote_port,
 			 const char *remote_address, 
 			 const unsigned char* ifname, const char *local_address,

+ 3 - 0
src/apps/uclient/uclient.c

@@ -1083,6 +1083,7 @@ static int refresh_channel(app_ur_session* elem, u16bits method, uint32_t lt)
 		stun_init_request(STUN_METHOD_REFRESH, &message);
 		lt = htonl(lt);
 		stun_attr_add(&message, STUN_ATTRIBUTE_LIFETIME, (const char*) &lt, 4);
+		add_origin(&message);
 		if(add_integrity(clnet_info, &message)<0) return -1;
 		if(use_fingerprints)
 			    stun_attr_add_fingerprint_str(message.buf, (size_t*) &(message.len));
@@ -1095,6 +1096,7 @@ static int refresh_channel(app_ur_session* elem, u16bits method, uint32_t lt)
 			if (!method || (method == STUN_METHOD_CREATE_PERMISSION)) {
 				stun_init_request(STUN_METHOD_CREATE_PERMISSION, &message);
 				stun_attr_add_addr(&message, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &(elem->pinfo.peer_addr));
+				add_origin(&message);
 				if(add_integrity(clnet_info, &message)<0) return -1;
 				if(use_fingerprints)
 				    stun_attr_add_fingerprint_str(message.buf, (size_t*) &(message.len));
@@ -1105,6 +1107,7 @@ static int refresh_channel(app_ur_session* elem, u16bits method, uint32_t lt)
 		if (!method || (method == STUN_METHOD_CHANNEL_BIND)) {
 			if (STUN_VALID_CHANNEL(elem->chnum)) {
 				stun_set_channel_bind_request(&message, &(elem->pinfo.peer_addr), elem->chnum);
+				add_origin(&message);
 				if(add_integrity(clnet_info, &message)<0) return -1;
 				if(use_fingerprints)
 					    stun_attr_add_fingerprint_str(message.buf, (size_t*) &(message.len));

+ 48 - 0
src/client/ns_turn_msg.c

@@ -43,6 +43,54 @@
 
 ///////////
 
+int stun_method_str(u16bits method, char *smethod)
+{
+	int ret = 0;
+
+	const char* s = "UNKNOWN";
+
+	switch(method) {
+	case STUN_METHOD_BINDING:
+		s = "BINDING";
+		break;
+	case STUN_METHOD_ALLOCATE:
+		s = "ALLOCATE";
+		break;
+	case STUN_METHOD_REFRESH:
+		s = "REFRESH";
+		break;
+	case STUN_METHOD_SEND:
+		s = "SEND";
+		break;
+	case STUN_METHOD_DATA:
+		s = "DATA";
+		break;
+	case STUN_METHOD_CREATE_PERMISSION:
+		s = "CREATE_PERMISSION";
+		break;
+	case STUN_METHOD_CHANNEL_BIND:
+		s = "CHANNEL_BIND";
+		break;
+	case STUN_METHOD_CONNECT:
+		s = "CONNECT";
+		break;
+	case STUN_METHOD_CONNECTION_BIND:
+		s = "CONNECTION_BIND";
+		break;
+	case STUN_METHOD_CONNECTION_ATTEMPT:
+		s = "CONNECTION_ATTEMPT";
+		break;
+	default:
+		ret = -1;
+	};
+
+	if(smethod) {
+		STRCPY(smethod,s);
+	}
+
+	return ret;
+}
+
 long turn_random(void)
 {
 	long ret = 0;

+ 2 - 0
src/client/ns_turn_msg.h

@@ -94,6 +94,8 @@ u32bits stun_adjust_allocate_lifetime(u32bits lifetime);
 
 ///////////// STR ////////////////////////////////////////////////
 
+int stun_method_str(u16bits method, char *smethod);
+
 int stun_get_message_len_str(u08bits *buf, size_t len, int padding, size_t *app_len);
 
 void stun_init_buffer_str(u08bits *buf, size_t *len);

+ 1 - 1
src/ns_turn_defs.h

@@ -31,7 +31,7 @@
 #ifndef __IOADEFS__
 #define __IOADEFS__
 
-#define TURN_SERVER_VERSION "4.1.1.1"
+#define TURN_SERVER_VERSION "4.1.2.1"
 #define TURN_SERVER_VERSION_NAME "Vitari"
 #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'"
 

+ 61 - 1
src/server/ns_turn_server.c

@@ -3472,7 +3472,65 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss,
 				}
 			}
 
-			if(!(ss->realm_set) && (method == STUN_METHOD_ALLOCATE)) {
+			/* check that the realm is the same as in the original request */
+			if(ss->realm_set) {
+				stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh),
+					ioa_network_buffer_get_size(in_buffer->nbh));
+
+				int origin_found = 0;
+				int norigins = 0;
+
+				while(sar && !origin_found) {
+					if(stun_attr_get_type(sar) == STUN_ATTRIBUTE_ORIGIN) {
+						int sarlen = stun_attr_get_len(sar);
+						if(sarlen>0) {
+							++norigins;
+							char *o = (char*)turn_malloc(sarlen+1);
+							ns_bcopy(stun_attr_get_value(sar),o,sarlen);
+							o[sarlen]=0;
+							char *corigin = (char*)turn_malloc(STUN_MAX_ORIGIN_SIZE+1);
+							corigin[0]=0;
+							if(get_canonic_origin(o,corigin,STUN_MAX_ORIGIN_SIZE)<0) {
+								TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
+									"%s: Wrong origin format: %s\n",
+									__FUNCTION__, o);
+							}
+							if(!strncmp(ss->origin,corigin,STUN_MAX_ORIGIN_SIZE)) {
+								origin_found = 1;
+							}
+							turn_free(corigin,sarlen+1);
+							turn_free(o,sarlen+1);
+						}
+					}
+					sar = stun_attr_get_next_str(ioa_network_buffer_data(in_buffer->nbh),
+							ioa_network_buffer_get_size(in_buffer->nbh), sar);
+				}
+
+				if(server->check_origin && *(server->check_origin)) {
+					if(ss->origin[0]) {
+						if(!origin_found) {
+							err_code = 441;
+							reason = (const u08bits *)"The origin attribute does not match the initial session origin value";
+							if(server->verbose) {
+								char smethod[129];
+								stun_method_str(method,smethod);
+								log_method(ss, smethod, err_code, reason);
+							}
+						}
+					} else if(norigins > 0){
+						err_code = 441;
+						reason = (const u08bits *)"The origin attribute is empty, does not match the initial session origin value";
+						if(server->verbose) {
+							char smethod[129];
+							stun_method_str(method,smethod);
+							log_method(ss, smethod, err_code, reason);
+						}
+					}
+				}
+			}
+
+			/* get the initial origin value */
+			if(!err_code && !(ss->realm_set) && (method == STUN_METHOD_ALLOCATE)) {
 
 				stun_attr_ref sar = stun_attr_get_first_str(ioa_network_buffer_data(in_buffer->nbh),
 					ioa_network_buffer_get_size(in_buffer->nbh));
@@ -4619,6 +4677,7 @@ void init_turn_server(turn_turnserver* server,
 		check_new_allocation_quota_cb chquotacb,
 		release_allocation_quota_cb raqcb,
 		ioa_addr *external_ip,
+		vintp check_origin,
 		vintp no_tcp_relay,
 		vintp no_udp_relay,
 		vintp stale_nonce,
@@ -4662,6 +4721,7 @@ void init_turn_server(turn_turnserver* server,
 
 	TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"turn server id=%d created\n",(int)id);
 
+	server->check_origin = check_origin;
 	server->no_tcp_relay = no_tcp_relay;
 	server->no_udp_relay = no_udp_relay;
 

+ 2 - 0
src/server/ns_turn_server.h

@@ -112,6 +112,7 @@ struct _turn_turnserver {
 	int verbose;
 	int fingerprint;
 	int rfc5780;
+	vintp check_origin;
 	vintp stale_nonce;
 	vintp stun_only;
 	vintp no_stun;
@@ -174,6 +175,7 @@ void init_turn_server(turn_turnserver* server,
 				    check_new_allocation_quota_cb chquotacb,
 				    release_allocation_quota_cb raqcb,
 				    ioa_addr *external_addr,
+				    vintp check_origin,
 				    vintp no_tcp_relay,
 				    vintp no_udp_relay,
 				    vintp stale_nonce,