mirror of
https://github.com/coturn/coturn.git
synced 2025-11-01 23:41:09 +01:00
working on per-realm white/black lists
This commit is contained in:
parent
5b300733dc
commit
13b8ac9e74
@ -1,5 +1,7 @@
|
|||||||
10/16/2014 Oleg Moskalenko <mom040267@gmail.com>
|
10/26/2014 Oleg Moskalenko <mom040267@gmail.com>
|
||||||
Version 4.2.1.4 'Monza':
|
Version 4.2.2.1 'Monza':
|
||||||
|
- black- and white- IP lists are divided per realm
|
||||||
|
(the DB schema changed);
|
||||||
- TCP/TLS tests extended.
|
- TCP/TLS tests extended.
|
||||||
- relay RTCP sockets ports allocation fixed.
|
- relay RTCP sockets ports allocation fixed.
|
||||||
- list of libraries cleaned.
|
- list of libraries cleaned.
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Common settings script.
|
# Common settings script.
|
||||||
|
|
||||||
TURNVERSION=4.2.1.4
|
TURNVERSION=4.2.2.1
|
||||||
BUILDDIR=~/rpmbuild
|
BUILDDIR=~/rpmbuild
|
||||||
ARCH=`uname -p`
|
ARCH=`uname -p`
|
||||||
TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn
|
TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
Name: turnserver
|
Name: turnserver
|
||||||
Version: 4.2.1.4
|
Version: 4.2.2.1
|
||||||
Release: 0%{dist}
|
Release: 0%{dist}
|
||||||
Summary: Coturn TURN Server
|
Summary: Coturn TURN Server
|
||||||
|
|
||||||
@ -294,8 +294,8 @@ fi
|
|||||||
%{_includedir}/turn/client/TurnMsgLib.h
|
%{_includedir}/turn/client/TurnMsgLib.h
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Thu Oct 16 2014 Oleg Moskalenko <mom040267@gmail.com>
|
* Sun Oct 26 2014 Oleg Moskalenko <mom040267@gmail.com>
|
||||||
- Sync to 4.2.1.4
|
- Sync to 4.2.2.1
|
||||||
* Sun Oct 05 2014 Oleg Moskalenko <mom040267@gmail.com>
|
* Sun Oct 05 2014 Oleg Moskalenko <mom040267@gmail.com>
|
||||||
- Sync to 4.2.1.2
|
- Sync to 4.2.1.2
|
||||||
* Thu Aug 14 2014 Oleg Moskalenko <mom040267@gmail.com>
|
* Thu Aug 14 2014 Oleg Moskalenko <mom040267@gmail.com>
|
||||||
|
|||||||
@ -896,11 +896,22 @@ static int mysql_get_ip_list(const char *kind, ip_range_list_t * list) {
|
|||||||
MYSQL * myc = get_mydb_connection();
|
MYSQL * myc = get_mydb_connection();
|
||||||
if(myc) {
|
if(myc) {
|
||||||
char statement[TURN_LONG_STRING_SIZE];
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
snprintf(statement,sizeof(statement),"select ip_range from %s_peer_ip",kind);
|
snprintf(statement,sizeof(statement),"select ip_range,realm from %s_peer_ip",kind);
|
||||||
int res = mysql_query(myc, statement);
|
int res = mysql_query(myc, statement);
|
||||||
|
|
||||||
|
if(res) {
|
||||||
|
static int wrong_table_reported = 0;
|
||||||
|
if(!wrong_table_reported) {
|
||||||
|
wrong_table_reported = 1;
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information; probably, the tables 'allowed_peer_ip' and/or 'denied_peer_ip' have to be upgraded to include the realm column.\n");
|
||||||
|
}
|
||||||
|
snprintf(statement, sizeof(statement), "select ip_range,'' from %s_peer_ip", kind);
|
||||||
|
res = mysql_query(myc, statement);
|
||||||
|
}
|
||||||
|
|
||||||
if(res == 0) {
|
if(res == 0) {
|
||||||
MYSQL_RES *mres = mysql_store_result(myc);
|
MYSQL_RES *mres = mysql_store_result(myc);
|
||||||
if(mres && mysql_field_count(myc)==1) {
|
if(mres && mysql_field_count(myc)==2) {
|
||||||
for(;;) {
|
for(;;) {
|
||||||
MYSQL_ROW row = mysql_fetch_row(mres);
|
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||||
if(!row) {
|
if(!row) {
|
||||||
@ -913,7 +924,11 @@ static int mysql_get_ip_list(const char *kind, ip_range_list_t * list) {
|
|||||||
char kval[TURN_LONG_STRING_SIZE];
|
char kval[TURN_LONG_STRING_SIZE];
|
||||||
ns_bcopy(row[0],kval,sz);
|
ns_bcopy(row[0],kval,sz);
|
||||||
kval[sz]=0;
|
kval[sz]=0;
|
||||||
add_ip_list_range(kval,NULL,list);
|
sz = lengths[1];
|
||||||
|
char rval[TURN_LONG_STRING_SIZE];
|
||||||
|
ns_bcopy(row[1],rval,sz);
|
||||||
|
rval[sz]=0;
|
||||||
|
add_ip_list_range(kval,rval,list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -645,30 +645,43 @@ static void pgsql_auth_ping(void * rch) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pgsql_get_ip_list(const char *kind, ip_range_list_t * list) {
|
|
||||||
int ret = -1;
|
static int pgsql_get_ip_list(const char *kind, ip_range_list_t * list)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
PGconn * pqc = get_pqdb_connection();
|
PGconn * pqc = get_pqdb_connection();
|
||||||
if(pqc) {
|
if (pqc) {
|
||||||
char statement[TURN_LONG_STRING_SIZE];
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
snprintf(statement,sizeof(statement),"select ip_range from %s_peer_ip",kind);
|
snprintf(statement, sizeof(statement), "select ip_range,realm from %s_peer_ip", kind);
|
||||||
PGresult *res = PQexec(pqc, statement);
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
|
||||||
if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) {
|
if (!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
|
||||||
int i = 0;
|
static int wrong_table_reported = 0;
|
||||||
for(i=0;i<PQntuples(res);i++) {
|
if(!wrong_table_reported) {
|
||||||
char *kval = PQgetvalue(res,i,0);
|
wrong_table_reported = 1;
|
||||||
if(kval) {
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s; probably, the tables 'allowed_peer_ip' and/or 'denied_peer_ip' have to be upgraded to include the realm column.\n",PQerrorMessage(pqc));
|
||||||
add_ip_list_range(kval,NULL,list);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ret = 0;
|
snprintf(statement, sizeof(statement), "select ip_range,'' from %s_peer_ip", kind);
|
||||||
|
res = PQexec(pqc, statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(res) {
|
if (res && (PQresultStatus(res) == PGRES_TUPLES_OK)) {
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0; i < PQntuples(res); i++) {
|
||||||
|
char *kval = PQgetvalue(res, i, 0);
|
||||||
|
char *rval = PQgetvalue(res, i, 1);
|
||||||
|
if (kval) {
|
||||||
|
add_ip_list_range(kval, rval, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res) {
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pgsql_reread_realms(secrets_list_t * realms_list) {
|
static void pgsql_reread_realms(secrets_list_t * realms_list) {
|
||||||
|
|||||||
@ -1094,14 +1094,20 @@ static void redis_auth_ping(void * rch) {
|
|||||||
send_message_to_redis((redis_context_handle)rch, "publish", "__XXX__", "__YYY__");
|
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;
|
|
||||||
|
static int redis_get_ip_list(const char *kind, ip_range_list_t * list)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
redisContext *rc = get_redis_connection();
|
redisContext *rc = get_redis_connection();
|
||||||
if(rc) {
|
if (rc) {
|
||||||
|
char header[TURN_LONG_STRING_SIZE];
|
||||||
char statement[TURN_LONG_STRING_SIZE];
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
snprintf(statement,sizeof(statement),"keys turn/%s-peer-ip/*", kind);
|
snprintf(header, sizeof(header), "turn/%s-peer-ip/", kind);
|
||||||
redisReply *reply = (redisReply*)redisCommand(rc, statement);
|
size_t header_len = strlen(header);
|
||||||
if(reply) {
|
snprintf(statement, sizeof(statement), "keys %s*", header);
|
||||||
|
redisReply *reply = (redisReply*) redisCommand(rc, statement);
|
||||||
|
if (reply) {
|
||||||
secrets_list_t keys;
|
secrets_list_t keys;
|
||||||
size_t isz = 0;
|
size_t isz = 0;
|
||||||
char s[257];
|
char s[257];
|
||||||
@ -1116,21 +1122,31 @@ static int redis_get_ip_list(const char *kind, ip_range_list_t * list) {
|
|||||||
} else {
|
} else {
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < reply->elements; ++i) {
|
for (i = 0; i < reply->elements; ++i) {
|
||||||
add_to_secrets_list(&keys,reply->element[i]->str);
|
add_to_secrets_list(&keys, reply->element[i]->str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(isz=0;isz<keys.sz;++isz) {
|
for (isz = 0; isz < keys.sz; ++isz) {
|
||||||
snprintf(s,sizeof(s),"get %s", keys.secrets[isz]);
|
char *realm = NULL;
|
||||||
redisReply *rget = (redisReply *)redisCommand(rc, s);
|
snprintf(s, sizeof(s), "get %s", keys.secrets[isz]);
|
||||||
if(rget) {
|
redisReply *rget = (redisReply *) redisCommand(rc, s);
|
||||||
|
if (rget) {
|
||||||
if (rget->type == REDIS_REPLY_ERROR)
|
if (rget->type == REDIS_REPLY_ERROR)
|
||||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", rget->str);
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", rget->str);
|
||||||
else if (rget->type != REDIS_REPLY_STRING) {
|
else if (rget->type != REDIS_REPLY_STRING) {
|
||||||
if (rget->type != REDIS_REPLY_NIL)
|
if (rget->type != REDIS_REPLY_NIL)
|
||||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
|
||||||
} else {
|
} else {
|
||||||
add_ip_list_range(rget->str,NULL,list);
|
char *ptr = ((char*)keys.secrets[isz])+header_len;
|
||||||
|
char *sep = strstr(ptr, "/");
|
||||||
|
if (sep) {
|
||||||
|
*sep = 0;
|
||||||
|
realm = ptr;
|
||||||
|
}
|
||||||
|
add_ip_list_range(rget->str, realm, list);
|
||||||
|
if(sep) {
|
||||||
|
*sep='/';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
turnFreeRedisReply(rget);
|
turnFreeRedisReply(rget);
|
||||||
}
|
}
|
||||||
@ -1139,10 +1155,10 @@ static int redis_get_ip_list(const char *kind, ip_range_list_t * list) {
|
|||||||
clean_secrets_list(&keys);
|
clean_secrets_list(&keys);
|
||||||
|
|
||||||
turnFreeRedisReply(reply);
|
turnFreeRedisReply(reply);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void redis_reread_realms(secrets_list_t * realms_list) {
|
static void redis_reread_realms(secrets_list_t * realms_list) {
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
#ifndef __IOADEFS__
|
#ifndef __IOADEFS__
|
||||||
#define __IOADEFS__
|
#define __IOADEFS__
|
||||||
|
|
||||||
#define TURN_SERVER_VERSION "4.2.1.4"
|
#define TURN_SERVER_VERSION "4.2.2.1"
|
||||||
#define TURN_SERVER_VERSION_NAME "Monza"
|
#define TURN_SERVER_VERSION_NAME "Monza"
|
||||||
#define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'"
|
#define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'"
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
CREATE TABLE turnusers_lt (
|
CREATE TABLE turnusers_lt (
|
||||||
realm varchar(512),
|
realm varchar(512) default '',
|
||||||
name varchar(512),
|
name varchar(512),
|
||||||
hmackey char(128),
|
hmackey char(128),
|
||||||
PRIMARY KEY (realm,name)
|
PRIMARY KEY (realm,name)
|
||||||
@ -12,19 +12,21 @@ CREATE TABLE turnusers_st (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE turn_secret (
|
CREATE TABLE turn_secret (
|
||||||
realm varchar(512),
|
realm varchar(512) default '',
|
||||||
value varchar(512),
|
value varchar(512),
|
||||||
primary key (realm,value)
|
primary key (realm,value)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE allowed_peer_ip (
|
CREATE TABLE allowed_peer_ip (
|
||||||
|
realm varchar(512) default '',
|
||||||
ip_range varchar(256),
|
ip_range varchar(256),
|
||||||
primary key (ip_range)
|
primary key (realm,ip_range)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE denied_peer_ip (
|
CREATE TABLE denied_peer_ip (
|
||||||
|
realm varchar(512) default '',
|
||||||
ip_range varchar(256),
|
ip_range varchar(256),
|
||||||
primary key (ip_range)
|
primary key (realm,ip_range)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE turn_origin_to_realm (
|
CREATE TABLE turn_origin_to_realm (
|
||||||
@ -34,7 +36,7 @@ CREATE TABLE turn_origin_to_realm (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE turn_realm_option (
|
CREATE TABLE turn_realm_option (
|
||||||
realm varchar(512),
|
realm varchar(512) default '',
|
||||||
opt varchar(32),
|
opt varchar(32),
|
||||||
value varchar(128),
|
value varchar(128),
|
||||||
primary key (realm,opt)
|
primary key (realm,opt)
|
||||||
|
|||||||
@ -28,13 +28,17 @@ issue command "keys turn/realm/north.gov/secret/*" it it will try to use the
|
|||||||
obtained keys in arbitrary order.
|
obtained keys in arbitrary order.
|
||||||
|
|
||||||
4) The "white" and "black" peer IP ranges are stored as keys of the
|
4) The "white" and "black" peer IP ranges are stored as keys of the
|
||||||
following form: "turn/allowed-peer-ip/<arbitrary>" or
|
following form:
|
||||||
"turn/denied-peer-ip/<arbitrary>"
|
"turn/allowed-peer-ip/<arbitrary-unique-id>" or
|
||||||
|
"turn/allowed-peer-ip/<realm>/<arbitrary-unique-id>" or
|
||||||
|
"turn/denied-peer-ip/<arbitrary-unique-id>" or
|
||||||
|
"turn/denied-peer-ip/<realm>/<arbitrary-unique-id>".
|
||||||
|
|
||||||
The meaning of the keys is the same as the meaning of allowed-peer-ip and
|
The meaning of the keys is the same as the meaning of allowed-peer-ip and
|
||||||
denied-peer-ip turnserver command-line option. The only difference is that
|
denied-peer-ip turnserver command-line option (with the addition of the realm option).
|
||||||
the option values are "static" (they remain the same for the lifetime of
|
The only difference is that the turnserver option values are "static"
|
||||||
the turnserver process) but the database records can be dynamically changed
|
(they remain the same for the lifetime of the turnserver process) but
|
||||||
|
the database records can be dynamically changed
|
||||||
and they will be almost immediately "seen" by the turnserver process.
|
and they will be almost immediately "seen" by the turnserver process.
|
||||||
|
|
||||||
5) For the oAuth authentication, there is a hash structure with the key
|
5) For the oAuth authentication, there is a hash structure with the key
|
||||||
@ -143,7 +147,12 @@ set turn/origin/https://bligh.edu:443 crinna.org
|
|||||||
set turn/denied-peer-ip/123456 "172.17.13.133-172.17.14.56"
|
set turn/denied-peer-ip/123456 "172.17.13.133-172.17.14.56"
|
||||||
set turn/denied-peer-ip/234567 "123::45"
|
set turn/denied-peer-ip/234567 "123::45"
|
||||||
|
|
||||||
|
set turn/denied-peer-ip/north.gov/1234567 "172.17.17.133-172.17.19.56"
|
||||||
|
set turn/denied-peer-ip/crinna.org/2345678 "123::77"
|
||||||
|
|
||||||
set turn/allowed-peer-ip/345678 "172.17.13.200"
|
set turn/allowed-peer-ip/345678 "172.17.13.200"
|
||||||
|
set turn/allowed-peer-ip/north.gov/345679 "172.17.13.201"
|
||||||
|
set turn/allowed-peer-ip/crinna.org/3456710 "172.17.13.202"
|
||||||
|
|
||||||
hmset turn/oauth/kid/north ikm_key Y2FybGVvbg== hkdf_hash_func 'SHA-256' as_rs_alg 'AES-128-CBC' auth_alg 'HMAC-SHA-256-128'
|
hmset turn/oauth/kid/north ikm_key Y2FybGVvbg== hkdf_hash_func 'SHA-256' as_rs_alg 'AES-128-CBC' auth_alg 'HMAC-SHA-256-128'
|
||||||
|
|
||||||
|
|||||||
@ -45,7 +45,12 @@ set turn/origin/https://bligh.edu:443 crinna.org
|
|||||||
set turn/denied-peer-ip/123456 "172.17.13.133-172.17.14.56"
|
set turn/denied-peer-ip/123456 "172.17.13.133-172.17.14.56"
|
||||||
set turn/denied-peer-ip/234567 "123::45"
|
set turn/denied-peer-ip/234567 "123::45"
|
||||||
|
|
||||||
|
set turn/denied-peer-ip/north.gov/1234567 "172.17.17.133-172.17.19.56"
|
||||||
|
set turn/denied-peer-ip/crinna.org/2345678 "123::77"
|
||||||
|
|
||||||
set turn/allowed-peer-ip/345678 "172.17.13.200"
|
set turn/allowed-peer-ip/345678 "172.17.13.200"
|
||||||
|
set turn/allowed-peer-ip/north.gov/345679 "172.17.13.201"
|
||||||
|
set turn/allowed-peer-ip/crinna.org/3456710 "172.17.13.202"
|
||||||
|
|
||||||
hmset turn/oauth/kid/north ikm_key Y2FybGVvbg== hkdf_hash_func 'SHA-256' as_rs_alg 'AES-256-CBC' auth_alg 'HMAC-SHA-256-128'
|
hmset turn/oauth/kid/north ikm_key Y2FybGVvbg== hkdf_hash_func 'SHA-256' as_rs_alg 'AES-256-CBC' auth_alg 'HMAC-SHA-256-128'
|
||||||
hmset turn/oauth/kid/oldempire ikm_key YXVsY3Vz hkdf_hash_func 'SHA-256' as_rs_alg 'AEAD-AES-256-GCM'
|
hmset turn/oauth/kid/oldempire ikm_key YXVsY3Vz hkdf_hash_func 'SHA-256' as_rs_alg 'AEAD-AES-256-GCM'
|
||||||
|
|||||||
@ -23,9 +23,13 @@ insert into turn_realm_option (realm,opt,value) values('north.gov','user-quota',
|
|||||||
insert into turn_realm_option (realm,opt,value) values('crinna.org','user-quota','8000');
|
insert into turn_realm_option (realm,opt,value) values('crinna.org','user-quota','8000');
|
||||||
|
|
||||||
insert into allowed_peer_ip (ip_range) values('172.17.13.200');
|
insert into allowed_peer_ip (ip_range) values('172.17.13.200');
|
||||||
|
insert into allowed_peer_ip (realm,ip_range) values('north.gov','172.17.13.201');
|
||||||
|
insert into allowed_peer_ip (realm,ip_range) values('crinna.org','172.17.13.202');
|
||||||
|
|
||||||
insert into denied_peer_ip (ip_range) values('172.17.13.133-172.17.14.56');
|
insert into denied_peer_ip (ip_range) values('172.17.13.133-172.17.14.56');
|
||||||
insert into denied_peer_ip (ip_range) values('123::45');
|
insert into denied_peer_ip (ip_range) values('123::45');
|
||||||
|
insert into denied_peer_ip (realm,ip_range) values('north.gov','172.17.17.133-172.17.19.56');
|
||||||
|
insert into denied_peer_ip (realm,ip_range) values('crinna.org','123::77');
|
||||||
|
|
||||||
insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('north','Y2FybGVvbg==',0,0,'SHA-256','AES-256-CBC','','HMAC-SHA-256-128','');
|
insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('north','Y2FybGVvbg==',0,0,'SHA-256','AES-256-CBC','','HMAC-SHA-256-128','');
|
||||||
insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('oldempire','YXVsY3Vz',0,0,'SHA-256','AEAD-AES-256-GCM','','','');
|
insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('oldempire','YXVsY3Vz',0,0,'SHA-256','AEAD-AES-256-GCM','','','');
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user