mirror of
				https://git.kernel.org/pub/scm/network/wireless/iwd.git
				synced 2025-10-31 21:27:30 +01:00 
			
		
		
		
	ttls: replace old AVP processing with new
This commit is contained in:
		
							parent
							
								
									5d1d1ad893
								
							
						
					
					
						commit
						4d8791dd3a
					
				
							
								
								
									
										164
									
								
								src/eap-ttls.c
									
									
									
									
									
								
							
							
						
						
									
										164
									
								
								src/eap-ttls.c
									
									
									
									
									
								
							| @ -142,8 +142,7 @@ struct eap_ttls_state { | ||||
| 	size_t rx_pkt_received, rx_pkt_len; | ||||
| 	uint8_t *tx_pkt_buf; | ||||
| 	size_t tx_pkt_len, tx_pkt_capacity, tx_pkt_offset; | ||||
| 	uint8_t *avp_buf; | ||||
| 	size_t avp_received, avp_capacity; | ||||
| 	struct databuf *avp_buf; | ||||
| 	bool completed; | ||||
| 	struct eap_state *phase2_eap; | ||||
| 	uint8_t negotiated_version; | ||||
| @ -166,10 +165,8 @@ static void __eap_ttls_reset_state(struct eap_ttls_state *ttls) | ||||
| 	ttls->tx_pkt_len = 0; | ||||
| 	ttls->tx_pkt_offset = 0; | ||||
| 
 | ||||
| 	l_free(ttls->avp_buf); | ||||
| 	databuf_free(ttls->avp_buf); | ||||
| 	ttls->avp_buf = NULL; | ||||
| 	ttls->avp_received = 0; | ||||
| 	ttls->avp_capacity = 0; | ||||
| 
 | ||||
| 	if (ttls->tls) { | ||||
| 		l_tls_free(ttls->tls); | ||||
| @ -278,6 +275,13 @@ static bool eap_ttls_phase2_eap_handle_avp(struct eap_state *eap, | ||||
| 						const uint8_t *data, | ||||
| 						size_t len) | ||||
| { | ||||
| 	struct eap_ttls_state *ttls = eap_get_data(eap); | ||||
| 
 | ||||
| 	if (type != RADIUS_ATTR_EAP_MESSAGE) | ||||
| 		return false; | ||||
| 
 | ||||
| 	eap_rx_packet(ttls->phase2->state, data, len); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| @ -337,149 +341,16 @@ static void eap_ttls_tx_cb(const uint8_t *data, size_t len, void *user_data) | ||||
| 	memcpy(eap_ttls_tx_buf_reserve(ttls, len), data, len); | ||||
| } | ||||
| 
 | ||||
| struct eap_ttls_avp { | ||||
| 	__be32 avp_code; | ||||
| 	uint8_t avp_flags; | ||||
| 	uint8_t avp_len[3]; | ||||
| 	uint8_t data[0]; | ||||
| } __attribute__ ((packed)); | ||||
| 
 | ||||
| #define EAP_TTLS_AVP_FLAG_V	(1 << 7) | ||||
| #define EAP_TTLS_AVP_FLAG_M	(1 << 6) | ||||
| 
 | ||||
| #define RADIUS_AVP_EAP_MESSAGE	79 | ||||
| 
 | ||||
| static bool eap_ttls_handle_avp(struct eap_state *eap, struct eap_ttls_avp *avp) | ||||
| { | ||||
| 	struct eap_ttls_state *ttls = eap_get_data(eap); | ||||
| 	uint8_t *data; | ||||
| 	uint64_t code; | ||||
| 	size_t data_len; | ||||
| 
 | ||||
| 	data = avp->data; | ||||
| 	data_len = ((avp->avp_len[0] << 16) | | ||||
| 		(avp->avp_len[1] << 8) | | ||||
| 		(avp->avp_len[2] << 0)) - sizeof(struct eap_ttls_avp); | ||||
| 
 | ||||
| 	code = l_get_be32(&avp->avp_code); | ||||
| 
 | ||||
| 	if (avp->avp_flags & EAP_TTLS_AVP_FLAG_V) { | ||||
| 		if (data_len < 4) | ||||
| 			goto avp_err; | ||||
| 
 | ||||
| 		code |= (uint64_t) l_get_be32(data) << 32; | ||||
| 		data += 4; | ||||
| 		data_len -= 4; | ||||
| 	} | ||||
| 
 | ||||
| 	switch (code) { | ||||
| 	/* EAP-Message attribute, actually defined in RFC2869 5.13 */ | ||||
| 	case RADIUS_AVP_EAP_MESSAGE: | ||||
| 		if (!ttls->phase2_eap) | ||||
| 			goto avp_err; | ||||
| 
 | ||||
| 		/* TODO: split if necessary */ | ||||
| 		eap_rx_packet(ttls->phase2_eap, data, data_len); | ||||
| 
 | ||||
| 		break; | ||||
| 
 | ||||
| 	default: | ||||
| 		if (avp->avp_flags & EAP_TTLS_AVP_FLAG_M) | ||||
| 			goto avp_err; | ||||
| 
 | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	return true; | ||||
| 
 | ||||
| avp_err: | ||||
| 	l_tls_close(ttls->tls); | ||||
| 
 | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| static size_t avp_min_len(const uint8_t *buf, size_t len) | ||||
| { | ||||
| 	struct eap_ttls_avp *avp; | ||||
| 
 | ||||
| 	if (len < sizeof(struct eap_ttls_avp)) | ||||
| 		return sizeof(struct eap_ttls_avp); | ||||
| 
 | ||||
| 	avp = (struct eap_ttls_avp *) buf; | ||||
| 
 | ||||
| 	return (((avp->avp_len[0] << 16) | | ||||
| 		(avp->avp_len[1] << 8) | | ||||
| 		(avp->avp_len[2] << 0)) + 3) & ~3; | ||||
| } | ||||
| 
 | ||||
| static void eap_ttls_data_cb(const uint8_t *data, size_t len, void *user_data) | ||||
| static void eap_ttls_data_cb(const uint8_t *data, size_t data_len, | ||||
| 								void *user_data) | ||||
| { | ||||
| 	struct eap_state *eap = user_data; | ||||
| 	struct eap_ttls_state *ttls = eap_get_data(eap); | ||||
| 	struct eap_ttls_avp *avp; | ||||
| 	size_t avp_len, chunk_len; | ||||
| 
 | ||||
| 	/* Continue assembling the AVP that we have buffered */ | ||||
| 	while (ttls->avp_received) { | ||||
| 		avp_len = avp_min_len(ttls->avp_buf, ttls->avp_received); | ||||
| 		chunk_len = avp_len - ttls->avp_received; | ||||
| 	if (!ttls->avp_buf) | ||||
| 		ttls->avp_buf = databuf_new(data_len); | ||||
| 
 | ||||
| 		if (chunk_len > len) | ||||
| 			chunk_len = len; | ||||
| 
 | ||||
| 		if (ttls->avp_received + chunk_len > ttls->avp_capacity) { | ||||
| 			ttls->avp_capacity = avp_len; | ||||
| 			ttls->avp_buf = l_realloc(ttls->avp_buf, | ||||
| 							ttls->avp_capacity); | ||||
| 		} | ||||
| 
 | ||||
| 		memcpy(ttls->avp_buf + ttls->avp_received, data, chunk_len); | ||||
| 		ttls->avp_received += chunk_len; | ||||
| 
 | ||||
| 		if (avp_len > ttls->avp_received) /* Wait for more data */ | ||||
| 			return; | ||||
| 
 | ||||
| 		/* Do we have a full AVP or just the header */ | ||||
| 		if (ttls->avp_received - chunk_len >= | ||||
| 				sizeof(struct eap_ttls_avp)) { | ||||
| 			ttls->avp_received = 0; | ||||
| 
 | ||||
| 			avp = (struct eap_ttls_avp *) ttls->avp_buf; | ||||
| 
 | ||||
| 			if (!eap_ttls_handle_avp(eap, avp)) | ||||
| 				return; | ||||
| 
 | ||||
| 			data += chunk_len; | ||||
| 			len -= chunk_len; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* Handle all the AVPs fully contained in the newly received data */ | ||||
| 	while (len) { | ||||
| 		avp_len = avp_min_len(data, len); | ||||
| 		if (len < avp_len || len < sizeof(struct eap_ttls_avp)) | ||||
| 			break; | ||||
| 
 | ||||
| 		avp = (struct eap_ttls_avp *) data; | ||||
| 
 | ||||
| 		if (!eap_ttls_handle_avp(eap, avp)) | ||||
| 			return; | ||||
| 
 | ||||
| 		data += avp_len; | ||||
| 		len -= avp_len; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!len) | ||||
| 		return; | ||||
| 
 | ||||
| 	/* Store the remaining bytes */ | ||||
| 	if (ttls->avp_capacity < len) { | ||||
| 		ttls->avp_capacity = avp_len; | ||||
| 		ttls->avp_buf = l_realloc(ttls->avp_buf, ttls->avp_capacity); | ||||
| 	} | ||||
| 
 | ||||
| 	memcpy(ttls->avp_buf, data, len); | ||||
| 	ttls->avp_received = len; | ||||
| 	databuf_append(ttls->avp_buf, data, data_len); | ||||
| } | ||||
| 
 | ||||
| static void eap_ttls_ready_cb(const char *peer_identity, void *user_data) | ||||
| @ -551,7 +422,7 @@ static void eap_ttls_handle_payload(struct eap_state *eap, | ||||
| 	if (!ttls->avp_buf) | ||||
| 		return; | ||||
| 
 | ||||
| 	avp_iter_init(&iter, ttls->avp_buf, ttls->avp_received); | ||||
| 	avp_iter_init(&iter, ttls->avp_buf->data, ttls->avp_buf->len); | ||||
| 
 | ||||
| 	while (avp_iter_next(&iter)) { | ||||
| 		if (ttls->phase2->handle_avp(eap, iter.type, iter.vendor_id, | ||||
| @ -562,9 +433,8 @@ static void eap_ttls_handle_payload(struct eap_state *eap, | ||||
| 			l_tls_close(ttls->tls); | ||||
| 	} | ||||
| 
 | ||||
| 	l_free(ttls->avp_buf); | ||||
| 	ttls->avp_received = 0; | ||||
| 	ttls->avp_capacity = 0; | ||||
| 	databuf_free(ttls->avp_buf); | ||||
| 	ttls->avp_buf = NULL; | ||||
| } | ||||
| 
 | ||||
| static void eap_ttls_handle_request(struct eap_state *eap, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tim Kourt
						Tim Kourt