1## This file is part of Scapy 2## See http://www.secdev.org/projects/scapy for more informations 3## Copyright (C) Philippe Biondi <phil@secdev.org> 4## Vincent Mauge <vmauge.nospam@nospam.gmail.com> 5## This program is published under a GPLv2 license 6 7""" 8RADIUS (Remote Authentication Dial In User Service) 9""" 10 11import struct 12import logging 13import hashlib 14import hmac 15from scapy.compat import * 16from scapy.packet import Packet, bind_layers 17from scapy.fields import ByteField, ByteEnumField, IntField, StrLenField,\ 18 XStrLenField, XStrFixedLenField, FieldLenField, PacketField,\ 19 PacketListField, IPField, MultiEnumField 20from scapy.layers.inet import UDP 21from scapy.layers.eap import EAP 22from scapy.config import conf 23from scapy.error import Scapy_Exception 24 25 26# https://www.iana.org/assignments/radius-types/radius-types.xhtml 27_radius_attribute_types = { 28 1: "User-Name", 29 2: "User-Password", 30 3: "CHAP-Password", 31 4: "NAS-IP-Address", 32 5: "NAS-Port", 33 6: "Service-Type", 34 7: "Framed-Protocol", 35 8: "Framed-IP-Address", 36 9: "Framed-IP-Netmask", 37 10: "Framed-Routing", 38 11: "Filter-Id", 39 12: "Framed-MTU", 40 13: "Framed-Compression", 41 14: "Login-IP-Host", 42 15: "Login-Service", 43 16: "Login-TCP-Port", 44 17: "Unassigned", 45 18: "Reply-Message", 46 19: "Callback-Number", 47 20: "Callback-Id", 48 21: "Unassigned", 49 22: "Framed-Route", 50 23: "Framed-IPX-Network", 51 24: "State", 52 25: "Class", 53 26: "Vendor-Specific", 54 27: "Session-Timeout", 55 28: "Idle-Timeout", 56 29: "Termination-Action", 57 30: "Called-Station-Id", 58 31: "Calling-Station-Id", 59 32: "NAS-Identifier", 60 33: "Proxy-State", 61 34: "Login-LAT-Service", 62 35: "Login-LAT-Node", 63 36: "Login-LAT-Group", 64 37: "Framed-AppleTalk-Link", 65 38: "Framed-AppleTalk-Network", 66 39: "Framed-AppleTalk-Zone", 67 40: "Acct-Status-Type", 68 41: "Acct-Delay-Time", 69 42: "Acct-Input-Octets", 70 43: "Acct-Output-Octets", 71 44: "Acct-Session-Id", 72 45: "Acct-Authentic", 73 46: "Acct-Session-Time", 74 47: "Acct-Input-Packets", 75 48: "Acct-Output-Packets", 76 49: "Acct-Terminate-Cause", 77 50: "Acct-Multi-Session-Id", 78 51: "Acct-Link-Count", 79 52: "Acct-Input-Gigawords", 80 53: "Acct-Output-Gigawords", 81 54: "Unassigned", 82 55: "Event-Timestamp", 83 56: "Egress-VLANID", 84 57: "Ingress-Filters", 85 58: "Egress-VLAN-Name", 86 59: "User-Priority-Table", 87 60: "CHAP-Challenge", 88 61: "NAS-Port-Type", 89 62: "Port-Limit", 90 63: "Login-LAT-Port", 91 64: "Tunnel-Type", 92 65: "Tunnel-Medium-Type", 93 66: "Tunnel-Client-Endpoint", 94 67: "Tunnel-Server-Endpoint", 95 68: "Acct-Tunnel-Connection", 96 69: "Tunnel-Password", 97 70: "ARAP-Password", 98 71: "ARAP-Features", 99 72: "ARAP-Zone-Access", 100 73: "ARAP-Security", 101 74: "ARAP-Security-Data", 102 75: "Password-Retry", 103 76: "Prompt", 104 77: "Connect-Info", 105 78: "Configuration-Token", 106 79: "EAP-Message", 107 80: "Message-Authenticator", 108 81: "Tunnel-Private-Group-ID", 109 82: "Tunnel-Assignment-ID", 110 83: "Tunnel-Preference", 111 84: "ARAP-Challenge-Response", 112 85: "Acct-Interim-Interval", 113 86: "Acct-Tunnel-Packets-Lost", 114 87: "NAS-Port-Id", 115 88: "Framed-Pool", 116 89: "CUI", 117 90: "Tunnel-Client-Auth-ID", 118 91: "Tunnel-Server-Auth-ID", 119 92: "NAS-Filter-Rule", 120 93: "Unassigned", 121 94: "Originating-Line-Info", 122 95: "NAS-IPv6-Address", 123 96: "Framed-Interface-Id", 124 97: "Framed-IPv6-Prefix", 125 98: "Login-IPv6-Host", 126 99: "Framed-IPv6-Route", 127 100: "Framed-IPv6-Pool", 128 101: "Error-Cause", 129 102: "EAP-Key-Name", 130 103: "Digest-Response", 131 104: "Digest-Realm", 132 105: "Digest-Nonce", 133 106: "Digest-Response-Auth", 134 107: "Digest-Nextnonce", 135 108: "Digest-Method", 136 109: "Digest-URI", 137 110: "Digest-Qop", 138 111: "Digest-Algorithm", 139 112: "Digest-Entity-Body-Hash", 140 113: "Digest-CNonce", 141 114: "Digest-Nonce-Count", 142 115: "Digest-Username", 143 116: "Digest-Opaque", 144 117: "Digest-Auth-Param", 145 118: "Digest-AKA-Auts", 146 119: "Digest-Domain", 147 120: "Digest-Stale", 148 121: "Digest-HA1", 149 122: "SIP-AOR", 150 123: "Delegated-IPv6-Prefix", 151 124: "MIP6-Feature-Vector", 152 125: "MIP6-Home-Link-Prefix", 153 126: "Operator-Name", 154 127: "Location-Information", 155 128: "Location-Data", 156 129: "Basic-Location-Policy-Rules", 157 130: "Extended-Location-Policy-Rules", 158 131: "Location-Capable", 159 132: "Requested-Location-Info", 160 133: "Framed-Management-Protocol", 161 134: "Management-Transport-Protection", 162 135: "Management-Policy-Id", 163 136: "Management-Privilege-Level", 164 137: "PKM-SS-Cert", 165 138: "PKM-CA-Cert", 166 139: "PKM-Config-Settings", 167 140: "PKM-Cryptosuite-List", 168 141: "PKM-SAID", 169 142: "PKM-SA-Descriptor", 170 143: "PKM-Auth-Key", 171 144: "DS-Lite-Tunnel-Name", 172 145: "Mobile-Node-Identifier", 173 146: "Service-Selection", 174 147: "PMIP6-Home-LMA-IPv6-Address", 175 148: "PMIP6-Visited-LMA-IPv6-Address", 176 149: "PMIP6-Home-LMA-IPv4-Address", 177 150: "PMIP6-Visited-LMA-IPv4-Address", 178 151: "PMIP6-Home-HN-Prefix", 179 152: "PMIP6-Visited-HN-Prefix", 180 153: "PMIP6-Home-Interface-ID", 181 154: "PMIP6-Visited-Interface-ID", 182 155: "PMIP6-Home-IPv4-HoA", 183 156: "PMIP6-Visited-IPv4-HoA", 184 157: "PMIP6-Home-DHCP4-Server-Address", 185 158: "PMIP6-Visited-DHCP4-Server-Address", 186 159: "PMIP6-Home-DHCP6-Server-Address", 187 160: "PMIP6-Visited-DHCP6-Server-Address", 188 161: "PMIP6-Home-IPv4-Gateway", 189 162: "PMIP6-Visited-IPv4-Gateway", 190 163: "EAP-Lower-Layer", 191 164: "GSS-Acceptor-Service-Name", 192 165: "GSS-Acceptor-Host-Name", 193 166: "GSS-Acceptor-Service-Specifics", 194 167: "GSS-Acceptor-Realm-Name", 195 168: "Framed-IPv6-Address", 196 169: "DNS-Server-IPv6-Address", 197 170: "Route-IPv6-Information", 198 171: "Delegated-IPv6-Prefix-Pool", 199 172: "Stateful-IPv6-Address-Pool", 200 173: "IPv6-6rd-Configuration", 201 174: "Allowed-Called-Station-Id", 202 175: "EAP-Peer-Id", 203 176: "EAP-Server-Id", 204 177: "Mobility-Domain-Id", 205 178: "Preauth-Timeout", 206 179: "Network-Id-Name", 207 180: "EAPoL-Announcement", 208 181: "WLAN-HESSID", 209 182: "WLAN-Venue-Info", 210 183: "WLAN-Venue-Language", 211 184: "WLAN-Venue-Name", 212 185: "WLAN-Reason-Code", 213 186: "WLAN-Pairwise-Cipher", 214 187: "WLAN-Group-Cipher", 215 188: "WLAN-AKM-Suite", 216 189: "WLAN-Group-Mgmt-Cipher", 217 190: "WLAN-RF-Band", 218 191: "Unassigned", 219} 220 221 222class RadiusAttribute(Packet): 223 """ 224 Implements a RADIUS attribute (RFC 2865). Every specific RADIUS attribute 225 class should inherit from this one. 226 """ 227 228 name = "Radius Attribute" 229 fields_desc = [ 230 ByteEnumField("type", 1, _radius_attribute_types), 231 FieldLenField("len", None, "value", "B", 232 adjust=lambda pkt, x: len(pkt.value) + 2), 233 StrLenField("value", "", length_from=lambda pkt: pkt.len - 2) 234 ] 235 236 registered_attributes = {} 237 238 @classmethod 239 def register_variant(cls): 240 """ 241 Registers the RADIUS attributes defined in this module. 242 """ 243 244 if hasattr(cls, "val"): 245 cls.registered_attributes[cls.val] = cls 246 else: 247 cls.registered_attributes[cls.type.default] = cls 248 249 @classmethod 250 def dispatch_hook(cls, _pkt=None, *args, **kargs): 251 """ 252 Returns the right RadiusAttribute class for the given data. 253 """ 254 255 if _pkt: 256 attr_type = orb(_pkt[0]) 257 return cls.registered_attributes.get(attr_type, cls) 258 return cls 259 260 def haslayer(self, cls): 261 if cls == "RadiusAttribute": 262 if isinstance(self, RadiusAttribute): 263 return True 264 elif issubclass(cls, RadiusAttribute): 265 if isinstance(self, cls): 266 return True 267 return super(RadiusAttribute, self).haslayer(cls) 268 269 def getlayer(self, cls, nb=1, _track=None, _subclass=True, **flt): 270 return super(RadiusAttribute, self).getlayer(cls, nb=nb, _track=_track, 271 _subclass=True, **flt) 272 273 def post_build(self, p, pay): 274 length = self.len 275 if length is None: 276 length = len(p) 277 p = p[:1] + struct.pack("!B", length) + p[2:] 278 return p 279 280 281class _SpecificRadiusAttr(RadiusAttribute): 282 """ 283 Class from which every "specific" RADIUS attribute defined in this module 284 inherits. 285 """ 286 287 __slots__ = ["val"] 288 289 def __init__(self, _pkt="", post_transform=None, _internal=0, _underlayer=None, **fields): 290 super(_SpecificRadiusAttr, self).__init__( 291 _pkt, 292 post_transform, 293 _internal, 294 _underlayer 295 ) 296 self.fields["type"] = self.val 297 name_parts = self.__class__.__name__.split('RadiusAttr_') 298 if len(name_parts) < 2: 299 raise Scapy_Exception( 300 "Invalid class name: {}".format(self.__class__.__name__) 301 ) 302 self.name = name_parts[1].replace('_', '-') 303 304 305# 306# RADIUS attributes which values are 4 bytes integers 307# 308 309class _RadiusAttrIntValue(_SpecificRadiusAttr): 310 """ 311 Implements a RADIUS attribute which value field is 4 bytes long integer. 312 """ 313 314 fields_desc = [ 315 ByteEnumField("type", 5, _radius_attribute_types), 316 ByteField("len", 6), 317 IntField("value", 0) 318 ] 319 320 321class RadiusAttr_NAS_Port(_RadiusAttrIntValue): 322 """RFC 2865""" 323 val = 5 324 325 326class RadiusAttr_Framed_MTU(_RadiusAttrIntValue): 327 """RFC 2865""" 328 val = 12 329 330 331class RadiusAttr_Login_TCP_Port(_RadiusAttrIntValue): 332 """RFC 2865""" 333 val = 16 334 335 336class RadiusAttr_Session_Timeout(_RadiusAttrIntValue): 337 """RFC 2865""" 338 val = 27 339 340 341class RadiusAttr_Idle_Timeout(_RadiusAttrIntValue): 342 """RFC 2865""" 343 val = 28 344 345 346class RadiusAttr_Framed_AppleTalk_Link(_RadiusAttrIntValue): 347 """RFC 2865""" 348 val = 37 349 350 351class RadiusAttr_Framed_AppleTalk_Network(_RadiusAttrIntValue): 352 """RFC 2865""" 353 val = 38 354 355 356class RadiusAttr_Acct_Delay_Time(_RadiusAttrIntValue): 357 """RFC 2866""" 358 val = 41 359 360 361class RadiusAttr_Acct_Input_Octets(_RadiusAttrIntValue): 362 """RFC 2866""" 363 val = 42 364 365 366class RadiusAttr_Acct_Output_Octets(_RadiusAttrIntValue): 367 """RFC 2866""" 368 val = 43 369 370 371class RadiusAttr_Acct_Session_Time(_RadiusAttrIntValue): 372 """RFC 2866""" 373 val = 46 374 375 376class RadiusAttr_Acct_Input_Packets(_RadiusAttrIntValue): 377 """RFC 2866""" 378 val = 47 379 380 381class RadiusAttr_Acct_Output_Packets(_RadiusAttrIntValue): 382 """RFC 2866""" 383 val = 48 384 385 386class RadiusAttr_Acct_Link_Count(_RadiusAttrIntValue): 387 """RFC 2866""" 388 val = 51 389 390 391class RadiusAttr_Acct_Input_Gigawords(_RadiusAttrIntValue): 392 """RFC 2869""" 393 val = 52 394 395 396class RadiusAttr_Acct_Output_Gigawords(_RadiusAttrIntValue): 397 """RFC 2869""" 398 val = 53 399 400 401class RadiusAttr_Egress_VLANID(_RadiusAttrIntValue): 402 """RFC 4675""" 403 val = 56 404 405 406class RadiusAttr_Port_Limit(_RadiusAttrIntValue): 407 """RFC 2865""" 408 val = 62 409 410 411class RadiusAttr_ARAP_Security(_RadiusAttrIntValue): 412 """RFC 2869""" 413 val = 73 414 415 416class RadiusAttr_Password_Retry(_RadiusAttrIntValue): 417 """RFC 2869""" 418 val = 75 419 420 421class RadiusAttr_Tunnel_Preference(_RadiusAttrIntValue): 422 """RFC 2868""" 423 val = 83 424 425 426class RadiusAttr_Acct_Interim_Interval(_RadiusAttrIntValue): 427 """RFC 2869""" 428 val = 85 429 430 431class RadiusAttr_Acct_Tunnel_Packets_Lost(_RadiusAttrIntValue): 432 """RFC 2867""" 433 val = 86 434 435 436class RadiusAttr_Management_Privilege_Level(_RadiusAttrIntValue): 437 """RFC 5607""" 438 val = 136 439 440 441class RadiusAttr_Mobility_Domain_Id(_RadiusAttrIntValue): 442 """RFC 7268""" 443 val = 177 444 445 446class RadiusAttr_Preauth_Timeout(_RadiusAttrIntValue): 447 """RFC 7268""" 448 val = 178 449 450 451class RadiusAttr_WLAN_Venue_Info(_RadiusAttrIntValue): 452 """RFC 7268""" 453 val = 182 454 455 456class RadiusAttr_WLAN_Reason_Code(_RadiusAttrIntValue): 457 """RFC 7268""" 458 val = 185 459 460 461class RadiusAttr_WLAN_Pairwise_Cipher(_RadiusAttrIntValue): 462 """RFC 7268""" 463 val = 186 464 465 466class RadiusAttr_WLAN_Group_Cipher(_RadiusAttrIntValue): 467 """RFC 7268""" 468 val = 187 469 470 471class RadiusAttr_WLAN_AKM_Suite(_RadiusAttrIntValue): 472 """RFC 7268""" 473 val = 188 474 475 476class RadiusAttr_WLAN_Group_Mgmt_Cipher(_RadiusAttrIntValue): 477 """RFC 7268""" 478 val = 189 479 480 481class RadiusAttr_WLAN_RF_Band(_RadiusAttrIntValue): 482 """RFC 7268""" 483 val = 190 484 485 486# 487# RADIUS attributes which values are string (displayed as hex) 488# 489 490class _RadiusAttrHexStringVal(_SpecificRadiusAttr): 491 """ 492 Implements a RADIUS attribute which value field is a string that will be 493 as a hex string. 494 """ 495 496 __slots__ = ["val"] 497 498 def __init__(self, _pkt="", post_transform=None, _internal=0, _underlayer=None, **fields): 499 super(_RadiusAttrHexStringVal, self).__init__( 500 _pkt, 501 post_transform, 502 _internal, 503 _underlayer 504 ) 505 self.fields["type"] = self.val 506 name_parts = self.__class__.__name__.split('RadiusAttr_') 507 if len(name_parts) < 2: 508 raise Scapy_Exception( 509 "Invalid class name: {}".format(self.__class__.__name__) 510 ) 511 self.name = name_parts[1].replace('_', '-') 512 513 fields_desc = [ 514 ByteEnumField("type", 24, _radius_attribute_types), 515 FieldLenField( 516 "len", 517 None, 518 "value", 519 "B", 520 adjust=lambda p, x: len(p.value) + 2 521 ), 522 XStrLenField("value", "", length_from=lambda p: p.len - 2 if p.len else 0) 523 ] 524 525 526class RadiusAttr_State(_RadiusAttrHexStringVal): 527 """RFC 2865""" 528 val = 24 529 530 531 532def prepare_packed_data(radius_packet, packed_req_authenticator): 533 """ 534 Pack RADIUS data prior computing the authentication MAC 535 """ 536 537 packed_hdr = struct.pack("!B", radius_packet.code) 538 packed_hdr += struct.pack("!B", radius_packet.id) 539 packed_hdr += struct.pack("!H", radius_packet.len) 540 541 packed_attrs = b'' 542 for attr in radius_packet.attributes: 543 packed_attrs += raw(attr) 544 545 return packed_hdr + packed_req_authenticator + packed_attrs 546 547 548class RadiusAttr_Message_Authenticator(_RadiusAttrHexStringVal): 549 """RFC 2869""" 550 val = 80 551 552 fields_desc = [ 553 ByteEnumField("type", 24, _radius_attribute_types), 554 FieldLenField( 555 "len", 556 18, 557 "value", 558 "B", 559 ), 560 XStrFixedLenField("value", "\x00" * 16, length=16) 561 ] 562 563 @staticmethod 564 def compute_message_authenticator(radius_packet, packed_req_authenticator, 565 shared_secret): 566 """ 567 Computes the "Message-Authenticator" of a given RADIUS packet. 568 """ 569 570 data = prepare_packed_data(radius_packet, packed_req_authenticator) 571 radius_hmac = hmac.new(shared_secret, data, hashlib.md5) 572 573 return radius_hmac.digest() 574 575# 576# RADIUS attributes which values are IPv4 prefixes 577# 578 579class _RadiusAttrIPv4AddrVal(RadiusAttribute): 580 """ 581 Implements a RADIUS attribute which value field is an IPv4 address. 582 """ 583 584 __slots__ = ["val"] 585 586 fields_desc = [ 587 ByteEnumField("type", 4, _radius_attribute_types), 588 ByteField("len", 6), 589 IPField("value", "0.0.0.0") 590 ] 591 592 593class RadiusAttr_NAS_IP_Address(_RadiusAttrIPv4AddrVal): 594 """RFC 2865""" 595 val = 4 596 597 598class RadiusAttr_Framed_IP_Address(_RadiusAttrIPv4AddrVal): 599 """RFC 2865""" 600 val = 8 601 602 603class RadiusAttr_Framed_IP_Netmask(_RadiusAttrIPv4AddrVal): 604 """RFC 2865""" 605 val = 9 606 607 608class RadiusAttr_Login_IP_Host(_RadiusAttrIPv4AddrVal): 609 """RFC 2865""" 610 val = 14 611 612 613class RadiusAttr_Framed_IPX_Network(_RadiusAttrIPv4AddrVal): 614 """RFC 2865""" 615 val = 23 616 617 618class RadiusAttr_PMIP6_Home_LMA_IPv4_Address(_RadiusAttrIPv4AddrVal): 619 """RFC 6572""" 620 val = 149 621 622 623class RadiusAttr_PMIP6_Visited_LMA_IPv4_Address(_RadiusAttrIPv4AddrVal): 624 """RFC 6572""" 625 val = 150 626 627 628class RadiusAttr_PMIP6_Home_DHCP4_Server_Address(_RadiusAttrIPv4AddrVal): 629 """RFC 6572""" 630 val = 157 631 632 633class RadiusAttr_PMIP6_Visited_DHCP4_Server_Address(_RadiusAttrIPv4AddrVal): 634 """RFC 6572""" 635 val = 158 636 637 638class RadiusAttr_PMIP6_Home_IPv4_Gateway(_RadiusAttrIPv4AddrVal): 639 """RFC 6572""" 640 val = 161 641 642 643class RadiusAttr_PMIP6_Visited_IPv4_Gateway(_RadiusAttrIPv4AddrVal): 644 """RFC 6572""" 645 val = 162 646 647 648# See IANA registry "RADIUS Types" 649_radius_attrs_values = { 650 # Service-Type 651 6: 652 { 653 1: "Login", 654 2: "Framed", 655 3: "Callback Login", 656 4: "Callback Framed", 657 5: "Outbound", 658 6: "Administrative", 659 7: "NAS Prompt", 660 8: "Authenticate Only", 661 9: "Callback NAS Prompt", 662 10: "Call Check", 663 11: "Callback Administrative", 664 12: "Voice", 665 13: "Fax", 666 14: "Modem Relay", 667 15: "IAPP-Register", 668 16: "IAPP-AP-Check", 669 17: "Authorize Only", 670 18: "Framed-Management", 671 19: "Additional-Authorization" 672 }, 673 674 # Framed-Protocol 675 7: 676 { 677 1: "PPP", 678 2: "SLIP", 679 3: "AppleTalk Remote Access Protocol (ARAP)", 680 4: "Gandalf proprietary SingleLink/MultiLink protocol", 681 5: "Xylogics proprietary IPX/SLIP", 682 6: "X.75 Synchronous", 683 7: "GPRS PDP Context" 684 }, 685 686 # Framed-Routing 687 10: 688 { 689 0: "None", 690 1: "Send routing packets", 691 2: "Listen for routing packets", 692 3: "Send and Listen" 693 }, 694 695 # Framed-Compression 696 13: 697 { 698 0: "None", 699 1: "VJ TCP/IP header compression", 700 2: "IPX header compression", 701 3: "Stac-LZS compression" 702 }, 703 704 # Login-Service 705 15: 706 { 707 0: "Telnet", 708 1: "Rlogin", 709 2: "TCP Clear", 710 3: "PortMaster (proprietary)", 711 4: "LAT", 712 5: "X25-PAD", 713 6: "X25-T3POS", 714 7: "Unassigned", 715 8: "TCP Clear Quiet (suppresses any NAS-generated connect string)" 716 }, 717 718 # Termination-Action 719 29: 720 { 721 0: "Default", 722 1: "RADIUS-Request" 723 }, 724 725 # Acct-Status-Type 726 40: 727 { 728 1: "Start", 729 2: "Stop", 730 3: "Interim-Update", 731 4: "Unassigned", 732 5: "Unassigned", 733 6: "Unassigned", 734 7: "Accounting-On", 735 8: "Accounting-Off", 736 9: "Tunnel-Start", 737 10: "Tunnel-Stop", 738 11: "Tunnel-Reject", 739 12: "Tunnel-Link-Start", 740 13: "Tunnel-Link-Stop", 741 14: "Tunnel-Link-Reject", 742 15: "Failed" 743 }, 744 745 # Acct-Authentic 746 45: 747 { 748 1: "RADIUS", 749 2: "Local", 750 3: "Remote", 751 4: "Diameter" 752 }, 753 754 # Acct-Terminate-Cause 755 49: 756 { 757 1: "User Request", 758 2: "Lost Carrier", 759 3: "Lost Service", 760 4: "Idle Timeout", 761 5: "Session Timeout", 762 6: "Admin Reset", 763 7: "Admin Reboot", 764 8: "Port Error", 765 9: "NAS Error", 766 10: "NAS Request", 767 11: "NAS Reboot", 768 12: "Port Unneeded", 769 13: "Port Preempted", 770 14: "Port Suspended", 771 15: "Service Unavailable", 772 16: "Callback", 773 17: "User Error", 774 18: "Host Request", 775 19: "Supplicant Restart", 776 20: "Reauthentication Failure", 777 21: "Port Reinitialized", 778 22: "Port Administratively Disabled", 779 23: "Lost Power", 780 }, 781 782 # NAS-Port-Type 783 61: 784 { 785 0: "Async", 786 1: "Sync", 787 2: "ISDN Sync", 788 3: "ISDN Async V.120", 789 4: "ISDN Async V.110", 790 5: "Virtual", 791 6: "PIAFS", 792 7: "HDLC Clear Channel", 793 8: "X.25", 794 9: "X.75", 795 10: "G.3 Fax", 796 11: "SDSL - Symmetric DSL", 797 12: "ADSL-CAP - Asymmetric DSL, Carrierless Amplitude Phase Modulation", 798 13: "ADSL-DMT - Asymmetric DSL, Discrete Multi-Tone", 799 14: "IDSL - ISDN Digital Subscriber Line", 800 15: "Ethernet", 801 16: "xDSL - Digital Subscriber Line of unknown type", 802 17: "Cable", 803 18: "Wireles - Other", 804 19: "Wireless - IEEE 802.11", 805 20: "Token-Ring", 806 21: "FDDI", 807 22: "Wireless - CDMA2000", 808 23: "Wireless - UMTS", 809 24: "Wireless - 1X-EV", 810 25: "IAPP", 811 26: "FTTP - Fiber to the Premises", 812 27: "Wireless - IEEE 802.16", 813 28: "Wireless - IEEE 802.20", 814 29: "Wireless - IEEE 802.22", 815 30: "PPPoA - PPP over ATM", 816 31: "PPPoEoA - PPP over Ethernet over ATM", 817 32: "PPPoEoE - PPP over Ethernet over Ethernet", 818 33: "PPPoEoVLAN - PPP over Ethernet over VLAN", 819 34: "PPPoEoQinQ - PPP over Ethernet over IEEE 802.1QinQ", 820 35: "xPON - Passive Optical Network", 821 36: "Wireless - XGP", 822 37: "WiMAX Pre-Release 8 IWK Function", 823 38: "WIMAX-WIFI-IWK: WiMAX WIFI Interworking", 824 39: "WIMAX-SFF: Signaling Forwarding Function for LTE/3GPP2", 825 40: "WIMAX-HA-LMA: WiMAX HA and or LMA function", 826 41: "WIMAX-DHCP: WIMAX DCHP service", 827 42: "WIMAX-LBS: WiMAX location based service", 828 43: "WIMAX-WVS: WiMAX voice service" 829 }, 830 831 # Tunnel-Type 832 64: 833 { 834 1: "Point-to-Point Tunneling Protocol (PPTP)", 835 2: "Layer Two Forwarding (L2F)", 836 3: "Layer Two Tunneling Protocol (L2TP)", 837 4: "Ascend Tunnel Management Protocol (ATMP)", 838 5: "Virtual Tunneling Protocol (VTP)", 839 6: "IP Authentication Header in the Tunnel-mode (AH)", 840 7: "IP-in-IP Encapsulation (IP-IP)", 841 8: "Minimal IP-in-IP Encapsulation (MIN-IP-IP)", 842 9: "IP Encapsulating Security Payload in the Tunnel-mode (ESP)", 843 10: "Generic Route Encapsulation (GRE)", 844 11: "Bay Dial Virtual Services (DVS)", 845 12: "IP-in-IP Tunneling", 846 13: "Virtual LANs (VLAN)" 847 }, 848 849 # Tunnel-Medium-Type 850 65: 851 { 852 1: "IPv4 (IP version 4)", 853 2: "IPv6 (IP version 6)", 854 3: "NSAP", 855 4: "HDLC (8-bit multidrop)", 856 5: "BBN 1822", 857 6: "802", 858 7: "E.163 (POTS)", 859 8: "E.164 (SMDS, Frame Relay, ATM)", 860 9: "F.69 (Telex)", 861 10: "X.121 (X.25, Frame Relay)", 862 11: "IPX", 863 12: "Appletalk", 864 13: "Decnet IV", 865 14: "Banyan Vine", 866 15: "E.164 with NSAP format subaddress" 867 }, 868 869 # ARAP-Zone-Access 870 72: 871 { 872 1: "Only allow access to default zone", 873 2: "Use zone filter inclusively", 874 3: "Not used", 875 4: "Use zone filter exclusively" 876 }, 877 878 # Prompt 879 76: 880 { 881 0: "No Echo", 882 1: "Echo" 883 }, 884 885 # Error-Cause Attribute 886 101: 887 { 888 201: "Residual Session Context Removed", 889 202: "Invalid EAP Packet (Ignored)", 890 401: "Unsupported Attribute", 891 402: "Missing Attribute", 892 403: "NAS Identification Mismatch", 893 404: "Invalid Request", 894 405: "Unsupported Service", 895 406: "Unsupported Extension", 896 407: "Invalid Attribute Value", 897 501: "Administratively Prohibited", 898 502: "Request Not Routable (Proxy)", 899 503: "Session Context Not Found", 900 504: "Session Context Not Removable", 901 505: "Other Proxy Processing Error", 902 506: "Resources Unavailable", 903 507: "Request Initiated", 904 508: "Multiple Session Selection Unsupported", 905 509: "Location-Info-Required", 906 601: "Response Too Big" 907 }, 908 909 # Operator Namespace Identifier - Attribute 126 910 126: 911 { 912 0x30: "TADIG", 913 0x31: "REALM", 914 0x32: "E212", 915 0x33: "ICC", 916 0xFF: "Reserved" 917 }, 918 919 # Basic-Location-Policy-Rules 920 129: 921 { 922 0: "Retransmission allowed", 923 }, 924 925 # Location-Capable 926 131: 927 { 928 1: "CIVIC_LOCATION", 929 2: "GEO_LOCATION", 930 4: "USERS_LOCATION", 931 8: "NAS_LOCATION" 932 }, 933 934 # Framed-Management-Protocol 935 133: 936 { 937 1: "SNMP", 938 2: "Web-based", 939 3: "NETCONF", 940 4: "FTP", 941 5: "TFTP", 942 6: "SFTP", 943 7: "RCP", 944 8: "SCP" 945 }, 946 947 # Management-Transport-Protection 948 134: 949 { 950 1: "No-Protection", 951 2: "Integrity-Protection", 952 3: "Integrity-Confidentiality-Protection", 953 }, 954} 955 956 957class _RadiusAttrIntEnumVal(_SpecificRadiusAttr): 958 """ 959 Implements a RADIUS attribute which value field is 4 bytes long integer. 960 """ 961 962 __slots__ = ["val"] 963 964 fields_desc = [ 965 ByteEnumField("type", 6, _radius_attribute_types), 966 ByteField("len", 6), 967 MultiEnumField( 968 "value", 969 0, 970 _radius_attrs_values, 971 depends_on=lambda p: p.type, 972 fmt="I" 973 ) 974 ] 975 976 977class RadiusAttr_Service_Type(_RadiusAttrIntEnumVal): 978 """RFC 2865""" 979 val = 6 980 981 982class RadiusAttr_Framed_Protocol(_RadiusAttrIntEnumVal): 983 """RFC 2865""" 984 val = 7 985 986 987class RadiusAttr_NAS_Port_Type(_RadiusAttrIntEnumVal): 988 """RFC 2865""" 989 val = 61 990 991 992class _EAPPacketField(PacketField): 993 994 """ 995 Handles EAP-Message attribute value (the actual EAP packet). 996 """ 997 998 def m2i(self, pkt, m): 999 ret = None 1000 eap_packet_len = struct.unpack("!H", m[2:4])[0] 1001 if eap_packet_len < 254: 1002 # If the EAP packet has not been fragmented, build a Scapy EAP 1003 # packet from the data. 1004 ret = EAP(m) 1005 else: 1006 ret = conf.raw_layer(m) 1007 return ret 1008 1009 1010class RadiusAttr_EAP_Message(RadiusAttribute): 1011 """ 1012 Implements the "EAP-Message" attribute (RFC 3579). 1013 """ 1014 1015 name = "EAP-Message" 1016 fields_desc = [ 1017 ByteEnumField("type", 79, _radius_attribute_types), 1018 FieldLenField( 1019 "len", 1020 None, 1021 "value", 1022 "B", 1023 adjust=lambda pkt, x: len(pkt.value) + 2 1024 ), 1025 _EAPPacketField("value", "", EAP) 1026 ] 1027 1028 1029class RadiusAttr_Vendor_Specific(RadiusAttribute): 1030 """ 1031 Implements the "Vendor-Specific" attribute, as described in RFC 2865. 1032 """ 1033 1034 name = "Vendor-Specific" 1035 fields_desc = [ 1036 ByteEnumField("type", 26, _radius_attribute_types), 1037 FieldLenField( 1038 "len", 1039 None, 1040 "value", 1041 "B", 1042 adjust=lambda pkt, x: len(pkt.value) + 8 1043 ), 1044 IntField("vendor_id", 0), 1045 ByteField("vendor_type", 0), 1046 FieldLenField( 1047 "vendor_len", 1048 None, 1049 "value", 1050 "B", 1051 adjust=lambda p, x: len(p.value) + 2 1052 ), 1053 StrLenField("value", "", length_from=lambda p: p.vendor_len - 2) 1054 ] 1055 1056 1057class _RADIUSAttrPacketListField(PacketListField): 1058 """ 1059 PacketListField handling a list of RADIUS attributes. 1060 """ 1061 1062 def getfield(self, pkt, s): 1063 lst = [] 1064 length = None 1065 ret = "" 1066 1067 if self.length_from is not None: 1068 length = self.length_from(pkt) 1069 1070 if length is not None: 1071 remain, ret = s[:length], s[length:] 1072 1073 while remain: 1074 attr_len = orb(remain[1]) 1075 current = remain[:attr_len] 1076 remain = remain[attr_len:] 1077 packet = self.m2i(pkt, current) 1078 lst.append(packet) 1079 1080 return remain + ret, lst 1081 1082 1083# See IANA RADIUS Packet Type Codes registry 1084_packet_codes = { 1085 1: "Access-Request", 1086 2: "Access-Accept", 1087 3: "Access-Reject", 1088 4: "Accounting-Request", 1089 5: "Accounting-Response", 1090 6: "Accounting-Status (now Interim Accounting)", 1091 7: "Password-Request", 1092 8: "Password-Ack", 1093 9: "Password-Reject", 1094 10: "Accounting-Message", 1095 11: "Access-Challenge", 1096 12: "Status-Server (experimental)", 1097 13: "Status-Client (experimental)", 1098 21: "Resource-Free-Request", 1099 22: "Resource-Free-Response", 1100 23: "Resource-Query-Request", 1101 24: "Resource-Query-Response", 1102 25: "Alternate-Resource-Reclaim-Request", 1103 26: "NAS-Reboot-Request", 1104 27: "NAS-Reboot-Response", 1105 28: "Reserved", 1106 29: "Next-Passcode", 1107 30: "New-Pin", 1108 31: "Terminate-Session", 1109 32: "Password-Expired", 1110 33: "Event-Request", 1111 34: "Event-Response", 1112 40: "Disconnect-Request", 1113 41: "Disconnect-ACK", 1114 42: "Disconnect-NAK", 1115 43: "CoA-Request", 1116 44: "CoA-ACK", 1117 45: "CoA-NAK", 1118 50: "IP-Address-Allocate", 1119 51: "IP-Address-Release", 1120 52: "Protocol-Error", 1121 250: "Experimental Use", 1122 251: "Experimental Use", 1123 252: "Experimental Use", 1124 253: "Experimental Use", 1125 254: "Reserved", 1126 255: "Reserved" 1127} 1128 1129 1130class Radius(Packet): 1131 """ 1132 Implements a RADIUS packet (RFC 2865). 1133 """ 1134 1135 name = "RADIUS" 1136 fields_desc = [ 1137 ByteEnumField("code", 1, _packet_codes), 1138 ByteField("id", 0), 1139 FieldLenField( 1140 "len", 1141 None, 1142 "attributes", 1143 "H", 1144 adjust=lambda pkt, x: len(pkt.attributes) + 20 1145 ), 1146 XStrFixedLenField("authenticator", "", 16), 1147 _RADIUSAttrPacketListField( 1148 "attributes", 1149 [], 1150 RadiusAttribute, 1151 length_from=lambda pkt: pkt.len - 20 1152 ) 1153 ] 1154 1155 def compute_authenticator(self, packed_request_auth, shared_secret): 1156 """ 1157 Computes the authenticator field (RFC 2865 - Section 3) 1158 """ 1159 1160 data = prepare_packed_data(self, packed_request_auth) 1161 radius_mac = hashlib.md5(data + shared_secret) 1162 return radius_mac.digest() 1163 1164 def post_build(self, p, pay): 1165 p += pay 1166 length = self.len 1167 if length is None: 1168 length = len(p) 1169 p = p[:2] + struct.pack("!H", length) + p[4:] 1170 return p 1171 1172 1173bind_layers(UDP, Radius, sport=1812) 1174bind_layers(UDP, Radius, dport=1812) 1175bind_layers(UDP, Radius, sport=1813) 1176bind_layers(UDP, Radius, dport=1813) 1177