mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	res_rtp_asterisk.c: Check DTLS packets against ICE candidate list
When ICE is in use, we can prevent a possible DOS attack by allowing DTLS protocol messages (client hello, etc) only from sources that are in the active remote candidates list. Resolves: GHSA-hxj9-xwr8-w8pq
This commit is contained in:
		
				
					committed by
					
						 Mike Bradeen
						Mike Bradeen
					
				
			
			
				
	
			
			
			
						parent
						
							8f015af774
						
					
				
				
					commit
					986b55eeaa
				
			| @@ -3179,6 +3179,61 @@ static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t s | ||||
|  | ||||
| 		ast_debug_dtls(3, "(%p) DTLS - __rtp_recvfrom rtp=%p - Got SSL packet '%d'\n", instance, rtp, *in); | ||||
|  | ||||
| 		/* | ||||
| 		 * If ICE is in use, we can prevent a possible DOS attack | ||||
| 		 * by allowing DTLS protocol messages (client hello, etc) | ||||
| 		 * only from sources that are in the active remote | ||||
| 		 * candidates list. | ||||
| 		 */ | ||||
|  | ||||
| 		if (rtp->ice) { | ||||
| 			int pass_src_check = 0; | ||||
| 			struct ao2_iterator i; | ||||
| 			struct ast_rtp_engine_ice_candidate *candidate; | ||||
| 			int cand_cnt = 0; | ||||
|  | ||||
| 			/* | ||||
| 			 * You'd think that this check would cause a "deadlock" | ||||
| 			 * because ast_rtp_ice_start_media calls dtls_perform_handshake | ||||
| 			 * before it sets ice_media_started = 1 so how can we do a | ||||
| 			 * handshake if we're dropping packets before we send them | ||||
| 			 * to openssl.  Fortunately, dtls_perform_handshake just sets | ||||
| 			 * up openssl to do the handshake and doesn't actually perform it | ||||
| 			 * itself and the locking prevents __rtp_recvfrom from | ||||
| 			 * running before the ice_media_started flag is set.  So only | ||||
| 			 * unexpected DTLS packets can get dropped here. | ||||
| 			 */ | ||||
| 			if (!rtp->ice_media_started) { | ||||
| 				ast_log(LOG_WARNING, "%s: DTLS packet from %s dropped. ICE not completed yet.\n", | ||||
| 					ast_rtp_instance_get_channel_id(instance), | ||||
| 					ast_sockaddr_stringify(sa)); | ||||
| 				return 0; | ||||
| 			} | ||||
|  | ||||
| 			/* | ||||
| 			 * If we got this far, then ice_active_remote_candidates | ||||
| 			 * can't be NULL. | ||||
| 			 */ | ||||
| 			i = ao2_iterator_init(rtp->ice_active_remote_candidates, 0); | ||||
| 			while ((candidate = ao2_iterator_next(&i)) && (cand_cnt < PJ_ICE_MAX_CAND)) { | ||||
| 				res = ast_sockaddr_cmp_addr(&candidate->address, sa); | ||||
| 				ao2_ref(candidate, -1); | ||||
| 				if (res == 0) { | ||||
| 					pass_src_check = 1; | ||||
| 					break; | ||||
| 				} | ||||
| 				cand_cnt++; | ||||
| 			} | ||||
| 			ao2_iterator_destroy(&i); | ||||
|  | ||||
| 			if (!pass_src_check) { | ||||
| 				ast_log(LOG_WARNING, "%s: DTLS packet from %s dropped. Source not in ICE active candidate list.\n", | ||||
| 					ast_rtp_instance_get_channel_id(instance), | ||||
| 					ast_sockaddr_stringify(sa)); | ||||
| 				return 0; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		/* | ||||
| 		 * A race condition is prevented between dtls_perform_handshake() | ||||
| 		 * and this function because both functions have to get the | ||||
|   | ||||
		Reference in New Issue
	
	Block a user