diff --git a/ChangeLog b/ChangeLog index c053ffd..ed3578d 100644 --- a/ChangeLog +++ b/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 Version 4.5.0.7 'dan Eider': diff --git a/README.turnadmin b/README.turnadmin index ec07197..b3cd0e9 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 diff --git a/README.turnserver b/README.turnserver index ba0c72b..dbcd3db 100644 --- a/README.turnserver +++ b/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 diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index cc191ae..45a65c4 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -276,6 +276,16 @@ # #mysql-userdb="host= dbname= user= password= port= connect_timeout= read_timeout=" +#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 diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index 491df5b..3a0148d 100644 --- a/man/man1/turnadmin.1 +++ b/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="" \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: diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 3f31386..35c1bed 100644 --- a/man/man1/turnserver.1 +++ b/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, diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index c596a63..7d7f1ff 100644 --- a/man/man1/turnutils.1 +++ b/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 diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index f9eaa71..3953796 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; @@ -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; } } diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 35b0dac..7f89ac7 100644 --- a/src/apps/relay/mainrelay.c +++ b/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= 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 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 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 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" @@ -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,×); + 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; diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index c7b5089..406bea8 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -77,6 +77,11 @@ #include "ns_ioalib_impl.h" +#include +#include +#include +#include + #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