diff --git a/ChangeLog b/ChangeLog index 9e432aef..4fdbf85d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,7 @@ 08/22/2014 Oleg Moskalenko Version 4.2.1.1 'Monza': - - oAuth security implementation: - TODO: - - token timeout; - - TLS renegotiation DoS attack prevention implemented; + - oAuth security experimental implementation; + - The "TLS renegotiation" DoS attack prevention implemented; - FQDN as relay-ip and listener-ip parameters (issue 6) (patch provided by IƱaki Baz Castillo); - redis user key operation fixed. diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 829fff98..a73bd589 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -388,7 +388,7 @@ static void auth_server_receive_message(struct bufferevent *bev, void *ptr) } } else { hmackey_t key; - if(get_user_key(am.in_oauth,&(am.out_oauth),am.username,am.realm,key,am.in_buffer.nbh)<0) { + if(get_user_key(am.in_oauth,&(am.out_oauth),&(am.max_session_time),am.username,am.realm,key,am.in_buffer.nbh)<0) { am.success = 0; } else { ns_bcopy(key,am.key,sizeof(hmackey_t)); @@ -770,7 +770,7 @@ static int handle_relay_message(relay_server_handle rs, struct message_to_relay static void handle_relay_auth_message(struct relay_server *rs, struct auth_message *am) { - am->resume_func(am->success, am->out_oauth, am->key, am->pwd, + am->resume_func(am->success, am->out_oauth, am->max_session_time, am->key, am->pwd, &(rs->server), am->ctxkey, &(am->in_buffer)); if (am->in_buffer.nbh) { ioa_network_buffer_delete(rs->ioa_eng, am->in_buffer.nbh); diff --git a/src/apps/relay/userdb.c b/src/apps/relay/userdb.c index 3dd9fe6f..48fefc05 100644 --- a/src/apps/relay/userdb.c +++ b/src/apps/relay/userdb.c @@ -398,10 +398,13 @@ static char *get_real_username(char *usname) /* * Password retrieval */ -int get_user_key(int in_oauth, int *out_oauth, u08bits *usname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh) +int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *usname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh) { int ret = -1; + if(max_session_time) + *max_session_time = 0; + if(in_oauth && out_oauth && usname && usname[0] && realm && realm[0]) { stun_attr_ref sar = stun_attr_get_first_by_type_str(ioa_network_buffer_data(nbh), @@ -495,7 +498,27 @@ int get_user_key(int in_oauth, int *out_oauth, u08bits *usname, u08bits *realm, dot.enc_block.mac_key, pwdtmp, turn_params.shatype,NULL)>0) { + + turn_time_t lifetime = (turn_time_t)(dot.enc_block.lifetime); + if(lifetime) { + turn_time_t ts = (turn_time_t)(dot.enc_block.timestamp >> 16); + turn_time_t to = ts + lifetime + OAUTH_TIME_DELTA; + turn_time_t ct = turn_time(); + if(!turn_time_before(ct,to)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "oAuth token is too old\n"); + return -1; + } + if(max_session_time) { + *max_session_time = to - ct; + if(*max_session_time > OAUTH_TIME_DELTA) + *max_session_time -= OAUTH_TIME_DELTA; + if(*max_session_time < OAUTH_TIME_DELTA) + *max_session_time = OAUTH_TIME_DELTA; + } + } + ns_bcopy(dot.enc_block.mac_key,key,dot.enc_block.key_length); + ret = 0; } } diff --git a/src/apps/relay/userdb.h b/src/apps/relay/userdb.h index 4fd6c7c5..036ea4f0 100644 --- a/src/apps/relay/userdb.h +++ b/src/apps/relay/userdb.h @@ -88,6 +88,7 @@ struct auth_message { turn_credential_type ct; int in_oauth; int out_oauth; + int max_session_time; u08bits username[STUN_MAX_USERNAME_SIZE + 1]; u08bits realm[STUN_MAX_REALM_SIZE + 1]; hmackey_t key; @@ -189,7 +190,7 @@ void add_to_secrets_list(secrets_list_t *sl, const char* elem); /////////// USER DB CHECK ////////////////// -int get_user_key(int in_oauth, int *out_oauth, u08bits *uname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh); +int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, u08bits *uname, u08bits *realm, hmackey_t key, ioa_network_buffer_handle nbh); int get_user_pwd(u08bits *uname, st_password_t pwd); u08bits *start_user_check(turnserver_id id, turn_credential_type ct, int in_oauth, int *out_oauth, u08bits *uname, u08bits *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, u64bits ctxkey, int *postpone_reply); int check_new_allocation_quota(u08bits *username, u08bits *realm); diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 73bd096b..b2372372 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -410,10 +410,10 @@ int main(int argc, char **argv) if(oauth) { - otoken_array[0].enc_block.lifetime = 0; + otoken_array[0].enc_block.lifetime = OAUTH_SESSION_LIFETIME; otoken_array[0].enc_block.timestamp = 0; - otoken_array[1].enc_block.lifetime = 0; + otoken_array[1].enc_block.lifetime = OAUTH_SESSION_LIFETIME; otoken_array[1].enc_block.timestamp = 0; switch(shatype) { diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index 003f51aa..2012ecdb 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -360,9 +360,9 @@ static int clnet_allocate(int verbose, } if(!dos) - stun_set_allocate_request(&message, 800, af4, af6, relay_transport, mobility); + stun_set_allocate_request(&message, UCLIENT_SESSION_LIFETIME, af4, af6, relay_transport, mobility); else - stun_set_allocate_request(&message, 300, af4, af6, relay_transport, mobility); + stun_set_allocate_request(&message, UCLIENT_SESSION_LIFETIME/3, af4, af6, relay_transport, mobility); if(bps) stun_attr_add_bandwidth_str(message.buf, (size_t*)(&(message.len)), bps); @@ -633,9 +633,8 @@ static int clnet_allocate(int verbose, stun_buffer message; stun_init_request(STUN_METHOD_REFRESH, &message); - uint32_t lt = htonl(600); - stun_attr_add(&message, STUN_ATTRIBUTE_LIFETIME, (const char*) <, - 4); + uint32_t lt = htonl(UCLIENT_SESSION_LIFETIME); + stun_attr_add(&message, STUN_ATTRIBUTE_LIFETIME, (const char*) <, 4); if(clnet_info->s_mobile_id[0]) { stun_attr_add(&message, STUN_ATTRIBUTE_MOBILITY_TICKET, (const char*)clnet_info->s_mobile_id, strlen(clnet_info->s_mobile_id)); diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index 4b705863..865f766d 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -1445,6 +1445,7 @@ int add_integrity(app_ur_conn_info *clnet_info, stun_buffer *message) encoded_oauth_token etoken; u08bits nonce[12]; RAND_bytes((unsigned char*)nonce,12); + otoken_array[cok].enc_block.timestamp = ((uint64_t)turn_time()) << 16; if(encode_oauth_token(clnet_info->server_name, &etoken, &(okey_array[cok]), &(otoken_array[cok]), nonce)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO," Cannot encode token\n"); return -1; diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index 83e3a0be..734de669 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -90,6 +90,9 @@ extern int oauth; extern oauth_key okey_array[2]; extern oauth_token otoken_array[2]; +#define UCLIENT_SESSION_LIFETIME (777) +#define OAUTH_SESSION_LIFETIME (555) + #define is_TCP_relay() (relay_transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) void start_mclient(const char *remote_address, int port, diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index f1e92621..9574c683 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1159,6 +1159,9 @@ static int handle_turn_allocate(turn_turnserver *server, } lifetime = stun_adjust_allocate_lifetime(lifetime); + if(ss->max_session_time_auth && (ss->max_session_time_auth < lifetime)) { + lifetime = ss->max_session_time_auth; + } u64bits out_reservation_token = 0; if(inc_quota(ss, username)<0) { @@ -1559,6 +1562,7 @@ static int handle_turn_refresh(turn_turnserver *server, ns_bcopy(orig_ss->origin,ss->origin,sizeof(ss->origin)); ss->origin_set = orig_ss->origin_set; ns_bcopy(orig_ss->pwd,ss->pwd,sizeof(ss->pwd)); + ss->max_session_time_auth = orig_ss->max_session_time_auth; if(check_stun_auth(server, ss, tid, resp_constructed, err_code, reason, in_buffer, nbh, STUN_METHOD_REFRESH, &message_integrity, &postpone_reply, can_resume)<0) { @@ -1577,8 +1581,12 @@ static int handle_turn_refresh(turn_turnserver *server, if (to_delete) lifetime = 0; - else + else { lifetime = stun_adjust_allocate_lifetime(lifetime); + if(ss->max_session_time_auth && (ss->max_session_time_auth < lifetime)) { + lifetime = ss->max_session_time_auth; + } + } if (af4c && refresh_relay_connection(server, orig_ss, lifetime, 0, 0, 0, err_code, AF_INET) < 0) { @@ -3110,7 +3118,7 @@ static int create_challenge_response(ts_ur_super_session *ss, stun_tid *tid, int #define min(a,b) ((a)<=(b) ? (a) : (b)) #endif -static void resume_processing_after_username_check(int success, int oauth, hmackey_t hmackey, st_password_t pwd, turn_turnserver *server, u64bits ctxkey, ioa_net_data *in_buffer) +static void resume_processing_after_username_check(int success, int oauth, int max_session_time, hmackey_t hmackey, st_password_t pwd, turn_turnserver *server, u64bits ctxkey, ioa_net_data *in_buffer) { if(server && in_buffer && in_buffer->nbh) { @@ -3123,6 +3131,7 @@ static void resume_processing_after_username_check(int success, int oauth, hmac ns_bcopy(hmackey,ss->hmackey,sizeof(hmackey_t)); ss->hmackey_set = 1; ss->oauth = oauth; + ss->max_session_time_auth = (turn_time_t)max_session_time; ns_bcopy(pwd,ss->pwd,sizeof(st_password_t)); } diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index fdc2e133..91ac0136 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -90,7 +90,7 @@ typedef enum { struct _turn_turnserver; typedef struct _turn_turnserver turn_turnserver; -typedef void (*get_username_resume_cb)(int success, int oauth, hmackey_t hmackey, st_password_t pwd, turn_turnserver *server, u64bits ctxkey, ioa_net_data *in_buffer); +typedef void (*get_username_resume_cb)(int success, int oauth, int max_session_time, hmackey_t hmackey, st_password_t pwd, turn_turnserver *server, u64bits ctxkey, ioa_net_data *in_buffer); typedef u08bits *(*get_user_key_cb)(turnserver_id id, turn_credential_type ct, int in_oauth, int *out_oauth, u08bits *uname, u08bits *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, u64bits ctxkey, int *postpone_reply); typedef int (*check_new_allocation_quota_cb)(u08bits *username, u08bits *realm); typedef void (*release_allocation_quota_cb)(u08bits *username, u08bits *realm); diff --git a/src/server/ns_turn_session.h b/src/server/ns_turn_session.h index f8510794..c1a2c70e 100644 --- a/src/server/ns_turn_session.h +++ b/src/server/ns_turn_session.h @@ -84,6 +84,7 @@ struct _ts_ur_super_session { st_password_t pwd; int quota_used; int oauth; + turn_time_t max_session_time_auth; /* Realm */ realm_options_t realm_options; int origin_set;