Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/scapy/layers/kerberos.py: 38%

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

1318 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) Gabriel Potter 

5 

6r""" 

7Kerberos V5 

8 

9Implements parts of: 

10 

11- Kerberos Network Authentication Service (V5): RFC4120 

12- Kerberos Version 5 GSS-API: RFC1964, RFC4121 

13- Kerberos Pre-Authentication: RFC6113 (FAST) 

14- Kerberos Principal Name Canonicalization and Cross-Realm Referrals: RFC6806 

15- Microsoft Windows 2000 Kerberos Change Password and Set Password Protocols: RFC3244 

16- User to User Kerberos Authentication: draft-ietf-cat-user2user-03 

17- Public Key Cryptography Based User-to-User Authentication (PKU2U): draft-zhu-pku2u-09 

18- Initial and Pass Through Authentication Using Kerberos V5 (IAKERB): 

19 draft-ietf-kitten-iakerb-03 

20- Kerberos Protocol Extensions: [MS-KILE] 

21- Kerberos Protocol Extensions: Service for User: [MS-SFU] 

22 

23 

24.. note:: 

25 You will find more complete documentation for this layer over at 

26 `Kerberos <https://scapy.readthedocs.io/en/latest/layers/kerberos.html>`_ 

27 

28Example decryption:: 

29 

30 >>> from scapy.libs.rfc3961 import Key, EncryptionType 

31 >>> pkt = Ether(hex_bytes("525400695813525400216c2b08004500015da71840008006dc\ 

32 83c0a87a9cc0a87a11c209005854f6ab2392c25bd650182014b6e00000000001316a8201\ 

33 2d30820129a103020105a20302010aa3633061304ca103020102a24504433041a0030201\ 

34 12a23a043848484decb01c9b62a1cabfbc3f2d1ed85aa5e093ba8358a8cea34d4393af93\ 

35 bf211e274fa58e814878db9f0d7a28d94e7327660db4f3704b3011a10402020080a20904\ 

36 073005a0030101ffa481b73081b4a00703050040810010a1123010a003020101a1093007\ 

37 1b0577696e3124a20e1b0c444f4d41494e2e4c4f43414ca321301fa003020102a1183016\ 

38 1b066b72627467741b0c444f4d41494e2e4c4f43414ca511180f32303337303931333032\ 

39 343830355aa611180f32303337303931333032343830355aa7060204701cc5d1a8153013\ 

40 0201120201110201170201180202ff79020103a91d301b3019a003020114a11204105749\ 

41 4e31202020202020202020202020")) 

42 >>> enc = pkt[Kerberos].root.padata[0].padataValue 

43 >>> k = Key(enc.etype.val, key=hex_bytes("7fada4e566ae4fb270e2800a23a\ 

44 e87127a819d42e69b5e22de0ddc63da80096d")) 

45 >>> enc.decrypt(k) 

46""" 

47 

48from collections import namedtuple 

49from datetime import datetime, timedelta, timezone 

50from enum import IntEnum 

51 

52import os 

53import re 

54import socket 

55import struct 

56 

57from scapy.error import warning 

58import scapy.asn1.mib # noqa: F401 

59from scapy.asn1.ber import BER_id_dec, BER_Decoding_Error 

60from scapy.asn1.asn1 import ( 

61 ASN1_BIT_STRING, 

62 ASN1_BOOLEAN, 

63 ASN1_Class, 

64 ASN1_GENERAL_STRING, 

65 ASN1_GENERALIZED_TIME, 

66 ASN1_INTEGER, 

67 ASN1_STRING, 

68 ASN1_Codecs, 

69) 

70from scapy.asn1fields import ( 

71 ASN1F_BOOLEAN, 

72 ASN1F_CHOICE, 

73 ASN1F_FLAGS, 

74 ASN1F_GENERAL_STRING, 

75 ASN1F_GENERALIZED_TIME, 

76 ASN1F_INTEGER, 

77 ASN1F_OID, 

78 ASN1F_PACKET, 

79 ASN1F_SEQUENCE, 

80 ASN1F_SEQUENCE_OF, 

81 ASN1F_STRING, 

82 ASN1F_enum_INTEGER, 

83 ASN1F_optional, 

84) 

85from scapy.asn1packet import ASN1_Packet 

86from scapy.automaton import Automaton, ATMT 

87from scapy.compat import bytes_encode 

88from scapy.error import log_runtime 

89from scapy.fields import ( 

90 ConditionalField, 

91 FieldLenField, 

92 FlagsField, 

93 IntEnumField, 

94 LEIntEnumField, 

95 LenField, 

96 LEShortEnumField, 

97 LEShortField, 

98 LongField, 

99 MultipleTypeField, 

100 PacketField, 

101 PacketLenField, 

102 PacketListField, 

103 PadField, 

104 ShortEnumField, 

105 ShortField, 

106 StrField, 

107 StrFieldUtf16, 

108 StrFixedLenEnumField, 

109 XByteField, 

110 XLEIntField, 

111 XLEShortField, 

112 XStrFixedLenField, 

113 XStrLenField, 

114 XStrField, 

115) 

116from scapy.packet import Packet, bind_bottom_up, bind_top_down, bind_layers 

117from scapy.supersocket import StreamSocket 

118from scapy.utils import strrot, strxor 

119from scapy.volatile import GeneralizedTime, RandNum, RandBin 

120 

121from scapy.layers.gssapi import ( 

122 GSSAPI_BLOB, 

123 GSS_C_FLAGS, 

124 GSS_S_BAD_MECH, 

125 GSS_S_COMPLETE, 

126 GSS_S_CONTINUE_NEEDED, 

127 GSS_S_DEFECTIVE_TOKEN, 

128 GSS_S_FAILURE, 

129 GssChannelBindings, 

130 SSP, 

131 _GSSAPI_OIDS, 

132 _GSSAPI_SIGNATURE_OIDS, 

133) 

134from scapy.layers.inet import TCP, UDP 

135 

136# Typing imports 

137from typing import ( 

138 Optional, 

139) 

140 

141 

142# kerberos APPLICATION 

143 

144 

145class ASN1_Class_KRB(ASN1_Class): 

146 name = "Kerberos" 

147 # APPLICATION + CONSTRUCTED = 0x40 | 0x20 

148 Token = 0x60 | 0 # GSSAPI 

149 Ticket = 0x60 | 1 

150 Authenticator = 0x60 | 2 

151 EncTicketPart = 0x60 | 3 

152 AS_REQ = 0x60 | 10 

153 AS_REP = 0x60 | 11 

154 TGS_REQ = 0x60 | 12 

155 TGS_REP = 0x60 | 13 

156 AP_REQ = 0x60 | 14 

157 AP_REP = 0x60 | 15 

158 PRIV = 0x60 | 21 

159 CRED = 0x60 | 22 

160 EncASRepPart = 0x60 | 25 

161 EncTGSRepPart = 0x60 | 26 

162 EncAPRepPart = 0x60 | 27 

163 EncKrbPrivPart = 0x60 | 28 

164 EncKrbCredPart = 0x60 | 29 

165 ERROR = 0x60 | 30 

166 

167 

168# RFC4120 sect 5.2 

169 

170 

171KerberosString = ASN1F_GENERAL_STRING 

172Realm = KerberosString 

173Int32 = ASN1F_INTEGER 

174UInt32 = ASN1F_INTEGER 

175 

176_PRINCIPAL_NAME_TYPES = { 

177 0: "NT-UNKNOWN", 

178 1: "NT-PRINCIPAL", 

179 2: "NT-SRV-INST", 

180 3: "NT-SRV-HST", 

181 4: "NT-SRV-XHST", 

182 5: "NT-UID", 

183 6: "NT-X500-PRINCIPAL", 

184 7: "NT-SMTP-NAME", 

185 10: "NT-ENTERPRISE", 

186} 

187 

188 

189class PrincipalName(ASN1_Packet): 

190 ASN1_codec = ASN1_Codecs.BER 

191 ASN1_root = ASN1F_SEQUENCE( 

192 ASN1F_enum_INTEGER( 

193 "nameType", 

194 0, 

195 _PRINCIPAL_NAME_TYPES, 

196 explicit_tag=0xA0, 

197 ), 

198 ASN1F_SEQUENCE_OF("nameString", [], KerberosString, explicit_tag=0xA1), 

199 ) 

200 

201 @staticmethod 

202 def fromUPN(upn: str): 

203 user, _ = _parse_upn(upn) 

204 return PrincipalName( 

205 nameString=[ASN1_GENERAL_STRING(user)], 

206 nameType=ASN1_INTEGER(1), # NT-PRINCIPAL 

207 ) 

208 

209 @staticmethod 

210 def fromSPN(spn: bytes): 

211 spn, _ = _parse_spn(spn) 

212 if spn.startswith("krbtgt"): 

213 return PrincipalName( 

214 nameString=[ASN1_GENERAL_STRING(x) for x in spn.split("/")], 

215 nameType=ASN1_INTEGER(2), # NT-SRV-INST 

216 ) 

217 else: 

218 return PrincipalName( 

219 nameString=[ASN1_GENERAL_STRING(x) for x in spn.split("/")], 

220 nameType=ASN1_INTEGER(3), # NT-SRV-HST 

221 ) 

222 

223 

224KerberosTime = ASN1F_GENERALIZED_TIME 

225Microseconds = ASN1F_INTEGER 

226 

227 

228# https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml#kerberos-parameters-1 

229 

230_KRB_E_TYPES = { 

231 1: "DES-CBC-CRC", 

232 2: "DES-CBC-MD4", 

233 3: "DES-CBC-MD5", 

234 5: "DES3-CBC-MD5", 

235 7: "DES3-CBC-SHA1", 

236 9: "DSAWITHSHA1-CMSOID", 

237 10: "MD5WITHRSAENCRYPTION-CMSOID", 

238 11: "SHA1WITHRSAENCRYPTION-CMSOID", 

239 12: "RC2CBC-ENVOID", 

240 13: "RSAENCRYPTION-ENVOID", 

241 14: "RSAES-OAEP-ENV-OID", 

242 15: "DES-EDE3-CBC-ENV-OID", 

243 16: "DES3-CBC-SHA1-KD", 

244 17: "AES128-CTS-HMAC-SHA1-96", 

245 18: "AES256-CTS-HMAC-SHA1-96", 

246 19: "AES128-CTS-HMAC-SHA256-128", 

247 20: "AES256-CTS-HMAC-SHA384-192", 

248 23: "RC4-HMAC", 

249 24: "RC4-HMAC-EXP", 

250 25: "CAMELLIA128-CTS-CMAC", 

251 26: "CAMELLIA256-CTS-CMAC", 

252} 

253 

254# https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml#kerberos-parameters-2 

255 

256_KRB_S_TYPES = { 

257 1: "CRC32", 

258 2: "RSA-MD4", 

259 3: "RSA-MD4-DES", 

260 4: "DES-MAC", 

261 5: "DES-MAC-K", 

262 6: "RSA-MD4-DES-K", 

263 7: "RSA-MD5", 

264 8: "RSA-MD5-DES", 

265 9: "RSA-MD5-DES3", 

266 10: "SHA1", 

267 12: "HMAC-SHA1-DES3-KD", 

268 13: "HMAC-SHA1-DES3", 

269 14: "SHA1", 

270 15: "HMAC-SHA1-96-AES128", 

271 16: "HMAC-SHA1-96-AES256", 

272 17: "CMAC-CAMELLIA128", 

273 18: "CMAC-CAMELLIA256", 

274 19: "HMAC-SHA256-128-AES128", 

275 20: "HMAC-SHA384-192-AES256", 

276 # RFC 4121 

277 0x8003: "KRB-AUTHENTICATOR", 

278 # [MS-KILE] 

279 0xFFFFFF76: "MD5", 

280} 

281 

282 

283class EncryptedData(ASN1_Packet): 

284 ASN1_codec = ASN1_Codecs.BER 

285 ASN1_root = ASN1F_SEQUENCE( 

286 ASN1F_enum_INTEGER("etype", 0x17, _KRB_E_TYPES, explicit_tag=0xA0), 

287 ASN1F_optional(UInt32("kvno", None, explicit_tag=0xA1)), 

288 ASN1F_STRING("cipher", "", explicit_tag=0xA2), 

289 ) 

290 

291 def get_usage(self): 

292 """ 

293 Get current key usage number and encrypted class 

294 """ 

295 # RFC 4120 sect 7.5.1 

296 if self.underlayer: 

297 if isinstance(self.underlayer, PADATA): 

298 patype = self.underlayer.padataType 

299 if patype == 2: 

300 # AS-REQ PA-ENC-TIMESTAMP padata timestamp 

301 return 1, PA_ENC_TS_ENC 

302 elif isinstance(self.underlayer, KRB_Ticket): 

303 # AS-REP Ticket and TGS-REP Ticket 

304 return 2, EncTicketPart 

305 elif isinstance(self.underlayer, KRB_AS_REP): 

306 # AS-REP encrypted part 

307 return 3, EncASRepPart 

308 elif isinstance(self.underlayer, KRB_AP_REQ) and isinstance( 

309 self.underlayer.underlayer, PADATA 

310 ): 

311 # TGS-REQ PA-TGS-REQ Authenticator 

312 return 7, KRB_Authenticator 

313 elif isinstance(self.underlayer, KRB_TGS_REP): 

314 # TGS-REP encrypted part 

315 return 8, EncTGSRepPart 

316 elif isinstance(self.underlayer, KRB_AP_REQ): 

317 # AP-REQ Authenticator 

318 return 11, KRB_Authenticator 

319 elif isinstance(self.underlayer, KRB_AP_REP): 

320 # AP-REP encrypted part 

321 return 12, EncAPRepPart 

322 elif isinstance(self.underlayer, KRB_PRIV): 

323 # KRB-PRIV encrypted part 

324 return 13, EncKrbPrivPart 

325 elif isinstance(self.underlayer, KRB_CRED): 

326 # KRB-CRED encrypted part 

327 return 14, EncKrbCredPart 

328 elif isinstance(self.underlayer, KrbFastArmoredReq): 

329 # KEY_USAGE_FAST_ENC 

330 return 51, KrbFastReq 

331 raise ValueError( 

332 "Could not guess key usage number. Please specify key_usage_number" 

333 ) 

334 

335 def decrypt(self, key, key_usage_number=None, cls=None): 

336 """ 

337 Decrypt and return the data contained in cipher. 

338 

339 :param key: the key to use for decryption 

340 :param key_usage_number: (optional) specify the key usage number. 

341 Guessed otherwise 

342 :param cls: (optional) the class of the decrypted payload 

343 Guessed otherwise (or bytes) 

344 """ 

345 if key_usage_number is None: 

346 key_usage_number, cls = self.get_usage() 

347 d = key.decrypt(key_usage_number, self.cipher.val) 

348 if cls: 

349 try: 

350 return cls(d) 

351 except BER_Decoding_Error: 

352 if cls == EncASRepPart: 

353 # https://datatracker.ietf.org/doc/html/rfc4120#section-5.4.2 

354 # "Compatibility note: Some implementations unconditionally send an 

355 # encrypted EncTGSRepPart (application tag number 26) in this field 

356 # regardless of whether the reply is a AS-REP or a TGS-REP. In the 

357 # interest of compatibility, implementors MAY relax the check on the 

358 # tag number of the decrypted ENC-PART." 

359 try: 

360 res = EncTGSRepPart(d) 

361 # https://github.com/krb5/krb5/blob/48ccd81656381522d1f9ccb8705c13f0266a46ab/src/lib/krb5/asn.1/asn1_k_encode.c#L1128 

362 # This is a bug because as the RFC clearly says above, we're 

363 # perfectly in our right to be strict on this. (MAY) 

364 log_runtime.warning( 

365 "Implementation bug detected. This looks like MIT Kerberos." 

366 ) 

367 return res 

368 except BER_Decoding_Error: 

369 pass 

370 raise 

371 return d 

372 

373 def encrypt(self, key, text, confounder=None, key_usage_number=None): 

374 """ 

375 Encrypt text and set it into cipher. 

376 

377 :param key: the key to use for encryption 

378 :param text: the bytes value to encode 

379 :param confounder: (optional) specify the confounder bytes. Random otherwise 

380 :param key_usage_number: (optional) specify the key usage number. 

381 Guessed otherwise 

382 """ 

383 if key_usage_number is None: 

384 key_usage_number = self.get_usage()[0] 

385 self.etype = key.etype 

386 self.cipher = ASN1_STRING( 

387 key.encrypt(key_usage_number, text, confounder=confounder) 

388 ) 

389 

390 

391class EncryptionKey(ASN1_Packet): 

392 ASN1_codec = ASN1_Codecs.BER 

393 ASN1_root = ASN1F_SEQUENCE( 

394 ASN1F_enum_INTEGER("keytype", 0, _KRB_E_TYPES, explicit_tag=0xA0), 

395 ASN1F_STRING("keyvalue", "", explicit_tag=0xA1), 

396 ) 

397 

398 def toKey(self): 

399 from scapy.libs.rfc3961 import Key 

400 

401 return Key( 

402 etype=self.keytype.val, 

403 key=self.keyvalue.val, 

404 ) 

405 

406 @classmethod 

407 def fromKey(self, key): 

408 return EncryptionKey( 

409 keytype=key.etype, 

410 keyvalue=key.key, 

411 ) 

412 

413 

414class _ASN1FString_PacketField(ASN1F_STRING): 

415 holds_packets = 1 

416 

417 def i2m(self, pkt, val): 

418 if isinstance(val, ASN1_Packet): 

419 val = ASN1_STRING(bytes(val)) 

420 return super(_ASN1FString_PacketField, self).i2m(pkt, val) 

421 

422 def any2i(self, pkt, x): 

423 if hasattr(x, "add_underlayer"): 

424 x.add_underlayer(pkt) 

425 return super(_ASN1FString_PacketField, self).any2i(pkt, x) 

426 

427 

428class _Checksum_Field(_ASN1FString_PacketField): 

429 def m2i(self, pkt, s): 

430 val = super(_Checksum_Field, self).m2i(pkt, s) 

431 if not val[0].val: 

432 return val 

433 if pkt.cksumtype.val == 0x8003: 

434 # Special case per RFC 4121 

435 return KRB_AuthenticatorChecksum(val[0].val, _underlayer=pkt), val[1] 

436 return val 

437 

438 

439class Checksum(ASN1_Packet): 

440 ASN1_codec = ASN1_Codecs.BER 

441 ASN1_root = ASN1F_SEQUENCE( 

442 ASN1F_enum_INTEGER( 

443 "cksumtype", 

444 0, 

445 _KRB_S_TYPES, 

446 explicit_tag=0xA0, 

447 ), 

448 _Checksum_Field("checksum", "", explicit_tag=0xA1), 

449 ) 

450 

451 def get_usage(self): 

452 """ 

453 Get current key usage number 

454 """ 

455 # RFC 4120 sect 7.5.1 

456 if self.underlayer: 

457 if isinstance(self.underlayer, KRB_Authenticator): 

458 # TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator cksum 

459 # (n°10 should never happen as we use RFC4121) 

460 return 6 

461 elif isinstance(self.underlayer, PA_FOR_USER): 

462 # [MS-SFU] sect 2.2.1 

463 return 17 

464 elif isinstance(self.underlayer, PA_S4U_X509_USER): 

465 # [MS-SFU] sect 2.2.1 

466 return 17 

467 elif isinstance(self.underlayer, AD_KDCIssued): 

468 # AD-KDC-ISSUED checksum 

469 return 19 

470 elif isinstance(self.underlayer, KrbFastArmoredReq): 

471 # KEY_USAGE_FAST_REQ_CHKSUM 

472 return 50 

473 raise ValueError( 

474 "Could not guess key usage number. Please specify key_usage_number" 

475 ) 

476 

477 def verify(self, key, text, key_usage_number=None): 

478 """ 

479 Decrypt and return the data contained in cipher. 

480 

481 :param key: the key to use to check the checksum 

482 :param text: the bytes to verify 

483 :param key_usage_number: (optional) specify the key usage number. 

484 Guessed otherwise 

485 """ 

486 if key_usage_number is None: 

487 key_usage_number = self.get_usage() 

488 key.verify_checksum(key_usage_number, text, self.checksum.val) 

489 

490 def make(self, key, text, key_usage_number=None, cksumtype=None): 

491 """ 

492 Encrypt text and set it into cipher. 

493 

494 :param key: the key to use to make the checksum 

495 :param text: the bytes to make a checksum of 

496 :param key_usage_number: (optional) specify the key usage number. 

497 Guessed otherwise 

498 """ 

499 if key_usage_number is None: 

500 key_usage_number = self.get_usage() 

501 self.cksumtype = cksumtype or key.cksumtype 

502 self.checksum = ASN1_STRING( 

503 key.make_checksum( 

504 keyusage=key_usage_number, 

505 text=text, 

506 cksumtype=self.cksumtype, 

507 ) 

508 ) 

509 

510 

511KerberosFlags = ASN1F_FLAGS 

512 

513_ADDR_TYPES = { 

514 # RFC4120 sect 7.5.3 

515 0x02: "IPv4", 

516 0x03: "Directional", 

517 0x05: "ChaosNet", 

518 0x06: "XNS", 

519 0x07: "ISO", 

520 0x0C: "DECNET Phase IV", 

521 0x10: "AppleTalk DDP", 

522 0x14: "NetBios", 

523 0x18: "IPv6", 

524} 

525 

526 

527class HostAddress(ASN1_Packet): 

528 ASN1_codec = ASN1_Codecs.BER 

529 ASN1_root = ASN1F_SEQUENCE( 

530 ASN1F_enum_INTEGER( 

531 "addrType", 

532 0, 

533 _ADDR_TYPES, 

534 explicit_tag=0xA0, 

535 ), 

536 ASN1F_STRING("address", "", explicit_tag=0xA1), 

537 ) 

538 

539 

540HostAddresses = lambda name, **kwargs: ASN1F_SEQUENCE_OF( 

541 name, [], HostAddress, **kwargs 

542) 

543 

544 

545_AUTHORIZATIONDATA_VALUES = { 

546 # Filled below 

547} 

548 

549 

550class _AuthorizationData_value_Field(_ASN1FString_PacketField): 

551 def m2i(self, pkt, s): 

552 val = super(_AuthorizationData_value_Field, self).m2i(pkt, s) 

553 if not val[0].val: 

554 return val 

555 if pkt.adType.val in _AUTHORIZATIONDATA_VALUES: 

556 return ( 

557 _AUTHORIZATIONDATA_VALUES[pkt.adType.val](val[0].val, _underlayer=pkt), 

558 val[1], 

559 ) 

560 return val 

561 

562 

563_AD_TYPES = { 

564 # RFC4120 sect 7.5.4 

565 1: "AD-IF-RELEVANT", 

566 2: "AD-INTENDED-FOR-SERVER", 

567 3: "AD-INTENDED-FOR-APPLICATION-CLASS", 

568 4: "AD-KDC-ISSUED", 

569 5: "AD-AND-OR", 

570 6: "AD-MANDATORY-TICKET-EXTENSIONS", 

571 7: "AD-IN-TICKET-EXTENSIONS", 

572 8: "AD-MANDATORY-FOR-KDC", 

573 64: "OSF-DCE", 

574 65: "SESAME", 

575 66: "AD-OSD-DCE-PKI-CERTID", 

576 128: "AD-WIN2K-PAC", 

577 129: "AD-ETYPE-NEGOTIATION", 

578 # [MS-KILE] additions 

579 141: "KERB-AUTH-DATA-TOKEN-RESTRICTIONS", 

580 142: "KERB-LOCAL", 

581 143: "AD-AUTH-DATA-AP-OPTIONS", 

582 144: "AD-TARGET-PRINCIPAL", # not an official name 

583} 

584 

585 

586class AuthorizationDataItem(ASN1_Packet): 

587 ASN1_codec = ASN1_Codecs.BER 

588 ASN1_root = ASN1F_SEQUENCE( 

589 ASN1F_enum_INTEGER( 

590 "adType", 

591 0, 

592 _AD_TYPES, 

593 explicit_tag=0xA0, 

594 ), 

595 _AuthorizationData_value_Field("adData", "", explicit_tag=0xA1), 

596 ) 

597 

598 

599class AuthorizationData(ASN1_Packet): 

600 ASN1_codec = ASN1_Codecs.BER 

601 ASN1_root = ASN1F_SEQUENCE_OF( 

602 "seq", [AuthorizationDataItem()], AuthorizationDataItem 

603 ) 

604 

605 

606AD_IF_RELEVANT = AuthorizationData 

607_AUTHORIZATIONDATA_VALUES[1] = AD_IF_RELEVANT 

608 

609 

610class AD_KDCIssued(ASN1_Packet): 

611 ASN1_codec = ASN1_Codecs.BER 

612 ASN1_root = ASN1F_SEQUENCE( 

613 ASN1F_PACKET("adChecksum", Checksum(), Checksum, explicit_tag=0xA0), 

614 ASN1F_optional( 

615 Realm("iRealm", "", explicit_tag=0xA1), 

616 ), 

617 ASN1F_optional(ASN1F_PACKET("iSname", None, PrincipalName, explicit_tag=0xA2)), 

618 ASN1F_PACKET("elements", None, AuthorizationData, explicit_tag=0xA3), 

619 ) 

620 

621 

622_AUTHORIZATIONDATA_VALUES[4] = AD_KDCIssued 

623 

624 

625class AD_AND_OR(ASN1_Packet): 

626 ASN1_codec = ASN1_Codecs.BER 

627 ASN1_root = ASN1F_SEQUENCE( 

628 Int32("conditionCount", 0, explicit_tag=0xA0), 

629 ASN1F_PACKET("elements", None, AuthorizationData, explicit_tag=0xA1), 

630 ) 

631 

632 

633_AUTHORIZATIONDATA_VALUES[5] = AD_AND_OR 

634 

635ADMANDATORYFORKDC = AuthorizationData 

636_AUTHORIZATIONDATA_VALUES[8] = ADMANDATORYFORKDC 

637 

638 

639# https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xml 

640_PADATA_TYPES = { 

641 1: "PA-TGS-REQ", 

642 2: "PA-ENC-TIMESTAMP", 

643 3: "PA-PW-SALT", 

644 11: "PA-ETYPE-INFO", 

645 14: "PA-PK-AS-REQ-OLD", 

646 15: "PA-PK-AS-REP-OLD", 

647 16: "PA-PK-AS-REQ", 

648 17: "PA-PK-AS-REP", 

649 19: "PA-ETYPE-INFO2", 

650 20: "PA-SVR-REFERRAL-INFO", 

651 128: "PA-PAC-REQUEST", 

652 129: "PA-FOR-USER", 

653 130: "PA-FOR-X509-USER", 

654 131: "PA-FOR-CHECK_DUPS", 

655 132: "PA-AS-CHECKSUM", 

656 133: "PA-FX-COOKIE", 

657 134: "PA-AUTHENTICATION-SET", 

658 135: "PA-AUTH-SET-SELECTED", 

659 136: "PA-FX-FAST", 

660 137: "PA-FX-ERROR", 

661 138: "PA-ENCRYPTED-CHALLENGE", 

662 141: "PA-OTP-CHALLENGE", 

663 142: "PA-OTP-REQUEST", 

664 143: "PA-OTP-CONFIRM", 

665 144: "PA-OTP-PIN-CHANGE", 

666 145: "PA-EPAK-AS-REQ", 

667 146: "PA-EPAK-AS-REP", 

668 147: "PA_PKINIT_KX", 

669 148: "PA_PKU2U_NAME", 

670 149: "PA-REQ-ENC-PA-REP", 

671 150: "PA_AS_FRESHNESS", 

672 151: "PA-SPAKE", 

673 165: "PA-SUPPORTED-ENCTYPES", 

674 166: "PA-EXTENDED-ERROR", 

675 167: "PA-PAC-OPTIONS", 

676} 

677 

678_PADATA_CLASSES = { 

679 # Filled elsewhere in this file 

680} 

681 

682 

683# RFC4120 

684 

685 

686class _PADATA_value_Field(_ASN1FString_PacketField): 

687 """ 

688 A special field that properly dispatches PA-DATA values according to 

689 padata-type and if the paquet is a request or a response. 

690 """ 

691 

692 def m2i(self, pkt, s): 

693 val = super(_PADATA_value_Field, self).m2i(pkt, s) 

694 if pkt.padataType.val in _PADATA_CLASSES: 

695 cls = _PADATA_CLASSES[pkt.padataType.val] 

696 if isinstance(cls, tuple): 

697 is_reply = ( 

698 pkt.underlayer.underlayer is not None 

699 and isinstance(pkt.underlayer.underlayer, KRB_ERROR) 

700 ) or isinstance(pkt.underlayer, (KRB_AS_REP, KRB_TGS_REP)) 

701 cls = cls[is_reply] 

702 if not val[0].val: 

703 return val 

704 return cls(val[0].val, _underlayer=pkt), val[1] 

705 return val 

706 

707 

708class PADATA(ASN1_Packet): 

709 ASN1_codec = ASN1_Codecs.BER 

710 ASN1_root = ASN1F_SEQUENCE( 

711 ASN1F_enum_INTEGER("padataType", 0, _PADATA_TYPES, explicit_tag=0xA1), 

712 _PADATA_value_Field( 

713 "padataValue", 

714 "", 

715 explicit_tag=0xA2, 

716 ), 

717 ) 

718 

719 

720# RFC 4120 sect 5.2.7.2 

721 

722 

723class PA_ENC_TS_ENC(ASN1_Packet): 

724 ASN1_codec = ASN1_Codecs.BER 

725 ASN1_root = ASN1F_SEQUENCE( 

726 KerberosTime("patimestamp", GeneralizedTime(), explicit_tag=0xA0), 

727 ASN1F_optional(Microseconds("pausec", 0, explicit_tag=0xA1)), 

728 ) 

729 

730 

731_PADATA_CLASSES[2] = EncryptedData 

732 

733 

734# RFC 4120 sect 5.2.7.4 

735 

736 

737class ETYPE_INFO_ENTRY(ASN1_Packet): 

738 ASN1_codec = ASN1_Codecs.BER 

739 ASN1_root = ASN1F_SEQUENCE( 

740 ASN1F_enum_INTEGER("etype", 0x1, _KRB_E_TYPES, explicit_tag=0xA0), 

741 ASN1F_optional( 

742 ASN1F_STRING("salt", "", explicit_tag=0xA1), 

743 ), 

744 ) 

745 

746 

747class ETYPE_INFO(ASN1_Packet): 

748 ASN1_codec = ASN1_Codecs.BER 

749 ASN1_root = ASN1F_SEQUENCE_OF("seq", [ETYPE_INFO_ENTRY()], ETYPE_INFO_ENTRY) 

750 

751 

752_PADATA_CLASSES[11] = ETYPE_INFO 

753 

754# RFC 4120 sect 5.2.7.5 

755 

756 

757class ETYPE_INFO_ENTRY2(ASN1_Packet): 

758 ASN1_codec = ASN1_Codecs.BER 

759 ASN1_root = ASN1F_SEQUENCE( 

760 ASN1F_enum_INTEGER("etype", 0x1, _KRB_E_TYPES, explicit_tag=0xA0), 

761 ASN1F_optional( 

762 KerberosString("salt", "", explicit_tag=0xA1), 

763 ), 

764 ASN1F_optional( 

765 ASN1F_STRING("s2kparams", "", explicit_tag=0xA2), 

766 ), 

767 ) 

768 

769 

770class ETYPE_INFO2(ASN1_Packet): 

771 ASN1_codec = ASN1_Codecs.BER 

772 ASN1_root = ASN1F_SEQUENCE_OF("seq", [ETYPE_INFO_ENTRY2()], ETYPE_INFO_ENTRY2) 

773 

774 

775_PADATA_CLASSES[19] = ETYPE_INFO2 

776 

777# PADATA Extended with RFC6113 

778 

779 

780class PA_AUTHENTICATION_SET_ELEM(ASN1_Packet): 

781 ASN1_codec = ASN1_Codecs.BER 

782 ASN1_root = ASN1F_SEQUENCE( 

783 Int32("paType", 0, explicit_tag=0xA0), 

784 ASN1F_optional( 

785 ASN1F_STRING("paHint", "", explicit_tag=0xA1), 

786 ), 

787 ASN1F_optional( 

788 ASN1F_STRING("paValue", "", explicit_tag=0xA2), 

789 ), 

790 ) 

791 

792 

793class PA_AUTHENTICATION_SET(ASN1_Packet): 

794 ASN1_codec = ASN1_Codecs.BER 

795 ASN1_root = ASN1F_SEQUENCE_OF( 

796 "elems", [PA_AUTHENTICATION_SET_ELEM()], PA_AUTHENTICATION_SET_ELEM 

797 ) 

798 

799 

800_PADATA_CLASSES[134] = PA_AUTHENTICATION_SET 

801 

802 

803# [MS-KILE] sect 2.2.3 

804 

805 

806class PA_PAC_REQUEST(ASN1_Packet): 

807 ASN1_codec = ASN1_Codecs.BER 

808 ASN1_root = ASN1F_SEQUENCE( 

809 ASN1F_BOOLEAN("includePac", True, explicit_tag=0xA0), 

810 ) 

811 

812 

813_PADATA_CLASSES[128] = PA_PAC_REQUEST 

814 

815 

816# [MS-KILE] sect 2.2.5 

817 

818 

819class LSAP_TOKEN_INFO_INTEGRITY(Packet): 

820 fields_desc = [ 

821 FlagsField( 

822 "Flags", 

823 0, 

824 -32, 

825 { 

826 0x00000001: "UAC-Restricted", 

827 }, 

828 ), 

829 LEIntEnumField( 

830 "TokenIL", 

831 0x00002000, 

832 { 

833 0x00000000: "Untrusted", 

834 0x00001000: "Low", 

835 0x00002000: "Medium", 

836 0x00003000: "High", 

837 0x00004000: "System", 

838 0x00005000: "Protected process", 

839 }, 

840 ), 

841 XStrFixedLenField("MachineID", b"", length=32), 

842 ] 

843 

844 

845# [MS-KILE] sect 2.2.6 

846 

847 

848class _KerbAdRestrictionEntry_Field(_ASN1FString_PacketField): 

849 def m2i(self, pkt, s): 

850 val = super(_KerbAdRestrictionEntry_Field, self).m2i(pkt, s) 

851 if not val[0].val: 

852 return val 

853 if pkt.restrictionType.val == 0x0000: # LSAP_TOKEN_INFO_INTEGRITY 

854 return LSAP_TOKEN_INFO_INTEGRITY(val[0].val, _underlayer=pkt), val[1] 

855 return val 

856 

857 

858class KERB_AD_RESTRICTION_ENTRY(ASN1_Packet): 

859 name = "KERB-AD-RESTRICTION-ENTRY" 

860 ASN1_codec = ASN1_Codecs.BER 

861 ASN1_root = ASN1F_SEQUENCE( 

862 ASN1F_SEQUENCE( 

863 ASN1F_enum_INTEGER( 

864 "restrictionType", 

865 0, 

866 {0: "LSAP_TOKEN_INFO_INTEGRITY"}, 

867 explicit_tag=0xA0, 

868 ), 

869 _KerbAdRestrictionEntry_Field("restriction", b"", explicit_tag=0xA1), 

870 ) 

871 ) 

872 

873 

874_AUTHORIZATIONDATA_VALUES[141] = KERB_AD_RESTRICTION_ENTRY 

875 

876 

877# [MS-KILE] sect 3.2.5.8 

878 

879 

880class KERB_AUTH_DATA_AP_OPTIONS(Packet): 

881 name = "KERB-AUTH-DATA-AP-OPTIONS" 

882 fields_desc = [ 

883 LEIntEnumField( 

884 "apOptions", 

885 0x4000, 

886 { 

887 0x4000: "KERB_AP_OPTIONS_CBT", 

888 }, 

889 ), 

890 ] 

891 

892 

893_AUTHORIZATIONDATA_VALUES[143] = KERB_AUTH_DATA_AP_OPTIONS 

894 

895 

896# This has no doc..? not in [MS-KILE] at least. 

897# We use the name wireshark/samba gave it 

898 

899 

900class KERB_AD_TARGET_PRINCIPAL(Packet): 

901 name = "KERB-AD-TARGET-PRINCIPAL" 

902 fields_desc = [ 

903 StrFieldUtf16("spn", ""), 

904 ] 

905 

906 

907_AUTHORIZATIONDATA_VALUES[144] = KERB_AD_TARGET_PRINCIPAL 

908 

909 

910# RFC6806 sect 6 

911 

912 

913class KERB_AD_LOGIN_ALIAS(ASN1_Packet): 

914 ASN1_codec = ASN1_Codecs.BER 

915 ASN1_root = ASN1F_SEQUENCE(ASN1F_SEQUENCE_OF("loginAliases", [], PrincipalName)) 

916 

917 

918_AUTHORIZATIONDATA_VALUES[80] = KERB_AD_LOGIN_ALIAS 

919 

920 

921# [MS-KILE] sect 2.2.8 

922 

923 

924class PA_SUPPORTED_ENCTYPES(Packet): 

925 fields_desc = [ 

926 FlagsField( 

927 "flags", 

928 0, 

929 -32, 

930 [ 

931 "DES-CBC-CRC", 

932 "DES-CBC-MD5", 

933 "RC4-HMAC", 

934 "AES128-CTS-HMAC-SHA1-96", 

935 "AES256-CTS-HMAC-SHA1-96", 

936 ] 

937 + ["bit_%d" % i for i in range(11)] 

938 + [ 

939 "FAST-supported", 

940 "Compount-identity-supported", 

941 "Claims-supported", 

942 "Resource-SID-compression-disabled", 

943 ], 

944 ) 

945 ] 

946 

947 

948_PADATA_CLASSES[165] = PA_SUPPORTED_ENCTYPES 

949 

950# [MS-KILE] sect 2.2.10 

951 

952 

953class PA_PAC_OPTIONS(ASN1_Packet): 

954 ASN1_codec = ASN1_Codecs.BER 

955 ASN1_root = ASN1F_SEQUENCE( 

956 KerberosFlags( 

957 "options", 

958 "", 

959 [ 

960 "Claims", 

961 "Branch-Aware", 

962 "Forward-to-Full-DC", 

963 "Resource-based-constrained-delegation", # [MS-SFU] 2.2.5 

964 ], 

965 explicit_tag=0xA0, 

966 ) 

967 ) 

968 

969 

970_PADATA_CLASSES[167] = PA_PAC_OPTIONS 

971 

972 

973# RFC6113 sect 5.4.1 

974 

975 

976class _KrbFastArmor_value_Field(_ASN1FString_PacketField): 

977 def m2i(self, pkt, s): 

978 val = super(_KrbFastArmor_value_Field, self).m2i(pkt, s) 

979 if not val[0].val: 

980 return val 

981 if pkt.armorType.val == 1: # FX_FAST_ARMOR_AP_REQUEST 

982 return KRB_AP_REQ(val[0].val, _underlayer=pkt), val[1] 

983 return val 

984 

985 

986class KrbFastArmor(ASN1_Packet): 

987 ASN1_codec = ASN1_Codecs.BER 

988 ASN1_root = ASN1F_SEQUENCE( 

989 ASN1F_enum_INTEGER( 

990 "armorType", 1, {1: "FX_FAST_ARMOR_AP_REQUEST"}, explicit_tag=0xA0 

991 ), 

992 _KrbFastArmor_value_Field("armorValue", "", explicit_tag=0xA1), 

993 ) 

994 

995 

996# RFC6113 sect 5.4.2 

997 

998 

999class KrbFastArmoredReq(ASN1_Packet): 

1000 ASN1_codec = ASN1_Codecs.BER 

1001 ASN1_root = ASN1F_SEQUENCE( 

1002 ASN1F_SEQUENCE( 

1003 ASN1F_optional( 

1004 ASN1F_PACKET("armor", KrbFastArmor(), KrbFastArmor, explicit_tag=0xA0) 

1005 ), 

1006 ASN1F_PACKET("reqChecksum", Checksum(), Checksum, explicit_tag=0xA1), 

1007 ASN1F_PACKET("encFastReq", None, EncryptedData, explicit_tag=0xA2), 

1008 ) 

1009 ) 

1010 

1011 

1012class PA_FX_FAST_REQUEST(ASN1_Packet): 

1013 ASN1_codec = ASN1_Codecs.BER 

1014 ASN1_root = ASN1F_CHOICE( 

1015 "armoredData", 

1016 ASN1_STRING(""), 

1017 ASN1F_PACKET("req", KrbFastArmoredReq, KrbFastArmoredReq, implicit_tag=0xA0), 

1018 ) 

1019 

1020 

1021# RFC6113 sect 5.4.3 

1022 

1023 

1024class KrbFastArmoredRep(ASN1_Packet): 

1025 ASN1_codec = ASN1_Codecs.BER 

1026 ASN1_root = ASN1F_SEQUENCE( 

1027 ASN1F_SEQUENCE( 

1028 ASN1F_PACKET("encFastRep", None, EncryptedData, explicit_tag=0xA0), 

1029 ) 

1030 ) 

1031 

1032 

1033class PA_FX_FAST_REPLY(ASN1_Packet): 

1034 ASN1_codec = ASN1_Codecs.BER 

1035 ASN1_root = ASN1F_CHOICE( 

1036 "armoredData", 

1037 ASN1_STRING(""), 

1038 ASN1F_PACKET("req", KrbFastArmoredRep, KrbFastArmoredRep, implicit_tag=0xA0), 

1039 ) 

1040 

1041 

1042class KrbFastFinished(ASN1_Packet): 

1043 ASN1_codec = ASN1_Codecs.BER 

1044 ASN1_root = ASN1F_SEQUENCE( 

1045 KerberosTime("timestamp", GeneralizedTime(), explicit_tag=0xA0), 

1046 Microseconds("usec", 0, explicit_tag=0xA1), 

1047 Realm("crealm", "", explicit_tag=0xA2), 

1048 ASN1F_PACKET("cname", None, PrincipalName, explicit_tag=0xA3), 

1049 ASN1F_PACKET("ticketChecksum", Checksum(), Checksum, explicit_tag=0xA4), 

1050 ) 

1051 

1052 

1053class KrbFastResponse(ASN1_Packet): 

1054 ASN1_codec = ASN1_Codecs.BER 

1055 ASN1_root = ASN1F_SEQUENCE( 

1056 ASN1F_SEQUENCE_OF("padata", [PADATA()], PADATA, explicit_tag=0xA0), 

1057 ASN1F_optional( 

1058 ASN1F_PACKET("stengthenKey", None, EncryptionKey, explicit_tag=0xA1) 

1059 ), 

1060 ASN1F_optional( 

1061 ASN1F_PACKET( 

1062 "finished", KrbFastFinished(), KrbFastFinished, explicit_tag=0xA2 

1063 ) 

1064 ), 

1065 UInt32("nonce", 0, explicit_tag=0xA3), 

1066 ) 

1067 

1068 

1069_PADATA_CLASSES[136] = (PA_FX_FAST_REQUEST, PA_FX_FAST_REPLY) 

1070 

1071# RFC 4556 

1072 

1073 

1074# sect 3.2.1 

1075 

1076 

1077class ExternalPrincipalIdentifier(ASN1_Packet): 

1078 ASN1_codec = ASN1_Codecs.BER 

1079 ASN1_root = ASN1F_SEQUENCE( 

1080 ASN1F_optional( 

1081 ASN1F_STRING("subjectName", "", implicit_tag=0xA0), 

1082 ), 

1083 ASN1F_optional( 

1084 ASN1F_STRING("issuerAndSerialNumber", "", implicit_tag=0xA1), 

1085 ), 

1086 ASN1F_optional( 

1087 ASN1F_STRING("subjectKeyIdentifier", "", implicit_tag=0xA2), 

1088 ), 

1089 ) 

1090 

1091 

1092class PA_PK_AS_REQ(ASN1_Packet): 

1093 ASN1_codec = ASN1_Codecs.BER 

1094 ASN1_root = ASN1F_SEQUENCE( 

1095 ASN1F_STRING("signedAuthpack", "", implicit_tag=0xA0), 

1096 ASN1F_optional( 

1097 ASN1F_SEQUENCE_OF( 

1098 "trustedCertifiers", 

1099 [ExternalPrincipalIdentifier()], 

1100 ExternalPrincipalIdentifier, 

1101 explicit_tag=0xA1, 

1102 ), 

1103 ), 

1104 ASN1F_optional( 

1105 ASN1F_STRING("kdcPkId", "", implicit_tag=0xA2), 

1106 ), 

1107 ) 

1108 

1109 

1110_PADATA_CLASSES[16] = PA_PK_AS_REQ 

1111 

1112# sect 3.2.3 

1113 

1114 

1115class DHRepInfo(ASN1_Packet): 

1116 ASN1_codec = ASN1_Codecs.BER 

1117 ASN1_root = ASN1F_SEQUENCE( 

1118 ASN1F_STRING("dhSignedData", "", implicit_tag=0xA0), 

1119 ASN1F_optional( 

1120 ASN1F_STRING("serverDHNonce", "", explicit_tag=0xA1), 

1121 ), 

1122 ) 

1123 

1124 

1125class EncKeyPack(ASN1_Packet): 

1126 ASN1_codec = ASN1_Codecs.BER 

1127 ASN1_root = ASN1F_STRING("encKeyPack", "") 

1128 

1129 

1130class PA_PK_AS_REP(ASN1_Packet): 

1131 ASN1_codec = ASN1_Codecs.BER 

1132 ASN1_root = ASN1F_CHOICE( 

1133 "rep", 

1134 ASN1_STRING(""), 

1135 ASN1F_PACKET("dhInfo", DHRepInfo(), DHRepInfo, explicit_tag=0xA0), 

1136 ASN1F_PACKET("encKeyPack", EncKeyPack(), EncKeyPack, explicit_tag=0xA1), 

1137 ) 

1138 

1139 

1140_PADATA_CLASSES[17] = PA_PK_AS_REP 

1141 

1142# [MS-SFU] 

1143 

1144 

1145# sect 2.2.1 

1146class PA_FOR_USER(ASN1_Packet): 

1147 ASN1_codec = ASN1_Codecs.BER 

1148 ASN1_root = ASN1F_SEQUENCE( 

1149 ASN1F_PACKET("userName", PrincipalName(), PrincipalName, explicit_tag=0xA0), 

1150 Realm("userRealm", "", explicit_tag=0xA1), 

1151 ASN1F_PACKET("cksum", Checksum(), Checksum, explicit_tag=0xA2), 

1152 KerberosString("authPackage", "Kerberos", explicit_tag=0xA3), 

1153 ) 

1154 

1155 

1156_PADATA_CLASSES[129] = PA_FOR_USER 

1157 

1158 

1159# sect 2.2.2 

1160 

1161 

1162class S4UUserID(ASN1_Packet): 

1163 ASN1_codec = ASN1_Codecs.BER 

1164 ASN1_root = ASN1F_SEQUENCE( 

1165 UInt32("nonce", 0, explicit_tag=0xA0), 

1166 ASN1F_optional( 

1167 ASN1F_PACKET("cname", None, PrincipalName, explicit_tag=0xA1), 

1168 ), 

1169 Realm("crealm", "", explicit_tag=0xA2), 

1170 ASN1F_optional( 

1171 ASN1F_STRING("subjectCertificate", None, explicit_tag=0xA3), 

1172 ), 

1173 ASN1F_optional( 

1174 ASN1F_FLAGS( 

1175 "options", 

1176 "", 

1177 [ 

1178 "reserved", 

1179 "KDC_CHECK_LOGON_HOUR_RESTRICTIONS", 

1180 "KDC_KEY_USAGE_27", 

1181 ], 

1182 explicit_tag=0xA4, 

1183 ) 

1184 ), 

1185 ) 

1186 

1187 

1188class PA_S4U_X509_USER(ASN1_Packet): 

1189 ASN1_codec = ASN1_Codecs.BER 

1190 ASN1_root = ASN1F_SEQUENCE( 

1191 ASN1F_PACKET("userId", S4UUserID(), S4UUserID, explicit_tag=0xA0), 

1192 ASN1F_PACKET("checksum", Checksum(), Checksum, explicit_tag=0xA1), 

1193 ) 

1194 

1195 

1196_PADATA_CLASSES[130] = PA_S4U_X509_USER 

1197 

1198 

1199# Back to RFC4120 

1200 

1201# sect 5.10 

1202KRB_MSG_TYPES = { 

1203 1: "Ticket", 

1204 2: "Authenticator", 

1205 3: "EncTicketPart", 

1206 10: "AS-REQ", 

1207 11: "AS-REP", 

1208 12: "TGS-REQ", 

1209 13: "TGS-REP", 

1210 14: "AP-REQ", 

1211 15: "AP-REP", 

1212 16: "KRB-TGT-REQ", # U2U 

1213 17: "KRB-TGT-REP", # U2U 

1214 20: "KRB-SAFE", 

1215 21: "KRB-PRIV", 

1216 22: "KRB-CRED", 

1217 25: "EncASRepPart", 

1218 26: "EncTGSRepPart", 

1219 27: "EncAPRepPart", 

1220 28: "EncKrbPrivPart", 

1221 29: "EnvKrbCredPart", 

1222 30: "KRB-ERROR", 

1223} 

1224 

1225# sect 5.3 

1226 

1227 

1228class KRB_Ticket(ASN1_Packet): 

1229 ASN1_codec = ASN1_Codecs.BER 

1230 ASN1_root = ASN1F_SEQUENCE( 

1231 ASN1F_SEQUENCE( 

1232 ASN1F_INTEGER("tktVno", 5, explicit_tag=0xA0), 

1233 Realm("realm", "", explicit_tag=0xA1), 

1234 ASN1F_PACKET("sname", PrincipalName(), PrincipalName, explicit_tag=0xA2), 

1235 ASN1F_PACKET("encPart", EncryptedData(), EncryptedData, explicit_tag=0xA3), 

1236 ), 

1237 implicit_tag=ASN1_Class_KRB.Ticket, 

1238 ) 

1239 

1240 def getSPN(self): 

1241 return "%s@%s" % ( 

1242 "/".join(x.val.decode() for x in self.sname.nameString), 

1243 self.realm.val.decode(), 

1244 ) 

1245 

1246 

1247class TransitedEncoding(ASN1_Packet): 

1248 ASN1_codec = ASN1_Codecs.BER 

1249 ASN1_root = ASN1F_SEQUENCE( 

1250 Int32("trType", 0, explicit_tag=0xA0), 

1251 ASN1F_STRING("contents", "", explicit_tag=0xA1), 

1252 ) 

1253 

1254 

1255_TICKET_FLAGS = [ 

1256 "reserved", 

1257 "forwardable", 

1258 "forwarded", 

1259 "proxiable", 

1260 "proxy", 

1261 "may-postdate", 

1262 "postdated", 

1263 "invalid", 

1264 "renewable", 

1265 "initial", 

1266 "pre-authent", 

1267 "hw-authent", 

1268 "transited-since-policy-checked", 

1269 "ok-as-delegate", 

1270 "unused", 

1271 "canonicalize", # RFC6806 

1272 "anonymous", # RFC6112 + RFC8129 

1273] 

1274 

1275 

1276class EncTicketPart(ASN1_Packet): 

1277 ASN1_codec = ASN1_Codecs.BER 

1278 ASN1_root = ASN1F_SEQUENCE( 

1279 ASN1F_SEQUENCE( 

1280 KerberosFlags( 

1281 "flags", 

1282 "", 

1283 _TICKET_FLAGS, 

1284 explicit_tag=0xA0, 

1285 ), 

1286 ASN1F_PACKET("key", EncryptionKey(), EncryptionKey, explicit_tag=0xA1), 

1287 Realm("crealm", "", explicit_tag=0xA2), 

1288 ASN1F_PACKET("cname", PrincipalName(), PrincipalName, explicit_tag=0xA3), 

1289 ASN1F_PACKET( 

1290 "transited", TransitedEncoding(), TransitedEncoding, explicit_tag=0xA4 

1291 ), 

1292 KerberosTime("authtime", GeneralizedTime(), explicit_tag=0xA5), 

1293 ASN1F_optional( 

1294 KerberosTime("starttime", GeneralizedTime(), explicit_tag=0xA6) 

1295 ), 

1296 KerberosTime("endtime", GeneralizedTime(), explicit_tag=0xA7), 

1297 ASN1F_optional( 

1298 KerberosTime("renewTill", GeneralizedTime(), explicit_tag=0xA8), 

1299 ), 

1300 ASN1F_optional( 

1301 HostAddresses("addresses", explicit_tag=0xA9), 

1302 ), 

1303 ASN1F_optional( 

1304 ASN1F_PACKET( 

1305 "authorizationData", None, AuthorizationData, explicit_tag=0xAA 

1306 ), 

1307 ), 

1308 ), 

1309 implicit_tag=ASN1_Class_KRB.EncTicketPart, 

1310 ) 

1311 

1312 

1313# sect 5.4.1 

1314 

1315 

1316class KRB_KDC_REQ_BODY(ASN1_Packet): 

1317 ASN1_codec = ASN1_Codecs.BER 

1318 ASN1_root = ASN1F_SEQUENCE( 

1319 KerberosFlags( 

1320 "kdcOptions", 

1321 "", 

1322 [ 

1323 "reserved", 

1324 "forwardable", 

1325 "forwarded", 

1326 "proxiable", 

1327 "proxy", 

1328 "allow-postdate", 

1329 "postdated", 

1330 "unused7", 

1331 "renewable", 

1332 "unused9", 

1333 "unused10", 

1334 "opt-hardware-auth", 

1335 "unused12", 

1336 "unused13", 

1337 "cname-in-addl-tkt", # [MS-SFU] sect 2.2.3 

1338 "canonicalize", # RFC6806 

1339 "request-anonymous", # RFC6112 + RFC8129 

1340 ] 

1341 + ["unused%d" % i for i in range(17, 26)] 

1342 + [ 

1343 "disable-transited-check", 

1344 "renewable-ok", 

1345 "enc-tkt-in-skey", 

1346 "unused29", 

1347 "renew", 

1348 "validate", 

1349 ], 

1350 explicit_tag=0xA0, 

1351 ), 

1352 ASN1F_optional(ASN1F_PACKET("cname", None, PrincipalName, explicit_tag=0xA1)), 

1353 Realm("realm", "", explicit_tag=0xA2), 

1354 ASN1F_optional( 

1355 ASN1F_PACKET("sname", None, PrincipalName, explicit_tag=0xA3), 

1356 ), 

1357 ASN1F_optional(KerberosTime("from_", None, explicit_tag=0xA4)), 

1358 KerberosTime("till", GeneralizedTime(), explicit_tag=0xA5), 

1359 ASN1F_optional(KerberosTime("rtime", GeneralizedTime(), explicit_tag=0xA6)), 

1360 UInt32("nonce", 0, explicit_tag=0xA7), 

1361 ASN1F_SEQUENCE_OF("etype", [], Int32, explicit_tag=0xA8), 

1362 ASN1F_optional( 

1363 HostAddresses("addresses", explicit_tag=0xA9), 

1364 ), 

1365 ASN1F_optional( 

1366 ASN1F_PACKET( 

1367 "encAuthorizationData", None, EncryptedData, explicit_tag=0xAA 

1368 ), 

1369 ), 

1370 ASN1F_optional( 

1371 ASN1F_SEQUENCE_OF("additionalTickets", [], KRB_Ticket, explicit_tag=0xAB) 

1372 ), 

1373 ) 

1374 

1375 

1376KRB_KDC_REQ = ASN1F_SEQUENCE( 

1377 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA1), 

1378 ASN1F_enum_INTEGER("msgType", 10, KRB_MSG_TYPES, explicit_tag=0xA2), 

1379 ASN1F_optional(ASN1F_SEQUENCE_OF("padata", [], PADATA, explicit_tag=0xA3)), 

1380 ASN1F_PACKET("reqBody", KRB_KDC_REQ_BODY(), KRB_KDC_REQ_BODY, explicit_tag=0xA4), 

1381) 

1382 

1383 

1384class KrbFastReq(ASN1_Packet): 

1385 # RFC6113 sect 5.4.2 

1386 ASN1_codec = ASN1_Codecs.BER 

1387 ASN1_root = ASN1F_SEQUENCE( 

1388 KerberosFlags( 

1389 "fastOptions", 

1390 "", 

1391 [ 

1392 "RESERVED", 

1393 "hide-client-names", 

1394 ] 

1395 + ["res%d" % i for i in range(2, 16)] 

1396 + ["kdc-follow-referrals"], 

1397 explicit_tag=0xA0, 

1398 ), 

1399 ASN1F_SEQUENCE_OF("padata", [PADATA()], PADATA, explicit_tag=0xA1), 

1400 ASN1F_PACKET("reqBody", None, KRB_KDC_REQ_BODY, explicit_tag=0xA2), 

1401 ) 

1402 

1403 

1404class KRB_AS_REQ(ASN1_Packet): 

1405 ASN1_codec = ASN1_Codecs.BER 

1406 ASN1_root = ASN1F_SEQUENCE( 

1407 KRB_KDC_REQ, 

1408 implicit_tag=ASN1_Class_KRB.AS_REQ, 

1409 ) 

1410 

1411 

1412class KRB_TGS_REQ(ASN1_Packet): 

1413 ASN1_codec = ASN1_Codecs.BER 

1414 ASN1_root = ASN1F_SEQUENCE( 

1415 KRB_KDC_REQ, 

1416 implicit_tag=ASN1_Class_KRB.TGS_REQ, 

1417 ) 

1418 msgType = ASN1_INTEGER(12) 

1419 

1420 

1421# sect 5.4.2 

1422 

1423KRB_KDC_REP = ASN1F_SEQUENCE( 

1424 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 

1425 ASN1F_enum_INTEGER("msgType", 11, KRB_MSG_TYPES, explicit_tag=0xA1), 

1426 ASN1F_optional( 

1427 ASN1F_SEQUENCE_OF("padata", [], PADATA, explicit_tag=0xA2), 

1428 ), 

1429 Realm("crealm", "", explicit_tag=0xA3), 

1430 ASN1F_PACKET("cname", None, PrincipalName, explicit_tag=0xA4), 

1431 ASN1F_PACKET("ticket", None, KRB_Ticket, explicit_tag=0xA5), 

1432 ASN1F_PACKET("encPart", None, EncryptedData, explicit_tag=0xA6), 

1433) 

1434 

1435 

1436class KRB_AS_REP(ASN1_Packet): 

1437 ASN1_codec = ASN1_Codecs.BER 

1438 ASN1_root = ASN1F_SEQUENCE( 

1439 KRB_KDC_REP, 

1440 implicit_tag=ASN1_Class_KRB.AS_REP, 

1441 ) 

1442 

1443 

1444class KRB_TGS_REP(ASN1_Packet): 

1445 ASN1_codec = ASN1_Codecs.BER 

1446 ASN1_root = ASN1F_SEQUENCE( 

1447 KRB_KDC_REP, 

1448 implicit_tag=ASN1_Class_KRB.TGS_REP, 

1449 ) 

1450 

1451 

1452class LastReqItem(ASN1_Packet): 

1453 ASN1_codec = ASN1_Codecs.BER 

1454 ASN1_root = ASN1F_SEQUENCE( 

1455 Int32("lrType", 0, explicit_tag=0xA0), 

1456 KerberosTime("lrValue", GeneralizedTime(), explicit_tag=0xA1), 

1457 ) 

1458 

1459 

1460EncKDCRepPart = ASN1F_SEQUENCE( 

1461 ASN1F_PACKET("key", None, EncryptionKey, explicit_tag=0xA0), 

1462 ASN1F_SEQUENCE_OF("lastReq", [], LastReqItem, explicit_tag=0xA1), 

1463 UInt32("nonce", 0, explicit_tag=0xA2), 

1464 ASN1F_optional( 

1465 KerberosTime("keyExpiration", GeneralizedTime(), explicit_tag=0xA3), 

1466 ), 

1467 KerberosFlags( 

1468 "flags", 

1469 "", 

1470 _TICKET_FLAGS, 

1471 explicit_tag=0xA4, 

1472 ), 

1473 KerberosTime("authtime", GeneralizedTime(), explicit_tag=0xA5), 

1474 ASN1F_optional( 

1475 KerberosTime("starttime", GeneralizedTime(), explicit_tag=0xA6), 

1476 ), 

1477 KerberosTime("endtime", GeneralizedTime(), explicit_tag=0xA7), 

1478 ASN1F_optional( 

1479 KerberosTime("renewTill", GeneralizedTime(), explicit_tag=0xA8), 

1480 ), 

1481 Realm("srealm", "", explicit_tag=0xA9), 

1482 ASN1F_PACKET("sname", PrincipalName(), PrincipalName, explicit_tag=0xAA), 

1483 ASN1F_optional( 

1484 HostAddresses("caddr", explicit_tag=0xAB), 

1485 ), 

1486 # RFC6806 sect 11 

1487 ASN1F_optional( 

1488 ASN1F_SEQUENCE_OF("encryptedPaData", [], PADATA, explicit_tag=0xAC), 

1489 ), 

1490) 

1491 

1492 

1493class EncASRepPart(ASN1_Packet): 

1494 ASN1_codec = ASN1_Codecs.BER 

1495 ASN1_root = ASN1F_SEQUENCE( 

1496 EncKDCRepPart, 

1497 implicit_tag=ASN1_Class_KRB.EncASRepPart, 

1498 ) 

1499 

1500 

1501class EncTGSRepPart(ASN1_Packet): 

1502 ASN1_codec = ASN1_Codecs.BER 

1503 ASN1_root = ASN1F_SEQUENCE( 

1504 EncKDCRepPart, 

1505 implicit_tag=ASN1_Class_KRB.EncTGSRepPart, 

1506 ) 

1507 

1508 

1509# sect 5.5.1 

1510 

1511 

1512class KRB_AP_REQ(ASN1_Packet): 

1513 ASN1_codec = ASN1_Codecs.BER 

1514 ASN1_root = ASN1F_SEQUENCE( 

1515 ASN1F_SEQUENCE( 

1516 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 

1517 ASN1F_enum_INTEGER("msgType", 14, KRB_MSG_TYPES, explicit_tag=0xA1), 

1518 KerberosFlags( 

1519 "apOptions", 

1520 "", 

1521 [ 

1522 "reserved", 

1523 "use-session-key", 

1524 "mutual-required", 

1525 ], 

1526 explicit_tag=0xA2, 

1527 ), 

1528 ASN1F_PACKET("ticket", None, KRB_Ticket, explicit_tag=0xA3), 

1529 ASN1F_PACKET("authenticator", None, EncryptedData, explicit_tag=0xA4), 

1530 ), 

1531 implicit_tag=ASN1_Class_KRB.AP_REQ, 

1532 ) 

1533 

1534 

1535_PADATA_CLASSES[1] = KRB_AP_REQ 

1536 

1537 

1538class KRB_Authenticator(ASN1_Packet): 

1539 ASN1_codec = ASN1_Codecs.BER 

1540 ASN1_root = ASN1F_SEQUENCE( 

1541 ASN1F_SEQUENCE( 

1542 ASN1F_INTEGER("authenticatorPvno", 5, explicit_tag=0xA0), 

1543 Realm("crealm", "", explicit_tag=0xA1), 

1544 ASN1F_PACKET("cname", None, PrincipalName, explicit_tag=0xA2), 

1545 ASN1F_optional( 

1546 ASN1F_PACKET("cksum", None, Checksum, explicit_tag=0xA3), 

1547 ), 

1548 Microseconds("cusec", 0, explicit_tag=0xA4), 

1549 KerberosTime("ctime", GeneralizedTime(), explicit_tag=0xA5), 

1550 ASN1F_optional( 

1551 ASN1F_PACKET("subkey", None, EncryptionKey, explicit_tag=0xA6), 

1552 ), 

1553 ASN1F_optional( 

1554 UInt32("seqNumber", 0, explicit_tag=0xA7), 

1555 ), 

1556 ASN1F_optional( 

1557 ASN1F_PACKET( 

1558 "encAuthorizationData", None, AuthorizationData, explicit_tag=0xA8 

1559 ), 

1560 ), 

1561 ), 

1562 implicit_tag=ASN1_Class_KRB.Authenticator, 

1563 ) 

1564 

1565 

1566# sect 5.5.2 

1567 

1568 

1569class KRB_AP_REP(ASN1_Packet): 

1570 ASN1_codec = ASN1_Codecs.BER 

1571 ASN1_root = ASN1F_SEQUENCE( 

1572 ASN1F_SEQUENCE( 

1573 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 

1574 ASN1F_enum_INTEGER("msgType", 15, KRB_MSG_TYPES, explicit_tag=0xA1), 

1575 ASN1F_PACKET("encPart", None, EncryptedData, explicit_tag=0xA2), 

1576 ), 

1577 implicit_tag=ASN1_Class_KRB.AP_REP, 

1578 ) 

1579 

1580 

1581class EncAPRepPart(ASN1_Packet): 

1582 ASN1_codec = ASN1_Codecs.BER 

1583 ASN1_root = ASN1F_SEQUENCE( 

1584 ASN1F_SEQUENCE( 

1585 KerberosTime("ctime", GeneralizedTime(), explicit_tag=0xA0), 

1586 Microseconds("cusec", 0, explicit_tag=0xA1), 

1587 ASN1F_optional( 

1588 ASN1F_PACKET("subkey", None, EncryptionKey, explicit_tag=0xA2), 

1589 ), 

1590 ASN1F_optional( 

1591 UInt32("seqNumber", 0, explicit_tag=0xA3), 

1592 ), 

1593 ), 

1594 implicit_tag=ASN1_Class_KRB.EncAPRepPart, 

1595 ) 

1596 

1597 

1598# sect 5.7 

1599 

1600 

1601class KRB_PRIV(ASN1_Packet): 

1602 ASN1_codec = ASN1_Codecs.BER 

1603 ASN1_root = ASN1F_SEQUENCE( 

1604 ASN1F_SEQUENCE( 

1605 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 

1606 ASN1F_enum_INTEGER("msgType", 21, KRB_MSG_TYPES, explicit_tag=0xA1), 

1607 ASN1F_PACKET("encPart", None, EncryptedData, explicit_tag=0xA3), 

1608 ), 

1609 implicit_tag=ASN1_Class_KRB.PRIV, 

1610 ) 

1611 

1612 

1613class EncKrbPrivPart(ASN1_Packet): 

1614 ASN1_codec = ASN1_Codecs.BER 

1615 ASN1_root = ASN1F_SEQUENCE( 

1616 ASN1F_SEQUENCE( 

1617 ASN1F_STRING("userData", ASN1_STRING(""), explicit_tag=0xA0), 

1618 ASN1F_optional( 

1619 KerberosTime("timestamp", None, explicit_tag=0xA1), 

1620 ), 

1621 ASN1F_optional( 

1622 Microseconds("usec", None, explicit_tag=0xA2), 

1623 ), 

1624 ASN1F_optional( 

1625 UInt32("seqNumber", None, explicit_tag=0xA3), 

1626 ), 

1627 ASN1F_PACKET("sAddress", None, HostAddress, explicit_tag=0xA4), 

1628 ASN1F_optional( 

1629 ASN1F_PACKET("cAddress", None, HostAddress, explicit_tag=0xA5), 

1630 ), 

1631 ), 

1632 implicit_tag=ASN1_Class_KRB.EncKrbPrivPart, 

1633 ) 

1634 

1635 

1636# sect 5.8 

1637 

1638 

1639class KRB_CRED(ASN1_Packet): 

1640 ASN1_codec = ASN1_Codecs.BER 

1641 ASN1_root = ASN1F_SEQUENCE( 

1642 ASN1F_SEQUENCE( 

1643 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 

1644 ASN1F_enum_INTEGER("msgType", 22, KRB_MSG_TYPES, explicit_tag=0xA1), 

1645 ASN1F_SEQUENCE_OF("tickets", [KRB_Ticket()], KRB_Ticket, explicit_tag=0xA2), 

1646 ASN1F_PACKET("encPart", None, EncryptedData, explicit_tag=0xA3), 

1647 ), 

1648 implicit_tag=ASN1_Class_KRB.CRED, 

1649 ) 

1650 

1651 

1652class KrbCredInfo(ASN1_Packet): 

1653 ASN1_codec = ASN1_Codecs.BER 

1654 ASN1_root = ASN1F_SEQUENCE( 

1655 ASN1F_PACKET("key", EncryptionKey(), EncryptionKey, explicit_tag=0xA0), 

1656 ASN1F_optional( 

1657 Realm("prealm", None, explicit_tag=0xA1), 

1658 ), 

1659 ASN1F_optional( 

1660 ASN1F_PACKET("pname", None, PrincipalName, explicit_tag=0xA2), 

1661 ), 

1662 ASN1F_optional( 

1663 KerberosFlags( 

1664 "flags", 

1665 None, 

1666 _TICKET_FLAGS, 

1667 explicit_tag=0xA3, 

1668 ), 

1669 ), 

1670 ASN1F_optional( 

1671 KerberosTime("authtime", None, explicit_tag=0xA4), 

1672 ), 

1673 ASN1F_optional(KerberosTime("starttime", None, explicit_tag=0xA5)), 

1674 ASN1F_optional( 

1675 KerberosTime("endtime", None, explicit_tag=0xA6), 

1676 ), 

1677 ASN1F_optional( 

1678 KerberosTime("renewTill", None, explicit_tag=0xA7), 

1679 ), 

1680 ASN1F_optional( 

1681 Realm("srealm", None, explicit_tag=0xA8), 

1682 ), 

1683 ASN1F_optional( 

1684 ASN1F_PACKET("sname", None, PrincipalName, explicit_tag=0xA9), 

1685 ), 

1686 ASN1F_optional( 

1687 HostAddresses("caddr", explicit_tag=0xAA), 

1688 ), 

1689 ) 

1690 

1691 

1692class EncKrbCredPart(ASN1_Packet): 

1693 ASN1_codec = ASN1_Codecs.BER 

1694 ASN1_root = ASN1F_SEQUENCE( 

1695 ASN1F_SEQUENCE( 

1696 ASN1F_SEQUENCE_OF( 

1697 "ticketInfo", 

1698 [KrbCredInfo()], 

1699 KrbCredInfo, 

1700 explicit_tag=0xA0, 

1701 ), 

1702 ASN1F_optional( 

1703 UInt32("nonce", None, explicit_tag=0xA1), 

1704 ), 

1705 ASN1F_optional( 

1706 KerberosTime("timestamp", None, explicit_tag=0xA2), 

1707 ), 

1708 ASN1F_optional( 

1709 Microseconds("usec", None, explicit_tag=0xA3), 

1710 ), 

1711 ASN1F_optional( 

1712 ASN1F_PACKET("sAddress", None, HostAddress, explicit_tag=0xA4), 

1713 ), 

1714 ASN1F_optional( 

1715 ASN1F_PACKET("cAddress", None, HostAddress, explicit_tag=0xA5), 

1716 ), 

1717 ), 

1718 implicit_tag=ASN1_Class_KRB.EncKrbCredPart, 

1719 ) 

1720 

1721 

1722# sect 5.9.1 

1723 

1724 

1725class MethodData(ASN1_Packet): 

1726 ASN1_codec = ASN1_Codecs.BER 

1727 ASN1_root = ASN1F_SEQUENCE_OF("seq", [PADATA()], PADATA) 

1728 

1729 

1730class _KRBERROR_data_Field(_ASN1FString_PacketField): 

1731 def m2i(self, pkt, s): 

1732 val = super(_KRBERROR_data_Field, self).m2i(pkt, s) 

1733 if not val[0].val: 

1734 return val 

1735 if pkt.errorCode.val in [14, 24, 25]: 

1736 # 14: KDC_ERR_ETYPE_NOSUPP 

1737 # 24: KDC_ERR_PREAUTH_FAILED 

1738 # 25: KDC_ERR_PREAUTH_REQUIRED 

1739 return MethodData(val[0].val, _underlayer=pkt), val[1] 

1740 elif pkt.errorCode.val in [18, 29, 41, 60]: 

1741 # 18: KDC_ERR_CLIENT_REVOKED 

1742 # 29: KDC_ERR_SVC_UNAVAILABLE 

1743 # 41: KRB_AP_ERR_MODIFIED 

1744 # 60: KRB_ERR_GENERIC 

1745 return KERB_ERROR_DATA(val[0].val, _underlayer=pkt), val[1] 

1746 elif pkt.errorCode.val == 69: 

1747 # KRB_AP_ERR_USER_TO_USER_REQUIRED 

1748 return KRB_TGT_REP(val[0].val, _underlayer=pkt), val[1] 

1749 return val 

1750 

1751 

1752class KRB_ERROR(ASN1_Packet): 

1753 ASN1_codec = ASN1_Codecs.BER 

1754 ASN1_root = ASN1F_SEQUENCE( 

1755 ASN1F_SEQUENCE( 

1756 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 

1757 ASN1F_enum_INTEGER("msgType", 30, KRB_MSG_TYPES, explicit_tag=0xA1), 

1758 ASN1F_optional( 

1759 KerberosTime("ctime", None, explicit_tag=0xA2), 

1760 ), 

1761 ASN1F_optional( 

1762 Microseconds("cusec", None, explicit_tag=0xA3), 

1763 ), 

1764 KerberosTime("stime", GeneralizedTime(), explicit_tag=0xA4), 

1765 Microseconds("susec", 0, explicit_tag=0xA5), 

1766 ASN1F_enum_INTEGER( 

1767 "errorCode", 

1768 0, 

1769 { 

1770 # RFC4120 sect 7.5.9 

1771 0: "KDC_ERR_NONE", 

1772 1: "KDC_ERR_NAME_EXP", 

1773 2: "KDC_ERR_SERVICE_EXP", 

1774 3: "KDC_ERR_BAD_PVNO", 

1775 4: "KDC_ERR_C_OLD_MAST_KVNO", 

1776 5: "KDC_ERR_S_OLD_MAST_KVNO", 

1777 6: "KDC_ERR_C_PRINCIPAL_UNKNOWN", 

1778 7: "KDC_ERR_S_PRINCIPAL_UNKNOWN", 

1779 8: "KDC_ERR_PRINCIPAL_NOT_UNIQUE", 

1780 9: "KDC_ERR_NULL_KEY", 

1781 10: "KDC_ERR_CANNOT_POSTDATE", 

1782 11: "KDC_ERR_NEVER_VALID", 

1783 12: "KDC_ERR_POLICY", 

1784 13: "KDC_ERR_BADOPTION", 

1785 14: "KDC_ERR_ETYPE_NOSUPP", 

1786 15: "KDC_ERR_SUMTYPE_NOSUPP", 

1787 16: "KDC_ERR_PADATA_TYPE_NOSUPP", 

1788 17: "KDC_ERR_TRTYPE_NOSUPP", 

1789 18: "KDC_ERR_CLIENT_REVOKED", 

1790 19: "KDC_ERR_SERVICE_REVOKED", 

1791 20: "KDC_ERR_TGT_REVOKED", 

1792 21: "KDC_ERR_CLIENT_NOTYET", 

1793 22: "KDC_ERR_SERVICE_NOTYET", 

1794 23: "KDC_ERR_KEY_EXPIRED", 

1795 24: "KDC_ERR_PREAUTH_FAILED", 

1796 25: "KDC_ERR_PREAUTH_REQUIRED", 

1797 26: "KDC_ERR_SERVER_NOMATCH", 

1798 27: "KDC_ERR_MUST_USE_USER2USER", 

1799 28: "KDC_ERR_PATH_NOT_ACCEPTED", 

1800 29: "KDC_ERR_SVC_UNAVAILABLE", 

1801 31: "KRB_AP_ERR_BAD_INTEGRITY", 

1802 32: "KRB_AP_ERR_TKT_EXPIRED", 

1803 33: "KRB_AP_ERR_TKT_NYV", 

1804 34: "KRB_AP_ERR_REPEAT", 

1805 35: "KRB_AP_ERR_NOT_US", 

1806 36: "KRB_AP_ERR_BADMATCH", 

1807 37: "KRB_AP_ERR_SKEW", 

1808 38: "KRB_AP_ERR_BADADDR", 

1809 39: "KRB_AP_ERR_BADVERSION", 

1810 40: "KRB_AP_ERR_MSG_TYPE", 

1811 41: "KRB_AP_ERR_MODIFIED", 

1812 42: "KRB_AP_ERR_BADORDER", 

1813 44: "KRB_AP_ERR_BADKEYVER", 

1814 45: "KRB_AP_ERR_NOKEY", 

1815 46: "KRB_AP_ERR_MUT_FAIL", 

1816 47: "KRB_AP_ERR_BADDIRECTION", 

1817 48: "KRB_AP_ERR_METHOD", 

1818 49: "KRB_AP_ERR_BADSEQ", 

1819 50: "KRB_AP_ERR_INAPP_CKSUM", 

1820 51: "KRB_AP_PATH_NOT_ACCEPTED", 

1821 52: "KRB_ERR_RESPONSE_TOO_BIG", 

1822 60: "KRB_ERR_GENERIC", 

1823 61: "KRB_ERR_FIELD_TOOLONG", 

1824 62: "KDC_ERROR_CLIENT_NOT_TRUSTED", 

1825 63: "KDC_ERROR_KDC_NOT_TRUSTED", 

1826 64: "KDC_ERROR_INVALID_SIG", 

1827 65: "KDC_ERR_KEY_TOO_WEAK", 

1828 66: "KDC_ERR_CERTIFICATE_MISMATCH", 

1829 67: "KRB_AP_ERR_NO_TGT", 

1830 68: "KDC_ERR_WRONG_REALM", 

1831 69: "KRB_AP_ERR_USER_TO_USER_REQUIRED", 

1832 70: "KDC_ERR_CANT_VERIFY_CERTIFICATE", 

1833 71: "KDC_ERR_INVALID_CERTIFICATE", 

1834 72: "KDC_ERR_REVOKED_CERTIFICATE", 

1835 73: "KDC_ERR_REVOCATION_STATUS_UNKNOWN", 

1836 74: "KDC_ERR_REVOCATION_STATUS_UNAVAILABLE", 

1837 75: "KDC_ERR_CLIENT_NAME_MISMATCH", 

1838 76: "KDC_ERR_KDC_NAME_MISMATCH", 

1839 # draft-ietf-kitten-iakerb 

1840 85: "KRB_AP_ERR_IAKERB_KDC_NOT_FOUND", 

1841 86: "KRB_AP_ERR_IAKERB_KDC_NO_RESPONSE", 

1842 # RFC6113 

1843 90: "KDC_ERR_PREAUTH_EXPIRED", 

1844 91: "KDC_ERR_MORE_PREAUTH_DATA_REQUIRED", 

1845 92: "KDC_ERR_PREAUTH_BAD_AUTHENTICATION_SET", 

1846 93: "KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS", 

1847 }, 

1848 explicit_tag=0xA6, 

1849 ), 

1850 ASN1F_optional(Realm("crealm", None, explicit_tag=0xA7)), 

1851 ASN1F_optional( 

1852 ASN1F_PACKET("cname", None, PrincipalName, explicit_tag=0xA8), 

1853 ), 

1854 Realm("realm", "", explicit_tag=0xA9), 

1855 ASN1F_PACKET("sname", PrincipalName(), PrincipalName, explicit_tag=0xAA), 

1856 ASN1F_optional(KerberosString("eText", "", explicit_tag=0xAB)), 

1857 ASN1F_optional(_KRBERROR_data_Field("eData", "", explicit_tag=0xAC)), 

1858 ), 

1859 implicit_tag=ASN1_Class_KRB.ERROR, 

1860 ) 

1861 

1862 

1863# [MS-KILE] sect 2.2.1 

1864 

1865 

1866class KERB_EXT_ERROR(Packet): 

1867 fields_desc = [ 

1868 XLEIntField("status", 0), 

1869 XLEIntField("reserved", 0), 

1870 XLEIntField("flags", 0x00000001), 

1871 ] 

1872 

1873 

1874# [MS-KILE] sect 2.2.2 

1875 

1876 

1877class _Error_Field(_ASN1FString_PacketField): 

1878 def m2i(self, pkt, s): 

1879 val = super(_Error_Field, self).m2i(pkt, s) 

1880 if not val[0].val: 

1881 return val 

1882 if pkt.dataType.val == 3: # KERB_ERR_TYPE_EXTENDED 

1883 return KERB_EXT_ERROR(val[0].val, _underlayer=pkt), val[1] 

1884 return val 

1885 

1886 

1887class KERB_ERROR_DATA(ASN1_Packet): 

1888 ASN1_codec = ASN1_Codecs.BER 

1889 ASN1_root = ASN1F_SEQUENCE( 

1890 ASN1F_enum_INTEGER( 

1891 "dataType", 

1892 2, 

1893 { 

1894 1: "KERB_AP_ERR_TYPE_NTSTATUS", # from the wdk 

1895 2: "KERB_AP_ERR_TYPE_SKEW_RECOVERY", 

1896 3: "KERB_ERR_TYPE_EXTENDED", 

1897 }, 

1898 explicit_tag=0xA1, 

1899 ), 

1900 ASN1F_optional(_Error_Field("dataValue", None, explicit_tag=0xA2)), 

1901 ) 

1902 

1903 

1904# Kerberos U2U - draft-ietf-cat-user2user-03 

1905 

1906 

1907class KRB_TGT_REQ(ASN1_Packet): 

1908 ASN1_codec = ASN1_Codecs.BER 

1909 ASN1_root = ASN1F_SEQUENCE( 

1910 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 

1911 ASN1F_enum_INTEGER("msgType", 16, KRB_MSG_TYPES, explicit_tag=0xA1), 

1912 ASN1F_optional( 

1913 ASN1F_PACKET("sname", None, PrincipalName, explicit_tag=0xA2), 

1914 ), 

1915 ASN1F_optional( 

1916 Realm("realm", None, explicit_tag=0xA3), 

1917 ), 

1918 ) 

1919 

1920 

1921class KRB_TGT_REP(ASN1_Packet): 

1922 ASN1_codec = ASN1_Codecs.BER 

1923 ASN1_root = ASN1F_SEQUENCE( 

1924 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 

1925 ASN1F_enum_INTEGER("msgType", 17, KRB_MSG_TYPES, explicit_tag=0xA1), 

1926 ASN1F_PACKET("ticket", None, KRB_Ticket, explicit_tag=0xA2), 

1927 ) 

1928 

1929 

1930# draft-ietf-kitten-iakerb-03 sect 4 

1931 

1932 

1933class KRB_FINISHED(ASN1_Packet): 

1934 ASN1_codec = ASN1_Codecs.BER 

1935 ASN1_root = ASN1F_SEQUENCE( 

1936 ASN1F_PACKET("gssMic", Checksum(), Checksum, explicit_tag=0xA1), 

1937 ) 

1938 

1939 

1940# RFC 6542 sect 3.1 

1941 

1942 

1943class KRB_GSS_EXT(Packet): 

1944 fields_desc = [ 

1945 IntEnumField( 

1946 "type", 

1947 0, 

1948 { 

1949 # https://www.iana.org/assignments/kerberos-v-gss-api/kerberos-v-gss-api.xhtml 

1950 0x00000000: "GSS_EXTS_CHANNEL_BINDING", # RFC 6542 sect 3.2 

1951 0x00000001: "GSS_EXTS_IAKERB_FINISHED", # not standard 

1952 0x00000002: "GSS_EXTS_FINISHED", # PKU2U / IAKERB 

1953 }, 

1954 ), 

1955 FieldLenField("length", None, length_of="data", fmt="!I"), 

1956 MultipleTypeField( 

1957 [ 

1958 ( 

1959 PacketField("data", KRB_FINISHED(), KRB_FINISHED), 

1960 lambda pkt: pkt.type == 0x00000002, 

1961 ), 

1962 ], 

1963 XStrLenField("data", b"", length_from=lambda pkt: pkt.length), 

1964 ), 

1965 ] 

1966 

1967 

1968# RFC 4121 sect 4.1.1 

1969 

1970 

1971class KRB_AuthenticatorChecksum(Packet): 

1972 fields_desc = [ 

1973 FieldLenField("Lgth", None, length_of="Bnd", fmt="<I"), 

1974 PacketLenField( 

1975 "Bnd", 

1976 GssChannelBindings(), 

1977 GssChannelBindings, 

1978 length_from=lambda pkt: pkt.Lgth, 

1979 ), 

1980 FlagsField( 

1981 "Flags", 

1982 0, 

1983 -32, 

1984 { 

1985 0x01: "GSS_C_DELEG_FLAG", 

1986 0x02: "GSS_C_MUTUAL_FLAG", 

1987 0x04: "GSS_C_REPLAY_FLAG", 

1988 0x08: "GSS_C_SEQUENCE_FLAG", 

1989 0x10: "GSS_C_CONF_FLAG", # confidentiality 

1990 0x20: "GSS_C_INTEG_FLAG", # integrity 

1991 # RFC4757 

1992 0x1000: "GSS_C_DCE_STYLE", 

1993 0x2000: "GSS_C_IDENTIFY_FLAG", 

1994 0x4000: "GSS_C_EXTENDED_ERROR_FLAG", 

1995 }, 

1996 ), 

1997 ConditionalField( 

1998 LEShortField("DlgOpt", 0), 

1999 lambda pkt: pkt.Flags.GSS_C_DELEG_FLAG, 

2000 ), 

2001 ConditionalField( 

2002 FieldLenField("Dlgth", None, length_of="Deleg"), 

2003 lambda pkt: pkt.Flags.GSS_C_DELEG_FLAG, 

2004 ), 

2005 ConditionalField( 

2006 PacketLenField( 

2007 "Deleg", KRB_CRED(), KRB_CRED, length_from=lambda pkt: pkt.Dlgth 

2008 ), 

2009 lambda pkt: pkt.Flags.GSS_C_DELEG_FLAG, 

2010 ), 

2011 # Extensions: RFC 6542 sect 3.1 

2012 PacketListField("Exts", KRB_GSS_EXT(), KRB_GSS_EXT), 

2013 ] 

2014 

2015 

2016# Kerberos V5 GSS-API - RFC1964 and RFC4121 

2017 

2018_TOK_IDS = { 

2019 # RFC 1964 

2020 b"\x01\x00": "KRB-AP-REQ", 

2021 b"\x02\x00": "KRB-AP-REP", 

2022 b"\x03\x00": "KRB-ERROR", 

2023 b"\x01\x01": "GSS_GetMIC-RFC1964", 

2024 b"\x02\x01": "GSS_Wrap-RFC1964", 

2025 b"\x01\x02": "GSS_Delete_sec_context-RFC1964", 

2026 # U2U: [draft-ietf-cat-user2user-03] 

2027 b"\x04\x00": "KRB-TGT-REQ", 

2028 b"\x04\x01": "KRB-TGT-REP", 

2029 # RFC 4121 

2030 b"\x04\x04": "GSS_GetMIC", 

2031 b"\x05\x04": "GSS_Wrap", 

2032 # IAKERB: [draft-ietf-kitten-iakerb-03] 

2033 b"\x05\x01": "IAKERB_PROXY", 

2034} 

2035_SGN_ALGS = { 

2036 0x00: "DES MAC MD5", 

2037 0x01: "MD2.5", 

2038 0x02: "DES MAC", 

2039 # RFC 4757 

2040 0x11: "HMAC", 

2041} 

2042_SEAL_ALGS = { 

2043 0: "DES", 

2044 0xFFFF: "none", 

2045 # RFC 4757 

2046 0x10: "RC4", 

2047} 

2048 

2049 

2050# RFC 1964 - sect 1.1 

2051 

2052# See https://www.iana.org/assignments/kerberos-v-gss-api/kerberos-v-gss-api.xhtml 

2053_InitialContextTokens = {} # filled below 

2054 

2055 

2056class KRB_InnerToken(Packet): 

2057 name = "Kerberos v5 InnerToken" 

2058 fields_desc = [ 

2059 StrFixedLenEnumField("TOK_ID", b"\x01\x00", _TOK_IDS, length=2), 

2060 PacketField( 

2061 "root", 

2062 KRB_AP_REQ(), 

2063 lambda x, _parent: _InitialContextTokens[_parent.TOK_ID](x), 

2064 ), 

2065 ] 

2066 

2067 @classmethod 

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

2069 if _pkt and len(_pkt) >= 13: 

2070 # Older RFC1964 variants of the token have KRB_GSSAPI_Token wrapper 

2071 if _pkt[2:13] == b"\x06\t*\x86H\x86\xf7\x12\x01\x02\x02": 

2072 return KRB_GSSAPI_Token 

2073 return cls 

2074 

2075 

2076# RFC 4121 - sect 4.1 

2077 

2078 

2079class KRB_GSSAPI_Token(GSSAPI_BLOB): 

2080 name = "Kerberos GSSAPI-Token" 

2081 ASN1_codec = ASN1_Codecs.BER 

2082 ASN1_root = ASN1F_SEQUENCE( 

2083 ASN1F_OID("MechType", "1.2.840.113554.1.2.2"), 

2084 ASN1F_PACKET( 

2085 "innerToken", 

2086 KRB_InnerToken(), 

2087 KRB_InnerToken, 

2088 implicit_tag=0x0, 

2089 ), 

2090 implicit_tag=ASN1_Class_KRB.Token, 

2091 ) 

2092 

2093 

2094# RFC 1964 - sect 1.2.1 

2095 

2096 

2097class KRB_GSS_MIC_RFC1964(Packet): 

2098 name = "Kerberos v5 MIC Token (RFC1964)" 

2099 fields_desc = [ 

2100 LEShortEnumField("SGN_ALG", 0, _SGN_ALGS), 

2101 XLEIntField("Filler", 0xFFFFFFFF), 

2102 XStrFixedLenField("SND_SEQ", b"", length=8), 

2103 PadField( # sect 1.2.2.3 

2104 XStrFixedLenField("SGN_CKSUM", b"", length=8), 

2105 align=8, 

2106 padwith=b"\x04", 

2107 ), 

2108 ] 

2109 

2110 

2111_InitialContextTokens[b"\x01\x01"] = KRB_GSS_MIC_RFC1964 

2112 

2113# RFC 1964 - sect 1.2.2 

2114 

2115 

2116class KRB_GSS_Wrap_RFC1964(Packet): 

2117 name = "Kerberos v5 GSS_Wrap (RFC1964)" 

2118 fields_desc = [ 

2119 LEShortEnumField("SGN_ALG", 0, _SGN_ALGS), 

2120 LEShortEnumField("SEAL_ALG", 0, _SEAL_ALGS), 

2121 XLEShortField("Filler", 0xFFFF), 

2122 XStrFixedLenField("SND_SEQ", b"", length=8), 

2123 PadField( # sect 1.2.2.3 

2124 XStrFixedLenField("SGN_CKSUM", b"", length=8), 

2125 align=8, 

2126 padwith=b"\x04", 

2127 ), 

2128 # sect 1.2.2.3 

2129 XStrFixedLenField("CONFOUNDER", b"", length=8), 

2130 ] 

2131 

2132 

2133_InitialContextTokens[b"\x02\x01"] = KRB_GSS_Wrap_RFC1964 

2134 

2135 

2136# RFC 1964 - sect 1.2.2 

2137 

2138 

2139class KRB_GSS_Delete_sec_context_RFC1964(Packet): 

2140 name = "Kerberos v5 GSS_Delete_sec_context (RFC1964)" 

2141 fields_desc = KRB_GSS_MIC_RFC1964.fields_desc 

2142 

2143 

2144_InitialContextTokens[b"\x01\x02"] = KRB_GSS_Delete_sec_context_RFC1964 

2145 

2146 

2147# RFC 4121 - sect 4.2.2 

2148_KRB5_GSS_Flags = [ 

2149 "SentByAcceptor", 

2150 "Sealed", 

2151 "AcceptorSubkey", 

2152] 

2153 

2154 

2155# RFC 4121 - sect 4.2.6.1 

2156 

2157 

2158class KRB_GSS_MIC(Packet): 

2159 name = "Kerberos v5 MIC Token" 

2160 fields_desc = [ 

2161 FlagsField("Flags", 0, 8, _KRB5_GSS_Flags), 

2162 XStrFixedLenField("Filler", b"\xff\xff\xff\xff\xff", length=5), 

2163 LongField("SND_SEQ", 0), # Big endian 

2164 XStrField("SGN_CKSUM", b"\x00" * 12), 

2165 ] 

2166 

2167 

2168_InitialContextTokens[b"\x04\x04"] = KRB_GSS_MIC 

2169 

2170 

2171# RFC 4121 - sect 4.2.6.2 

2172 

2173 

2174class KRB_GSS_Wrap(Packet): 

2175 name = "Kerberos v5 Wrap Token" 

2176 fields_desc = [ 

2177 FlagsField("Flags", 0, 8, _KRB5_GSS_Flags), 

2178 XByteField("Filler", 0xFF), 

2179 ShortField("EC", 0), # Big endian 

2180 ShortField("RRC", 0), # Big endian 

2181 LongField("SND_SEQ", 0), # Big endian 

2182 XStrField("Data", b""), 

2183 ] 

2184 

2185 

2186_InitialContextTokens[b"\x05\x04"] = KRB_GSS_Wrap 

2187 

2188 

2189# Kerberos IAKERB - draft-ietf-kitten-iakerb-03 

2190 

2191 

2192class IAKERB_HEADER(ASN1_Packet): 

2193 ASN1_codec = ASN1_Codecs.BER 

2194 ASN1_root = ASN1F_SEQUENCE( 

2195 Realm("targetRealm", "", explicit_tag=0xA1), 

2196 ASN1F_optional( 

2197 ASN1F_STRING("cookie", None, explicit_tag=0xA2), 

2198 ), 

2199 ) 

2200 

2201 

2202_InitialContextTokens[b"\x05\x01"] = IAKERB_HEADER 

2203 

2204 

2205# Register for GSSAPI 

2206 

2207# Kerberos 5 

2208_GSSAPI_OIDS["1.2.840.113554.1.2.2"] = KRB_InnerToken 

2209_GSSAPI_SIGNATURE_OIDS["1.2.840.113554.1.2.2"] = KRB_InnerToken 

2210# Kerberos 5 - U2U 

2211_GSSAPI_OIDS["1.2.840.113554.1.2.2.3"] = KRB_InnerToken 

2212# Kerberos 5 - IAKERB 

2213_GSSAPI_OIDS["1.3.6.1.5.2.5"] = KRB_InnerToken 

2214 

2215 

2216# Entry class 

2217 

2218# RFC4120 sect 5.10 

2219 

2220 

2221class Kerberos(ASN1_Packet): 

2222 ASN1_codec = ASN1_Codecs.BER 

2223 ASN1_root = ASN1F_CHOICE( 

2224 "root", 

2225 None, 

2226 # RFC4120 

2227 KRB_GSSAPI_Token, # [APPLICATION 0] 

2228 KRB_Ticket, # [APPLICATION 1] 

2229 KRB_Authenticator, # [APPLICATION 2] 

2230 KRB_AS_REQ, # [APPLICATION 10] 

2231 KRB_AS_REP, # [APPLICATION 11] 

2232 KRB_TGS_REQ, # [APPLICATION 12] 

2233 KRB_TGS_REP, # [APPLICATION 13] 

2234 KRB_AP_REQ, # [APPLICATION 14] 

2235 KRB_AP_REP, # [APPLICATION 15] 

2236 # RFC4120 

2237 KRB_ERROR, # [APPLICATION 30] 

2238 ) 

2239 

2240 def mysummary(self): 

2241 return self.root.summary() 

2242 

2243 

2244bind_bottom_up(UDP, Kerberos, sport=88) 

2245bind_bottom_up(UDP, Kerberos, dport=88) 

2246bind_layers(UDP, Kerberos, sport=88, dport=88) 

2247 

2248_InitialContextTokens[b"\x01\x00"] = KRB_AP_REQ 

2249_InitialContextTokens[b"\x02\x00"] = KRB_AP_REP 

2250_InitialContextTokens[b"\x03\x00"] = KRB_ERROR 

2251_InitialContextTokens[b"\x04\x00"] = KRB_TGT_REQ 

2252_InitialContextTokens[b"\x04\x01"] = KRB_TGT_REP 

2253 

2254bind_layers(KRB_InnerToken, Kerberos) 

2255 

2256 

2257# RFC4120 sect 7.2.2 

2258 

2259 

2260class KerberosTCPHeader(Packet): 

2261 # According to RFC 5021, first bit to 1 has a special meaning and 

2262 # negotiates Kerberos TCP extensions... But apart from rfc6251 no one used that 

2263 # https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml#kerberos-parameters-4 

2264 fields_desc = [LenField("len", None, fmt="!I")] 

2265 

2266 @classmethod 

2267 def tcp_reassemble(cls, data, *args, **kwargs): 

2268 if len(data) < 4: 

2269 return None 

2270 length = struct.unpack("!I", data[:4])[0] 

2271 if len(data) == length + 4: 

2272 return cls(data) 

2273 

2274 

2275bind_layers(KerberosTCPHeader, Kerberos) 

2276 

2277bind_bottom_up(TCP, KerberosTCPHeader, sport=88) 

2278bind_layers(TCP, KerberosTCPHeader, dport=88) 

2279 

2280 

2281# RFC3244 sect 2 

2282 

2283 

2284class KPASSWD_REQ(Packet): 

2285 fields_desc = [ 

2286 ShortField("len", None), 

2287 ShortField("pvno", 0xFF80), 

2288 ShortField("apreqlen", None), 

2289 PacketLenField( 

2290 "apreq", KRB_AP_REQ(), KRB_AP_REQ, length_from=lambda pkt: pkt.apreqlen 

2291 ), 

2292 ConditionalField( 

2293 PacketLenField( 

2294 "krbpriv", 

2295 KRB_PRIV(), 

2296 KRB_PRIV, 

2297 length_from=lambda pkt: pkt.len - 6 - pkt.apreqlen, 

2298 ), 

2299 lambda pkt: pkt.apreqlen != 0, 

2300 ), 

2301 ConditionalField( 

2302 PacketLenField( 

2303 "error", KRB_ERROR(), KRB_ERROR, length_from=lambda pkt: pkt.len - 6 

2304 ), 

2305 lambda pkt: pkt.apreqlen == 0, 

2306 ), 

2307 ] 

2308 

2309 def post_build(self, p, pay): 

2310 if self.len is None: 

2311 p = struct.pack("!H", len(p)) + p[2:] 

2312 if self.apreqlen is None and self.krbpriv is not None: 

2313 p = p[:4] + struct.pack("!H", len(self.apreq)) + p[6:] 

2314 return p + pay 

2315 

2316 

2317class ChangePasswdData(ASN1_Packet): 

2318 ASN1_codec = ASN1_Codecs.BER 

2319 ASN1_root = ASN1F_SEQUENCE( 

2320 ASN1F_STRING("newpasswd", ASN1_STRING(""), explicit_tag=0xA0), 

2321 ASN1F_optional( 

2322 ASN1F_PACKET("targname", None, PrincipalName, explicit_tag=0xA1) 

2323 ), 

2324 ASN1F_optional(Realm("targrealm", None, explicit_tag=0xA2)), 

2325 ) 

2326 

2327 

2328class KPASSWD_REP(Packet): 

2329 fields_desc = [ 

2330 ShortField("len", None), 

2331 ShortField("pvno", 0x0001), 

2332 ShortField("apreplen", None), 

2333 PacketLenField( 

2334 "aprep", KRB_AP_REP(), KRB_AP_REP, length_from=lambda pkt: pkt.apreplen 

2335 ), 

2336 ConditionalField( 

2337 PacketLenField( 

2338 "krbpriv", 

2339 KRB_PRIV(), 

2340 KRB_PRIV, 

2341 length_from=lambda pkt: pkt.len - 6 - pkt.apreplen, 

2342 ), 

2343 lambda pkt: pkt.apreplen != 0, 

2344 ), 

2345 ConditionalField( 

2346 PacketLenField( 

2347 "error", KRB_ERROR(), KRB_ERROR, length_from=lambda pkt: pkt.len - 6 

2348 ), 

2349 lambda pkt: pkt.apreplen == 0, 

2350 ), 

2351 ] 

2352 

2353 def post_build(self, p, pay): 

2354 if self.len is None: 

2355 p = struct.pack("!H", len(p)) + p[2:] 

2356 if self.apreplen is None and self.krbpriv is not None: 

2357 p = p[:4] + struct.pack("!H", len(self.aprep)) + p[6:] 

2358 return p + pay 

2359 

2360 def answers(self, other): 

2361 return isinstance(other, KPASSWD_REQ) 

2362 

2363 

2364KPASSWD_RESULTS = { 

2365 0: "KRB5_KPASSWD_SUCCESS", 

2366 1: "KRB5_KPASSWD_MALFORMED", 

2367 2: "KRB5_KPASSWD_HARDERROR", 

2368 3: "KRB5_KPASSWD_AUTHERROR", 

2369 4: "KRB5_KPASSWD_SOFTERROR", 

2370 5: "KRB5_KPASSWD_ACCESSDENIED", 

2371 6: "KRB5_KPASSWD_BAD_VERSION", 

2372 7: "KRB5_KPASSWD_INITIAL_FLAG_NEEDED", 

2373} 

2374 

2375 

2376class KPasswdRepData(Packet): 

2377 fields_desc = [ 

2378 ShortEnumField("resultCode", 0, KPASSWD_RESULTS), 

2379 StrField("resultString", ""), 

2380 ] 

2381 

2382 

2383class Kpasswd(Packet): 

2384 @classmethod 

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

2386 if _pkt and len(_pkt) >= 4: 

2387 if _pkt[2:4] == b"\xff\x80": 

2388 return KPASSWD_REQ 

2389 elif _pkt[2:4] == b"\x00\x01": 

2390 asn1_tag = BER_id_dec(_pkt[6:8])[0] & 0x1F 

2391 if asn1_tag == 14: 

2392 return KPASSWD_REQ 

2393 elif asn1_tag == 15: 

2394 return KPASSWD_REP 

2395 return KPASSWD_REQ 

2396 

2397 

2398bind_bottom_up(UDP, Kpasswd, sport=464) 

2399bind_bottom_up(UDP, Kpasswd, dport=464) 

2400bind_top_down(UDP, KPASSWD_REQ, sport=464, dport=464) 

2401bind_top_down(UDP, KPASSWD_REP, sport=464, dport=464) 

2402 

2403 

2404class KpasswdTCPHeader(Packet): 

2405 fields_desc = [LenField("len", None, fmt="!I")] 

2406 

2407 @classmethod 

2408 def tcp_reassemble(cls, data, *args, **kwargs): 

2409 if len(data) < 4: 

2410 return None 

2411 length = struct.unpack("!I", data[:4])[0] 

2412 if len(data) == length + 4: 

2413 return cls(data) 

2414 

2415 

2416bind_layers(KpasswdTCPHeader, Kpasswd) 

2417 

2418bind_bottom_up(TCP, KpasswdTCPHeader, sport=464) 

2419bind_layers(TCP, KpasswdTCPHeader, dport=464) 

2420 

2421 

2422# Util functions 

2423 

2424 

2425class KerberosClient(Automaton): 

2426 RES_AS_MODE = namedtuple("AS_Result", ["asrep", "sessionkey", "kdcrep"]) 

2427 RES_TGS_MODE = namedtuple("TGS_Result", ["tgsrep", "sessionkey", "kdcrep"]) 

2428 

2429 class MODE(IntEnum): 

2430 AS_REQ = 0 

2431 TGS_REQ = 1 

2432 

2433 def __init__( 

2434 self, 

2435 mode=MODE.AS_REQ, 

2436 ip=None, 

2437 host=None, 

2438 upn=None, 

2439 password=None, 

2440 realm=None, 

2441 spn=None, 

2442 ticket=None, 

2443 renew=False, 

2444 additional_tickets=[], 

2445 u2u=False, 

2446 for_user=None, 

2447 etypes=None, 

2448 key=None, 

2449 port=88, 

2450 timeout=5, 

2451 **kwargs, 

2452 ): 

2453 import scapy.libs.rfc3961 # Trigger error if any # noqa: F401 

2454 from scapy.layers.ldap import dclocator 

2455 

2456 if not upn: 

2457 raise ValueError("Invalid upn") 

2458 if not spn: 

2459 raise ValueError("Invalid spn") 

2460 if realm is None: 

2461 if mode == self.MODE.AS_REQ: 

2462 _, realm = _parse_upn(upn) 

2463 elif mode == self.MODE.TGS_REQ: 

2464 _, realm = _parse_spn(spn) 

2465 if not realm and ticket: 

2466 # if no realm is specified, but there's a ticket, take the realm 

2467 # of the ticket. 

2468 realm = ticket.realm.val.decode() 

2469 else: 

2470 raise ValueError("Invalid realm") 

2471 

2472 if mode == self.MODE.AS_REQ: 

2473 if not host: 

2474 raise ValueError("Invalid host") 

2475 elif mode == self.MODE.TGS_REQ: 

2476 if not ticket: 

2477 raise ValueError("Invalid ticket") 

2478 

2479 if not ip: 

2480 # No KDC IP provided. Find it by querying the DNS 

2481 ip = dclocator( 

2482 realm, 

2483 timeout=timeout, 

2484 # Use connect mode instead of ldap for compatibility 

2485 # with MIT kerberos servers 

2486 mode="connect", 

2487 port=port, 

2488 debug=kwargs.get("debug", 0), 

2489 ).ip 

2490 

2491 if etypes is None: 

2492 from scapy.libs.rfc3961 import EncryptionType 

2493 

2494 etypes = [ 

2495 EncryptionType.AES256_CTS_HMAC_SHA1_96, 

2496 EncryptionType.AES128_CTS_HMAC_SHA1_96, 

2497 EncryptionType.RC4_HMAC, 

2498 EncryptionType.DES_CBC_MD5, 

2499 ] 

2500 self.etypes = etypes 

2501 

2502 self.mode = mode 

2503 

2504 self.result = None # Result 

2505 

2506 self._timeout = timeout 

2507 self._ip = ip 

2508 self._port = port 

2509 sock = self._connect() 

2510 

2511 if self.mode == self.MODE.AS_REQ: 

2512 self.host = host.upper() 

2513 self.password = password and bytes_encode(password) 

2514 self.spn = spn 

2515 self.upn = upn 

2516 self.realm = realm.upper() 

2517 self.ticket = ticket 

2518 self.renew = renew 

2519 self.additional_tickets = additional_tickets # U2U + S4U2Proxy 

2520 self.u2u = u2u # U2U 

2521 self.for_user = for_user # FOR-USER 

2522 self.key = key 

2523 # See RFC4120 - sect 7.2.2 

2524 # This marks whether we should follow-up after an EOF 

2525 self.should_followup = False 

2526 # Negotiated parameters 

2527 self.pre_auth = False 

2528 self.fxcookie = None 

2529 super(KerberosClient, self).__init__( 

2530 sock=sock, 

2531 **kwargs, 

2532 ) 

2533 

2534 def _connect(self): 

2535 sock = socket.socket() 

2536 sock.settimeout(self._timeout) 

2537 sock.connect((self._ip, self._port)) 

2538 sock = StreamSocket(sock, KerberosTCPHeader) 

2539 return sock 

2540 

2541 def send(self, pkt): 

2542 super(KerberosClient, self).send(KerberosTCPHeader() / pkt) 

2543 

2544 def _base_kdc_req(self, now_time): 

2545 kdcreq = KRB_KDC_REQ_BODY( 

2546 etype=[ASN1_INTEGER(x) for x in self.etypes], 

2547 additionalTickets=None, 

2548 # Windows default 

2549 kdcOptions="forwardable+renewable+canonicalize", 

2550 cname=None, 

2551 realm=ASN1_GENERAL_STRING(self.realm), 

2552 till=ASN1_GENERALIZED_TIME(now_time + timedelta(hours=10)), 

2553 rtime=ASN1_GENERALIZED_TIME(now_time + timedelta(hours=10)), 

2554 nonce=ASN1_INTEGER(RandNum(0, 0x7FFFFFFF)._fix()), 

2555 ) 

2556 if self.renew: 

2557 kdcreq.kdcOptions.set(30, 1) # set 'renew' (bit 30) 

2558 return kdcreq 

2559 

2560 def as_req(self): 

2561 now_time = datetime.utcnow().replace(microsecond=0, tzinfo=timezone.utc) 

2562 

2563 kdc_req = self._base_kdc_req(now_time=now_time) 

2564 kdc_req.addresses = [ 

2565 HostAddress( 

2566 addrType=ASN1_INTEGER(20), # Netbios 

2567 address=ASN1_STRING(self.host.ljust(16, " ")), 

2568 ) 

2569 ] 

2570 kdc_req.cname = PrincipalName.fromUPN(self.upn) 

2571 kdc_req.sname = PrincipalName.fromSPN(self.spn) 

2572 

2573 asreq = Kerberos( 

2574 root=KRB_AS_REQ( 

2575 padata=[ 

2576 PADATA( 

2577 padataType=ASN1_INTEGER(128), # PA-PAC-REQUEST 

2578 padataValue=PA_PAC_REQUEST(includePac=ASN1_BOOLEAN(-1)), 

2579 ) 

2580 ], 

2581 reqBody=kdc_req, 

2582 ) 

2583 ) 

2584 # Pre-auth support 

2585 if self.pre_auth: 

2586 asreq.root.padata.insert( 

2587 0, 

2588 PADATA( 

2589 padataType=0x2, # PA-ENC-TIMESTAMP 

2590 padataValue=EncryptedData(), 

2591 ), 

2592 ) 

2593 asreq.root.padata[0].padataValue.encrypt( 

2594 self.key, PA_ENC_TS_ENC(patimestamp=ASN1_GENERALIZED_TIME(now_time)) 

2595 ) 

2596 # Cookie support 

2597 if self.fxcookie: 

2598 asreq.root.padata.insert( 

2599 0, 

2600 PADATA( 

2601 padataType=133, # PA-FX-COOKIE 

2602 padataValue=self.fxcookie, 

2603 ), 

2604 ) 

2605 return asreq 

2606 

2607 def tgs_req(self): 

2608 now_time = datetime.utcnow().replace(microsecond=0, tzinfo=timezone.utc) 

2609 

2610 kdc_req = self._base_kdc_req(now_time=now_time) 

2611 

2612 _, crealm = _parse_upn(self.upn) 

2613 authenticator = KRB_Authenticator( 

2614 crealm=ASN1_GENERAL_STRING(crealm), 

2615 cname=PrincipalName.fromUPN(self.upn), 

2616 cksum=None, 

2617 ctime=ASN1_GENERALIZED_TIME(now_time), 

2618 cusec=ASN1_INTEGER(0), 

2619 subkey=None, 

2620 seqNumber=None, 

2621 encAuthorizationData=None, 

2622 ) 

2623 

2624 apreq = KRB_AP_REQ(ticket=self.ticket, authenticator=EncryptedData()) 

2625 

2626 # Additional tickets 

2627 if self.additional_tickets: 

2628 kdc_req.additionalTickets = self.additional_tickets 

2629 

2630 if self.u2u: # U2U 

2631 kdc_req.kdcOptions.set(28, 1) # set 'enc-tkt-in-skey' (bit 28) 

2632 

2633 kdc_req.sname = PrincipalName.fromSPN(self.spn) 

2634 

2635 tgsreq = Kerberos( 

2636 root=KRB_TGS_REQ( 

2637 padata=[ 

2638 PADATA( 

2639 padataType=ASN1_INTEGER(1), # PA-TGS-REQ 

2640 padataValue=apreq, 

2641 ) 

2642 ], 

2643 reqBody=kdc_req, 

2644 ) 

2645 ) 

2646 

2647 # [MS-SFU] FOR-USER extension 

2648 if self.for_user is not None: 

2649 from scapy.libs.rfc3961 import ChecksumType 

2650 

2651 paforuser = PA_FOR_USER( 

2652 userName=PrincipalName.fromUPN(self.for_user), 

2653 userRealm=ASN1_GENERAL_STRING(_parse_upn(self.for_user)[1]), 

2654 cksum=Checksum(), 

2655 ) 

2656 S4UByteArray = struct.pack( # [MS-SFU] sect 2.2.1 

2657 "<I", paforuser.userName.nameType.val 

2658 ) + ( 

2659 ( 

2660 "".join(x.val for x in paforuser.userName.nameString) 

2661 + paforuser.userRealm.val 

2662 + paforuser.authPackage.val 

2663 ).encode() 

2664 ) 

2665 paforuser.cksum.make( 

2666 self.key, 

2667 S4UByteArray, 

2668 cksumtype=ChecksumType.HMAC_MD5, 

2669 ) 

2670 tgsreq.root.padata.append( 

2671 PADATA( 

2672 padataType=ASN1_INTEGER(129), # PA-FOR-USER 

2673 padataValue=paforuser, 

2674 ) 

2675 ) 

2676 

2677 # Compute checksum 

2678 if self.key.cksumtype: 

2679 authenticator.cksum = Checksum() 

2680 authenticator.cksum.make( 

2681 self.key, 

2682 bytes(kdc_req), 

2683 ) 

2684 # Encrypt authenticator 

2685 apreq.authenticator.encrypt(self.key, authenticator) 

2686 return tgsreq 

2687 

2688 @ATMT.state(initial=1) 

2689 def BEGIN(self): 

2690 pass 

2691 

2692 @ATMT.condition(BEGIN) 

2693 def should_send_as_req(self): 

2694 if self.mode == self.MODE.AS_REQ: 

2695 raise self.SENT_AP_REQ() 

2696 

2697 @ATMT.condition(BEGIN) 

2698 def should_send_tgs_req(self): 

2699 if self.mode == self.MODE.TGS_REQ: 

2700 raise self.SENT_TGS_REQ() 

2701 

2702 @ATMT.action(should_send_as_req) 

2703 def send_as_req(self): 

2704 self.send(self.as_req()) 

2705 

2706 @ATMT.action(should_send_tgs_req) 

2707 def send_tgs_req(self): 

2708 self.send(self.tgs_req()) 

2709 

2710 @ATMT.state() 

2711 def SENT_AP_REQ(self): 

2712 pass 

2713 

2714 @ATMT.state() 

2715 def SENT_TGS_REQ(self): 

2716 pass 

2717 

2718 def _process_padatas_and_key(self, padatas): 

2719 from scapy.libs.rfc3961 import EncryptionType, Key 

2720 

2721 etype = None 

2722 salt = b"" 

2723 # Process pa-data 

2724 if padatas is not None: 

2725 for padata in padatas: 

2726 if padata.padataType == 0x13 and etype is None: # PA-ETYPE-INFO2 

2727 elt = padata.padataValue.seq[0] 

2728 if elt.etype.val in self.etypes: 

2729 etype = elt.etype.val 

2730 if etype != EncryptionType.RC4_HMAC: 

2731 salt = elt.salt.val 

2732 elif padata.padataType == 133: # PA-FX-COOKIE 

2733 self.fxcookie = padata.padataValue 

2734 

2735 etype = etype or self.etypes[0] 

2736 # Compute key if not already provided 

2737 if self.key is None: 

2738 self.key = Key.string_to_key( 

2739 etype, 

2740 self.password, 

2741 salt, 

2742 ) 

2743 

2744 @ATMT.receive_condition(SENT_AP_REQ) 

2745 def receive_krb_error_as_req(self, pkt): 

2746 if Kerberos in pkt and isinstance(pkt.root, KRB_ERROR): 

2747 if pkt.root.errorCode == 25: # KDC_ERR_PREAUTH_REQUIRED 

2748 if not self.key and (not self.upn or not self.password): 

2749 log_runtime.warning( 

2750 "Got 'KDC_ERR_PREAUTH_REQUIRED', " 

2751 "but no key, nor upn+pass was passed." 

2752 ) 

2753 raise self.FINAL() 

2754 self._process_padatas_and_key(pkt.root.eData.seq) 

2755 self.should_followup = True 

2756 self.pre_auth = True 

2757 raise self.BEGIN() 

2758 else: 

2759 log_runtime.warning("Received KRB_ERROR") 

2760 pkt.show() 

2761 raise self.FINAL() 

2762 

2763 @ATMT.receive_condition(SENT_AP_REQ) 

2764 def receive_as_rep(self, pkt): 

2765 if Kerberos in pkt and isinstance(pkt.root, KRB_AS_REP): 

2766 raise self.FINAL().action_parameters(pkt) 

2767 

2768 @ATMT.eof(SENT_AP_REQ) 

2769 def retry_after_eof_in_apreq(self): 

2770 if self.should_followup: 

2771 # Reconnect and Restart 

2772 self.should_followup = False 

2773 self.update_sock(self._connect()) 

2774 raise self.BEGIN() 

2775 else: 

2776 log_runtime.warning("Socket was closed in an unexpected state") 

2777 raise self.FINAL() 

2778 

2779 @ATMT.action(receive_as_rep) 

2780 def decrypt_as_rep(self, pkt): 

2781 self._process_padatas_and_key(pkt.root.padata) 

2782 if not self.pre_auth: 

2783 log_runtime.warning("Pre-authentication was disabled for this account !") 

2784 # Decrypt 

2785 enc = pkt.root.encPart 

2786 res = enc.decrypt(self.key) 

2787 self.result = self.RES_AS_MODE(pkt.root, res.key.toKey(), res) 

2788 

2789 @ATMT.receive_condition(SENT_TGS_REQ) 

2790 def receive_krb_error_tgs_req(self, pkt): 

2791 if Kerberos in pkt and isinstance(pkt.root, KRB_ERROR): 

2792 log_runtime.warning("Received KRB_ERROR") 

2793 pkt.show() 

2794 raise self.FINAL() 

2795 

2796 @ATMT.receive_condition(SENT_TGS_REQ) 

2797 def receive_tgs_rep(self, pkt): 

2798 if Kerberos in pkt and isinstance(pkt.root, KRB_TGS_REP): 

2799 if not self.renew and pkt.root.ticket.sname.nameString[0].val == b"krbtgt": 

2800 log_runtime.warning("Received a cross-realm referral ticket !") 

2801 raise self.FINAL().action_parameters(pkt) 

2802 

2803 @ATMT.action(receive_tgs_rep) 

2804 def decrypt_tgs_rep(self, pkt): 

2805 # Decrypt 

2806 enc = pkt.root.encPart 

2807 res = enc.decrypt(self.key) 

2808 self.result = self.RES_TGS_MODE(pkt.root, res.key.toKey(), res) 

2809 

2810 @ATMT.state(final=1) 

2811 def FINAL(self): 

2812 pass 

2813 

2814 

2815def _parse_upn(upn): 

2816 m = re.match(r"^([^@\\/]+)(@|\\|/)([^@\\/]+)$", upn) 

2817 if not m: 

2818 raise ValueError("Invalid UPN: '%s'" % upn) 

2819 if m.group(2) == "@": 

2820 user = m.group(1) 

2821 domain = m.group(3) 

2822 else: 

2823 user = m.group(3) 

2824 domain = m.group(1) 

2825 return user, domain 

2826 

2827 

2828def _parse_spn(spn): 

2829 m = re.match(r"^((?:[^@\\/]+)/(?:[^@\\/]+))(?:@([^@\\/]+))?$", spn) 

2830 if not m: 

2831 raise ValueError("Invalid SPN: '%s'" % spn) 

2832 return m.group(1), m.group(2) 

2833 

2834 

2835def krb_as_req( 

2836 upn, spn=None, ip=None, key=None, password=None, realm=None, host="WIN10", **kwargs 

2837): 

2838 r""" 

2839 Kerberos AS-Req 

2840 

2841 :param upn: the user principal name formatted as "DOMAIN\user", "DOMAIN/user" 

2842 or "user@DOMAIN" 

2843 :param spn: (optional) the full service principal name. 

2844 Defaults to "krbtgt/<realm>" 

2845 :param ip: the KDC ip. (optional. If not provided, Scapy will query the DNS for 

2846 _kerberos._tcp.dc._msdcs.domain.local). 

2847 :param key: (optional) pass the Key object. 

2848 :param password: (optional) otherwise, pass the user's password 

2849 :param realm: (optional) the realm to use. Otherwise use the one from UPN. 

2850 :param host: (optional) the host performing the AS-Req. WIN10 by default. 

2851 

2852 :return: returns a named tuple (asrep=<...>, sessionkey=<...>) 

2853 

2854 Example:: 

2855 

2856 >>> # The KDC is on 192.168.122.17, we ask a TGT for user1 

2857 >>> krb_as_req("user1@DOMAIN.LOCAL", "192.168.122.17", password="Password1") 

2858 

2859 Equivalent:: 

2860 

2861 >>> from scapy.libs.rfc3961 import Key, EncryptionType 

2862 >>> key = Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=hex_bytes("6d0748c546 

2863 ...: f4e99205e78f8da7681d4ec5520ae4815543720c2a647c1ae814c9")) 

2864 >>> krb_as_req("user1@DOMAIN.LOCAL", "192.168.122.17", key=key) 

2865 """ 

2866 if realm is None: 

2867 _, realm = _parse_upn(upn) 

2868 if key is None: 

2869 if password is None: 

2870 try: 

2871 from prompt_toolkit import prompt 

2872 

2873 password = prompt("Enter password: ", is_password=True) 

2874 except ImportError: 

2875 password = input("Enter password: ") 

2876 cli = KerberosClient( 

2877 mode=KerberosClient.MODE.AS_REQ, 

2878 realm=realm, 

2879 ip=ip, 

2880 spn=spn or "krbtgt/" + realm, 

2881 host=host, 

2882 upn=upn, 

2883 password=password, 

2884 key=key, 

2885 **kwargs, 

2886 ) 

2887 cli.run() 

2888 cli.stop() 

2889 return cli.result 

2890 

2891 

2892def krb_tgs_req( 

2893 upn, 

2894 spn, 

2895 sessionkey, 

2896 ticket, 

2897 ip=None, 

2898 renew=False, 

2899 realm=None, 

2900 additional_tickets=[], 

2901 u2u=False, 

2902 etypes=None, 

2903 for_user=None, 

2904 **kwargs, 

2905): 

2906 r""" 

2907 Kerberos TGS-Req 

2908 

2909 :param upn: the user principal name formatted as "DOMAIN\user", "DOMAIN/user" 

2910 or "user@DOMAIN" 

2911 :param spn: the full service principal name (e.g. "cifs/srv1") 

2912 :param sessionkey: the session key retrieved from the tgt 

2913 :param ticket: the tgt ticket 

2914 :param ip: the KDC ip. (optional. If not provided, Scapy will query the DNS for 

2915 _kerberos._tcp.dc._msdcs.domain.local). 

2916 :param renew: ask for renewal 

2917 :param realm: (optional) the realm to use. Otherwise use the one from SPN. 

2918 :param additional_tickets: (optional) a list of additional tickets to pass. 

2919 :param u2u: (optional) if specified, enable U2U and request the ticket to be 

2920 signed using the session key from the first additional ticket. 

2921 :param etypes: array of EncryptionType values. 

2922 By default: AES128, AES256, RC4, DES_MD5 

2923 :param for_user: a user principal name to request the ticket for. This is the 

2924 S4U2Self extension. 

2925 

2926 :return: returns a named tuple (tgsrep=<...>, sessionkey=<...>) 

2927 

2928 Example:: 

2929 

2930 >>> # The KDC is on 192.168.122.17, we ask a TGT for user1 

2931 >>> krb_as_req("user1@DOMAIN.LOCAL", "192.168.122.17", password="Password1") 

2932 

2933 Equivalent:: 

2934 

2935 >>> from scapy.libs.rfc3961 import Key, EncryptionType 

2936 >>> key = Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=hex_bytes("6d0748c546 

2937 ...: f4e99205e78f8da7681d4ec5520ae4815543720c2a647c1ae814c9")) 

2938 >>> krb_as_req("user1@DOMAIN.LOCAL", "192.168.122.17", key=key) 

2939 """ 

2940 cli = KerberosClient( 

2941 mode=KerberosClient.MODE.TGS_REQ, 

2942 realm=realm, 

2943 upn=upn, 

2944 ip=ip, 

2945 spn=spn, 

2946 key=sessionkey, 

2947 ticket=ticket, 

2948 renew=renew, 

2949 additional_tickets=additional_tickets, 

2950 u2u=u2u, 

2951 etypes=etypes, 

2952 for_user=for_user, 

2953 **kwargs, 

2954 ) 

2955 cli.run() 

2956 cli.stop() 

2957 return cli.result 

2958 

2959 

2960def krb_as_and_tgs(upn, spn, ip=None, key=None, password=None, **kwargs): 

2961 """ 

2962 Kerberos AS-Req then TGS-Req 

2963 """ 

2964 res = krb_as_req(upn=upn, ip=ip, key=key, password=password, **kwargs) 

2965 if not res: 

2966 return 

2967 return krb_tgs_req( 

2968 upn=upn, 

2969 spn=spn, 

2970 sessionkey=res.sessionkey, 

2971 ticket=res.asrep.ticket, 

2972 ip=ip, 

2973 **kwargs, 

2974 ) 

2975 

2976 

2977def kpasswd( 

2978 upn, 

2979 targetupn=None, 

2980 ip=None, 

2981 password=None, 

2982 newpassword=None, 

2983 key=None, 

2984 ticket=None, 

2985 realm=None, 

2986 ssp=None, 

2987 setpassword=None, 

2988 timeout=3, 

2989 port=464, 

2990 debug=0, 

2991 **kwargs, 

2992): 

2993 """ 

2994 Change a password using RFC3244's Kerberos Set / Change Password. 

2995 

2996 :param upn: the UPN to use for authentication 

2997 :param targetupn: (optional) the UPN to change the password of. If not specified, 

2998 same as upn. 

2999 :param ip: the KDC ip. (optional. If not provided, Scapy will query the DNS for 

3000 _kerberos._tcp.dc._msdcs.domain.local). 

3001 :param key: (optional) pass the Key object. 

3002 :param ticket: (optional) a ticket to use. Either a TGT or ST for kadmin/changepw. 

3003 :param password: (optional) otherwise, pass the user's password 

3004 :param realm: (optional) the realm to use. Otherwise use the one from UPN. 

3005 :param setpassword: (optional) use "Set Password" mechanism. 

3006 :param ssp: (optional) a Kerberos SSP for the service kadmin/changepw@REALM. 

3007 If provided, you probably don't need anything else. Otherwise built. 

3008 """ 

3009 from scapy.layers.ldap import dclocator 

3010 

3011 if not realm: 

3012 _, realm = _parse_upn(upn) 

3013 spn = "kadmin/changepw@%s" % realm 

3014 if ip is None: 

3015 ip = dclocator( 

3016 realm, 

3017 timeout=timeout, 

3018 # Use connect mode instead of ldap for compatibility 

3019 # with MIT kerberos servers 

3020 mode="connect", 

3021 port=port, 

3022 debug=debug, 

3023 ).ip 

3024 if ssp is None and ticket is not None: 

3025 tktspn = ticket.getSPN().split("/")[0] 

3026 assert tktspn in ["krbtgt", "kadmin"], "Unexpected ticket type ! %s" % tktspn 

3027 if tktspn == "krbtgt": 

3028 log_runtime.info( 

3029 "Using 'Set Password' mode. This only works with admin privileges." 

3030 ) 

3031 setpassword = True 

3032 resp = krb_tgs_req( 

3033 upn=upn, 

3034 spn=spn, 

3035 ticket=ticket, 

3036 sessionkey=key, 

3037 ip=ip, 

3038 debug=debug, 

3039 ) 

3040 if resp is None: 

3041 return 

3042 ticket = resp.tgsrep.ticket 

3043 key = resp.sessionkey 

3044 if setpassword is None: 

3045 setpassword = bool(targetupn) 

3046 elif setpassword and targetupn is None: 

3047 targetupn = upn 

3048 assert setpassword or not targetupn, "Cannot use targetupn in changepassword mode !" 

3049 # Get a ticket for kadmin/changepw 

3050 if ssp is None: 

3051 if ticket is None: 

3052 # Get a ticket for kadmin/changepw through AS-REQ 

3053 resp = krb_as_req( 

3054 upn=upn, 

3055 spn=spn, 

3056 key=key, 

3057 ip=ip, 

3058 password=password, 

3059 debug=debug, 

3060 ) 

3061 if resp is None: 

3062 return 

3063 ticket = resp.asrep.ticket 

3064 key = resp.sessionkey 

3065 ssp = KerberosSSP( 

3066 UPN=upn, 

3067 SPN=spn, 

3068 ST=ticket, 

3069 KEY=key, 

3070 DC_IP=ip, 

3071 debug=debug, 

3072 **kwargs, 

3073 ) 

3074 Context, tok, negResult = ssp.GSS_Init_sec_context( 

3075 None, 

3076 req_flags=0, # No GSS_C_MUTUAL_FLAG 

3077 ) 

3078 if negResult != GSS_S_CONTINUE_NEEDED: 

3079 warning("SSP failed on initial GSS_Init_sec_context !") 

3080 if tok: 

3081 tok.show() 

3082 return 

3083 apreq = tok.innerToken.root 

3084 # Connect 

3085 sock = socket.socket() 

3086 sock.settimeout(timeout) 

3087 sock.connect((ip, port)) 

3088 sock = StreamSocket(sock, KpasswdTCPHeader) 

3089 # Do KPASSWD request 

3090 if newpassword is None: 

3091 try: 

3092 from prompt_toolkit import prompt 

3093 

3094 newpassword = prompt("Enter NEW password: ", is_password=True) 

3095 except ImportError: 

3096 newpassword = input("Enter NEW password: ") 

3097 krbpriv = KRB_PRIV(encPart=EncryptedData()) 

3098 krbpriv.encPart.encrypt( 

3099 Context.KrbSessionKey, 

3100 EncKrbPrivPart( 

3101 sAddress=HostAddress( 

3102 addrType=ASN1_INTEGER(2), # IPv4 

3103 address=ASN1_STRING(b"\xc0\xa8\x00e"), 

3104 ), 

3105 userData=ASN1_STRING( 

3106 bytes( 

3107 ChangePasswdData( 

3108 newpasswd=newpassword, 

3109 targname=PrincipalName.fromUPN(targetupn), 

3110 targrealm=realm, 

3111 ) 

3112 ) 

3113 if setpassword 

3114 else newpassword 

3115 ), 

3116 timestamp=None, 

3117 usec=None, 

3118 seqNumber=Context.SendSeqNum, 

3119 ), 

3120 ) 

3121 resp = sock.sr1( 

3122 KpasswdTCPHeader() 

3123 / KPASSWD_REQ( 

3124 pvno=0xFF80 if setpassword else 1, 

3125 apreq=apreq, 

3126 krbpriv=krbpriv, 

3127 ), 

3128 timeout=timeout, 

3129 verbose=0, 

3130 ) 

3131 # Verify KPASSWD response 

3132 if not resp: 

3133 raise TimeoutError("KPASSWD_REQ timed out !") 

3134 if KPASSWD_REP not in resp: 

3135 resp.show() 

3136 raise ValueError("Invalid response to KPASSWD_REQ !") 

3137 Context, tok, negResult = ssp.GSS_Init_sec_context(Context, resp.aprep) 

3138 if negResult != GSS_S_COMPLETE: 

3139 warning("SSP failed on subsequent GSS_Init_sec_context !") 

3140 if tok: 

3141 tok.show() 

3142 return 

3143 # Parse answer KRB_PRIV 

3144 krbanswer = resp.krbpriv.encPart.decrypt(Context.KrbSessionKey) 

3145 userRep = KPasswdRepData(krbanswer.userData.val) 

3146 if userRep.resultCode != 0: 

3147 warning(userRep.sprintf("KPASSWD failed !")) 

3148 userRep.show() 

3149 return 

3150 print(userRep.sprintf("%resultCode%")) 

3151 

3152 

3153# SSP 

3154 

3155 

3156class KerberosSSP(SSP): 

3157 """ 

3158 The KerberosSSP 

3159 

3160 Client settings: 

3161 

3162 :param ST: the service ticket to use for access. 

3163 If not provided, will be retrieved 

3164 :param SPN: the SPN of the service to use 

3165 :param UPN: The client UPN 

3166 :param DC_IP: (optional) is ST+KEY are not provided, will need to contact 

3167 the KDC at this IP. If not provided, will perform dc locator. 

3168 :param TGT: (optional) pass a TGT to use to get the ST. 

3169 :param KEY: the session key associated with the ST if it is provided, 

3170 OR the session key associated with the TGT 

3171 OR the kerberos key associated with the UPN 

3172 :param PASSWORD: (optional) if a UPN is provided and not a KEY, this is the 

3173 password of the UPN. 

3174 :param U2U: (optional) use U2U when requesting the ST. 

3175 

3176 Server settings: 

3177 

3178 :param SPN: the SPN of the service to use 

3179 :param KEY: the kerberos key to use to decrypt the AP-req 

3180 :param TGT: (optional) pass a TGT to use for U2U 

3181 :param DC_IP: (optional) if TGT is not provided, request one on the KDC at 

3182 this IP using using the KEY when using U2U. 

3183 :param REQUIRE_U2U: (optional, default False) require U2U 

3184 """ 

3185 

3186 oid = "1.2.840.113554.1.2.2" 

3187 auth_type = 0x10 

3188 

3189 class STATE(SSP.STATE): 

3190 INIT = 1 

3191 CLI_SENT_TGTREQ = 2 

3192 CLI_SENT_APREQ = 3 

3193 CLI_RCVD_APREP = 4 

3194 SRV_SENT_APREP = 5 

3195 

3196 class CONTEXT(SSP.CONTEXT): 

3197 __slots__ = [ 

3198 "SessionKey", 

3199 "ServerHostname", 

3200 "U2U", 

3201 "KrbSessionKey", # raw Key object 

3202 "STSessionKey", # raw ST Key object (for DCE_STYLE) 

3203 "SeqNum", # for AP 

3204 "SendSeqNum", # for MIC 

3205 "RecvSeqNum", # for MIC 

3206 "IsAcceptor", 

3207 "SendSealKeyUsage", 

3208 "SendSignKeyUsage", 

3209 "RecvSealKeyUsage", 

3210 "RecvSignKeyUsage", 

3211 ] 

3212 

3213 def __init__(self, IsAcceptor, req_flags=None): 

3214 self.state = KerberosSSP.STATE.INIT 

3215 self.SessionKey = None 

3216 self.ServerHostname = None 

3217 self.U2U = False 

3218 self.SendSeqNum = 0 

3219 self.RecvSeqNum = 0 

3220 self.KrbSessionKey = None 

3221 self.STSessionKey = None 

3222 self.IsAcceptor = IsAcceptor 

3223 # [RFC 4121] sect 2 

3224 if IsAcceptor: 

3225 self.SendSealKeyUsage = 22 

3226 self.SendSignKeyUsage = 23 

3227 self.RecvSealKeyUsage = 24 

3228 self.RecvSignKeyUsage = 25 

3229 else: 

3230 self.SendSealKeyUsage = 24 

3231 self.SendSignKeyUsage = 25 

3232 self.RecvSealKeyUsage = 22 

3233 self.RecvSignKeyUsage = 23 

3234 super(KerberosSSP.CONTEXT, self).__init__(req_flags=req_flags) 

3235 

3236 def clifailure(self): 

3237 self.__init__(self.IsAcceptor, req_flags=self.flags) 

3238 

3239 def __repr__(self): 

3240 if self.U2U: 

3241 return "KerberosSSP-U2U" 

3242 return "KerberosSSP" 

3243 

3244 def __init__( 

3245 self, 

3246 ST=None, 

3247 UPN=None, 

3248 PASSWORD=None, 

3249 U2U=False, 

3250 KEY=None, 

3251 SPN=None, 

3252 TGT=None, 

3253 DC_IP=None, 

3254 REQUIRE_U2U=False, 

3255 SKEY_TYPE=None, 

3256 debug=0, 

3257 **kwargs, 

3258 ): 

3259 self.ST = ST 

3260 self.UPN = UPN 

3261 self.KEY = KEY 

3262 self.SPN = SPN 

3263 self.TGT = TGT 

3264 self.PASSWORD = PASSWORD 

3265 self.U2U = U2U 

3266 self.DC_IP = DC_IP 

3267 self.REQUIRE_U2U = REQUIRE_U2U 

3268 self.debug = debug 

3269 if SKEY_TYPE is None: 

3270 from scapy.libs.rfc3961 import EncryptionType 

3271 

3272 SKEY_TYPE = EncryptionType.AES128_CTS_HMAC_SHA1_96 

3273 self.SKEY_TYPE = SKEY_TYPE 

3274 super(KerberosSSP, self).__init__(**kwargs) 

3275 

3276 def GSS_GetMICEx(self, Context, msgs, qop_req=0): 

3277 """ 

3278 [MS-KILE] sect 3.4.5.6 

3279 

3280 - AES: RFC4121 sect 4.2.6.1 

3281 """ 

3282 if Context.KrbSessionKey.etype in [17, 18]: # AES 

3283 # Concatenate the ToSign 

3284 ToSign = b"".join(x.data for x in msgs if x.sign) 

3285 sig = KRB_InnerToken( 

3286 TOK_ID=b"\x04\x04", 

3287 root=KRB_GSS_MIC( 

3288 Flags="AcceptorSubkey" 

3289 + ("+SentByAcceptor" if Context.IsAcceptor else ""), 

3290 SND_SEQ=Context.SendSeqNum, 

3291 ), 

3292 ) 

3293 ToSign += bytes(sig)[:16] 

3294 sig.root.SGN_CKSUM = Context.KrbSessionKey.make_checksum( 

3295 keyusage=Context.SendSignKeyUsage, 

3296 text=ToSign, 

3297 ) 

3298 else: 

3299 raise NotImplementedError 

3300 Context.SendSeqNum += 1 

3301 return sig 

3302 

3303 def GSS_VerifyMICEx(self, Context, msgs, signature): 

3304 """ 

3305 [MS-KILE] sect 3.4.5.7 

3306 

3307 - AES: RFC4121 sect 4.2.6.1 

3308 """ 

3309 Context.RecvSeqNum = signature.root.SND_SEQ 

3310 if Context.KrbSessionKey.etype in [17, 18]: # AES 

3311 # Concatenate the ToSign 

3312 ToSign = b"".join(x.data for x in msgs if x.sign) 

3313 ToSign += bytes(signature)[:16] 

3314 sig = Context.KrbSessionKey.make_checksum( 

3315 keyusage=Context.RecvSignKeyUsage, 

3316 text=ToSign, 

3317 ) 

3318 else: 

3319 raise NotImplementedError 

3320 if sig != signature.root.SGN_CKSUM: 

3321 raise ValueError("ERROR: Checksums don't match") 

3322 

3323 def GSS_WrapEx(self, Context, msgs, qop_req=0): 

3324 """ 

3325 [MS-KILE] sect 3.4.5.4 

3326 

3327 - AES: RFC4121 sect 4.2.6.2 and [MS-KILE] sect 3.4.5.4.1 

3328 - HMAC-RC4: RFC4757 sect 7.3 and [MS-KILE] sect 3.4.5.4.1 

3329 """ 

3330 confidentiality = Context.flags & GSS_C_FLAGS.GSS_C_CONF_FLAG 

3331 if Context.KrbSessionKey.etype in [17, 18]: # AES 

3332 # Build token 

3333 tok = KRB_InnerToken( 

3334 TOK_ID=b"\x05\x04", 

3335 root=KRB_GSS_Wrap( 

3336 Flags="AcceptorSubkey" 

3337 + ("+SentByAcceptor" if Context.IsAcceptor else "") 

3338 + ("+Sealed" if confidentiality else ""), 

3339 SND_SEQ=Context.SendSeqNum, 

3340 RRC=0, 

3341 ), 

3342 ) 

3343 Context.SendSeqNum += 1 

3344 # Real separation starts now: RFC4121 sect 4.2.4 

3345 if confidentiality: 

3346 # Confidentiality is requested (see RFC4121 sect 4.3) 

3347 # {"header" | encrypt(plaintext-data | filler | "header")} 

3348 # 0. Roll confounder 

3349 Confounder = os.urandom(Context.KrbSessionKey.ep.blocksize) 

3350 # 1. Concatenate the data to be encrypted 

3351 Data = b"".join(x.data for x in msgs if x.conf_req_flag) 

3352 DataLen = len(Data) 

3353 # 2. Add filler 

3354 tok.root.EC = ((-DataLen) % Context.KrbSessionKey.ep.blocksize) or 16 

3355 Filler = b"\x00" * tok.root.EC 

3356 Data += Filler 

3357 # 3. Add first 16 octets of the Wrap token "header" 

3358 PlainHeader = bytes(tok)[:16] 

3359 Data += PlainHeader 

3360 # 4. Build 'ToSign', exclusively used for checksum 

3361 ToSign = Confounder 

3362 ToSign += b"".join(x.data for x in msgs if x.sign) 

3363 ToSign += Filler 

3364 ToSign += PlainHeader 

3365 # 5. Finalize token for signing 

3366 # "The RRC field is [...] 28 if encryption is requested." 

3367 tok.root.RRC = 28 

3368 # 6. encrypt() is the encryption operation (which provides for 

3369 # integrity protection) 

3370 Data = Context.KrbSessionKey.encrypt( 

3371 keyusage=Context.SendSealKeyUsage, 

3372 plaintext=Data, 

3373 confounder=Confounder, 

3374 signtext=ToSign, 

3375 ) 

3376 # 7. Rotate 

3377 Data = strrot(Data, tok.root.RRC + tok.root.EC) 

3378 # 8. Split (token and encrypted messages) 

3379 toklen = len(Data) - DataLen 

3380 tok.root.Data = Data[:toklen] 

3381 offset = toklen 

3382 for msg in msgs: 

3383 msglen = len(msg.data) 

3384 if msg.conf_req_flag: 

3385 msg.data = Data[offset : offset + msglen] 

3386 offset += msglen 

3387 return msgs, tok 

3388 else: 

3389 # No confidentiality is requested 

3390 # {"header" | plaintext-data | get_mic(plaintext-data | "header")} 

3391 # 0. Concatenate the data 

3392 Data = b"".join(x.data for x in msgs if x.sign) 

3393 DataLen = len(Data) 

3394 # 1. Add first 16 octets of the Wrap token "header" 

3395 ToSign = Data 

3396 ToSign += bytes(tok)[:16] 

3397 # 2. get_mic() is the checksum operation for the required 

3398 # checksum mechanism 

3399 Mic = Context.KrbSessionKey.make_checksum( 

3400 keyusage=Context.SendSealKeyUsage, 

3401 text=ToSign, 

3402 ) 

3403 # In Wrap tokens without confidentiality, the EC field SHALL be used 

3404 # to encode the number of octets in the trailing checksum 

3405 tok.root.EC = 12 # len(tok.root.Data) == 12 for AES 

3406 # "The RRC field ([RFC4121] section 4.2.5) is 12 if no encryption 

3407 # is requested" 

3408 tok.root.RRC = 12 

3409 # 3. Concat and pack 

3410 for msg in msgs: 

3411 if msg.sign: 

3412 msg.data = b"" 

3413 Data = Data + Mic 

3414 # 4. Rotate 

3415 tok.root.Data = strrot(Data, tok.root.RRC) 

3416 return msgs, tok 

3417 elif Context.KrbSessionKey.etype in [23, 24]: # RC4 

3418 from scapy.libs.rfc3961 import Hmac_MD5, Cipher, algorithms, _rfc1964pad 

3419 

3420 # Build token 

3421 seq = struct.pack(">I", Context.SendSeqNum) 

3422 tok = KRB_InnerToken( 

3423 TOK_ID=b"\x02\x01", 

3424 root=KRB_GSS_Wrap_RFC1964( 

3425 SGN_ALG="HMAC", 

3426 SEAL_ALG="RC4" if confidentiality else "none", 

3427 SND_SEQ=seq 

3428 + ( 

3429 # See errata 

3430 b"\xff\xff\xff\xff" 

3431 if Context.IsAcceptor 

3432 else b"\x00\x00\x00\x00" 

3433 ), 

3434 ), 

3435 ) 

3436 Context.SendSeqNum += 1 

3437 # 0. Concatenate data 

3438 ToSign = _rfc1964pad(b"".join(x.data for x in msgs if x.sign)) 

3439 ToEncrypt = b"".join(x.data for x in msgs if x.conf_req_flag) 

3440 Kss = Context.KrbSessionKey.key 

3441 # 1. Roll confounder 

3442 Confounder = os.urandom(8) 

3443 # 2. Compute the 'Kseq' key 

3444 Klocal = strxor(Kss, len(Kss) * b"\xf0") 

3445 if Context.KrbSessionKey.etype == 24: # EXP 

3446 Kcrypt = Hmac_MD5(Klocal).digest(b"fortybits\x00" + b"\x00\x00\x00\x00") 

3447 Kcrypt = Kcrypt[:7] + b"\xab" * 9 

3448 else: 

3449 Kcrypt = Hmac_MD5(Klocal).digest(b"\x00\x00\x00\x00") 

3450 Kcrypt = Hmac_MD5(Kcrypt).digest(seq) 

3451 # 3. Build SGN_CKSUM 

3452 tok.root.SGN_CKSUM = Context.KrbSessionKey.make_checksum( 

3453 keyusage=13, # See errata 

3454 text=bytes(tok)[:8] + Confounder + ToSign, 

3455 )[:8] 

3456 # 4. Populate token + encrypt 

3457 if confidentiality: 

3458 # 'encrypt' is requested 

3459 rc4 = Cipher(algorithms.ARC4(Kcrypt), mode=None).encryptor() 

3460 tok.root.CONFOUNDER = rc4.update(Confounder) 

3461 Data = rc4.update(ToEncrypt) 

3462 # Split encrypted data 

3463 offset = 0 

3464 for msg in msgs: 

3465 msglen = len(msg.data) 

3466 if msg.conf_req_flag: 

3467 msg.data = Data[offset : offset + msglen] 

3468 offset += msglen 

3469 else: 

3470 # 'encrypt' is not requested 

3471 tok.root.CONFOUNDER = Confounder 

3472 # 5. Compute the 'Kseq' key 

3473 if Context.KrbSessionKey.etype == 24: # EXP 

3474 Kseq = Hmac_MD5(Kss).digest(b"fortybits\x00" + b"\x00\x00\x00\x00") 

3475 Kseq = Kseq[:7] + b"\xab" * 9 

3476 else: 

3477 Kseq = Hmac_MD5(Kss).digest(b"\x00\x00\x00\x00") 

3478 Kseq = Hmac_MD5(Kseq).digest(tok.root.SGN_CKSUM) 

3479 # 6. Encrypt 'SND_SEQ' 

3480 rc4 = Cipher(algorithms.ARC4(Kseq), mode=None).encryptor() 

3481 tok.root.SND_SEQ = rc4.update(tok.root.SND_SEQ) 

3482 # 7. Include 'InitialContextToken pseudo ASN.1 header' 

3483 tok = KRB_GSSAPI_Token( 

3484 MechType="1.2.840.113554.1.2.2", # Kerberos 5 

3485 innerToken=tok, 

3486 ) 

3487 return msgs, tok 

3488 else: 

3489 raise NotImplementedError 

3490 

3491 def GSS_UnwrapEx(self, Context, msgs, signature): 

3492 """ 

3493 [MS-KILE] sect 3.4.5.5 

3494 

3495 - AES: RFC4121 sect 4.2.6.2 

3496 - HMAC-RC4: RFC4757 sect 7.3 

3497 """ 

3498 confidentiality = Context.flags & GSS_C_FLAGS.GSS_C_CONF_FLAG 

3499 if Context.KrbSessionKey.etype in [17, 18]: # AES 

3500 # Real separation starts now: RFC4121 sect 4.2.4 

3501 if confidentiality: 

3502 # 0. Concatenate the data 

3503 Data = signature.root.Data 

3504 Data += b"".join(x.data for x in msgs if x.conf_req_flag) 

3505 # 1. Un-Rotate 

3506 Data = strrot(Data, signature.root.RRC + signature.root.EC, right=False) 

3507 

3508 # 2. Function to build 'ToSign', exclusively used for checksum 

3509 def MakeToSign(Confounder, DecText): 

3510 offset = 0 

3511 # 2.a Confounder 

3512 ToSign = Confounder 

3513 # 2.b Messages 

3514 for msg in msgs: 

3515 msglen = len(msg.data) 

3516 if msg.conf_req_flag: 

3517 ToSign += DecText[offset : offset + msglen] 

3518 offset += msglen 

3519 elif msg.sign: 

3520 ToSign += msg.data 

3521 # 2.c Filler & Padding 

3522 ToSign += DecText[offset:] 

3523 return ToSign 

3524 

3525 # 3. Decrypt 

3526 Data = Context.KrbSessionKey.decrypt( 

3527 keyusage=Context.RecvSealKeyUsage, 

3528 ciphertext=Data, 

3529 presignfunc=MakeToSign, 

3530 ) 

3531 # 4. Split 

3532 Data, f16header = ( 

3533 Data[:-16], 

3534 Data[-16:], 

3535 ) 

3536 # 5. Check header 

3537 hdr = signature.copy() 

3538 hdr.root.RRC = 0 

3539 if f16header != bytes(hdr)[:16]: 

3540 raise ValueError("ERROR: Headers don't match") 

3541 # 6. Split (and ignore filler) 

3542 offset = 0 

3543 for msg in msgs: 

3544 msglen = len(msg.data) 

3545 if msg.conf_req_flag: 

3546 msg.data = Data[offset : offset + msglen] 

3547 offset += msglen 

3548 return msgs 

3549 else: 

3550 # No confidentiality is requested 

3551 # 0. Concatenate the data 

3552 Data = signature.root.Data 

3553 Data += b"".join(x.data for x in msgs if x.sign) 

3554 # 1. Un-Rotate 

3555 Data = strrot(Data, signature.root.RRC, right=False) 

3556 # 2. Split 

3557 Data, Mic = Data[: -signature.root.EC], Data[-signature.root.EC :] 

3558 # "Both the EC field and the RRC field in 

3559 # the token header SHALL be filled with zeroes for the purpose of 

3560 # calculating the checksum." 

3561 ToSign = Data 

3562 hdr = signature.copy() 

3563 hdr.root.RRC = 0 

3564 hdr.root.EC = 0 

3565 # Concatenate the data 

3566 ToSign += bytes(hdr)[:16] 

3567 # 3. Calculate the signature 

3568 sig = Context.KrbSessionKey.make_checksum( 

3569 keyusage=Context.RecvSealKeyUsage, 

3570 text=ToSign, 

3571 ) 

3572 # 4. Compare 

3573 if sig != Mic: 

3574 raise ValueError("ERROR: Checksums don't match") 

3575 # 5. Split 

3576 for msg in msgs: 

3577 if msg.sign: 

3578 msg.data = Data 

3579 return msgs 

3580 elif Context.KrbSessionKey.etype in [23, 24]: # RC4 

3581 from scapy.libs.rfc3961 import Hmac_MD5, Cipher, algorithms, _rfc1964pad 

3582 

3583 # Drop wrapping 

3584 tok = signature.innerToken 

3585 

3586 # 0. Concatenate data 

3587 ToDecrypt = b"".join(x.data for x in msgs if x.conf_req_flag) 

3588 Kss = Context.KrbSessionKey.key 

3589 # 1. Compute the 'Kseq' key 

3590 if Context.KrbSessionKey.etype == 24: # EXP 

3591 Kseq = Hmac_MD5(Kss).digest(b"fortybits\x00" + b"\x00\x00\x00\x00") 

3592 Kseq = Kseq[:7] + b"\xab" * 9 

3593 else: 

3594 Kseq = Hmac_MD5(Kss).digest(b"\x00\x00\x00\x00") 

3595 Kseq = Hmac_MD5(Kseq).digest(tok.root.SGN_CKSUM) 

3596 # 2. Decrypt 'SND_SEQ' 

3597 rc4 = Cipher(algorithms.ARC4(Kseq), mode=None).encryptor() 

3598 seq = rc4.update(tok.root.SND_SEQ)[:4] 

3599 # 3. Compute the 'Kcrypt' key 

3600 Klocal = strxor(Kss, len(Kss) * b"\xf0") 

3601 if Context.KrbSessionKey.etype == 24: # EXP 

3602 Kcrypt = Hmac_MD5(Klocal).digest(b"fortybits\x00" + b"\x00\x00\x00\x00") 

3603 Kcrypt = Kcrypt[:7] + b"\xab" * 9 

3604 else: 

3605 Kcrypt = Hmac_MD5(Klocal).digest(b"\x00\x00\x00\x00") 

3606 Kcrypt = Hmac_MD5(Kcrypt).digest(seq) 

3607 # 4. Decrypt 

3608 if confidentiality: 

3609 # 'encrypt' was requested 

3610 rc4 = Cipher(algorithms.ARC4(Kcrypt), mode=None).encryptor() 

3611 Confounder = rc4.update(tok.root.CONFOUNDER) 

3612 Data = rc4.update(ToDecrypt) 

3613 # Split encrypted data 

3614 offset = 0 

3615 for msg in msgs: 

3616 msglen = len(msg.data) 

3617 if msg.conf_req_flag: 

3618 msg.data = Data[offset : offset + msglen] 

3619 offset += msglen 

3620 else: 

3621 # 'encrypt' was not requested 

3622 Confounder = tok.root.CONFOUNDER 

3623 # 5. Verify SGN_CKSUM 

3624 ToSign = _rfc1964pad(b"".join(x.data for x in msgs if x.sign)) 

3625 Context.KrbSessionKey.verify_checksum( 

3626 keyusage=13, # See errata 

3627 text=bytes(tok)[:8] + Confounder + ToSign, 

3628 cksum=tok.root.SGN_CKSUM, 

3629 ) 

3630 return msgs 

3631 else: 

3632 raise NotImplementedError 

3633 

3634 def GSS_Init_sec_context( 

3635 self, Context: CONTEXT, val=None, req_flags: Optional[GSS_C_FLAGS] = None 

3636 ): 

3637 if Context is None: 

3638 # New context 

3639 Context = self.CONTEXT(IsAcceptor=False, req_flags=req_flags) 

3640 

3641 from scapy.libs.rfc3961 import Key 

3642 

3643 if Context.state == self.STATE.INIT and self.U2U: 

3644 # U2U - Get TGT 

3645 Context.state = self.STATE.CLI_SENT_TGTREQ 

3646 return ( 

3647 Context, 

3648 KRB_GSSAPI_Token( 

3649 MechType="1.2.840.113554.1.2.2.3", # U2U 

3650 innerToken=KRB_InnerToken( 

3651 TOK_ID=b"\x04\x00", 

3652 root=KRB_TGT_REQ(), 

3653 ), 

3654 ), 

3655 GSS_S_CONTINUE_NEEDED, 

3656 ) 

3657 

3658 if Context.state in [self.STATE.INIT, self.STATE.CLI_SENT_TGTREQ]: 

3659 if not self.UPN: 

3660 raise ValueError("Missing UPN attribute") 

3661 # Do we have a ST? 

3662 if self.ST is None: 

3663 # Client sends an AP-req 

3664 if not self.SPN: 

3665 raise ValueError("Missing SPN attribute") 

3666 additional_tickets = [] 

3667 if self.U2U: 

3668 try: 

3669 # GSSAPI / Kerberos 

3670 tgt_rep = val.root.innerToken.root 

3671 except AttributeError: 

3672 try: 

3673 # Kerberos 

3674 tgt_rep = val.innerToken.root 

3675 except AttributeError: 

3676 return Context, None, GSS_S_DEFECTIVE_TOKEN 

3677 if not isinstance(tgt_rep, KRB_TGT_REP): 

3678 tgt_rep.show() 

3679 raise ValueError("KerberosSSP: Unexpected token !") 

3680 additional_tickets = [tgt_rep.ticket] 

3681 if self.TGT is not None: 

3682 if not self.KEY: 

3683 raise ValueError("Cannot use TGT without the KEY") 

3684 # Use TGT 

3685 res = krb_tgs_req( 

3686 upn=self.UPN, 

3687 spn=self.SPN, 

3688 ip=self.DC_IP, 

3689 sessionkey=self.KEY, 

3690 ticket=self.TGT, 

3691 additional_tickets=additional_tickets, 

3692 u2u=self.U2U, 

3693 debug=self.debug, 

3694 ) 

3695 else: 

3696 # Ask for TGT then ST 

3697 res = krb_as_and_tgs( 

3698 upn=self.UPN, 

3699 spn=self.SPN, 

3700 ip=self.DC_IP, 

3701 key=self.KEY, 

3702 password=self.PASSWORD, 

3703 additional_tickets=additional_tickets, 

3704 u2u=self.U2U, 

3705 debug=self.debug, 

3706 ) 

3707 if not res: 

3708 # Failed to retrieve the ticket 

3709 return Context, None, GSS_S_FAILURE 

3710 self.ST, self.KEY = res.tgsrep.ticket, res.sessionkey 

3711 elif not self.KEY: 

3712 raise ValueError("Must provide KEY with ST") 

3713 Context.STSessionKey = self.KEY 

3714 # Save ServerHostname 

3715 if len(self.ST.sname.nameString) == 2: 

3716 Context.ServerHostname = self.ST.sname.nameString[1].val.decode() 

3717 # Build the KRB-AP 

3718 apOptions = ASN1_BIT_STRING("000") 

3719 if Context.flags & GSS_C_FLAGS.GSS_C_MUTUAL_FLAG: 

3720 apOptions.set(2, "1") # mutual-required 

3721 if self.U2U: 

3722 apOptions.set(1, "1") # use-session-key 

3723 Context.U2U = True 

3724 ap_req = KRB_AP_REQ( 

3725 apOptions=apOptions, 

3726 ticket=self.ST, 

3727 authenticator=EncryptedData(), 

3728 ) 

3729 # Build the authenticator 

3730 now_time = datetime.utcnow().replace(microsecond=0, tzinfo=timezone.utc) 

3731 Context.KrbSessionKey = Key.random_to_key( 

3732 self.SKEY_TYPE, 

3733 os.urandom(16), 

3734 ) 

3735 Context.SendSeqNum = RandNum(0, 0x7FFFFFFF)._fix() 

3736 ap_req.authenticator.encrypt( 

3737 Context.STSessionKey, 

3738 KRB_Authenticator( 

3739 crealm=self.ST.realm, 

3740 cname=PrincipalName.fromUPN(self.UPN), 

3741 # RFC 4121 checksum 

3742 cksum=Checksum( 

3743 cksumtype="KRB-AUTHENTICATOR", 

3744 checksum=KRB_AuthenticatorChecksum(Flags=int(Context.flags)), 

3745 ), 

3746 ctime=ASN1_GENERALIZED_TIME(now_time), 

3747 cusec=ASN1_INTEGER(0), 

3748 subkey=EncryptionKey.fromKey(Context.KrbSessionKey), 

3749 seqNumber=Context.SendSeqNum, 

3750 encAuthorizationData=AuthorizationData( 

3751 seq=[ 

3752 AuthorizationDataItem( 

3753 adType="AD-IF-RELEVANT", 

3754 adData=AuthorizationData( 

3755 seq=[ 

3756 AuthorizationDataItem( 

3757 adType="KERB-AUTH-DATA-TOKEN-RESTRICTIONS", 

3758 adData=KERB_AD_RESTRICTION_ENTRY( 

3759 restriction=LSAP_TOKEN_INFO_INTEGRITY( 

3760 MachineID=bytes(RandBin(32)) 

3761 ) 

3762 ), 

3763 ), 

3764 AuthorizationDataItem( 

3765 adType="KERB-LOCAL", 

3766 adData=b"\x00" * 16, 

3767 ), 

3768 ] 

3769 ), 

3770 ) 

3771 ] 

3772 ), 

3773 ), 

3774 ) 

3775 Context.state = self.STATE.CLI_SENT_APREQ 

3776 if Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE: 

3777 # Raw kerberos DCE-STYLE 

3778 return Context, ap_req, GSS_S_CONTINUE_NEEDED 

3779 else: 

3780 # Kerberos wrapper 

3781 return ( 

3782 Context, 

3783 KRB_GSSAPI_Token( 

3784 innerToken=KRB_InnerToken( 

3785 root=ap_req, 

3786 ) 

3787 ), 

3788 GSS_S_CONTINUE_NEEDED, 

3789 ) 

3790 

3791 elif Context.state == self.STATE.CLI_SENT_APREQ: 

3792 if isinstance(val, KRB_AP_REP): 

3793 # Raw AP_REP was passed 

3794 ap_rep = val 

3795 else: 

3796 try: 

3797 # GSSAPI / Kerberos 

3798 ap_rep = val.root.innerToken.root 

3799 except AttributeError: 

3800 try: 

3801 # Kerberos 

3802 ap_rep = val.innerToken.root 

3803 except AttributeError: 

3804 try: 

3805 # Raw kerberos DCE-STYLE 

3806 ap_rep = val.root 

3807 except AttributeError: 

3808 return Context, None, GSS_S_DEFECTIVE_TOKEN 

3809 if not isinstance(ap_rep, KRB_AP_REP): 

3810 return Context, None, GSS_S_DEFECTIVE_TOKEN 

3811 # Retrieve SessionKey 

3812 repPart = ap_rep.encPart.decrypt(Context.STSessionKey) 

3813 if repPart.subkey is not None: 

3814 Context.SessionKey = repPart.subkey.keyvalue.val 

3815 Context.KrbSessionKey = repPart.subkey.toKey() 

3816 # OK ! 

3817 Context.state = self.STATE.CLI_RCVD_APREP 

3818 if Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE: 

3819 # [MS-KILE] sect 3.4.5.1 

3820 # The client MUST generate an additional AP exchange reply message 

3821 # exactly as the server would as the final message to send to the 

3822 # server. 

3823 now_time = datetime.utcnow().replace(microsecond=0, tzinfo=timezone.utc) 

3824 cli_ap_rep = KRB_AP_REP(encPart=EncryptedData()) 

3825 cli_ap_rep.encPart.encrypt( 

3826 Context.STSessionKey, 

3827 EncAPRepPart( 

3828 ctime=ASN1_GENERALIZED_TIME(now_time), 

3829 seqNumber=repPart.seqNumber, 

3830 subkey=None, 

3831 ), 

3832 ) 

3833 return Context, cli_ap_rep, GSS_S_COMPLETE 

3834 return Context, None, GSS_S_COMPLETE 

3835 elif ( 

3836 Context.state == self.STATE.CLI_RCVD_APREP 

3837 and Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE 

3838 ): 

3839 # DCE_STYLE with SPNEGOSSP 

3840 return Context, None, GSS_S_COMPLETE 

3841 else: 

3842 raise ValueError("KerberosSSP: Unknown state") 

3843 

3844 def _setup_u2u(self): 

3845 if not self.TGT: 

3846 # Get a TGT for ourselves 

3847 try: 

3848 upn = "@".join(self.SPN.split("/")[1].split(".", 1)) 

3849 except KeyError: 

3850 raise ValueError("Couldn't transform the SPN into a valid UPN") 

3851 res = krb_as_req(upn, self.DC_IP, key=self.KEY) 

3852 self.TGT, self.KEY = res.asrep.ticket, res.sessionkey 

3853 

3854 def GSS_Accept_sec_context(self, Context: CONTEXT, val=None): 

3855 if Context is None: 

3856 # New context 

3857 Context = self.CONTEXT(IsAcceptor=True, req_flags=0) 

3858 

3859 from scapy.libs.rfc3961 import Key 

3860 

3861 if Context.state == self.STATE.INIT: 

3862 if not self.SPN: 

3863 raise ValueError("Missing SPN attribute") 

3864 # Server receives AP-req, sends AP-rep 

3865 if isinstance(val, KRB_AP_REQ): 

3866 # Raw AP_REQ was passed 

3867 ap_req = val 

3868 else: 

3869 try: 

3870 # GSSAPI/Kerberos 

3871 ap_req = val.root.innerToken.root 

3872 except AttributeError: 

3873 try: 

3874 # Raw Kerberos 

3875 ap_req = val.root 

3876 except AttributeError: 

3877 return Context, None, GSS_S_DEFECTIVE_TOKEN 

3878 if isinstance(ap_req, KRB_TGT_REQ): 

3879 # Special U2U case 

3880 self._setup_u2u() 

3881 Context.U2U = True 

3882 return ( 

3883 None, 

3884 KRB_GSSAPI_Token( 

3885 MechType="1.2.840.113554.1.2.2.3", # U2U 

3886 innerToken=KRB_InnerToken( 

3887 TOK_ID=b"\x04\x01", 

3888 root=KRB_TGT_REP( 

3889 ticket=self.TGT, 

3890 ), 

3891 ), 

3892 ), 

3893 GSS_S_CONTINUE_NEEDED, 

3894 ) 

3895 elif not isinstance(ap_req, KRB_AP_REQ): 

3896 ap_req.show() 

3897 raise ValueError("Unexpected type in KerberosSSP") 

3898 if not self.KEY: 

3899 raise ValueError("Missing KEY attribute") 

3900 # Validate SPN 

3901 tkt_spn = "/".join( 

3902 x.val.decode() for x in ap_req.ticket.sname.nameString[:2] 

3903 ).lower() 

3904 if tkt_spn not in [self.SPN.lower(), self.SPN.lower().split(".", 1)[0]]: 

3905 warning("KerberosSSP: bad SPN: %s != %s" % (tkt_spn, self.SPN)) 

3906 return Context, None, GSS_S_BAD_MECH 

3907 # Enforce U2U if required 

3908 if self.REQUIRE_U2U and ap_req.apOptions.val[1] != "1": # use-session-key 

3909 # Required but not provided. Return an error 

3910 self._setup_u2u() 

3911 Context.U2U = True 

3912 now_time = datetime.utcnow().replace(microsecond=0, tzinfo=timezone.utc) 

3913 err = KRB_GSSAPI_Token( 

3914 innerToken=KRB_InnerToken( 

3915 TOK_ID=b"\x03\x00", 

3916 root=KRB_ERROR( 

3917 errorCode="KRB_AP_ERR_USER_TO_USER_REQUIRED", 

3918 stime=ASN1_GENERALIZED_TIME(now_time), 

3919 realm=ap_req.ticket.realm, 

3920 sname=ap_req.ticket.sname, 

3921 eData=KRB_TGT_REP( 

3922 ticket=self.TGT, 

3923 ), 

3924 ), 

3925 ) 

3926 ) 

3927 return Context, err, GSS_S_CONTINUE_NEEDED 

3928 # Decrypt the ticket 

3929 try: 

3930 tkt = ap_req.ticket.encPart.decrypt(self.KEY) 

3931 except ValueError as ex: 

3932 warning("KerberosSSP: %s (bad KEY?)" % ex) 

3933 now_time = datetime.utcnow().replace(microsecond=0, tzinfo=timezone.utc) 

3934 err = KRB_GSSAPI_Token( 

3935 innerToken=KRB_InnerToken( 

3936 TOK_ID=b"\x03\x00", 

3937 root=KRB_ERROR( 

3938 errorCode="KRB_AP_ERR_MODIFIED", 

3939 stime=ASN1_GENERALIZED_TIME(now_time), 

3940 realm=ap_req.ticket.realm, 

3941 sname=ap_req.ticket.sname, 

3942 eData=None, 

3943 ), 

3944 ) 

3945 ) 

3946 return Context, err, GSS_S_DEFECTIVE_TOKEN 

3947 # Get AP-REP session key 

3948 Context.STSessionKey = tkt.key.toKey() 

3949 authenticator = ap_req.authenticator.decrypt(Context.STSessionKey) 

3950 # Compute an application session key ([MS-KILE] sect 3.1.1.2) 

3951 subkey = None 

3952 if ap_req.apOptions.val[2] == "1": # mutual-required 

3953 appkey = Key.random_to_key( 

3954 self.SKEY_TYPE, 

3955 os.urandom(16), 

3956 ) 

3957 Context.KrbSessionKey = appkey 

3958 Context.SessionKey = appkey.key 

3959 subkey = EncryptionKey.fromKey(appkey) 

3960 else: 

3961 Context.KrbSessionKey = self.KEY 

3962 Context.SessionKey = self.KEY.key 

3963 # Eventually process the "checksum" 

3964 if authenticator.cksum: 

3965 if authenticator.cksum.cksumtype == 0x8003: 

3966 # KRB-Authenticator 

3967 Context.flags = GSS_C_FLAGS(int(authenticator.cksum.checksum.Flags)) 

3968 # Build response (RFC4120 sect 3.2.4) 

3969 ap_rep = KRB_AP_REP(encPart=EncryptedData()) 

3970 ap_rep.encPart.encrypt( 

3971 Context.STSessionKey, 

3972 EncAPRepPart( 

3973 ctime=authenticator.ctime, 

3974 cusec=authenticator.cusec, 

3975 seqNumber=None, 

3976 subkey=subkey, 

3977 ), 

3978 ) 

3979 Context.state = self.STATE.SRV_SENT_APREP 

3980 if Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE: 

3981 # [MS-KILE] sect 3.4.5.1 

3982 return Context, ap_rep, GSS_S_CONTINUE_NEEDED 

3983 return Context, ap_rep, GSS_S_COMPLETE # success 

3984 elif ( 

3985 Context.state == self.STATE.SRV_SENT_APREP 

3986 and Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE 

3987 ): 

3988 # [MS-KILE] sect 3.4.5.1 

3989 # The server MUST receive the additional AP exchange reply message and 

3990 # verify that the message is constructed correctly. 

3991 if not val: 

3992 return Context, None, GSS_S_DEFECTIVE_TOKEN 

3993 # Server receives AP-req, sends AP-rep 

3994 if isinstance(val, KRB_AP_REP): 

3995 # Raw AP_REP was passed 

3996 ap_rep = val 

3997 else: 

3998 try: 

3999 # GSSAPI/Kerberos 

4000 ap_rep = val.root.innerToken.root 

4001 except AttributeError: 

4002 try: 

4003 # Raw Kerberos 

4004 ap_rep = val.root 

4005 except AttributeError: 

4006 return Context, None, GSS_S_DEFECTIVE_TOKEN 

4007 # Decrypt the AP-REP 

4008 try: 

4009 ap_rep.encPart.decrypt(Context.STSessionKey) 

4010 except ValueError as ex: 

4011 warning("KerberosSSP: %s (bad KEY?)" % ex) 

4012 return Context, None, GSS_S_DEFECTIVE_TOKEN 

4013 return Context, None, GSS_S_COMPLETE # success 

4014 else: 

4015 raise ValueError("KerberosSSP: Unknown state %s" % repr(Context.state)) 

4016 

4017 def GSS_Passive(self, Context: CONTEXT, val=None): 

4018 if Context is None: 

4019 Context = self.CONTEXT(True) 

4020 Context.passive = True 

4021 

4022 if Context.state == self.STATE.INIT: 

4023 Context, _, status = self.GSS_Accept_sec_context(Context, val) 

4024 Context.state = self.STATE.CLI_SENT_APREQ 

4025 return Context, status 

4026 elif Context.state == self.STATE.CLI_SENT_APREQ: 

4027 Context, _, status = self.GSS_Init_sec_context(Context, val) 

4028 return Context, status 

4029 

4030 def GSS_Passive_set_Direction(self, Context: CONTEXT, IsAcceptor=False): 

4031 if Context.IsAcceptor is not IsAcceptor: 

4032 return 

4033 # Swap everything 

4034 Context.SendSealKeyUsage, Context.RecvSealKeyUsage = ( 

4035 Context.RecvSealKeyUsage, 

4036 Context.SendSealKeyUsage, 

4037 ) 

4038 Context.SendSignKeyUsage, Context.RecvSignKeyUsage = ( 

4039 Context.RecvSignKeyUsage, 

4040 Context.SendSignKeyUsage, 

4041 ) 

4042 Context.IsAcceptor = not Context.IsAcceptor 

4043 

4044 def MaximumSignatureLength(self, Context: CONTEXT): 

4045 if Context.flags & GSS_C_FLAGS.GSS_C_CONF_FLAG: 

4046 # TODO: support DES 

4047 if Context.KrbSessionKey.etype in [17, 18]: # AES 

4048 return 76 

4049 elif Context.KrbSessionKey.etype in [23, 24]: # RC4_HMAC 

4050 return 45 

4051 else: 

4052 raise NotImplementedError 

4053 else: 

4054 return 28 

4055 

4056 def canMechListMIC(self, Context: CONTEXT): 

4057 return bool(Context.KrbSessionKey)