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_STRING_PacketField, 83 ASN1F_enum_INTEGER, 84 ASN1F_optional, 85) 86from scapy.asn1packet import ASN1_Packet 87from scapy.automaton import Automaton, ATMT 88from scapy.config import conf 89from scapy.compat import bytes_encode 90from scapy.error import log_runtime 91from scapy.fields import ( 92 ConditionalField, 93 FieldLenField, 94 FlagsField, 95 IntEnumField, 96 LEIntEnumField, 97 LenField, 98 LEShortEnumField, 99 LEShortField, 100 LongField, 101 MultipleTypeField, 102 PacketField, 103 PacketLenField, 104 PacketListField, 105 PadField, 106 ShortEnumField, 107 ShortField, 108 StrField, 109 StrFieldUtf16, 110 StrFixedLenEnumField, 111 XByteField, 112 XLEIntField, 113 XLEShortField, 114 XStrFixedLenField, 115 XStrLenField, 116 XStrField, 117) 118from scapy.packet import Packet, bind_bottom_up, bind_top_down, bind_layers 119from scapy.supersocket import StreamSocket 120from scapy.utils import strrot, strxor 121from scapy.volatile import GeneralizedTime, RandNum, RandBin 122 123from scapy.layers.gssapi import ( 124 GSSAPI_BLOB, 125 GSS_C_FLAGS, 126 GSS_S_BAD_MECH, 127 GSS_S_COMPLETE, 128 GSS_S_CONTINUE_NEEDED, 129 GSS_S_DEFECTIVE_TOKEN, 130 GSS_S_FAILURE, 131 GssChannelBindings, 132 SSP, 133 _GSSAPI_OIDS, 134 _GSSAPI_SIGNATURE_OIDS, 135) 136from scapy.layers.inet import TCP, UDP 137 138# Typing imports 139from typing import ( 140 Optional, 141) 142 143 144# kerberos APPLICATION 145 146 147class ASN1_Class_KRB(ASN1_Class): 148 name = "Kerberos" 149 # APPLICATION + CONSTRUCTED = 0x40 | 0x20 150 Token = 0x60 | 0 # GSSAPI 151 Ticket = 0x60 | 1 152 Authenticator = 0x60 | 2 153 EncTicketPart = 0x60 | 3 154 AS_REQ = 0x60 | 10 155 AS_REP = 0x60 | 11 156 TGS_REQ = 0x60 | 12 157 TGS_REP = 0x60 | 13 158 AP_REQ = 0x60 | 14 159 AP_REP = 0x60 | 15 160 PRIV = 0x60 | 21 161 CRED = 0x60 | 22 162 EncASRepPart = 0x60 | 25 163 EncTGSRepPart = 0x60 | 26 164 EncAPRepPart = 0x60 | 27 165 EncKrbPrivPart = 0x60 | 28 166 EncKrbCredPart = 0x60 | 29 167 ERROR = 0x60 | 30 168 169 170# RFC4120 sect 5.2 171 172 173KerberosString = ASN1F_GENERAL_STRING 174Realm = KerberosString 175Int32 = ASN1F_INTEGER 176UInt32 = ASN1F_INTEGER 177 178_PRINCIPAL_NAME_TYPES = { 179 0: "NT-UNKNOWN", 180 1: "NT-PRINCIPAL", 181 2: "NT-SRV-INST", 182 3: "NT-SRV-HST", 183 4: "NT-SRV-XHST", 184 5: "NT-UID", 185 6: "NT-X500-PRINCIPAL", 186 7: "NT-SMTP-NAME", 187 10: "NT-ENTERPRISE", 188} 189 190 191class PrincipalName(ASN1_Packet): 192 ASN1_codec = ASN1_Codecs.BER 193 ASN1_root = ASN1F_SEQUENCE( 194 ASN1F_enum_INTEGER( 195 "nameType", 196 0, 197 _PRINCIPAL_NAME_TYPES, 198 explicit_tag=0xA0, 199 ), 200 ASN1F_SEQUENCE_OF("nameString", [], KerberosString, explicit_tag=0xA1), 201 ) 202 203 @staticmethod 204 def fromUPN(upn: str): 205 user, _ = _parse_upn(upn) 206 return PrincipalName( 207 nameString=[ASN1_GENERAL_STRING(user)], 208 nameType=ASN1_INTEGER(1), # NT-PRINCIPAL 209 ) 210 211 @staticmethod 212 def fromSPN(spn: bytes): 213 spn, _ = _parse_spn(spn) 214 if spn.startswith("krbtgt"): 215 return PrincipalName( 216 nameString=[ASN1_GENERAL_STRING(x) for x in spn.split("/")], 217 nameType=ASN1_INTEGER(2), # NT-SRV-INST 218 ) 219 else: 220 return PrincipalName( 221 nameString=[ASN1_GENERAL_STRING(x) for x in spn.split("/")], 222 nameType=ASN1_INTEGER(3), # NT-SRV-HST 223 ) 224 225 226KerberosTime = ASN1F_GENERALIZED_TIME 227Microseconds = ASN1F_INTEGER 228 229 230# https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml#kerberos-parameters-1 231 232_KRB_E_TYPES = { 233 1: "DES-CBC-CRC", 234 2: "DES-CBC-MD4", 235 3: "DES-CBC-MD5", 236 5: "DES3-CBC-MD5", 237 7: "DES3-CBC-SHA1", 238 9: "DSAWITHSHA1-CMSOID", 239 10: "MD5WITHRSAENCRYPTION-CMSOID", 240 11: "SHA1WITHRSAENCRYPTION-CMSOID", 241 12: "RC2CBC-ENVOID", 242 13: "RSAENCRYPTION-ENVOID", 243 14: "RSAES-OAEP-ENV-OID", 244 15: "DES-EDE3-CBC-ENV-OID", 245 16: "DES3-CBC-SHA1-KD", 246 17: "AES128-CTS-HMAC-SHA1-96", 247 18: "AES256-CTS-HMAC-SHA1-96", 248 19: "AES128-CTS-HMAC-SHA256-128", 249 20: "AES256-CTS-HMAC-SHA384-192", 250 23: "RC4-HMAC", 251 24: "RC4-HMAC-EXP", 252 25: "CAMELLIA128-CTS-CMAC", 253 26: "CAMELLIA256-CTS-CMAC", 254} 255 256# https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml#kerberos-parameters-2 257 258_KRB_S_TYPES = { 259 1: "CRC32", 260 2: "RSA-MD4", 261 3: "RSA-MD4-DES", 262 4: "DES-MAC", 263 5: "DES-MAC-K", 264 6: "RSA-MD4-DES-K", 265 7: "RSA-MD5", 266 8: "RSA-MD5-DES", 267 9: "RSA-MD5-DES3", 268 10: "SHA1", 269 12: "HMAC-SHA1-DES3-KD", 270 13: "HMAC-SHA1-DES3", 271 14: "SHA1", 272 15: "HMAC-SHA1-96-AES128", 273 16: "HMAC-SHA1-96-AES256", 274 17: "CMAC-CAMELLIA128", 275 18: "CMAC-CAMELLIA256", 276 19: "HMAC-SHA256-128-AES128", 277 20: "HMAC-SHA384-192-AES256", 278 # RFC 4121 279 0x8003: "KRB-AUTHENTICATOR", 280 # [MS-KILE] 281 0xFFFFFF76: "MD5", 282} 283 284 285class EncryptedData(ASN1_Packet): 286 ASN1_codec = ASN1_Codecs.BER 287 ASN1_root = ASN1F_SEQUENCE( 288 ASN1F_enum_INTEGER("etype", 0x17, _KRB_E_TYPES, explicit_tag=0xA0), 289 ASN1F_optional(UInt32("kvno", None, explicit_tag=0xA1)), 290 ASN1F_STRING("cipher", "", explicit_tag=0xA2), 291 ) 292 293 def get_usage(self): 294 """ 295 Get current key usage number and encrypted class 296 """ 297 # RFC 4120 sect 7.5.1 298 if self.underlayer: 299 if isinstance(self.underlayer, PADATA): 300 patype = self.underlayer.padataType 301 if patype == 2: 302 # AS-REQ PA-ENC-TIMESTAMP padata timestamp 303 return 1, PA_ENC_TS_ENC 304 elif isinstance(self.underlayer, KRB_Ticket): 305 # AS-REP Ticket and TGS-REP Ticket 306 return 2, EncTicketPart 307 elif isinstance(self.underlayer, KRB_AS_REP): 308 # AS-REP encrypted part 309 return 3, EncASRepPart 310 elif isinstance(self.underlayer, KRB_AP_REQ) and isinstance( 311 self.underlayer.underlayer, PADATA 312 ): 313 # TGS-REQ PA-TGS-REQ Authenticator 314 return 7, KRB_Authenticator 315 elif isinstance(self.underlayer, KRB_TGS_REP): 316 # TGS-REP encrypted part 317 return 8, EncTGSRepPart 318 elif isinstance(self.underlayer, KRB_AP_REQ): 319 # AP-REQ Authenticator 320 return 11, KRB_Authenticator 321 elif isinstance(self.underlayer, KRB_AP_REP): 322 # AP-REP encrypted part 323 return 12, EncAPRepPart 324 elif isinstance(self.underlayer, KRB_PRIV): 325 # KRB-PRIV encrypted part 326 return 13, EncKrbPrivPart 327 elif isinstance(self.underlayer, KRB_CRED): 328 # KRB-CRED encrypted part 329 return 14, EncKrbCredPart 330 elif isinstance(self.underlayer, KrbFastArmoredReq): 331 # KEY_USAGE_FAST_ENC 332 return 51, KrbFastReq 333 raise ValueError( 334 "Could not guess key usage number. Please specify key_usage_number" 335 ) 336 337 def decrypt(self, key, key_usage_number=None, cls=None): 338 """ 339 Decrypt and return the data contained in cipher. 340 341 :param key: the key to use for decryption 342 :param key_usage_number: (optional) specify the key usage number. 343 Guessed otherwise 344 :param cls: (optional) the class of the decrypted payload 345 Guessed otherwise (or bytes) 346 """ 347 if key_usage_number is None: 348 key_usage_number, cls = self.get_usage() 349 d = key.decrypt(key_usage_number, self.cipher.val) 350 if cls: 351 try: 352 return cls(d) 353 except BER_Decoding_Error: 354 if cls == EncASRepPart: 355 # https://datatracker.ietf.org/doc/html/rfc4120#section-5.4.2 356 # "Compatibility note: Some implementations unconditionally send an 357 # encrypted EncTGSRepPart (application tag number 26) in this field 358 # regardless of whether the reply is a AS-REP or a TGS-REP. In the 359 # interest of compatibility, implementors MAY relax the check on the 360 # tag number of the decrypted ENC-PART." 361 try: 362 res = EncTGSRepPart(d) 363 # https://github.com/krb5/krb5/blob/48ccd81656381522d1f9ccb8705c13f0266a46ab/src/lib/krb5/asn.1/asn1_k_encode.c#L1128 364 # This is a bug because as the RFC clearly says above, we're 365 # perfectly in our right to be strict on this. (MAY) 366 log_runtime.warning( 367 "Implementation bug detected. This looks like MIT Kerberos." 368 ) 369 return res 370 except BER_Decoding_Error: 371 pass 372 raise 373 return d 374 375 def encrypt(self, key, text, confounder=None, key_usage_number=None): 376 """ 377 Encrypt text and set it into cipher. 378 379 :param key: the key to use for encryption 380 :param text: the bytes value to encode 381 :param confounder: (optional) specify the confounder bytes. Random otherwise 382 :param key_usage_number: (optional) specify the key usage number. 383 Guessed otherwise 384 """ 385 if key_usage_number is None: 386 key_usage_number = self.get_usage()[0] 387 self.etype = key.etype 388 self.cipher = ASN1_STRING( 389 key.encrypt(key_usage_number, text, confounder=confounder) 390 ) 391 392 393class EncryptionKey(ASN1_Packet): 394 ASN1_codec = ASN1_Codecs.BER 395 ASN1_root = ASN1F_SEQUENCE( 396 ASN1F_enum_INTEGER("keytype", 0, _KRB_E_TYPES, explicit_tag=0xA0), 397 ASN1F_STRING("keyvalue", "", explicit_tag=0xA1), 398 ) 399 400 def toKey(self): 401 from scapy.libs.rfc3961 import Key 402 403 return Key( 404 etype=self.keytype.val, 405 key=self.keyvalue.val, 406 ) 407 408 @classmethod 409 def fromKey(self, key): 410 return EncryptionKey( 411 keytype=key.etype, 412 keyvalue=key.key, 413 ) 414 415 416class _Checksum_Field(ASN1F_STRING_PacketField): 417 def m2i(self, pkt, s): 418 val = super(_Checksum_Field, self).m2i(pkt, s) 419 if not val[0].val: 420 return val 421 if pkt.cksumtype.val == 0x8003: 422 # Special case per RFC 4121 423 return KRB_AuthenticatorChecksum(val[0].val, _underlayer=pkt), val[1] 424 return val 425 426 427class Checksum(ASN1_Packet): 428 ASN1_codec = ASN1_Codecs.BER 429 ASN1_root = ASN1F_SEQUENCE( 430 ASN1F_enum_INTEGER( 431 "cksumtype", 432 0, 433 _KRB_S_TYPES, 434 explicit_tag=0xA0, 435 ), 436 _Checksum_Field("checksum", "", explicit_tag=0xA1), 437 ) 438 439 def get_usage(self): 440 """ 441 Get current key usage number 442 """ 443 # RFC 4120 sect 7.5.1 444 if self.underlayer: 445 if isinstance(self.underlayer, KRB_Authenticator): 446 # TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator cksum 447 # (n°10 should never happen as we use RFC4121) 448 return 6 449 elif isinstance(self.underlayer, PA_FOR_USER): 450 # [MS-SFU] sect 2.2.1 451 return 17 452 elif isinstance(self.underlayer, PA_S4U_X509_USER): 453 # [MS-SFU] sect 2.2.1 454 return 17 455 elif isinstance(self.underlayer, AD_KDCIssued): 456 # AD-KDC-ISSUED checksum 457 return 19 458 elif isinstance(self.underlayer, KrbFastArmoredReq): 459 # KEY_USAGE_FAST_REQ_CHKSUM 460 return 50 461 raise ValueError( 462 "Could not guess key usage number. Please specify key_usage_number" 463 ) 464 465 def verify(self, key, text, key_usage_number=None): 466 """ 467 Decrypt and return the data contained in cipher. 468 469 :param key: the key to use to check the checksum 470 :param text: the bytes to verify 471 :param key_usage_number: (optional) specify the key usage number. 472 Guessed otherwise 473 """ 474 if key_usage_number is None: 475 key_usage_number = self.get_usage() 476 key.verify_checksum(key_usage_number, text, self.checksum.val) 477 478 def make(self, key, text, key_usage_number=None, cksumtype=None): 479 """ 480 Encrypt text and set it into cipher. 481 482 :param key: the key to use to make the checksum 483 :param text: the bytes to make a checksum of 484 :param key_usage_number: (optional) specify the key usage number. 485 Guessed otherwise 486 """ 487 if key_usage_number is None: 488 key_usage_number = self.get_usage() 489 self.cksumtype = cksumtype or key.cksumtype 490 self.checksum = ASN1_STRING( 491 key.make_checksum( 492 keyusage=key_usage_number, 493 text=text, 494 cksumtype=self.cksumtype, 495 ) 496 ) 497 498 499KerberosFlags = ASN1F_FLAGS 500 501_ADDR_TYPES = { 502 # RFC4120 sect 7.5.3 503 0x02: "IPv4", 504 0x03: "Directional", 505 0x05: "ChaosNet", 506 0x06: "XNS", 507 0x07: "ISO", 508 0x0C: "DECNET Phase IV", 509 0x10: "AppleTalk DDP", 510 0x14: "NetBios", 511 0x18: "IPv6", 512} 513 514 515class HostAddress(ASN1_Packet): 516 ASN1_codec = ASN1_Codecs.BER 517 ASN1_root = ASN1F_SEQUENCE( 518 ASN1F_enum_INTEGER( 519 "addrType", 520 0, 521 _ADDR_TYPES, 522 explicit_tag=0xA0, 523 ), 524 ASN1F_STRING("address", "", explicit_tag=0xA1), 525 ) 526 527 528HostAddresses = lambda name, **kwargs: ASN1F_SEQUENCE_OF( 529 name, [], HostAddress, **kwargs 530) 531 532 533_AUTHORIZATIONDATA_VALUES = { 534 # Filled below 535} 536 537 538class _AuthorizationData_value_Field(ASN1F_STRING_PacketField): 539 def m2i(self, pkt, s): 540 val = super(_AuthorizationData_value_Field, self).m2i(pkt, s) 541 if not val[0].val: 542 return val 543 if pkt.adType.val in _AUTHORIZATIONDATA_VALUES: 544 return ( 545 _AUTHORIZATIONDATA_VALUES[pkt.adType.val](val[0].val, _underlayer=pkt), 546 val[1], 547 ) 548 return val 549 550 551_AD_TYPES = { 552 # RFC4120 sect 7.5.4 553 1: "AD-IF-RELEVANT", 554 2: "AD-INTENDED-FOR-SERVER", 555 3: "AD-INTENDED-FOR-APPLICATION-CLASS", 556 4: "AD-KDC-ISSUED", 557 5: "AD-AND-OR", 558 6: "AD-MANDATORY-TICKET-EXTENSIONS", 559 7: "AD-IN-TICKET-EXTENSIONS", 560 8: "AD-MANDATORY-FOR-KDC", 561 64: "OSF-DCE", 562 65: "SESAME", 563 66: "AD-OSD-DCE-PKI-CERTID", 564 128: "AD-WIN2K-PAC", 565 129: "AD-ETYPE-NEGOTIATION", 566 # [MS-KILE] additions 567 141: "KERB-AUTH-DATA-TOKEN-RESTRICTIONS", 568 142: "KERB-LOCAL", 569 143: "AD-AUTH-DATA-AP-OPTIONS", 570 144: "KERB-AUTH-DATA-CLIENT-TARGET", 571} 572 573 574class AuthorizationDataItem(ASN1_Packet): 575 ASN1_codec = ASN1_Codecs.BER 576 ASN1_root = ASN1F_SEQUENCE( 577 ASN1F_enum_INTEGER( 578 "adType", 579 0, 580 _AD_TYPES, 581 explicit_tag=0xA0, 582 ), 583 _AuthorizationData_value_Field("adData", "", explicit_tag=0xA1), 584 ) 585 586 587class AuthorizationData(ASN1_Packet): 588 ASN1_codec = ASN1_Codecs.BER 589 ASN1_root = ASN1F_SEQUENCE_OF( 590 "seq", [AuthorizationDataItem()], AuthorizationDataItem 591 ) 592 593 594AD_IF_RELEVANT = AuthorizationData 595_AUTHORIZATIONDATA_VALUES[1] = AD_IF_RELEVANT 596 597 598class AD_KDCIssued(ASN1_Packet): 599 ASN1_codec = ASN1_Codecs.BER 600 ASN1_root = ASN1F_SEQUENCE( 601 ASN1F_PACKET("adChecksum", Checksum(), Checksum, explicit_tag=0xA0), 602 ASN1F_optional( 603 Realm("iRealm", "", explicit_tag=0xA1), 604 ), 605 ASN1F_optional(ASN1F_PACKET("iSname", None, PrincipalName, explicit_tag=0xA2)), 606 ASN1F_PACKET("elements", None, AuthorizationData, explicit_tag=0xA3), 607 ) 608 609 610_AUTHORIZATIONDATA_VALUES[4] = AD_KDCIssued 611 612 613class AD_AND_OR(ASN1_Packet): 614 ASN1_codec = ASN1_Codecs.BER 615 ASN1_root = ASN1F_SEQUENCE( 616 Int32("conditionCount", 0, explicit_tag=0xA0), 617 ASN1F_PACKET("elements", None, AuthorizationData, explicit_tag=0xA1), 618 ) 619 620 621_AUTHORIZATIONDATA_VALUES[5] = AD_AND_OR 622 623ADMANDATORYFORKDC = AuthorizationData 624_AUTHORIZATIONDATA_VALUES[8] = ADMANDATORYFORKDC 625 626 627# https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xml 628_PADATA_TYPES = { 629 1: "PA-TGS-REQ", 630 2: "PA-ENC-TIMESTAMP", 631 3: "PA-PW-SALT", 632 11: "PA-ETYPE-INFO", 633 14: "PA-PK-AS-REQ-OLD", 634 15: "PA-PK-AS-REP-OLD", 635 16: "PA-PK-AS-REQ", 636 17: "PA-PK-AS-REP", 637 19: "PA-ETYPE-INFO2", 638 20: "PA-SVR-REFERRAL-INFO", 639 128: "PA-PAC-REQUEST", 640 129: "PA-FOR-USER", 641 130: "PA-FOR-X509-USER", 642 131: "PA-FOR-CHECK_DUPS", 643 132: "PA-AS-CHECKSUM", 644 133: "PA-FX-COOKIE", 645 134: "PA-AUTHENTICATION-SET", 646 135: "PA-AUTH-SET-SELECTED", 647 136: "PA-FX-FAST", 648 137: "PA-FX-ERROR", 649 138: "PA-ENCRYPTED-CHALLENGE", 650 141: "PA-OTP-CHALLENGE", 651 142: "PA-OTP-REQUEST", 652 143: "PA-OTP-CONFIRM", 653 144: "PA-OTP-PIN-CHANGE", 654 145: "PA-EPAK-AS-REQ", 655 146: "PA-EPAK-AS-REP", 656 147: "PA-PKINIT-KX", 657 148: "PA-PKU2U-NAME", 658 149: "PA-REQ-ENC-PA-REP", 659 150: "PA-AS-FRESHNESS", 660 151: "PA-SPAKE", 661 161: "KERB-KEY-LIST-REQ", 662 162: "KERB-KEY-LIST-REP", 663 165: "PA-SUPPORTED-ENCTYPES", 664 166: "PA-EXTENDED-ERROR", 665 167: "PA-PAC-OPTIONS", 666} 667 668_PADATA_CLASSES = { 669 # Filled elsewhere in this file 670} 671 672 673# RFC4120 674 675 676class _PADATA_value_Field(ASN1F_STRING_PacketField): 677 """ 678 A special field that properly dispatches PA-DATA values according to 679 padata-type and if the paquet is a request or a response. 680 """ 681 682 def m2i(self, pkt, s): 683 val = super(_PADATA_value_Field, self).m2i(pkt, s) 684 if pkt.padataType.val in _PADATA_CLASSES: 685 cls = _PADATA_CLASSES[pkt.padataType.val] 686 if isinstance(cls, tuple): 687 is_reply = ( 688 pkt.underlayer.underlayer is not None 689 and isinstance(pkt.underlayer.underlayer, KRB_ERROR) 690 ) or isinstance(pkt.underlayer, (KRB_AS_REP, KRB_TGS_REP)) 691 cls = cls[is_reply] 692 if not val[0].val: 693 return val 694 return cls(val[0].val, _underlayer=pkt), val[1] 695 return val 696 697 698class PADATA(ASN1_Packet): 699 ASN1_codec = ASN1_Codecs.BER 700 ASN1_root = ASN1F_SEQUENCE( 701 ASN1F_enum_INTEGER("padataType", 0, _PADATA_TYPES, explicit_tag=0xA1), 702 _PADATA_value_Field( 703 "padataValue", 704 "", 705 explicit_tag=0xA2, 706 ), 707 ) 708 709 710# RFC 4120 sect 5.2.7.2 711 712 713class PA_ENC_TS_ENC(ASN1_Packet): 714 ASN1_codec = ASN1_Codecs.BER 715 ASN1_root = ASN1F_SEQUENCE( 716 KerberosTime("patimestamp", GeneralizedTime(), explicit_tag=0xA0), 717 ASN1F_optional(Microseconds("pausec", 0, explicit_tag=0xA1)), 718 ) 719 720 721_PADATA_CLASSES[2] = EncryptedData 722 723 724# RFC 4120 sect 5.2.7.4 725 726 727class ETYPE_INFO_ENTRY(ASN1_Packet): 728 ASN1_codec = ASN1_Codecs.BER 729 ASN1_root = ASN1F_SEQUENCE( 730 ASN1F_enum_INTEGER("etype", 0x1, _KRB_E_TYPES, explicit_tag=0xA0), 731 ASN1F_optional( 732 ASN1F_STRING("salt", "", explicit_tag=0xA1), 733 ), 734 ) 735 736 737class ETYPE_INFO(ASN1_Packet): 738 ASN1_codec = ASN1_Codecs.BER 739 ASN1_root = ASN1F_SEQUENCE_OF("seq", [ETYPE_INFO_ENTRY()], ETYPE_INFO_ENTRY) 740 741 742_PADATA_CLASSES[11] = ETYPE_INFO 743 744# RFC 4120 sect 5.2.7.5 745 746 747class ETYPE_INFO_ENTRY2(ASN1_Packet): 748 ASN1_codec = ASN1_Codecs.BER 749 ASN1_root = ASN1F_SEQUENCE( 750 ASN1F_enum_INTEGER("etype", 0x1, _KRB_E_TYPES, explicit_tag=0xA0), 751 ASN1F_optional( 752 KerberosString("salt", "", explicit_tag=0xA1), 753 ), 754 ASN1F_optional( 755 ASN1F_STRING("s2kparams", "", explicit_tag=0xA2), 756 ), 757 ) 758 759 760class ETYPE_INFO2(ASN1_Packet): 761 ASN1_codec = ASN1_Codecs.BER 762 ASN1_root = ASN1F_SEQUENCE_OF("seq", [ETYPE_INFO_ENTRY2()], ETYPE_INFO_ENTRY2) 763 764 765_PADATA_CLASSES[19] = ETYPE_INFO2 766 767# PADATA Extended with RFC6113 768 769 770class PA_AUTHENTICATION_SET_ELEM(ASN1_Packet): 771 ASN1_codec = ASN1_Codecs.BER 772 ASN1_root = ASN1F_SEQUENCE( 773 Int32("paType", 0, explicit_tag=0xA0), 774 ASN1F_optional( 775 ASN1F_STRING("paHint", "", explicit_tag=0xA1), 776 ), 777 ASN1F_optional( 778 ASN1F_STRING("paValue", "", explicit_tag=0xA2), 779 ), 780 ) 781 782 783class PA_AUTHENTICATION_SET(ASN1_Packet): 784 ASN1_codec = ASN1_Codecs.BER 785 ASN1_root = ASN1F_SEQUENCE_OF( 786 "elems", [PA_AUTHENTICATION_SET_ELEM()], PA_AUTHENTICATION_SET_ELEM 787 ) 788 789 790_PADATA_CLASSES[134] = PA_AUTHENTICATION_SET 791 792 793# [MS-KILE] sect 2.2.3 794 795 796class PA_PAC_REQUEST(ASN1_Packet): 797 ASN1_codec = ASN1_Codecs.BER 798 ASN1_root = ASN1F_SEQUENCE( 799 ASN1F_BOOLEAN("includePac", True, explicit_tag=0xA0), 800 ) 801 802 803_PADATA_CLASSES[128] = PA_PAC_REQUEST 804 805 806# [MS-KILE] sect 2.2.5 807 808 809class LSAP_TOKEN_INFO_INTEGRITY(Packet): 810 fields_desc = [ 811 FlagsField( 812 "Flags", 813 0, 814 -32, 815 { 816 0x00000001: "UAC-Restricted", 817 }, 818 ), 819 LEIntEnumField( 820 "TokenIL", 821 0x00002000, 822 { 823 0x00000000: "Untrusted", 824 0x00001000: "Low", 825 0x00002000: "Medium", 826 0x00003000: "High", 827 0x00004000: "System", 828 0x00005000: "Protected process", 829 }, 830 ), 831 XStrFixedLenField("MachineID", b"", length=32), 832 ] 833 834 835# [MS-KILE] sect 2.2.6 836 837 838class _KerbAdRestrictionEntry_Field(ASN1F_STRING_PacketField): 839 def m2i(self, pkt, s): 840 val = super(_KerbAdRestrictionEntry_Field, self).m2i(pkt, s) 841 if not val[0].val: 842 return val 843 if pkt.restrictionType.val == 0x0000: # LSAP_TOKEN_INFO_INTEGRITY 844 return LSAP_TOKEN_INFO_INTEGRITY(val[0].val, _underlayer=pkt), val[1] 845 return val 846 847 848class KERB_AD_RESTRICTION_ENTRY(ASN1_Packet): 849 name = "KERB-AD-RESTRICTION-ENTRY" 850 ASN1_codec = ASN1_Codecs.BER 851 ASN1_root = ASN1F_SEQUENCE( 852 ASN1F_SEQUENCE( 853 ASN1F_enum_INTEGER( 854 "restrictionType", 855 0, 856 {0: "LSAP_TOKEN_INFO_INTEGRITY"}, 857 explicit_tag=0xA0, 858 ), 859 _KerbAdRestrictionEntry_Field("restriction", b"", explicit_tag=0xA1), 860 ) 861 ) 862 863 864_AUTHORIZATIONDATA_VALUES[141] = KERB_AD_RESTRICTION_ENTRY 865 866 867# [MS-KILE] sect 3.2.5.8 868 869 870class KERB_AUTH_DATA_AP_OPTIONS(Packet): 871 name = "KERB-AUTH-DATA-AP-OPTIONS" 872 fields_desc = [ 873 LEIntEnumField( 874 "apOptions", 875 0x4000, 876 { 877 0x4000: "KERB_AP_OPTIONS_CBT", 878 0x8000: "KERB_AP_OPTIONS_UNVERIFIED_TARGET_NAME", 879 }, 880 ), 881 ] 882 883 884_AUTHORIZATIONDATA_VALUES[143] = KERB_AUTH_DATA_AP_OPTIONS 885 886 887# This has no doc..? [MS-KILE] only mentions its name. 888 889 890class KERB_AUTH_DATA_CLIENT_TARGET(Packet): 891 name = "KERB-AD-TARGET-PRINCIPAL" 892 fields_desc = [ 893 StrFieldUtf16("spn", ""), 894 ] 895 896 897_AUTHORIZATIONDATA_VALUES[144] = KERB_AUTH_DATA_CLIENT_TARGET 898 899 900# RFC6806 sect 6 901 902 903class KERB_AD_LOGIN_ALIAS(ASN1_Packet): 904 ASN1_codec = ASN1_Codecs.BER 905 ASN1_root = ASN1F_SEQUENCE(ASN1F_SEQUENCE_OF("loginAliases", [], PrincipalName)) 906 907 908_AUTHORIZATIONDATA_VALUES[80] = KERB_AD_LOGIN_ALIAS 909 910 911# [MS-KILE] sect 2.2.8 912 913 914class PA_SUPPORTED_ENCTYPES(Packet): 915 fields_desc = [ 916 FlagsField( 917 "flags", 918 0, 919 -32, 920 [ 921 "DES-CBC-CRC", 922 "DES-CBC-MD5", 923 "RC4-HMAC", 924 "AES128-CTS-HMAC-SHA1-96", 925 "AES256-CTS-HMAC-SHA1-96", 926 ] 927 + ["bit_%d" % i for i in range(11)] 928 + [ 929 "FAST-supported", 930 "Compount-identity-supported", 931 "Claims-supported", 932 "Resource-SID-compression-disabled", 933 ], 934 ) 935 ] 936 937 938_PADATA_CLASSES[165] = PA_SUPPORTED_ENCTYPES 939 940# [MS-KILE] sect 2.2.10 941 942 943class PA_PAC_OPTIONS(ASN1_Packet): 944 ASN1_codec = ASN1_Codecs.BER 945 ASN1_root = ASN1F_SEQUENCE( 946 KerberosFlags( 947 "options", 948 "", 949 [ 950 "Claims", 951 "Branch-Aware", 952 "Forward-to-Full-DC", 953 "Resource-based-constrained-delegation", # [MS-SFU] 2.2.5 954 ], 955 explicit_tag=0xA0, 956 ) 957 ) 958 959 960_PADATA_CLASSES[167] = PA_PAC_OPTIONS 961 962# [MS-KILE] sect 2.2.11 963 964 965class KERB_KEY_LIST_REQ(ASN1_Packet): 966 ASN1_codec = ASN1_Codecs.BER 967 ASN1_root = ASN1F_SEQUENCE_OF( 968 "keytypes", 969 [], 970 ASN1F_enum_INTEGER("", 0, _KRB_E_TYPES), 971 ) 972 973 974_PADATA_CLASSES[161] = KERB_KEY_LIST_REQ 975 976# [MS-KILE] sect 2.2.12 977 978 979class KERB_KEY_LIST_REP(ASN1_Packet): 980 ASN1_codec = ASN1_Codecs.BER 981 ASN1_root = ASN1F_SEQUENCE_OF( 982 "keys", 983 [], 984 ASN1F_PACKET("", None, EncryptionKey), 985 ) 986 987 988_PADATA_CLASSES[162] = KERB_KEY_LIST_REP 989 990# [MS-KILE] sect 2.2.13 991 992 993class KERB_SUPERSEDED_BY_USER(ASN1_Packet): 994 ASN1_codec = ASN1_Codecs.BER 995 ASN1_root = ASN1F_SEQUENCE( 996 ASN1F_PACKET("name", None, PrincipalName, explicit_tag=0xA0), 997 Realm("realm", None, explicit_tag=0xA1), 998 ) 999 1000 1001# [MS-KILE] sect 2.2.14 1002 1003 1004class KERB_DMSA_KEY_PACKAGE(ASN1_Packet): 1005 ASN1_codec = ASN1_Codecs.BER 1006 ASN1_root = ASN1F_SEQUENCE( 1007 ASN1F_SEQUENCE_OF( 1008 "currentKeys", 1009 [], 1010 ASN1F_PACKET("", None, EncryptionKey), 1011 explicit_tag=0xA0, 1012 ), 1013 ASN1F_optional( 1014 ASN1F_SEQUENCE_OF( 1015 "previousKeys", 1016 [], 1017 ASN1F_PACKET("", None, EncryptionKey), 1018 explicit_tag=0xA0, 1019 ), 1020 ), 1021 KerberosTime("expirationInterval", GeneralizedTime(), explicit_tag=0xA2), 1022 KerberosTime("fetchInterval", GeneralizedTime(), explicit_tag=0xA4), 1023 ) 1024 1025 1026# RFC6113 sect 5.4.1 1027 1028 1029class _KrbFastArmor_value_Field(ASN1F_STRING_PacketField): 1030 def m2i(self, pkt, s): 1031 val = super(_KrbFastArmor_value_Field, self).m2i(pkt, s) 1032 if not val[0].val: 1033 return val 1034 if pkt.armorType.val == 1: # FX_FAST_ARMOR_AP_REQUEST 1035 return KRB_AP_REQ(val[0].val, _underlayer=pkt), val[1] 1036 return val 1037 1038 1039class KrbFastArmor(ASN1_Packet): 1040 ASN1_codec = ASN1_Codecs.BER 1041 ASN1_root = ASN1F_SEQUENCE( 1042 ASN1F_enum_INTEGER( 1043 "armorType", 1, {1: "FX_FAST_ARMOR_AP_REQUEST"}, explicit_tag=0xA0 1044 ), 1045 _KrbFastArmor_value_Field("armorValue", "", explicit_tag=0xA1), 1046 ) 1047 1048 1049# RFC6113 sect 5.4.2 1050 1051 1052class KrbFastArmoredReq(ASN1_Packet): 1053 ASN1_codec = ASN1_Codecs.BER 1054 ASN1_root = ASN1F_SEQUENCE( 1055 ASN1F_SEQUENCE( 1056 ASN1F_optional( 1057 ASN1F_PACKET("armor", KrbFastArmor(), KrbFastArmor, explicit_tag=0xA0) 1058 ), 1059 ASN1F_PACKET("reqChecksum", Checksum(), Checksum, explicit_tag=0xA1), 1060 ASN1F_PACKET("encFastReq", None, EncryptedData, explicit_tag=0xA2), 1061 ) 1062 ) 1063 1064 1065class PA_FX_FAST_REQUEST(ASN1_Packet): 1066 ASN1_codec = ASN1_Codecs.BER 1067 ASN1_root = ASN1F_CHOICE( 1068 "armoredData", 1069 ASN1_STRING(""), 1070 ASN1F_PACKET("req", KrbFastArmoredReq, KrbFastArmoredReq, implicit_tag=0xA0), 1071 ) 1072 1073 1074# RFC6113 sect 5.4.3 1075 1076 1077class KrbFastArmoredRep(ASN1_Packet): 1078 ASN1_codec = ASN1_Codecs.BER 1079 ASN1_root = ASN1F_SEQUENCE( 1080 ASN1F_SEQUENCE( 1081 ASN1F_PACKET("encFastRep", None, EncryptedData, explicit_tag=0xA0), 1082 ) 1083 ) 1084 1085 1086class PA_FX_FAST_REPLY(ASN1_Packet): 1087 ASN1_codec = ASN1_Codecs.BER 1088 ASN1_root = ASN1F_CHOICE( 1089 "armoredData", 1090 ASN1_STRING(""), 1091 ASN1F_PACKET("req", KrbFastArmoredRep, KrbFastArmoredRep, implicit_tag=0xA0), 1092 ) 1093 1094 1095class KrbFastFinished(ASN1_Packet): 1096 ASN1_codec = ASN1_Codecs.BER 1097 ASN1_root = ASN1F_SEQUENCE( 1098 KerberosTime("timestamp", GeneralizedTime(), explicit_tag=0xA0), 1099 Microseconds("usec", 0, explicit_tag=0xA1), 1100 Realm("crealm", "", explicit_tag=0xA2), 1101 ASN1F_PACKET("cname", None, PrincipalName, explicit_tag=0xA3), 1102 ASN1F_PACKET("ticketChecksum", Checksum(), Checksum, explicit_tag=0xA4), 1103 ) 1104 1105 1106class KrbFastResponse(ASN1_Packet): 1107 ASN1_codec = ASN1_Codecs.BER 1108 ASN1_root = ASN1F_SEQUENCE( 1109 ASN1F_SEQUENCE_OF("padata", [PADATA()], PADATA, explicit_tag=0xA0), 1110 ASN1F_optional( 1111 ASN1F_PACKET("stengthenKey", None, EncryptionKey, explicit_tag=0xA1) 1112 ), 1113 ASN1F_optional( 1114 ASN1F_PACKET( 1115 "finished", KrbFastFinished(), KrbFastFinished, explicit_tag=0xA2 1116 ) 1117 ), 1118 UInt32("nonce", 0, explicit_tag=0xA3), 1119 ) 1120 1121 1122_PADATA_CLASSES[136] = (PA_FX_FAST_REQUEST, PA_FX_FAST_REPLY) 1123 1124# RFC 4556 1125 1126 1127# sect 3.2.1 1128 1129 1130class ExternalPrincipalIdentifier(ASN1_Packet): 1131 ASN1_codec = ASN1_Codecs.BER 1132 ASN1_root = ASN1F_SEQUENCE( 1133 ASN1F_optional( 1134 ASN1F_STRING("subjectName", "", implicit_tag=0xA0), 1135 ), 1136 ASN1F_optional( 1137 ASN1F_STRING("issuerAndSerialNumber", "", implicit_tag=0xA1), 1138 ), 1139 ASN1F_optional( 1140 ASN1F_STRING("subjectKeyIdentifier", "", implicit_tag=0xA2), 1141 ), 1142 ) 1143 1144 1145class PA_PK_AS_REQ(ASN1_Packet): 1146 ASN1_codec = ASN1_Codecs.BER 1147 ASN1_root = ASN1F_SEQUENCE( 1148 ASN1F_STRING("signedAuthpack", "", implicit_tag=0xA0), 1149 ASN1F_optional( 1150 ASN1F_SEQUENCE_OF( 1151 "trustedCertifiers", 1152 [ExternalPrincipalIdentifier()], 1153 ExternalPrincipalIdentifier, 1154 explicit_tag=0xA1, 1155 ), 1156 ), 1157 ASN1F_optional( 1158 ASN1F_STRING("kdcPkId", "", implicit_tag=0xA2), 1159 ), 1160 ) 1161 1162 1163_PADATA_CLASSES[16] = PA_PK_AS_REQ 1164 1165# sect 3.2.3 1166 1167 1168class DHRepInfo(ASN1_Packet): 1169 ASN1_codec = ASN1_Codecs.BER 1170 ASN1_root = ASN1F_SEQUENCE( 1171 ASN1F_STRING("dhSignedData", "", implicit_tag=0xA0), 1172 ASN1F_optional( 1173 ASN1F_STRING("serverDHNonce", "", explicit_tag=0xA1), 1174 ), 1175 ) 1176 1177 1178class EncKeyPack(ASN1_Packet): 1179 ASN1_codec = ASN1_Codecs.BER 1180 ASN1_root = ASN1F_STRING("encKeyPack", "") 1181 1182 1183class PA_PK_AS_REP(ASN1_Packet): 1184 ASN1_codec = ASN1_Codecs.BER 1185 ASN1_root = ASN1F_CHOICE( 1186 "rep", 1187 ASN1_STRING(""), 1188 ASN1F_PACKET("dhInfo", DHRepInfo(), DHRepInfo, explicit_tag=0xA0), 1189 ASN1F_PACKET("encKeyPack", EncKeyPack(), EncKeyPack, explicit_tag=0xA1), 1190 ) 1191 1192 1193_PADATA_CLASSES[17] = PA_PK_AS_REP 1194 1195# [MS-SFU] 1196 1197 1198# sect 2.2.1 1199class PA_FOR_USER(ASN1_Packet): 1200 ASN1_codec = ASN1_Codecs.BER 1201 ASN1_root = ASN1F_SEQUENCE( 1202 ASN1F_PACKET("userName", PrincipalName(), PrincipalName, explicit_tag=0xA0), 1203 Realm("userRealm", "", explicit_tag=0xA1), 1204 ASN1F_PACKET("cksum", Checksum(), Checksum, explicit_tag=0xA2), 1205 KerberosString("authPackage", "Kerberos", explicit_tag=0xA3), 1206 ) 1207 1208 1209_PADATA_CLASSES[129] = PA_FOR_USER 1210 1211 1212# sect 2.2.2 1213 1214 1215class S4UUserID(ASN1_Packet): 1216 ASN1_codec = ASN1_Codecs.BER 1217 ASN1_root = ASN1F_SEQUENCE( 1218 UInt32("nonce", 0, explicit_tag=0xA0), 1219 ASN1F_optional( 1220 ASN1F_PACKET("cname", None, PrincipalName, explicit_tag=0xA1), 1221 ), 1222 Realm("crealm", "", explicit_tag=0xA2), 1223 ASN1F_optional( 1224 ASN1F_STRING("subjectCertificate", None, explicit_tag=0xA3), 1225 ), 1226 ASN1F_optional( 1227 ASN1F_FLAGS( 1228 "options", 1229 "", 1230 [ 1231 "reserved", 1232 "KDC_CHECK_LOGON_HOUR_RESTRICTIONS", 1233 "KDC_KEY_USAGE_27", 1234 ], 1235 explicit_tag=0xA4, 1236 ) 1237 ), 1238 ) 1239 1240 1241class PA_S4U_X509_USER(ASN1_Packet): 1242 ASN1_codec = ASN1_Codecs.BER 1243 ASN1_root = ASN1F_SEQUENCE( 1244 ASN1F_PACKET("userId", S4UUserID(), S4UUserID, explicit_tag=0xA0), 1245 ASN1F_PACKET("checksum", Checksum(), Checksum, explicit_tag=0xA1), 1246 ) 1247 1248 1249_PADATA_CLASSES[130] = PA_S4U_X509_USER 1250 1251 1252# Back to RFC4120 1253 1254# sect 5.10 1255KRB_MSG_TYPES = { 1256 1: "Ticket", 1257 2: "Authenticator", 1258 3: "EncTicketPart", 1259 10: "AS-REQ", 1260 11: "AS-REP", 1261 12: "TGS-REQ", 1262 13: "TGS-REP", 1263 14: "AP-REQ", 1264 15: "AP-REP", 1265 16: "KRB-TGT-REQ", # U2U 1266 17: "KRB-TGT-REP", # U2U 1267 20: "KRB-SAFE", 1268 21: "KRB-PRIV", 1269 22: "KRB-CRED", 1270 25: "EncASRepPart", 1271 26: "EncTGSRepPart", 1272 27: "EncAPRepPart", 1273 28: "EncKrbPrivPart", 1274 29: "EnvKrbCredPart", 1275 30: "KRB-ERROR", 1276} 1277 1278# sect 5.3 1279 1280 1281class KRB_Ticket(ASN1_Packet): 1282 ASN1_codec = ASN1_Codecs.BER 1283 ASN1_root = ASN1F_SEQUENCE( 1284 ASN1F_SEQUENCE( 1285 ASN1F_INTEGER("tktVno", 5, explicit_tag=0xA0), 1286 Realm("realm", "", explicit_tag=0xA1), 1287 ASN1F_PACKET("sname", PrincipalName(), PrincipalName, explicit_tag=0xA2), 1288 ASN1F_PACKET("encPart", EncryptedData(), EncryptedData, explicit_tag=0xA3), 1289 ), 1290 implicit_tag=ASN1_Class_KRB.Ticket, 1291 ) 1292 1293 def getSPN(self): 1294 return "%s@%s" % ( 1295 "/".join(x.val.decode() for x in self.sname.nameString), 1296 self.realm.val.decode(), 1297 ) 1298 1299 1300class TransitedEncoding(ASN1_Packet): 1301 ASN1_codec = ASN1_Codecs.BER 1302 ASN1_root = ASN1F_SEQUENCE( 1303 Int32("trType", 0, explicit_tag=0xA0), 1304 ASN1F_STRING("contents", "", explicit_tag=0xA1), 1305 ) 1306 1307 1308_TICKET_FLAGS = [ 1309 "reserved", 1310 "forwardable", 1311 "forwarded", 1312 "proxiable", 1313 "proxy", 1314 "may-postdate", 1315 "postdated", 1316 "invalid", 1317 "renewable", 1318 "initial", 1319 "pre-authent", 1320 "hw-authent", 1321 "transited-since-policy-checked", 1322 "ok-as-delegate", 1323 "unused", 1324 "canonicalize", # RFC6806 1325 "anonymous", # RFC6112 + RFC8129 1326] 1327 1328 1329class EncTicketPart(ASN1_Packet): 1330 ASN1_codec = ASN1_Codecs.BER 1331 ASN1_root = ASN1F_SEQUENCE( 1332 ASN1F_SEQUENCE( 1333 KerberosFlags( 1334 "flags", 1335 "", 1336 _TICKET_FLAGS, 1337 explicit_tag=0xA0, 1338 ), 1339 ASN1F_PACKET("key", EncryptionKey(), EncryptionKey, explicit_tag=0xA1), 1340 Realm("crealm", "", explicit_tag=0xA2), 1341 ASN1F_PACKET("cname", PrincipalName(), PrincipalName, explicit_tag=0xA3), 1342 ASN1F_PACKET( 1343 "transited", TransitedEncoding(), TransitedEncoding, explicit_tag=0xA4 1344 ), 1345 KerberosTime("authtime", GeneralizedTime(), explicit_tag=0xA5), 1346 ASN1F_optional( 1347 KerberosTime("starttime", GeneralizedTime(), explicit_tag=0xA6) 1348 ), 1349 KerberosTime("endtime", GeneralizedTime(), explicit_tag=0xA7), 1350 ASN1F_optional( 1351 KerberosTime("renewTill", GeneralizedTime(), explicit_tag=0xA8), 1352 ), 1353 ASN1F_optional( 1354 HostAddresses("addresses", explicit_tag=0xA9), 1355 ), 1356 ASN1F_optional( 1357 ASN1F_PACKET( 1358 "authorizationData", None, AuthorizationData, explicit_tag=0xAA 1359 ), 1360 ), 1361 ), 1362 implicit_tag=ASN1_Class_KRB.EncTicketPart, 1363 ) 1364 1365 1366# sect 5.4.1 1367 1368 1369class KRB_KDC_REQ_BODY(ASN1_Packet): 1370 ASN1_codec = ASN1_Codecs.BER 1371 ASN1_root = ASN1F_SEQUENCE( 1372 KerberosFlags( 1373 "kdcOptions", 1374 "", 1375 [ 1376 "reserved", 1377 "forwardable", 1378 "forwarded", 1379 "proxiable", 1380 "proxy", 1381 "allow-postdate", 1382 "postdated", 1383 "unused7", 1384 "renewable", 1385 "unused9", 1386 "unused10", 1387 "opt-hardware-auth", 1388 "unused12", 1389 "unused13", 1390 "cname-in-addl-tkt", # [MS-SFU] sect 2.2.3 1391 "canonicalize", # RFC6806 1392 "request-anonymous", # RFC6112 + RFC8129 1393 ] 1394 + ["unused%d" % i for i in range(17, 26)] 1395 + [ 1396 "disable-transited-check", 1397 "renewable-ok", 1398 "enc-tkt-in-skey", 1399 "unused29", 1400 "renew", 1401 "validate", 1402 ], 1403 explicit_tag=0xA0, 1404 ), 1405 ASN1F_optional(ASN1F_PACKET("cname", None, PrincipalName, explicit_tag=0xA1)), 1406 Realm("realm", "", explicit_tag=0xA2), 1407 ASN1F_optional( 1408 ASN1F_PACKET("sname", None, PrincipalName, explicit_tag=0xA3), 1409 ), 1410 ASN1F_optional(KerberosTime("from_", None, explicit_tag=0xA4)), 1411 KerberosTime("till", GeneralizedTime(), explicit_tag=0xA5), 1412 ASN1F_optional(KerberosTime("rtime", GeneralizedTime(), explicit_tag=0xA6)), 1413 UInt32("nonce", 0, explicit_tag=0xA7), 1414 ASN1F_SEQUENCE_OF("etype", [], Int32, explicit_tag=0xA8), 1415 ASN1F_optional( 1416 HostAddresses("addresses", explicit_tag=0xA9), 1417 ), 1418 ASN1F_optional( 1419 ASN1F_PACKET( 1420 "encAuthorizationData", None, EncryptedData, explicit_tag=0xAA 1421 ), 1422 ), 1423 ASN1F_optional( 1424 ASN1F_SEQUENCE_OF("additionalTickets", [], KRB_Ticket, explicit_tag=0xAB) 1425 ), 1426 ) 1427 1428 1429KRB_KDC_REQ = ASN1F_SEQUENCE( 1430 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA1), 1431 ASN1F_enum_INTEGER("msgType", 10, KRB_MSG_TYPES, explicit_tag=0xA2), 1432 ASN1F_optional(ASN1F_SEQUENCE_OF("padata", [], PADATA, explicit_tag=0xA3)), 1433 ASN1F_PACKET("reqBody", KRB_KDC_REQ_BODY(), KRB_KDC_REQ_BODY, explicit_tag=0xA4), 1434) 1435 1436 1437class KrbFastReq(ASN1_Packet): 1438 # RFC6113 sect 5.4.2 1439 ASN1_codec = ASN1_Codecs.BER 1440 ASN1_root = ASN1F_SEQUENCE( 1441 KerberosFlags( 1442 "fastOptions", 1443 "", 1444 [ 1445 "RESERVED", 1446 "hide-client-names", 1447 ] 1448 + ["res%d" % i for i in range(2, 16)] 1449 + ["kdc-follow-referrals"], 1450 explicit_tag=0xA0, 1451 ), 1452 ASN1F_SEQUENCE_OF("padata", [PADATA()], PADATA, explicit_tag=0xA1), 1453 ASN1F_PACKET("reqBody", None, KRB_KDC_REQ_BODY, explicit_tag=0xA2), 1454 ) 1455 1456 1457class KRB_AS_REQ(ASN1_Packet): 1458 ASN1_codec = ASN1_Codecs.BER 1459 ASN1_root = ASN1F_SEQUENCE( 1460 KRB_KDC_REQ, 1461 implicit_tag=ASN1_Class_KRB.AS_REQ, 1462 ) 1463 1464 1465class KRB_TGS_REQ(ASN1_Packet): 1466 ASN1_codec = ASN1_Codecs.BER 1467 ASN1_root = ASN1F_SEQUENCE( 1468 KRB_KDC_REQ, 1469 implicit_tag=ASN1_Class_KRB.TGS_REQ, 1470 ) 1471 msgType = ASN1_INTEGER(12) 1472 1473 1474# sect 5.4.2 1475 1476KRB_KDC_REP = ASN1F_SEQUENCE( 1477 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 1478 ASN1F_enum_INTEGER("msgType", 11, KRB_MSG_TYPES, explicit_tag=0xA1), 1479 ASN1F_optional( 1480 ASN1F_SEQUENCE_OF("padata", [], PADATA, explicit_tag=0xA2), 1481 ), 1482 Realm("crealm", "", explicit_tag=0xA3), 1483 ASN1F_PACKET("cname", None, PrincipalName, explicit_tag=0xA4), 1484 ASN1F_PACKET("ticket", None, KRB_Ticket, explicit_tag=0xA5), 1485 ASN1F_PACKET("encPart", None, EncryptedData, explicit_tag=0xA6), 1486) 1487 1488 1489class KRB_AS_REP(ASN1_Packet): 1490 ASN1_codec = ASN1_Codecs.BER 1491 ASN1_root = ASN1F_SEQUENCE( 1492 KRB_KDC_REP, 1493 implicit_tag=ASN1_Class_KRB.AS_REP, 1494 ) 1495 1496 1497class KRB_TGS_REP(ASN1_Packet): 1498 ASN1_codec = ASN1_Codecs.BER 1499 ASN1_root = ASN1F_SEQUENCE( 1500 KRB_KDC_REP, 1501 implicit_tag=ASN1_Class_KRB.TGS_REP, 1502 ) 1503 1504 1505class LastReqItem(ASN1_Packet): 1506 ASN1_codec = ASN1_Codecs.BER 1507 ASN1_root = ASN1F_SEQUENCE( 1508 Int32("lrType", 0, explicit_tag=0xA0), 1509 KerberosTime("lrValue", GeneralizedTime(), explicit_tag=0xA1), 1510 ) 1511 1512 1513EncKDCRepPart = ASN1F_SEQUENCE( 1514 ASN1F_PACKET("key", None, EncryptionKey, explicit_tag=0xA0), 1515 ASN1F_SEQUENCE_OF("lastReq", [], LastReqItem, explicit_tag=0xA1), 1516 UInt32("nonce", 0, explicit_tag=0xA2), 1517 ASN1F_optional( 1518 KerberosTime("keyExpiration", GeneralizedTime(), explicit_tag=0xA3), 1519 ), 1520 KerberosFlags( 1521 "flags", 1522 "", 1523 _TICKET_FLAGS, 1524 explicit_tag=0xA4, 1525 ), 1526 KerberosTime("authtime", GeneralizedTime(), explicit_tag=0xA5), 1527 ASN1F_optional( 1528 KerberosTime("starttime", GeneralizedTime(), explicit_tag=0xA6), 1529 ), 1530 KerberosTime("endtime", GeneralizedTime(), explicit_tag=0xA7), 1531 ASN1F_optional( 1532 KerberosTime("renewTill", GeneralizedTime(), explicit_tag=0xA8), 1533 ), 1534 Realm("srealm", "", explicit_tag=0xA9), 1535 ASN1F_PACKET("sname", PrincipalName(), PrincipalName, explicit_tag=0xAA), 1536 ASN1F_optional( 1537 HostAddresses("caddr", explicit_tag=0xAB), 1538 ), 1539 # RFC6806 sect 11 1540 ASN1F_optional( 1541 ASN1F_SEQUENCE_OF("encryptedPaData", [], PADATA, explicit_tag=0xAC), 1542 ), 1543) 1544 1545 1546class EncASRepPart(ASN1_Packet): 1547 ASN1_codec = ASN1_Codecs.BER 1548 ASN1_root = ASN1F_SEQUENCE( 1549 EncKDCRepPart, 1550 implicit_tag=ASN1_Class_KRB.EncASRepPart, 1551 ) 1552 1553 1554class EncTGSRepPart(ASN1_Packet): 1555 ASN1_codec = ASN1_Codecs.BER 1556 ASN1_root = ASN1F_SEQUENCE( 1557 EncKDCRepPart, 1558 implicit_tag=ASN1_Class_KRB.EncTGSRepPart, 1559 ) 1560 1561 1562# sect 5.5.1 1563 1564 1565class KRB_AP_REQ(ASN1_Packet): 1566 ASN1_codec = ASN1_Codecs.BER 1567 ASN1_root = ASN1F_SEQUENCE( 1568 ASN1F_SEQUENCE( 1569 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 1570 ASN1F_enum_INTEGER("msgType", 14, KRB_MSG_TYPES, explicit_tag=0xA1), 1571 KerberosFlags( 1572 "apOptions", 1573 "", 1574 [ 1575 "reserved", 1576 "use-session-key", 1577 "mutual-required", 1578 ], 1579 explicit_tag=0xA2, 1580 ), 1581 ASN1F_PACKET("ticket", None, KRB_Ticket, explicit_tag=0xA3), 1582 ASN1F_PACKET("authenticator", None, EncryptedData, explicit_tag=0xA4), 1583 ), 1584 implicit_tag=ASN1_Class_KRB.AP_REQ, 1585 ) 1586 1587 1588_PADATA_CLASSES[1] = KRB_AP_REQ 1589 1590 1591class KRB_Authenticator(ASN1_Packet): 1592 ASN1_codec = ASN1_Codecs.BER 1593 ASN1_root = ASN1F_SEQUENCE( 1594 ASN1F_SEQUENCE( 1595 ASN1F_INTEGER("authenticatorPvno", 5, explicit_tag=0xA0), 1596 Realm("crealm", "", explicit_tag=0xA1), 1597 ASN1F_PACKET("cname", None, PrincipalName, explicit_tag=0xA2), 1598 ASN1F_optional( 1599 ASN1F_PACKET("cksum", None, Checksum, explicit_tag=0xA3), 1600 ), 1601 Microseconds("cusec", 0, explicit_tag=0xA4), 1602 KerberosTime("ctime", GeneralizedTime(), explicit_tag=0xA5), 1603 ASN1F_optional( 1604 ASN1F_PACKET("subkey", None, EncryptionKey, explicit_tag=0xA6), 1605 ), 1606 ASN1F_optional( 1607 UInt32("seqNumber", 0, explicit_tag=0xA7), 1608 ), 1609 ASN1F_optional( 1610 ASN1F_PACKET( 1611 "encAuthorizationData", None, AuthorizationData, explicit_tag=0xA8 1612 ), 1613 ), 1614 ), 1615 implicit_tag=ASN1_Class_KRB.Authenticator, 1616 ) 1617 1618 1619# sect 5.5.2 1620 1621 1622class KRB_AP_REP(ASN1_Packet): 1623 ASN1_codec = ASN1_Codecs.BER 1624 ASN1_root = ASN1F_SEQUENCE( 1625 ASN1F_SEQUENCE( 1626 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 1627 ASN1F_enum_INTEGER("msgType", 15, KRB_MSG_TYPES, explicit_tag=0xA1), 1628 ASN1F_PACKET("encPart", None, EncryptedData, explicit_tag=0xA2), 1629 ), 1630 implicit_tag=ASN1_Class_KRB.AP_REP, 1631 ) 1632 1633 1634class EncAPRepPart(ASN1_Packet): 1635 ASN1_codec = ASN1_Codecs.BER 1636 ASN1_root = ASN1F_SEQUENCE( 1637 ASN1F_SEQUENCE( 1638 KerberosTime("ctime", GeneralizedTime(), explicit_tag=0xA0), 1639 Microseconds("cusec", 0, explicit_tag=0xA1), 1640 ASN1F_optional( 1641 ASN1F_PACKET("subkey", None, EncryptionKey, explicit_tag=0xA2), 1642 ), 1643 ASN1F_optional( 1644 UInt32("seqNumber", 0, explicit_tag=0xA3), 1645 ), 1646 ), 1647 implicit_tag=ASN1_Class_KRB.EncAPRepPart, 1648 ) 1649 1650 1651# sect 5.7 1652 1653 1654class KRB_PRIV(ASN1_Packet): 1655 ASN1_codec = ASN1_Codecs.BER 1656 ASN1_root = ASN1F_SEQUENCE( 1657 ASN1F_SEQUENCE( 1658 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 1659 ASN1F_enum_INTEGER("msgType", 21, KRB_MSG_TYPES, explicit_tag=0xA1), 1660 ASN1F_PACKET("encPart", None, EncryptedData, explicit_tag=0xA3), 1661 ), 1662 implicit_tag=ASN1_Class_KRB.PRIV, 1663 ) 1664 1665 1666class EncKrbPrivPart(ASN1_Packet): 1667 ASN1_codec = ASN1_Codecs.BER 1668 ASN1_root = ASN1F_SEQUENCE( 1669 ASN1F_SEQUENCE( 1670 ASN1F_STRING("userData", ASN1_STRING(""), explicit_tag=0xA0), 1671 ASN1F_optional( 1672 KerberosTime("timestamp", None, explicit_tag=0xA1), 1673 ), 1674 ASN1F_optional( 1675 Microseconds("usec", None, explicit_tag=0xA2), 1676 ), 1677 ASN1F_optional( 1678 UInt32("seqNumber", None, explicit_tag=0xA3), 1679 ), 1680 ASN1F_PACKET("sAddress", None, HostAddress, explicit_tag=0xA4), 1681 ASN1F_optional( 1682 ASN1F_PACKET("cAddress", None, HostAddress, explicit_tag=0xA5), 1683 ), 1684 ), 1685 implicit_tag=ASN1_Class_KRB.EncKrbPrivPart, 1686 ) 1687 1688 1689# sect 5.8 1690 1691 1692class KRB_CRED(ASN1_Packet): 1693 ASN1_codec = ASN1_Codecs.BER 1694 ASN1_root = ASN1F_SEQUENCE( 1695 ASN1F_SEQUENCE( 1696 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 1697 ASN1F_enum_INTEGER("msgType", 22, KRB_MSG_TYPES, explicit_tag=0xA1), 1698 ASN1F_SEQUENCE_OF("tickets", [KRB_Ticket()], KRB_Ticket, explicit_tag=0xA2), 1699 ASN1F_PACKET("encPart", None, EncryptedData, explicit_tag=0xA3), 1700 ), 1701 implicit_tag=ASN1_Class_KRB.CRED, 1702 ) 1703 1704 1705class KrbCredInfo(ASN1_Packet): 1706 ASN1_codec = ASN1_Codecs.BER 1707 ASN1_root = ASN1F_SEQUENCE( 1708 ASN1F_PACKET("key", EncryptionKey(), EncryptionKey, explicit_tag=0xA0), 1709 ASN1F_optional( 1710 Realm("prealm", None, explicit_tag=0xA1), 1711 ), 1712 ASN1F_optional( 1713 ASN1F_PACKET("pname", None, PrincipalName, explicit_tag=0xA2), 1714 ), 1715 ASN1F_optional( 1716 KerberosFlags( 1717 "flags", 1718 None, 1719 _TICKET_FLAGS, 1720 explicit_tag=0xA3, 1721 ), 1722 ), 1723 ASN1F_optional( 1724 KerberosTime("authtime", None, explicit_tag=0xA4), 1725 ), 1726 ASN1F_optional(KerberosTime("starttime", None, explicit_tag=0xA5)), 1727 ASN1F_optional( 1728 KerberosTime("endtime", None, explicit_tag=0xA6), 1729 ), 1730 ASN1F_optional( 1731 KerberosTime("renewTill", None, explicit_tag=0xA7), 1732 ), 1733 ASN1F_optional( 1734 Realm("srealm", None, explicit_tag=0xA8), 1735 ), 1736 ASN1F_optional( 1737 ASN1F_PACKET("sname", None, PrincipalName, explicit_tag=0xA9), 1738 ), 1739 ASN1F_optional( 1740 HostAddresses("caddr", explicit_tag=0xAA), 1741 ), 1742 ) 1743 1744 1745class EncKrbCredPart(ASN1_Packet): 1746 ASN1_codec = ASN1_Codecs.BER 1747 ASN1_root = ASN1F_SEQUENCE( 1748 ASN1F_SEQUENCE( 1749 ASN1F_SEQUENCE_OF( 1750 "ticketInfo", 1751 [KrbCredInfo()], 1752 KrbCredInfo, 1753 explicit_tag=0xA0, 1754 ), 1755 ASN1F_optional( 1756 UInt32("nonce", None, explicit_tag=0xA1), 1757 ), 1758 ASN1F_optional( 1759 KerberosTime("timestamp", None, explicit_tag=0xA2), 1760 ), 1761 ASN1F_optional( 1762 Microseconds("usec", None, explicit_tag=0xA3), 1763 ), 1764 ASN1F_optional( 1765 ASN1F_PACKET("sAddress", None, HostAddress, explicit_tag=0xA4), 1766 ), 1767 ASN1F_optional( 1768 ASN1F_PACKET("cAddress", None, HostAddress, explicit_tag=0xA5), 1769 ), 1770 ), 1771 implicit_tag=ASN1_Class_KRB.EncKrbCredPart, 1772 ) 1773 1774 1775# sect 5.9.1 1776 1777 1778class MethodData(ASN1_Packet): 1779 ASN1_codec = ASN1_Codecs.BER 1780 ASN1_root = ASN1F_SEQUENCE_OF("seq", [PADATA()], PADATA) 1781 1782 1783class _KRBERROR_data_Field(ASN1F_STRING_PacketField): 1784 def m2i(self, pkt, s): 1785 val = super(_KRBERROR_data_Field, self).m2i(pkt, s) 1786 if not val[0].val: 1787 return val 1788 if pkt.errorCode.val in [14, 24, 25]: 1789 # 14: KDC_ERR_ETYPE_NOSUPP 1790 # 24: KDC_ERR_PREAUTH_FAILED 1791 # 25: KDC_ERR_PREAUTH_REQUIRED 1792 return MethodData(val[0].val, _underlayer=pkt), val[1] 1793 elif pkt.errorCode.val in [6, 7, 13, 18, 29, 41, 60]: 1794 # 6: KDC_ERR_C_PRINCIPAL_UNKNOWN 1795 # 7: KDC_ERR_S_PRINCIPAL_UNKNOWN 1796 # 13: KDC_ERR_BADOPTION 1797 # 18: KDC_ERR_CLIENT_REVOKED 1798 # 29: KDC_ERR_SVC_UNAVAILABLE 1799 # 41: KRB_AP_ERR_MODIFIED 1800 # 60: KRB_ERR_GENERIC 1801 return KERB_ERROR_DATA(val[0].val, _underlayer=pkt), val[1] 1802 elif pkt.errorCode.val == 69: 1803 # KRB_AP_ERR_USER_TO_USER_REQUIRED 1804 return KRB_TGT_REP(val[0].val, _underlayer=pkt), val[1] 1805 return val 1806 1807 1808class KRB_ERROR(ASN1_Packet): 1809 ASN1_codec = ASN1_Codecs.BER 1810 ASN1_root = ASN1F_SEQUENCE( 1811 ASN1F_SEQUENCE( 1812 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 1813 ASN1F_enum_INTEGER("msgType", 30, KRB_MSG_TYPES, explicit_tag=0xA1), 1814 ASN1F_optional( 1815 KerberosTime("ctime", None, explicit_tag=0xA2), 1816 ), 1817 ASN1F_optional( 1818 Microseconds("cusec", None, explicit_tag=0xA3), 1819 ), 1820 KerberosTime("stime", GeneralizedTime(), explicit_tag=0xA4), 1821 Microseconds("susec", 0, explicit_tag=0xA5), 1822 ASN1F_enum_INTEGER( 1823 "errorCode", 1824 0, 1825 { 1826 # RFC4120 sect 7.5.9 1827 0: "KDC_ERR_NONE", 1828 1: "KDC_ERR_NAME_EXP", 1829 2: "KDC_ERR_SERVICE_EXP", 1830 3: "KDC_ERR_BAD_PVNO", 1831 4: "KDC_ERR_C_OLD_MAST_KVNO", 1832 5: "KDC_ERR_S_OLD_MAST_KVNO", 1833 6: "KDC_ERR_C_PRINCIPAL_UNKNOWN", 1834 7: "KDC_ERR_S_PRINCIPAL_UNKNOWN", 1835 8: "KDC_ERR_PRINCIPAL_NOT_UNIQUE", 1836 9: "KDC_ERR_NULL_KEY", 1837 10: "KDC_ERR_CANNOT_POSTDATE", 1838 11: "KDC_ERR_NEVER_VALID", 1839 12: "KDC_ERR_POLICY", 1840 13: "KDC_ERR_BADOPTION", 1841 14: "KDC_ERR_ETYPE_NOSUPP", 1842 15: "KDC_ERR_SUMTYPE_NOSUPP", 1843 16: "KDC_ERR_PADATA_TYPE_NOSUPP", 1844 17: "KDC_ERR_TRTYPE_NOSUPP", 1845 18: "KDC_ERR_CLIENT_REVOKED", 1846 19: "KDC_ERR_SERVICE_REVOKED", 1847 20: "KDC_ERR_TGT_REVOKED", 1848 21: "KDC_ERR_CLIENT_NOTYET", 1849 22: "KDC_ERR_SERVICE_NOTYET", 1850 23: "KDC_ERR_KEY_EXPIRED", 1851 24: "KDC_ERR_PREAUTH_FAILED", 1852 25: "KDC_ERR_PREAUTH_REQUIRED", 1853 26: "KDC_ERR_SERVER_NOMATCH", 1854 27: "KDC_ERR_MUST_USE_USER2USER", 1855 28: "KDC_ERR_PATH_NOT_ACCEPTED", 1856 29: "KDC_ERR_SVC_UNAVAILABLE", 1857 31: "KRB_AP_ERR_BAD_INTEGRITY", 1858 32: "KRB_AP_ERR_TKT_EXPIRED", 1859 33: "KRB_AP_ERR_TKT_NYV", 1860 34: "KRB_AP_ERR_REPEAT", 1861 35: "KRB_AP_ERR_NOT_US", 1862 36: "KRB_AP_ERR_BADMATCH", 1863 37: "KRB_AP_ERR_SKEW", 1864 38: "KRB_AP_ERR_BADADDR", 1865 39: "KRB_AP_ERR_BADVERSION", 1866 40: "KRB_AP_ERR_MSG_TYPE", 1867 41: "KRB_AP_ERR_MODIFIED", 1868 42: "KRB_AP_ERR_BADORDER", 1869 44: "KRB_AP_ERR_BADKEYVER", 1870 45: "KRB_AP_ERR_NOKEY", 1871 46: "KRB_AP_ERR_MUT_FAIL", 1872 47: "KRB_AP_ERR_BADDIRECTION", 1873 48: "KRB_AP_ERR_METHOD", 1874 49: "KRB_AP_ERR_BADSEQ", 1875 50: "KRB_AP_ERR_INAPP_CKSUM", 1876 51: "KRB_AP_PATH_NOT_ACCEPTED", 1877 52: "KRB_ERR_RESPONSE_TOO_BIG", 1878 60: "KRB_ERR_GENERIC", 1879 61: "KRB_ERR_FIELD_TOOLONG", 1880 62: "KDC_ERROR_CLIENT_NOT_TRUSTED", 1881 63: "KDC_ERROR_KDC_NOT_TRUSTED", 1882 64: "KDC_ERROR_INVALID_SIG", 1883 65: "KDC_ERR_KEY_TOO_WEAK", 1884 66: "KDC_ERR_CERTIFICATE_MISMATCH", 1885 67: "KRB_AP_ERR_NO_TGT", 1886 68: "KDC_ERR_WRONG_REALM", 1887 69: "KRB_AP_ERR_USER_TO_USER_REQUIRED", 1888 70: "KDC_ERR_CANT_VERIFY_CERTIFICATE", 1889 71: "KDC_ERR_INVALID_CERTIFICATE", 1890 72: "KDC_ERR_REVOKED_CERTIFICATE", 1891 73: "KDC_ERR_REVOCATION_STATUS_UNKNOWN", 1892 74: "KDC_ERR_REVOCATION_STATUS_UNAVAILABLE", 1893 75: "KDC_ERR_CLIENT_NAME_MISMATCH", 1894 76: "KDC_ERR_KDC_NAME_MISMATCH", 1895 # draft-ietf-kitten-iakerb 1896 85: "KRB_AP_ERR_IAKERB_KDC_NOT_FOUND", 1897 86: "KRB_AP_ERR_IAKERB_KDC_NO_RESPONSE", 1898 # RFC6113 1899 90: "KDC_ERR_PREAUTH_EXPIRED", 1900 91: "KDC_ERR_MORE_PREAUTH_DATA_REQUIRED", 1901 92: "KDC_ERR_PREAUTH_BAD_AUTHENTICATION_SET", 1902 93: "KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS", 1903 }, 1904 explicit_tag=0xA6, 1905 ), 1906 ASN1F_optional(Realm("crealm", None, explicit_tag=0xA7)), 1907 ASN1F_optional( 1908 ASN1F_PACKET("cname", None, PrincipalName, explicit_tag=0xA8), 1909 ), 1910 Realm("realm", "", explicit_tag=0xA9), 1911 ASN1F_PACKET("sname", PrincipalName(), PrincipalName, explicit_tag=0xAA), 1912 ASN1F_optional(KerberosString("eText", "", explicit_tag=0xAB)), 1913 ASN1F_optional(_KRBERROR_data_Field("eData", "", explicit_tag=0xAC)), 1914 ), 1915 implicit_tag=ASN1_Class_KRB.ERROR, 1916 ) 1917 1918 1919# [MS-KILE] sect 2.2.1 1920 1921 1922class KERB_EXT_ERROR(Packet): 1923 fields_desc = [ 1924 XLEIntField("status", 0), 1925 XLEIntField("reserved", 0), 1926 XLEIntField("flags", 0x00000001), 1927 ] 1928 1929 1930# [MS-KILE] sect 2.2.2 1931 1932 1933class _Error_Field(ASN1F_STRING_PacketField): 1934 def m2i(self, pkt, s): 1935 val = super(_Error_Field, self).m2i(pkt, s) 1936 if not val[0].val: 1937 return val 1938 if pkt.dataType.val == 3: # KERB_ERR_TYPE_EXTENDED 1939 return KERB_EXT_ERROR(val[0].val, _underlayer=pkt), val[1] 1940 return val 1941 1942 1943class KERB_ERROR_DATA(ASN1_Packet): 1944 ASN1_codec = ASN1_Codecs.BER 1945 ASN1_root = ASN1F_SEQUENCE( 1946 ASN1F_enum_INTEGER( 1947 "dataType", 1948 2, 1949 { 1950 1: "KERB_AP_ERR_TYPE_NTSTATUS", # from the wdk 1951 2: "KERB_AP_ERR_TYPE_SKEW_RECOVERY", 1952 3: "KERB_ERR_TYPE_EXTENDED", 1953 }, 1954 explicit_tag=0xA1, 1955 ), 1956 ASN1F_optional(_Error_Field("dataValue", None, explicit_tag=0xA2)), 1957 ) 1958 1959 1960# Kerberos U2U - draft-ietf-cat-user2user-03 1961 1962 1963class KRB_TGT_REQ(ASN1_Packet): 1964 ASN1_codec = ASN1_Codecs.BER 1965 ASN1_root = ASN1F_SEQUENCE( 1966 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 1967 ASN1F_enum_INTEGER("msgType", 16, KRB_MSG_TYPES, explicit_tag=0xA1), 1968 ASN1F_optional( 1969 ASN1F_PACKET("sname", None, PrincipalName, explicit_tag=0xA2), 1970 ), 1971 ASN1F_optional( 1972 Realm("realm", None, explicit_tag=0xA3), 1973 ), 1974 ) 1975 1976 1977class KRB_TGT_REP(ASN1_Packet): 1978 ASN1_codec = ASN1_Codecs.BER 1979 ASN1_root = ASN1F_SEQUENCE( 1980 ASN1F_INTEGER("pvno", 5, explicit_tag=0xA0), 1981 ASN1F_enum_INTEGER("msgType", 17, KRB_MSG_TYPES, explicit_tag=0xA1), 1982 ASN1F_PACKET("ticket", None, KRB_Ticket, explicit_tag=0xA2), 1983 ) 1984 1985 1986# draft-ietf-kitten-iakerb-03 sect 4 1987 1988 1989class KRB_FINISHED(ASN1_Packet): 1990 ASN1_codec = ASN1_Codecs.BER 1991 ASN1_root = ASN1F_SEQUENCE( 1992 ASN1F_PACKET("gssMic", Checksum(), Checksum, explicit_tag=0xA1), 1993 ) 1994 1995 1996# RFC 6542 sect 3.1 1997 1998 1999class KRB_GSS_EXT(Packet): 2000 fields_desc = [ 2001 IntEnumField( 2002 "type", 2003 0, 2004 { 2005 # https://www.iana.org/assignments/kerberos-v-gss-api/kerberos-v-gss-api.xhtml 2006 0x00000000: "GSS_EXTS_CHANNEL_BINDING", # RFC 6542 sect 3.2 2007 0x00000001: "GSS_EXTS_IAKERB_FINISHED", # not standard 2008 0x00000002: "GSS_EXTS_FINISHED", # PKU2U / IAKERB 2009 }, 2010 ), 2011 FieldLenField("length", None, length_of="data", fmt="!I"), 2012 MultipleTypeField( 2013 [ 2014 ( 2015 PacketField("data", KRB_FINISHED(), KRB_FINISHED), 2016 lambda pkt: pkt.type == 0x00000002, 2017 ), 2018 ], 2019 XStrLenField("data", b"", length_from=lambda pkt: pkt.length), 2020 ), 2021 ] 2022 2023 2024# RFC 4121 sect 4.1.1 2025 2026 2027class KRB_AuthenticatorChecksum(Packet): 2028 fields_desc = [ 2029 FieldLenField("Lgth", None, length_of="Bnd", fmt="<I"), 2030 PacketLenField( 2031 "Bnd", 2032 GssChannelBindings(), 2033 GssChannelBindings, 2034 length_from=lambda pkt: pkt.Lgth, 2035 ), 2036 FlagsField( 2037 "Flags", 2038 0, 2039 -32, 2040 { 2041 0x01: "GSS_C_DELEG_FLAG", 2042 0x02: "GSS_C_MUTUAL_FLAG", 2043 0x04: "GSS_C_REPLAY_FLAG", 2044 0x08: "GSS_C_SEQUENCE_FLAG", 2045 0x10: "GSS_C_CONF_FLAG", # confidentiality 2046 0x20: "GSS_C_INTEG_FLAG", # integrity 2047 # RFC4757 2048 0x1000: "GSS_C_DCE_STYLE", 2049 0x2000: "GSS_C_IDENTIFY_FLAG", 2050 0x4000: "GSS_C_EXTENDED_ERROR_FLAG", 2051 }, 2052 ), 2053 ConditionalField( 2054 LEShortField("DlgOpt", 0), 2055 lambda pkt: pkt.Flags.GSS_C_DELEG_FLAG, 2056 ), 2057 ConditionalField( 2058 FieldLenField("Dlgth", None, length_of="Deleg"), 2059 lambda pkt: pkt.Flags.GSS_C_DELEG_FLAG, 2060 ), 2061 ConditionalField( 2062 PacketLenField( 2063 "Deleg", KRB_CRED(), KRB_CRED, length_from=lambda pkt: pkt.Dlgth 2064 ), 2065 lambda pkt: pkt.Flags.GSS_C_DELEG_FLAG, 2066 ), 2067 # Extensions: RFC 6542 sect 3.1 2068 PacketListField("Exts", KRB_GSS_EXT(), KRB_GSS_EXT), 2069 ] 2070 2071 2072# Kerberos V5 GSS-API - RFC1964 and RFC4121 2073 2074_TOK_IDS = { 2075 # RFC 1964 2076 b"\x01\x00": "KRB-AP-REQ", 2077 b"\x02\x00": "KRB-AP-REP", 2078 b"\x03\x00": "KRB-ERROR", 2079 b"\x01\x01": "GSS_GetMIC-RFC1964", 2080 b"\x02\x01": "GSS_Wrap-RFC1964", 2081 b"\x01\x02": "GSS_Delete_sec_context-RFC1964", 2082 # U2U: [draft-ietf-cat-user2user-03] 2083 b"\x04\x00": "KRB-TGT-REQ", 2084 b"\x04\x01": "KRB-TGT-REP", 2085 # RFC 4121 2086 b"\x04\x04": "GSS_GetMIC", 2087 b"\x05\x04": "GSS_Wrap", 2088 # IAKERB: [draft-ietf-kitten-iakerb-03] 2089 b"\x05\x01": "IAKERB_PROXY", 2090} 2091_SGN_ALGS = { 2092 0x00: "DES MAC MD5", 2093 0x01: "MD2.5", 2094 0x02: "DES MAC", 2095 # RFC 4757 2096 0x11: "HMAC", 2097} 2098_SEAL_ALGS = { 2099 0: "DES", 2100 0xFFFF: "none", 2101 # RFC 4757 2102 0x10: "RC4", 2103} 2104 2105 2106# RFC 1964 - sect 1.1 2107 2108# See https://www.iana.org/assignments/kerberos-v-gss-api/kerberos-v-gss-api.xhtml 2109_InitialContextTokens = {} # filled below 2110 2111 2112class KRB_InnerToken(Packet): 2113 name = "Kerberos v5 InnerToken" 2114 fields_desc = [ 2115 StrFixedLenEnumField("TOK_ID", b"\x01\x00", _TOK_IDS, length=2), 2116 PacketField( 2117 "root", 2118 KRB_AP_REQ(), 2119 lambda x, _parent: _InitialContextTokens[_parent.TOK_ID](x), 2120 ), 2121 ] 2122 2123 def mysummary(self): 2124 return self.sprintf( 2125 "Kerberos %s" % _TOK_IDS.get(self.TOK_ID, repr(self.TOK_ID)) 2126 ) 2127 2128 def guess_payload_class(self, payload): 2129 if self.TOK_ID in [b"\x01\x01", b"\x02\x01", b"\x04\x04", b"\x05\x04"]: 2130 return conf.padding_layer 2131 return Kerberos 2132 2133 @classmethod 2134 def dispatch_hook(cls, _pkt=None, *args, **kargs): 2135 if _pkt and len(_pkt) >= 13: 2136 # Older RFC1964 variants of the token have KRB_GSSAPI_Token wrapper 2137 if _pkt[2:13] == b"\x06\t*\x86H\x86\xf7\x12\x01\x02\x02": 2138 return KRB_GSSAPI_Token 2139 return cls 2140 2141 2142# RFC 4121 - sect 4.1 2143 2144 2145class KRB_GSSAPI_Token(GSSAPI_BLOB): 2146 name = "Kerberos GSSAPI-Token" 2147 ASN1_codec = ASN1_Codecs.BER 2148 ASN1_root = ASN1F_SEQUENCE( 2149 ASN1F_OID("MechType", "1.2.840.113554.1.2.2"), 2150 ASN1F_PACKET( 2151 "innerToken", 2152 KRB_InnerToken(), 2153 KRB_InnerToken, 2154 implicit_tag=0x0, 2155 ), 2156 implicit_tag=ASN1_Class_KRB.Token, 2157 ) 2158 2159 2160# RFC 1964 - sect 1.2.1 2161 2162 2163class KRB_GSS_MIC_RFC1964(Packet): 2164 name = "Kerberos v5 MIC Token (RFC1964)" 2165 fields_desc = [ 2166 LEShortEnumField("SGN_ALG", 0, _SGN_ALGS), 2167 XLEIntField("Filler", 0xFFFFFFFF), 2168 XStrFixedLenField("SND_SEQ", b"", length=8), 2169 PadField( # sect 1.2.2.3 2170 XStrFixedLenField("SGN_CKSUM", b"", length=8), 2171 align=8, 2172 padwith=b"\x04", 2173 ), 2174 ] 2175 2176 def default_payload_class(self, payload): 2177 return conf.padding_layer 2178 2179 2180_InitialContextTokens[b"\x01\x01"] = KRB_GSS_MIC_RFC1964 2181 2182# RFC 1964 - sect 1.2.2 2183 2184 2185class KRB_GSS_Wrap_RFC1964(Packet): 2186 name = "Kerberos v5 GSS_Wrap (RFC1964)" 2187 fields_desc = [ 2188 LEShortEnumField("SGN_ALG", 0, _SGN_ALGS), 2189 LEShortEnumField("SEAL_ALG", 0, _SEAL_ALGS), 2190 XLEShortField("Filler", 0xFFFF), 2191 XStrFixedLenField("SND_SEQ", b"", length=8), 2192 PadField( # sect 1.2.2.3 2193 XStrFixedLenField("SGN_CKSUM", b"", length=8), 2194 align=8, 2195 padwith=b"\x04", 2196 ), 2197 # sect 1.2.2.3 2198 XStrFixedLenField("CONFOUNDER", b"", length=8), 2199 ] 2200 2201 def default_payload_class(self, payload): 2202 return conf.padding_layer 2203 2204 2205_InitialContextTokens[b"\x02\x01"] = KRB_GSS_Wrap_RFC1964 2206 2207 2208# RFC 1964 - sect 1.2.2 2209 2210 2211class KRB_GSS_Delete_sec_context_RFC1964(Packet): 2212 name = "Kerberos v5 GSS_Delete_sec_context (RFC1964)" 2213 fields_desc = KRB_GSS_MIC_RFC1964.fields_desc 2214 2215 2216_InitialContextTokens[b"\x01\x02"] = KRB_GSS_Delete_sec_context_RFC1964 2217 2218 2219# RFC 4121 - sect 4.2.2 2220_KRB5_GSS_Flags = [ 2221 "SentByAcceptor", 2222 "Sealed", 2223 "AcceptorSubkey", 2224] 2225 2226 2227# RFC 4121 - sect 4.2.6.1 2228 2229 2230class KRB_GSS_MIC(Packet): 2231 name = "Kerberos v5 MIC Token" 2232 fields_desc = [ 2233 FlagsField("Flags", 0, 8, _KRB5_GSS_Flags), 2234 XStrFixedLenField("Filler", b"\xff\xff\xff\xff\xff", length=5), 2235 LongField("SND_SEQ", 0), # Big endian 2236 XStrField("SGN_CKSUM", b"\x00" * 12), 2237 ] 2238 2239 def default_payload_class(self, payload): 2240 return conf.padding_layer 2241 2242 2243_InitialContextTokens[b"\x04\x04"] = KRB_GSS_MIC 2244 2245 2246# RFC 4121 - sect 4.2.6.2 2247 2248 2249class KRB_GSS_Wrap(Packet): 2250 name = "Kerberos v5 Wrap Token" 2251 fields_desc = [ 2252 FlagsField("Flags", 0, 8, _KRB5_GSS_Flags), 2253 XByteField("Filler", 0xFF), 2254 ShortField("EC", 0), # Big endian 2255 ShortField("RRC", 0), # Big endian 2256 LongField("SND_SEQ", 0), # Big endian 2257 MultipleTypeField( 2258 [ 2259 ( 2260 XStrField("Data", b""), 2261 lambda pkt: pkt.Flags.Sealed, 2262 ) 2263 ], 2264 XStrLenField("Data", b"", length_from=lambda pkt: pkt.EC), 2265 ), 2266 ] 2267 2268 def default_payload_class(self, payload): 2269 return conf.padding_layer 2270 2271 2272_InitialContextTokens[b"\x05\x04"] = KRB_GSS_Wrap 2273 2274 2275# Kerberos IAKERB - draft-ietf-kitten-iakerb-03 2276 2277 2278class IAKERB_HEADER(ASN1_Packet): 2279 ASN1_codec = ASN1_Codecs.BER 2280 ASN1_root = ASN1F_SEQUENCE( 2281 Realm("targetRealm", "", explicit_tag=0xA1), 2282 ASN1F_optional( 2283 ASN1F_STRING("cookie", None, explicit_tag=0xA2), 2284 ), 2285 ) 2286 2287 2288_InitialContextTokens[b"\x05\x01"] = IAKERB_HEADER 2289 2290 2291# Register for GSSAPI 2292 2293# Kerberos 5 2294_GSSAPI_OIDS["1.2.840.113554.1.2.2"] = KRB_InnerToken 2295_GSSAPI_SIGNATURE_OIDS["1.2.840.113554.1.2.2"] = KRB_InnerToken 2296# Kerberos 5 - U2U 2297_GSSAPI_OIDS["1.2.840.113554.1.2.2.3"] = KRB_InnerToken 2298# Kerberos 5 - IAKERB 2299_GSSAPI_OIDS["1.3.6.1.5.2.5"] = KRB_InnerToken 2300 2301 2302# Entry class 2303 2304# RFC4120 sect 5.10 2305 2306 2307class Kerberos(ASN1_Packet): 2308 ASN1_codec = ASN1_Codecs.BER 2309 ASN1_root = ASN1F_CHOICE( 2310 "root", 2311 None, 2312 # RFC4120 2313 KRB_GSSAPI_Token, # [APPLICATION 0] 2314 KRB_Ticket, # [APPLICATION 1] 2315 KRB_Authenticator, # [APPLICATION 2] 2316 KRB_AS_REQ, # [APPLICATION 10] 2317 KRB_AS_REP, # [APPLICATION 11] 2318 KRB_TGS_REQ, # [APPLICATION 12] 2319 KRB_TGS_REP, # [APPLICATION 13] 2320 KRB_AP_REQ, # [APPLICATION 14] 2321 KRB_AP_REP, # [APPLICATION 15] 2322 # RFC4120 2323 KRB_ERROR, # [APPLICATION 30] 2324 ) 2325 2326 def mysummary(self): 2327 return self.root.summary() 2328 2329 2330bind_bottom_up(UDP, Kerberos, sport=88) 2331bind_bottom_up(UDP, Kerberos, dport=88) 2332bind_layers(UDP, Kerberos, sport=88, dport=88) 2333 2334_InitialContextTokens[b"\x01\x00"] = KRB_AP_REQ 2335_InitialContextTokens[b"\x02\x00"] = KRB_AP_REP 2336_InitialContextTokens[b"\x03\x00"] = KRB_ERROR 2337_InitialContextTokens[b"\x04\x00"] = KRB_TGT_REQ 2338_InitialContextTokens[b"\x04\x01"] = KRB_TGT_REP 2339 2340 2341# RFC4120 sect 7.2.2 2342 2343 2344class KerberosTCPHeader(Packet): 2345 # According to RFC 5021, first bit to 1 has a special meaning and 2346 # negotiates Kerberos TCP extensions... But apart from rfc6251 no one used that 2347 # https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml#kerberos-parameters-4 2348 fields_desc = [LenField("len", None, fmt="!I")] 2349 2350 @classmethod 2351 def tcp_reassemble(cls, data, *args, **kwargs): 2352 if len(data) < 4: 2353 return None 2354 length = struct.unpack("!I", data[:4])[0] 2355 if len(data) == length + 4: 2356 return cls(data) 2357 2358 2359bind_layers(KerberosTCPHeader, Kerberos) 2360 2361bind_bottom_up(TCP, KerberosTCPHeader, sport=88) 2362bind_layers(TCP, KerberosTCPHeader, dport=88) 2363 2364 2365# RFC3244 sect 2 2366 2367 2368class KPASSWD_REQ(Packet): 2369 fields_desc = [ 2370 ShortField("len", None), 2371 ShortField("pvno", 0xFF80), 2372 ShortField("apreqlen", None), 2373 PacketLenField( 2374 "apreq", KRB_AP_REQ(), KRB_AP_REQ, length_from=lambda pkt: pkt.apreqlen 2375 ), 2376 ConditionalField( 2377 PacketLenField( 2378 "krbpriv", 2379 KRB_PRIV(), 2380 KRB_PRIV, 2381 length_from=lambda pkt: pkt.len - 6 - pkt.apreqlen, 2382 ), 2383 lambda pkt: pkt.apreqlen != 0, 2384 ), 2385 ConditionalField( 2386 PacketLenField( 2387 "error", KRB_ERROR(), KRB_ERROR, length_from=lambda pkt: pkt.len - 6 2388 ), 2389 lambda pkt: pkt.apreqlen == 0, 2390 ), 2391 ] 2392 2393 def post_build(self, p, pay): 2394 if self.len is None: 2395 p = struct.pack("!H", len(p)) + p[2:] 2396 if self.apreqlen is None and self.krbpriv is not None: 2397 p = p[:4] + struct.pack("!H", len(self.apreq)) + p[6:] 2398 return p + pay 2399 2400 2401class ChangePasswdData(ASN1_Packet): 2402 ASN1_codec = ASN1_Codecs.BER 2403 ASN1_root = ASN1F_SEQUENCE( 2404 ASN1F_STRING("newpasswd", ASN1_STRING(""), explicit_tag=0xA0), 2405 ASN1F_optional( 2406 ASN1F_PACKET("targname", None, PrincipalName, explicit_tag=0xA1) 2407 ), 2408 ASN1F_optional(Realm("targrealm", None, explicit_tag=0xA2)), 2409 ) 2410 2411 2412class KPASSWD_REP(Packet): 2413 fields_desc = [ 2414 ShortField("len", None), 2415 ShortField("pvno", 0x0001), 2416 ShortField("apreplen", None), 2417 PacketLenField( 2418 "aprep", KRB_AP_REP(), KRB_AP_REP, length_from=lambda pkt: pkt.apreplen 2419 ), 2420 ConditionalField( 2421 PacketLenField( 2422 "krbpriv", 2423 KRB_PRIV(), 2424 KRB_PRIV, 2425 length_from=lambda pkt: pkt.len - 6 - pkt.apreplen, 2426 ), 2427 lambda pkt: pkt.apreplen != 0, 2428 ), 2429 ConditionalField( 2430 PacketLenField( 2431 "error", KRB_ERROR(), KRB_ERROR, length_from=lambda pkt: pkt.len - 6 2432 ), 2433 lambda pkt: pkt.apreplen == 0, 2434 ), 2435 ] 2436 2437 def post_build(self, p, pay): 2438 if self.len is None: 2439 p = struct.pack("!H", len(p)) + p[2:] 2440 if self.apreplen is None and self.krbpriv is not None: 2441 p = p[:4] + struct.pack("!H", len(self.aprep)) + p[6:] 2442 return p + pay 2443 2444 def answers(self, other): 2445 return isinstance(other, KPASSWD_REQ) 2446 2447 2448KPASSWD_RESULTS = { 2449 0: "KRB5_KPASSWD_SUCCESS", 2450 1: "KRB5_KPASSWD_MALFORMED", 2451 2: "KRB5_KPASSWD_HARDERROR", 2452 3: "KRB5_KPASSWD_AUTHERROR", 2453 4: "KRB5_KPASSWD_SOFTERROR", 2454 5: "KRB5_KPASSWD_ACCESSDENIED", 2455 6: "KRB5_KPASSWD_BAD_VERSION", 2456 7: "KRB5_KPASSWD_INITIAL_FLAG_NEEDED", 2457} 2458 2459 2460class KPasswdRepData(Packet): 2461 fields_desc = [ 2462 ShortEnumField("resultCode", 0, KPASSWD_RESULTS), 2463 StrField("resultString", ""), 2464 ] 2465 2466 2467class Kpasswd(Packet): 2468 @classmethod 2469 def dispatch_hook(cls, _pkt=None, *args, **kargs): 2470 if _pkt and len(_pkt) >= 4: 2471 if _pkt[2:4] == b"\xff\x80": 2472 return KPASSWD_REQ 2473 elif _pkt[2:4] == b"\x00\x01": 2474 asn1_tag = BER_id_dec(_pkt[6:8])[0] & 0x1F 2475 if asn1_tag == 14: 2476 return KPASSWD_REQ 2477 elif asn1_tag == 15: 2478 return KPASSWD_REP 2479 return KPASSWD_REQ 2480 2481 2482bind_bottom_up(UDP, Kpasswd, sport=464) 2483bind_bottom_up(UDP, Kpasswd, dport=464) 2484bind_top_down(UDP, KPASSWD_REQ, sport=464, dport=464) 2485bind_top_down(UDP, KPASSWD_REP, sport=464, dport=464) 2486 2487 2488class KpasswdTCPHeader(Packet): 2489 fields_desc = [LenField("len", None, fmt="!I")] 2490 2491 @classmethod 2492 def tcp_reassemble(cls, data, *args, **kwargs): 2493 if len(data) < 4: 2494 return None 2495 length = struct.unpack("!I", data[:4])[0] 2496 if len(data) == length + 4: 2497 return cls(data) 2498 2499 2500bind_layers(KpasswdTCPHeader, Kpasswd) 2501 2502bind_bottom_up(TCP, KpasswdTCPHeader, sport=464) 2503bind_layers(TCP, KpasswdTCPHeader, dport=464) 2504 2505 2506# Util functions 2507 2508 2509class KerberosClient(Automaton): 2510 RES_AS_MODE = namedtuple("AS_Result", ["asrep", "sessionkey", "kdcrep"]) 2511 RES_TGS_MODE = namedtuple("TGS_Result", ["tgsrep", "sessionkey", "kdcrep"]) 2512 2513 class MODE(IntEnum): 2514 AS_REQ = 0 2515 TGS_REQ = 1 2516 GET_SALT = 2 2517 2518 def __init__( 2519 self, 2520 mode=MODE.AS_REQ, 2521 ip=None, 2522 host=None, 2523 upn=None, 2524 password=None, 2525 realm=None, 2526 spn=None, 2527 ticket=None, 2528 renew=False, 2529 additional_tickets=[], 2530 u2u=False, 2531 for_user=None, 2532 s4u2proxy=False, 2533 etypes=None, 2534 key=None, 2535 port=88, 2536 timeout=5, 2537 **kwargs, 2538 ): 2539 import scapy.libs.rfc3961 # Trigger error if any # noqa: F401 2540 from scapy.layers.ldap import dclocator 2541 2542 if not upn: 2543 raise ValueError("Invalid upn") 2544 if not spn: 2545 raise ValueError("Invalid spn") 2546 if realm is None: 2547 if mode in [self.MODE.AS_REQ, self.MODE.GET_SALT]: 2548 _, realm = _parse_upn(upn) 2549 elif mode == self.MODE.TGS_REQ: 2550 _, realm = _parse_spn(spn) 2551 if not realm and ticket: 2552 # if no realm is specified, but there's a ticket, take the realm 2553 # of the ticket. 2554 realm = ticket.realm.val.decode() 2555 else: 2556 raise ValueError("Invalid realm") 2557 2558 if mode in [self.MODE.AS_REQ, self.MODE.GET_SALT]: 2559 if not host: 2560 raise ValueError("Invalid host") 2561 elif mode == self.MODE.TGS_REQ: 2562 if not ticket: 2563 raise ValueError("Invalid ticket") 2564 2565 if not ip: 2566 # No KDC IP provided. Find it by querying the DNS 2567 ip = dclocator( 2568 realm, 2569 timeout=timeout, 2570 # Use connect mode instead of ldap for compatibility 2571 # with MIT kerberos servers 2572 mode="connect", 2573 port=port, 2574 debug=kwargs.get("debug", 0), 2575 ).ip 2576 2577 if mode == self.MODE.GET_SALT: 2578 if etypes is not None: 2579 raise ValueError("Cannot specify etypes in GET_SALT mode !") 2580 2581 from scapy.libs.rfc3961 import EncryptionType 2582 2583 etypes = [ 2584 EncryptionType.AES256_CTS_HMAC_SHA1_96, 2585 EncryptionType.AES128_CTS_HMAC_SHA1_96, 2586 ] 2587 elif etypes is None: 2588 from scapy.libs.rfc3961 import EncryptionType 2589 2590 etypes = [ 2591 EncryptionType.AES256_CTS_HMAC_SHA1_96, 2592 EncryptionType.AES128_CTS_HMAC_SHA1_96, 2593 EncryptionType.RC4_HMAC, 2594 EncryptionType.DES_CBC_MD5, 2595 ] 2596 self.etypes = etypes 2597 2598 self.mode = mode 2599 2600 self.result = None # Result 2601 2602 self._timeout = timeout 2603 self._ip = ip 2604 self._port = port 2605 sock = self._connect() 2606 2607 if self.mode in [self.MODE.AS_REQ, self.MODE.GET_SALT]: 2608 self.host = host.upper() 2609 self.password = password and bytes_encode(password) 2610 self.spn = spn 2611 self.upn = upn 2612 self.realm = realm.upper() 2613 self.ticket = ticket 2614 self.renew = renew 2615 self.additional_tickets = additional_tickets # U2U + S4U2Proxy 2616 self.u2u = u2u # U2U 2617 self.for_user = for_user # FOR-USER 2618 self.s4u2proxy = s4u2proxy # S4U2Proxy 2619 self.key = key 2620 # See RFC4120 - sect 7.2.2 2621 # This marks whether we should follow-up after an EOF 2622 self.should_followup = False 2623 # Negotiated parameters 2624 self.pre_auth = False 2625 self.fxcookie = None 2626 super(KerberosClient, self).__init__( 2627 sock=sock, 2628 **kwargs, 2629 ) 2630 2631 def _connect(self): 2632 sock = socket.socket() 2633 sock.settimeout(self._timeout) 2634 sock.connect((self._ip, self._port)) 2635 sock = StreamSocket(sock, KerberosTCPHeader) 2636 return sock 2637 2638 def send(self, pkt): 2639 super(KerberosClient, self).send(KerberosTCPHeader() / pkt) 2640 2641 def _base_kdc_req(self, now_time): 2642 kdcreq = KRB_KDC_REQ_BODY( 2643 etype=[ASN1_INTEGER(x) for x in self.etypes], 2644 additionalTickets=None, 2645 # Windows default 2646 kdcOptions="forwardable+renewable+canonicalize", 2647 cname=None, 2648 realm=ASN1_GENERAL_STRING(self.realm), 2649 till=ASN1_GENERALIZED_TIME(now_time + timedelta(hours=10)), 2650 rtime=ASN1_GENERALIZED_TIME(now_time + timedelta(hours=10)), 2651 nonce=ASN1_INTEGER(RandNum(0, 0x7FFFFFFF)._fix()), 2652 ) 2653 if self.renew: 2654 kdcreq.kdcOptions.set(30, 1) # set 'renew' (bit 30) 2655 return kdcreq 2656 2657 def as_req(self): 2658 now_time = datetime.now(timezone.utc).replace(microsecond=0) 2659 2660 kdc_req = self._base_kdc_req(now_time=now_time) 2661 kdc_req.addresses = [ 2662 HostAddress( 2663 addrType=ASN1_INTEGER(20), # Netbios 2664 address=ASN1_STRING(self.host.ljust(16, " ")), 2665 ) 2666 ] 2667 kdc_req.cname = PrincipalName.fromUPN(self.upn) 2668 kdc_req.sname = PrincipalName.fromSPN(self.spn) 2669 2670 asreq = Kerberos( 2671 root=KRB_AS_REQ( 2672 padata=[ 2673 PADATA( 2674 padataType=ASN1_INTEGER(128), # PA-PAC-REQUEST 2675 padataValue=PA_PAC_REQUEST(includePac=ASN1_BOOLEAN(-1)), 2676 ) 2677 ], 2678 reqBody=kdc_req, 2679 ) 2680 ) 2681 # Pre-auth support 2682 if self.pre_auth: 2683 asreq.root.padata.insert( 2684 0, 2685 PADATA( 2686 padataType=0x2, # PA-ENC-TIMESTAMP 2687 padataValue=EncryptedData(), 2688 ), 2689 ) 2690 asreq.root.padata[0].padataValue.encrypt( 2691 self.key, PA_ENC_TS_ENC(patimestamp=ASN1_GENERALIZED_TIME(now_time)) 2692 ) 2693 # Cookie support 2694 if self.fxcookie: 2695 asreq.root.padata.insert( 2696 0, 2697 PADATA( 2698 padataType=133, # PA-FX-COOKIE 2699 padataValue=self.fxcookie, 2700 ), 2701 ) 2702 return asreq 2703 2704 def tgs_req(self): 2705 now_time = datetime.now(timezone.utc).replace(microsecond=0) 2706 2707 kdc_req = self._base_kdc_req(now_time=now_time) 2708 2709 _, crealm = _parse_upn(self.upn) 2710 authenticator = KRB_Authenticator( 2711 crealm=ASN1_GENERAL_STRING(crealm), 2712 cname=PrincipalName.fromUPN(self.upn), 2713 cksum=None, 2714 ctime=ASN1_GENERALIZED_TIME(now_time), 2715 cusec=ASN1_INTEGER(0), 2716 subkey=None, 2717 seqNumber=None, 2718 encAuthorizationData=None, 2719 ) 2720 2721 apreq = KRB_AP_REQ(ticket=self.ticket, authenticator=EncryptedData()) 2722 2723 # Additional tickets 2724 if self.additional_tickets: 2725 kdc_req.additionalTickets = self.additional_tickets 2726 2727 if self.u2u: # U2U 2728 kdc_req.kdcOptions.set(28, 1) # set 'enc-tkt-in-skey' (bit 28) 2729 2730 kdc_req.sname = PrincipalName.fromSPN(self.spn) 2731 2732 tgsreq = Kerberos( 2733 root=KRB_TGS_REQ( 2734 padata=[ 2735 PADATA( 2736 padataType=ASN1_INTEGER(1), # PA-TGS-REQ 2737 padataValue=apreq, 2738 ) 2739 ], 2740 reqBody=kdc_req, 2741 ) 2742 ) 2743 2744 # [MS-SFU] FOR-USER extension 2745 if self.for_user is not None: 2746 from scapy.libs.rfc3961 import ChecksumType 2747 2748 paforuser = PA_FOR_USER( 2749 userName=PrincipalName.fromUPN(self.for_user), 2750 userRealm=ASN1_GENERAL_STRING(_parse_upn(self.for_user)[1]), 2751 cksum=Checksum(), 2752 ) 2753 S4UByteArray = struct.pack( # [MS-SFU] sect 2.2.1 2754 "<I", paforuser.userName.nameType.val 2755 ) + ( 2756 ( 2757 "".join(x.val for x in paforuser.userName.nameString) 2758 + paforuser.userRealm.val 2759 + paforuser.authPackage.val 2760 ).encode() 2761 ) 2762 paforuser.cksum.make( 2763 self.key, 2764 S4UByteArray, 2765 cksumtype=ChecksumType.HMAC_MD5, 2766 ) 2767 tgsreq.root.padata.append( 2768 PADATA( 2769 padataType=ASN1_INTEGER(129), # PA-FOR-USER 2770 padataValue=paforuser, 2771 ) 2772 ) 2773 2774 # [MS-SFU] S4U2proxy - sect 3.1.5.2.1 2775 if self.s4u2proxy: 2776 # "PA-PAC-OPTIONS with resource-based constrained-delegation bit set" 2777 tgsreq.root.padata.append( 2778 PADATA( 2779 padataType=ASN1_INTEGER(167), # PA-PAC-OPTIONS 2780 padataValue=PA_PAC_OPTIONS( 2781 options="Resource-based-constrained-delegation", 2782 ), 2783 ) 2784 ) 2785 # "kdc-options field: MUST include the new cname-in-addl-tkt options flag" 2786 kdc_req.kdcOptions.set(14, 1) 2787 2788 # Compute checksum 2789 if self.key.cksumtype: 2790 authenticator.cksum = Checksum() 2791 authenticator.cksum.make( 2792 self.key, 2793 bytes(kdc_req), 2794 ) 2795 # Encrypt authenticator 2796 apreq.authenticator.encrypt(self.key, authenticator) 2797 return tgsreq 2798 2799 @ATMT.state(initial=1) 2800 def BEGIN(self): 2801 pass 2802 2803 @ATMT.condition(BEGIN) 2804 def should_send_as_req(self): 2805 if self.mode in [self.MODE.AS_REQ, self.MODE.GET_SALT]: 2806 raise self.SENT_AP_REQ() 2807 2808 @ATMT.condition(BEGIN) 2809 def should_send_tgs_req(self): 2810 if self.mode == self.MODE.TGS_REQ: 2811 raise self.SENT_TGS_REQ() 2812 2813 @ATMT.action(should_send_as_req) 2814 def send_as_req(self): 2815 self.send(self.as_req()) 2816 2817 @ATMT.action(should_send_tgs_req) 2818 def send_tgs_req(self): 2819 self.send(self.tgs_req()) 2820 2821 @ATMT.state() 2822 def SENT_AP_REQ(self): 2823 pass 2824 2825 @ATMT.state() 2826 def SENT_TGS_REQ(self): 2827 pass 2828 2829 def _process_padatas_and_key(self, padatas): 2830 from scapy.libs.rfc3961 import EncryptionType, Key 2831 2832 etype = None 2833 salt = b"" 2834 # Process pa-data 2835 if padatas is not None: 2836 for padata in padatas: 2837 if padata.padataType == 0x13 and etype is None: # PA-ETYPE-INFO2 2838 elt = padata.padataValue.seq[0] 2839 if elt.etype.val in self.etypes: 2840 etype = elt.etype.val 2841 if etype != EncryptionType.RC4_HMAC: 2842 salt = elt.salt.val 2843 elif padata.padataType == 133: # PA-FX-COOKIE 2844 self.fxcookie = padata.padataValue 2845 2846 etype = etype or self.etypes[0] 2847 # Compute key if not already provided 2848 if self.key is None: 2849 self.key = Key.string_to_key( 2850 etype, 2851 self.password, 2852 salt, 2853 ) 2854 2855 @ATMT.receive_condition(SENT_AP_REQ, prio=0) 2856 def receive_salt_mode(self, pkt): 2857 # This is only for "Salt-Mode", a mode where we get the salt then 2858 # exit. 2859 if self.mode == self.MODE.GET_SALT: 2860 if Kerberos not in pkt: 2861 raise self.FINAL() 2862 if not isinstance(pkt.root, KRB_ERROR): 2863 log_runtime.error("Pre-auth is likely disabled !") 2864 raise self.FINAL() 2865 if pkt.root.errorCode == 25: # KDC_ERR_PREAUTH_REQUIRED 2866 for padata in pkt.root.eData.seq: 2867 if padata.padataType == 0x13: # PA-ETYPE-INFO2 2868 elt = padata.padataValue.seq[0] 2869 if elt.etype.val in self.etypes: 2870 self.result = elt.salt.val 2871 raise self.FINAL() 2872 else: 2873 log_runtime.error("Failed to retrieve the salt !") 2874 raise self.FINAL() 2875 2876 @ATMT.receive_condition(SENT_AP_REQ, prio=1) 2877 def receive_krb_error_as_req(self, pkt): 2878 # We check for a PREAUTH_REQUIRED error. This means that preauth is required 2879 # and we need to do a second exchange. 2880 if Kerberos in pkt and isinstance(pkt.root, KRB_ERROR): 2881 if pkt.root.errorCode == 25: # KDC_ERR_PREAUTH_REQUIRED 2882 if not self.key and (not self.upn or not self.password): 2883 log_runtime.error( 2884 "Got 'KDC_ERR_PREAUTH_REQUIRED', " 2885 "but no key, nor upn+pass was passed." 2886 ) 2887 raise self.FINAL() 2888 self._process_padatas_and_key(pkt.root.eData.seq) 2889 self.should_followup = True 2890 self.pre_auth = True 2891 raise self.BEGIN() 2892 else: 2893 log_runtime.error("Received KRB_ERROR") 2894 pkt.show() 2895 raise self.FINAL() 2896 2897 @ATMT.receive_condition(SENT_AP_REQ, prio=2) 2898 def receive_as_rep(self, pkt): 2899 if Kerberos in pkt and isinstance(pkt.root, KRB_AS_REP): 2900 raise self.FINAL().action_parameters(pkt) 2901 2902 @ATMT.eof(SENT_AP_REQ) 2903 def retry_after_eof_in_apreq(self): 2904 if self.should_followup: 2905 # Reconnect and Restart 2906 self.should_followup = False 2907 self.update_sock(self._connect()) 2908 raise self.BEGIN() 2909 else: 2910 log_runtime.error("Socket was closed in an unexpected state") 2911 raise self.FINAL() 2912 2913 @ATMT.action(receive_as_rep) 2914 def decrypt_as_rep(self, pkt): 2915 self._process_padatas_and_key(pkt.root.padata) 2916 if not self.pre_auth: 2917 log_runtime.warning("Pre-authentication was disabled for this account !") 2918 # Decrypt 2919 enc = pkt.root.encPart 2920 res = enc.decrypt(self.key) 2921 self.result = self.RES_AS_MODE(pkt.root, res.key.toKey(), res) 2922 2923 @ATMT.receive_condition(SENT_TGS_REQ) 2924 def receive_krb_error_tgs_req(self, pkt): 2925 if Kerberos in pkt and isinstance(pkt.root, KRB_ERROR): 2926 log_runtime.warning("Received KRB_ERROR") 2927 pkt.show() 2928 raise self.FINAL() 2929 2930 @ATMT.receive_condition(SENT_TGS_REQ) 2931 def receive_tgs_rep(self, pkt): 2932 if Kerberos in pkt and isinstance(pkt.root, KRB_TGS_REP): 2933 if not self.renew and pkt.root.ticket.sname.nameString[0].val == b"krbtgt": 2934 log_runtime.warning("Received a cross-realm referral ticket !") 2935 raise self.FINAL().action_parameters(pkt) 2936 2937 @ATMT.action(receive_tgs_rep) 2938 def decrypt_tgs_rep(self, pkt): 2939 # Decrypt 2940 enc = pkt.root.encPart 2941 res = enc.decrypt(self.key) 2942 self.result = self.RES_TGS_MODE(pkt.root, res.key.toKey(), res) 2943 2944 @ATMT.state(final=1) 2945 def FINAL(self): 2946 pass 2947 2948 2949def _parse_upn(upn): 2950 m = re.match(r"^([^@\\/]+)(@|\\|/)([^@\\/]+)$", upn) 2951 if not m: 2952 raise ValueError("Invalid UPN: '%s'" % upn) 2953 if m.group(2) == "@": 2954 user = m.group(1) 2955 domain = m.group(3) 2956 else: 2957 user = m.group(3) 2958 domain = m.group(1) 2959 return user, domain 2960 2961 2962def _parse_spn(spn): 2963 m = re.match(r"^((?:[^@\\/]+)/(?:[^@\\/]+))(?:@([^@\\/]+))?$", spn) 2964 if not m: 2965 raise ValueError("Invalid SPN: '%s'" % spn) 2966 return m.group(1), m.group(2) 2967 2968 2969def krb_as_req( 2970 upn, spn=None, ip=None, key=None, password=None, realm=None, host="WIN10", **kwargs 2971): 2972 r""" 2973 Kerberos AS-Req 2974 2975 :param upn: the user principal name formatted as "DOMAIN\user", "DOMAIN/user" 2976 or "user@DOMAIN" 2977 :param spn: (optional) the full service principal name. 2978 Defaults to "krbtgt/<realm>" 2979 :param ip: the KDC ip. (optional. If not provided, Scapy will query the DNS for 2980 _kerberos._tcp.dc._msdcs.domain.local). 2981 :param key: (optional) pass the Key object. 2982 :param password: (optional) otherwise, pass the user's password 2983 :param realm: (optional) the realm to use. Otherwise use the one from UPN. 2984 :param host: (optional) the host performing the AS-Req. WIN10 by default. 2985 2986 :return: returns a named tuple (asrep=<...>, sessionkey=<...>) 2987 2988 Example:: 2989 2990 >>> # The KDC is on 192.168.122.17, we ask a TGT for user1 2991 >>> krb_as_req("user1@DOMAIN.LOCAL", "192.168.122.17", password="Password1") 2992 2993 Equivalent:: 2994 2995 >>> from scapy.libs.rfc3961 import Key, EncryptionType 2996 >>> key = Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=hex_bytes("6d0748c546 2997 ...: f4e99205e78f8da7681d4ec5520ae4815543720c2a647c1ae814c9")) 2998 >>> krb_as_req("user1@DOMAIN.LOCAL", "192.168.122.17", key=key) 2999 """ 3000 if realm is None: 3001 _, realm = _parse_upn(upn) 3002 if key is None: 3003 if password is None: 3004 try: 3005 from prompt_toolkit import prompt 3006 3007 password = prompt("Enter password: ", is_password=True) 3008 except ImportError: 3009 password = input("Enter password: ") 3010 cli = KerberosClient( 3011 mode=KerberosClient.MODE.AS_REQ, 3012 realm=realm, 3013 ip=ip, 3014 spn=spn or "krbtgt/" + realm, 3015 host=host, 3016 upn=upn, 3017 password=password, 3018 key=key, 3019 **kwargs, 3020 ) 3021 cli.run() 3022 cli.stop() 3023 return cli.result 3024 3025 3026def krb_tgs_req( 3027 upn, 3028 spn, 3029 sessionkey, 3030 ticket, 3031 ip=None, 3032 renew=False, 3033 realm=None, 3034 additional_tickets=[], 3035 u2u=False, 3036 etypes=None, 3037 for_user=None, 3038 s4u2proxy=False, 3039 **kwargs, 3040): 3041 r""" 3042 Kerberos TGS-Req 3043 3044 :param upn: the user principal name formatted as "DOMAIN\user", "DOMAIN/user" 3045 or "user@DOMAIN" 3046 :param spn: the full service principal name (e.g. "cifs/srv1") 3047 :param sessionkey: the session key retrieved from the tgt 3048 :param ticket: the tgt ticket 3049 :param ip: the KDC ip. (optional. If not provided, Scapy will query the DNS for 3050 _kerberos._tcp.dc._msdcs.domain.local). 3051 :param renew: ask for renewal 3052 :param realm: (optional) the realm to use. Otherwise use the one from SPN. 3053 :param additional_tickets: (optional) a list of additional tickets to pass. 3054 :param u2u: (optional) if specified, enable U2U and request the ticket to be 3055 signed using the session key from the first additional ticket. 3056 :param etypes: array of EncryptionType values. 3057 By default: AES128, AES256, RC4, DES_MD5 3058 :param for_user: a user principal name to request the ticket for. This is the 3059 S4U2Self extension. 3060 3061 :return: returns a named tuple (tgsrep=<...>, sessionkey=<...>) 3062 3063 Example:: 3064 3065 >>> # The KDC is on 192.168.122.17, we ask a TGT for user1 3066 >>> krb_as_req("user1@DOMAIN.LOCAL", "192.168.122.17", password="Password1") 3067 3068 Equivalent:: 3069 3070 >>> from scapy.libs.rfc3961 import Key, EncryptionType 3071 >>> key = Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=hex_bytes("6d0748c546 3072 ...: f4e99205e78f8da7681d4ec5520ae4815543720c2a647c1ae814c9")) 3073 >>> krb_as_req("user1@DOMAIN.LOCAL", "192.168.122.17", key=key) 3074 """ 3075 cli = KerberosClient( 3076 mode=KerberosClient.MODE.TGS_REQ, 3077 realm=realm, 3078 upn=upn, 3079 ip=ip, 3080 spn=spn, 3081 key=sessionkey, 3082 ticket=ticket, 3083 renew=renew, 3084 additional_tickets=additional_tickets, 3085 u2u=u2u, 3086 etypes=etypes, 3087 for_user=for_user, 3088 s4u2proxy=s4u2proxy, 3089 **kwargs, 3090 ) 3091 cli.run() 3092 cli.stop() 3093 return cli.result 3094 3095 3096def krb_as_and_tgs(upn, spn, ip=None, key=None, password=None, **kwargs): 3097 """ 3098 Kerberos AS-Req then TGS-Req 3099 """ 3100 res = krb_as_req(upn=upn, ip=ip, key=key, password=password, **kwargs) 3101 if not res: 3102 return 3103 return krb_tgs_req( 3104 upn=upn, 3105 spn=spn, 3106 sessionkey=res.sessionkey, 3107 ticket=res.asrep.ticket, 3108 ip=ip, 3109 **kwargs, 3110 ) 3111 3112 3113def krb_get_salt(upn, ip=None, realm=None, host="WIN10", **kwargs): 3114 """ 3115 Kerberos AS-Req only to get the salt associated with the UPN. 3116 """ 3117 if realm is None: 3118 _, realm = _parse_upn(upn) 3119 cli = KerberosClient( 3120 mode=KerberosClient.MODE.GET_SALT, 3121 realm=realm, 3122 ip=ip, 3123 spn="krbtgt/" + realm, 3124 upn=upn, 3125 host=host, 3126 **kwargs, 3127 ) 3128 cli.run() 3129 cli.stop() 3130 return cli.result 3131 3132 3133def kpasswd( 3134 upn, 3135 targetupn=None, 3136 ip=None, 3137 password=None, 3138 newpassword=None, 3139 key=None, 3140 ticket=None, 3141 realm=None, 3142 ssp=None, 3143 setpassword=None, 3144 timeout=3, 3145 port=464, 3146 debug=0, 3147 **kwargs, 3148): 3149 """ 3150 Change a password using RFC3244's Kerberos Set / Change Password. 3151 3152 :param upn: the UPN to use for authentication 3153 :param targetupn: (optional) the UPN to change the password of. If not specified, 3154 same as upn. 3155 :param ip: the KDC ip. (optional. If not provided, Scapy will query the DNS for 3156 _kerberos._tcp.dc._msdcs.domain.local). 3157 :param key: (optional) pass the Key object. 3158 :param ticket: (optional) a ticket to use. Either a TGT or ST for kadmin/changepw. 3159 :param password: (optional) otherwise, pass the user's password 3160 :param realm: (optional) the realm to use. Otherwise use the one from UPN. 3161 :param setpassword: (optional) use "Set Password" mechanism. 3162 :param ssp: (optional) a Kerberos SSP for the service kadmin/changepw@REALM. 3163 If provided, you probably don't need anything else. Otherwise built. 3164 """ 3165 from scapy.layers.ldap import dclocator 3166 3167 if not realm: 3168 _, realm = _parse_upn(upn) 3169 spn = "kadmin/changepw@%s" % realm 3170 if ip is None: 3171 ip = dclocator( 3172 realm, 3173 timeout=timeout, 3174 # Use connect mode instead of ldap for compatibility 3175 # with MIT kerberos servers 3176 mode="connect", 3177 port=port, 3178 debug=debug, 3179 ).ip 3180 if ssp is None and ticket is not None: 3181 tktspn = ticket.getSPN().split("/")[0] 3182 assert tktspn in ["krbtgt", "kadmin"], "Unexpected ticket type ! %s" % tktspn 3183 if tktspn == "krbtgt": 3184 log_runtime.info( 3185 "Using 'Set Password' mode. This only works with admin privileges." 3186 ) 3187 setpassword = True 3188 resp = krb_tgs_req( 3189 upn=upn, 3190 spn=spn, 3191 ticket=ticket, 3192 sessionkey=key, 3193 ip=ip, 3194 debug=debug, 3195 ) 3196 if resp is None: 3197 return 3198 ticket = resp.tgsrep.ticket 3199 key = resp.sessionkey 3200 if setpassword is None: 3201 setpassword = bool(targetupn) 3202 elif setpassword and targetupn is None: 3203 targetupn = upn 3204 assert setpassword or not targetupn, "Cannot use targetupn in changepassword mode !" 3205 # Get a ticket for kadmin/changepw 3206 if ssp is None: 3207 if ticket is None: 3208 # Get a ticket for kadmin/changepw through AS-REQ 3209 resp = krb_as_req( 3210 upn=upn, 3211 spn=spn, 3212 key=key, 3213 ip=ip, 3214 password=password, 3215 debug=debug, 3216 ) 3217 if resp is None: 3218 return 3219 ticket = resp.asrep.ticket 3220 key = resp.sessionkey 3221 ssp = KerberosSSP( 3222 UPN=upn, 3223 SPN=spn, 3224 ST=ticket, 3225 KEY=key, 3226 DC_IP=ip, 3227 debug=debug, 3228 **kwargs, 3229 ) 3230 Context, tok, negResult = ssp.GSS_Init_sec_context( 3231 None, 3232 req_flags=0, # No GSS_C_MUTUAL_FLAG 3233 ) 3234 if negResult != GSS_S_CONTINUE_NEEDED: 3235 warning("SSP failed on initial GSS_Init_sec_context !") 3236 if tok: 3237 tok.show() 3238 return 3239 apreq = tok.innerToken.root 3240 # Connect 3241 sock = socket.socket() 3242 sock.settimeout(timeout) 3243 sock.connect((ip, port)) 3244 sock = StreamSocket(sock, KpasswdTCPHeader) 3245 # Do KPASSWD request 3246 if newpassword is None: 3247 try: 3248 from prompt_toolkit import prompt 3249 3250 newpassword = prompt("Enter NEW password: ", is_password=True) 3251 except ImportError: 3252 newpassword = input("Enter NEW password: ") 3253 krbpriv = KRB_PRIV(encPart=EncryptedData()) 3254 krbpriv.encPart.encrypt( 3255 Context.KrbSessionKey, 3256 EncKrbPrivPart( 3257 sAddress=HostAddress( 3258 addrType=ASN1_INTEGER(2), # IPv4 3259 address=ASN1_STRING(b"\xc0\xa8\x00e"), 3260 ), 3261 userData=ASN1_STRING( 3262 bytes( 3263 ChangePasswdData( 3264 newpasswd=newpassword, 3265 targname=PrincipalName.fromUPN(targetupn), 3266 targrealm=realm, 3267 ) 3268 ) 3269 if setpassword 3270 else newpassword 3271 ), 3272 timestamp=None, 3273 usec=None, 3274 seqNumber=Context.SendSeqNum, 3275 ), 3276 ) 3277 resp = sock.sr1( 3278 KpasswdTCPHeader() 3279 / KPASSWD_REQ( 3280 pvno=0xFF80 if setpassword else 1, 3281 apreq=apreq, 3282 krbpriv=krbpriv, 3283 ), 3284 timeout=timeout, 3285 verbose=0, 3286 ) 3287 # Verify KPASSWD response 3288 if not resp: 3289 raise TimeoutError("KPASSWD_REQ timed out !") 3290 if KPASSWD_REP not in resp: 3291 resp.show() 3292 raise ValueError("Invalid response to KPASSWD_REQ !") 3293 Context, tok, negResult = ssp.GSS_Init_sec_context(Context, resp.aprep) 3294 if negResult != GSS_S_COMPLETE: 3295 warning("SSP failed on subsequent GSS_Init_sec_context !") 3296 if tok: 3297 tok.show() 3298 return 3299 # Parse answer KRB_PRIV 3300 krbanswer = resp.krbpriv.encPart.decrypt(Context.KrbSessionKey) 3301 userRep = KPasswdRepData(krbanswer.userData.val) 3302 if userRep.resultCode != 0: 3303 warning(userRep.sprintf("KPASSWD failed !")) 3304 userRep.show() 3305 return 3306 print(userRep.sprintf("%resultCode%")) 3307 3308 3309# SSP 3310 3311 3312class KerberosSSP(SSP): 3313 """ 3314 The KerberosSSP 3315 3316 Client settings: 3317 3318 :param ST: the service ticket to use for access. 3319 If not provided, will be retrieved 3320 :param SPN: the SPN of the service to use 3321 :param UPN: The client UPN 3322 :param DC_IP: (optional) is ST+KEY are not provided, will need to contact 3323 the KDC at this IP. If not provided, will perform dc locator. 3324 :param TGT: (optional) pass a TGT to use to get the ST. 3325 :param KEY: the session key associated with the ST if it is provided, 3326 OR the session key associated with the TGT 3327 OR the kerberos key associated with the UPN 3328 :param PASSWORD: (optional) if a UPN is provided and not a KEY, this is the 3329 password of the UPN. 3330 :param U2U: (optional) use U2U when requesting the ST. 3331 3332 Server settings: 3333 3334 :param SPN: the SPN of the service to use 3335 :param KEY: the kerberos key to use to decrypt the AP-req 3336 :param TGT: (optional) pass a TGT to use for U2U 3337 :param DC_IP: (optional) if TGT is not provided, request one on the KDC at 3338 this IP using using the KEY when using U2U. 3339 :param REQUIRE_U2U: (optional, default False) require U2U 3340 """ 3341 3342 oid = "1.2.840.113554.1.2.2" 3343 auth_type = 0x10 3344 3345 class STATE(SSP.STATE): 3346 INIT = 1 3347 CLI_SENT_TGTREQ = 2 3348 CLI_SENT_APREQ = 3 3349 CLI_RCVD_APREP = 4 3350 SRV_SENT_APREP = 5 3351 3352 class CONTEXT(SSP.CONTEXT): 3353 __slots__ = [ 3354 "SessionKey", 3355 "ServerHostname", 3356 "U2U", 3357 "KrbSessionKey", # raw Key object 3358 "STSessionKey", # raw ST Key object (for DCE_STYLE) 3359 "SeqNum", # for AP 3360 "SendSeqNum", # for MIC 3361 "RecvSeqNum", # for MIC 3362 "IsAcceptor", 3363 "SendSealKeyUsage", 3364 "SendSignKeyUsage", 3365 "RecvSealKeyUsage", 3366 "RecvSignKeyUsage", 3367 ] 3368 3369 def __init__(self, IsAcceptor, req_flags=None): 3370 self.state = KerberosSSP.STATE.INIT 3371 self.SessionKey = None 3372 self.ServerHostname = None 3373 self.U2U = False 3374 self.SendSeqNum = 0 3375 self.RecvSeqNum = 0 3376 self.KrbSessionKey = None 3377 self.STSessionKey = None 3378 self.IsAcceptor = IsAcceptor 3379 # [RFC 4121] sect 2 3380 if IsAcceptor: 3381 self.SendSealKeyUsage = 22 3382 self.SendSignKeyUsage = 23 3383 self.RecvSealKeyUsage = 24 3384 self.RecvSignKeyUsage = 25 3385 else: 3386 self.SendSealKeyUsage = 24 3387 self.SendSignKeyUsage = 25 3388 self.RecvSealKeyUsage = 22 3389 self.RecvSignKeyUsage = 23 3390 super(KerberosSSP.CONTEXT, self).__init__(req_flags=req_flags) 3391 3392 def clifailure(self): 3393 self.__init__(self.IsAcceptor, req_flags=self.flags) 3394 3395 def __repr__(self): 3396 if self.U2U: 3397 return "KerberosSSP-U2U" 3398 return "KerberosSSP" 3399 3400 def __init__( 3401 self, 3402 ST=None, 3403 UPN=None, 3404 PASSWORD=None, 3405 U2U=False, 3406 KEY=None, 3407 SPN=None, 3408 TGT=None, 3409 DC_IP=None, 3410 REQUIRE_U2U=False, 3411 SKEY_TYPE=None, 3412 debug=0, 3413 **kwargs, 3414 ): 3415 self.ST = ST 3416 self.UPN = UPN 3417 self.KEY = KEY 3418 self.SPN = SPN 3419 self.TGT = TGT 3420 self.PASSWORD = PASSWORD 3421 self.U2U = U2U 3422 self.DC_IP = DC_IP 3423 self.REQUIRE_U2U = REQUIRE_U2U 3424 self.debug = debug 3425 if SKEY_TYPE is None: 3426 from scapy.libs.rfc3961 import EncryptionType 3427 3428 SKEY_TYPE = EncryptionType.AES128_CTS_HMAC_SHA1_96 3429 self.SKEY_TYPE = SKEY_TYPE 3430 super(KerberosSSP, self).__init__(**kwargs) 3431 3432 def GSS_GetMICEx(self, Context, msgs, qop_req=0): 3433 """ 3434 [MS-KILE] sect 3.4.5.6 3435 3436 - AES: RFC4121 sect 4.2.6.1 3437 """ 3438 if Context.KrbSessionKey.etype in [17, 18]: # AES 3439 # Concatenate the ToSign 3440 ToSign = b"".join(x.data for x in msgs if x.sign) 3441 sig = KRB_InnerToken( 3442 TOK_ID=b"\x04\x04", 3443 root=KRB_GSS_MIC( 3444 Flags="AcceptorSubkey" 3445 + ("+SentByAcceptor" if Context.IsAcceptor else ""), 3446 SND_SEQ=Context.SendSeqNum, 3447 ), 3448 ) 3449 ToSign += bytes(sig)[:16] 3450 sig.root.SGN_CKSUM = Context.KrbSessionKey.make_checksum( 3451 keyusage=Context.SendSignKeyUsage, 3452 text=ToSign, 3453 ) 3454 else: 3455 raise NotImplementedError 3456 Context.SendSeqNum += 1 3457 return sig 3458 3459 def GSS_VerifyMICEx(self, Context, msgs, signature): 3460 """ 3461 [MS-KILE] sect 3.4.5.7 3462 3463 - AES: RFC4121 sect 4.2.6.1 3464 """ 3465 Context.RecvSeqNum = signature.root.SND_SEQ 3466 if Context.KrbSessionKey.etype in [17, 18]: # AES 3467 # Concatenate the ToSign 3468 ToSign = b"".join(x.data for x in msgs if x.sign) 3469 ToSign += bytes(signature)[:16] 3470 sig = Context.KrbSessionKey.make_checksum( 3471 keyusage=Context.RecvSignKeyUsage, 3472 text=ToSign, 3473 ) 3474 else: 3475 raise NotImplementedError 3476 if sig != signature.root.SGN_CKSUM: 3477 raise ValueError("ERROR: Checksums don't match") 3478 3479 def GSS_WrapEx(self, Context, msgs, qop_req=0): 3480 """ 3481 [MS-KILE] sect 3.4.5.4 3482 3483 - AES: RFC4121 sect 4.2.6.2 and [MS-KILE] sect 3.4.5.4.1 3484 - HMAC-RC4: RFC4757 sect 7.3 and [MS-KILE] sect 3.4.5.4.1 3485 """ 3486 # Is confidentiality in use? 3487 confidentiality = (Context.flags & GSS_C_FLAGS.GSS_C_CONF_FLAG) and any( 3488 x.conf_req_flag for x in msgs 3489 ) 3490 if Context.KrbSessionKey.etype in [17, 18]: # AES 3491 # Build token 3492 tok = KRB_InnerToken( 3493 TOK_ID=b"\x05\x04", 3494 root=KRB_GSS_Wrap( 3495 Flags="AcceptorSubkey" 3496 + ("+SentByAcceptor" if Context.IsAcceptor else "") 3497 + ("+Sealed" if confidentiality else ""), 3498 SND_SEQ=Context.SendSeqNum, 3499 RRC=0, 3500 ), 3501 ) 3502 Context.SendSeqNum += 1 3503 # Real separation starts now: RFC4121 sect 4.2.4 3504 if confidentiality: 3505 # Confidentiality is requested (see RFC4121 sect 4.3) 3506 # {"header" | encrypt(plaintext-data | filler | "header")} 3507 # 0. Roll confounder 3508 Confounder = os.urandom(Context.KrbSessionKey.ep.blocksize) 3509 # 1. Concatenate the data to be encrypted 3510 Data = b"".join(x.data for x in msgs if x.conf_req_flag) 3511 DataLen = len(Data) 3512 # 2. Add filler 3513 tok.root.EC = ((-DataLen) % Context.KrbSessionKey.ep.blocksize) or 16 3514 Filler = b"\x00" * tok.root.EC 3515 Data += Filler 3516 # 3. Add first 16 octets of the Wrap token "header" 3517 PlainHeader = bytes(tok)[:16] 3518 Data += PlainHeader 3519 # 4. Build 'ToSign', exclusively used for checksum 3520 ToSign = Confounder 3521 ToSign += b"".join(x.data for x in msgs if x.sign) 3522 ToSign += Filler 3523 ToSign += PlainHeader 3524 # 5. Finalize token for signing 3525 # "The RRC field is [...] 28 if encryption is requested." 3526 tok.root.RRC = 28 3527 # 6. encrypt() is the encryption operation (which provides for 3528 # integrity protection) 3529 Data = Context.KrbSessionKey.encrypt( 3530 keyusage=Context.SendSealKeyUsage, 3531 plaintext=Data, 3532 confounder=Confounder, 3533 signtext=ToSign, 3534 ) 3535 # 7. Rotate 3536 Data = strrot(Data, tok.root.RRC + tok.root.EC) 3537 # 8. Split (token and encrypted messages) 3538 toklen = len(Data) - DataLen 3539 tok.root.Data = Data[:toklen] 3540 offset = toklen 3541 for msg in msgs: 3542 msglen = len(msg.data) 3543 if msg.conf_req_flag: 3544 msg.data = Data[offset : offset + msglen] 3545 offset += msglen 3546 return msgs, tok 3547 else: 3548 # No confidentiality is requested 3549 # {"header" | plaintext-data | get_mic(plaintext-data | "header")} 3550 # 0. Concatenate the data 3551 Data = b"".join(x.data for x in msgs if x.sign) 3552 DataLen = len(Data) 3553 # 1. Add first 16 octets of the Wrap token "header" 3554 ToSign = Data 3555 ToSign += bytes(tok)[:16] 3556 # 2. get_mic() is the checksum operation for the required 3557 # checksum mechanism 3558 Mic = Context.KrbSessionKey.make_checksum( 3559 keyusage=Context.SendSealKeyUsage, 3560 text=ToSign, 3561 ) 3562 # In Wrap tokens without confidentiality, the EC field SHALL be used 3563 # to encode the number of octets in the trailing checksum 3564 tok.root.EC = 12 # len(tok.root.Data) == 12 for AES 3565 # "The RRC field ([RFC4121] section 4.2.5) is 12 if no encryption 3566 # is requested" 3567 tok.root.RRC = 12 3568 # 3. Concat and pack 3569 for msg in msgs: 3570 if msg.sign: 3571 msg.data = b"" 3572 Data = Data + Mic 3573 # 4. Rotate 3574 tok.root.Data = strrot(Data, tok.root.RRC) 3575 return msgs, tok 3576 elif Context.KrbSessionKey.etype in [23, 24]: # RC4 3577 from scapy.libs.rfc3961 import ( 3578 Cipher, 3579 Hmac_MD5, 3580 _rfc1964pad, 3581 decrepit_algorithms, 3582 ) 3583 3584 # Build token 3585 seq = struct.pack(">I", Context.SendSeqNum) 3586 tok = KRB_InnerToken( 3587 TOK_ID=b"\x02\x01", 3588 root=KRB_GSS_Wrap_RFC1964( 3589 SGN_ALG="HMAC", 3590 SEAL_ALG="RC4" if confidentiality else "none", 3591 SND_SEQ=seq 3592 + ( 3593 # See errata 3594 b"\xff\xff\xff\xff" 3595 if Context.IsAcceptor 3596 else b"\x00\x00\x00\x00" 3597 ), 3598 ), 3599 ) 3600 Context.SendSeqNum += 1 3601 # 0. Concatenate data 3602 ToSign = _rfc1964pad(b"".join(x.data for x in msgs if x.sign)) 3603 ToEncrypt = b"".join(x.data for x in msgs if x.conf_req_flag) 3604 Kss = Context.KrbSessionKey.key 3605 # 1. Roll confounder 3606 Confounder = os.urandom(8) 3607 # 2. Compute the 'Kseq' key 3608 Klocal = strxor(Kss, len(Kss) * b"\xf0") 3609 if Context.KrbSessionKey.etype == 24: # EXP 3610 Kcrypt = Hmac_MD5(Klocal).digest(b"fortybits\x00" + b"\x00\x00\x00\x00") 3611 Kcrypt = Kcrypt[:7] + b"\xab" * 9 3612 else: 3613 Kcrypt = Hmac_MD5(Klocal).digest(b"\x00\x00\x00\x00") 3614 Kcrypt = Hmac_MD5(Kcrypt).digest(seq) 3615 # 3. Build SGN_CKSUM 3616 tok.root.SGN_CKSUM = Context.KrbSessionKey.make_checksum( 3617 keyusage=13, # See errata 3618 text=bytes(tok)[:8] + Confounder + ToSign, 3619 )[:8] 3620 # 4. Populate token + encrypt 3621 if confidentiality: 3622 # 'encrypt' is requested 3623 rc4 = Cipher(decrepit_algorithms.ARC4(Kcrypt), mode=None).encryptor() 3624 tok.root.CONFOUNDER = rc4.update(Confounder) 3625 Data = rc4.update(ToEncrypt) 3626 # Split encrypted data 3627 offset = 0 3628 for msg in msgs: 3629 msglen = len(msg.data) 3630 if msg.conf_req_flag: 3631 msg.data = Data[offset : offset + msglen] 3632 offset += msglen 3633 else: 3634 # 'encrypt' is not requested 3635 tok.root.CONFOUNDER = Confounder 3636 # 5. Compute the 'Kseq' key 3637 if Context.KrbSessionKey.etype == 24: # EXP 3638 Kseq = Hmac_MD5(Kss).digest(b"fortybits\x00" + b"\x00\x00\x00\x00") 3639 Kseq = Kseq[:7] + b"\xab" * 9 3640 else: 3641 Kseq = Hmac_MD5(Kss).digest(b"\x00\x00\x00\x00") 3642 Kseq = Hmac_MD5(Kseq).digest(tok.root.SGN_CKSUM) 3643 # 6. Encrypt 'SND_SEQ' 3644 rc4 = Cipher(decrepit_algorithms.ARC4(Kseq), mode=None).encryptor() 3645 tok.root.SND_SEQ = rc4.update(tok.root.SND_SEQ) 3646 # 7. Include 'InitialContextToken pseudo ASN.1 header' 3647 tok = KRB_GSSAPI_Token( 3648 MechType="1.2.840.113554.1.2.2", # Kerberos 5 3649 innerToken=tok, 3650 ) 3651 return msgs, tok 3652 else: 3653 raise NotImplementedError 3654 3655 def GSS_UnwrapEx(self, Context, msgs, signature): 3656 """ 3657 [MS-KILE] sect 3.4.5.5 3658 3659 - AES: RFC4121 sect 4.2.6.2 3660 - HMAC-RC4: RFC4757 sect 7.3 3661 """ 3662 if Context.KrbSessionKey.etype in [17, 18]: # AES 3663 confidentiality = signature.root.Flags.Sealed 3664 # Real separation starts now: RFC4121 sect 4.2.4 3665 if confidentiality: 3666 # 0. Concatenate the data 3667 Data = signature.root.Data 3668 Data += b"".join(x.data for x in msgs if x.conf_req_flag) 3669 # 1. Un-Rotate 3670 Data = strrot(Data, signature.root.RRC + signature.root.EC, right=False) 3671 3672 # 2. Function to build 'ToSign', exclusively used for checksum 3673 def MakeToSign(Confounder, DecText): 3674 offset = 0 3675 # 2.a Confounder 3676 ToSign = Confounder 3677 # 2.b Messages 3678 for msg in msgs: 3679 msglen = len(msg.data) 3680 if msg.conf_req_flag: 3681 ToSign += DecText[offset : offset + msglen] 3682 offset += msglen 3683 elif msg.sign: 3684 ToSign += msg.data 3685 # 2.c Filler & Padding 3686 ToSign += DecText[offset:] 3687 return ToSign 3688 3689 # 3. Decrypt 3690 Data = Context.KrbSessionKey.decrypt( 3691 keyusage=Context.RecvSealKeyUsage, 3692 ciphertext=Data, 3693 presignfunc=MakeToSign, 3694 ) 3695 # 4. Split 3696 Data, f16header = ( 3697 Data[:-16], 3698 Data[-16:], 3699 ) 3700 # 5. Check header 3701 hdr = signature.copy() 3702 hdr.root.RRC = 0 3703 if f16header != bytes(hdr)[:16]: 3704 raise ValueError("ERROR: Headers don't match") 3705 # 6. Split (and ignore filler) 3706 offset = 0 3707 for msg in msgs: 3708 msglen = len(msg.data) 3709 if msg.conf_req_flag: 3710 msg.data = Data[offset : offset + msglen] 3711 offset += msglen 3712 # Case without msgs 3713 if len(msgs) == 1 and not msgs[0].data: 3714 msgs[0].data = Data 3715 return msgs 3716 else: 3717 # No confidentiality is requested 3718 # 0. Concatenate the data 3719 Data = signature.root.Data 3720 Data += b"".join(x.data for x in msgs if x.sign) 3721 # 1. Un-Rotate 3722 Data = strrot(Data, signature.root.RRC, right=False) 3723 # 2. Split 3724 Data, Mic = Data[: -signature.root.EC], Data[-signature.root.EC :] 3725 # "Both the EC field and the RRC field in 3726 # the token header SHALL be filled with zeroes for the purpose of 3727 # calculating the checksum." 3728 ToSign = Data 3729 hdr = signature.copy() 3730 hdr.root.RRC = 0 3731 hdr.root.EC = 0 3732 # Concatenate the data 3733 ToSign += bytes(hdr)[:16] 3734 # 3. Calculate the signature 3735 sig = Context.KrbSessionKey.make_checksum( 3736 keyusage=Context.RecvSealKeyUsage, 3737 text=ToSign, 3738 ) 3739 # 4. Compare 3740 if sig != Mic: 3741 raise ValueError("ERROR: Checksums don't match") 3742 # Case without msgs 3743 if len(msgs) == 1 and not msgs[0].data: 3744 msgs[0].data = Data 3745 return msgs 3746 elif Context.KrbSessionKey.etype in [23, 24]: # RC4 3747 from scapy.libs.rfc3961 import ( 3748 Cipher, 3749 Hmac_MD5, 3750 _rfc1964pad, 3751 decrepit_algorithms, 3752 ) 3753 3754 # Drop wrapping 3755 tok = signature.innerToken 3756 3757 # Detect confidentiality 3758 confidentiality = tok.root.SEAL_ALG != 0xFFFF 3759 3760 # 0. Concatenate data 3761 ToDecrypt = b"".join(x.data for x in msgs if x.conf_req_flag) 3762 Kss = Context.KrbSessionKey.key 3763 # 1. Compute the 'Kseq' key 3764 if Context.KrbSessionKey.etype == 24: # EXP 3765 Kseq = Hmac_MD5(Kss).digest(b"fortybits\x00" + b"\x00\x00\x00\x00") 3766 Kseq = Kseq[:7] + b"\xab" * 9 3767 else: 3768 Kseq = Hmac_MD5(Kss).digest(b"\x00\x00\x00\x00") 3769 Kseq = Hmac_MD5(Kseq).digest(tok.root.SGN_CKSUM) 3770 # 2. Decrypt 'SND_SEQ' 3771 rc4 = Cipher(decrepit_algorithms.ARC4(Kseq), mode=None).encryptor() 3772 seq = rc4.update(tok.root.SND_SEQ)[:4] 3773 # 3. Compute the 'Kcrypt' key 3774 Klocal = strxor(Kss, len(Kss) * b"\xf0") 3775 if Context.KrbSessionKey.etype == 24: # EXP 3776 Kcrypt = Hmac_MD5(Klocal).digest(b"fortybits\x00" + b"\x00\x00\x00\x00") 3777 Kcrypt = Kcrypt[:7] + b"\xab" * 9 3778 else: 3779 Kcrypt = Hmac_MD5(Klocal).digest(b"\x00\x00\x00\x00") 3780 Kcrypt = Hmac_MD5(Kcrypt).digest(seq) 3781 # 4. Decrypt 3782 if confidentiality: 3783 # 'encrypt' was requested 3784 rc4 = Cipher(decrepit_algorithms.ARC4(Kcrypt), mode=None).encryptor() 3785 Confounder = rc4.update(tok.root.CONFOUNDER) 3786 Data = rc4.update(ToDecrypt) 3787 # Split encrypted data 3788 offset = 0 3789 for msg in msgs: 3790 msglen = len(msg.data) 3791 if msg.conf_req_flag: 3792 msg.data = Data[offset : offset + msglen] 3793 offset += msglen 3794 else: 3795 # 'encrypt' was not requested 3796 Confounder = tok.root.CONFOUNDER 3797 # 5. Verify SGN_CKSUM 3798 ToSign = _rfc1964pad(b"".join(x.data for x in msgs if x.sign)) 3799 Context.KrbSessionKey.verify_checksum( 3800 keyusage=13, # See errata 3801 text=bytes(tok)[:8] + Confounder + ToSign, 3802 cksum=tok.root.SGN_CKSUM, 3803 ) 3804 return msgs 3805 else: 3806 raise NotImplementedError 3807 3808 def GSS_Init_sec_context( 3809 self, Context: CONTEXT, val=None, req_flags: Optional[GSS_C_FLAGS] = None 3810 ): 3811 if Context is None: 3812 # New context 3813 Context = self.CONTEXT(IsAcceptor=False, req_flags=req_flags) 3814 3815 from scapy.libs.rfc3961 import Key 3816 3817 if Context.state == self.STATE.INIT and self.U2U: 3818 # U2U - Get TGT 3819 Context.state = self.STATE.CLI_SENT_TGTREQ 3820 return ( 3821 Context, 3822 KRB_GSSAPI_Token( 3823 MechType="1.2.840.113554.1.2.2.3", # U2U 3824 innerToken=KRB_InnerToken( 3825 TOK_ID=b"\x04\x00", 3826 root=KRB_TGT_REQ(), 3827 ), 3828 ), 3829 GSS_S_CONTINUE_NEEDED, 3830 ) 3831 3832 if Context.state in [self.STATE.INIT, self.STATE.CLI_SENT_TGTREQ]: 3833 if not self.UPN: 3834 raise ValueError("Missing UPN attribute") 3835 # Do we have a ST? 3836 if self.ST is None: 3837 # Client sends an AP-req 3838 if not self.SPN: 3839 raise ValueError("Missing SPN attribute") 3840 additional_tickets = [] 3841 if self.U2U: 3842 try: 3843 # GSSAPI / Kerberos 3844 tgt_rep = val.root.innerToken.root 3845 except AttributeError: 3846 try: 3847 # Kerberos 3848 tgt_rep = val.innerToken.root 3849 except AttributeError: 3850 return Context, None, GSS_S_DEFECTIVE_TOKEN 3851 if not isinstance(tgt_rep, KRB_TGT_REP): 3852 tgt_rep.show() 3853 raise ValueError("KerberosSSP: Unexpected token !") 3854 additional_tickets = [tgt_rep.ticket] 3855 if self.TGT is not None: 3856 if not self.KEY: 3857 raise ValueError("Cannot use TGT without the KEY") 3858 # Use TGT 3859 res = krb_tgs_req( 3860 upn=self.UPN, 3861 spn=self.SPN, 3862 ip=self.DC_IP, 3863 sessionkey=self.KEY, 3864 ticket=self.TGT, 3865 additional_tickets=additional_tickets, 3866 u2u=self.U2U, 3867 debug=self.debug, 3868 ) 3869 else: 3870 # Ask for TGT then ST 3871 res = krb_as_and_tgs( 3872 upn=self.UPN, 3873 spn=self.SPN, 3874 ip=self.DC_IP, 3875 key=self.KEY, 3876 password=self.PASSWORD, 3877 additional_tickets=additional_tickets, 3878 u2u=self.U2U, 3879 debug=self.debug, 3880 ) 3881 if not res: 3882 # Failed to retrieve the ticket 3883 return Context, None, GSS_S_FAILURE 3884 self.ST, self.KEY = res.tgsrep.ticket, res.sessionkey 3885 elif not self.KEY: 3886 raise ValueError("Must provide KEY with ST") 3887 Context.STSessionKey = self.KEY 3888 # Save ServerHostname 3889 if len(self.ST.sname.nameString) == 2: 3890 Context.ServerHostname = self.ST.sname.nameString[1].val.decode() 3891 # Build the KRB-AP 3892 apOptions = ASN1_BIT_STRING("000") 3893 if Context.flags & GSS_C_FLAGS.GSS_C_MUTUAL_FLAG: 3894 apOptions.set(2, "1") # mutual-required 3895 if self.U2U: 3896 apOptions.set(1, "1") # use-session-key 3897 Context.U2U = True 3898 ap_req = KRB_AP_REQ( 3899 apOptions=apOptions, 3900 ticket=self.ST, 3901 authenticator=EncryptedData(), 3902 ) 3903 # Build the authenticator 3904 now_time = datetime.now(timezone.utc).replace(microsecond=0) 3905 Context.KrbSessionKey = Key.random_to_key( 3906 self.SKEY_TYPE, 3907 os.urandom(16), 3908 ) 3909 Context.SendSeqNum = RandNum(0, 0x7FFFFFFF)._fix() 3910 _, crealm = _parse_upn(self.UPN) 3911 ap_req.authenticator.encrypt( 3912 Context.STSessionKey, 3913 KRB_Authenticator( 3914 crealm=crealm, 3915 cname=PrincipalName.fromUPN(self.UPN), 3916 # RFC 4121 checksum 3917 cksum=Checksum( 3918 cksumtype="KRB-AUTHENTICATOR", 3919 checksum=KRB_AuthenticatorChecksum(Flags=int(Context.flags)), 3920 ), 3921 ctime=ASN1_GENERALIZED_TIME(now_time), 3922 cusec=ASN1_INTEGER(0), 3923 subkey=EncryptionKey.fromKey(Context.KrbSessionKey), 3924 seqNumber=Context.SendSeqNum, 3925 encAuthorizationData=AuthorizationData( 3926 seq=[ 3927 AuthorizationDataItem( 3928 adType="AD-IF-RELEVANT", 3929 adData=AuthorizationData( 3930 seq=[ 3931 AuthorizationDataItem( 3932 adType="KERB-AUTH-DATA-TOKEN-RESTRICTIONS", 3933 adData=KERB_AD_RESTRICTION_ENTRY( 3934 restriction=LSAP_TOKEN_INFO_INTEGRITY( 3935 MachineID=bytes(RandBin(32)) 3936 ) 3937 ), 3938 ), 3939 AuthorizationDataItem( 3940 adType="KERB-LOCAL", 3941 adData=b"\x00" * 16, 3942 ), 3943 ] 3944 ), 3945 ) 3946 ] 3947 ), 3948 ), 3949 ) 3950 Context.state = self.STATE.CLI_SENT_APREQ 3951 if Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE: 3952 # Raw kerberos DCE-STYLE 3953 return Context, ap_req, GSS_S_CONTINUE_NEEDED 3954 else: 3955 # Kerberos wrapper 3956 return ( 3957 Context, 3958 KRB_GSSAPI_Token( 3959 innerToken=KRB_InnerToken( 3960 root=ap_req, 3961 ) 3962 ), 3963 GSS_S_CONTINUE_NEEDED, 3964 ) 3965 3966 elif Context.state == self.STATE.CLI_SENT_APREQ: 3967 if isinstance(val, KRB_AP_REP): 3968 # Raw AP_REP was passed 3969 ap_rep = val 3970 else: 3971 try: 3972 # GSSAPI / Kerberos 3973 ap_rep = val.root.innerToken.root 3974 except AttributeError: 3975 try: 3976 # Kerberos 3977 ap_rep = val.innerToken.root 3978 except AttributeError: 3979 try: 3980 # Raw kerberos DCE-STYLE 3981 ap_rep = val.root 3982 except AttributeError: 3983 return Context, None, GSS_S_DEFECTIVE_TOKEN 3984 if not isinstance(ap_rep, KRB_AP_REP): 3985 return Context, None, GSS_S_DEFECTIVE_TOKEN 3986 # Retrieve SessionKey 3987 repPart = ap_rep.encPart.decrypt(Context.STSessionKey) 3988 if repPart.subkey is not None: 3989 Context.SessionKey = repPart.subkey.keyvalue.val 3990 Context.KrbSessionKey = repPart.subkey.toKey() 3991 # OK ! 3992 Context.state = self.STATE.CLI_RCVD_APREP 3993 if Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE: 3994 # [MS-KILE] sect 3.4.5.1 3995 # The client MUST generate an additional AP exchange reply message 3996 # exactly as the server would as the final message to send to the 3997 # server. 3998 now_time = datetime.now(timezone.utc).replace(microsecond=0) 3999 cli_ap_rep = KRB_AP_REP(encPart=EncryptedData()) 4000 cli_ap_rep.encPart.encrypt( 4001 Context.STSessionKey, 4002 EncAPRepPart( 4003 ctime=ASN1_GENERALIZED_TIME(now_time), 4004 seqNumber=repPart.seqNumber, 4005 subkey=None, 4006 ), 4007 ) 4008 return Context, cli_ap_rep, GSS_S_COMPLETE 4009 return Context, None, GSS_S_COMPLETE 4010 elif ( 4011 Context.state == self.STATE.CLI_RCVD_APREP 4012 and Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE 4013 ): 4014 # DCE_STYLE with SPNEGOSSP 4015 return Context, None, GSS_S_COMPLETE 4016 else: 4017 raise ValueError("KerberosSSP: Unknown state") 4018 4019 def _setup_u2u(self): 4020 if not self.TGT: 4021 # Get a TGT for ourselves 4022 try: 4023 upn = "@".join(self.SPN.split("/")[1].split(".", 1)) 4024 except KeyError: 4025 raise ValueError("Couldn't transform the SPN into a valid UPN") 4026 res = krb_as_req(upn, self.DC_IP, key=self.KEY) 4027 self.TGT, self.KEY = res.asrep.ticket, res.sessionkey 4028 4029 def GSS_Accept_sec_context(self, Context: CONTEXT, val=None): 4030 if Context is None: 4031 # New context 4032 Context = self.CONTEXT(IsAcceptor=True, req_flags=0) 4033 4034 from scapy.libs.rfc3961 import Key 4035 4036 if Context.state == self.STATE.INIT: 4037 if not self.SPN: 4038 raise ValueError("Missing SPN attribute") 4039 # Server receives AP-req, sends AP-rep 4040 if isinstance(val, KRB_AP_REQ): 4041 # Raw AP_REQ was passed 4042 ap_req = val 4043 else: 4044 try: 4045 # GSSAPI/Kerberos 4046 ap_req = val.root.innerToken.root 4047 except AttributeError: 4048 try: 4049 # Raw Kerberos 4050 ap_req = val.root 4051 except AttributeError: 4052 return Context, None, GSS_S_DEFECTIVE_TOKEN 4053 if isinstance(ap_req, KRB_TGT_REQ): 4054 # Special U2U case 4055 self._setup_u2u() 4056 Context.U2U = True 4057 return ( 4058 None, 4059 KRB_GSSAPI_Token( 4060 MechType="1.2.840.113554.1.2.2.3", # U2U 4061 innerToken=KRB_InnerToken( 4062 TOK_ID=b"\x04\x01", 4063 root=KRB_TGT_REP( 4064 ticket=self.TGT, 4065 ), 4066 ), 4067 ), 4068 GSS_S_CONTINUE_NEEDED, 4069 ) 4070 elif not isinstance(ap_req, KRB_AP_REQ): 4071 ap_req.show() 4072 raise ValueError("Unexpected type in KerberosSSP") 4073 if not self.KEY: 4074 raise ValueError("Missing KEY attribute") 4075 # Validate SPN 4076 tkt_spn = "/".join( 4077 x.val.decode() for x in ap_req.ticket.sname.nameString[:2] 4078 ).lower() 4079 if tkt_spn not in [self.SPN.lower(), self.SPN.lower().split(".", 1)[0]]: 4080 warning("KerberosSSP: bad SPN: %s != %s" % (tkt_spn, self.SPN)) 4081 return Context, None, GSS_S_BAD_MECH 4082 # Enforce U2U if required 4083 if self.REQUIRE_U2U and ap_req.apOptions.val[1] != "1": # use-session-key 4084 # Required but not provided. Return an error 4085 self._setup_u2u() 4086 Context.U2U = True 4087 now_time = datetime.now(timezone.utc).replace(microsecond=0) 4088 err = KRB_GSSAPI_Token( 4089 innerToken=KRB_InnerToken( 4090 TOK_ID=b"\x03\x00", 4091 root=KRB_ERROR( 4092 errorCode="KRB_AP_ERR_USER_TO_USER_REQUIRED", 4093 stime=ASN1_GENERALIZED_TIME(now_time), 4094 realm=ap_req.ticket.realm, 4095 sname=ap_req.ticket.sname, 4096 eData=KRB_TGT_REP( 4097 ticket=self.TGT, 4098 ), 4099 ), 4100 ) 4101 ) 4102 return Context, err, GSS_S_CONTINUE_NEEDED 4103 # Decrypt the ticket 4104 try: 4105 tkt = ap_req.ticket.encPart.decrypt(self.KEY) 4106 except ValueError as ex: 4107 warning("KerberosSSP: %s (bad KEY?)" % ex) 4108 now_time = datetime.now(timezone.utc).replace(microsecond=0) 4109 err = KRB_GSSAPI_Token( 4110 innerToken=KRB_InnerToken( 4111 TOK_ID=b"\x03\x00", 4112 root=KRB_ERROR( 4113 errorCode="KRB_AP_ERR_MODIFIED", 4114 stime=ASN1_GENERALIZED_TIME(now_time), 4115 realm=ap_req.ticket.realm, 4116 sname=ap_req.ticket.sname, 4117 eData=None, 4118 ), 4119 ) 4120 ) 4121 return Context, err, GSS_S_DEFECTIVE_TOKEN 4122 # Get AP-REP session key 4123 Context.STSessionKey = tkt.key.toKey() 4124 authenticator = ap_req.authenticator.decrypt(Context.STSessionKey) 4125 # Compute an application session key ([MS-KILE] sect 3.1.1.2) 4126 subkey = None 4127 if ap_req.apOptions.val[2] == "1": # mutual-required 4128 appkey = Key.random_to_key( 4129 self.SKEY_TYPE, 4130 os.urandom(16), 4131 ) 4132 Context.KrbSessionKey = appkey 4133 Context.SessionKey = appkey.key 4134 subkey = EncryptionKey.fromKey(appkey) 4135 else: 4136 Context.KrbSessionKey = self.KEY 4137 Context.SessionKey = self.KEY.key 4138 # Eventually process the "checksum" 4139 if authenticator.cksum: 4140 if authenticator.cksum.cksumtype == 0x8003: 4141 # KRB-Authenticator 4142 Context.flags = authenticator.cksum.checksum.Flags 4143 # Build response (RFC4120 sect 3.2.4) 4144 ap_rep = KRB_AP_REP(encPart=EncryptedData()) 4145 ap_rep.encPart.encrypt( 4146 Context.STSessionKey, 4147 EncAPRepPart( 4148 ctime=authenticator.ctime, 4149 cusec=authenticator.cusec, 4150 seqNumber=None, 4151 subkey=subkey, 4152 ), 4153 ) 4154 Context.state = self.STATE.SRV_SENT_APREP 4155 if Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE: 4156 # [MS-KILE] sect 3.4.5.1 4157 return Context, ap_rep, GSS_S_CONTINUE_NEEDED 4158 return Context, ap_rep, GSS_S_COMPLETE # success 4159 elif ( 4160 Context.state == self.STATE.SRV_SENT_APREP 4161 and Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE 4162 ): 4163 # [MS-KILE] sect 3.4.5.1 4164 # The server MUST receive the additional AP exchange reply message and 4165 # verify that the message is constructed correctly. 4166 if not val: 4167 return Context, None, GSS_S_DEFECTIVE_TOKEN 4168 # Server receives AP-req, sends AP-rep 4169 if isinstance(val, KRB_AP_REP): 4170 # Raw AP_REP was passed 4171 ap_rep = val 4172 else: 4173 try: 4174 # GSSAPI/Kerberos 4175 ap_rep = val.root.innerToken.root 4176 except AttributeError: 4177 try: 4178 # Raw Kerberos 4179 ap_rep = val.root 4180 except AttributeError: 4181 return Context, None, GSS_S_DEFECTIVE_TOKEN 4182 # Decrypt the AP-REP 4183 try: 4184 ap_rep.encPart.decrypt(Context.STSessionKey) 4185 except ValueError as ex: 4186 warning("KerberosSSP: %s (bad KEY?)" % ex) 4187 return Context, None, GSS_S_DEFECTIVE_TOKEN 4188 return Context, None, GSS_S_COMPLETE # success 4189 else: 4190 raise ValueError("KerberosSSP: Unknown state %s" % repr(Context.state)) 4191 4192 def GSS_Passive(self, Context: CONTEXT, val=None): 4193 if Context is None: 4194 Context = self.CONTEXT(True) 4195 Context.passive = True 4196 4197 if Context.state == self.STATE.INIT: 4198 Context, _, status = self.GSS_Accept_sec_context(Context, val) 4199 Context.state = self.STATE.CLI_SENT_APREQ 4200 return Context, GSS_S_CONTINUE_NEEDED 4201 elif Context.state == self.STATE.CLI_SENT_APREQ: 4202 Context, _, status = self.GSS_Init_sec_context(Context, val) 4203 return Context, status 4204 4205 def GSS_Passive_set_Direction(self, Context: CONTEXT, IsAcceptor=False): 4206 if Context.IsAcceptor is not IsAcceptor: 4207 return 4208 # Swap everything 4209 Context.SendSealKeyUsage, Context.RecvSealKeyUsage = ( 4210 Context.RecvSealKeyUsage, 4211 Context.SendSealKeyUsage, 4212 ) 4213 Context.SendSignKeyUsage, Context.RecvSignKeyUsage = ( 4214 Context.RecvSignKeyUsage, 4215 Context.SendSignKeyUsage, 4216 ) 4217 Context.IsAcceptor = not Context.IsAcceptor 4218 4219 def MaximumSignatureLength(self, Context: CONTEXT): 4220 if Context.flags & GSS_C_FLAGS.GSS_C_CONF_FLAG: 4221 # TODO: support DES 4222 if Context.KrbSessionKey.etype in [17, 18]: # AES 4223 return 76 4224 elif Context.KrbSessionKey.etype in [23, 24]: # RC4_HMAC 4225 return 45 4226 else: 4227 raise NotImplementedError 4228 else: 4229 return 28 4230 4231 def canMechListMIC(self, Context: CONTEXT): 4232 return bool(Context.KrbSessionKey) 4233