working on oauth
This commit is contained in:
parent
84f12a9ed4
commit
18180cafdc
@ -1631,4 +1631,218 @@ int stun_attr_add_padding_str(u08bits *buf, size_t *len, u16bits padding_len)
|
||||
return stun_attr_add_str(buf, len, STUN_ATTRIBUTE_PADDING, avalue, padding_len);
|
||||
}
|
||||
|
||||
/* OAUTH */
|
||||
|
||||
static void remove_spaces(char *s)
|
||||
{
|
||||
char *sfns = s;
|
||||
while(*sfns) {
|
||||
if(*sfns != ' ')
|
||||
break;
|
||||
++sfns;
|
||||
}
|
||||
if(*sfns) {
|
||||
if(sfns != s) {
|
||||
while(*sfns && (*sfns != ' ')) {
|
||||
*s = *sfns;
|
||||
++s;
|
||||
++sfns;
|
||||
};
|
||||
*s = 0;
|
||||
} else {
|
||||
while(*s) {
|
||||
if(*s == ' ') {
|
||||
*s = 0;
|
||||
break;
|
||||
}
|
||||
++s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void normalize_algorithm(char *s)
|
||||
{
|
||||
char c = *s;
|
||||
while(c) {
|
||||
if(c=='_') c='-';
|
||||
else if((c>='a')&&(c<='z')) {
|
||||
c = c - 'a' + 'A';
|
||||
}
|
||||
++s;
|
||||
c = *s;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t calculate_enc_key_length(ENC_ALG a)
|
||||
{
|
||||
switch(a) {
|
||||
case AES_128_CBC:
|
||||
return 16;
|
||||
case AES_256_CBC:
|
||||
return 32;
|
||||
default:
|
||||
;
|
||||
};
|
||||
|
||||
return 32;
|
||||
}
|
||||
|
||||
static size_t calculate_auth_key_length(AUTH_ALG a)
|
||||
{
|
||||
switch(a) {
|
||||
case AUTH_ALG_HMAC_SHA_1:
|
||||
return 20;
|
||||
case AUTH_ALG_HMAC_SHA_256_128:
|
||||
return 32;
|
||||
case AUTH_ALG_HMAC_SHA_256:
|
||||
return 32;
|
||||
default:
|
||||
;
|
||||
};
|
||||
|
||||
return 32;
|
||||
}
|
||||
|
||||
static int calculate_key(char *key, size_t key_size, char *new_key, size_t new_key_size, SHATYPE shatype,
|
||||
char *err_msg, size_t err_msg_size)
|
||||
{
|
||||
//Extract:
|
||||
u08bits prk[128];
|
||||
unsigned int prk_len = 0;
|
||||
stun_calculate_hmac((const u08bits *)key, key_size, (const u08bits *)"", 0, prk, &prk_len, shatype);
|
||||
|
||||
//Expand:
|
||||
u08bits buf[128];
|
||||
buf[0]=1;
|
||||
u08bits hmac[128];
|
||||
unsigned int hmac_len = 0;
|
||||
stun_calculate_hmac((const u08bits *)buf, 1, prk, prk_len, hmac, &hmac_len, shatype);
|
||||
ns_bcopy(hmac,new_key,hmac_len);
|
||||
|
||||
//Check
|
||||
if(new_key_size>hmac_len) {
|
||||
ns_bcopy(hmac,buf,hmac_len);
|
||||
buf[hmac_len]=2;
|
||||
u08bits hmac1[128];
|
||||
unsigned int hmac1_len = 0;
|
||||
stun_calculate_hmac((const u08bits *)buf, hmac_len+1, prk, prk_len, hmac1, &hmac1_len, shatype);
|
||||
ns_bcopy(hmac1,new_key+hmac_len,hmac1_len);
|
||||
if(new_key_size > (hmac_len + hmac1_len)) {
|
||||
if(err_msg) {
|
||||
snprintf(err_msg,err_msg_size,"Wrong HKDF procedure (key sizes): output.sz=%lu, hmac(1)=%lu, hmac(2)=%lu",(unsigned long)new_key_size,(unsigned long)hmac_len,(unsigned long)hmac1_len);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, size_t err_msg_size)
|
||||
{
|
||||
if(oakd && key) {
|
||||
|
||||
if(!(oakd->ikm_key_size)) {
|
||||
if(!(oakd->as_rs_key_size)) {
|
||||
if(err_msg) {
|
||||
snprintf(err_msg,err_msg_size,"AS-RS key is not defined");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if(!(oakd->auth_key_size)) {
|
||||
if(err_msg) {
|
||||
snprintf(err_msg,err_msg_size,"AUTH key is not defined");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
remove_spaces(oakd->kid);
|
||||
|
||||
remove_spaces(oakd->hkdf_hash_func);
|
||||
remove_spaces(oakd->as_rs_alg);
|
||||
remove_spaces(oakd->auth_alg);
|
||||
|
||||
normalize_algorithm(oakd->hkdf_hash_func);
|
||||
normalize_algorithm(oakd->as_rs_alg);
|
||||
normalize_algorithm(oakd->auth_alg);
|
||||
|
||||
if(!(oakd->kid[0])) {
|
||||
if(err_msg) {
|
||||
snprintf(err_msg,err_msg_size,"KID is not defined");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
ns_bzero(key,sizeof(oauth_key));
|
||||
|
||||
STRCPY(key->kid,oakd->kid);
|
||||
|
||||
ns_bcopy(oakd->as_rs_key,key->as_rs_key,sizeof(key->as_rs_key));
|
||||
key->as_rs_key_size = oakd->as_rs_key_size;
|
||||
ns_bcopy(oakd->auth_key,key->auth_key,sizeof(key->auth_key));
|
||||
key->auth_key_size = oakd->auth_key_size;
|
||||
ns_bcopy(oakd->ikm_key,key->ikm_key,sizeof(key->ikm_key));
|
||||
key->ikm_key_size = oakd->ikm_key_size;
|
||||
|
||||
key->timestamp = oakd->timestamp;
|
||||
key->lifetime = oakd->lifetime;
|
||||
|
||||
key->hkdf_hash_func = SHATYPE_SHA256;
|
||||
if(!strcmp(oakd->hkdf_hash_func,"SHA1") || !strcmp(oakd->hkdf_hash_func,"SHA-1")) {
|
||||
key->hkdf_hash_func = SHATYPE_SHA1;
|
||||
} else if(!strcmp(oakd->hkdf_hash_func,"SHA256") || !strcmp(oakd->hkdf_hash_func,"SHA-256")) {
|
||||
key->hkdf_hash_func = SHATYPE_SHA256;
|
||||
} else if(oakd->hkdf_hash_func[0]) {
|
||||
if(err_msg) {
|
||||
snprintf(err_msg,err_msg_size,"Wrong HKDF hash function algorithm: %s",oakd->hkdf_hash_func);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
key->as_rs_alg = ENC_ALG_DEFAULT;
|
||||
if(!strcmp(oakd->as_rs_alg,"AES-128-CBC")) {
|
||||
key->as_rs_alg = AES_128_CBC;
|
||||
} else if(!strcmp(oakd->as_rs_alg,"AES-256-CBC")) {
|
||||
key->as_rs_alg = AES_256_CBC;
|
||||
} else if(oakd->as_rs_alg[0]) {
|
||||
if(err_msg) {
|
||||
snprintf(err_msg,err_msg_size,"Wrong oAuth token encryption algorithm: %s",oakd->as_rs_alg);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
key->auth_alg = AUTH_ALG_DEFAULT;
|
||||
if(!strcmp(oakd->auth_alg,"HMAC-SHA-1") || !strcmp(oakd->auth_alg,"HMAC-SHA1")) {
|
||||
key->auth_alg = AUTH_ALG_HMAC_SHA_1;
|
||||
} else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256")) {
|
||||
key->auth_alg = AUTH_ALG_HMAC_SHA_256;
|
||||
} else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256-128")) {
|
||||
key->auth_alg = AUTH_ALG_HMAC_SHA_256_128;
|
||||
} else if(oakd->auth_alg[0]) {
|
||||
if(err_msg) {
|
||||
snprintf(err_msg,err_msg_size,"Wrong oAuth token hash algorithm: %s",oakd->auth_alg);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(!(key->auth_key_size)) {
|
||||
key->auth_key_size = calculate_auth_key_length(key->auth_alg);
|
||||
if(calculate_key(key->ikm_key,key->ikm_key_size,key->auth_key,key->auth_key_size,key->hkdf_hash_func,err_msg,err_msg_size)<0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(!(key->as_rs_key_size)) {
|
||||
key->as_rs_key_size = calculate_enc_key_length(key->as_rs_alg);
|
||||
if(calculate_key(key->ikm_key,key->ikm_key_size,key->as_rs_key,key->as_rs_key_size,key->hkdf_hash_func,err_msg,err_msg_size)<0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
@ -209,6 +209,9 @@ int stun_attr_add_padding_str(u08bits *buf, size_t *len, u16bits padding_len);
|
||||
/* HTTP */
|
||||
int is_http_get(const char *s, size_t blen);
|
||||
|
||||
/* OAUTH */
|
||||
int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, size_t err_msg_size);
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -38,6 +38,12 @@
|
||||
#define STUN_ATTRIBUTE_ORIGIN (0x802F)
|
||||
/* <<== Origin */
|
||||
|
||||
/* Bandwidth */
|
||||
|
||||
#define STUN_ATTRIBUTE_NEW_BANDWIDTH (0x8000 + STUN_ATTRIBUTE_BANDWIDTH)
|
||||
|
||||
/* <<== Bandwidth */
|
||||
|
||||
/* SHA AGILITY ==>> */
|
||||
|
||||
#define SHA1SIZEBYTES (20)
|
||||
@ -46,7 +52,9 @@
|
||||
#define MAXSHASIZE (128)
|
||||
|
||||
enum _SHATYPE {
|
||||
SHATYPE_SHA1 = 0,
|
||||
SHATYPE_ERROR = -1,
|
||||
SHATYPE_DEFAULT=0,
|
||||
SHATYPE_SHA1=SHATYPE_DEFAULT,
|
||||
SHATYPE_SHA256
|
||||
};
|
||||
|
||||
@ -58,10 +66,75 @@ typedef enum _SHATYPE SHATYPE;
|
||||
|
||||
/* <<== SHA AGILITY */
|
||||
|
||||
/* Bandwidth */
|
||||
/* OAUTH TOKEN ENC ALG ==> */
|
||||
|
||||
#define STUN_ATTRIBUTE_NEW_BANDWIDTH (0x8000 + STUN_ATTRIBUTE_BANDWIDTH)
|
||||
enum _ENC_ALG {
|
||||
ENC_ALG_ERROR=-1,
|
||||
ENC_ALG_DEFAULT=0,
|
||||
AES_128_CBC=ENC_ALG_DEFAULT,
|
||||
AES_256_CBC,
|
||||
ENG_ALG_NUM
|
||||
};
|
||||
|
||||
/* <<== Bandwidth */
|
||||
typedef enum _ENC_ALG ENC_ALG;
|
||||
|
||||
/* <<== OAUTH TOKEN ENC ALG */
|
||||
|
||||
/* OAUTH TOKEN AUTH ALG ==> */
|
||||
|
||||
enum _AUTH_ALG {
|
||||
AUTH_ALG_ERROR = -1,
|
||||
AUTH_ALG_DEFAULT = 0,
|
||||
AUTH_ALG_HMAC_SHA_256_128 = AUTH_ALG_DEFAULT,
|
||||
AUTH_ALG_HMAC_SHA_1,
|
||||
AUTH_ALG_HMAC_SHA_256
|
||||
};
|
||||
|
||||
typedef enum _AUTH_ALG AUTH_ALG;
|
||||
|
||||
/* <<== OAUTH TOKEN AUTH ALG */
|
||||
|
||||
/**
|
||||
* oAuth struct
|
||||
*/
|
||||
|
||||
#define OAUTH_KID_SIZE (128)
|
||||
#define OAUTH_HASH_FUNC_SIZE (64)
|
||||
#define OAUTH_ALG_SIZE (64)
|
||||
#define OAUTH_KEY_SIZE (256)
|
||||
|
||||
struct _oauth_key_data {
|
||||
char kid[OAUTH_KID_SIZE+1];
|
||||
char ikm_key[OAUTH_KEY_SIZE+1];
|
||||
size_t ikm_key_size;
|
||||
u64bits timestamp;
|
||||
turn_time_t 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];
|
||||
size_t as_rs_key_size;
|
||||
char auth_alg[OAUTH_ALG_SIZE+1];
|
||||
char auth_key[OAUTH_KEY_SIZE+1];
|
||||
size_t auth_key_size;
|
||||
};
|
||||
|
||||
typedef struct _oauth_key_data oauth_key_data;
|
||||
|
||||
struct _oauth_key {
|
||||
char kid[OAUTH_KID_SIZE+1];
|
||||
char ikm_key[OAUTH_KEY_SIZE+1];
|
||||
size_t ikm_key_size;
|
||||
u64bits timestamp;
|
||||
turn_time_t lifetime;
|
||||
SHATYPE hkdf_hash_func;
|
||||
ENC_ALG as_rs_alg;
|
||||
char as_rs_key[OAUTH_KEY_SIZE+1];
|
||||
size_t as_rs_key_size;
|
||||
AUTH_ALG auth_alg;
|
||||
char auth_key[OAUTH_KEY_SIZE+1];
|
||||
size_t auth_key_size;
|
||||
};
|
||||
|
||||
typedef struct _oauth_key oauth_key;
|
||||
|
||||
#endif //__LIB_TURN_MSG_DEFS_NEW__
|
||||
|
||||
@ -39,3 +39,16 @@ CREATE TABLE turn_realm_option (
|
||||
value varchar(128),
|
||||
primary key (realm,opt)
|
||||
);
|
||||
|
||||
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),
|
||||
primary key (kid)
|
||||
);
|
||||
|
||||
@ -116,7 +116,7 @@ save
|
||||
IV. Redis database configuration parameters
|
||||
|
||||
TURN Server connects to the Redis and keeps the same connection during the
|
||||
TURN server lifetime. That means that we have to take care about that
|
||||
TURN Server process lifetime. That means that we have to take care about that
|
||||
connection - it must not expire.
|
||||
|
||||
You have to take care about Redis connection parameters, the timeout and the
|
||||
|
||||
Loading…
Reference in New Issue
Block a user