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

92 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.compat import orb 

15from scapy.fields import ByteEnumField, FieldLenField, FlagsField, IntField, \ 

16 IntEnumField, LenField, XIntField, ShortField, ShortEnumField, \ 

17 StrFixedLenField, StrLenField, XShortField, XByteField 

18 

19_PPTP_MAGIC_COOKIE = 0x1a2b3c4d 

20 

21_PPTP_msg_type = {1: "Control Message", 

22 2: "Managemenent Message"} 

23 

24_PPTP_ctrl_msg_type = { # Control Connection Management 

25 1: "Start-Control-Connection-Request", 

26 2: "Start-Control-Connection-Reply", 

27 3: "Stop-Control-Connection-Request", 

28 4: "Stop-Control-Connection-Reply", 

29 5: "Echo-Request", 

30 6: "Echo-Reply", 

31 # Call Management 

32 7: "Outgoing-Call-Request", 

33 8: "Outgoing-Call-Reply", 

34 9: "Incoming-Call-Request", 

35 10: "Incoming-Call-Reply", 

36 11: "Incoming-Call-Connected", 

37 12: "Call-Clear-Request", 

38 13: "Call-Disconnect-Notify", 

39 # Error Reporting 

40 14: "WAN-Error-Notify", 

41 # PPP Session Control 

42 15: "Set-Link-Info"} 

43 

44_PPTP_general_error_code = {0: "None", 

45 1: "Not-Connected", 

46 2: "Bad-Format", 

47 3: "Bad-Value", 

48 4: "No-Resource", 

49 5: "Bad-Call ID", 

50 6: "PAC-Error"} 

51 

52 

53class PPTP(Packet): 

54 name = "PPTP" 

55 fields_desc = [FieldLenField("len", None, fmt="H", length_of="data", 

56 adjust=lambda p, x: x + 12), 

57 ShortEnumField("type", 1, _PPTP_msg_type), 

58 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

59 ShortEnumField("ctrl_msg_type", 1, _PPTP_ctrl_msg_type), 

60 XShortField("reserved_0", 0x0000), 

61 StrLenField("data", "", length_from=lambda p: p.len - 12)] 

62 

63 registered_options = {} 

64 

65 @classmethod 

66 def register_variant(cls): 

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

68 

69 @classmethod 

70 def dispatch_hook(cls, _pkt=None, *args, **kargs): 

71 if _pkt: 

72 o = orb(_pkt[9]) 

73 return cls.registered_options.get(o, cls) 

74 return cls 

75 

76 

77_PPTP_FRAMING_CAPABILITIES_FLAGS = ["Asynchronous Framing supported", 

78 "Synchronous Framing supported"] 

79 

80_PPTP_BEARER_CAPABILITIES_FLAGS = ["Analog access supported", 

81 "Digital access supported"] 

82 

83 

84class PPTPStartControlConnectionRequest(PPTP): 

85 name = "PPTP Start Control Connection Request" 

86 fields_desc = [LenField("len", 156), 

87 ShortEnumField("type", 1, _PPTP_msg_type), 

88 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

89 ShortEnumField("ctrl_msg_type", 1, _PPTP_ctrl_msg_type), 

90 XShortField("reserved_0", 0x0000), 

91 ShortField("protocol_version", 0x0100), 

92 XShortField("reserved_1", 0x0000), 

93 FlagsField("framing_capabilities", 0, 32, 

94 _PPTP_FRAMING_CAPABILITIES_FLAGS), 

95 FlagsField("bearer_capabilities", 0, 32, 

96 _PPTP_BEARER_CAPABILITIES_FLAGS), 

97 ShortField("maximum_channels", 65535), 

98 ShortField("firmware_revision", 256), 

99 StrFixedLenField("host_name", "linux", 64), 

100 StrFixedLenField("vendor_string", "", 64)] 

101 

102 

103_PPTP_start_control_connection_result = {1: "OK", 

104 2: "General error", 

105 3: "Command channel already exists", 

106 4: "Not authorized", 

107 5: "Unsupported protocol version"} 

108 

109 

110class PPTPStartControlConnectionReply(PPTP): 

111 name = "PPTP Start Control Connection Reply" 

112 fields_desc = [LenField("len", 156), 

113 ShortEnumField("type", 1, _PPTP_msg_type), 

114 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

115 ShortEnumField("ctrl_msg_type", 2, _PPTP_ctrl_msg_type), 

116 XShortField("reserved_0", 0x0000), 

117 ShortField("protocol_version", 0x0100), 

118 ByteEnumField("result_code", 1, 

119 _PPTP_start_control_connection_result), 

120 ByteEnumField("error_code", 0, _PPTP_general_error_code), 

121 FlagsField("framing_capabilities", 0, 32, 

122 _PPTP_FRAMING_CAPABILITIES_FLAGS), 

123 FlagsField("bearer_capabilities", 0, 32, 

124 _PPTP_BEARER_CAPABILITIES_FLAGS), 

125 ShortField("maximum_channels", 65535), 

126 ShortField("firmware_revision", 256), 

127 StrFixedLenField("host_name", "linux", 64), 

128 StrFixedLenField("vendor_string", "", 64)] 

129 

130 def answers(self, other): 

131 return isinstance(other, PPTPStartControlConnectionRequest) 

132 

133 

134_PPTP_stop_control_connection_reason = {1: "None", 

135 2: "Stop-Protocol", 

136 3: "Stop-Local-Shutdown"} 

137 

138 

139class PPTPStopControlConnectionRequest(PPTP): 

140 name = "PPTP Stop Control Connection Request" 

141 fields_desc = [LenField("len", 16), 

142 ShortEnumField("type", 1, _PPTP_msg_type), 

143 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

144 ShortEnumField("ctrl_msg_type", 3, _PPTP_ctrl_msg_type), 

145 XShortField("reserved_0", 0x0000), 

146 ByteEnumField("reason", 1, 

147 _PPTP_stop_control_connection_reason), 

148 XByteField("reserved_1", 0x00), 

149 XShortField("reserved_2", 0x0000)] 

150 

151 

152_PPTP_stop_control_connection_result = {1: "OK", 

153 2: "General error"} 

154 

155 

156class PPTPStopControlConnectionReply(PPTP): 

157 name = "PPTP Stop Control Connection Reply" 

158 fields_desc = [LenField("len", 16), 

159 ShortEnumField("type", 1, _PPTP_msg_type), 

160 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

161 ShortEnumField("ctrl_msg_type", 4, _PPTP_ctrl_msg_type), 

162 XShortField("reserved_0", 0x0000), 

163 ByteEnumField("result_code", 1, 

164 _PPTP_stop_control_connection_result), 

165 ByteEnumField("error_code", 0, _PPTP_general_error_code), 

166 XShortField("reserved_2", 0x0000)] 

167 

168 def answers(self, other): 

169 return isinstance(other, PPTPStopControlConnectionRequest) 

170 

171 

172class PPTPEchoRequest(PPTP): 

173 name = "PPTP Echo Request" 

174 fields_desc = [LenField("len", 16), 

175 ShortEnumField("type", 1, _PPTP_msg_type), 

176 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

177 ShortEnumField("ctrl_msg_type", 5, _PPTP_ctrl_msg_type), 

178 XShortField("reserved_0", 0x0000), 

179 IntField("identifier", None)] 

180 

181 

182_PPTP_echo_result = {1: "OK", 

183 2: "General error"} 

184 

185 

186class PPTPEchoReply(PPTP): 

187 name = "PPTP Echo Reply" 

188 fields_desc = [LenField("len", 20), 

189 ShortEnumField("type", 1, _PPTP_msg_type), 

190 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

191 ShortEnumField("ctrl_msg_type", 6, _PPTP_ctrl_msg_type), 

192 XShortField("reserved_0", 0x0000), 

193 IntField("identifier", None), 

194 ByteEnumField("result_code", 1, _PPTP_echo_result), 

195 ByteEnumField("error_code", 0, _PPTP_general_error_code), 

196 XShortField("reserved_1", 0x0000)] 

197 

198 def answers(self, other): 

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

200 

201 

202_PPTP_bearer_type = {1: "Analog channel", 

203 2: "Digital channel", 

204 3: "Any type of channel"} 

205 

206_PPTP_framing_type = {1: "Asynchronous framing", 

207 2: "Synchronous framing", 

208 3: "Any type of framing"} 

209 

210 

211class PPTPOutgoingCallRequest(PPTP): 

212 name = "PPTP Outgoing Call Request" 

213 fields_desc = [LenField("len", 168), 

214 ShortEnumField("type", 1, _PPTP_msg_type), 

215 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

216 ShortEnumField("ctrl_msg_type", 7, _PPTP_ctrl_msg_type), 

217 XShortField("reserved_0", 0x0000), 

218 ShortField("call_id", 1), 

219 ShortField("call_serial_number", 0), 

220 IntField("minimum_bps", 32768), 

221 IntField("maximum_bps", 2147483648), 

222 IntEnumField("bearer_type", 3, _PPTP_bearer_type), 

223 IntEnumField("framing_type", 3, _PPTP_framing_type), 

224 ShortField("pkt_window_size", 16), 

225 ShortField("pkt_proc_delay", 0), 

226 ShortField('phone_number_len', 0), 

227 XShortField("reserved_1", 0x0000), 

228 StrFixedLenField("phone_number", '', 64), 

229 StrFixedLenField("subaddress", '', 64)] 

230 

231 

232_PPTP_result_code = {1: "Connected", 

233 2: "General error", 

234 3: "No Carrier", 

235 4: "Busy", 

236 5: "No dial tone", 

237 6: "Time-out", 

238 7: "Do not accept"} 

239 

240 

241class PPTPOutgoingCallReply(PPTP): 

242 name = "PPTP Outgoing Call Reply" 

243 fields_desc = [LenField("len", 32), 

244 ShortEnumField("type", 1, _PPTP_msg_type), 

245 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

246 ShortEnumField("ctrl_msg_type", 8, _PPTP_ctrl_msg_type), 

247 XShortField("reserved_0", 0x0000), 

248 ShortField("call_id", 1), 

249 ShortField("peer_call_id", 1), 

250 ByteEnumField("result_code", 1, _PPTP_result_code), 

251 ByteEnumField("error_code", 0, _PPTP_general_error_code), 

252 ShortField("cause_code", 0), 

253 IntField("connect_speed", 100000000), 

254 ShortField("pkt_window_size", 16), 

255 ShortField("pkt_proc_delay", 0), 

256 IntField("channel_id", 0)] 

257 

258 def answers(self, other): 

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

260 

261 

262class PPTPIncomingCallRequest(PPTP): 

263 name = "PPTP Incoming Call Request" 

264 fields_desc = [LenField("len", 220), 

265 ShortEnumField("type", 1, _PPTP_msg_type), 

266 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

267 ShortEnumField("ctrl_msg_type", 9, _PPTP_ctrl_msg_type), 

268 XShortField("reserved_0", 0x0000), 

269 ShortField("call_id", 1), 

270 ShortField("call_serial_number", 1), 

271 IntEnumField("bearer_type", 3, _PPTP_bearer_type), 

272 IntField("channel_id", 0), 

273 ShortField("dialed_number_len", 0), 

274 ShortField("dialing_number_len", 0), 

275 StrFixedLenField("dialed_number", "", 64), 

276 StrFixedLenField("dialing_number", "", 64), 

277 StrFixedLenField("subaddress", "", 64)] 

278 

279 

280class PPTPIncomingCallReply(PPTP): 

281 name = "PPTP Incoming Call Reply" 

282 fields_desc = [LenField("len", 148), 

283 ShortEnumField("type", 1, _PPTP_msg_type), 

284 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

285 ShortEnumField("ctrl_msg_type", 10, _PPTP_ctrl_msg_type), 

286 XShortField("reserved_0", 0x0000), 

287 ShortField("call_id", 1), 

288 ShortField("peer_call_id", 1), 

289 ByteEnumField("result_code", 1, _PPTP_result_code), 

290 ByteEnumField("error_code", 0, _PPTP_general_error_code), 

291 ShortField("pkt_window_size", 64), 

292 ShortField("pkt_transmit_delay", 0), 

293 XShortField("reserved_1", 0x0000)] 

294 

295 def answers(self, other): 

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

297 

298 

299class PPTPIncomingCallConnected(PPTP): 

300 name = "PPTP Incoming Call Connected" 

301 fields_desc = [LenField("len", 28), 

302 ShortEnumField("type", 1, _PPTP_msg_type), 

303 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

304 ShortEnumField("ctrl_msg_type", 11, _PPTP_ctrl_msg_type), 

305 XShortField("reserved_0", 0x0000), 

306 ShortField("peer_call_id", 1), 

307 XShortField("reserved_1", 0x0000), 

308 IntField("connect_speed", 100000000), 

309 ShortField("pkt_window_size", 64), 

310 ShortField("pkt_transmit_delay", 0), 

311 IntEnumField("framing_type", 1, _PPTP_framing_type)] 

312 

313 def answers(self, other): 

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

315 

316 

317class PPTPCallClearRequest(PPTP): 

318 name = "PPTP Call Clear Request" 

319 fields_desc = [LenField("len", 16), 

320 ShortEnumField("type", 1, _PPTP_msg_type), 

321 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

322 ShortEnumField("ctrl_msg_type", 12, _PPTP_ctrl_msg_type), 

323 XShortField("reserved_0", 0x0000), 

324 ShortField("call_id", 1), 

325 XShortField("reserved_1", 0x0000)] 

326 

327 

328_PPTP_call_disconnect_result = {1: "Lost Carrier", 

329 2: "General error", 

330 3: "Admin Shutdown", 

331 4: "Request"} 

332 

333 

334class PPTPCallDisconnectNotify(PPTP): 

335 name = "PPTP Call Disconnect Notify" 

336 fields_desc = [LenField("len", 148), 

337 ShortEnumField("type", 1, _PPTP_msg_type), 

338 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

339 ShortEnumField("ctrl_msg_type", 13, _PPTP_ctrl_msg_type), 

340 XShortField("reserved_0", 0x0000), 

341 ShortField("call_id", 1), 

342 ByteEnumField("result_code", 1, 

343 _PPTP_call_disconnect_result), 

344 ByteEnumField("error_code", 0, _PPTP_general_error_code), 

345 ShortField("cause_code", 0), 

346 XShortField("reserved_1", 0x0000), 

347 StrFixedLenField("call_statistic", "", 128)] 

348 

349 

350class PPTPWANErrorNotify(PPTP): 

351 name = "PPTP WAN Error Notify" 

352 fields_desc = [LenField("len", 40), 

353 ShortEnumField("type", 1, _PPTP_msg_type), 

354 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

355 ShortEnumField("ctrl_msg_type", 14, _PPTP_ctrl_msg_type), 

356 XShortField("reserved_0", 0x0000), 

357 ShortField("peer_call_id", 1), 

358 XShortField("reserved_1", 0x0000), 

359 IntField("crc_errors", 0), 

360 IntField("framing_errors", 0), 

361 IntField("hardware_overruns", 0), 

362 IntField("buffer_overruns", 0), 

363 IntField("time_out_errors", 0), 

364 IntField("alignment_errors", 0)] 

365 

366 

367class PPTPSetLinkInfo(PPTP): 

368 name = "PPTP Set Link Info" 

369 fields_desc = [LenField("len", 24), 

370 ShortEnumField("type", 1, _PPTP_msg_type), 

371 XIntField("magic_cookie", _PPTP_MAGIC_COOKIE), 

372 ShortEnumField("ctrl_msg_type", 15, _PPTP_ctrl_msg_type), 

373 XShortField("reserved_0", 0x0000), 

374 ShortField("peer_call_id", 1), 

375 XShortField("reserved_1", 0x0000), 

376 XIntField("send_accm", 0x00000000), 

377 XIntField("receive_accm", 0x00000000)] 

378 

379 

380bind_layers(TCP, PPTP, sport=1723) 

381bind_layers(TCP, PPTP, dport=1723)