diff --git a/examples/var/db/turndb b/examples/var/db/turndb index 8a52386..8026af8 100644 Binary files a/examples/var/db/turndb and b/examples/var/db/turndb differ diff --git a/src/apps/relay/dbdrivers/dbd_mongo.c b/src/apps/relay/dbdrivers/dbd_mongo.c index cf04a86..a491df6 100644 --- a/src/apps/relay/dbdrivers/dbd_mongo.c +++ b/src/apps/relay/dbdrivers/dbd_mongo.c @@ -666,7 +666,7 @@ static int mongo_del_secret(u08bits *secret, u08bits *realm) { BSON_APPEND_UTF8(&query, "realm", (const char *)realm); if(secret && (secret[0]!=0)) { BSON_APPEND_UTF8(&query, "value", (const char *)secret); - } + } mongoc_collection_delete(collection, MONGOC_DELETE_NONE, &query, NULL, NULL); mongoc_collection_destroy(collection); @@ -696,38 +696,89 @@ static int mongo_set_secret(u08bits *secret, u08bits *realm) { return 0; } } - -static int mongo_add_origin(u08bits *origin, u08bits *realm) { - mongoc_collection_t * collection = mongo_get_collection("realm"); + +static int mongo_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int delete) +{ + char sub_collection_name[129]; + snprintf(sub_collection_name,sizeof(sub_collection_name)-1,"%s_peer_ip",kind); + + mongoc_collection_t * collection = mongo_get_collection("realm"); if(!collection) - return -1; - - int ret = -1; - - bson_t query, doc, child; - bson_init(&query); - BSON_APPEND_UTF8(&query, "realm", (const char *)realm); - bson_init(&doc); - bson_append_document_begin(&doc, "$addToSet", -1, &child); - BSON_APPEND_UTF8(&child, "origin", (const char *)origin); - bson_append_document_end(&doc, &child); + return -1; - if (!mongoc_collection_update(collection, MONGOC_UPDATE_UPSERT, &query, &doc, NULL, NULL)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating realm origin information\n"); - } else { - ret = 0; - } - mongoc_collection_destroy(collection); - bson_destroy(&query); - bson_destroy(&doc); - return ret; + int ret = -1; + + u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0"; + if(!realm) realm=realm0; + + bson_t query, doc, child; + bson_init(&query); + BSON_APPEND_UTF8(&query, "realm", (const char *)realm); + bson_init(&doc); + if(delete) { + bson_append_document_begin(&doc, "$pull", -1, &child); + } else { + bson_append_document_begin(&doc, "$addToSet", -1, &child); + } + BSON_APPEND_UTF8(&child, sub_collection_name, (const char *)ip); + bson_append_document_end(&doc, &child); + + mongoc_update_flags_t flags = 0; + + if(delete) { + flags = MONGOC_UPDATE_MULTI_UPDATE; + } else { + flags = MONGOC_UPDATE_UPSERT; + } + + if (!mongoc_collection_update(collection, flags, &query, &doc, NULL, NULL)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting permission ip information\n"); + } else { + ret = 0; + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + bson_destroy(&doc); + return ret; } -static int mongo_del_origin(u08bits *origin) { - mongoc_collection_t * collection = mongo_get_collection("realm"); +static int mongo_add_origin(u08bits *origin, u08bits *realm) +{ + mongoc_collection_t * collection = mongo_get_collection("realm"); if(!collection) + return -1; + + int ret = -1; + + u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0"; + if(!realm) realm=realm0; + + bson_t query, doc, child; + bson_init(&query); + BSON_APPEND_UTF8(&query, "realm", (const char *)realm); + bson_init(&doc); + bson_append_document_begin(&doc, "$addToSet", -1, &child); + BSON_APPEND_UTF8(&child, "origin", (const char *)origin); + bson_append_document_end(&doc, &child); + + if (!mongoc_collection_update(collection, MONGOC_UPDATE_UPSERT, &query, &doc, NULL, NULL)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating realm origin information\n"); + } else { + ret = 0; + } + mongoc_collection_destroy(collection); + bson_destroy(&query); + bson_destroy(&doc); + return ret; +} + +static int mongo_del_origin(u08bits *origin) +{ + mongoc_collection_t * collection = mongo_get_collection("realm"); + + if(!collection) return -1; int ret = -1; @@ -1327,6 +1378,7 @@ static const turn_dbdriver_t driver = { &mongo_list_realm_options, &mongo_auth_ping, &mongo_get_ip_list, + &mongo_set_permission_ip, &mongo_reread_realms, &mongo_set_oauth_key, &mongo_get_oauth_key, diff --git a/src/apps/relay/dbdrivers/dbd_mysql.c b/src/apps/relay/dbdrivers/dbd_mysql.c index 4b793d3..a536bda 100644 --- a/src/apps/relay/dbdrivers/dbd_mysql.c +++ b/src/apps/relay/dbdrivers/dbd_mysql.c @@ -701,6 +701,37 @@ static int mysql_set_secret(u08bits *secret, u08bits *realm) { } return ret; } + +static int mysql_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int delete) +{ + int ret = -1; + + u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0"; + if(!realm) realm=realm0; + + donot_print_connection_success = 1; + + char statement[TURN_LONG_STRING_SIZE]; + + MYSQL * myc = get_mydb_connection(); + if (myc) { + if(delete) { + snprintf(statement, sizeof(statement), "delete from %s_peer_ip where realm = '%s' and ip_range = '%s'", kind, (char*)realm, ip); + } else { + snprintf(statement, sizeof(statement), "insert into %s_peer_ip (realm,ip_range) values('%s','%s')", kind, (char*)realm, ip); + } + int res = mysql_query(myc, statement); + if (res) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "Error inserting permission ip information: %s\n", + mysql_error(myc)); + } else { + ret = 0; + } + } + return ret; +} static int mysql_add_origin(u08bits *origin, u08bits *realm) { int ret = -1; @@ -1196,6 +1227,7 @@ static const turn_dbdriver_t driver = { &mysql_list_realm_options, &mysql_auth_ping, &mysql_get_ip_list, + &mysql_set_permission_ip, &mysql_reread_realms, &mysql_set_oauth_key, &mysql_get_oauth_key, diff --git a/src/apps/relay/dbdrivers/dbd_pgsql.c b/src/apps/relay/dbdrivers/dbd_pgsql.c index 9f843bf..6b99e2a 100644 --- a/src/apps/relay/dbdrivers/dbd_pgsql.c +++ b/src/apps/relay/dbdrivers/dbd_pgsql.c @@ -245,7 +245,7 @@ static int pgsql_set_user_key(u08bits *usname, u08bits *realm, const char *key) if(res) { PQclear(res); } - snprintf(statement,sizeof(statement),"update turnusers_lt set hmackey='%s' where name='%s' and realm='%s'",key,usname,realm); + snprintf(statement,sizeof(statement),"update turnusers_lt set hmackey='%s' where name='%s' and realm='%s'",key,usname,realm); res = PQexec(pqc, statement); if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user information: %s\n",PQerrorMessage(pqc)); @@ -449,13 +449,13 @@ static int pgsql_del_secret(u08bits *secret, u08bits *realm) { static int pgsql_set_secret(u08bits *secret, u08bits *realm) { int ret = -1; donot_print_connection_success = 1; - char statement[TURN_LONG_STRING_SIZE]; + char statement[TURN_LONG_STRING_SIZE]; PGconn *pqc = get_pqdb_connection(); if (pqc) { snprintf(statement,sizeof(statement),"insert into turn_secret (realm,value) values('%s','%s')",realm,secret); PGresult *res = PQexec(pqc, statement); if (!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { - TURN_LOG_FUNC( + TURN_LOG_FUNC( TURN_LOG_LEVEL_ERROR, "Error inserting/updating secret key information: %s\n", PQerrorMessage(pqc)); @@ -467,7 +467,45 @@ static int pgsql_set_secret(u08bits *secret, u08bits *realm) { } } - return ret; + return ret; +} + +static int pgsql_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int delete) +{ + int ret = -1; + + u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0"; + if(!realm) realm=realm0; + + donot_print_connection_success = 1; + + char statement[TURN_LONG_STRING_SIZE]; + + PGconn *pqc = get_pqdb_connection(); + + if (pqc) { + + if(delete) { + snprintf(statement, sizeof(statement), "delete from %s_peer_ip where realm = '%s' and ip_range = '%s'", kind, (char*)realm, ip); + } else { + snprintf(statement, sizeof(statement), "insert into %s_peer_ip (realm,ip_range) values('%s','%s')", kind, (char*)realm, ip); + } + + PGresult *res = PQexec(pqc, statement); + if (!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) { + TURN_LOG_FUNC( + TURN_LOG_LEVEL_ERROR, + "Error inserting ip permission information: %s\n", + PQerrorMessage(pqc)); + } else { + ret = 0; + } + if (res) { + PQclear(res); + } + } + + return ret; } static int pgsql_add_origin(u08bits *origin, u08bits *realm) { @@ -913,6 +951,7 @@ static const turn_dbdriver_t driver = { &pgsql_list_realm_options, &pgsql_auth_ping, &pgsql_get_ip_list, + &pgsql_set_permission_ip, &pgsql_reread_realms, &pgsql_set_oauth_key, &pgsql_get_oauth_key, diff --git a/src/apps/relay/dbdrivers/dbd_redis.c b/src/apps/relay/dbdrivers/dbd_redis.c index fbd7fa5..de1bf28 100644 --- a/src/apps/relay/dbdrivers/dbd_redis.c +++ b/src/apps/relay/dbdrivers/dbd_redis.c @@ -809,6 +809,32 @@ static int redis_set_secret(u08bits *secret, u08bits *realm) } return ret; } + +static int redis_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int delete) +{ + int ret = -1; + + u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0"; + if(!realm) realm=realm0; + + donot_print_connection_success = 1; + + redisContext *rc = get_redis_connection(); + if (rc) { + char s[TURN_LONG_STRING_SIZE]; + + if(delete) { + snprintf(s, sizeof(s), "srem turn/realm/%s/%s-peer-ip %s", (char*) realm, kind, ip); + } else { + snprintf(s, sizeof(s), "sadd turn/realm/%s/%s-peer-ip %s", (char*) realm, kind, ip); + } + + turnFreeRedisReply(redisCommand(rc, s)); + turnFreeRedisReply(redisCommand(rc, "save")); + ret = 0; + } + return ret; +} static int redis_add_origin(u08bits *origin, u08bits *realm) { int ret = -1; @@ -1315,6 +1341,7 @@ static const turn_dbdriver_t driver = { &redis_list_realm_options, &redis_auth_ping, &redis_get_ip_list, + &redis_set_permission_ip, &redis_reread_realms, &redis_set_oauth_key, &redis_get_oauth_key, diff --git a/src/apps/relay/dbdrivers/dbd_sqlite.c b/src/apps/relay/dbdrivers/dbd_sqlite.c index 36e6dc5..f5f2c6d 100644 --- a/src/apps/relay/dbdrivers/dbd_sqlite.c +++ b/src/apps/relay/dbdrivers/dbd_sqlite.c @@ -959,6 +959,45 @@ static int sqlite_get_ip_list(const char *kind, ip_range_list_t * list) return ret; } +static int sqlite_set_permission_ip(const char *kind, u08bits *realm, const char* ip, int delete) +{ + int ret = -1; + + u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0"; + if(!realm) realm=realm0; + + char statement[TURN_LONG_STRING_SIZE]; + + sqlite3_stmt *st = NULL; + int rc = 0; + + donot_print_connection_success=1; + + sqlite3 *sqliteconnection = get_sqlite_connection(); + if (sqliteconnection) { + + sqlite_lock(1); + + if(delete) { + snprintf(statement, sizeof(statement), "delete from %s_peer_ip where realm = '%s' and ip_range = '%s'", kind, (char*)realm, ip); + } else { + snprintf(statement, sizeof(statement), "insert or replace into %s_peer_ip (realm,ip_range) values('%s','%s')", kind, (char*)realm, ip); + } + + if ((rc = sqlite3_prepare(sqliteconnection, statement, -1, &st, 0)) == SQLITE_OK) { + sqlite3_step(st); + ret = 0; + } else { + const char* errmsg = sqlite3_errmsg(sqliteconnection); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error updating SQLite DB information: %s\n", errmsg); + } + sqlite3_finalize(st); + + sqlite_unlock(1); + } + return ret; +} + static void sqlite_reread_realms(secrets_list_t * realms_list) { sqlite3 *sqliteconnection = get_sqlite_connection(); @@ -1254,6 +1293,7 @@ static const turn_dbdriver_t driver = { &sqlite_list_realm_options, &sqlite_auth_ping, &sqlite_get_ip_list, + &sqlite_set_permission_ip, &sqlite_reread_realms, &sqlite_set_oauth_key, &sqlite_get_oauth_key, diff --git a/src/apps/relay/dbdrivers/dbdriver.h b/src/apps/relay/dbdrivers/dbdriver.h index 53f1fd0..7cfd3b0 100644 --- a/src/apps/relay/dbdrivers/dbdriver.h +++ b/src/apps/relay/dbdrivers/dbdriver.h @@ -63,6 +63,7 @@ typedef struct _turn_dbdriver_t { int (*list_realm_options)(u08bits *realm); void (*auth_ping)(void * rch); int (*get_ip_list)(const char *kind, ip_range_list_t * list); + int (*set_permission_ip)(const char *kind, u08bits *realm, const char* ip, int delete); void (*reread_realms)(secrets_list_t * realms_list); int (*set_oauth_key)(oauth_key_data_raw *key); int (*get_oauth_key)(const u08bits *kid, oauth_key_data_raw *key); diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index 416c236..337dbd7 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -238,8 +238,8 @@ static void free_headers_list(struct headers_list *h) { } } -const char *get_http_header_value(const struct http_request *request, const char* key) { - const char *ret = NULL; +const char *get_http_header_value(const struct http_request *request, const char* key, const char* default_value) { + const char *ret = default_value; if(key && key[0] && request && request->headers) { if(request->headers->uri_headers) { ret = evhttp_find_header(request->headers->uri_headers,key); @@ -247,6 +247,7 @@ const char *get_http_header_value(const struct http_request *request, const char if(!ret && request->headers->post_headers) { ret = get_headers_list_value(request->headers->post_headers,key); } + if(!ret) ret = default_value; } return ret; } diff --git a/src/apps/relay/http_server.h b/src/apps/relay/http_server.h index 8bb3f26..422d795 100644 --- a/src/apps/relay/http_server.h +++ b/src/apps/relay/http_server.h @@ -63,7 +63,7 @@ struct http_request { }; struct http_request* parse_http_request(char* request); -const char *get_http_header_value(const struct http_request *request, const char* key); +const char *get_http_header_value(const struct http_request *request, const char* key, const char* def); void free_http_request(struct http_request *request); //////////////////////////////////////////// diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index a115c87..821654f 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1384,6 +1384,13 @@ typedef enum _AS_FORM AS_FORM; #define HR_DELETE_REALM "dr" #define HR_DELETE_SECRET "ds" #define HR_DELETE_ORIGIN "do" +#define HR_DELETE_IP "dip" +#define HR_DELETE_IP_REALM "dipr" +#define HR_DELETE_IP_KIND "dipk" +#define HR_ADD_IP "aip" +#define HR_ADD_IP_REALM "aipr" +#define HR_ADD_IP_KIND "aipk" +#define HR_UPDATE_PARAMETER "togglepar" struct form_name { AS_FORM form; @@ -1571,7 +1578,7 @@ static void sbprintf(struct str_buffer *sb, const char *format, ...) if(sb && format) { va_list args; va_start (args, format); - static char s[1025]="\0"; + char s[1025]="\0"; vsnprintf(s,sizeof(s)-1,format, args); str_buffer_append(sb,s); va_end (args); @@ -1586,7 +1593,7 @@ static void https_print_flag(struct str_buffer* sb, int flag, const char* name, if(!param_name) { sbprintf(sb,"