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

91 statements  

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> 

5 

6""" 

7PPTP (Point to Point Tunneling Protocol) 

8 

9[RFC 2637] 

10""" 

11 

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 

17 

18_PPTP_MAGIC_COOKIE = 0x1a2b3c4d 

19 

20_PPTP_msg_type = {1: "Control Message", 

21 2: "Managemenent Message"} 

22 

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"} 

42 

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"} 

50 

51 

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)] 

61 

62 registered_options = {} 

63 

64 @classmethod 

65 def register_variant(cls): 

66 cls.registered_options[cls.ctrl_msg_type.default] = cls 

67 

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 

74 

75 

76_PPTP_FRAMING_CAPABILITIES_FLAGS = ["Asynchronous Framing supported", 

77 "Synchronous Framing supported"] 

78 

79_PPTP_BEARER_CAPABILITIES_FLAGS = ["Analog access supported", 

80 "Digital access supported"] 

81 

82 

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)] 

100 

101 

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"} 

107 

108 

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)] 

128 

129 def answers(self, other): 

130 return isinstance(other, PPTPStartControlConnectionRequest) 

131 

132 

133_PPTP_stop_control_connection_reason = {1: "None", 

134 2: "Stop-Protocol", 

135 3: "Stop-Local-Shutdown"} 

136 

137 

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)] 

149 

150 

151_PPTP_stop_control_connection_result = {1: "OK", 

152 2: "General error"} 

153 

154 

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)] 

166 

167 def answers(self, other): 

168 return isinstance(other, PPTPStopControlConnectionRequest) 

169 

170 

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)] 

179 

180 

181_PPTP_echo_result = {1: "OK", 

182 2: "General error"} 

183 

184 

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)] 

196 

197 def answers(self, other): 

198 return isinstance(other, PPTPEchoRequest) and other.identifier == self.identifier # noqa: E501 

199 

200 

201_PPTP_bearer_type = {1: "Analog channel", 

202 2: "Digital channel", 

203 3: "Any type of channel"} 

204 

205_PPTP_framing_type = {1: "Asynchronous framing", 

206 2: "Synchronous framing", 

207 3: "Any type of framing"} 

208 

209 

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)] 

229 

230 

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"} 

238 

239 

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)] 

256 

257 def answers(self, other): 

258 return isinstance(other, PPTPOutgoingCallRequest) and other.call_id == self.peer_call_id # noqa: E501 

259 

260 

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)] 

277 

278 

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)] 

293 

294 def answers(self, other): 

295 return isinstance(other, PPTPIncomingCallRequest) and other.call_id == self.peer_call_id # noqa: E501 

296 

297 

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)] 

311 

312 def answers(self, other): 

313 return isinstance(other, PPTPIncomingCallReply) and other.call_id == self.peer_call_id # noqa: E501 

314 

315 

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)] 

325 

326 

327_PPTP_call_disconnect_result = {1: "Lost Carrier", 

328 2: "General error", 

329 3: "Admin Shutdown", 

330 4: "Request"} 

331 

332 

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)] 

347 

348 

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)] 

364 

365 

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)] 

377 

378 

379bind_layers(TCP, PPTP, sport=1723) 

380bind_layers(TCP, PPTP, dport=1723)