浏览代码

Merge branch 'mysql-password-encryption'

Mészáros Mihály 7 年之前
父节点
当前提交
a88c1eed78

+ 1 - 0
ChangeLog

@@ -17,6 +17,7 @@ Version 4.5.0.8 'dan Eider':
 	- 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)
 
 12/10/2017 Oleg Moskalenko <[email protected]>
 Version 4.5.0.7 'dan Eider':

+ 19 - 1
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="<db-connection-string>" -I
 List the origin-to-realm relations in PostgreSQL DB for a single realm:
 
 $ turnadmin --psql-userdb="<db-connection-string>" -I -r <realm>
-  
+
+Create new key file for mysql password encryption:
+
+$ turnadmin -E --key-path <key-file>
+
+Create encrypted mysql password:
+
+$ turnadmin -E --file-key-path <key-file> -p <secret>
+
+Verify/decrypt encrypted password:
+
+$ turnadmin --file-key-path <key-file> -v <encrypted>
+
+   
 Help:  
 
 $ turnadmin -h

+ 6 - 0
README.turnserver

@@ -120,6 +120,12 @@ User database settings:
 		(see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the 
 		command options description).
 		
+--secret-key-file 	If you want to use password as encrpyted in the mysql connection string MySQL encrypted connection, this is key path.
+			This is the file path which contain secret key of aes encryption while using password encryption.
+			This attribute should be use if allow-encoding-with-aes set to 1.
+--allow-encoding-with-aes	If you want to use password as encrpyted in the mysql connection string. Set allow-encoding-with-aes to 1.
+				If you want to use clearteaxt password in the mysql connection string. Set allow-encoding-with-aes to 0.
+				You have to enable secret-key-file attribute above as a key location.
 -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 

+ 10 - 0
examples/etc/turnserver.conf

@@ -276,6 +276,16 @@
 #
 #mysql-userdb="host=<host> dbname=<database-name> user=<database-user> password=<database-user-password> port=<port> connect_timeout=<seconds> read_timeout=<seconds>"
 
+#If you want to use password as encrpyted in the mysql connection string MySQL encrypted connection, this is key path.
+#This is the file path which contain secret key of aes encryption while using password encryption.
+#This attribute should be use if allow-encoding-with-aes set to 1.
+#secret-key-file=/path/
+
+#If you want to use password as encrpyted in the mysql connection string. Set allow-encoding-with-aes to 1.
+#If you want to use clearteaxt password in the mysql connection string. Set allow-encoding-with-aes to 0.
+#You have to enable secret-key-file attribute above as a key location.
+#allow-encoding-with-aes=1 or 0
+
 # 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

+ 34 - 1
man/man1/turnadmin.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "11 December 2017" "" ""
+.TH TURN 1 "15 August 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="<db\-connection\-string>" \fB\-I\fP
 List the origin\-to\-realm relations in PostgreSQL DB for a single realm:
 .PP
 $ \fIturnadmin\fP \fB\-\-psql\-userdb\fP="<db\-connection\-string>" \fB\-I\fP \fB\-r\fP <realm>
+.PP
+Create new key file for mysql password encryption:
+.PP
+$ \fIturnadmin\fP \fB\-E\fP \fB\-\-key\-path\fP <key\-file>
+.PP
+Create encrypted mysql password:
+.PP
+$ \fIturnadmin\fP \fB\-E\fP \fB\-\-file\-key\-path\fP <key\-file> \fB\-p\fP <secret>
+.PP
+Verify/decrypt encrypted password:
+.PP
+$ \fIturnadmin\fP \fB\-\-file\-key\-path\fP <key\-file> \fB\-v\fP <encrypted>
+.RE
+.PP
+
+.RS
 .TP
 .B
 Help:

+ 13 - 1
man/man1/turnserver.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "11 December 2017" "" ""
+.TH TURN 1 "15 August 2018" "" ""
 .SH GENERAL INFORMATION
 
 The \fBTURN Server\fP project contains the source code of a TURN server and TURN client 
@@ -180,6 +180,18 @@ command \fIoptions\fP description).
 .RE
 .TP
 .B
+\fB\-\-secret\-key\-file\fP
+If you want to use password as encrpyted in the mysql connection string MySQL encrypted connection, this is key path.
+This is the file path which contain secret key of aes encryption while using password encryption.
+This attribute should be use if allow\-encoding\-with\-aes set to 1.
+.TP
+.B
+\fB\-\-allow\-encoding\-with\-aes\fP
+If you want to use password as encrpyted in the mysql connection string. Set allow\-encoding\-with\-aes to 1.
+If you want to use clearteaxt password in the mysql connection string. Set allow\-encoding\-with\-aes to 0.
+You have to enable secret\-key\-file attribute above as a key location.
+.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,

+ 1 - 1
man/man1/turnutils.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "11 December 2017" "" ""
+.TH TURN 1 "15 August 2018" "" ""
 .SH GENERAL INFORMATION
 
 A set of turnutils_* programs provides some utility functionality to be used

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

@@ -35,6 +35,7 @@
 #if !defined(TURN_NO_MYSQL)
 #include <mysql.h>
 
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 static int donot_print_connection_success = 0;
@@ -72,6 +73,33 @@ static void MyconninfoFree(Myconninfo *co) {
 		ns_bzero(co,sizeof(Myconninfo));
 	}
 }
+struct ctr_state state;
+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]="";
+	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=malloc(sizeof(char)*strlen(last));
+	strcpy(out,last);
+	return out;
+}
+
 
 static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) {
 	Myconninfo *co = (Myconninfo*)turn_malloc(sizeof(Myconninfo));
@@ -234,6 +262,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.allow_encoding){
+					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 +278,10 @@ 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.allow_encoding)
+					    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;
 				}
 			}

+ 335 - 123
src/apps/relay/mainrelay.c

@@ -116,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,"",
@@ -151,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   /* allow_encoding */
 };
 
 //////////////// OpenSSL Init //////////////////////
@@ -487,12 +491,18 @@ static char Usage[] = "Usage: turnserver [options]\n"
 "	                                	This database can be used for long-term credentials mechanism users,\n"
 "		                                and it can store the secret value(s) for secret-based timed authentication in TURN RESP API.\n"
 "						The connection string my be space-separated list of parameters:\n"
-"	        	          		\"host=<ip-addr> dbname=<database-name> user=<database-user> \\\n								password=<database-user-password> port=<db-port> connect_timeout=<seconds> read_timeout=<seconds>\".\n\n"
+"	        	          		\"host=<ip-addr> dbname=<database-name> user=<database-user> \\\n							password=<database-user-password> port=<db-port> connect_timeout=<seconds> read_timeout=<seconds>\".\n\n"
 "						The connection string parameters for the secure communications (SSL):\n"
 "						ca, capath, cert, key, cipher\n"
 "						(see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the\n"
 "						command options description).\n\n"
 "	        	          		All connection-string parameters are optional.\n\n"
+"--secret-key-file	<filename>		If you want to use password as encrpyted in the mysql connection string MySQL encrypted connection, this is key path.\n"
+"						This is the file path which contain secret key of aes encryption while using password encryption.\n"
+"						This attribute should be use if allow-encoding-with-aes set to 1.\n"
+"--allow-encoding-with-aes	<1/0>		If you want to use password as encrpyted in the mysql connection string. Set allow-encoding-with-aes to 1.\n"
+"						If you want to use clearteaxt password in the mysql connection string. Set allow-encoding-with-aes to 0.\n"
+"						You have to enable secret-key-file attribute above as a key location.\n"
 #endif
 #if !defined(TURN_NO_MONGO)
 " -J, --mongo-userdb	<connection-string>	MongoDB connection string, if used (default - empty, no MongoDB used).\n"
@@ -588,10 +598,10 @@ static char Usage[] = "Usage: turnserver [options]\n"
 "						See the docs for more information.\n"
 " -C, --rest-api-separator	<SYMBOL>	This is the timestamp/username separator symbol (character) in TURN REST API.\n"
 "						The default value is ':'.\n"
-"     --max-allocate-timeout=<seconds>		Max time, in seconds, allowed for full allocation establishment. Default is 60.\n"
-"     --allowed-peer-ip=<ip[-ip]> 		Specifies an ip or range of ips that are explicitly allowed to connect to the \n"
+" --max-allocate-timeout=<seconds>		Max time, in seconds, allowed for full allocation establishment. Default is 60.\n"
+" --allowed-peer-ip=<ip[-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=<ip[-ip]> 		Specifies an ip or range of ips that are not allowed to connect to the turn server.\n"
+" --denied-peer-ip=<ip[-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"
@@ -650,6 +660,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"
@@ -670,6 +682,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
@@ -682,8 +697,8 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\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 ADMIN_OPTIONS "PEgGORIHKYlLkaADSdb:e:M:J:N:u:r:p:s:X:o:h:x:v:f:"
 
 enum EXTRA_OPTS {
 	NO_UDP_OPT=256,
@@ -751,7 +766,9 @@ enum EXTRA_OPTS {
 	SERVER_NAME_OPT,
 	OAUTH_OPT,
 	PROD_OPT,
-	NO_HTTP_OPT
+	NO_HTTP_OPT,
+	SECRET_KEY_OPT,
+	ALLOW_ENCODING_OPT
 };
 
 struct myoption {
@@ -870,11 +887,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 },
+				{ "allow-encoding-with-aes", required_argument, NULL, ALLOW_ENCODING_OPT},
 				{ 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' },
@@ -906,6 +926,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' },
@@ -919,6 +942,142 @@ static const struct myoption admin_long_options[] = {
 				{ NULL, no_argument, NULL, 0 }
 };
 
+
+struct ctr_state state;
+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.
+	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.
+	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;
+    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,&times);
+	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 = 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]="";
+    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]))
@@ -1305,6 +1464,12 @@ 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 ALLOW_ENCODING_OPT:
+  		turn_params.allow_encoding = atoi(value);
+  		break;
 	case PKEY_FILE_OPT:
 		STRCPY(turn_params.pkey_file,value);
 		break;
@@ -1492,6 +1657,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";
@@ -1504,84 +1671,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);
@@ -1612,45 +1783,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);
 		}
 	}
 
@@ -1950,6 +2143,10 @@ int main(int argc, char **argv)
 
 	TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Domain name: %s\n",turn_params.domain);
 	TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Default realm: %s\n",get_realm(NULL)->options.name);
+    if(turn_params.allow_encoding){
+        TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "allow-encoding-with-aes activated.\n");
+    }
+
 	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);
 	}
@@ -2652,6 +2849,21 @@ static void set_ctx(SSL_CTX** out, const char *protocol, const SSL_METHOD* metho
 		}
 	}
 
+	{//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;
 

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

@@ -77,6 +77,11 @@
 
 #include "ns_ioalib_impl.h"
 
+#include <openssl/aes.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/modes.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -309,6 +314,11 @@ typedef struct _turn_params_ {
 
   unsigned long cpus;
 
+  ///////// Encryption /////////
+  char secret_key_file[1025];
+  unsigned char secret_key[1025];
+  int allow_encoding;
+
 } turn_params_t;
 
 extern turn_params_t turn_params;
@@ -357,6 +367,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