| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245 |
- /*
- * Copyright (C) 2011, 2012, 2013 Citrix Systems
- * Copyright (C) 2014 Vivocha S.p.A.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
- #include "../mainrelay.h"
- #include "dbd_redis.h"
- #if !defined(TURN_NO_HIREDIS)
- #include "hiredis_libevent2.h"
- #include <hiredis/hiredis.h>
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- static int donot_print_connection_success = 0;
- static void turnFreeRedisReply(void *reply) {
- if(reply) {
- freeReplyObject(reply);
- }
- }
- struct _Ryconninfo {
- char *host;
- char *dbname;
- char *password;
- unsigned int connect_timeout;
- unsigned int port;
- };
- typedef struct _Ryconninfo Ryconninfo;
- static void RyconninfoFree(Ryconninfo *co) {
- if(co) {
- if(co->host) turn_free(co->host, strlen(co->host)+1);
- if(co->dbname) turn_free(co->dbname, strlen(co->dbname)+1);
- if(co->password) turn_free(co->password, strlen(co->password)+1);
- ns_bzero(co,sizeof(Ryconninfo));
- }
- }
- static Ryconninfo *RyconninfoParse(const char *userdb, char **errmsg) {
- Ryconninfo *co = (Ryconninfo*) turn_malloc(sizeof(Ryconninfo));
- ns_bzero(co,sizeof(Ryconninfo));
- if (userdb) {
- char *s0 = turn_strdup(userdb);
- char *s = s0;
- while (s && *s) {
- while (*s && (*s == ' '))
- ++s;
- char *snext = strstr(s, " ");
- if (snext) {
- *snext = 0;
- ++snext;
- }
- char* seq = strstr(s, "=");
- if (!seq) {
- RyconninfoFree(co);
- co = NULL;
- if (errmsg) {
- *errmsg = turn_strdup(s);
- }
- break;
- }
- *seq = 0;
- if (!strcmp(s, "host"))
- co->host = turn_strdup(seq + 1);
- else if (!strcmp(s, "ip"))
- co->host = turn_strdup(seq + 1);
- else if (!strcmp(s, "addr"))
- co->host = turn_strdup(seq + 1);
- else if (!strcmp(s, "ipaddr"))
- co->host = turn_strdup(seq + 1);
- else if (!strcmp(s, "hostaddr"))
- co->host = turn_strdup(seq + 1);
- else if (!strcmp(s, "dbname"))
- co->dbname = turn_strdup(seq + 1);
- else if (!strcmp(s, "db"))
- co->dbname = turn_strdup(seq + 1);
- else if (!strcmp(s, "database"))
- co->dbname = turn_strdup(seq + 1);
- else if (!strcmp(s, "user"))
- ;
- else if (!strcmp(s, "uname"))
- ;
- else if (!strcmp(s, "name"))
- ;
- else if (!strcmp(s, "username"))
- ;
- else if (!strcmp(s, "password"))
- co->password = turn_strdup(seq + 1);
- else if (!strcmp(s, "pwd"))
- co->password = turn_strdup(seq + 1);
- else if (!strcmp(s, "passwd"))
- co->password = turn_strdup(seq + 1);
- else if (!strcmp(s, "secret"))
- co->password = turn_strdup(seq + 1);
- else if (!strcmp(s, "port"))
- co->port = (unsigned int) atoi(seq + 1);
- else if (!strcmp(s, "p"))
- co->port = (unsigned int) atoi(seq + 1);
- else if (!strcmp(s, "connect_timeout"))
- co->connect_timeout = (unsigned int) atoi(seq + 1);
- else if (!strcmp(s, "timeout"))
- co->connect_timeout = (unsigned int) atoi(seq + 1);
- else {
- RyconninfoFree(co);
- co = NULL;
- if (errmsg) {
- *errmsg = turn_strdup(s);
- }
- break;
- }
- s = snext;
- }
- turn_free(s0, strlen(s0)+1);
- }
- if(co) {
- if(!(co->dbname))
- co->dbname=turn_strdup("0");
- if(!(co->host))
- co->host=turn_strdup("127.0.0.1");
- if(!(co->password))
- co->password=turn_strdup("");
- }
- return co;
- }
- redis_context_handle get_redis_async_connection(struct event_base *base, const char* connection_string, int delete_keys) {
- redis_context_handle ret = NULL;
- char *errmsg = NULL;
- if(base && connection_string && connection_string[0]) {
- Ryconninfo *co = RyconninfoParse(connection_string, &errmsg);
- if (!co) {
- if (errmsg) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", connection_string, errmsg);
- turn_free(errmsg,strlen(errmsg)+1);
- } else {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error\n", connection_string);
- }
- } else if (errmsg) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", connection_string, errmsg);
- turn_free(errmsg,strlen(errmsg)+1);
- RyconninfoFree(co);
- } else {
- if(delete_keys) {
- redisContext *rc = NULL;
- char ip[256] = "\0";
- int port = DEFAULT_REDIS_PORT;
- if (co->host)
- STRCPY(ip,co->host);
- if (!ip[0])
- STRCPY(ip,"127.0.0.1");
- if (co->port)
- port = (int) (co->port);
- if (co->connect_timeout) {
- struct timeval tv;
- tv.tv_usec = 0;
- tv.tv_sec = (time_t) (co->connect_timeout);
- rc = redisConnectWithTimeout(ip, port, tv);
- } else {
- rc = redisConnect(ip, port);
- }
- if (!rc) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB async connection\n");
- } else {
- if (co->password) {
- turnFreeRedisReply(redisCommand(rc, "AUTH %s", co->password));
- }
- if (co->dbname) {
- turnFreeRedisReply(redisCommand(rc, "select %s", co->dbname));
- }
- {
- redisReply *reply = (redisReply*)redisCommand(rc, "keys turn/*/allocation/*/status");
- if(reply) {
- secrets_list_t keys;
- size_t isz = 0;
- char s[513];
- init_secrets_list(&keys);
- if (reply->type == REDIS_REPLY_ERROR) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
- } else if (reply->type != REDIS_REPLY_ARRAY) {
- if (reply->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
- } else {
- size_t i;
- for (i = 0; i < reply->elements; ++i) {
- add_to_secrets_list(&keys,reply->element[i]->str);
- }
- }
- for(isz=0;isz<keys.sz;++isz) {
- snprintf(s,sizeof(s),"del %s", keys.secrets[isz]);
- turnFreeRedisReply(redisCommand(rc, s));
- }
- clean_secrets_list(&keys);
- turnFreeRedisReply(reply);
- }
- }
- redisFree(rc);
- }
- }
- ret = redisLibeventAttach(base, co->host, co->port, co->password, atoi(co->dbname));
- if (!ret) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB connection\n");
- } else if (is_redis_asyncconn_good(ret) && !donot_print_connection_success) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis DB async connection to be used: %s\n", connection_string);
- }
- RyconninfoFree(co);
- }
- }
- return ret;
- }
- static redisContext *get_redis_connection(void) {
- persistent_users_db_t *pud = get_persistent_users_db();
- redisContext *redisconnection = (redisContext*)(pud->connection);
- if(redisconnection) {
- if(redisconnection->err) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Cannot connect to redis, err=%d, flags=0x%lx\n", __FUNCTION__,(int)redisconnection->err,(unsigned long)redisconnection->flags);
- redisFree(redisconnection);
- pud->connection = NULL;
- redisconnection = NULL;
- }
- }
- if (!redisconnection) {
- char *errmsg = NULL;
- Ryconninfo *co = RyconninfoParse(pud->userdb, &errmsg);
- if (!co) {
- if (errmsg) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", pud->userdb, errmsg);
- turn_free(errmsg,strlen(errmsg)+1);
- } else {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error\n", pud->userdb);
- }
- } else if (errmsg) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open Redis DB connection <%s>, connection string format error: %s\n", pud->userdb, errmsg);
- turn_free(errmsg,strlen(errmsg)+1);
- RyconninfoFree(co);
- } else {
- char ip[256] = "\0";
- int port = DEFAULT_REDIS_PORT;
- if (co->host)
- STRCPY(ip,co->host);
- if (!ip[0])
- STRCPY(ip,"127.0.0.1");
- if (co->port)
- port = (int) (co->port);
- if (co->connect_timeout) {
- struct timeval tv;
- tv.tv_usec = 0;
- tv.tv_sec = (time_t) (co->connect_timeout);
- redisconnection = redisConnectWithTimeout(ip, port, tv);
- } else {
- redisconnection = redisConnect(ip, port);
- }
- if (redisconnection) {
- if(redisconnection->err) {
- if(redisconnection->errstr[0]) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis: %s\n",redisconnection->errstr);
- }
- redisFree(redisconnection);
- redisconnection = NULL;
- } else if (co->password) {
- void *reply = redisCommand(redisconnection, "AUTH %s", co->password);
- if(!reply) {
- if(redisconnection->err && redisconnection->errstr[0]) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis: %s\n",redisconnection->errstr);
- }
- redisFree(redisconnection);
- redisconnection = NULL;
- } else {
- turnFreeRedisReply(reply);
- if (co->dbname) {
- reply = redisCommand(redisconnection, "select %s", co->dbname);
- if(!reply) {
- if(redisconnection->err && redisconnection->errstr[0]) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis: %s\n",redisconnection->errstr);
- }
- redisFree(redisconnection);
- redisconnection = NULL;
- } else {
- turnFreeRedisReply(reply);
- }
- }
- }
- }
- }
- if (!redisconnection) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB connection\n");
- } else if (!donot_print_connection_success) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Redis DB sync connection success: %s\n", pud->userdb);
- }
- RyconninfoFree(co);
- }
- pud->connection = redisconnection;
- pud = get_persistent_users_db();
- redisconnection = (redisContext*)(pud->connection);
- }
- return redisconnection;
- }
- static int set_redis_realm_opt(char *realm, const char* key, unsigned long *value)
- {
- int found = 0;
- redisContext *rc = get_redis_connection();
- if(rc) {
- redisReply *rget = NULL;
- char s[1025];
- snprintf(s, sizeof(s), "get turn/realm/%s/%s", realm, key);
- rget = (redisReply *) redisCommand(rc, s);
- if (rget) {
- if (rget->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", rget->str);
- else if (rget->type != REDIS_REPLY_STRING) {
- if (rget->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
- } else {
- lock_realms();
- *value = (unsigned long)atol(rget->str);
- unlock_realms();
- found = 1;
- }
- turnFreeRedisReply(rget);
- }
- }
- return found;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- static int redis_get_auth_secrets(secrets_list_t *sl, u08bits *realm)
- {
- int ret = -1;
- redisContext *rc = get_redis_connection();
- if (rc) {
- redisReply *reply = (redisReply*) redisCommand(rc, "smembers turn/realm/%s/secret", (char*) realm);
- if (reply) {
- if (reply->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
- else if (reply->type != REDIS_REPLY_ARRAY) {
- if (reply->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
- } else {
- size_t i;
- for (i = 0; i < reply->elements; ++i) {
- add_to_secrets_list(sl, reply->element[i]->str);
- }
- }
- ret = 0;
- turnFreeRedisReply(reply);
- }
- }
- return ret;
- }
-
- static int redis_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) {
- int ret = -1;
- redisContext * rc = get_redis_connection();
- if(rc) {
- char s[TURN_LONG_STRING_SIZE];
- snprintf(s,sizeof(s),"get turn/realm/%s/user/%s/key", (char*)realm, usname);
- redisReply *rget = (redisReply *)redisCommand(rc, s);
- if(rget) {
- if (rget->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", rget->str);
- else if (rget->type != REDIS_REPLY_STRING) {
- if (rget->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
- } else {
- size_t sz = get_hmackey_size(turn_params.shatype);
- if(strlen(rget->str)<sz*2) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key format: %s, user %s\n",rget->str,usname);
- } else if(convert_string_key_to_binary(rget->str, key, sz)<0) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key: %s, user %s\n",rget->str,usname);
- } else {
- ret = 0;
- }
- }
- turnFreeRedisReply(rget);
- }
- if(ret == 0) {
- snprintf(s,sizeof(s),"get turn/realm/%s/user/%s/password", (char*)realm, usname);
- rget = (redisReply *)redisCommand(rc, s);
- if(rget) {
- if (rget->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", rget->str);
- else if (rget->type != REDIS_REPLY_STRING) {
- if (rget->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
- } else {
- if(stun_produce_integrity_key_str((u08bits*)usname, realm, (u08bits*)rget->str, key, turn_params.shatype)>=0) {
- ret = 0;
- }
- }
- turnFreeRedisReply(rget);
- }
- }
- }
- return ret;
- }
- static int redis_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
- int ret = -1;
- redisContext * rc = get_redis_connection();
- if(rc) {
- char s[TURN_LONG_STRING_SIZE];
- ns_bzero(key,sizeof(oauth_key_data_raw));
- STRCPY(key->kid,kid);
- snprintf(s,sizeof(s),"hgetall turn/oauth/kid/%s", (const char*)kid);
- redisReply *reply = (redisReply *)redisCommand(rc, s);
- if(reply) {
- if (reply->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
- else if (reply->type != REDIS_REPLY_ARRAY) {
- if (reply->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
- } else if(reply->elements > 1) {
- size_t i;
- for (i = 0; i < (reply->elements)/2; ++i) {
- char *kw = reply->element[2*i]->str;
- char *val = reply->element[2*i+1]->str;
- if(kw) {
- if(!strcmp(kw,"as_rs_alg")) {
- STRCPY(key->as_rs_alg,val);
- } else if(!strcmp(kw,"as_rs_key")) {
- STRCPY(key->as_rs_key,val);
- } else if(!strcmp(kw,"auth_key")) {
- STRCPY(key->auth_key,val);
- } else if(!strcmp(kw,"auth_alg")) {
- STRCPY(key->auth_alg,val);
- } else if(!strcmp(kw,"ikm_key")) {
- STRCPY(key->ikm_key,val);
- } else if(!strcmp(kw,"hkdf_hash_func")) {
- STRCPY(key->hkdf_hash_func,val);
- } else if(!strcmp(kw,"timestamp")) {
- key->timestamp = (u64bits)strtoull(val,NULL,10);
- } else if(!strcmp(kw,"lifetime")) {
- key->lifetime = (u32bits)strtoul(val,NULL,10);
- }
- }
- }
- ret = 0;
- }
- turnFreeRedisReply(reply);
- }
- }
- return ret;
- }
-
- static int redis_get_user_pwd(u08bits *usname, st_password_t pwd) {
- int ret = -1;
- redisContext * rc = get_redis_connection();
- if(rc) {
- char s[TURN_LONG_STRING_SIZE];
- snprintf(s,sizeof(s),"get turn/user/%s/password", usname);
- redisReply *rget = (redisReply *)redisCommand(rc, s);
- if(rget) {
- if (rget->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", rget->str);
- else if (rget->type != REDIS_REPLY_STRING) {
- if (rget->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
- } else {
- strncpy((char*)pwd,rget->str,SHORT_TERM_PASSWORD_SIZE);
- pwd[SHORT_TERM_PASSWORD_SIZE]=0;
- ret = 0;
- }
- turnFreeRedisReply(rget);
- }
- }
- return ret;
- }
-
- static int redis_set_user_key(u08bits *usname, u08bits *realm, const char *key) {
- int ret = -1;
- redisContext *rc = get_redis_connection();
- if(rc) {
- char statement[TURN_LONG_STRING_SIZE];
- snprintf(statement,sizeof(statement),"set turn/realm/%s/user/%s/key %s",(char*)realm,usname,key);
- turnFreeRedisReply(redisCommand(rc, statement));
- snprintf(statement,sizeof(statement),"del turn/realm/%s/user/%s/password",(char*)realm,usname);
- turnFreeRedisReply(redisCommand(rc, statement));
- turnFreeRedisReply(redisCommand(rc, "save"));
- ret = 0;
- }
- return ret;
- }
- static int redis_set_oauth_key(oauth_key_data_raw *key) {
- int ret = -1;
- redisContext *rc = get_redis_connection();
- if(rc) {
- char statement[TURN_LONG_STRING_SIZE];
- snprintf(statement,sizeof(statement),"hmset turn/oauth/kid/%s ikm_key '%s' hkdf_hash_func '%s' as_rs_alg '%s' as_rs_key '%s' auth_alg '%s' auth_key '%s' timestamp %llu lifetime %lu",
- key->kid,key->ikm_key,key->hkdf_hash_func,key->as_rs_alg,key->as_rs_key,key->auth_alg,key->auth_key,(unsigned long long)key->timestamp,(unsigned long)key->lifetime);
- turnFreeRedisReply(redisCommand(rc, statement));
- turnFreeRedisReply(redisCommand(rc, "save"));
- ret = 0;
- }
- return ret;
- }
-
- static int redis_set_user_pwd(u08bits *usname, st_password_t pwd) {
- int ret = -1;
- redisContext *rc = get_redis_connection();
- if(rc) {
- char statement[TURN_LONG_STRING_SIZE];
- snprintf(statement,sizeof(statement),"set turn/user/%s/password %s",usname,pwd);
- turnFreeRedisReply(redisCommand(rc, statement));
- turnFreeRedisReply(redisCommand(rc, "save"));
- ret = 0;
- }
- return ret;
- }
-
- static int redis_del_user(u08bits *usname, int is_st, u08bits *realm) {
- int ret = -1;
- redisContext *rc = get_redis_connection();
- if(rc) {
- char statement[TURN_LONG_STRING_SIZE];
- if(is_st) {
- snprintf(statement,sizeof(statement),"del turn/user/%s/password",usname);
- turnFreeRedisReply(redisCommand(rc, statement));
- } else {
- snprintf(statement,sizeof(statement),"del turn/realm/%s/user/%s/key",(char*)realm,usname);
- turnFreeRedisReply(redisCommand(rc, statement));
- snprintf(statement,sizeof(statement),"del turn/realm/%s/user/%s/password",(char*)realm,usname);
- turnFreeRedisReply(redisCommand(rc, statement));
- }
- turnFreeRedisReply(redisCommand(rc, "save"));
- ret = 0;
- }
- return ret;
- }
- static int redis_del_oauth_key(const u08bits *kid) {
- int ret = -1;
- redisContext *rc = get_redis_connection();
- if(rc) {
- char statement[TURN_LONG_STRING_SIZE];
- snprintf(statement,sizeof(statement),"del turn/oauth/kid/%s",(const char*)kid);
- turnFreeRedisReply(redisCommand(rc, statement));
- turnFreeRedisReply(redisCommand(rc, "save"));
- ret = 0;
- }
- return ret;
- }
-
- static int redis_list_users(int is_st, u08bits *realm) {
- int ret = -1;
- redisContext *rc = get_redis_connection();
- if(rc) {
- secrets_list_t keys;
- size_t isz = 0;
- init_secrets_list(&keys);
- redisReply *reply = NULL;
- if(!is_st) {
- if(realm && realm[0]) {
- reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/user/*/key", (char*)realm);
- } else {
- reply = (redisReply*)redisCommand(rc, "keys turn/realm/*/user/*/key");
- }
- if(reply) {
- if (reply->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
- else if (reply->type != REDIS_REPLY_ARRAY) {
- if (reply->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
- } else {
- size_t i;
- for (i = 0; i < reply->elements; ++i) {
- add_to_secrets_list(&keys,reply->element[i]->str);
- }
- }
- turnFreeRedisReply(reply);
- }
- if(realm && realm[0]) {
- reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/user/*/password", (char*)realm);
- } else {
- reply = (redisReply*)redisCommand(rc, "keys turn/realm/*/user/*/password");
- }
- if(reply) {
- if (reply->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
- else if (reply->type != REDIS_REPLY_ARRAY) {
- if (reply->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
- } else {
- size_t i;
- for (i = 0; i < reply->elements; ++i) {
- add_to_secrets_list(&keys,reply->element[i]->str);
- }
- }
- turnFreeRedisReply(reply);
- }
- } else {
- reply = (redisReply*)redisCommand(rc, "keys turn/user/*/password");
- if(reply) {
- if (reply->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
- else if (reply->type != REDIS_REPLY_ARRAY) {
- if (reply->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
- } else {
- size_t i;
- for (i = 0; i < reply->elements; ++i) {
- add_to_secrets_list(&keys,reply->element[i]->str);
- }
- }
- turnFreeRedisReply(reply);
- }
- }
- for(isz=0;isz<keys.sz;++isz) {
- char *s = keys.secrets[isz];
- char *sh = strstr(s,"/user/");
- if(sh) {
- sh += 6;
- char* st = strchr(sh,'/');
- if(st)
- *st=0;
- printf("%s\n",sh);
- }
- }
- clean_secrets_list(&keys);
- ret = 0;
- }
- return ret;
- }
- static int redis_list_oauth_keys(void) {
- int ret = -1;
- redisContext *rc = get_redis_connection();
- secrets_list_t keys;
- size_t isz = 0;
- init_secrets_list(&keys);
- if(rc) {
- redisReply *reply = NULL;
- reply = (redisReply*)redisCommand(rc, "keys turn/oauth/kid/*");
- if(reply) {
- if (reply->type == REDIS_REPLY_ERROR) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
- } else if (reply->type != REDIS_REPLY_ARRAY) {
- if (reply->type != REDIS_REPLY_NIL) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
- }
- } else {
- size_t i;
- for (i = 0; i < reply->elements; ++i) {
- add_to_secrets_list(&keys,reply->element[i]->str);
- }
- }
- turnFreeRedisReply(reply);
- }
- }
- for(isz=0;isz<keys.sz;++isz) {
- char *s = keys.secrets[isz];
- s += strlen("turn/oauth/kid/");
- oauth_key_data_raw key_;
- oauth_key_data_raw *key=&key_;
- if(redis_get_oauth_key((const u08bits*)s,key) == 0) {
- printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, hkdf_hash_func=%s, as_rs_alg=%s, as_rs_key=%s, auth_alg=%s, auth_key=%s\n",
- key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, key->hkdf_hash_func,
- key->as_rs_alg, key->as_rs_key, key->auth_alg, key->auth_key);
- }
- }
- clean_secrets_list(&keys);
- ret = 0;
- return ret;
- }
-
- static int redis_show_secret(u08bits *realm)
- {
- int ret = -1;
- donot_print_connection_success = 1;
- redisContext *rc = get_redis_connection();
- if (rc) {
- redisReply *reply = NULL;
- if (realm && realm[0]) {
- reply = (redisReply*) redisCommand(rc, "keys turn/realm/%s/secret", (char*) realm);
- } else {
- reply = (redisReply*) redisCommand(rc, "keys turn/realm/*/secret");
- }
- if (reply) {
- secrets_list_t keys;
- size_t isz = 0;
- char s[257];
- init_secrets_list(&keys);
- if (reply->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
- else if (reply->type != REDIS_REPLY_ARRAY) {
- if (reply->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
- } else {
- size_t i;
- for (i = 0; i < reply->elements; ++i) {
- add_to_secrets_list(&keys, reply->element[i]->str);
- }
- }
- for (isz = 0; isz < keys.sz; ++isz) {
- snprintf(s, sizeof(s), "smembers %s", keys.secrets[isz]);
- redisReply *rget = (redisReply *) redisCommand(rc, s);
- if (rget) {
- if (rget->type == REDIS_REPLY_ERROR) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", rget->str);
- } else if (rget->type == REDIS_REPLY_STRING) {
- printf("%s\n", rget->str);
- } else if (rget->type != REDIS_REPLY_ARRAY) {
- if (rget->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
- } else {
- size_t i;
- for (i = 0; i < rget->elements; ++i) {
- printf("%s\n", rget->element[i]->str);
- }
- }
- }
- turnFreeRedisReply(rget);
- }
- clean_secrets_list(&keys);
- turnFreeRedisReply(reply);
- ret = 0;
- }
- }
- return ret;
- }
-
- static int redis_del_secret(u08bits *secret, u08bits *realm)
- {
- int ret = -1;
- donot_print_connection_success = 1;
- redisContext *rc = get_redis_connection();
- if (rc) {
- turnFreeRedisReply(redisCommand(rc, "srem turn/realm/%s/secret %s", (char*) realm, (char*) secret));
- turnFreeRedisReply(redisCommand(rc, "save"));
- ret = 0;
- }
- return ret;
- }
-
- static int redis_set_secret(u08bits *secret, u08bits *realm)
- {
- int ret = -1;
- donot_print_connection_success = 1;
- redisContext *rc = get_redis_connection();
- if (rc) {
- char s[TURN_LONG_STRING_SIZE];
- redis_del_secret(secret, realm);
- snprintf(s, sizeof(s), "sadd turn/realm/%s/secret %s", (char*) realm, secret);
- turnFreeRedisReply(redisCommand(rc, s));
- turnFreeRedisReply(redisCommand(rc, "save"));
- ret = 0;
- }
- return ret;
- }
-
- static int redis_add_origin(u08bits *origin, u08bits *realm) {
- int ret = -1;
- redisContext *rc = get_redis_connection();
- if(rc) {
- char s[TURN_LONG_STRING_SIZE];
- snprintf(s,sizeof(s),"set turn/origin/%s %s", (char*)origin, (char*)realm);
- turnFreeRedisReply(redisCommand(rc, s));
- turnFreeRedisReply(redisCommand(rc, "save"));
- ret = 0;
- }
- return ret;
- }
-
- static int redis_del_origin(u08bits *origin) {
- int ret = -1;
- redisContext *rc = get_redis_connection();
- if(rc) {
- char s[TURN_LONG_STRING_SIZE];
- snprintf(s,sizeof(s),"del turn/origin/%s", (char*)origin);
- turnFreeRedisReply(redisCommand(rc, s));
- turnFreeRedisReply(redisCommand(rc, "save"));
- ret = 0;
- }
- return ret;
- }
-
- static int redis_list_origins(u08bits *realm) {
- int ret = -1;
- donot_print_connection_success = 1;
- redisContext *rc = get_redis_connection();
- if(rc) {
- secrets_list_t keys;
- size_t isz = 0;
- init_secrets_list(&keys);
- redisReply *reply = NULL;
- {
- reply = (redisReply*)redisCommand(rc, "keys turn/origin/*");
- if(reply) {
- if (reply->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
- else if (reply->type != REDIS_REPLY_ARRAY) {
- if (reply->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
- } else {
- size_t i;
- size_t offset = strlen("turn/origin/");
- for (i = 0; i < reply->elements; ++i) {
- add_to_secrets_list(&keys,reply->element[i]->str+offset);
- }
- }
- turnFreeRedisReply(reply);
- }
- }
- for(isz=0;isz<keys.sz;++isz) {
- char *o = keys.secrets[isz];
- reply = (redisReply*)redisCommand(rc, "get turn/origin/%s",o);
- if(reply) {
- if (reply->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
- else if (reply->type != REDIS_REPLY_STRING) {
- if (reply->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
- } else {
- if(!(realm && realm[0] && strcmp((char*)realm,reply->str))) {
- printf("%s ==>> %s\n",o,reply->str);
- }
- }
- turnFreeRedisReply(reply);
- }
- }
- clean_secrets_list(&keys);
- ret = 0;
- }
- return ret;
- }
-
- static int redis_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) {
- int ret = -1;
- redisContext *rc = get_redis_connection();
- if(rc) {
- char s[TURN_LONG_STRING_SIZE];
- if(value>0)
- snprintf(s,sizeof(s),"set turn/realm/%s/%s %lu", (char*)realm, opt, (unsigned long)value);
- else
- snprintf(s,sizeof(s),"del turn/realm/%s/%s", (char*)realm, opt);
- turnFreeRedisReply(redisCommand(rc, s));
- turnFreeRedisReply(redisCommand(rc, "save"));
- ret = 0;
- }
- return ret;
- }
-
- static int redis_list_realm_options(u08bits *realm) {
- int ret = -1;
- donot_print_connection_success = 1;
- redisContext *rc = get_redis_connection();
- if(rc) {
- secrets_list_t keys;
- size_t isz = 0;
- init_secrets_list(&keys);
- redisReply *reply = NULL;
- {
- if(realm && realm[0]) {
- reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/*",realm);
- } else {
- reply = (redisReply*)redisCommand(rc, "keys turn/realm/*");
- }
- if(reply) {
- if (reply->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
- else if (reply->type != REDIS_REPLY_ARRAY) {
- if (reply->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
- } else {
- size_t i;
- for (i = 0; i < reply->elements; ++i) {
- if(strstr(reply->element[i]->str,"/max-bps")||
- strstr(reply->element[i]->str,"/total-quota")||
- strstr(reply->element[i]->str,"/user-quota")) {
- add_to_secrets_list(&keys,reply->element[i]->str);
- }
- }
- }
- turnFreeRedisReply(reply);
- }
- }
- size_t offset = strlen("turn/realm/");
- for(isz=0;isz<keys.sz;++isz) {
- char *o = keys.secrets[isz];
- reply = (redisReply*)redisCommand(rc, "get %s",o);
- if(reply) {
- if (reply->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
- else if (reply->type != REDIS_REPLY_STRING) {
- if (reply->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
- } else {
- printf("%s = %s\n",o+offset,reply->str);
- }
- turnFreeRedisReply(reply);
- }
- }
- clean_secrets_list(&keys);
- ret = 0;
- }
- return ret;
- }
-
- static void redis_auth_ping(void * rch) {
- donot_print_connection_success = 1;
- redisContext *rc = get_redis_connection();
- if(rc) {
- turnFreeRedisReply(redisCommand(rc, "keys turn/origin/*"));
- }
- if(rch)
- send_message_to_redis((redis_context_handle)rch, "publish", "__XXX__", "__YYY__");
- }
-
- static int redis_get_ip_list(const char *kind, ip_range_list_t * list)
- {
- int ret = -1;
- redisContext *rc = get_redis_connection();
- if (rc) {
- char statement[TURN_LONG_STRING_SIZE];
- const char* header = "turn/realm/";
- size_t header_len = strlen(header);
- snprintf(statement, sizeof(statement), "keys %s*/%s-peer-ip", header,kind);
- redisReply *reply = (redisReply*) redisCommand(rc, statement);
- if (reply) {
- secrets_list_t keys;
- size_t isz = 0;
- char s[257];
- init_secrets_list(&keys);
- if (reply->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
- else if (reply->type != REDIS_REPLY_ARRAY) {
- if (reply->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
- } else {
- size_t i;
- for (i = 0; i < reply->elements; ++i) {
- add_to_secrets_list(&keys, reply->element[i]->str);
- }
- }
- for (isz = 0; isz < keys.sz; ++isz) {
- char *realm = NULL;
- snprintf(s, sizeof(s), "smembers %s", keys.secrets[isz]);
- redisReply *rget = (redisReply *) redisCommand(rc, s);
- char *ptr = ((char*)keys.secrets[isz])+header_len;
- char *sep = strstr(ptr, "/");
- if (sep) {
- *sep = 0;
- realm = ptr;
- }
- if (rget) {
- if (rget->type == REDIS_REPLY_ERROR) {
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", rget->str);
- } else if (rget->type == REDIS_REPLY_STRING) {
- add_ip_list_range(rget->str, realm, list);
- } else if (rget->type != REDIS_REPLY_ARRAY) {
- if (rget->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
- } else {
- size_t i;
- for (i = 0; i < rget->elements; ++i) {
- add_ip_list_range(rget->element[i]->str, realm, list);
- }
- }
- turnFreeRedisReply(rget);
- }
- if(sep) {
- *sep='/';
- }
- }
- clean_secrets_list(&keys);
- turnFreeRedisReply(reply);
- ret = 0;
- }
- }
- return ret;
- }
-
- static void redis_reread_realms(secrets_list_t * realms_list) {
- redisContext *rc = get_redis_connection();
- if (rc) {
- redisReply *reply = (redisReply*) redisCommand(rc, "keys turn/origin/*");
- if (reply) {
- ur_string_map *o_to_realm_new = ur_string_map_create(turn_free_simple);
- secrets_list_t keys;
- init_secrets_list(&keys);
- size_t isz = 0;
- char s[1025];
- if (reply->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
- else if (reply->type != REDIS_REPLY_ARRAY) {
- if (reply->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
- } else {
- size_t i;
- for (i = 0; i < reply->elements; ++i) {
- add_to_secrets_list(&keys, reply->element[i]->str);
- }
- }
- size_t offset = strlen("turn/origin/");
- for (isz = 0; isz < keys.sz; ++isz) {
- char *origin = keys.secrets[isz] + offset;
- snprintf(s, sizeof(s), "get %s", keys.secrets[isz]);
- redisReply *rget = (redisReply *) redisCommand(rc, s);
- if (rget) {
- if (rget->type == REDIS_REPLY_ERROR)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", rget->str);
- else if (rget->type != REDIS_REPLY_STRING) {
- if (rget->type != REDIS_REPLY_NIL)
- TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
- } else {
- get_realm(rget->str);
- ur_string_map_value_type value = turn_strdup(rget->str);
- ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) origin, value);
- }
- turnFreeRedisReply(rget);
- }
- }
- clean_secrets_list(&keys);
- update_o_to_realm(o_to_realm_new);
- turnFreeRedisReply(reply);
- }
- {
- size_t i = 0;
- size_t rlsz = 0;
- lock_realms();
- rlsz = realms_list->sz;
- unlock_realms();
- for (i = 0; i<rlsz; ++i) {
- char *realm = realms_list->secrets[i];
- realm_params_t* rp = get_realm(realm);
- unsigned long value = 0;
- if(!set_redis_realm_opt(realm,"max-bps",&value)) {
- lock_realms();
- rp->options.perf_options.max_bps = turn_params.max_bps;
- unlock_realms();
- }
- rp->options.perf_options.max_bps = (band_limit_t)value;
- if(!set_redis_realm_opt(realm,"total-quota",&value)) {
- lock_realms();
- rp->options.perf_options.total_quota = turn_params.total_quota;
- unlock_realms();
- }
- rp->options.perf_options.total_quota = (vint)value;
- if(!set_redis_realm_opt(realm,"user-quota",&value)) {
- lock_realms();
- rp->options.perf_options.user_quota = turn_params.user_quota;
- unlock_realms();
- }
- rp->options.perf_options.user_quota = (vint)value;
- }
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- static turn_dbdriver_t driver = {
- &redis_get_auth_secrets,
- &redis_get_user_key,
- &redis_get_user_pwd,
- &redis_set_user_key,
- &redis_set_user_pwd,
- &redis_del_user,
- &redis_list_users,
- &redis_show_secret,
- &redis_del_secret,
- &redis_set_secret,
- &redis_add_origin,
- &redis_del_origin,
- &redis_list_origins,
- &redis_set_realm_option_one,
- &redis_list_realm_options,
- &redis_auth_ping,
- &redis_get_ip_list,
- &redis_reread_realms,
- &redis_set_oauth_key,
- &redis_get_oauth_key,
- &redis_del_oauth_key,
- &redis_list_oauth_keys
- };
- turn_dbdriver_t * get_redis_dbdriver(void) {
- return &driver;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- #else
- turn_dbdriver_t * get_redis_dbdriver(void) {
- return NULL;
- }
- #endif
|