| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
""" |
|---|
| 4 |
Radius extension for Scapy <http://www.secdev.org/scapy> |
|---|
| 5 |
|
|---|
| 6 |
This module provides Scapy layers for the Radius |
|---|
| 7 |
protocol as defined in RFC 2865 and 2866 and other. |
|---|
| 8 |
|
|---|
| 9 |
Copyright (c) 2008 MAUGE Vincent : vmauge.nospam[at]nospam.gmail.com |
|---|
| 10 |
|
|---|
| 11 |
This program is free software; you can redistribute it and/or |
|---|
| 12 |
modify it under the terms of the GNU General Public License |
|---|
| 13 |
as published by the Free Software Foundation; either version 2 |
|---|
| 14 |
of the License, or (at your option) any later version. |
|---|
| 15 |
|
|---|
| 16 |
This program is distributed in the hope that it will be useful, |
|---|
| 17 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 18 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 19 |
GNU General Public License for more details. |
|---|
| 20 |
""" |
|---|
| 21 |
|
|---|
| 22 |
from scapy import * |
|---|
| 23 |
|
|---|
| 24 |
class Radius_Attribute(Packet): |
|---|
| 25 |
name = "Radius Attribute" |
|---|
| 26 |
fields_desc = [ |
|---|
| 27 |
ByteEnumField("type",1,{ 1:"User-Name", |
|---|
| 28 |
2:"User-Password", |
|---|
| 29 |
3:"CHAP-Password", |
|---|
| 30 |
4:"NAS-IP-Address", |
|---|
| 31 |
5:"NAS-Port", |
|---|
| 32 |
6:"Service-Type", |
|---|
| 33 |
7:"Framed-Protocol", |
|---|
| 34 |
8:"Framed-IP-Address", |
|---|
| 35 |
9:"Framed-IP-Netmask", |
|---|
| 36 |
10:"Framed-Routing", |
|---|
| 37 |
11:"Filter-Id", |
|---|
| 38 |
12:"Framed-MTU", |
|---|
| 39 |
13:"Framed-Compression", |
|---|
| 40 |
14:"Login-IP-Host", |
|---|
| 41 |
15:"Login-Service", |
|---|
| 42 |
16:"Login-TCP-Port", |
|---|
| 43 |
17:"(unassigned)", |
|---|
| 44 |
18:"Reply-Message", |
|---|
| 45 |
19:"Callback-Number", |
|---|
| 46 |
20:"Callback-Id", |
|---|
| 47 |
21:"(unassigned)", |
|---|
| 48 |
22:"Framed-Route", |
|---|
| 49 |
23:"Framed-IPX-Network", |
|---|
| 50 |
24:"State", |
|---|
| 51 |
25:"Class", |
|---|
| 52 |
26:"Vendor-Specific", |
|---|
| 53 |
27:"Session-Timeout", |
|---|
| 54 |
28:"Idle-Timeout", |
|---|
| 55 |
29:"Termination-Action", |
|---|
| 56 |
30:"Called-Station-Id", |
|---|
| 57 |
31:"Calling-Station-Id", |
|---|
| 58 |
32:"NAS-Identifier", |
|---|
| 59 |
33:"Proxy-State", |
|---|
| 60 |
34:"Login-LAT-Service", |
|---|
| 61 |
35:"Login-LAT-Node", |
|---|
| 62 |
36:"Login-LAT-Group", |
|---|
| 63 |
37:"Framed-AppleTalk-Link", |
|---|
| 64 |
38:"Framed-AppleTalk-Network", |
|---|
| 65 |
39:"Framed-AppleTalk-Zone", |
|---|
| 66 |
40:"Acct-Status-Type", |
|---|
| 67 |
41:"Acct-Delay-Time", |
|---|
| 68 |
42:"Acct-Input-Octets", |
|---|
| 69 |
43:"Acct-Output-Octets", |
|---|
| 70 |
44:"Acct-Session-Id", |
|---|
| 71 |
45:"Acct-Authentic", |
|---|
| 72 |
46:"Acct-Session-Time", |
|---|
| 73 |
47:"Acct-Input-Packets", |
|---|
| 74 |
48:"Acct-Output-Packets", |
|---|
| 75 |
49:"Acct-Terminate-Cause", |
|---|
| 76 |
50:"Acct-Multi-Session-Id", |
|---|
| 77 |
51:"Acct-Link-Count", |
|---|
| 78 |
60:"CHAP-Challenge", |
|---|
| 79 |
61:"NAS-Port-Type", |
|---|
| 80 |
62:"Port-Limit", |
|---|
| 81 |
63:"Login-LAT-Port"}), |
|---|
| 82 |
FieldLenField("len",None,"value","B", adjust=lambda pkt,x:x+2), |
|---|
| 83 |
StrLenField("value",None,length_from= lambda pkt:pkt.len-2),] |
|---|
| 84 |
|
|---|
| 85 |
def post_build(self, p, pay): |
|---|
| 86 |
l = self.len |
|---|
| 87 |
if l is None: |
|---|
| 88 |
l = len(p) |
|---|
| 89 |
p = p[:2]+struct.pack("!B",l)+p[4:] |
|---|
| 90 |
return p |
|---|
| 91 |
|
|---|
| 92 |
def extract_padding(self, pay): |
|---|
| 93 |
return "",pay |
|---|
| 94 |
|
|---|
| 95 |
|
|---|
| 96 |
|
|---|
| 97 |
class My_Radius(Packet): |
|---|
| 98 |
name = "My Radius" |
|---|
| 99 |
fields_desc = [ |
|---|
| 100 |
ByteEnumField("code", 1, {1: "Access-Request", |
|---|
| 101 |
2: "Access-Accept", |
|---|
| 102 |
3: "Access-Reject", |
|---|
| 103 |
4: "Accounting-Request", |
|---|
| 104 |
5: "Accounting-Accept", |
|---|
| 105 |
6: "Accounting-Status", |
|---|
| 106 |
7: "Password-Request", |
|---|
| 107 |
8: "Password-Ack", |
|---|
| 108 |
9: "Password-Reject", |
|---|
| 109 |
10: "Accounting-Message", |
|---|
| 110 |
11: "Access-Challenge", |
|---|
| 111 |
12: "Status-Server", |
|---|
| 112 |
13: "Status-Client", |
|---|
| 113 |
21: "Resource-Free-Request", |
|---|
| 114 |
22: "Resource-Free-Response", |
|---|
| 115 |
23: "Resource-Query-Request", |
|---|
| 116 |
24: "Resource-Query-Response", |
|---|
| 117 |
25: "Alternate-Resource-Reclaim-Request", |
|---|
| 118 |
26: "NAS-Reboot-Request", |
|---|
| 119 |
27: "NAS-Reboot-Response", |
|---|
| 120 |
29: "Next-Passcode", |
|---|
| 121 |
30: "New-Pin", |
|---|
| 122 |
31: "Terminate-Session", |
|---|
| 123 |
32: "Password-Expired", |
|---|
| 124 |
33: "Event-Request", |
|---|
| 125 |
34: "Event-Response", |
|---|
| 126 |
40: "Disconnect-Request", |
|---|
| 127 |
41: "Disconnect-ACK", |
|---|
| 128 |
42: "Disconnect-NAK", |
|---|
| 129 |
43: "CoA-Request", |
|---|
| 130 |
44: "CoA-ACK", |
|---|
| 131 |
45: "CoA-NAK", |
|---|
| 132 |
50: "IP-Address-Allocate", |
|---|
| 133 |
51: "IP-Address-Release", |
|---|
| 134 |
253: "Experimental-use", |
|---|
| 135 |
254: "Reserved", |
|---|
| 136 |
255: "Reserved"} ), |
|---|
| 137 |
ByteField("id", 0), |
|---|
| 138 |
FieldLenField("len", None, "attributes", "H" , adjust= lambda pkt,x:len(x.value_pair)+20), |
|---|
| 139 |
StrFixedLenField("authenticator","",16), |
|---|
| 140 |
PacketListField("attributes",[],Radius_Attribute,length_from=lambda pkt:pkt.len-20),] |
|---|
| 141 |
|
|---|
| 142 |
def post_build(self, p, pay): |
|---|
| 143 |
p += pay |
|---|
| 144 |
l = self.len |
|---|
| 145 |
if l is None: |
|---|
| 146 |
l = len(p) |
|---|
| 147 |
p = p[:2]+struct.pack("!H",l)+p[4:] |
|---|
| 148 |
return p |
|---|
| 149 |
|
|---|
| 150 |
bind_layers( UDP, My_Radius, sport=1812 ) |
|---|
| 151 |
bind_layers( UDP, My_Radius, dport=1812 ) |
|---|
| 152 |
bind_layers( UDP, My_Radius, sport=1813 ) |
|---|
| 153 |
bind_layers( UDP, My_Radius, dport=1813 ) |
|---|
| 154 |
|
|---|
| 155 |
|
|---|
| 156 |
|
|---|
| 157 |
if __name__ == "__main__": |
|---|
| 158 |
interact(mydict=globals(), mybanner="Radius extension 0.1") |
|---|