working on oauth

This commit is contained in:
mom040267 2014-08-27 07:19:48 +00:00
parent e6bc87dd08
commit 268de3e3d1
7 changed files with 702 additions and 31 deletions

15
INSTALL
View File

@ -769,6 +769,21 @@ used for the HMAC key generation.
The key must be 32 characters (HEX representation of 16 bytes) for SHA1,
or 64 characters (HEX representation of 32 bytes) for SHA256.
# oAuth key storage table.
#
CREATE TABLE oauth_key (
kid varchar(128),
ikm_key varchar(256) default '',
timestamp bigint default 0,
lifetime integer default 0,
hkdf_hash_func varchar(64) default '',
as_rs_alg varchar(64) default '',
as_rs_key varchar(256) default '',
auth_alg varchar(64) default '',
auth_key varchar(256) default '',
primary key (kid)
);
You can use turnadmin program to manage the database - you can either use
turnadmin to add/modify/delete users, or you can use turnadmin to produce
the hmac keys and modify the database with your favorite tools.

View File

@ -234,6 +234,79 @@ static int mongo_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) {
bson_destroy(&fields);
return ret;
}
static int mongo_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
mongoc_collection_t * collection = mongo_get_collection("oauth_key");
if (!collection)
return -1;
bson_t query;
bson_init(&query);
BSON_APPEND_UTF8(&query, "kid", (const char *)key->kid);
bson_t fields;
bson_init(&fields);
BSON_APPEND_INT32(&fields, "lifetime", 1);
BSON_APPEND_INT32(&fields, "timestamp", 1);
BSON_APPEND_INT32(&fields, "as_rs_alg", 1);
BSON_APPEND_INT32(&fields, "as_rs_key", 1);
BSON_APPEND_INT32(&fields, "auth_alg", 1);
BSON_APPEND_INT32(&fields, "auth_key", 1);
BSON_APPEND_INT32(&fields, "hkdf_hash_func", 1);
BSON_APPEND_INT32(&fields, "ikm_key", 1);
mongoc_cursor_t * cursor;
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 1, 0,
&query, &fields, NULL);
int ret = -1;
ns_bzero(key,sizeof(oauth_key_data_raw));
STRCPY(key->kid,kid);
if (!cursor) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
"Error querying MongoDB collection 'oauth_key'\n");
} else {
const bson_t * item;
uint32_t length;
bson_iter_t iter;
if (mongoc_cursor_next(cursor, &item)) {
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "as_rs_alg") && BSON_ITER_HOLDS_UTF8(&iter)) {
STRCPY(key->as_rs_alg,bson_iter_utf8(&iter, &length));
}
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "as_rs_key") && BSON_ITER_HOLDS_UTF8(&iter)) {
STRCPY(key->as_rs_key,bson_iter_utf8(&iter, &length));
}
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "auth_alg") && BSON_ITER_HOLDS_UTF8(&iter)) {
STRCPY(key->auth_alg,bson_iter_utf8(&iter, &length));
}
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "auth_key") && BSON_ITER_HOLDS_UTF8(&iter)) {
STRCPY(key->auth_key,bson_iter_utf8(&iter, &length));
}
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "ikm_key") && BSON_ITER_HOLDS_UTF8(&iter)) {
STRCPY(key->ikm_key,bson_iter_utf8(&iter, &length));
}
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "hkdf_hash_func") && BSON_ITER_HOLDS_UTF8(&iter)) {
STRCPY(key->hkdf_hash_func,bson_iter_utf8(&iter, &length));
}
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "timestamp") && BSON_ITER_HOLDS_INT64(&iter)) {
key->timestamp = (u64bits)bson_iter_int64(&iter);
}
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "lifetime") && BSON_ITER_HOLDS_INT32(&iter)) {
key->lifetime = (u32bits)bson_iter_int32(&iter);
}
ret = 0;
}
mongoc_cursor_destroy(cursor);
}
mongoc_collection_destroy(collection);
bson_destroy(&query);
bson_destroy(&fields);
return ret;
}
static int mongo_get_user_pwd(u08bits *usname, st_password_t pwd) {
mongoc_collection_t * collection = mongo_get_collection("turnusers_st");
@ -302,7 +375,43 @@ static int mongo_set_user_key(u08bits *usname, u08bits *realm, const char *key)
int ret = -1;
if (!mongoc_collection_update(collection, MONGOC_UPDATE_UPSERT, &query, &doc, NULL, NULL)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating secret key information\n");
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user key information\n");
} else {
ret = 0;
}
mongoc_collection_destroy(collection);
bson_destroy(&doc);
bson_destroy(&query);
return ret;
}
static int mongo_set_oauth_key(oauth_key_data_raw *key) {
mongoc_collection_t * collection = mongo_get_collection("oauth_key");
if(!collection)
return -1;
bson_t query;
bson_init(&query);
BSON_APPEND_UTF8(&query, "kid", (const char *)key->kid);
bson_t doc;
bson_init(&doc);
BSON_APPEND_UTF8(&query, "kid", (const char *)key->kid);
BSON_APPEND_UTF8(&doc, "as_rs_alg", (const char *)key->as_rs_alg);
BSON_APPEND_UTF8(&doc, "as_rs_key", (const char *)key->as_rs_key);
BSON_APPEND_UTF8(&doc, "auth_alg", (const char *)key->auth_alg);
BSON_APPEND_UTF8(&doc, "auth_key", (const char *)key->auth_key);
BSON_APPEND_UTF8(&doc, "hkdf_hash_func", (const char *)key->hkdf_hash_func);
BSON_APPEND_UTF8(&doc, "ikm_key", (const char *)key->ikm_key);
BSON_APPEND_INT64(&doc, "timestamp", (int64_t)key->timestamp);
BSON_APPEND_INT32(&doc, "lifetime", (int32_t)key->lifetime);
int ret = -1;
if (!mongoc_collection_update(collection, MONGOC_UPDATE_UPSERT, &query, &doc, NULL, NULL)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating oauth key information\n");
} else {
ret = 0;
}
@ -364,6 +473,29 @@ static int mongo_del_user(u08bits *usname, int is_st, u08bits *realm) {
bson_destroy(&query);
return ret;
}
static int mongo_del_oauth_key(const u08bits *kid) {
mongoc_collection_t * collection = mongo_get_collection("oauth_key");
if(!collection)
return -1;
bson_t query;
bson_init(&query);
BSON_APPEND_UTF8(&query, "kid", (const char *)kid);
int ret = -1;
if (!mongoc_collection_delete(collection, MONGOC_DELETE_SINGLE_REMOVE, &query, NULL, NULL)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting oauth key information\n");
} else {
ret = 0;
}
mongoc_collection_destroy(collection);
bson_destroy(&query);
return ret;
}
static int mongo_list_users(int is_st, u08bits *realm) {
const char * collection_name = is_st ? "turnusers_st" : "turnusers_lt";
@ -425,6 +557,86 @@ static int mongo_list_users(int is_st, u08bits *realm) {
bson_destroy(&fields);
return ret;
}
static int mongo_list_oauth_keys(void) {
const char * collection_name = "oauth_key";
mongoc_collection_t * collection = mongo_get_collection(collection_name);
if(!collection)
return -1;
bson_t query, child;
bson_init(&query);
bson_append_document_begin(&query, "$orderby", -1, &child);
bson_append_int32(&child, "kid", -1, 1);
bson_append_document_end(&query, &child);
bson_t fields;
bson_init(&fields);
BSON_APPEND_INT32(&fields, "kid", 1);
BSON_APPEND_INT32(&fields, "lifetime", 1);
BSON_APPEND_INT32(&fields, "timestamp", 1);
BSON_APPEND_INT32(&fields, "as_rs_alg", 1);
BSON_APPEND_INT32(&fields, "as_rs_key", 1);
BSON_APPEND_INT32(&fields, "auth_alg", 1);
BSON_APPEND_INT32(&fields, "auth_key", 1);
BSON_APPEND_INT32(&fields, "hkdf_hash_func", 1);
BSON_APPEND_INT32(&fields, "ikm_key", 1);
mongoc_cursor_t * cursor;
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL);
int ret = -1;
if (!cursor) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection '%s'\n", collection_name);
} else {
const bson_t * item;
oauth_key_data_raw key_;
oauth_key_data_raw *key=&key_;
uint32_t length;
bson_iter_t iter;
while (mongoc_cursor_next(cursor, &item)) {
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "kid") && BSON_ITER_HOLDS_UTF8(&iter)) {
STRCPY(key->kid,bson_iter_utf8(&iter, &length));
}
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "as_rs_alg") && BSON_ITER_HOLDS_UTF8(&iter)) {
STRCPY(key->as_rs_alg,bson_iter_utf8(&iter, &length));
}
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "as_rs_key") && BSON_ITER_HOLDS_UTF8(&iter)) {
STRCPY(key->as_rs_key,bson_iter_utf8(&iter, &length));
}
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "auth_alg") && BSON_ITER_HOLDS_UTF8(&iter)) {
STRCPY(key->auth_alg,bson_iter_utf8(&iter, &length));
}
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "auth_key") && BSON_ITER_HOLDS_UTF8(&iter)) {
STRCPY(key->auth_key,bson_iter_utf8(&iter, &length));
}
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "ikm_key") && BSON_ITER_HOLDS_UTF8(&iter)) {
STRCPY(key->ikm_key,bson_iter_utf8(&iter, &length));
}
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "hkdf_hash_func") && BSON_ITER_HOLDS_UTF8(&iter)) {
STRCPY(key->hkdf_hash_func,bson_iter_utf8(&iter, &length));
}
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "timestamp") && BSON_ITER_HOLDS_INT64(&iter)) {
key->timestamp = (u64bits)bson_iter_int64(&iter);
}
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "lifetime") && BSON_ITER_HOLDS_INT32(&iter)) {
key->lifetime = (u32bits)bson_iter_int32(&iter);
}
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);
}
mongoc_cursor_destroy(cursor);
ret = 0;
}
mongoc_collection_destroy(collection);
bson_destroy(&query);
bson_destroy(&fields);
return ret;
}
static int mongo_show_secret(u08bits *realm) {
mongoc_collection_t * collection = mongo_get_collection("turn_secret");
@ -921,7 +1133,11 @@ static turn_dbdriver_t driver = {
&mongo_list_realm_options,
&mongo_auth_ping,
&mongo_get_ip_list,
&mongo_reread_realms
&mongo_reread_realms,
&mongo_set_oauth_key,
&mongo_get_oauth_key,
&mongo_del_oauth_key,
&mongo_list_oauth_keys
};
turn_dbdriver_t * get_mongo_dbdriver(void) {

View File

@ -372,6 +372,140 @@ static int mysql_get_user_pwd(u08bits *usname, st_password_t pwd) {
}
return ret;
}
static int mysql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
int ret = 1;
char statement[TURN_LONG_STRING_SIZE];
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key from oauth_key where kid='%s'",(const char*)kid);
MYSQL * myc = get_mydb_connection();
if(myc) {
int res = mysql_query(myc, statement);
if(res) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
} else {
MYSQL_RES *mres = mysql_store_result(myc);
if(!mres) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
} else if(mysql_field_count(myc)!=8) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement);
} else {
MYSQL_ROW row = mysql_fetch_row(mres);
if(row && row[0]) {
unsigned long *lengths = mysql_fetch_lengths(mres);
if(lengths) {
STRCPY((char*)key->kid,kid);
ns_bcopy(row[0],key->ikm_key,lengths[0]);
key->ikm_key[lengths[0]]=0;
char stimestamp[128];
ns_bcopy(row[1],stimestamp,lengths[1]);
stimestamp[lengths[1]]=0;
key->timestamp = (u64bits)strtoull(stimestamp,NULL,10);
char slifetime[128];
ns_bcopy(row[2],slifetime,lengths[2]);
slifetime[lengths[2]]=0;
key->lifetime = (u32bits)strtoul(slifetime,NULL,10);
ns_bcopy(row[3],key->hkdf_hash_func,lengths[3]);
key->hkdf_hash_func[lengths[3]]=0;
ns_bcopy(row[4],key->as_rs_alg,lengths[4]);
key->as_rs_alg[lengths[4]]=0;
ns_bcopy(row[5],key->as_rs_key,lengths[5]);
key->as_rs_key[lengths[5]]=0;
ns_bcopy(row[6],key->auth_alg,lengths[6]);
key->auth_alg[lengths[6]]=0;
ns_bcopy(row[7],key->auth_key,lengths[7]);
key->auth_key[lengths[7]]=0;
ret = 0;
}
}
}
if(mres)
mysql_free_result(mres);
}
}
return ret;
}
static int mysql_list_oauth_keys(void) {
oauth_key_data_raw key_;
oauth_key_data_raw *key=&key_;
int ret = 1;
char statement[TURN_LONG_STRING_SIZE];
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key,kid from oauth_key order by kid");
MYSQL * myc = get_mydb_connection();
if(myc) {
int res = mysql_query(myc, statement);
if(res) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
} else {
MYSQL_RES *mres = mysql_store_result(myc);
if(!mres) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
} else if(mysql_field_count(myc)!=9) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement);
} else {
MYSQL_ROW row = mysql_fetch_row(mres);
while(row) {
unsigned long *lengths = mysql_fetch_lengths(mres);
if(lengths) {
ns_bcopy(row[0],key->ikm_key,lengths[0]);
key->ikm_key[lengths[0]]=0;
char stimestamp[128];
ns_bcopy(row[1],stimestamp,lengths[1]);
stimestamp[lengths[1]]=0;
key->timestamp = (u64bits)strtoull(stimestamp,NULL,10);
char slifetime[128];
ns_bcopy(row[2],slifetime,lengths[2]);
slifetime[lengths[2]]=0;
key->lifetime = (u32bits)strtoul(slifetime,NULL,10);
ns_bcopy(row[3],key->hkdf_hash_func,lengths[3]);
key->hkdf_hash_func[lengths[3]]=0;
ns_bcopy(row[4],key->as_rs_alg,lengths[4]);
key->as_rs_alg[lengths[4]]=0;
ns_bcopy(row[5],key->as_rs_key,lengths[5]);
key->as_rs_key[lengths[5]]=0;
ns_bcopy(row[6],key->auth_alg,lengths[6]);
key->auth_alg[lengths[6]]=0;
ns_bcopy(row[7],key->auth_key,lengths[7]);
key->auth_key[lengths[7]]=0;
ns_bcopy(row[8],key->kid,lengths[8]);
key->kid[lengths[8]]=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);
}
row = mysql_fetch_row(mres);
}
}
if(mres)
mysql_free_result(mres);
}
}
return ret;
}
static int mysql_set_user_key(u08bits *usname, u08bits *realm, const char *key) {
int ret = 1;
@ -390,6 +524,27 @@ static int mysql_set_user_key(u08bits *usname, u08bits *realm, const char *key)
}
return ret;
}
static int mysql_set_oauth_key(oauth_key_data_raw *key) {
int ret = 1;
char statement[TURN_LONG_STRING_SIZE];
MYSQL * myc = get_mydb_connection();
if(myc) {
snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s','%s','%s')",
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);
int res = mysql_query(myc, statement);
if(res) {
snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, hkdf_hash_func = '%s', as_rs_alg='%s',as_rs_key='%s',auth_alg='%s',auth_key='%s' where kid='%s'",key->ikm_key,(unsigned 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,key->kid);
res = mysql_query(myc, statement);
if(res) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating oauth key information: %s\n",mysql_error(myc));
}
}
}
return ret;
}
static int mysql_set_user_pwd(u08bits *usname, st_password_t pwd) {
int ret = 1;
@ -430,6 +585,22 @@ static int mysql_del_user(u08bits *usname, int is_st, u08bits *realm) {
}
return ret;
}
static int mysql_del_oauth_key(const u08bits *kid) {
int ret = 1;
char statement[TURN_LONG_STRING_SIZE];
MYSQL * myc = get_mydb_connection();
if(myc) {
snprintf(statement,sizeof(statement),"delete from oauth_key where kid = '%s'",(const char*)kid);
int res = mysql_query(myc, statement);
if(res) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting oauth key information: %s\n",mysql_error(myc));
} else {
ret = 0;
}
}
return ret;
}
static int mysql_list_users(int is_st, u08bits *realm) {
int ret = 1;
@ -893,7 +1064,11 @@ static turn_dbdriver_t driver = {
&mysql_list_realm_options,
&mysql_auth_ping,
&mysql_get_ip_list,
&mysql_reread_realms
&mysql_reread_realms,
&mysql_set_oauth_key,
&mysql_get_oauth_key,
&mysql_del_oauth_key,
&mysql_list_oauth_keys
};
turn_dbdriver_t * get_mysql_dbdriver(void) {

View File

@ -174,6 +174,86 @@ static int pgsql_get_user_pwd(u08bits *usname, st_password_t pwd) {
}
return ret;
}
static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
int ret = 1;
char statement[TURN_LONG_STRING_SIZE];
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key from oauth_key where kid='%s'",(const char*)kid);
PGconn * pqc = get_pqdb_connection();
if(pqc) {
PGresult *res = PQexec(pqc, statement);
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res)!=1)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
} else {
STRCPY((char*)key->ikm_key,PQgetvalue(res,0,0));
key->timestamp = (u64bits)strtoll(PQgetvalue(res,0,1),NULL,10);
key->lifetime = (u32bits)strtol(PQgetvalue(res,0,2),NULL,10);
STRCPY((char*)key->hkdf_hash_func,PQgetvalue(res,0,3));
STRCPY((char*)key->as_rs_alg,PQgetvalue(res,0,4));
STRCPY((char*)key->as_rs_key,PQgetvalue(res,0,5));
STRCPY((char*)key->auth_alg,PQgetvalue(res,0,6));
STRCPY((char*)key->auth_key,PQgetvalue(res,0,7));
STRCPY((char*)key->kid,kid);
ret = 0;
}
if(res) {
PQclear(res);
}
}
return ret;
}
static int pgsql_list_oauth_keys(void) {
oauth_key_data_raw key_;
oauth_key_data_raw *key=&key_;
int ret = 1;
char statement[TURN_LONG_STRING_SIZE];
snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key,kid from oauth_key order by kid");
PGconn * pqc = get_pqdb_connection();
if(pqc) {
PGresult *res = PQexec(pqc, statement);
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
} else {
int i = 0;
for(i=0;i<PQntuples(res);i++) {
STRCPY((char*)key->ikm_key,PQgetvalue(res,i,0));
key->timestamp = (u64bits)strtoll(PQgetvalue(res,i,1),NULL,10);
key->lifetime = (u32bits)strtol(PQgetvalue(res,i,2),NULL,10);
STRCPY((char*)key->hkdf_hash_func,PQgetvalue(res,i,3));
STRCPY((char*)key->as_rs_alg,PQgetvalue(res,i,4));
STRCPY((char*)key->as_rs_key,PQgetvalue(res,i,5));
STRCPY((char*)key->auth_alg,PQgetvalue(res,i,6));
STRCPY((char*)key->auth_key,PQgetvalue(res,i,7));
STRCPY((char*)key->kid,PQgetvalue(res,i,8));
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);
ret = 0;
}
}
if(res) {
PQclear(res);
}
}
return ret;
}
static int pgsql_set_user_key(u08bits *usname, u08bits *realm, const char *key) {
int ret = 1;
@ -201,7 +281,38 @@ static int pgsql_set_user_key(u08bits *usname, u08bits *realm, const char *key)
}
return ret;
}
static int pgsql_set_oauth_key(oauth_key_data_raw *key) {
int ret = 1;
char statement[TURN_LONG_STRING_SIZE];
PGconn *pqc = get_pqdb_connection();
if(pqc) {
snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s','%s','%s')",
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);
PGresult *res = PQexec(pqc, statement);
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
if(res) {
PQclear(res);
}
snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, hkdf_hash_func = '%s', as_rs_alg='%s',as_rs_key='%s',auth_alg='%s',auth_key='%s' where kid='%s'",key->ikm_key,(unsigned 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,key->kid);
res = PQexec(pqc, statement);
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating oauth_key information: %s\n",PQerrorMessage(pqc));
} else {
ret = 0;
}
}
if(res) {
PQclear(res);
}
}
return ret;
}
static int pgsql_set_user_pwd(u08bits *usname, st_password_t pwd) {
int ret = 1;
char statement[TURN_LONG_STRING_SIZE];
@ -246,6 +357,27 @@ static int pgsql_del_user(u08bits *usname, int is_st, u08bits *realm) {
}
return ret;
}
static int pgsql_del_oauth_key(const u08bits *kid) {
int ret = 1;
char statement[TURN_LONG_STRING_SIZE];
PGconn *pqc = get_pqdb_connection();
if(pqc) {
snprintf(statement,sizeof(statement),"delete from oauth_key where kid = '%s'",(const char*)kid);
PGresult *res = PQexec(pqc, statement);
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting oauth_key information: %s\n",PQerrorMessage(pqc));
} else {
ret = 0;
}
if(res) {
PQclear(res);
}
}
return ret;
}
static int pgsql_list_users(int is_st, u08bits *realm) {
int ret = 1;
@ -655,7 +787,11 @@ static turn_dbdriver_t driver = {
&pgsql_list_realm_options,
&pgsql_auth_ping,
&pgsql_get_ip_list,
&pgsql_reread_realms
&pgsql_reread_realms,
&pgsql_set_oauth_key,
&pgsql_get_oauth_key,
&pgsql_del_oauth_key,
&pgsql_list_oauth_keys
};
turn_dbdriver_t * get_pgsql_dbdriver(void) {

View File

@ -492,6 +492,53 @@ static int redis_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) {
}
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 {
size_t i;
for (i = 0; i < (reply->elements)/2; ++i) {
char *kw = reply->element[i]->str;
if(kw) {
if(!strcmp(kw,"as_rs_alg")) {
STRCPY(key->as_rs_alg,reply->element[i+1]->str);
} else if(!strcmp(kw,"as_rs_key")) {
STRCPY(key->as_rs_key,reply->element[i+1]->str);
} else if(!strcmp(kw,"auth_key")) {
STRCPY(key->auth_key,reply->element[i+1]->str);
} else if(!strcmp(kw,"auth_alg")) {
STRCPY(key->auth_alg,reply->element[i+1]->str);
} else if(!strcmp(kw,"ikm_key")) {
STRCPY(key->ikm_key,reply->element[i+1]->str);
} else if(!strcmp(kw,"hkdf_hash_func")) {
STRCPY(key->hkdf_hash_func,reply->element[i+1]->str);
} else if(!strcmp(kw,"timestamp")) {
key->timestamp = (u64bits)strtoull(reply->element[i+1]->str,NULL,10);
} else if(!strcmp(kw,"lifetime")) {
key->lifetime = (u32bits)strtoul(reply->element[i+1]->str,NULL,10);
}
}
}
}
turnFreeRedisReply(reply);
ret = 0;
}
}
return ret;
}
static int redis_get_user_pwd(u08bits *usname, st_password_t pwd) {
int ret = 1;
@ -531,16 +578,30 @@ static int redis_set_user_key(u08bits *usname, u08bits *realm, const char *key)
}
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));
snprintf(statement,sizeof(statement),"set turn/user/%s/password %s",usname,pwd);
turnFreeRedisReply(redisCommand(rc, statement));
turnFreeRedisReply(redisCommand(rc, "save"));
ret = 0;
ret = 0;
}
return ret;
}
@ -565,6 +626,19 @@ static int redis_del_user(u08bits *usname, int is_st, u08bits *realm) {
}
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;
@ -656,6 +730,51 @@ static int redis_list_users(int is_st, u08bits *realm) {
}
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];
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;
@ -1134,7 +1253,11 @@ static turn_dbdriver_t driver = {
&redis_list_realm_options,
&redis_auth_ping,
&redis_get_ip_list,
&redis_reread_realms
&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) {

View File

@ -42,6 +42,22 @@ extern "C" {
////////////////////////////////////////////
struct _oauth_key_data_raw {
char kid[OAUTH_KID_SIZE+1];
char ikm_key[OAUTH_KEY_SIZE+1];
u64bits timestamp;
u32bits lifetime;
char hkdf_hash_func[OAUTH_HASH_FUNC_SIZE+1];
char as_rs_alg[OAUTH_ALG_SIZE+1];
char as_rs_key[OAUTH_KEY_SIZE+1];
char auth_alg[OAUTH_ALG_SIZE+1];
char auth_key[OAUTH_KEY_SIZE+1];
};
typedef struct _oauth_key_data_raw oauth_key_data_raw;
////////////////////////////////////////////
typedef struct _turn_dbdriver_t {
int (*get_auth_secrets)(secrets_list_t *sl, u08bits *realm);
int (*get_user_key)(u08bits *usname, u08bits *realm, hmackey_t key);
@ -61,6 +77,10 @@ typedef struct _turn_dbdriver_t {
void (*auth_ping)(void * rch);
int (*get_ip_list)(const char *kind, ip_range_list_t * list);
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);
int (*del_oauth_key)(const u08bits *kid);
int (*list_oauth_keys)(void);
} turn_dbdriver_t;
/////////// USER DB CHECK //////////////////
@ -71,20 +91,6 @@ turn_dbdriver_t * get_dbdriver(void);
////////////// OAUTH UTILS ////////////////
struct _oauth_key_data_raw {
char kid[OAUTH_KID_SIZE+1];
char ikm_key[OAUTH_KEY_SIZE+1];
u64bits timestamp;
u32bits lifetime;
char hkdf_hash_func[OAUTH_HASH_FUNC_SIZE+1];
char as_rs_alg[OAUTH_ALG_SIZE+1];
char as_rs_key[OAUTH_KEY_SIZE+1];
char auth_alg[OAUTH_ALG_SIZE+1];
char auth_key[OAUTH_KEY_SIZE+1];
};
typedef struct _oauth_key_data_raw oauth_key_data_raw;
void convert_oauth_key_data_raw(const oauth_key_data_raw *raw, oauth_key_data *oakd);
////////////////////////////////////////////

View File

@ -42,13 +42,13 @@ CREATE TABLE turn_realm_option (
CREATE TABLE oauth_key (
kid varchar(128),
ikm_key varchar(256),
timestamp bigint,
lifetime integer,
hkdf_hash_func varchar(64),
as_rs_alg varchar(64),
as_rs_key varchar(256),
auth_alg varchar(64),
auth_key varchar(256),
ikm_key varchar(256) default '',
timestamp bigint default 0,
lifetime integer default 0,
hkdf_hash_func varchar(64) default '',
as_rs_alg varchar(64) default '',
as_rs_key varchar(256) default '',
auth_alg varchar(64) default '',
auth_key varchar(256) default '',
primary key (kid)
);