Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/layers/pptp.py: 91%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# SPDX-License-Identifier: GPL-2.0-only
2# This file is part of Scapy
3# See https://scapy.net/ for more information
4# Copyright (C) Jan Sebechlebsky <sebechlebskyjan@gmail.com>
6"""
7PPTP (Point to Point Tunneling Protocol)
9[RFC 2637]
10"""
12from scapy.packet import Packet, bind_layers
13from scapy.layers.inet import TCP
14from scapy.fields import ByteEnumField, FieldLenField, FlagsField, IntField, \
15 IntEnumField, LenField, XIntField, ShortField, ShortEnumField, \
16 StrFixedLenField, StrLenField, XShortField, XByteField
18_PPTP_MAGIC_COOKIE = 0x1a2b3c4d
20_PPTP_msg_type = {1: "Control Message",
21 2: "Managemenent Message"}
23_PPTP_ctrl_msg_type = { # Control Connection Management
24 1: "Start-Control-Connection-Request",
25 2: "Start-Control-Connection-Reply",
26 3: "Stop-Control-Connection-Request",
27 4: "Stop-Control-Connection-Reply",
28 5: "Echo-Request",
29 6: "Echo-Reply",
30 # Call Management
31 7: "Outgoing-Call-Request",
32 8: "Outgoing-Call-Reply",
33 9: "Incoming-Call-Request",
34 10: "Incoming-Call-Reply",
35 11: "Incoming-Call-Connected",
36 12: "Call-Clear-Request",
37 13: "Call-Disconnect-Notify",
38 # Error Reporting
39 14: "WAN-Error-Notify",
40 # PPP Session Control
41 15: "Set-Link-Info"}
43_PPTP_general_error_code = {0: "None",
44 1: "Not-Connected",
45 2: "Bad-Format",
46 3: "Bad-Value",
47 4: "No-Resource",
48 5: "Bad-Call ID",
49 6: "PAC-Error"}
52class PPTP(Packet):
53 name = "PPTP"
54 fields_desc = [FieldLenField("len", None, fmt="H", length_of="data",
55 adjust=lambda p, x: x + 12),
56 ShortEnumField("type", 1, _PPTP_msg_type),
57 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
58 ShortEnumField("ctrl_msg_type", 1, _PPTP_ctrl_msg_type),
59 XShortField("reserved_0", 0x0000),
60 StrLenField("data", "", length_from=lambda p: p.len - 12)]
62 registered_options = {}
64 @classmethod
65 def register_variant(cls):
66 cls.registered_options[cls.ctrl_msg_type.default] = cls
68 @classmethod
69 def dispatch_hook(cls, _pkt=None, *args, **kargs):
70 if _pkt:
71 o = _pkt[9]
72 return cls.registered_options.get(o, cls)
73 return cls
76_PPTP_FRAMING_CAPABILITIES_FLAGS = ["Asynchronous Framing supported",
77 "Synchronous Framing supported"]
79_PPTP_BEARER_CAPABILITIES_FLAGS = ["Analog access supported",
80 "Digital access supported"]
83class PPTPStartControlConnectionRequest(PPTP):
84 name = "PPTP Start Control Connection Request"
85 fields_desc = [LenField("len", 156),
86 ShortEnumField("type", 1, _PPTP_msg_type),
87 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
88 ShortEnumField("ctrl_msg_type", 1, _PPTP_ctrl_msg_type),
89 XShortField("reserved_0", 0x0000),
90 ShortField("protocol_version", 0x0100),
91 XShortField("reserved_1", 0x0000),
92 FlagsField("framing_capabilities", 0, 32,
93 _PPTP_FRAMING_CAPABILITIES_FLAGS),
94 FlagsField("bearer_capabilities", 0, 32,
95 _PPTP_BEARER_CAPABILITIES_FLAGS),
96 ShortField("maximum_channels", 65535),
97 ShortField("firmware_revision", 256),
98 StrFixedLenField("host_name", "linux", 64),
99 StrFixedLenField("vendor_string", "", 64)]
102_PPTP_start_control_connection_result = {1: "OK",
103 2: "General error",
104 3: "Command channel already exists",
105 4: "Not authorized",
106 5: "Unsupported protocol version"}
109class PPTPStartControlConnectionReply(PPTP):
110 name = "PPTP Start Control Connection Reply"
111 fields_desc = [LenField("len", 156),
112 ShortEnumField("type", 1, _PPTP_msg_type),
113 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
114 ShortEnumField("ctrl_msg_type", 2, _PPTP_ctrl_msg_type),
115 XShortField("reserved_0", 0x0000),
116 ShortField("protocol_version", 0x0100),
117 ByteEnumField("result_code", 1,
118 _PPTP_start_control_connection_result),
119 ByteEnumField("error_code", 0, _PPTP_general_error_code),
120 FlagsField("framing_capabilities", 0, 32,
121 _PPTP_FRAMING_CAPABILITIES_FLAGS),
122 FlagsField("bearer_capabilities", 0, 32,
123 _PPTP_BEARER_CAPABILITIES_FLAGS),
124 ShortField("maximum_channels", 65535),
125 ShortField("firmware_revision", 256),
126 StrFixedLenField("host_name", "linux", 64),
127 StrFixedLenField("vendor_string", "", 64)]
129 def answers(self, other):
130 return isinstance(other, PPTPStartControlConnectionRequest)
133_PPTP_stop_control_connection_reason = {1: "None",
134 2: "Stop-Protocol",
135 3: "Stop-Local-Shutdown"}
138class PPTPStopControlConnectionRequest(PPTP):
139 name = "PPTP Stop Control Connection Request"
140 fields_desc = [LenField("len", 16),
141 ShortEnumField("type", 1, _PPTP_msg_type),
142 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
143 ShortEnumField("ctrl_msg_type", 3, _PPTP_ctrl_msg_type),
144 XShortField("reserved_0", 0x0000),
145 ByteEnumField("reason", 1,
146 _PPTP_stop_control_connection_reason),
147 XByteField("reserved_1", 0x00),
148 XShortField("reserved_2", 0x0000)]
151_PPTP_stop_control_connection_result = {1: "OK",
152 2: "General error"}
155class PPTPStopControlConnectionReply(PPTP):
156 name = "PPTP Stop Control Connection Reply"
157 fields_desc = [LenField("len", 16),
158 ShortEnumField("type", 1, _PPTP_msg_type),
159 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
160 ShortEnumField("ctrl_msg_type", 4, _PPTP_ctrl_msg_type),
161 XShortField("reserved_0", 0x0000),
162 ByteEnumField("result_code", 1,
163 _PPTP_stop_control_connection_result),
164 ByteEnumField("error_code", 0, _PPTP_general_error_code),
165 XShortField("reserved_2", 0x0000)]
167 def answers(self, other):
168 return isinstance(other, PPTPStopControlConnectionRequest)
171class PPTPEchoRequest(PPTP):
172 name = "PPTP Echo Request"
173 fields_desc = [LenField("len", 16),
174 ShortEnumField("type", 1, _PPTP_msg_type),
175 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
176 ShortEnumField("ctrl_msg_type", 5, _PPTP_ctrl_msg_type),
177 XShortField("reserved_0", 0x0000),
178 IntField("identifier", None)]
181_PPTP_echo_result = {1: "OK",
182 2: "General error"}
185class PPTPEchoReply(PPTP):
186 name = "PPTP Echo Reply"
187 fields_desc = [LenField("len", 20),
188 ShortEnumField("type", 1, _PPTP_msg_type),
189 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
190 ShortEnumField("ctrl_msg_type", 6, _PPTP_ctrl_msg_type),
191 XShortField("reserved_0", 0x0000),
192 IntField("identifier", None),
193 ByteEnumField("result_code", 1, _PPTP_echo_result),
194 ByteEnumField("error_code", 0, _PPTP_general_error_code),
195 XShortField("reserved_1", 0x0000)]
197 def answers(self, other):
198 return isinstance(other, PPTPEchoRequest) and other.identifier == self.identifier # noqa: E501
201_PPTP_bearer_type = {1: "Analog channel",
202 2: "Digital channel",
203 3: "Any type of channel"}
205_PPTP_framing_type = {1: "Asynchronous framing",
206 2: "Synchronous framing",
207 3: "Any type of framing"}
210class PPTPOutgoingCallRequest(PPTP):
211 name = "PPTP Outgoing Call Request"
212 fields_desc = [LenField("len", 168),
213 ShortEnumField("type", 1, _PPTP_msg_type),
214 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
215 ShortEnumField("ctrl_msg_type", 7, _PPTP_ctrl_msg_type),
216 XShortField("reserved_0", 0x0000),
217 ShortField("call_id", 1),
218 ShortField("call_serial_number", 0),
219 IntField("minimum_bps", 32768),
220 IntField("maximum_bps", 2147483648),
221 IntEnumField("bearer_type", 3, _PPTP_bearer_type),
222 IntEnumField("framing_type", 3, _PPTP_framing_type),
223 ShortField("pkt_window_size", 16),
224 ShortField("pkt_proc_delay", 0),
225 ShortField('phone_number_len', 0),
226 XShortField("reserved_1", 0x0000),
227 StrFixedLenField("phone_number", '', 64),
228 StrFixedLenField("subaddress", '', 64)]
231_PPTP_result_code = {1: "Connected",
232 2: "General error",
233 3: "No Carrier",
234 4: "Busy",
235 5: "No dial tone",
236 6: "Time-out",
237 7: "Do not accept"}
240class PPTPOutgoingCallReply(PPTP):
241 name = "PPTP Outgoing Call Reply"
242 fields_desc = [LenField("len", 32),
243 ShortEnumField("type", 1, _PPTP_msg_type),
244 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
245 ShortEnumField("ctrl_msg_type", 8, _PPTP_ctrl_msg_type),
246 XShortField("reserved_0", 0x0000),
247 ShortField("call_id", 1),
248 ShortField("peer_call_id", 1),
249 ByteEnumField("result_code", 1, _PPTP_result_code),
250 ByteEnumField("error_code", 0, _PPTP_general_error_code),
251 ShortField("cause_code", 0),
252 IntField("connect_speed", 100000000),
253 ShortField("pkt_window_size", 16),
254 ShortField("pkt_proc_delay", 0),
255 IntField("channel_id", 0)]
257 def answers(self, other):
258 return isinstance(other, PPTPOutgoingCallRequest) and other.call_id == self.peer_call_id # noqa: E501
261class PPTPIncomingCallRequest(PPTP):
262 name = "PPTP Incoming Call Request"
263 fields_desc = [LenField("len", 220),
264 ShortEnumField("type", 1, _PPTP_msg_type),
265 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
266 ShortEnumField("ctrl_msg_type", 9, _PPTP_ctrl_msg_type),
267 XShortField("reserved_0", 0x0000),
268 ShortField("call_id", 1),
269 ShortField("call_serial_number", 1),
270 IntEnumField("bearer_type", 3, _PPTP_bearer_type),
271 IntField("channel_id", 0),
272 ShortField("dialed_number_len", 0),
273 ShortField("dialing_number_len", 0),
274 StrFixedLenField("dialed_number", "", 64),
275 StrFixedLenField("dialing_number", "", 64),
276 StrFixedLenField("subaddress", "", 64)]
279class PPTPIncomingCallReply(PPTP):
280 name = "PPTP Incoming Call Reply"
281 fields_desc = [LenField("len", 148),
282 ShortEnumField("type", 1, _PPTP_msg_type),
283 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
284 ShortEnumField("ctrl_msg_type", 10, _PPTP_ctrl_msg_type),
285 XShortField("reserved_0", 0x0000),
286 ShortField("call_id", 1),
287 ShortField("peer_call_id", 1),
288 ByteEnumField("result_code", 1, _PPTP_result_code),
289 ByteEnumField("error_code", 0, _PPTP_general_error_code),
290 ShortField("pkt_window_size", 64),
291 ShortField("pkt_transmit_delay", 0),
292 XShortField("reserved_1", 0x0000)]
294 def answers(self, other):
295 return isinstance(other, PPTPIncomingCallRequest) and other.call_id == self.peer_call_id # noqa: E501
298class PPTPIncomingCallConnected(PPTP):
299 name = "PPTP Incoming Call Connected"
300 fields_desc = [LenField("len", 28),
301 ShortEnumField("type", 1, _PPTP_msg_type),
302 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
303 ShortEnumField("ctrl_msg_type", 11, _PPTP_ctrl_msg_type),
304 XShortField("reserved_0", 0x0000),
305 ShortField("peer_call_id", 1),
306 XShortField("reserved_1", 0x0000),
307 IntField("connect_speed", 100000000),
308 ShortField("pkt_window_size", 64),
309 ShortField("pkt_transmit_delay", 0),
310 IntEnumField("framing_type", 1, _PPTP_framing_type)]
312 def answers(self, other):
313 return isinstance(other, PPTPIncomingCallReply) and other.call_id == self.peer_call_id # noqa: E501
316class PPTPCallClearRequest(PPTP):
317 name = "PPTP Call Clear Request"
318 fields_desc = [LenField("len", 16),
319 ShortEnumField("type", 1, _PPTP_msg_type),
320 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
321 ShortEnumField("ctrl_msg_type", 12, _PPTP_ctrl_msg_type),
322 XShortField("reserved_0", 0x0000),
323 ShortField("call_id", 1),
324 XShortField("reserved_1", 0x0000)]
327_PPTP_call_disconnect_result = {1: "Lost Carrier",
328 2: "General error",
329 3: "Admin Shutdown",
330 4: "Request"}
333class PPTPCallDisconnectNotify(PPTP):
334 name = "PPTP Call Disconnect Notify"
335 fields_desc = [LenField("len", 148),
336 ShortEnumField("type", 1, _PPTP_msg_type),
337 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
338 ShortEnumField("ctrl_msg_type", 13, _PPTP_ctrl_msg_type),
339 XShortField("reserved_0", 0x0000),
340 ShortField("call_id", 1),
341 ByteEnumField("result_code", 1,
342 _PPTP_call_disconnect_result),
343 ByteEnumField("error_code", 0, _PPTP_general_error_code),
344 ShortField("cause_code", 0),
345 XShortField("reserved_1", 0x0000),
346 StrFixedLenField("call_statistic", "", 128)]
349class PPTPWANErrorNotify(PPTP):
350 name = "PPTP WAN Error Notify"
351 fields_desc = [LenField("len", 40),
352 ShortEnumField("type", 1, _PPTP_msg_type),
353 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
354 ShortEnumField("ctrl_msg_type", 14, _PPTP_ctrl_msg_type),
355 XShortField("reserved_0", 0x0000),
356 ShortField("peer_call_id", 1),
357 XShortField("reserved_1", 0x0000),
358 IntField("crc_errors", 0),
359 IntField("framing_errors", 0),
360 IntField("hardware_overruns", 0),
361 IntField("buffer_overruns", 0),
362 IntField("time_out_errors", 0),
363 IntField("alignment_errors", 0)]
366class PPTPSetLinkInfo(PPTP):
367 name = "PPTP Set Link Info"
368 fields_desc = [LenField("len", 24),
369 ShortEnumField("type", 1, _PPTP_msg_type),
370 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE),
371 ShortEnumField("ctrl_msg_type", 15, _PPTP_ctrl_msg_type),
372 XShortField("reserved_0", 0x0000),
373 ShortField("peer_call_id", 1),
374 XShortField("reserved_1", 0x0000),
375 XIntField("send_accm", 0x00000000),
376 XIntField("receive_accm", 0x00000000)]
379bind_layers(TCP, PPTP, sport=1723)
380bind_layers(TCP, PPTP, dport=1723)