diff --git a/scapy/layers/radius.py b/scapy/layers/radius.py index 4d93bcff41d40ef76088b8a41e9c6dad5f8e1d3d..1038974efd779212aa1b93ed16fea3920c836589 100644 --- a/scapy/layers/radius.py +++ b/scapy/layers/radius.py @@ -9,139 +9,1199 @@ RADIUS (Remote Authentication Dial In User Service) """ import struct -from scapy.packet import * -from scapy.fields import * -from scapy.layers.inet import * +import logging +from scapy.packet import Packet, bind_layers +from scapy.fields import ByteField, ByteEnumField, IntField, StrLenField,\ + XStrLenField, XStrFixedLenField, FieldLenField, PacketField,\ + PacketListField, IPField, MultiEnumField +from scapy.layers.inet import UDP +from scapy.layers.l2 import EAP +from scapy.config import conf +from scapy.error import Scapy_Exception + + +g_log_loading = logging.getLogger("scapy.logging") + +_crypto_loading_failure_message = \ + "Could not import python-cryptography."\ + "Computations for the \"authenticator\" field (RADIUS packets) and"\ + "\"Message-Authenticator\" attribute value field are disabled." + +if conf.crypto_valid: + from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives import hashes, hmac +else: + g_log_loading.info(_crypto_loading_failure_message) + + +# https://www.iana.org/assignments/radius-types/radius-types.xhtml +_radius_attribute_types = { + 1: "User-Name", + 2: "User-Password", + 3: "CHAP-Password", + 4: "NAS-IP-Address", + 5: "NAS-Port", + 6: "Service-Type", + 7: "Framed-Protocol", + 8: "Framed-IP-Address", + 9: "Framed-IP-Netmask", + 10: "Framed-Routing", + 11: "Filter-Id", + 12: "Framed-MTU", + 13: "Framed-Compression", + 14: "Login-IP-Host", + 15: "Login-Service", + 16: "Login-TCP-Port", + 17: "Unassigned", + 18: "Reply-Message", + 19: "Callback-Number", + 20: "Callback-Id", + 21: "Unassigned", + 22: "Framed-Route", + 23: "Framed-IPX-Network", + 24: "State", + 25: "Class", + 26: "Vendor-Specific", + 27: "Session-Timeout", + 28: "Idle-Timeout", + 29: "Termination-Action", + 30: "Called-Station-Id", + 31: "Calling-Station-Id", + 32: "NAS-Identifier", + 33: "Proxy-State", + 34: "Login-LAT-Service", + 35: "Login-LAT-Node", + 36: "Login-LAT-Group", + 37: "Framed-AppleTalk-Link", + 38: "Framed-AppleTalk-Network", + 39: "Framed-AppleTalk-Zone", + 40: "Acct-Status-Type", + 41: "Acct-Delay-Time", + 42: "Acct-Input-Octets", + 43: "Acct-Output-Octets", + 44: "Acct-Session-Id", + 45: "Acct-Authentic", + 46: "Acct-Session-Time", + 47: "Acct-Input-Packets", + 48: "Acct-Output-Packets", + 49: "Acct-Terminate-Cause", + 50: "Acct-Multi-Session-Id", + 51: "Acct-Link-Count", + 52: "Acct-Input-Gigawords", + 53: "Acct-Output-Gigawords", + 54: "Unassigned", + 55: "Event-Timestamp", + 56: "Egress-VLANID", + 57: "Ingress-Filters", + 58: "Egress-VLAN-Name", + 59: "User-Priority-Table", + 60: "CHAP-Challenge", + 61: "NAS-Port-Type", + 62: "Port-Limit", + 63: "Login-LAT-Port", + 64: "Tunnel-Type", + 65: "Tunnel-Medium-Type", + 66: "Tunnel-Client-Endpoint", + 67: "Tunnel-Server-Endpoint", + 68: "Acct-Tunnel-Connection", + 69: "Tunnel-Password", + 70: "ARAP-Password", + 71: "ARAP-Features", + 72: "ARAP-Zone-Access", + 73: "ARAP-Security", + 74: "ARAP-Security-Data", + 75: "Password-Retry", + 76: "Prompt", + 77: "Connect-Info", + 78: "Configuration-Token", + 79: "EAP-Message", + 80: "Message-Authenticator", + 81: "Tunnel-Private-Group-ID", + 82: "Tunnel-Assignment-ID", + 83: "Tunnel-Preference", + 84: "ARAP-Challenge-Response", + 85: "Acct-Interim-Interval", + 86: "Acct-Tunnel-Packets-Lost", + 87: "NAS-Port-Id", + 88: "Framed-Pool", + 89: "CUI", + 90: "Tunnel-Client-Auth-ID", + 91: "Tunnel-Server-Auth-ID", + 92: "NAS-Filter-Rule", + 93: "Unassigned", + 94: "Originating-Line-Info", + 95: "NAS-IPv6-Address", + 96: "Framed-Interface-Id", + 97: "Framed-IPv6-Prefix", + 98: "Login-IPv6-Host", + 99: "Framed-IPv6-Route", + 100: "Framed-IPv6-Pool", + 101: "Error-Cause", + 102: "EAP-Key-Name", + 103: "Digest-Response", + 104: "Digest-Realm", + 105: "Digest-Nonce", + 106: "Digest-Response-Auth", + 107: "Digest-Nextnonce", + 108: "Digest-Method", + 109: "Digest-URI", + 110: "Digest-Qop", + 111: "Digest-Algorithm", + 112: "Digest-Entity-Body-Hash", + 113: "Digest-CNonce", + 114: "Digest-Nonce-Count", + 115: "Digest-Username", + 116: "Digest-Opaque", + 117: "Digest-Auth-Param", + 118: "Digest-AKA-Auts", + 119: "Digest-Domain", + 120: "Digest-Stale", + 121: "Digest-HA1", + 122: "SIP-AOR", + 123: "Delegated-IPv6-Prefix", + 124: "MIP6-Feature-Vector", + 125: "MIP6-Home-Link-Prefix", + 126: "Operator-Name", + 127: "Location-Information", + 128: "Location-Data", + 129: "Basic-Location-Policy-Rules", + 130: "Extended-Location-Policy-Rules", + 131: "Location-Capable", + 132: "Requested-Location-Info", + 133: "Framed-Management-Protocol", + 134: "Management-Transport-Protection", + 135: "Management-Policy-Id", + 136: "Management-Privilege-Level", + 137: "PKM-SS-Cert", + 138: "PKM-CA-Cert", + 139: "PKM-Config-Settings", + 140: "PKM-Cryptosuite-List", + 141: "PKM-SAID", + 142: "PKM-SA-Descriptor", + 143: "PKM-Auth-Key", + 144: "DS-Lite-Tunnel-Name", + 145: "Mobile-Node-Identifier", + 146: "Service-Selection", + 147: "PMIP6-Home-LMA-IPv6-Address", + 148: "PMIP6-Visited-LMA-IPv6-Address", + 149: "PMIP6-Home-LMA-IPv4-Address", + 150: "PMIP6-Visited-LMA-IPv4-Address", + 151: "PMIP6-Home-HN-Prefix", + 152: "PMIP6-Visited-HN-Prefix", + 153: "PMIP6-Home-Interface-ID", + 154: "PMIP6-Visited-Interface-ID", + 155: "PMIP6-Home-IPv4-HoA", + 156: "PMIP6-Visited-IPv4-HoA", + 157: "PMIP6-Home-DHCP4-Server-Address", + 158: "PMIP6-Visited-DHCP4-Server-Address", + 159: "PMIP6-Home-DHCP6-Server-Address", + 160: "PMIP6-Visited-DHCP6-Server-Address", + 161: "PMIP6-Home-IPv4-Gateway", + 162: "PMIP6-Visited-IPv4-Gateway", + 163: "EAP-Lower-Layer", + 164: "GSS-Acceptor-Service-Name", + 165: "GSS-Acceptor-Host-Name", + 166: "GSS-Acceptor-Service-Specifics", + 167: "GSS-Acceptor-Realm-Name", + 168: "Framed-IPv6-Address", + 169: "DNS-Server-IPv6-Address", + 170: "Route-IPv6-Information", + 171: "Delegated-IPv6-Prefix-Pool", + 172: "Stateful-IPv6-Address-Pool", + 173: "IPv6-6rd-Configuration", + 174: "Allowed-Called-Station-Id", + 175: "EAP-Peer-Id", + 176: "EAP-Server-Id", + 177: "Mobility-Domain-Id", + 178: "Preauth-Timeout", + 179: "Network-Id-Name", + 180: "EAPoL-Announcement", + 181: "WLAN-HESSID", + 182: "WLAN-Venue-Info", + 183: "WLAN-Venue-Language", + 184: "WLAN-Venue-Name", + 185: "WLAN-Reason-Code", + 186: "WLAN-Pairwise-Cipher", + 187: "WLAN-Group-Cipher", + 188: "WLAN-AKM-Suite", + 189: "WLAN-Group-Mgmt-Cipher", + 190: "WLAN-RF-Band", + 191: "Unassigned", +} + + +class RadiusAttribute(Packet): + """ + Implements a RADIUS attribute (RFC 2865). Every specific RADIUS attribute + class should inherit from this one. + """ -class RadiusAttribute(Packet): name = "Radius Attribute" fields_desc = [ - ByteEnumField("type",1,{ 1:"User-Name", - 2:"User-Password", - 3:"CHAP-Password", - 4:"NAS-IP-Address", - 5:"NAS-Port", - 6:"Service-Type", - 7:"Framed-Protocol", - 8:"Framed-IP-Address", - 9:"Framed-IP-Netmask", - 10:"Framed-Routing", - 11:"Filter-Id", - 12:"Framed-MTU", - 13:"Framed-Compression", - 14:"Login-IP-Host", - 15:"Login-Service", - 16:"Login-TCP-Port", - 17:"(unassigned)", - 18:"Reply-Message", - 19:"Callback-Number", - 20:"Callback-Id", - 21:"(unassigned)", - 22:"Framed-Route", - 23:"Framed-IPX-Network", - 24:"State", - 25:"Class", - 26:"Vendor-Specific", - 27:"Session-Timeout", - 28:"Idle-Timeout", - 29:"Termination-Action", - 30:"Called-Station-Id", - 31:"Calling-Station-Id", - 32:"NAS-Identifier", - 33:"Proxy-State", - 34:"Login-LAT-Service", - 35:"Login-LAT-Node", - 36:"Login-LAT-Group", - 37:"Framed-AppleTalk-Link", - 38:"Framed-AppleTalk-Network", - 39:"Framed-AppleTalk-Zone", - 40:"Acct-Status-Type", - 41:"Acct-Delay-Time", - 42:"Acct-Input-Octets", - 43:"Acct-Output-Octets", - 44:"Acct-Session-Id", - 45:"Acct-Authentic", - 46:"Acct-Session-Time", - 47:"Acct-Input-Packets", - 48:"Acct-Output-Packets", - 49:"Acct-Terminate-Cause", - 50:"Acct-Multi-Session-Id", - 51:"Acct-Link-Count", - 60:"CHAP-Challenge", - 61:"NAS-Port-Type", - 62:"Port-Limit", - 63:"Login-LAT-Port", - 70:"ARAP-Password", - 75:"Password-Retry", - 79:"EAP-Message", - 80:"Message-Authenticator", - 94:"Originating-Line-Info", - 101:"Error-Cause" - }), - FieldLenField("len", None, "value", "B", adjust=lambda pkt,x:len(pkt.value)+2), - StrLenField("value", "" , length_from=lambda pkt:pkt.len-2),] + ByteEnumField("type", 1, _radius_attribute_types), + FieldLenField("len", None, "value", "B", + adjust=lambda pkt, x: len(pkt.value) + 2), + StrLenField("value", "", length_from=lambda pkt: pkt.len - 2) + ] + + registered_attributes = {} + + @classmethod + def register_variant(cls): + """ + Registers the RADIUS attributes defined in this module. + """ + + if hasattr(cls, "val"): + cls.registered_attributes[cls.val] = cls + else: + cls.registered_attributes[cls.type.default] = cls + + @classmethod + def dispatch_hook(cls, _pkt=None, *args, **kargs): + """ + Returns the right RadiusAttribute class for the given data. + """ + + if _pkt: + attr_type = ord(_pkt[0]) + return cls.registered_attributes.get(attr_type, cls) + return cls + + def haslayer(self, cls): + if cls == RadiusAttribute: + for attr_class in RadiusAttribute.registered_attributes.values(): + if isinstance(self, attr_class): + return True + elif cls in RadiusAttribute.registered_attributes.values() and isinstance(self, cls): + return True + return False + + def getlayer(self, cls, nb=1, _track=None): + layer = None + if cls == RadiusAttribute: + for attr_class in RadiusAttribute.registered_attributes.values(): + if isinstance(self, attr_class): + layer = self + break + else: + layer = Packet.getlayer(self, cls, nb, _track) + return layer + def post_build(self, p, pay): - l = self.len - if l is None: - l = len(p) - p = p[:1]+struct.pack("!B", l)+p[2:] + length = self.len + if length is None: + length = len(p) + p = p[:1] + struct.pack("!B", length) + p[2:] return p - - def extract_padding(self, pay): - return "",pay + + +class _SpecificRadiusAttr(RadiusAttribute): + """ + Class from which every "specific" RADIUS attribute defined in this module + inherits. + """ + + __slots__ = ["val"] + + def __init__(self, _pkt="", post_transform=None, _internal=0, _underlayer=None, **fields): + super(_SpecificRadiusAttr, self).__init__( + _pkt, + post_transform, + _internal, + _underlayer + ) + self.fields["type"] = self.val + name_parts = self.__class__.__name__.split('RadiusAttr_') + if len(name_parts) < 2: + raise Scapy_Exception( + "Invalid class name: {}".format(self.__class__.__name__) + ) + self.name = name_parts[1].replace('_', '-') + + +# +# RADIUS attributes which values are 4 bytes integers +# + +class _RadiusAttrIntValue(_SpecificRadiusAttr): + """ + Implements a RADIUS attribute which value field is 4 bytes long integer. + """ + + fields_desc = [ + ByteEnumField("type", 5, _radius_attribute_types), + ByteField("len", 6), + IntField("value", 0) + ] + + +class RadiusAttr_NAS_Port(_RadiusAttrIntValue): + """RFC 2865""" + val = 5 + + +class RadiusAttr_Framed_MTU(_RadiusAttrIntValue): + """RFC 2865""" + val = 12 + + +class RadiusAttr_Login_TCP_Port(_RadiusAttrIntValue): + """RFC 2865""" + val = 16 + + +class RadiusAttr_Session_Timeout(_RadiusAttrIntValue): + """RFC 2865""" + val = 27 + + +class RadiusAttr_Idle_Timeout(_RadiusAttrIntValue): + """RFC 2865""" + val = 28 + + +class RadiusAttr_Framed_AppleTalk_Link(_RadiusAttrIntValue): + """RFC 2865""" + val = 37 + + +class RadiusAttr_Framed_AppleTalk_Network(_RadiusAttrIntValue): + """RFC 2865""" + val = 38 + + +class RadiusAttr_Acct_Delay_Time(_RadiusAttrIntValue): + """RFC 2866""" + val = 41 + + +class RadiusAttr_Acct_Input_Octets(_RadiusAttrIntValue): + """RFC 2866""" + val = 42 + + +class RadiusAttr_Acct_Output_Octets(_RadiusAttrIntValue): + """RFC 2866""" + val = 43 + + +class RadiusAttr_Acct_Session_Time(_RadiusAttrIntValue): + """RFC 2866""" + val = 46 + + +class RadiusAttr_Acct_Input_Packets(_RadiusAttrIntValue): + """RFC 2866""" + val = 47 + + +class RadiusAttr_Acct_Output_Packets(_RadiusAttrIntValue): + """RFC 2866""" + val = 48 + + +class RadiusAttr_Acct_Link_Count(_RadiusAttrIntValue): + """RFC 2866""" + val = 51 + + +class RadiusAttr_Acct_Input_Gigawords(_RadiusAttrIntValue): + """RFC 2869""" + val = 52 + + +class RadiusAttr_Acct_Output_Gigawords(_RadiusAttrIntValue): + """RFC 2869""" + val = 53 + + +class RadiusAttr_Egress_VLANID(_RadiusAttrIntValue): + """RFC 4675""" + val = 56 + + +class RadiusAttr_Port_Limit(_RadiusAttrIntValue): + """RFC 2865""" + val = 62 + + +class RadiusAttr_ARAP_Security(_RadiusAttrIntValue): + """RFC 2869""" + val = 73 + + +class RadiusAttr_Password_Retry(_RadiusAttrIntValue): + """RFC 2869""" + val = 75 + + +class RadiusAttr_Tunnel_Preference(_RadiusAttrIntValue): + """RFC 2868""" + val = 83 + + +class RadiusAttr_Acct_Interim_Interval(_RadiusAttrIntValue): + """RFC 2869""" + val = 85 + + +class RadiusAttr_Acct_Tunnel_Packets_Lost(_RadiusAttrIntValue): + """RFC 2867""" + val = 86 + + +class RadiusAttr_Management_Privilege_Level(_RadiusAttrIntValue): + """RFC 5607""" + val = 136 + + +class RadiusAttr_Mobility_Domain_Id(_RadiusAttrIntValue): + """RFC 7268""" + val = 177 + + +class RadiusAttr_Preauth_Timeout(_RadiusAttrIntValue): + """RFC 7268""" + val = 178 + + +class RadiusAttr_WLAN_Venue_Info(_RadiusAttrIntValue): + """RFC 7268""" + val = 182 + + +class RadiusAttr_WLAN_Reason_Code(_RadiusAttrIntValue): + """RFC 7268""" + val = 185 + + +class RadiusAttr_WLAN_Pairwise_Cipher(_RadiusAttrIntValue): + """RFC 7268""" + val = 186 + + +class RadiusAttr_WLAN_Group_Cipher(_RadiusAttrIntValue): + """RFC 7268""" + val = 187 + + +class RadiusAttr_WLAN_AKM_Suite(_RadiusAttrIntValue): + """RFC 7268""" + val = 188 + + +class RadiusAttr_WLAN_Group_Mgmt_Cipher(_RadiusAttrIntValue): + """RFC 7268""" + val = 189 + + +class RadiusAttr_WLAN_RF_Band(_RadiusAttrIntValue): + """RFC 7268""" + val = 190 + + +# +# RADIUS attributes which values are string (displayed as hex) +# + +class _RadiusAttrHexStringVal(_SpecificRadiusAttr): + """ + Implements a RADIUS attribute which value field is a string that will be + as a hex string. + """ + + __slots__ = ["val"] + + def __init__(self, _pkt="", post_transform=None, _internal=0, _underlayer=None, **fields): + super(_RadiusAttrHexStringVal, self).__init__( + _pkt, + post_transform, + _internal, + _underlayer + ) + self.fields["type"] = self.val + name_parts = self.__class__.__name__.split('RadiusAttr_') + if len(name_parts) < 2: + raise Scapy_Exception( + "Invalid class name: {}".format(self.__class__.__name__) + ) + self.name = name_parts[1].replace('_', '-') + + fields_desc = [ + ByteEnumField("type", 24, _radius_attribute_types), + FieldLenField( + "len", + None, + "value", + "B", + adjust=lambda p, x: len(p.value) + 2 + ), + XStrLenField("value", "", length_from=lambda p: p.len - 2 if p.len else 0) + ] + + +class RadiusAttr_State(_RadiusAttrHexStringVal): + """RFC 2865""" + val = 24 + + +class RadiusAttr_Message_Authenticator(_RadiusAttrHexStringVal): + """RFC 2869""" + val = 80 + + fields_desc = [ + ByteEnumField("type", 24, _radius_attribute_types), + FieldLenField( + "len", + 18, + "value", + "B", + ), + XStrFixedLenField("value", "\x00" * 16, length=16) + ] + + @staticmethod + def compute_message_authenticator( + radius_packet, + packed_req_authenticator, + shared_secret + ): + """ + Computes the "Message-Authenticator" of a given RADIUS packet. + """ + + if not conf.crypto_valid: + g_log_loading.info(_crypto_loading_failure_message) + return None + + packed_hdr = struct.pack("!B", radius_packet.code) + packed_hdr += struct.pack("!B", radius_packet.id) + packed_hdr += struct.pack("!H", radius_packet.len) + packed_attrs = '' + for index in range(0, len(radius_packet.attributes)): + packed_attrs = packed_attrs + str(radius_packet.attributes[index]) + + hmac_ = hmac.HMAC( + shared_secret, + hashes.MD5(), + backend=default_backend() + ) + packed_data = packed_hdr + packed_req_authenticator + packed_attrs + hmac_.update(packed_data) + return hmac_.finalize() + + +# +# RADIUS attributes which values are IPv4 prefixes +# + +class _RadiusAttrIPv4AddrVal(RadiusAttribute): + """ + Implements a RADIUS attribute which value field is an IPv4 address. + """ + + __slots__ = ["val"] + + fields_desc = [ + ByteEnumField("type", 4, _radius_attribute_types), + ByteField("len", 6), + IPField("value", "0.0.0.0") + ] + + +class RadiusAttr_NAS_IP_Address(_RadiusAttrIPv4AddrVal): + """RFC 2865""" + val = 4 + + +class RadiusAttr_Framed_IP_Address(_RadiusAttrIPv4AddrVal): + """RFC 2865""" + val = 8 + + +class RadiusAttr_Framed_IP_Netmask(_RadiusAttrIPv4AddrVal): + """RFC 2865""" + val = 9 + + +class RadiusAttr_Login_IP_Host(_RadiusAttrIPv4AddrVal): + """RFC 2865""" + val = 14 + + +class RadiusAttr_Framed_IPX_Network(_RadiusAttrIPv4AddrVal): + """RFC 2865""" + val = 23 + + +class RadiusAttr_PMIP6_Home_LMA_IPv4_Address(_RadiusAttrIPv4AddrVal): + """RFC 6572""" + val = 149 + + +class RadiusAttr_PMIP6_Visited_LMA_IPv4_Address(_RadiusAttrIPv4AddrVal): + """RFC 6572""" + val = 150 + + +class RadiusAttr_PMIP6_Home_DHCP4_Server_Address(_RadiusAttrIPv4AddrVal): + """RFC 6572""" + val = 157 + + +class RadiusAttr_PMIP6_Visited_DHCP4_Server_Address(_RadiusAttrIPv4AddrVal): + """RFC 6572""" + val = 158 + + +class RadiusAttr_PMIP6_Home_IPv4_Gateway(_RadiusAttrIPv4AddrVal): + """RFC 6572""" + val = 161 + + +class RadiusAttr_PMIP6_Visited_IPv4_Gateway(_RadiusAttrIPv4AddrVal): + """RFC 6572""" + val = 162 + + +# See IANA registry "RADIUS Types" +_radius_attrs_values = { + # Service-Type + 6: + { + 1: "Login", + 2: "Framed", + 3: "Callback Login", + 4: "Callback Framed", + 5: "Outbound", + 6: "Administrative", + 7: "NAS Prompt", + 8: "Authenticate Only", + 9: "Callback NAS Prompt", + 10: "Call Check", + 11: "Callback Administrative", + 12: "Voice", + 13: "Fax", + 14: "Modem Relay", + 15: "IAPP-Register", + 16: "IAPP-AP-Check", + 17: "Authorize Only", + 18: "Framed-Management", + 19: "Additional-Authorization" + }, + + # Framed-Protocol + 7: + { + 1: "PPP", + 2: "SLIP", + 3: "AppleTalk Remote Access Protocol (ARAP)", + 4: "Gandalf proprietary SingleLink/MultiLink protocol", + 5: "Xylogics proprietary IPX/SLIP", + 6: "X.75 Synchronous", + 7: "GPRS PDP Context" + }, + + # Framed-Routing + 10: + { + 0: "None", + 1: "Send routing packets", + 2: "Listen for routing packets", + 3: "Send and Listen" + }, + + # Framed-Compression + 13: + { + 0: "None", + 1: "VJ TCP/IP header compression", + 2: "IPX header compression", + 3: "Stac-LZS compression" + }, + + # Login-Service + 15: + { + 0: "Telnet", + 1: "Rlogin", + 2: "TCP Clear", + 3: "PortMaster (proprietary)", + 4: "LAT", + 5: "X25-PAD", + 6: "X25-T3POS", + 7: "Unassigned", + 8: "TCP Clear Quiet (suppresses any NAS-generated connect string)" + }, + + # Termination-Action + 29: + { + 0: "Default", + 1: "RADIUS-Request" + }, + + # Acct-Status-Type + 40: + { + 1: "Start", + 2: "Stop", + 3: "Interim-Update", + 4: "Unassigned", + 5: "Unassigned", + 6: "Unassigned", + 7: "Accounting-On", + 8: "Accounting-Off", + 9: "Tunnel-Start", + 10: "Tunnel-Stop", + 11: "Tunnel-Reject", + 12: "Tunnel-Link-Start", + 13: "Tunnel-Link-Stop", + 14: "Tunnel-Link-Reject", + 15: "Failed" + }, + + # Acct-Authentic + 45: + { + 1: "RADIUS", + 2: "Local", + 3: "Remote", + 4: "Diameter" + }, + + # Acct-Terminate-Cause + 49: + { + 1: "User Request", + 2: "Lost Carrier", + 3: "Lost Service", + 4: "Idle Timeout", + 5: "Session Timeout", + 6: "Admin Reset", + 7: "Admin Reboot", + 8: "Port Error", + 9: "NAS Error", + 10: "NAS Request", + 11: "NAS Reboot", + 12: "Port Unneeded", + 13: "Port Preempted", + 14: "Port Suspended", + 15: "Service Unavailable", + 16: "Callback", + 17: "User Error", + 18: "Host Request", + 19: "Supplicant Restart", + 20: "Reauthentication Failure", + 21: "Port Reinitialized", + 22: "Port Administratively Disabled", + 23: "Lost Power", + }, + + # NAS-Port-Type + 61: + { + 0: "Async", + 1: "Sync", + 2: "ISDN Sync", + 3: "ISDN Async V.120", + 4: "ISDN Async V.110", + 5: "Virtual", + 6: "PIAFS", + 7: "HDLC Clear Channel", + 8: "X.25", + 9: "X.75", + 10: "G.3 Fax", + 11: "SDSL - Symmetric DSL", + 12: "ADSL-CAP - Asymmetric DSL, Carrierless Amplitude Phase Modulation", + 13: "ADSL-DMT - Asymmetric DSL, Discrete Multi-Tone", + 14: "IDSL - ISDN Digital Subscriber Line", + 15: "Ethernet", + 16: "xDSL - Digital Subscriber Line of unknown type", + 17: "Cable", + 18: "Wireles - Other", + 19: "Wireless - IEEE 802.11", + 20: "Token-Ring", + 21: "FDDI", + 22: "Wireless - CDMA2000", + 23: "Wireless - UMTS", + 24: "Wireless - 1X-EV", + 25: "IAPP", + 26: "FTTP - Fiber to the Premises", + 27: "Wireless - IEEE 802.16", + 28: "Wireless - IEEE 802.20", + 29: "Wireless - IEEE 802.22", + 30: "PPPoA - PPP over ATM", + 31: "PPPoEoA - PPP over Ethernet over ATM", + 32: "PPPoEoE - PPP over Ethernet over Ethernet", + 33: "PPPoEoVLAN - PPP over Ethernet over VLAN", + 34: "PPPoEoQinQ - PPP over Ethernet over IEEE 802.1QinQ", + 35: "xPON - Passive Optical Network", + 36: "Wireless - XGP", + 37: "WiMAX Pre-Release 8 IWK Function", + 38: "WIMAX-WIFI-IWK: WiMAX WIFI Interworking", + 39: "WIMAX-SFF: Signaling Forwarding Function for LTE/3GPP2", + 40: "WIMAX-HA-LMA: WiMAX HA and or LMA function", + 41: "WIMAX-DHCP: WIMAX DCHP service", + 42: "WIMAX-LBS: WiMAX location based service", + 43: "WIMAX-WVS: WiMAX voice service" + }, + + # Tunnel-Type + 64: + { + 1: "Point-to-Point Tunneling Protocol (PPTP)", + 2: "Layer Two Forwarding (L2F)", + 3: "Layer Two Tunneling Protocol (L2TP)", + 4: "Ascend Tunnel Management Protocol (ATMP)", + 5: "Virtual Tunneling Protocol (VTP)", + 6: "IP Authentication Header in the Tunnel-mode (AH)", + 7: "IP-in-IP Encapsulation (IP-IP)", + 8: "Minimal IP-in-IP Encapsulation (MIN-IP-IP)", + 9: "IP Encapsulating Security Payload in the Tunnel-mode (ESP)", + 10: "Generic Route Encapsulation (GRE)", + 11: "Bay Dial Virtual Services (DVS)", + 12: "IP-in-IP Tunneling", + 13: "Virtual LANs (VLAN)" + }, + + # Tunnel-Medium-Type + 65: + { + 1: "IPv4 (IP version 4)", + 2: "IPv6 (IP version 6)", + 3: "NSAP", + 4: "HDLC (8-bit multidrop)", + 5: "BBN 1822", + 6: "802", + 7: "E.163 (POTS)", + 8: "E.164 (SMDS, Frame Relay, ATM)", + 9: "F.69 (Telex)", + 10: "X.121 (X.25, Frame Relay)", + 11: "IPX", + 12: "Appletalk", + 13: "Decnet IV", + 14: "Banyan Vine", + 15: "E.164 with NSAP format subaddress" + }, + + # ARAP-Zone-Access + 72: + { + 1: "Only allow access to default zone", + 2: "Use zone filter inclusively", + 3: "Not used", + 4: "Use zone filter exclusively" + }, + + # Prompt + 76: + { + 0: "No Echo", + 1: "Echo" + }, + + # Error-Cause Attribute + 101: + { + 201: "Residual Session Context Removed", + 202: "Invalid EAP Packet (Ignored)", + 401: "Unsupported Attribute", + 402: "Missing Attribute", + 403: "NAS Identification Mismatch", + 404: "Invalid Request", + 405: "Unsupported Service", + 406: "Unsupported Extension", + 407: "Invalid Attribute Value", + 501: "Administratively Prohibited", + 502: "Request Not Routable (Proxy)", + 503: "Session Context Not Found", + 504: "Session Context Not Removable", + 505: "Other Proxy Processing Error", + 506: "Resources Unavailable", + 507: "Request Initiated", + 508: "Multiple Session Selection Unsupported", + 509: "Location-Info-Required", + 601: "Response Too Big" + }, + + # Operator Namespace Identifier - Attribute 126 + 126: + { + 0x30: "TADIG", + 0x31: "REALM", + 0x32: "E212", + 0x33: "ICC", + 0xFF: "Reserved" + }, + + # Basic-Location-Policy-Rules + 129: + { + 0: "Retransmission allowed", + }, + + # Location-Capable + 131: + { + 1: "CIVIC_LOCATION", + 2: "GEO_LOCATION", + 4: "USERS_LOCATION", + 8: "NAS_LOCATION" + }, + + # Framed-Management-Protocol + 133: + { + 1: "SNMP", + 2: "Web-based", + 3: "NETCONF", + 4: "FTP", + 5: "TFTP", + 6: "SFTP", + 7: "RCP", + 8: "SCP" + }, + + # Management-Transport-Protection + 134: + { + 1: "No-Protection", + 2: "Integrity-Protection", + 3: "Integrity-Confidentiality-Protection", + }, +} + + +class _RadiusAttrIntEnumVal(_SpecificRadiusAttr): + """ + Implements a RADIUS attribute which value field is 4 bytes long integer. + """ + + __slots__ = ["val"] + + fields_desc = [ + ByteEnumField("type", 6, _radius_attribute_types), + ByteField("len", 6), + MultiEnumField( + "value", + 0, + _radius_attrs_values, + depends_on=lambda p: p.type, + fmt="I" + ) + ] + + +class RadiusAttr_Service_Type(_RadiusAttrIntEnumVal): + """RFC 2865""" + val = 6 + + +class RadiusAttr_Framed_Protocol(_RadiusAttrIntEnumVal): + """RFC 2865""" + val = 7 + + +class RadiusAttr_NAS_Port_Type(_RadiusAttrIntEnumVal): + """RFC 2865""" + val = 61 + + +class _EAPPacketField(PacketField): + + """ + Handles EAP-Message attribute value (the actual EAP packet). + """ + + def m2i(self, pkt, m): + ret = None + eap_packet_len = struct.unpack("!H", m[2:4])[0] + if eap_packet_len < 254: + # If the EAP packet has not been fragmented, build a Scapy EAP + # packet from the data. + ret = EAP(m) + else: + ret = conf.raw_layer(m) + return ret + + +class RadiusAttr_EAP_Message(RadiusAttribute): + """ + Implements the "EAP-Message" attribute (RFC 3579). + """ + + name = "EAP-Message" + fields_desc = [ + ByteEnumField("type", 79, _radius_attribute_types), + FieldLenField( + "len", + None, + "value", + "B", + adjust=lambda pkt, x: len(pkt.value) + 2 + ), + _EAPPacketField("value", "", EAP) + ] + + +class RadiusAttr_Vendor_Specific(RadiusAttribute): + """ + Implements the "Vendor-Specific" attribute, as described in RFC 2865. + """ + + name = "Vendor-Specific" + fields_desc = [ + ByteEnumField("type", 26, _radius_attribute_types), + FieldLenField( + "len", + None, + "value", + "B", + adjust=lambda pkt, x: len(pkt.value) + 8 + ), + IntField("vendor_id", 0), + ByteField("vendor_type", 0), + FieldLenField( + "vendor_len", + None, + "value", + "B", + adjust=lambda p, x: len(p.value) + 2 + ), + StrLenField("value", "", length_from=lambda p: p.vendor_len - 2) + ] + + +class _RADIUSAttrPacketListField(PacketListField): + """ + PacketListField handling a list of RADIUS attributes. + """ + + def getfield(self, pkt, s): + lst = [] + length = None + ret = "" + + if self.length_from is not None: + length = self.length_from(pkt) + + if length is not None: + remain, ret = s[:length], s[length:] + + while remain: + attr_len = struct.unpack("!B", remain[1])[0] + current = remain[:attr_len] + remain = remain[attr_len:] + packet = self.m2i(pkt, current) + lst.append(packet) + + return remain + ret, lst + + +# See IANA RADIUS Packet Type Codes registry +_packet_codes = { + 1: "Access-Request", + 2: "Access-Accept", + 3: "Access-Reject", + 4: "Accounting-Request", + 5: "Accounting-Response", + 6: "Accounting-Status (now Interim Accounting)", + 7: "Password-Request", + 8: "Password-Ack", + 9: "Password-Reject", + 10: "Accounting-Message", + 11: "Access-Challenge", + 12: "Status-Server (experimental)", + 13: "Status-Client (experimental)", + 21: "Resource-Free-Request", + 22: "Resource-Free-Response", + 23: "Resource-Query-Request", + 24: "Resource-Query-Response", + 25: "Alternate-Resource-Reclaim-Request", + 26: "NAS-Reboot-Request", + 27: "NAS-Reboot-Response", + 28: "Reserved", + 29: "Next-Passcode", + 30: "New-Pin", + 31: "Terminate-Session", + 32: "Password-Expired", + 33: "Event-Request", + 34: "Event-Response", + 40: "Disconnect-Request", + 41: "Disconnect-ACK", + 42: "Disconnect-NAK", + 43: "CoA-Request", + 44: "CoA-ACK", + 45: "CoA-NAK", + 50: "IP-Address-Allocate", + 51: "IP-Address-Release", + 52: "Protocol-Error", + 250: "Experimental Use", + 251: "Experimental Use", + 252: "Experimental Use", + 253: "Experimental Use", + 254: "Reserved", + 255: "Reserved" +} class Radius(Packet): - name = "Radius" - fields_desc = [ ByteEnumField("code", 1, {1: "Access-Request", - 2: "Access-Accept", - 3: "Access-Reject", - 4: "Accounting-Request", - 5: "Accounting-Accept", - 6: "Accounting-Status", - 7: "Password-Request", - 8: "Password-Ack", - 9: "Password-Reject", - 10: "Accounting-Message", - 11: "Access-Challenge", - 12: "Status-Server", - 13: "Status-Client", - 21: "Resource-Free-Request", - 22: "Resource-Free-Response", - 23: "Resource-Query-Request", - 24: "Resource-Query-Response", - 25: "Alternate-Resource-Reclaim-Request", - 26: "NAS-Reboot-Request", - 27: "NAS-Reboot-Response", - 29: "Next-Passcode", - 30: "New-Pin", - 31: "Terminate-Session", - 32: "Password-Expired", - 33: "Event-Request", - 34: "Event-Response", - 40: "Disconnect-Request", - 41: "Disconnect-ACK", - 42: "Disconnect-NAK", - 43: "CoA-Request", - 44: "CoA-ACK", - 45: "CoA-NAK", - 50: "IP-Address-Allocate", - 51: "IP-Address-Release", - 253: "Experimental-use", - 254: "Reserved", - 255: "Reserved"} ), - ByteField("id", 0), - FieldLenField("len", None, "attributes", "H" , adjust=lambda pkt,x:len(pkt.attributes)+20), - StrFixedLenField("authenticator","",16), - PacketListField("attributes", [], RadiusAttribute, length_from=lambda pkt:pkt.len-20) ] + """ + Implements a RADIUS packet (RFC 2865). + """ + + name = "RADIUS" + fields_desc = [ + ByteEnumField("code", 1, _packet_codes), + ByteField("id", 0), + FieldLenField( + "len", + None, + "attributes", + "H", + adjust=lambda pkt, x: len(pkt.attributes) + 20 + ), + XStrFixedLenField("authenticator", "", 16), + _RADIUSAttrPacketListField( + "attributes", + [], + RadiusAttribute, + length_from=lambda pkt: pkt.len - 20 + ) + ] + + def compute_authenticator(self, packed_request_auth, shared_secret): + """ + Computes the authenticator field (RFC 2865 - Section 3) + """ + + if not conf.crypto_valid: + g_log_loading.info(_crypto_loading_failure_message) + return None + + packed_hdr = struct.pack("!B", self.code) + packed_hdr += struct.pack("!B", self.id) + packed_hdr += struct.pack("!H", self.len) + packed_attrs = '' + for index in range(0, len(self.attributes)): + packed_attrs = packed_attrs + str(self.attributes[index]) + packed_data = packed_hdr + packed_request_auth + packed_attrs +\ + shared_secret + + digest = hashes.Hash(hashes.MD5(), backend=default_backend()) + digest.update(packed_data) + return digest.finalize() + def post_build(self, p, pay): p += pay - l = self.len - if l is None: - l = len(p) - p = p[:2]+struct.pack("!H",l)+p[4:] + length = self.len + if length is None: + length = len(p) + p = p[:2] + struct.pack("!H", length) + p[4:] return p diff --git a/test/regression.uts b/test/regression.uts index 02e741310fdf48b8f92765cd0bc9ee7bdee101fe..843088abaefa4f6ac4d768e35482ab4691ef1b82 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -7547,16 +7547,177 @@ RIPEntry in p and RIPAuth in p and p[RIPAuth].password.startswith("scapy") ############ ############ -+ Radius tests ++ RADIUS tests -= Radius - build += IP/UDP/RADIUS - Build s = str(IP()/UDP(sport=1812)/Radius(authenticator="scapy")/RadiusAttribute(value="scapy")) s == b'E\x00\x007\x00\x01\x00\x00@\x11|\xb3\x7f\x00\x00\x01\x7f\x00\x00\x01\x07\x14\x07\x15\x00#U\xb2\x01\x00\x00\x1bscapy\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x07scapy' -= Radius - dissection += IP/UDP/RADIUS - Dissection p = IP(s) Radius in p and len(p[Radius].attributes) == 1 and p[Radius].attributes[0].value == "scapy" += RADIUS - Access-Request - Dissection (1) +s = b'\x01\xae\x01\x17>k\xd4\xc4\x19V\x0b*1\x99\xc8D\xea\xc2\x94Z\x01\x06leap\x06\x06\x00\x00\x00\x02\x1a\x1b\x00\x00\x00\t\x01\x15service-type=Framed\x0c\x06\x00\x00#\xee\x1e\x13AC-7E-8A-4E-E2-92\x1f\x1300-26-73-9E-0F-D3O\x0b\x02\x01\x00\t\x01leapP\x12U\xbc\x12\xcdM\x00\xf8\xdb4\xf1\x18r\xca_\x8c\xf6f\x02\x1a1\x00\x00\x00\t\x01+audit-session-id=0AC8090E0000001A0354CA00\x1a\x14\x00\x00\x00\t\x01\x0emethod=dot1x\x08\x06\xc0\xa8\n\xb9\x04\x06\xc0\xa8\n\x80\x1a\x1d\x00\x00\x00\t\x02\x17GigabitEthernet1/0/18W\x17GigabitEthernet1/0/18=\x06\x00\x00\x00\x0f\x05\x06\x00\x00\xc3\xc6' +radius_packet = Radius(s) +assert(radius_packet.id == 174) +assert(radius_packet.len == 279) +assert(radius_packet.authenticator == b'>k\xd4\xc4\x19V\x0b*1\x99\xc8D\xea\xc2\x94Z') +assert(len(radius_packet.attributes) == 17) +assert(radius_packet.attributes[0].type == 1) +assert(type(radius_packet.attributes[0]) == RadiusAttribute) +assert(radius_packet.attributes[0].len == 6) +assert(radius_packet.attributes[0].value == "leap") +assert(radius_packet.attributes[1].type == 6) +assert(type(radius_packet.attributes[1]) == RadiusAttr_Service_Type) +assert(radius_packet.attributes[1].len == 6) +assert(radius_packet.attributes[1].value == 2) +assert(radius_packet.attributes[2].type == 26) +assert(type(radius_packet.attributes[2]) == RadiusAttr_Vendor_Specific) +assert(radius_packet.attributes[2].len == 27) +assert(radius_packet.attributes[2].vendor_id == 9) +assert(radius_packet.attributes[2].vendor_type == 1) +assert(radius_packet.attributes[2].vendor_len == 21) +assert(radius_packet.attributes[2].value == "service-type=Framed") +assert(radius_packet.attributes[6].type == 79) +assert(type(radius_packet.attributes[6]) == RadiusAttr_EAP_Message) +assert(radius_packet.attributes[6].len == 11) +assert(radius_packet.attributes[6].value.haslayer(EAP)) +assert(radius_packet.attributes[6].value[EAP].code == 2) +assert(radius_packet.attributes[6].value[EAP].id == 1) +assert(radius_packet.attributes[6].value[EAP].len == 9) +assert(radius_packet.attributes[6].value[EAP].type == 1) +assert(hasattr(radius_packet.attributes[6].value[EAP], "identity")) +assert(radius_packet.attributes[6].value[EAP].identity == "leap") +assert(radius_packet.attributes[7].type == 80) +assert(type(radius_packet.attributes[7]) == RadiusAttr_Message_Authenticator) +assert(radius_packet.attributes[7].len == 18) +assert(radius_packet.attributes[7].value == b'U\xbc\x12\xcdM\x00\xf8\xdb4\xf1\x18r\xca_\x8c\xf6') +assert(radius_packet.attributes[11].type == 8) +assert(type(radius_packet.attributes[11]) == RadiusAttr_Framed_IP_Address) +assert(radius_packet.attributes[11].len == 6) +assert(radius_packet.attributes[11].value == '192.168.10.185') +assert(radius_packet.attributes[16].type == 5) +assert(type(radius_packet.attributes[16]) == RadiusAttr_NAS_Port) +assert(radius_packet.attributes[16].len == 6) +assert(radius_packet.attributes[16].value == 50118) + += RADIUS - Access-Challenge - Dissection (2) +s = b'\x0b\xae\x00[\xc7\xae\xfc6\xa1=\xb5\x99&^\xdf=\xe9\x00\xa6\xe8\x12\rHello, leapO\x16\x01\x02\x00\x14\x11\x01\x00\x08\xb8\xc4\x1a4\x97x\xd3\x82leapP\x12\xd3\x12\x17\xa6\x0c.\x94\x85\x03]t\xd1\xdb\xd0\x13\x8c\x18\x12iQs\xf7iSb@k\x9d,\xa0\x99\x8ehO' +radius_packet = Radius(s) +assert(radius_packet.id == 174) +assert(radius_packet.len == 91) +assert(radius_packet.authenticator == b'\xc7\xae\xfc6\xa1=\xb5\x99&^\xdf=\xe9\x00\xa6\xe8') +assert(len(radius_packet.attributes) == 4) +assert(radius_packet.attributes[0].type == 18) +assert(type(radius_packet.attributes[0]) == RadiusAttribute) +assert(radius_packet.attributes[0].len == 13) +assert(radius_packet.attributes[0].value == "Hello, leap") +assert(radius_packet.attributes[1].type == 79) +assert(type(radius_packet.attributes[1]) == RadiusAttr_EAP_Message) +assert(radius_packet.attributes[1].len == 22) +assert(radius_packet.attributes[1][EAP].code == 1) +assert(radius_packet.attributes[1][EAP].id == 2) +assert(radius_packet.attributes[1][EAP].len == 20) +assert(radius_packet.attributes[1][EAP].type == 17) +assert(radius_packet.attributes[2].type == 80) +assert(type(radius_packet.attributes[2]) == RadiusAttr_Message_Authenticator) +assert(radius_packet.attributes[2].len == 18) +assert(radius_packet.attributes[2].value == b'\xd3\x12\x17\xa6\x0c.\x94\x85\x03]t\xd1\xdb\xd0\x13\x8c') +assert(radius_packet.attributes[3].type == 24) +assert(type(radius_packet.attributes[3]) == RadiusAttr_State) +assert(radius_packet.attributes[3].len == 18) +assert(radius_packet.attributes[3].value == b'iQs\xf7iSb@k\x9d,\xa0\x99\x8ehO') + += RADIUS - Access-Request - Dissection (3) +s = b'\x01\xaf\x01DC\xbe!J\x08\xdf\xcf\x9f\x00v~,\xfb\x8e`\xc8\x01\x06leap\x06\x06\x00\x00\x00\x02\x1a\x1b\x00\x00\x00\t\x01\x15service-type=Framed\x0c\x06\x00\x00#\xee\x1e\x13AC-7E-8A-4E-E2-92\x1f\x1300-26-73-9E-0F-D3O&\x02\x02\x00$\x11\x01\x00\x18\rE\xc9\x92\xf6\x9ae\x04\xa2\x06\x13\x8f\x0b#\xf1\xc56\x8eU\xd9\x89\xe5\xa1)leapP\x12|\x1c\x9d[dv\x9c\x19\x96\xc6\xec\xb82\x8f\n f\x02\x1a1\x00\x00\x00\t\x01+audit-session-id=0AC8090E0000001A0354CA00\x1a\x14\x00\x00\x00\t\x01\x0emethod=dot1x\x08\x06\xc0\xa8\n\xb9\x04\x06\xc0\xa8\n\x80\x1a\x1d\x00\x00\x00\t\x02\x17GigabitEthernet1/0/18W\x17GigabitEthernet1/0/18=\x06\x00\x00\x00\x0f\x05\x06\x00\x00\xc3\xc6\x18\x12iQs\xf7iSb@k\x9d,\xa0\x99\x8ehO' +radius_packet = Radius(s) +assert(radius_packet.id == 175) +assert(radius_packet.len == 324) +assert(radius_packet.authenticator == 'C\xbe!J\x08\xdf\xcf\x9f\x00v~,\xfb\x8e`\xc8') +assert(len(radius_packet.attributes) == 18) +assert(radius_packet.attributes[0].type == 1) +assert(type(radius_packet.attributes[0]) == RadiusAttribute) +assert(radius_packet.attributes[0].len == 6) +assert(radius_packet.attributes[0].value == "leap") +assert(radius_packet.attributes[1].type == 6) +assert(type(radius_packet.attributes[1]) == RadiusAttr_Service_Type) +assert(radius_packet.attributes[1].len == 6) +assert(radius_packet.attributes[1].value == 2) +assert(radius_packet.attributes[2].type == 26) +assert(type(radius_packet.attributes[2]) == RadiusAttr_Vendor_Specific) +assert(radius_packet.attributes[2].len == 27) +assert(radius_packet.attributes[2].vendor_id == 9) +assert(radius_packet.attributes[2].vendor_type == 1) +assert(radius_packet.attributes[2].vendor_len == 21) +assert(radius_packet.attributes[2].value == "service-type=Framed") +assert(radius_packet.attributes[6].type == 79) +assert(type(radius_packet.attributes[6]) == RadiusAttr_EAP_Message) +assert(radius_packet.attributes[6].len == 38) +assert(radius_packet.attributes[6].value.haslayer(EAP)) +assert(radius_packet.attributes[6].value[EAP].code == 2) +assert(radius_packet.attributes[6].value[EAP].id == 2) +assert(radius_packet.attributes[6].value[EAP].len == 36) +assert(radius_packet.attributes[6].value[EAP].type == 17) +assert(radius_packet.attributes[7].type == 80) +assert(type(radius_packet.attributes[7]) == RadiusAttr_Message_Authenticator) +assert(radius_packet.attributes[7].len == 18) +assert(radius_packet.attributes[7].value == b'|\x1c\x9d[dv\x9c\x19\x96\xc6\xec\xb82\x8f\n ') +assert(radius_packet.attributes[11].type == 8) +assert(type(radius_packet.attributes[11]) == RadiusAttr_Framed_IP_Address) +assert(radius_packet.attributes[11].len == 6) +assert(radius_packet.attributes[11].value == '192.168.10.185') +assert(radius_packet.attributes[16].type == 5) +assert(type(radius_packet.attributes[16]) == RadiusAttr_NAS_Port) +assert(radius_packet.attributes[16].len == 6) +assert(radius_packet.attributes[16].value == 50118) +assert(radius_packet.attributes[17].type == 24) +assert(type(radius_packet.attributes[17]) == RadiusAttr_State) +assert(radius_packet.attributes[17].len == 18) +assert(radius_packet.attributes[17].value == b'iQs\xf7iSb@k\x9d,\xa0\x99\x8ehO') + += RADIUS - Access-Challenge - Dissection (4) +s = b'\x0b\xaf\x00K\x82 \x95=\xfd\x80\x05 -l}\xab)\xa5kU\x12\rHello, leapO\x06\x03\x03\x00\x04P\x12l0\xb9\x8d\xca\xfc!\xf3\xa7\x08\x80\xe1\xf6}\x84\xff\x18\x12iQs\xf7hRb@k\x9d,\xa0\x99\x8ehO' +radius_packet = Radius(s) +assert(radius_packet.id == 175) +assert(radius_packet.len == 75) +assert(radius_packet.authenticator == b'\x82 \x95=\xfd\x80\x05 -l}\xab)\xa5kU') +assert(len(radius_packet.attributes) == 4) +assert(radius_packet.attributes[0].type == 18) +assert(type(radius_packet.attributes[0]) == RadiusAttribute) +assert(radius_packet.attributes[0].len == 13) +assert(radius_packet.attributes[0].value == "Hello, leap") +assert(radius_packet.attributes[1].type == 79) +assert(type(radius_packet.attributes[1]) == RadiusAttr_EAP_Message) +assert(radius_packet.attributes[1].len == 6) +assert(radius_packet.attributes[1][EAP].code == 3) +assert(radius_packet.attributes[1][EAP].id == 3) +assert(radius_packet.attributes[1][EAP].len == 4) +assert(radius_packet.attributes[2].type == 80) +assert(type(radius_packet.attributes[2]) == RadiusAttr_Message_Authenticator) +assert(radius_packet.attributes[2].len == 18) +assert(radius_packet.attributes[2].value == b'l0\xb9\x8d\xca\xfc!\xf3\xa7\x08\x80\xe1\xf6}\x84\xff') +assert(radius_packet.attributes[3].type == 24) +assert(type(radius_packet.attributes[3]) == RadiusAttr_State) +assert(radius_packet.attributes[3].len == 18) +assert(radius_packet.attributes[3].value == b'iQs\xf7hRb@k\x9d,\xa0\x99\x8ehO') + += RADIUS - Response Authenticator computation +~ crypto +s = b'\x01\xae\x01\x17>k\xd4\xc4\x19V\x0b*1\x99\xc8D\xea\xc2\x94Z\x01\x06leap\x06\x06\x00\x00\x00\x02\x1a\x1b\x00\x00\x00\t\x01\x15service-type=Framed\x0c\x06\x00\x00#\xee\x1e\x13AC-7E-8A-4E-E2-92\x1f\x1300-26-73-9E-0F-D3O\x0b\x02\x01\x00\t\x01leapP\x12U\xbc\x12\xcdM\x00\xf8\xdb4\xf1\x18r\xca_\x8c\xf6f\x02\x1a1\x00\x00\x00\t\x01+audit-session-id=0AC8090E0000001A0354CA00\x1a\x14\x00\x00\x00\t\x01\x0emethod=dot1x\x08\x06\xc0\xa8\n\xb9\x04\x06\xc0\xa8\n\x80\x1a\x1d\x00\x00\x00\t\x02\x17GigabitEthernet1/0/18W\x17GigabitEthernet1/0/18=\x06\x00\x00\x00\x0f\x05\x06\x00\x00\xc3\xc6' +access_request = Radius(s) +s = b'\x0b\xae\x00[\xc7\xae\xfc6\xa1=\xb5\x99&^\xdf=\xe9\x00\xa6\xe8\x12\rHello, leapO\x16\x01\x02\x00\x14\x11\x01\x00\x08\xb8\xc4\x1a4\x97x\xd3\x82leapP\x12\xd3\x12\x17\xa6\x0c.\x94\x85\x03]t\xd1\xdb\xd0\x13\x8c\x18\x12iQs\xf7iSb@k\x9d,\xa0\x99\x8ehO' +access_challenge = Radius(s) +access_challenge.compute_authenticator(access_request.authenticator, "radiuskey") == access_challenge.authenticator + += RADIUS - Layers (1) +radius_attr = RadiusAttr_EAP_Message(value = EAP()) +assert(RadiusAttr_EAP_Message in radius_attr) +assert(RadiusAttribute in radius_attr) +type(radius_attr[RadiusAttribute]) +assert(type(radius_attr[RadiusAttribute]) == RadiusAttr_EAP_Message) +assert(EAP in radius_attr.value) + ############ ############