mirror of https://github.com/secdev/scapy.git
Merge pull request #607 from gpotter2/fix-prs-160
Support for Diameter protocol layer (base RFC6733 + extensions)
This commit is contained in:
commit
17def859da
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,253 @@
|
|||
# UTscapy syntax is explained here: http://www.secdev.org/projects/UTscapy/
|
||||
|
||||
# original author: patrick battistello
|
||||
|
||||
% Validation of Diameter layer
|
||||
|
||||
|
||||
#######################################################################
|
||||
+ Different ways of building basic AVPs
|
||||
#######################################################################
|
||||
|
||||
= AVP identified by full name
|
||||
a1 = AVP ('High-User-Priority', val=15)
|
||||
a1.show()
|
||||
str(a1) == b'\x00\x00\x02/@\x00\x00\x0c\x00\x00\x00\x0f'
|
||||
|
||||
= Same AVP identified by the beggining of the name
|
||||
a1b = AVP ('High-U', val=15)
|
||||
a1b.show()
|
||||
str(a1b) == str(a1)
|
||||
|
||||
= Same AVP identified by its code
|
||||
a1c = AVP (559, val=15)
|
||||
a1c.show()
|
||||
str(a1c) == str(a1)
|
||||
|
||||
= The Session-Id AVP (with some padding added)
|
||||
a2 = AVP ('Session-Id', val='aaa.test.orange.fr;1428128;644587')
|
||||
a2.show()
|
||||
str(a2) == b'\x00\x00\x01\x07@\x00\x00)aaa.test.orange.fr;1428128;644587\x00\x00\x00'
|
||||
|
||||
= An enumerated AVP
|
||||
a3 = AVP ('Auth-Session-State', val='NO_STATE_MAINTAINED')
|
||||
a3.show()
|
||||
str(a3) == b'\x00\x00\x01\x15@\x00\x00\x0c\x00\x00\x00\x01'
|
||||
|
||||
= An address AVP
|
||||
a4v4 = AVP("CG-Address", val='192.168.0.1')
|
||||
a4v4.show()
|
||||
str(a4v4) == b'\x00\x00\x03N\xc0\x00\x00\x12\x00\x00(\xaf\x00\x01\xc0\xa8\x00\x01\x00\x00'
|
||||
|
||||
a4v6 = AVP("CG-Address", val='::1')
|
||||
a4v6.show()
|
||||
str(a4v6) == b'\x00\x00\x03N\xc0\x00\x00\x1e\x00\x00(\xaf\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00'
|
||||
|
||||
a4error = AVP("CG-Address", val="unknown")
|
||||
a4error.show()
|
||||
assert str(a4error) == str(AVP("CG-Address"))
|
||||
|
||||
= A time AVP
|
||||
a5 = AVP("Expiry-Time")
|
||||
a5.show()
|
||||
assert not a5.val
|
||||
|
||||
= An empty Auth App ID AVP
|
||||
a6 = AVP("Auth-Application-Id")
|
||||
a6.show()
|
||||
str(a6) == b'\x00\x00\x01\x02@\x00\x00\x0c\x00\x00\x00\x00'
|
||||
|
||||
= An ISDN AVP
|
||||
a7 = AVP("MSISDN", val="101")
|
||||
a7.show()
|
||||
str(a7) == b'\x00\x00\x02\xbd\xc0\x00\x00\x0e\x00\x00(\xaf\x01\xf1\x00\x00'
|
||||
|
||||
= Some OctetString AVPs
|
||||
a8 = AVP("Authorization-Token", val="test")
|
||||
a8.show()
|
||||
assert str(a8) == b'\x00\x00\x01\xfa\xc0\x00\x00\x10\x00\x00(\xaftest'
|
||||
|
||||
a8 = AVP("Authorization-Token", val="testé")
|
||||
a8.show()
|
||||
assert a8.val == b"test\xc3\xa9"
|
||||
assert str(a8) == b'\x00\x00\x01\xfa\xc0\x00\x00\x12\x00\x00(\xaftest\xc3\xa9\x00\x00'
|
||||
|
||||
= Unknown AVP identifier
|
||||
|
||||
a9 = AVP("wrong")
|
||||
assert not a9
|
||||
|
||||
|
||||
#######################################################################
|
||||
+ AVPs with vendor field
|
||||
#######################################################################
|
||||
|
||||
= Vendor AVP identified by full name
|
||||
a4 = AVP ('Feature-List-ID', val=1)
|
||||
a4.show()
|
||||
str(a4) == b'\x00\x00\x02u\x80\x00\x00\x10\x00\x00(\xaf\x00\x00\x00\x01'
|
||||
|
||||
= Same AVP identified by its code and vendor ID
|
||||
* This time a list is required as first argument
|
||||
a4c = AVP ( [629, 10415], val=1)
|
||||
str(a4c) == str(a4)
|
||||
|
||||
|
||||
#######################################################################
|
||||
+ Altering the AVPs default provided values
|
||||
#######################################################################
|
||||
|
||||
= Altering the flags of the Origin-Host AVP
|
||||
a5 = AVP ('Origin-Host', avpFlags=187, val='aaa.test.orange.fr')
|
||||
a5.show()
|
||||
str(a5) == b'\x00\x00\x01\x08\xbb\x00\x00\x1aaaa.test.orange.fr\x00\x00'
|
||||
|
||||
= Altering the length of the Destination-Realm AVP
|
||||
a6 = AVP (283, avpLen=33, val='foreign.realm1.fr')
|
||||
a6.show()
|
||||
str(a6) == '\x00\x00\x01\x1b@\x00\x00!foreign.realm1.fr\x00\x00\x00'
|
||||
|
||||
= Altering the vendor of the Public-Identity AVP, and hence the flags ...
|
||||
a7 = AVP ( [601, 98765432], val = 'sip:+0123456789@aaa.test.orange.fr')
|
||||
a7.show()
|
||||
str(a7) == b'\x00\x00\x02Y\x80\x00\x00.\x05\xe3\nxsip:+0123456789@aaa.test.orange.fr\x00\x00'
|
||||
|
||||
|
||||
#######################################################################
|
||||
+ Grouped AVPs
|
||||
#######################################################################
|
||||
|
||||
= The Supported-Features AVP (with vendor)
|
||||
a8 = AVP ('Supported-Features')
|
||||
a8.val.append(a1)
|
||||
a8.val.append(a5)
|
||||
a8.show()
|
||||
str(a8) == b'\x00\x00\x02t\x80\x00\x004\x00\x00(\xaf\x00\x00\x02/@\x00\x00\x0c\x00\x00\x00\x0f\x00\x00\x01\x08\xbb\x00\x00\x1aaaa.test.orange.fr\x00\x00'
|
||||
|
||||
= The same AVP created more simply
|
||||
a8b = AVP ('Supported-Features', val = [a1, a5])
|
||||
str(a8b) == str(a8)
|
||||
|
||||
= (re)Building the previous AVP from scratch
|
||||
a8c = AVP ('Supported-Features', val = [
|
||||
AVP ('High-User-Priority', val=15),
|
||||
AVP ('Origin-Host', avpFlags=187, val='aaa.test.orange.fr') ])
|
||||
str(a8c) == str(a8)
|
||||
|
||||
= Another (dummy) grouped AVP
|
||||
a9 = AVP (297, val = [a2, a4, a6])
|
||||
a9.show()
|
||||
str(a9) == b'\x00\x00\x01)@\x00\x00`\x00\x00\x01\x07@\x00\x00)aaa.test.orange.fr;1428128;644587\x00\x00\x00\x00\x00\x02u\x80\x00\x00\x10\x00\x00(\xaf\x00\x00\x00\x01\x00\x00\x01\x1b@\x00\x00!foreign.realm1.fr\x00\x00\x00'
|
||||
|
||||
= A grouped AVP inside another grouped AVP
|
||||
a10 = AVP ('Server-Cap', val = [a1, a9])
|
||||
a10.show()
|
||||
str(a10) == b'\x00\x00\x02[\xc0\x00\x00x\x00\x00(\xaf\x00\x00\x02/@\x00\x00\x0c\x00\x00\x00\x0f\x00\x00\x01)@\x00\x00`\x00\x00\x01\x07@\x00\x00)aaa.test.orange.fr;1428128;644587\x00\x00\x00\x00\x00\x02u\x80\x00\x00\x10\x00\x00(\xaf\x00\x00\x00\x01\x00\x00\x01\x1b@\x00\x00!foreign.realm1.fr\x00\x00\x00'
|
||||
|
||||
= A big grouped AVP
|
||||
a11 = AVP ('SIP-Auth', val = [a2, a4, a8, a10])
|
||||
a11.show()
|
||||
str(a11) == b'\x00\x00\x01x@\x00\x00\xf0\x00\x00\x01\x07@\x00\x00)aaa.test.orange.fr;1428128;644587\x00\x00\x00\x00\x00\x02u\x80\x00\x00\x10\x00\x00(\xaf\x00\x00\x00\x01\x00\x00\x02t\x80\x00\x004\x00\x00(\xaf\x00\x00\x02/@\x00\x00\x0c\x00\x00\x00\x0f\x00\x00\x01\x08\xbb\x00\x00\x1aaaa.test.orange.fr\x00\x00\x00\x00\x02[\xc0\x00\x00x\x00\x00(\xaf\x00\x00\x02/@\x00\x00\x0c\x00\x00\x00\x0f\x00\x00\x01)@\x00\x00`\x00\x00\x01\x07@\x00\x00)aaa.test.orange.fr;1428128;644587\x00\x00\x00\x00\x00\x02u\x80\x00\x00\x10\x00\x00(\xaf\x00\x00\x00\x01\x00\x00\x01\x1b@\x00\x00!foreign.realm1.fr\x00\x00\x00'
|
||||
|
||||
= Dissect grouped AVP
|
||||
|
||||
a12 = DiamG(b'\x01\x00\x00!\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xbd\xc0\x00\x00\r\x00\x00(\xaf\x01')
|
||||
assert isinstance(a12.avpList[0], AVP_10415_701)
|
||||
assert "MSISDN" in a12.avpList[0].name
|
||||
|
||||
#######################################################################
|
||||
+ Diameter Requests (without AVPs)
|
||||
#######################################################################
|
||||
|
||||
= A simple request identified by its name
|
||||
r1 = DiamReq ('Capabilities-Exchange', drHbHId=1234, drEtEId=5678)
|
||||
r1.show()
|
||||
str(r1) == b'\x01\x00\x00\x14\x80\x00\x01\x01\x00\x00\x00\x00\x00\x00\x04\xd2\x00\x00\x16.'
|
||||
|
||||
= Unknown request by its name
|
||||
ur = DiamReq ('Unknown')
|
||||
str(ur) == b'\x01\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||
|
||||
= The same one identified by its code
|
||||
r1b = DiamReq (257, drHbHId=1234, drEtEId=5678)
|
||||
str(r1b) == str(r1)
|
||||
|
||||
= Unknown request by its code
|
||||
ur = DiamReq (0)
|
||||
str(ur) == b'\x01\x00\x00\x14\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||
|
||||
= The same one identified by its abbreviation
|
||||
* Only the first 2 abbreviation letters are significant (although 3 are provided in this example)
|
||||
r1c = DiamReq ('CER', drHbHId=1234, drEtEId=5678)
|
||||
str(r1c) == str(r1)
|
||||
|
||||
= Altering the request default fields
|
||||
r2 = DiamReq ('CER', drHbHId=1234, drEtEId=5678, drFlags=179, drAppId=978, drLen=12)
|
||||
r2.show()
|
||||
str(r2) == b'\x01\x00\x00\x0c\xb3\x00\x01\x01\x00\x00\x03\xd2\x00\x00\x04\xd2\x00\x00\x16.'
|
||||
|
||||
= Altering the default request fields with string
|
||||
r2b = DiamReq ('CER', drAppId="1")
|
||||
r2b.show()
|
||||
str(r2b) == b'\x01\x00\x00\x14\x00\x00\x01\x01\x01\x00\x00$\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||
|
||||
= Altering the default request fields with invalid string
|
||||
r2be = DiamReq ('CER', drAppId="-1")
|
||||
r2be.show()
|
||||
str(r2be) == b'\x01\x00\x00\x14\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||
|
||||
|
||||
#######################################################################
|
||||
+ Diameter Answers (without AVPs)
|
||||
#######################################################################
|
||||
|
||||
= A simple answer identified by its name
|
||||
ans1 = DiamAns ('Capabilities-Exchange', drHbHId=1234, drEtEId=5678)
|
||||
ans1.show()
|
||||
str(ans1) == b'\x01\x00\x00\x14\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x04\xd2\x00\x00\x16.'
|
||||
|
||||
= Same answer identified by its code or abbreviation
|
||||
ans1b = DiamAns (257, drHbHId=1234, drEtEId=5678)
|
||||
ans1c = DiamAns ('CEA', drHbHId=1234, drEtEId=5678)
|
||||
str(ans1b) == str(ans1), str(ans1c) == str(ans1)
|
||||
_ == (True, True)
|
||||
|
||||
= Altering the answer default fields
|
||||
ans2 = DiamAns ('CEA', drHbHId=1234, drEtEId=5678, drFlags=115, drAppId=1154, drLen=18)
|
||||
ans2.show()
|
||||
str(ans2) == b'\x01\x00\x00\x12s\x00\x01\x01\x00\x00\x04\x82\x00\x00\x04\xd2\x00\x00\x16.'
|
||||
|
||||
|
||||
#######################################################################
|
||||
+ Full Diameter messages
|
||||
#######################################################################
|
||||
|
||||
= A dummy Multimedia-Auth request (identified by only a portion of its name)
|
||||
r3 = DiamReq ('Multimedia-Auth', drHbHId=0x5478, drEtEId=0x1234, avpList = [a11])
|
||||
r3.show()
|
||||
str(r3) == b'\x01\x00\x01\x04\xc0\x00\x01\x1e\x00\x00\x00\x06\x00\x00Tx\x00\x00\x124\x00\x00\x01x@\x00\x00\xf0\x00\x00\x01\x07@\x00\x00)aaa.test.orange.fr;1428128;644587\x00\x00\x00\x00\x00\x02u\x80\x00\x00\x10\x00\x00(\xaf\x00\x00\x00\x01\x00\x00\x02t\x80\x00\x004\x00\x00(\xaf\x00\x00\x02/@\x00\x00\x0c\x00\x00\x00\x0f\x00\x00\x01\x08\xbb\x00\x00\x1aaaa.test.orange.fr\x00\x00\x00\x00\x02[\xc0\x00\x00x\x00\x00(\xaf\x00\x00\x02/@\x00\x00\x0c\x00\x00\x00\x0f\x00\x00\x01)@\x00\x00`\x00\x00\x01\x07@\x00\x00)aaa.test.orange.fr;1428128;644587\x00\x00\x00\x00\x00\x02u\x80\x00\x00\x10\x00\x00(\xaf\x00\x00\x00\x01\x00\x00\x01\x1b@\x00\x00!foreign.realm1.fr\x00\x00\x00'
|
||||
|
||||
|
||||
= The same request built from scratch
|
||||
r3b = DiamReq ('Multimedia-Auth', drHbHId=0x5478, drEtEId=0x1234,
|
||||
avpList = [
|
||||
AVP ('SIP-Auth', val = [
|
||||
AVP ('Session-Id', val='aaa.test.orange.fr;1428128;644587'),
|
||||
AVP ('Feature-List-ID', val=1),
|
||||
AVP ('Supported-Features', val = [
|
||||
AVP ('High-User-Priority', val=15),
|
||||
AVP ('Origin-Host', avpFlags=187, val='aaa.test.orange.fr')
|
||||
]),
|
||||
AVP ('Server-Cap', val = [
|
||||
AVP ('High-User-Priority', val=15),
|
||||
AVP (297, val = [
|
||||
AVP ('Session-Id', val='aaa.test.orange.fr;1428128;644587'),
|
||||
AVP ('Feature-List-ID', val=1),
|
||||
AVP (283, avpLen=33, val='foreign.realm1.fr')
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
str(r3b) == str(r3)
|
||||
|
|
@ -426,7 +426,70 @@ class SCTPChunkParamAdaptationLayer(_SCTPChunkParam, Packet):
|
|||
|
||||
############## SCTP Chunks
|
||||
|
||||
# Dictionary taken from: http://www.iana.org/assignments/sctp-parameters/sctp-parameters.xhtml
|
||||
SCTP_PAYLOAD_PROTOCOL_INDENTIFIERS = {
|
||||
0: 'Reserved',
|
||||
1: 'IUA',
|
||||
2: 'M2UA',
|
||||
3: 'M3UA',
|
||||
4: 'SUA',
|
||||
5: 'M2PA',
|
||||
6: 'V5UA',
|
||||
7: 'H.248',
|
||||
8: 'BICC/Q.2150.3',
|
||||
9: 'TALI',
|
||||
10: 'DUA',
|
||||
11: 'ASAP',
|
||||
12: 'ENRP',
|
||||
13: 'H.323',
|
||||
14: 'Q.IPC/Q.2150.3',
|
||||
15: 'SIMCO',
|
||||
16: 'DDP Segment Chunk',
|
||||
17: 'DDP Stream Session Control',
|
||||
18: 'S1AP',
|
||||
19: 'RUA',
|
||||
20: 'HNBAP',
|
||||
21: 'ForCES-HP',
|
||||
22: 'ForCES-MP',
|
||||
23: 'ForCES-LP',
|
||||
24: 'SBc-AP',
|
||||
25: 'NBAP',
|
||||
26: 'Unassigned',
|
||||
27: 'X2AP',
|
||||
28: 'IRCP',
|
||||
29: 'LCS-AP',
|
||||
30: 'MPICH2',
|
||||
31: 'SABP',
|
||||
32: 'FGP',
|
||||
33: 'PPP',
|
||||
34: 'CALCAPP',
|
||||
35: 'SSP',
|
||||
36: 'NPMP-CONTROL',
|
||||
37: 'NPMP-DATA',
|
||||
38: 'ECHO',
|
||||
39: 'DISCARD',
|
||||
40: 'DAYTIME',
|
||||
41: 'CHARGEN',
|
||||
42: '3GPP RNA',
|
||||
43: '3GPP M2AP',
|
||||
44: '3GPP M3AP',
|
||||
45: 'SSH/SCTP',
|
||||
46: 'Diameter/SCTP',
|
||||
47: 'Diameter/DTLS/SCTP',
|
||||
48: 'R14P',
|
||||
49: 'Unassigned',
|
||||
50: 'WebRTC DCEP',
|
||||
51: 'WebRTC String',
|
||||
52: 'WebRTC Binary Partial',
|
||||
53: 'WebRTC Binary',
|
||||
54: 'WebRTC String Partial',
|
||||
55: '3GPP PUA',
|
||||
56: 'WebRTC String Empty',
|
||||
57: 'WebRTC Binary Empty'
|
||||
}
|
||||
|
||||
class SCTPChunkData(_SCTPChunkGuessPayload, Packet):
|
||||
# TODO : add a padding function in post build if this layer is used to generate SCTP chunk data
|
||||
fields_desc = [ ByteEnumField("type", 0, sctpchunktypes),
|
||||
BitField("reserved", None, 4),
|
||||
BitField("delay_sack", 0, 1),
|
||||
|
@ -437,11 +500,12 @@ class SCTPChunkData(_SCTPChunkGuessPayload, Packet):
|
|||
XIntField("tsn", None),
|
||||
XShortField("stream_id", None),
|
||||
XShortField("stream_seq", None),
|
||||
XIntField("proto_id", None),
|
||||
IntEnumField("proto_id", None, SCTP_PAYLOAD_PROTOCOL_INDENTIFIERS),
|
||||
PadField(StrLenField("data", None, length_from=lambda pkt: pkt.len-16),
|
||||
4, padwith=b"\x00"),
|
||||
]
|
||||
|
||||
|
||||
class SCTPChunkInit(_SCTPChunkGuessPayload, Packet):
|
||||
fields_desc = [ ByteEnumField("type", 1, sctpchunktypes),
|
||||
XByteField("flags", None),
|
||||
|
|
Loading…
Reference in New Issue