def verify_message_authentication(radius_packet, secret): """ Verifies authenticity of the message When the message integrity check is calculated the signature string should be considered to be sixteen octets of zero. The shared secret is used as the key for the HMAC-MD5 message integrity check. The Message-Authenticator is calculated and inserted in the packet before the Response Authenticator is calculated. """ radius_packet_copy = radius.RADIUSPacket() radius_packet_copy.set_code(radius_packet.get_code()) radius_packet_copy.set_identifier(radius_packet.get_identifier()) radius_packet_copy.set_authenticator(radius_packet.get_authenticator()) #authenticator = radius_packet_copy.get_authenticator(); attributes = radius_packet.get_attributes() authentication_message = None for attribute in attributes: if attribute.get_type( ) == radius.RADIUS_EAP_MESSAGE_AUTHENTICATOR_ATTRIBUTE: authentication_message = attribute.get_value() # Set Message-Authentication attribute value to 16 zero bytes attribute = radius.RADIUSAttribute( radius.RADIUS_EAP_MESSAGE_AUTHENTICATOR_ATTRIBUTE, [0] * radius.RADIUS_AUTHENTICATOR_FIELD_LENGTH) radius_packet_copy.add_attribute(attribute) md5hmac = digest.HMACMD5() #computed_authenticator = md5.digest(bytearray(radius_packet_copy.get_bytes()) + bytearray(secret)); authenticator_bytes = md5hmac.digest( secret, bytearray(radius_packet_copy.get_bytes())) return Utils.compare_bytearrays(authenticator_bytes, authentication_message)
def handle_accounting_response(authenticator, radius_identifier, socket, address): """ Radius accounting response """ radius_accounting_response = radius.RADIUSPacket() """ Set the code of the RADIUS packet to challenge type """ radius_accounting_response.set_code( radius.RADIUS_ACCOUNTING_RESPONSE_TYPE) """ Set correct value of the authenticator field """ radius_accounting_response.set_authenticator(authenticator) """ Set the identifier so that the NAS can match request with response """ radius_accounting_response.set_identifier(radius_identifier) """ Compute resposne authenticator """ response_authenticator = Utils.Utils.compute_response_authenticator( radius_accounting_response, bytearray(config["security"]["radius_master_secret"], encoding='utf8')) radius_accounting_response.set_authenticator(response_authenticator) """ Send response packet """ bytes_out = socket.sendto( bytearray(radius_accounting_response.get_bytes()), address) print("Sent %d" % (bytes_out))
def handle_access_reject(authenticator, radius_identifier, socket, address): eap_packet = eap.EAPFailure() packet = eap_packet.get_bytes() radius_reject = radius.RADIUSPacket() radius_reject.set_code(radius.RADIUS_ACCESS_REJECT_TYPE) radius_reject.set_authenticator(authenticator) radius_reject.set_identifier(radius_identifier) Utils.Utils.radius_split_message( radius_reject, packet, config["networking"]["eap_message_attribute_length"]) message_authenticator_attribute = (radius.RADIUSAttribute( radius.RADIUS_EAP_MESSAGE_AUTHENTICATOR_ATTRIBUTE, [0] * radius.RADIUS_AUTHENTICATOR_FIELD_LENGTH)) radius_reject.add_attribute(message_authenticator_attribute) message_authentication_bytes = ( Utils.Utils.compute_message_authentication( radius_reject, bytearray(config["security"]["radius_master_secret"], encoding='utf8'))) radius_reject = Utils.Utils.set_message_authentication( radius_reject, message_authentication_bytes) response_authenticator = Utils.Utils.compute_response_authenticator( radius_reject, bytearray(config["security"]["radius_master_secret"], encoding='utf8')) radius_reject.set_authenticator(response_authenticator) bytes_out = socket.sendto(bytearray(radius_reject.get_bytes()), address) print("Sent %d" % (bytes_out))
def acknowledge_client_key_exchange_fragment(authenticator, radius_identifier, eap_identifier, socket, address): eap_ttls_packet = eap.EAPTTLSRequest() eap_ttls_packet.set_identifier(eap_identifier) packet = eap_ttls_packet.get_bytes() radius_challenge = radius.RADIUSPacket() """ Set the code of the RADIUS packet to challenge type """ radius_challenge.set_code(radius.RADIUS_ACCESS_CHALLENGE_TYPE) """ Set correct value of the authenticator field """ radius_challenge.set_authenticator(authenticator) """ Set the identifier so that the NAS can match request with response """ radius_challenge.set_identifier(radius_identifier) #message = outstanding_packets[calling_station_id][0].get_bytes(); Utils.Utils.radius_split_message( radius_challenge, packet, config["networking"]["eap_message_attribute_length"]) message_authenticator_attribute = (radius.RADIUSAttribute( radius.RADIUS_EAP_MESSAGE_AUTHENTICATOR_ATTRIBUTE, [0] * radius.RADIUS_AUTHENTICATOR_FIELD_LENGTH)) radius_challenge.add_attribute(message_authenticator_attribute) """ Compute message authentication """ message_authentication_bytes = ( Utils.Utils.compute_message_authentication( radius_challenge, bytearray(config["security"]["radius_master_secret"], encoding='utf8'))) """ Update the message authentication attribute """ radius_challenge = Utils.Utils.set_message_authentication( radius_challenge, message_authentication_bytes) """ Compute and update response authenticator """ response_authenticator = Utils.Utils.compute_response_authenticator( radius_challenge, bytearray(config["security"]["radius_master_secret"], encoding='utf8')) radius_challenge.set_authenticator(response_authenticator) bytes_out = socket.sendto(bytearray(radius_challenge.get_bytes()), address) print("Sent %d" % (bytes_out))
def verify_accounting_authenticator(radius_packet, secret): authenticator = radius_packet.get_authenticator() radius_packet_copy = radius.RADIUSPacket() radius_packet_copy.set_code(radius_packet.get_code()) radius_packet_copy.set_identifier(radius_packet.get_identifier()) attributes = radius_packet.get_attributes() for attribute in attributes: radius_packet_copy.add_attribute(attribute) md5 = digest.MD5Digest() authenticator_computed = md5.digest( bytearray(radius_packet_copy.get_bytes()) + secret) return Utils.compare_bytearrays(authenticator_computed, authenticator)
def set_message_authentication(radius_packet, authentication_message): """ Sets the value of the message authentication attribute This is rather wrong way of doing things. Perhaps, in future, we may set attribute values directly in the packet. """ radius_packet_copy = radius.RADIUSPacket() radius_packet_copy.set_code(radius_packet.get_code()) radius_packet_copy.set_identifier(radius_packet.get_identifier()) radius_packet_copy.set_authenticator(radius_packet.get_authenticator()) attributes = radius_packet.get_attributes() for attribute in attributes: if attribute.get_type( ) == radius.RADIUS_EAP_MESSAGE_AUTHENTICATOR_ATTRIBUTE: attribute = radius.RADIUSAttribute( radius.RADIUS_EAP_MESSAGE_AUTHENTICATOR_ATTRIBUTE, authentication_message) radius_packet_copy.add_attribute(attribute) return radius_packet_copy
def compute_message_authentication(radius_packet, secret): """ Computes message authentication code for the given RADIUS packet. For Access-Challenge, Access-Accept, and Access-Reject packets, the Message-Authenticator is calculated as follows, using the Request-Authenticator from the Access-Request this packet is in reply to: Message-Authenticator = HMAC-MD5 (Type, Identifier, Length, Request Authenticator, Attributes) When the message integrity check is calculated the signature string should be considered to be sixteen octets of zero. The shared secret is used as the key for the HMAC-MD5 message integrity check. The Message-Authenticator is calculated and inserted in the packet before the Response Authenticator is calculated. """ radius_packet_copy = radius.RADIUSPacket() radius_packet_copy.set_code(radius_packet.get_code()) radius_packet_copy.set_identifier(radius_packet.get_identifier()) radius_packet_copy.set_authenticator(radius_packet.get_authenticator()) attributes = radius_packet.get_attributes() authentication_message = None for attribute in attributes: if attribute.get_type( ) == radius.RADIUS_EAP_MESSAGE_AUTHENTICATOR_ATTRIBUTE: authentication_message = attribute.get_value() # Set Message-Authentication attribute value to 16 zero bytes attribute = radius.RADIUSAttribute( radius.RADIUS_EAP_MESSAGE_AUTHENTICATOR_ATTRIBUTE, [0] * radius.RADIUS_AUTHENTICATOR_FIELD_LENGTH) radius_packet_copy.add_attribute(attribute) md5hmac = digest.HMACMD5() return md5hmac.digest(secret, bytearray(radius_packet_copy.get_bytes()))
def accounting_loop(socket): """ Runs accounting loop """ mtu = config["networking"]["mtu"]; running = True; while running: data, address = socket.recvfrom(mtu); src_ip = address[0]; src_port = address[1]; print("Got packet from address %s on port %s" % (src_ip, src_port)) """ RFC 2866 defines attributes which can be used in RADIUS accouting packets https://tools.ietf.org/html/rfc2866 """ try: radius_packet = radius.RADIUSPacket(data); print("Packet type: %s" % (radius_packet.get_code())) if radius_packet.get_code() == radius.RADIUS_ACCOUNTING_REQUEST_TYPE: print("Got accouting request packet"); authenticator = radius_packet.get_authenticator(); radius_identifier = radius_packet.get_identifier(); """ The following steps should be taken: (i) verify the authenticity of the packet (ii) check the packet's Acct-Status-Type (iii) if accouting type is of type Start insert a record into the database (iv) if accouting type is of type stop finilize the accounting """ if not Utils.Utils.verify_accounting_authenticator(radius_packet, bytearray(config["security"]["radius_master_secret"], encoding='utf8')): print("Invalid authenticator in RADIUS packet..."); continue; PacketProcessor.handle_accounting_response(authenticator, radius_identifier, socket, address); continue; except Exception as e: traceback.print_exc();
def authentication_loop(socket): """ Runs the authentication loop. This is the main loop where TLS packets are processed and state is maintained """ certificate = certs.X509v3Certificate.load(config["security"]["certificate_path"]); private_key = certs.RSAPrivateKey.load(config["security"]["private_key"]); mtu = config["networking"]["mtu"]; running = True; outstanding_packets = dict(); handshake_packets = dict(); duplicates = dict(); eap_identifier = 1; while running: data, address = socket.recvfrom(mtu); src_ip = address[0]; src_port = address[1]; print("Got packet from address %s on port %s" % (src_ip, src_port)) try: radius_packet = radius.RADIUSPacket(data); calling_station_id = Utils.Utils.get_calling_station_id(radius_packet); """ The Identifier field is one octet, and aids in matching requests and replies. The RADIUS server can detect a duplicate request if it has the same client source IP address and source UDP port and Identifier within a short span of time. """ if calling_station_id not in duplicates.keys(): duplicates[calling_station_id] = radius_packet.get_identifier(); else: if duplicates[calling_station_id] == radius_packet.get_identifier(): print("We have a duplicate. Skipping..."); continue; else: duplicates[calling_station_id] = radius_packet.get_identifier(); print("Packet type: %d" % (radius_packet.get_code())); # if radius_packet.get_code() == radius.RADIUS_ACCESS_REQUEST_TYPE: authenticator = radius_packet.get_authenticator(); radius_identifier = radius_packet.get_identifier(); """ Check the authenticity of the RADIUS packet """ if not PacketProcessor.verify_access_request_packet(radius_packet): print("RADIUS packet verification failure. Skipping the packet..."); continue; # Construct EAP message from fragments fragments = Utils.Utils.get_eap_packet(radius_packet); if not calling_station_id: print("No calling station ID present in RADIUS packet. Skipping..."); continue; # Non-EAP packet (need to check what to do in case no EAP message is present in RADIUS packet) if len(fragments) == 0x0: print("No RADIUS encapsulated EAP packet fragments were found. Skipping..."); continue; # Silently drop the packet for now eap_packet = eap.EAPPacket(fragments); if eap_packet.get_type() == eap.EAP_IDENTITY_TYPE: if tls_state_machine.get_state(calling_station_id): print("TLS state already exists. Perhaps this is a duplicate. Skipping."); continue; print("Sending RADIUS access challenge in response to RADIUS access request..."); #print("Sending encapsulated EAP Request packet with start flag set to 1..."); radius_challenge = PacketProcessor.handle_identity_packet(eap_packet, tls_state_machine, calling_station_id, authenticator, radius_identifier, eap_identifier, socket, address); eap_identifier = (eap_identifier + 1) % 0x100; elif eap_packet.get_type() == eap.EAP_TTLS_TYPE: print("Got EAP TTLS packet"); # Reconstruct EAP TTLS packet from fragments eap_ttls_packet = eap.EAPTTLSPacket(fragments); tls_state = tls_state_machine.get_state(calling_station_id); if not tls_state: print("Invalid TLS state."); continue; if eap_ttls_packet.get_code() != eap.EAP_TTLS_RESPONSE_CODE: print("Should be EAP TTLS response packet. Droping..."); continue; flags = eap_ttls_packet.get_flags(); has_more_fragments = eap.HAS_MORE_FRAGMENTS(flags); # If the packet has more fragments flag set we should # reassemble the TLS packet before we can parse it. if not has_more_fragments: # If we have not seen client's hello we should process it first print("We have received unfragmented packet..."); if not tls_state.get_client_hello_received(): handshake_packets[calling_station_id] = []; # We are looking for TLS client's hello packet tls_packet = tls.TLSPacket(eap_ttls_packet.get_bytes_without_header()); if tls_packet.get_records()[0].get_content_type() == tls.TLS_CONTENT_TYPE_ALERT: print("Error has occured."); continue; if not (PacketProcessor.handle_client_hello_packet( tls_packet, tls_state, handshake_packets[calling_station_id] )): print("Failed to handle client hello packet. Skipping"); continue; outstanding_packets[calling_station_id] = PacketProcessor.process_server_hello_packet( tls_state, certificate, eap_identifier, handshake_packets[calling_station_id] ); packet = outstanding_packets[calling_station_id][0]; outstanding_packets[calling_station_id] = outstanding_packets[calling_station_id][1:]; PacketProcessor.send_outstanding_packet( packet.get_bytes(), authenticator, radius_identifier, eap_identifier, socket, address); eap_identifier = (eap_identifier + 1) % 0x100; elif not tls_state.get_server_hello_sent(): # We should now send the server's hello packet if len(outstanding_packets[calling_station_id]) > 0: packet = outstanding_packets[calling_station_id][0]; outstanding_packets[calling_station_id] = outstanding_packets[calling_station_id][1:]; PacketProcessor.send_outstanding_packet( packet.get_bytes(), authenticator, radius_identifier, eap_identifier, socket, address); eap_identifier = (eap_identifier + 1) % 0x100; if len(outstanding_packets[calling_station_id]) == 0: print("Server hello, certificate and server hello done packets have been sent out."); tls_state.set_server_hello_sent(True); tls_state.set_server_certificate_sent(True); tls_state.set_server_hello_done_sent(True); else: print("We should have outstanding packets. Error..."); continue; elif not tls_state.get_server_certificate_sent(): # We should now send the server's certificate print("We should never be in this state."); pass elif not tls_state.get_server_hello_done_sent(): # We should now send the server's hello done print("We should never be in this state."); pass elif not tls_state.get_client_key_exchange_received(): # We are expecting the client's key exchange protocol outstanding_packets[calling_station_id] += eap_ttls_packet.get_bytes_without_header(); tls_packet = tls.TLSPacket(outstanding_packets[calling_station_id]); if tls_packet.get_records()[0].get_content_type() == tls.TLS_CONTENT_TYPE_ALERT: print("Error has occured."); continue; PacketProcessor.handle_client_key_exchange_packet( tls_packet, tls_state, private_key.get_key_info(), handshake_packets[calling_station_id]); if not PacketProcessor.handle_client_cipher_spec_change_packet(tls_packet, tls_state): # This is an error - client's cipher spec change packet must follow the client # key exchange packet continue; # Verify the encrypted finished message if not PacketProcessor.handle_client_encrypted_finish_message( tls_packet, tls_state, handshake_packets[calling_station_id]): print("Failed to verify the encrypted finish message."); else: print("Verification succeeded."); #print(hexlify(bytearray(PacketProcessor.get_unencrypted_finished_message(tls_state, tls_packet)))) handshake_packets[calling_station_id] += PacketProcessor.get_unencrypted_finished_message(tls_state, tls_packet); #tls_state.set_client_finished_message_received(True); PacketProcessor.process_server_cipher_spec_changed_packet( authenticator, radius_identifier, eap_identifier, socket, address); eap_identifier = (eap_identifier + 1) % 0x100; tls_state.set_client_key_exchange_received(True); #tls_state.set_server_cipher_spec_changed_sent(True); elif not tls_state.get_server_cipher_spec_changed_sent(): print("Processing server's encrypted message."); PacketProcessor.process_server_encrypted_finish_message( tls_state, handshake_packets[calling_station_id], authenticator, radius_identifier, socket, address ); tls_state.set_server_cipher_spec_changed_sent(True); tls_state.set_server_finished_message_sent(True); continue; elif tls_state.get_server_finished_message_sent(): tls_packet = tls.TLSPacket(eap_ttls_packet.get_bytes_without_header()); if tls_packet.get_records()[0].get_content_type() == tls.TLS_CONTENT_TYPE_ALERT: print("Encrypted alert. Skipping."); PacketProcessor.process_encrypted_alert(tls_state, tls_packet); continue; elif tls_packet.get_records()[0].get_content_type() == tls.TLS_CONTENT_TYPE_APPLICATION_DATA: print("Expecting PAP packet with AVPs (username and password)"); attributes = PacketProcessor.process_encrypted_pap_avp(tls_state, tls_packet); username = None; password = None; for attribute in attributes: if attribute.get_code() == eap.PAP_USERNAME_ATTRIBUTE_CODE: username = utils.Utils.remove_null_bytes(attribute.get_data()); elif attribute.get_code() == eap.PAP_PASSWORD_ATTRBIUTE_CODE: password = utils.Utils.remove_null_bytes(attribute.get_data()); else: print("Unknown attribute"); continue; if database.authenticate(username, password): print("Access was granted to the user"); (bytes_remaining, conn_speed) = database.get_bytes_remaining_and_conn_speed(username); PacketProcessor.handle_access_accept( tls_state, bytes_remaining, conn_speed, authenticator, radius_identifier, socket, address); else: print("Access was rejected"); PacketProcessor.handle_access_reject( authenticator, radius_identifier, socket, address); else: print("Unknonw state. We should never be here.") else: if not tls_state.get_client_hello_received(): # We are looking for TLS client's hello packet pass elif not tls_state.get_server_hello_sent(): # We should now send the server's hello packet pass elif not tls_state.get_server_certificate_sent(): # We should now send the server's certificate pass elif not tls_state.get_server_hello_done_sent(): # We should now send the server's hello done pass elif not tls_state.get_client_key_exchange_received(): # We are expecting the client's key exchange protocol outstanding_packets[calling_station_id] += eap_ttls_packet.get_bytes_without_header(); PacketProcessor.acknowledge_client_key_exchange_fragment( authenticator, radius_identifier, eap_identifier, socket, address); # This should be done on per client bases eap_identifier = (eap_identifier + 1) % 0x100; elif not tls_state.get_client_cipher_spec_changed_received(): # We are expecting the client's cipher spec changed pass elif not tls_state.get_client_finished_message_received(): # We are expecting the client's finished message pass elif not tls_state.get_server_cipher_spec_changed_sent(): # We should now pass else: print("Unsupported EAP packet type..."); else: print("Invalid RADIUS packet type recieved. Expected RADIUS Access-Request packet."); except Exception as e: traceback.print_exc();
def handle_access_accept(tls_state, bytes_remaining, conn_speed, authenticator, radius_identifier, socket, address): eap_packet = eap.EAPSuccess() packet = eap_packet.get_bytes() radius_success = radius.RADIUSPacket() radius_success.set_code(radius.RADIUS_ACCESS_ACCEPT_TYPE) radius_success.set_authenticator(authenticator) radius_success.set_identifier(radius_identifier) Utils.Utils.radius_split_message( radius_success, packet, config["networking"]["eap_message_attribute_length"]) keying_material = wpa2.WPA2.generate_keying_material( tls_state.get_master_secret(), bytearray(tls_state.get_client_random()), bytearray(tls_state.get_server_random())) # This code was tested and the MSK and EMSK were derived correctly... msk_key = wpa2.WPA2.generate_msk(keying_material) emsk_key = wpa2.WPA2.generate_emsk(keying_material) microsoft_recv_key_attribute = radius.MicrosoftAttribute() microsoft_recv_key_attribute.set_value( wpa2.WPA2.encrypt_ms_key( bytearray(config["security"]["radius_master_secret"], encoding='utf8'), authenticator, msk_key[0:wpa2.RECV_KEY_LENGTH])) microsoft_recv_key_attribute.set_type(radius.MS_MPPE_RECV_KEY) microsoft_send_key_attribute = radius.MicrosoftAttribute() microsoft_send_key_attribute.set_value( wpa2.WPA2.encrypt_ms_key( bytearray(config["security"]["radius_master_secret"], encoding='utf8'), authenticator, msk_key[wpa2.RECV_KEY_LENGTH:wpa2.RECV_KEY_LENGTH + wpa2.SEND_KEY_LENGTH])) microsoft_send_key_attribute.set_type(radius.MS_MPPE_SEND_KEY) mikrotik_conn_speed_attribute = radius.MikroTikAttribute() mikrotik_conn_speed_attribute.set_value( bytearray(conn_speed.encode("ascii"))) mikrotik_conn_speed_attribute.set_type(radius.MIKROTIK_RATE_LIMIT) mikrotik_total_limit_attribute = radius.MikroTikAttribute() mikrotik_total_limit_attribute.set_value( struct.pack(">I", int(bytes_remaining % (4 * 1024 * 1024)))) mikrotik_total_limit_attribute.set_type(radius.MIKROTIK_TOTAL_LIMIT) #mikrotik_total_limit_attribute.set_type(radius.MIKROTIK_SEND_LIMIT); mikrotik_total_limit_giga_attribute = radius.MikroTikAttribute() mikrotik_total_limit_giga_attribute.set_value( struct.pack(">I", int(bytes_remaining / (4 * 1024 * 1024)))) mikrotik_total_limit_giga_attribute.set_type( radius.MIKROTIK_TOTAL_GIGAWORDS_LIMIT) mikrotik_recv_limit_attribute = radius.MikroTikAttribute() mikrotik_recv_limit_attribute.set_value( struct.pack(">I", int(bytes_remaining % (4 * 1024 * 1024)))) mikrotik_recv_limit_attribute.set_type(radius.MIKROTIK_RECV_LIMIT) mikrotik_recv_limit_giga_attribute = radius.MikroTikAttribute() mikrotik_recv_limit_giga_attribute.set_value( struct.pack(">I", int(bytes_remaining / (4 * 1024 * 1024)))) mikrotik_recv_limit_giga_attribute.set_type( radius.MIKROTIK_RECV_GIGAWORDS_LIMIT) conn_speed_attribute = (radius.RADIUSVendorSpecificAttribute( radius.RADIUS_VENDOR_SPECIFIC_ATTRIBUTE, radius.RADIUS_MIKROTIK_VENDOR_ID, mikrotik_conn_speed_attribute.get_bytes())) radius_success.add_attribute(conn_speed_attribute) total_limit_attribute = (radius.RADIUSVendorSpecificAttribute( radius.RADIUS_VENDOR_SPECIFIC_ATTRIBUTE, radius.RADIUS_MIKROTIK_VENDOR_ID, mikrotik_total_limit_attribute.get_bytes())) radius_success.add_attribute(total_limit_attribute) total_limit_giga_attribute = (radius.RADIUSVendorSpecificAttribute( radius.RADIUS_VENDOR_SPECIFIC_ATTRIBUTE, radius.RADIUS_MIKROTIK_VENDOR_ID, mikrotik_total_limit_giga_attribute.get_bytes())) radius_success.add_attribute(total_limit_giga_attribute) recv_limit_giga_attribute = (radius.RADIUSVendorSpecificAttribute( radius.RADIUS_VENDOR_SPECIFIC_ATTRIBUTE, radius.RADIUS_MIKROTIK_VENDOR_ID, mikrotik_recv_limit_giga_attribute.get_bytes())) #radius_success.add_attribute(recv_limit_giga_attribute); send_key_attribute = (radius.RADIUSVendorSpecificAttribute( radius.RADIUS_VENDOR_SPECIFIC_ATTRIBUTE, radius.RADIUS_MICROSOFT_VENDOR_ID, microsoft_send_key_attribute.get_bytes())) radius_success.add_attribute(send_key_attribute) recv_key_attribute = (radius.RADIUSVendorSpecificAttribute( radius.RADIUS_VENDOR_SPECIFIC_ATTRIBUTE, radius.RADIUS_MICROSOFT_VENDOR_ID, microsoft_recv_key_attribute.get_bytes())) radius_success.add_attribute(recv_key_attribute) message_authenticator_attribute = (radius.RADIUSAttribute( radius.RADIUS_EAP_MESSAGE_AUTHENTICATOR_ATTRIBUTE, [0] * radius.RADIUS_AUTHENTICATOR_FIELD_LENGTH)) radius_success.add_attribute(message_authenticator_attribute) message_authentication_bytes = ( Utils.Utils.compute_message_authentication( radius_success, bytearray(config["security"]["radius_master_secret"], encoding='utf8'))) radius_success = Utils.Utils.set_message_authentication( radius_success, message_authentication_bytes) response_authenticator = Utils.Utils.compute_response_authenticator( radius_success, bytearray(config["security"]["radius_master_secret"], encoding='utf8')) radius_success.set_authenticator(response_authenticator) bytes_out = socket.sendto(bytearray(radius_success.get_bytes()), address) print("Sent %d" % (bytes_out))
def handle_identity_packet(eap_packet, tls_state_machine, calling_station_id, authenticator, radius_identifier, eap_identifier, socket, address): """ Handles identity packet """ user_identity = eap_packet.get_bytes_without_header() print("Got EAP Identity: %s" % ("".join(map(chr, user_identity)))) """ Create EAP TTLS request packet """ eap_start = eap.EAPTTLSRequest() eap_start.set_is_start_flag() eap_start.set_identifier(eap_identifier) # Fix me we need to handle identifiers #eap_start.set_identifier(eap_identifier); #eap_identifier += 1; eap_start_bytes = eap_start.get_bytes() radius_challenge = radius.RADIUSPacket() """ Set the code of the RADIUS packet to challenge type """ radius_challenge.set_code(radius.RADIUS_ACCESS_CHALLENGE_TYPE) """ Set correct value of the authenticator field """ radius_challenge.set_authenticator(authenticator) """ Set the identifier so that the NAS can match request with response """ radius_challenge.set_identifier(radius_identifier) eap_attribute = (radius.RADIUSAttribute( radius.RADIUS_EAP_MESSAGE_ATTRIBUTE, eap_start_bytes)) radius_challenge.add_attribute(eap_attribute) message_authenticator_attribute = (radius.RADIUSAttribute( radius.RADIUS_EAP_MESSAGE_AUTHENTICATOR_ATTRIBUTE, [0] * radius.RADIUS_AUTHENTICATOR_FIELD_LENGTH)) radius_challenge.add_attribute(message_authenticator_attribute) """ Compute message authentication """ message_authentication_bytes = ( Utils.Utils.compute_message_authentication( radius_challenge, bytearray(config["security"]["radius_master_secret"], encoding='utf8'))) """ Update the message authentication attribute """ radius_challenge = Utils.Utils.set_message_authentication( radius_challenge, message_authentication_bytes) """ Compute and update response authenticator """ response_authenticator = Utils.Utils.compute_response_authenticator( radius_challenge, bytearray(config["security"]["radius_master_secret"], encoding='utf8')) radius_challenge.set_authenticator(response_authenticator) """ Initialize state """ tls_state_machine.init_state(calling_station_id) """ Send response packet """ bytes_out = socket.sendto(bytearray(radius_challenge.get_bytes()), address) print("Sent %d" % (bytes_out))
def process_server_encrypted_finish_message(tls_state, handshake_messages, authenticator, radius_identifier, socket, address): """ Processes server's encrypted finish message """ master_secret = tls_state.get_master_secret() verify_data_computed = utils.Utils.verify_server_finshed_message( master_secret, handshake_messages, tls.FINISHED_MESSAGE_VERIFY_DATA_LENGTH) server_sequence_number = tls_state.get_server_sequence_number() tls_packet = tls.TLSPacket() tls_record = tls.TLSRecordLayer() finished_message_protocol = tls.FinishedMessageProtocol() finished_message_protocol.set_verify_data(verify_data_computed) hmac = utils.Utils.compute_server_finished_message_mac( tls_state.get_server_write_mac_key(), server_sequence_number, tls.TLS_CONTENT_TYPE_HANDSHAKE, tls.TLS_PROTOCOL_VERSION, finished_message_protocol.get_bytes()) finished_message_protocol_bytes = finished_message_protocol.get_bytes( ) message = bytearray(finished_message_protocol_bytes) + hmac # This should be # padding = [(aes.BLOCK_SIZE - len(message) % aes.BLOCK_SIZE)] * (aes.BLOCK_SIZE - len(message) % aes.BLOCK_SIZE); padding = [0x0f] * (aes.BLOCK_SIZE - len(message) % aes.BLOCK_SIZE) padding[len(padding) - 1] = len(padding) - 1 key = tls_state.get_server_write_cipher_key() iv = utils.Utils.generate_random(aes.IV_SIZE) cipher = aes.AESCipher(aes.AES_CBC_MODE, key, iv) encrypted_bytes = cipher.encrypt((message + bytearray(padding))) tls_record.add_encrypted_protocol(bytearray(iv + encrypted_bytes)) tls_packet.add_record(tls_record) eap_ttls_packet = eap.EAPTTLSRequest() eap_ttls_packet.set_payload(tls_packet.get_bytes(), len(tls_packet.get_bytes())) packet = eap_ttls_packet.get_bytes() radius_challenge = radius.RADIUSPacket() """ Set the code of the RADIUS packet to challenge type """ radius_challenge.set_code(radius.RADIUS_ACCESS_CHALLENGE_TYPE) """ Set correct value of the authenticator field """ radius_challenge.set_authenticator(authenticator) """ Set the identifier so that the NAS can match request with response """ radius_challenge.set_identifier(radius_identifier) #message = outstanding_packets[calling_station_id][0].get_bytes(); Utils.Utils.radius_split_message( radius_challenge, packet, config["networking"]["eap_message_attribute_length"]) message_authenticator_attribute = (radius.RADIUSAttribute( radius.RADIUS_EAP_MESSAGE_AUTHENTICATOR_ATTRIBUTE, [0] * radius.RADIUS_AUTHENTICATOR_FIELD_LENGTH)) radius_challenge.add_attribute(message_authenticator_attribute) """ Compute message authentication """ message_authentication_bytes = ( Utils.Utils.compute_message_authentication( radius_challenge, bytearray(config["security"]["radius_master_secret"], encoding='utf8'))) """ Update the message authentication attribute """ radius_challenge = Utils.Utils.set_message_authentication( radius_challenge, message_authentication_bytes) """ Compute and update response authenticator """ response_authenticator = Utils.Utils.compute_response_authenticator( radius_challenge, bytearray(config["security"]["radius_master_secret"], encoding='utf8')) radius_challenge.set_authenticator(response_authenticator) bytes_out = socket.sendto(bytearray(radius_challenge.get_bytes()), address) print("Sent %d" % (bytes_out))
def process_server_cipher_spec_changed_packet(authenticator, radius_identifier, eap_identifier, socket, address): tls_record_layer = tls.TLSRecordLayer() tls_record_layer.set_content_type( tls.TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) tls_record_layer.set_message([tls.TLS_CHANGE_CIPHER_SPEC_MESSAGE]) tls_packet = tls.TLSPacket() tls_packet.add_record(tls_record_layer) radius_challenge = radius.RADIUSPacket() """ Set the code of the RADIUS packet to challenge type """ radius_challenge.set_code(radius.RADIUS_ACCESS_CHALLENGE_TYPE) """ Set correct value of the authenticator field """ radius_challenge.set_authenticator(authenticator) """ Set the identifier so that the NAS can match request with response """ radius_challenge.set_identifier(radius_identifier) tls_packet_bytes = tls_packet.get_bytes() eap_ttls_packet = eap.EAPTTLSRequest() eap_ttls_packet.set_identifier(eap_identifier) eap_ttls_packet.set_payload(tls_packet_bytes, len(tls_packet_bytes)) #message = outstanding_packets[calling_station_id][0].get_bytes(); Utils.Utils.radius_split_message( radius_challenge, eap_ttls_packet.get_bytes(), config["networking"]["eap_message_attribute_length"]) message_authenticator_attribute = (radius.RADIUSAttribute( radius.RADIUS_EAP_MESSAGE_AUTHENTICATOR_ATTRIBUTE, [0] * radius.RADIUS_AUTHENTICATOR_FIELD_LENGTH)) radius_challenge.add_attribute(message_authenticator_attribute) """ Compute message authentication """ message_authentication_bytes = ( Utils.Utils.compute_message_authentication( radius_challenge, bytearray(config["security"]["radius_master_secret"], encoding='utf8'))) """ Update the message authentication attribute """ radius_challenge = Utils.Utils.set_message_authentication( radius_challenge, message_authentication_bytes) """ Compute and update response authenticator """ response_authenticator = Utils.Utils.compute_response_authenticator( radius_challenge, bytearray(config["security"]["radius_master_secret"], encoding='utf8')) radius_challenge.set_authenticator(response_authenticator) bytes_out = socket.sendto(bytearray(radius_challenge.get_bytes()), address) print("Sent %d" % (bytes_out))