Browse Source

token timeout implemented

mom040267 11 years ago
parent
commit
cbb37c645f

+ 2 - 4
ChangeLog

@@ -1,9 +1,7 @@
 08/22/2014 Oleg Moskalenko <[email protected]>
 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.

+ 2 - 2
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);

+ 24 - 1
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;
 					}
 				}

+ 2 - 1
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);

+ 2 - 2
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) {

+ 4 - 5
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*) &lt,
-					4);
+			uint32_t lt = htonl(UCLIENT_SESSION_LIFETIME);
+			stun_attr_add(&message, STUN_ATTRIBUTE_LIFETIME, (const char*) &lt, 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));

+ 1 - 0
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;

+ 3 - 0
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,

+ 11 - 2
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));
 			}
 

+ 1 - 1
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);

+ 1 - 0
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;