kerberos
import "github.com/TheManticoreProject/Manticore/network/kerberos/v5"
Package kerberos provides a native Kerberos client implementation for Active Directory authentication, without external dependencies. It supports RC4-HMAC and AES-CTS-HMAC-SHA1-96 encryption types.
Index
- type ASREPRoastResult
- type ForgeOptions
- type ForgedTicket
- type KerberoastResult
- type KerberosClient
- func NewClient(username, realm, kdcHost string) *KerberosClient
- func (c *KerberosClient) Destroy()
- func (c *KerberosClient) ExportServiceTicketCCache(spn string) ([]byte, error)
- func (c *KerberosClient) ExportServiceTicketCCacheToFile(spn, path string) error
- func (c *KerberosClient) ExportServiceTicketKirbi(spn string) ([]byte, error)
- func (c *KerberosClient) ExportServiceTicketKirbiToFile(spn, path string) error
- func (c *KerberosClient) ExportTGTCCache() (*ccache.CCache, error)
- func (c *KerberosClient) ExportTGTKirbi() ([]byte, error)
- func (c *KerberosClient) FASTEnabled() bool
- func (c *KerberosClient) ForgeDiamond(krbtgtKey []byte, mods PACModifications) (*ForgedTicket, error)
- func (c *KerberosClient) ForgeSapphire(opts SapphireOptions) (*ForgedTicket, error)
- func (c *KerberosClient) GetTGS(spn string, includePAC bool) (messages.Ticket, []byte, []byte, int, error)
- func (c *KerberosClient) GetTGSU2U(targetUser, targetRealm string, targetTGTRaw []byte) (messages.Ticket, []byte, []byte, error)
- func (c *KerberosClient) GetTGT() error
- func (c *KerberosClient) HasTGT() bool
- func (c *KerberosClient) InsecureSkipPKINITKDCSignatureCheck() *KerberosClient
- func (c *KerberosClient) KDCHost() string
- func (c *KerberosClient) Kerberoast(spn string) (*KerberoastResult, error)
- func (c *KerberosClient) LoadForgedServiceTicket(ft *ForgedTicket) error
- func (c *KerberosClient) LoadServiceTicket(st *ServiceTicket) error
- func (c *KerberosClient) LoadTGT(cred *messages.KRBCred) error
- func (c *KerberosClient) LoadTGTFromCCache(cc *ccache.CCache) error
- func (c *KerberosClient) LoadTGTFromCCacheBytes(data []byte) error
- func (c *KerberosClient) LoadTGTFromCCacheEnv() error
- func (c *KerberosClient) LoadTGTFromCCacheFile(path string) error
- func (c *KerberosClient) LoadTGTFromKirbiBytes(data []byte) error
- func (c *KerberosClient) LoadTGTFromKirbiFile(path string) error
- func (c *KerberosClient) PKINITReplyKey() (key []byte, etype int)
- func (c *KerberosClient) PreferRC4ServiceTicket() *KerberosClient
- func (c *KerberosClient) Realm() string
- func (c *KerberosClient) Renew() error
- func (c *KerberosClient) S4U2Proxy(targetSPN string, s4u2selfTicketRaw []byte) (messages.Ticket, []byte, []byte, error)
- func (c *KerberosClient) S4U2Self(impersonateUser, impersonateRealm string) (messages.Ticket, []byte, []byte, error)
- func (c *KerberosClient) TGTFlags() asn1.BitString
- func (c *KerberosClient) TGTInvalid() bool
- func (c *KerberosClient) TGTMayPostdate() bool
- func (c *KerberosClient) TGTPostdated() bool
- func (c *KerberosClient) UnPACTheHash() (lmHash, ntHash []byte, err error)
- func (c *KerberosClient) Username() string
- func (c *KerberosClient) Validate() error
- func (c *KerberosClient) WithAESKey(hexKey string) error
- func (c *KerberosClient) WithAESKeyForEType(hexKey string, etype int) error
- func (c *KerberosClient) WithCredential(cred *credentials.Credential) *KerberosClient
- func (c *KerberosClient) WithFASTArmor(cname, realm string, ticket messages.Ticket, ticketRaw, sessionKey []byte, sessionEType int) *KerberosClient
- func (c *KerberosClient) WithFASTArmorFromClient(armor *KerberosClient) *KerberosClient
- func (c *KerberosClient) WithKDCResolver(fn func(realm string) (string, error)) *KerberosClient
- func (c *KerberosClient) WithKeytab(kt *keytab.Keytab, etype int) error
- func (c *KerberosClient) WithKeytabBytes(data []byte) error
- func (c *KerberosClient) WithKeytabFile(path string) error
- func (c *KerberosClient) WithNTHash(hexHash string) error
- func (c *KerberosClient) WithPKINIT(priv *rsa.PrivateKey, certDER []byte) *KerberosClient
- func (c *KerberosClient) WithPKINITAnchors(anchors …*x509.Certificate) *KerberosClient
- func (c *KerberosClient) WithPKINITGroups(groups …pkinit.DHGroup) *KerberosClient
- func (c *KerberosClient) WithPKINITKDCCert(certDER []byte) *KerberosClient
- func (c *KerberosClient) WithPassword(password string) *KerberosClient
- func (c *KerberosClient) WithPostdate(start time.Time) *KerberosClient
- func (c *KerberosClient) WithRealmKDC(realm, kdcHost string) *KerberosClient
- func (c *KerberosClient) WithResolver(r *net.Resolver) *KerberosClient
- type PACModifications
- type SPNEGOMechanism
- type SapphireOptions
- type ServiceTicket
- func LoadServiceTicketFromCCacheBytes(data []byte, spn string) (*ServiceTicket, error)
- func LoadServiceTicketFromCCacheFile(path, spn string) (*ServiceTicket, error)
- func LoadServiceTicketFromKirbiBytes(data []byte, spn string) (*ServiceTicket, error)
- func LoadServiceTicketFromKirbiFile(path, spn string) (*ServiceTicket, error)
type ASREPRoastResult
ASREPRoastResult contains the raw fields extracted from an AS-REP response for an account that does not require Kerberos pre-authentication (UF_DONT_REQUIRE_PREAUTH). The caller is responsible for formatting CipherText into a crackable hash (e.g. hashcat $krb5asrep$<etype>$<username>@<realm>:<first16>$<rest>).
type ASREPRoastResult struct {
// Username is the account that was targeted.
Username string
// Realm is the Kerberos realm (uppercased).
Realm string
// EncryptionType is the etype of the encrypted part (23=RC4, 17=AES128, 18=AES256).
EncryptionType int
// CipherText is the raw encrypted part of the AS-REP, crackable offline.
CipherText []byte
}
func ASREPRoast
func ASREPRoast(username, realm, kdcHost string) (*ASREPRoastResult, error)
ASREPRoast sends an AS-REQ without pre-authentication data for the given username and returns the encrypted part of the AS-REP response for offline cracking.
If the account requires pre-authentication the KDC responds with KDC_ERR_PREAUTH_REQUIRED (25) and this function returns an error. If the account does not exist the KDC responds with KDC_ERR_C_PRINCIPAL_UNKNOWN (6).
type ForgeOptions
ForgeOptions describes the identity and validity of a forged ticket. The zero value is not valid: Realm, Username, DomainSID, and Key must be set.
type ForgeOptions struct {
// Realm is the Kerberos realm (AD domain DNS name); it is uppercased.
Realm string
// Username is the client account's sAMAccountName the ticket impersonates.
Username string
// DomainSID is the account domain SID (e.g. "S-1-5-21-…"), used as the PAC
// LogonDomainId; user and group SIDs are formed as DomainSID-<RID>.
DomainSID string
// UserRID is the impersonated account's RID (e.g. 500 for the built-in
// Administrator).
UserRID uint32
// PrimaryGroupRID is the RID of the account's primary group (e.g. 513,
// Domain Users). Defaults to 513 when zero.
PrimaryGroupRID uint32
// GroupRIDs are the RIDs of the account's groups in the account domain. When
// empty a default privileged set (Domain Users/Admins, Schema/Enterprise
// Admins, Group Policy Creator Owners) is used.
GroupRIDs []uint32
// ExtraSIDs are fully-qualified SIDs added to the PAC ExtraSids list (e.g.
// the Enterprise Admins SID for a cross-domain golden ticket).
ExtraSIDs []string
// LogonDomainName is the account domain's NetBIOS name (PAC LogonDomainName).
LogonDomainName string
// LogonServer is the NetBIOS name of the authenticating DC (PAC LogonServer).
LogonServer string
// Key is the signing/encryption key: an RC4 NT hash (16 bytes) or an AES key
// (16/32 bytes) of the krbtgt account (golden) or the service account (silver).
Key []byte
// KeyEType is the Kerberos encryption type of Key (23 = RC4, 17 = AES128,
// 18 = AES256).
KeyEType int
// KvNo is the key version number recorded in the ticket enc-part (optional;
// omitted when zero).
KvNo int
// SessionKey is the session key sealed in the ticket. A random key of
// SessionEType is generated when nil.
SessionKey []byte
// SessionEType is the session key's encryption type (defaults to RC4).
SessionEType int
// StartTime is when the ticket becomes valid (defaults to now).
StartTime time.Time
// EndTime is the ticket's expiry (defaults to StartTime + 10 years).
EndTime time.Time
// RenewTill is the renewable lifetime end (defaults to EndTime).
RenewTill time.Time
// UserAccountControl overrides the PAC UserAccountControl flags (defaults to
// a normal, non-expiring account).
UserAccountControl uint32
}
type ForgedTicket
ForgedTicket is the result of forging a golden or silver ticket: a Ticket and the matching KrbCredInfo (session key, flags, times, principals). It can be serialized to a .kirbi (KirbiBytes) or imported directly into a KerberosClient (LoadTGT / LoadServiceTicket) for pass-the-ticket use.
type ForgedTicket struct {
// Ticket is the forged Kerberos ticket (APPLICATION[1]).
Ticket messages.Ticket
// TicketRaw is the DER of Ticket, for verbatim re-emission in an AP-REQ.
TicketRaw []byte
// CredInfo describes the ticket for KRB-CRED export/import (session key,
// flags, times, client and service principals).
CredInfo messages.KrbCredInfo
// SessionKey is the ticket session key (also present in CredInfo).
SessionKey []byte
// SessionEType is the session key's encryption type.
SessionEType int
}
func ForgeGolden
func ForgeGolden(opts ForgeOptions) (*ForgedTicket, error)
ForgeGolden forges a golden ticket: a TGT for krbtgt/REALM signed with the domain krbtgt key supplied in opts.Key. Import the result with a client’s LoadTGT (via KirbiBytes) to request service tickets from the KDC with no password.
func ForgeSilver
func ForgeSilver(opts ForgeOptions, spn string) (*ForgedTicket, error)
ForgeSilver forges a silver ticket: a service ticket for the given SPN (“service/host”) signed with that service account’s key supplied in opts.Key. The ticket is presented directly to the service (no KDC round-trip); import it with LoadServiceTicket for use over SMB/RPC/LDAP.
func (*ForgedTicket) KirbiBytes
func (f *ForgedTicket) KirbiBytes() ([]byte, error)
KirbiBytes serializes the forged ticket as a .kirbi (DER KRB-CRED) with an unencrypted enc-part, ready for pass-the-ticket import.
type KerberoastResult
KerberoastResult holds the crackable encrypted part of a service ticket obtained for a target SPN. The service ticket’s enc-part is encrypted with the service account’s long-term key, so it can be cracked offline to recover that account’s password. Format it for a cracker with attacks.FormatTGSHash(account, result.Realm, result.SPN, result.EType, result.Cipher), where account is the service account’s sAMAccountName. The account is the AES string-to-key salt input (UPPER(realm)+account), so passing the SPN there produces the wrong salt and an uncrackable AES hash; it is not carried on the result and must be resolved separately (e.g. the account owning the SPN in the directory). For RC4 (etype 23) the account field is not used in the salt, so any placeholder cracks, but supplying the real sAMAccountName keeps both etypes correct.
type KerberoastResult struct {
// SPN is the service principal name that was roasted.
SPN string
// Realm is the Kerberos realm (uppercased).
Realm string
// EType is the encryption type of the ticket's enc-part (23 = RC4 yields the
// most crackable hash; request it by advertising RC4 in the TGS-REQ).
EType int
// Cipher is the raw encrypted part of the service ticket.
Cipher []byte
}
type KerberosClient
KerberosClient manages Kerberos authentication against an Active Directory KDC.
It provides protocol-level primitives: TGT acquisition with PA-ENC-TIMESTAMP pre-authentication, TGS requests, and ASREPRoast. All cryptographic operations use the native Manticore implementations (no external Kerberos library).
Typical usage:
c := kerberos.NewClient("john", "CORP.LOCAL", "10.0.0.1")
c.WithPassword("secret")
if err := c.GetTGT(); err != nil { ... }
ticket, ticketRaw, sessionKey, sessionEType, err := c.GetTGS("cifs/dc01.corp.local", true)
type KerberosClient struct {
// contains filtered or unexported fields
}
func NewClient
func NewClient(username, realm, kdcHost string) *KerberosClient
NewClient creates a new KerberosClient for the given username, realm and KDC host. The realm is uppercased automatically (required by the Kerberos specification). Call WithPassword before calling GetTGT.
func (*KerberosClient) Destroy
func (c *KerberosClient) Destroy()
Destroy zeroes out key material held by the client.
func (*KerberosClient) ExportServiceTicketCCache
func (c *KerberosClient) ExportServiceTicketCCache(spn string) ([]byte, error)
ExportServiceTicketCCache returns the cached service ticket for spn as an MIT ccache (v4) holding a single credential, the service-ticket counterpart of ExportTGTCCache. The ticket must have been obtained via GetTGS (or wired in via LoadServiceTicket) beforehand.
func (*KerberosClient) ExportServiceTicketCCacheToFile
func (c *KerberosClient) ExportServiceTicketCCacheToFile(spn, path string) error
ExportServiceTicketCCacheToFile writes the cached service ticket for spn to path in MIT ccache (v4) form, mode 0600.
func (*KerberosClient) ExportServiceTicketKirbi
func (c *KerberosClient) ExportServiceTicketKirbi(spn string) ([]byte, error)
ExportServiceTicketKirbi returns the cached service ticket for spn as .kirbi (DER KRB-CRED) bytes, the service-ticket counterpart of ExportTGTKirbi. The ticket must have been obtained via GetTGS (or wired in via LoadServiceTicket) beforehand.
func (*KerberosClient) ExportServiceTicketKirbiToFile
func (c *KerberosClient) ExportServiceTicketKirbiToFile(spn, path string) error
ExportServiceTicketKirbiToFile writes the cached service ticket for spn to path in .kirbi (DER KRB-CRED) form, mode 0600.
func (*KerberosClient) ExportTGTCCache
func (c *KerberosClient) ExportTGTCCache() (*ccache.CCache, error)
ExportTGTCCache returns the current TGT as an MIT ccache (v4) holding a single credential. GetTGT must have succeeded first.
func (*KerberosClient) ExportTGTKirbi
func (c *KerberosClient) ExportTGTKirbi() ([]byte, error)
ExportTGTKirbi returns the current TGT as .kirbi (DER KRB-CRED) bytes, suitable for pass-the-ticket with Rubeus. GetTGT must have succeeded first.
func (*KerberosClient) FASTEnabled
func (c *KerberosClient) FASTEnabled() bool
FASTEnabled reports whether a FAST armor TGT has been configured.
func (*KerberosClient) ForgeDiamond
func (c *KerberosClient) ForgeDiamond(krbtgtKey []byte, mods PACModifications) (*ForgedTicket, error)
ForgeDiamond forges a diamond ticket from the TGT this client currently holds. GetTGT must have succeeded first (with a password, hash, key, or PKINIT): the client’s genuine TGT is decrypted with krbtgtKey, its PAC is edited per mods, re-signed and re-encrypted with krbtgtKey, and returned as a ForgedTicket usable via KirbiBytes / LoadTGTFromKirbiBytes (pass-the-ticket) exactly like a golden ticket — but built on a ticket the KDC really issued.
krbtgtKey is the domain krbtgt account’s long-term key; its encryption type is taken from the TGT’s own enc-part etype (the KDC encrypted the TGT with it).
func (*KerberosClient) ForgeSapphire
func (c *KerberosClient) ForgeSapphire(opts SapphireOptions) (*ForgedTicket, error)
ForgeSapphire forges a sapphire ticket. Using the TGT this client holds (GetTGT must have succeeded), it requests the impersonated user’s genuine PAC via a combined S4U2Self + user-to-user (ENC-TKT-IN-SKEY) exchange — so the KDC encrypts the reply ticket to the client’s own TGT session key — extracts that real PAC, and grafts it into a forged TGT (krbtgt/REALM) re-signed and encrypted with opts.Key. The result is usable via KirbiBytes / LoadTGTFromKirbiBytes to act as the impersonated user, with a PAC whose identity fields the KDC actually issued.
func (*KerberosClient) GetTGS
func (c *KerberosClient) GetTGS(spn string, includePAC bool) (messages.Ticket, []byte, []byte, int, error)
GetTGS requests a service ticket for the given Service Principal Name. GetTGT must have been called successfully beforehand.
The SPN format is “service/host” (e.g. “cifs/dc01.corp.local”) or “service/host@REALM”.
includePAC controls whether the KDC should include the PAC in the service ticket. Pass false for kerberoasting (produces shorter, hashcat-crackable ciphers).
Returns the parsed service Ticket, the raw APPLICATION[1] ticket bytes as received from the KDC (suitable for verbatim re-emission in a downstream AP-REQ via messages.APReq{TicketRaw: …}.Marshal), the associated session key bytes, and the session key’s encryption type. The session-key etype is the KDC’s choice and is not necessarily the ticket’s own encryption type (the server long-term key etype): a Windows KDC can, for example, wrap an AES256 ticket around an RC4 session key. Callers keying the AP-REQ authenticator or per-message GSS tokens must use this returned etype, not Ticket.EncPart.EType.
func (*KerberosClient) GetTGSU2U
func (c *KerberosClient) GetTGSU2U(targetUser, targetRealm string, targetTGTRaw []byte) (messages.Ticket, []byte, []byte, error)
GetTGSU2U performs a user-to-user (U2U) TGS exchange: it requests a service ticket to the target user (targetUser in targetRealm, or the client’s realm if empty), presenting the target user’s TGT (targetTGTRaw, raw APPLICATION[1] bytes) in additional-tickets with the ENC-TKT-IN-SKEY option. The KDC issues a ticket whose enc-part is encrypted with the session key of the target’s TGT (not a long-term key), which the target verifies via an AP-REQ carrying the USE-SESSION-KEY option.
GetTGT must have succeeded first (for the client’s own TGT). Returns the service ticket, its raw bytes, and the ticket session key.
func (*KerberosClient) GetTGT
func (c *KerberosClient) GetTGT() error
GetTGT requests a Ticket Granting Ticket from the KDC using the password configured via WithPassword.
Windows KDCs silently drop AS-REQs without PA-ENC-TIMESTAMP, so we skip the probe and send PA-ENC-TIMESTAMP immediately with the default AD salt (realm+username). If the KDC returns PREAUTH_REQUIRED with different etype/salt info, we retry once with the corrected values.
func (*KerberosClient) HasTGT
func (c *KerberosClient) HasTGT() bool
HasTGT reports whether a Ticket Granting Ticket has been acquired (via GetTGT).
func (*KerberosClient) InsecureSkipPKINITKDCSignatureCheck
func (c *KerberosClient) InsecureSkipPKINITKDCSignatureCheck() *KerberosClient
InsecureSkipPKINITKDCSignatureCheck disables verification of the KDC’s CMS SignedData signature on the AS-REP, for the anonymous / self-signed lab case where no trust anchor can be pinned. It is insecure — it removes the RFC 4556 §3.2.4 protection against a substituted KDC DH public value — so call it only knowingly.
func (*KerberosClient) KDCHost
func (c *KerberosClient) KDCHost() string
KDCHost returns the KDC host configured for this client.
func (*KerberosClient) Kerberoast
func (c *KerberosClient) Kerberoast(spn string) (*KerberoastResult, error)
Kerberoast requests a service ticket for the given SPN and returns its encrypted part for offline cracking. GetTGT must have succeeded first. The PAC is not requested (includePAC = false), yielding a shorter, PAC-free ticket as Kerberoasting tools do.
To obtain an RC4 (NT-hash-crackable) ticket, ensure RC4 is offered; the KDC returns the strongest etype the service account key supports.
func (*KerberosClient) LoadForgedServiceTicket
func (c *KerberosClient) LoadForgedServiceTicket(ft *ForgedTicket) error
LoadForgedServiceTicket wires a forged (silver) ticket into the client for pass-the-ticket, the forging-side counterpart of LoadServiceTicket.
func (*KerberosClient) LoadServiceTicket
func (c *KerberosClient) LoadServiceTicket(st *ServiceTicket) error
LoadServiceTicket wires a service ticket (a forged silver ticket, or one recovered from a .kirbi/ccache) into the client so a subsequent GetTGS for its SPN returns it verbatim with no TGT and no KDC round-trip. Combined with the SPNEGO mechanism this is silver-ticket pass-the-ticket against SMB/RPC/LDAP.
func (*KerberosClient) LoadTGT
func (c *KerberosClient) LoadTGT(cred *messages.KRBCred) error
LoadTGT wires a Ticket Granting Ticket held in a parsed KRB-CRED (.kirbi) into the client, enabling pass-the-ticket: subsequent GetTGS / SPNEGO calls reuse the ticket and its session key with no password.
The KRB-CRED must carry an unencrypted enc-part (etype 0, the .kirbi convention) so the session key and ticket metadata can be read. When the credential holds multiple tickets the krbtgt/REALM entry is selected; if none is a TGT the first entry is used. The client’s username and realm are set from the ticket’s client principal, so a client created with NewClient("", “”, kdcHost) becomes fully usable after import.
func (*KerberosClient) LoadTGTFromCCache
func (c *KerberosClient) LoadTGTFromCCache(cc *ccache.CCache) error
LoadTGTFromCCache wires a Ticket Granting Ticket held in a parsed MIT ccache into the client for pass-the-ticket. The krbtgt/REALM credential is selected; if the cache holds none, the first credential is used. Username and realm are taken from the credential’s client principal.
func (*KerberosClient) LoadTGTFromCCacheBytes
func (c *KerberosClient) LoadTGTFromCCacheBytes(data []byte) error
LoadTGTFromCCacheBytes parses MIT ccache (v4) bytes and loads the TGT they carry.
func (*KerberosClient) LoadTGTFromCCacheEnv
func (c *KerberosClient) LoadTGTFromCCacheEnv() error
LoadTGTFromCCacheEnv loads the TGT from the ccache named by the KRB5CCNAME environment variable. A leading “FILE:” type prefix (the only cache type this package implements) is accepted and stripped. It errors if KRB5CCNAME is unset or names a non-FILE cache.
func (*KerberosClient) LoadTGTFromCCacheFile
func (c *KerberosClient) LoadTGTFromCCacheFile(path string) error
LoadTGTFromCCacheFile reads an MIT ccache file and loads the TGT it carries.
func (*KerberosClient) LoadTGTFromKirbiBytes
func (c *KerberosClient) LoadTGTFromKirbiBytes(data []byte) error
LoadTGTFromKirbiBytes parses .kirbi (DER KRB-CRED) bytes and loads the TGT they carry via LoadTGT.
func (*KerberosClient) LoadTGTFromKirbiFile
func (c *KerberosClient) LoadTGTFromKirbiFile(path string) error
LoadTGTFromKirbiFile reads a .kirbi file and loads the TGT it carries.
func (*KerberosClient) PKINITReplyKey
func (c *KerberosClient) PKINITReplyKey() (key []byte, etype int)
PKINITReplyKey returns the AS reply key derived from the PKINIT Diffie-Hellman exchange (nil until GetTGT succeeds over PKINIT). It is the key that decrypts the AS-REP enc-part and, for UnPAC-the-hash, the PAC_CREDENTIAL_INFO buffer.
func (*KerberosClient) PreferRC4ServiceTicket
func (c *KerberosClient) PreferRC4ServiceTicket() *KerberosClient
PreferRC4ServiceTicket makes GetTGS request an RC4-HMAC service ticket (RC4 session key). Windows RPC’s DCE-style Kerberos per-message protection is only interoperable with RC4 on some servers, so the DCE/RPC client forces it.
func (*KerberosClient) Realm
func (c *KerberosClient) Realm() string
Realm returns the realm (uppercased) configured for this client.
func (*KerberosClient) Renew
func (c *KerberosClient) Renew() error
Renew refreshes the client’s renewable Ticket Granting Ticket without re-authenticating. It sends a TGS-REQ with the renew KDC option, presenting the current TGT in a PA-TGS-REQ AP-REQ (RFC 4120 §3.3.3). The KDC returns a fresh TGT with a new session key and advanced start/end times (capped at the ticket’s renew-till), which replaces the client’s stored TGT and session key on success. GetTGT must have succeeded first, and the current TGT must be renewable and not past its renew-till, or the KDC rejects the request.
func (*KerberosClient) S4U2Proxy
func (c *KerberosClient) S4U2Proxy(targetSPN string, s4u2selfTicketRaw []byte) (messages.Ticket, []byte, []byte, error)
S4U2Proxy performs the MS-SFU S4U2Proxy exchange: the service, holding its own TGT and a service ticket obtained on behalf of a user (typically from S4U2Self), requests a service ticket to a target service (targetSPN) as that user. It is the second half of constrained delegation.
s4u2selfTicketRaw is the raw APPLICATION[1] bytes of the user’s service ticket to this service (the S4U2Self result). The request sets the cname-in-addl-tkt KDC option, carries that ticket in additional-tickets, and includes PA-PAC-OPTIONS with the resource-based-constrained-delegation bit. Returns the service ticket to the target, its raw bytes, and the ticket session key.
func (*KerberosClient) S4U2Self
func (c *KerberosClient) S4U2Self(impersonateUser, impersonateRealm string) (messages.Ticket, []byte, []byte, error)
S4U2Self performs the MS-SFU S4U2Self exchange: the service (this client’s principal), holding its own TGT, requests a service ticket to itself on behalf of the user (impersonateUser, impersonateRealm), identified only by name. It is the first half of constrained delegation and, on its own, a way to obtain a usable service ticket (with the target user’s PAC) for any user without their secret — subject to the account’s delegation configuration.
GetTGT must have succeeded first (the client must hold its service TGT). If impersonateRealm is empty the client’s realm is used. Returns the service ticket, its raw APPLICATION[1] bytes, and the ticket session key.
func (*KerberosClient) TGTFlags
func (c *KerberosClient) TGTFlags() asn1.BitString
TGTFlags returns the ticket-flags BitString of the currently held TGT (the decrypted AS-REP/TGS-REP enc-part flags). It is the zero BitString before GetTGT succeeds. See TGTMayPostdate / TGTPostdated / TGTInvalid for the postdating-relevant decodes.
func (*KerberosClient) TGTInvalid
func (c *KerberosClient) TGTInvalid() bool
TGTInvalid reports whether the held TGT carries the INVALID flag. A postdated ticket is issued INVALID and must be turned valid by a VALIDATE exchange (see Validate) once its start time is reached (RFC 4120 §2.4, §3.3.3).
func (*KerberosClient) TGTMayPostdate
func (c *KerberosClient) TGTMayPostdate() bool
TGTMayPostdate reports whether the held TGT carries the MAY-POSTDATE flag, i.e. it is authorized to obtain postdated tickets (RFC 4120 §2.4).
func (*KerberosClient) TGTPostdated
func (c *KerberosClient) TGTPostdated() bool
TGTPostdated reports whether the held TGT carries the POSTDATED flag, i.e. it was issued with a start time in the future (RFC 4120 §2.4).
func (*KerberosClient) UnPACTheHash
func (c *KerberosClient) UnPACTheHash() (lmHash, ntHash []byte, err error)
UnPACTheHash recovers the account’s NTLM secrets from the PAC after a PKINIT (certificate / Shadow Credentials) logon — the “UnPAC-the-hash” technique.
A PKINIT-issued PAC carries a PAC_CREDENTIAL_INFO buffer holding the account’s NT hash, encrypted under the PKINIT-derived AS reply key. That buffer lives in the TGT (encrypted to the KDC), so it cannot be read directly; instead this method requests a user-to-user (ENC-TKT-IN-SKEY) service ticket to the account itself, which the KDC encrypts under the client’s own TGT session key. It decrypts that ticket, extracts the PAC, then decrypts PAC_CREDENTIAL_INFO with the reply key and parses the NTLM_SUPPLEMENTAL_CREDENTIAL.
GetTGT must have succeeded over PKINIT (see WithPKINIT) so the reply key is available. Returns the recovered LM and NT hashes (LM may be nil).
func (*KerberosClient) Username
func (c *KerberosClient) Username() string
Username returns the username configured for this client.
func (*KerberosClient) Validate
func (c *KerberosClient) Validate() error
Validate turns a postdated (INVALID-flagged) TGT into a usable one once its start time has passed. It sends a TGS-REQ with the validate KDC option, presenting the ticket in a PA-TGS-REQ AP-REQ (RFC 4120 §3.3.3); the KDC clears the INVALID flag and returns a fresh ticket, which replaces the client’s stored TGT and session key on success. GetTGT must have succeeded first. Many KDCs (including default Active Directory policy) disable postdating, in which case the KDC rejects the request.
func (*KerberosClient) WithAESKey
func (c *KerberosClient) WithAESKey(hexKey string) error
WithAESKey configures a pass-the-key credential from a hex-encoded AES key (16 bytes -> AES128, 32 bytes -> AES256).
func (*KerberosClient) WithAESKeyForEType
func (c *KerberosClient) WithAESKeyForEType(hexKey string, etype int) error
WithAESKeyForEType configures a pass-the-key credential for an explicit AES-SHA1 or AES-SHA2 enctype. The explicit enctype is required for AES-SHA2 because its key lengths are the same as the corresponding AES-SHA1 profiles.
func (*KerberosClient) WithCredential
func (c *KerberosClient) WithCredential(cred *credentials.Credential) *KerberosClient
WithCredential configures an arbitrary credential (password, NT hash, or AES key). Returns the client to allow fluent chaining.
func (*KerberosClient) WithFASTArmor
func (c *KerberosClient) WithFASTArmor(cname, realm string, ticket messages.Ticket, ticketRaw, sessionKey []byte, sessionEType int) *KerberosClient
WithFASTArmor enables RFC 6113 FAST (Kerberos armoring) on the AS exchange, using the supplied armor TGT. cname/realm identify the armor principal (the account that owns the TGT); ticket/ticketRaw are the armor TGT (raw is the verbatim APPLICATION[1] bytes as issued by the KDC); sessionKey/sessionEType are the armor TGT’s session key. Once configured, GetTGT performs a FAST-armored AS-REQ with a PA-ENCRYPTED-CHALLENGE factor. Returns the client for fluent chaining.
func (*KerberosClient) WithFASTArmorFromClient
func (c *KerberosClient) WithFASTArmorFromClient(armor *KerberosClient) *KerberosClient
WithFASTArmorFromClient enables FAST using another client’s already-acquired TGT as the armor (the “self-armor” pattern when armor is the same client that has a TGT). The armor client MUST have completed GetTGT. Returns the client for fluent chaining.
func (*KerberosClient) WithKDCResolver
func (c *KerberosClient) WithKDCResolver(fn func(realm string) (string, error)) *KerberosClient
WithKDCResolver installs a custom function that resolves a realm to a KDC host for the cross-realm referral chase. It takes precedence over DNS-SRV discovery but not over explicit WithRealmKDC entries or the client’s own home realm. Returns the client to allow fluent chaining.
func (*KerberosClient) WithKeytab
func (c *KerberosClient) WithKeytab(kt *keytab.Keytab, etype int) error
WithKeytab selects a long-term key from a parsed keytab and configures it as the client’s credential (pass-the-key), so GetTGT needs no password.
The entry is chosen for the client’s own principal (username@realm); the strongest usable enctype present is preferred (AES256 > AES128 > RC4). When the client was created with an empty username (NewClient("", realm, kdc)), the principal of the selected entry populates the client’s username. Pass etype > 0 to force a specific enctype instead of the strongest.
func (*KerberosClient) WithKeytabBytes
func (c *KerberosClient) WithKeytabBytes(data []byte) error
WithKeytabBytes parses keytab bytes and configures the client’s credential from them via WithKeytab (strongest usable enctype, etype 0).
func (*KerberosClient) WithKeytabFile
func (c *KerberosClient) WithKeytabFile(path string) error
WithKeytabFile reads a .keytab file and configures the client’s credential from it (strongest usable enctype).
func (*KerberosClient) WithNTHash
func (c *KerberosClient) WithNTHash(hexHash string) error
WithNTHash configures an NT-hash (overpass-the-hash) credential from a hex string (accepts an “LM:NT” pair). GetTGT will request an RC4-HMAC TGT.
func (*KerberosClient) WithPKINIT
func (c *KerberosClient) WithPKINIT(priv *rsa.PrivateKey, certDER []byte) *KerberosClient
WithPKINIT configures certificate-based (PKINIT, RFC 4556) pre-authentication with Diffie-Hellman key agreement. priv is the client’s RSA private key and certDER is its DER-encoded X.509 certificate (for Shadow Credentials, a self-signed certificate whose public key is registered in the target’s msDS-KeyCredentialLink). A subsequent GetTGT performs the PKINIT AS exchange instead of password/hash pre-authentication.
By default the client offers MODP group 14 (2048-bit) and falls back to group 2 (1024-bit); use WithPKINITGroups to override.
func (*KerberosClient) WithPKINITAnchors
func (c *KerberosClient) WithPKINITAnchors(anchors ...*x509.Certificate) *KerberosClient
WithPKINITAnchors adds trusted certificates (the issuing CA / root, or the pinned KDC certificate itself) that the KDC’s PKINIT signing certificate must chain to. Supplying at least one anchor turns on verification of the KDC’s CMS SignedData signature on the AS-REP (RFC 4556 §3.2.4).
func (*KerberosClient) WithPKINITGroups
func (c *KerberosClient) WithPKINITGroups(groups ...pkinit.DHGroup) *KerberosClient
WithPKINITGroups overrides the ordered list of MODP Diffie-Hellman groups the PKINIT AS exchange will try (the first the KDC accepts is used).
func (*KerberosClient) WithPKINITKDCCert
func (c *KerberosClient) WithPKINITKDCCert(certDER []byte) *KerberosClient
WithPKINITKDCCert pins the KDC’s PKINIT signing certificate as a trust anchor: a subsequent GetTGT verifies the KDC’s CMS SignedData signature on the AS-REP and requires the signer certificate to be byte-identical to certDER (RFC 4556 §3.2.4). This covers a self-signed KDC certificate directly; to trust a CA instead, use WithPKINITAnchors. By default (no anchor and no opt-out) the KDC signature is not verified.
func (*KerberosClient) WithPassword
func (c *KerberosClient) WithPassword(password string) *KerberosClient
WithPassword configures a password credential for GetTGT. Returns the client to allow fluent chaining.
func (*KerberosClient) WithPostdate
func (c *KerberosClient) WithPostdate(start time.Time) *KerberosClient
WithPostdate configures GetTGT to request a postdated Ticket Granting Ticket with the given (future) start time (RFC 4120 §3.3). The AS-REQ is sent with the allow-postdate and postdated KDC options and a from field carrying start; its endtime is derived from start (a 24h window). The KDC — if postdating is permitted by policy — returns a TGT flagged POSTDATED and INVALID whose start time lies in the future. Call Validate once that start time is reached (or where the KDC allows, immediately) to clear the INVALID flag and turn it into a usable TGT.
Many production KDCs (default Active Directory policy included) disable postdating, in which case GetTGT surfaces the KDC’s policy error (e.g. KDC_ERR_POLICY / KDC_ERR_CANNOT_POSTDATE).
Returns the client to allow fluent chaining. Passing the zero time clears the request, restoring an ordinary immediate-start TGT.
func (*KerberosClient) WithRealmKDC
func (c *KerberosClient) WithRealmKDC(realm, kdcHost string) *KerberosClient
WithRealmKDC registers the KDC host to contact when the cross-realm referral chase reaches the given realm. The realm is uppercased automatically. This is the minimal, no-dependency way to resolve a target-realm KDC; automatic discovery (DNS SRV) is used for any realm not registered here. Returns the client to allow fluent chaining.
func (*KerberosClient) WithResolver
func (c *KerberosClient) WithResolver(r *net.Resolver) *KerberosClient
WithResolver installs the DNS resolver used for KDC discovery (SRV lookups) and for resolving KDC hostnames to A/AAAA addresses. Passing nil restores the default (net.DefaultResolver). This lets a caller point Kerberos DNS at a specific server (e.g. the domain controller) without altering system-wide resolver configuration. Returns the client to allow fluent chaining.
type PACModifications
PACModifications describes the edits a diamond ticket applies to a genuinely issued PAC’s KERB_VALIDATION_INFO. The zero value makes no changes (a faithful re-encryption of the original ticket).
type PACModifications struct {
// AddGroupRIDs are group RIDs appended to the account-domain group list
// (GroupIds), e.g. 512 (Domain Admins) or 519 (Enterprise Admins). RIDs
// already present are skipped.
AddGroupRIDs []uint32
// ExtraSIDs are fully-qualified SIDs appended to the PAC ExtraSids list (e.g.
// the Enterprise Admins SID of another domain). Adding any sets the ExtraSids
// UserFlags bit ([MS-PAC] 2.5).
ExtraSIDs []string
// UserRID, when non-zero, overrides the PAC UserId (the impersonated RID).
UserRID uint32
// PrimaryGroupRID, when non-zero, overrides the PAC PrimaryGroupId.
PrimaryGroupRID uint32
}
type SPNEGOMechanism
SPNEGOMechanism adapts the native Kerberos client and GSS-API layer to the crypto/spnego KerberosProvider interface, so SMB and DCE/RPC can authenticate with Kerberos through SPNEGO. It targets a single service principal (spn), for example “cifs/host.domain” for SMB or “host/host.domain” / “ldap/host.domain”.
It is created by the consumer (SMB/RPC) and assigned to spnego.AuthContext.Kerberos, keeping crypto/spnego free of any dependency on the Kerberos implementation.
type SPNEGOMechanism struct {
// contains filtered or unexported fields
}
func NewSPNEGOMechanism
func NewSPNEGOMechanism(client *KerberosClient, spn string) *SPNEGOMechanism
NewSPNEGOMechanism builds a mechanism over an existing client (which supplies the credentials and realm) targeting the given service principal name.
func (*SPNEGOMechanism) AcceptResponseToken
func (m *SPNEGOMechanism) AcceptResponseToken(token []byte) error
AcceptResponseToken verifies the server’s KRB_AP_REP (mutual authentication). An empty token is a no-op. A server KRB-ERROR is surfaced with its code.
func (*SPNEGOMechanism) InitToken
func (m *SPNEGOMechanism) InitToken() ([]byte, error)
InitToken acquires (if needed) a TGT and a service ticket for the SPN, then builds the KRB_AP_REQ GSS token to place in the SPNEGO NegTokenInit. Mutual authentication is requested and an initiator subkey is asserted (as Windows GSS clients do).
func (*SPNEGOMechanism) SessionKey
func (m *SPNEGOMechanism) SessionKey() []byte
SessionKey returns the established GSS context key for SMB/RPC message signing and sealing: the negotiated subkey if present, otherwise the service ticket session key.
type SapphireOptions
SapphireOptions describes a sapphire ticket: the privileged account to harvest a genuine PAC for, and the krbtgt key that signs and encrypts the emitted TGT.
type SapphireOptions struct {
// ImpersonateUser is the privileged account (e.g. Administrator) whose real
// PAC to obtain via S4U2Self + U2U.
ImpersonateUser string
// ImpersonateRealm is that account's realm; empty means the client's realm.
ImpersonateRealm string
// Key is the domain krbtgt account's long-term key, which signs the grafted
// PAC (server and KDC signatures) and encrypts the emitted TGT.
Key []byte
// KeyEType is Key's Kerberos encryption type (17 = AES128, 18 = AES256,
// 23 = RC4).
KeyEType int
// SessionKey is the session key sealed in the emitted TGT; a random key of
// SessionEType is generated when nil.
SessionKey []byte
// SessionEType is the session key's encryption type (defaults to RC4).
SessionEType int
// StartTime, EndTime, RenewTill bound the emitted TGT (defaults: now,
// now+10y, EndTime).
StartTime time.Time
EndTime time.Time
RenewTill time.Time
}
type ServiceTicket
ServiceTicket is a service ticket recovered from a .kirbi or ccache, in the shape GetTGS returns: the parsed Ticket, the raw APPLICATION[1] bytes for verbatim re-emission in an AP-REQ, and the associated session key. It supports silver-ticket-style reuse — presenting a captured service ticket to a single service without contacting the KDC.
type ServiceTicket struct {
// Ticket is the parsed service ticket.
Ticket messages.Ticket
// TicketRaw is the raw APPLICATION[1] ticket TLV (feed to messages.APReq{TicketRaw}).
TicketRaw []byte
// SessionKey seals the AP-REQ Authenticator presented to the service.
SessionKey []byte
// SessionEType is the encryption type of SessionKey.
SessionEType int
// Client is the client principal the ticket was issued to.
Client messages.PrincipalName
// CRealm is the client's realm.
CRealm string
// SName is the service principal the ticket is for.
SName messages.PrincipalName
// SRealm is the service's realm.
SRealm string
}
func LoadServiceTicketFromCCacheBytes
func LoadServiceTicketFromCCacheBytes(data []byte, spn string) (*ServiceTicket, error)
LoadServiceTicketFromCCacheBytes parses MIT ccache (v4) bytes and returns the selected service ticket. See LoadServiceTicketFromKirbiBytes for spn matching.
func LoadServiceTicketFromCCacheFile
func LoadServiceTicketFromCCacheFile(path, spn string) (*ServiceTicket, error)
LoadServiceTicketFromCCacheFile reads an MIT ccache file and returns the selected service ticket. See LoadServiceTicketFromKirbiBytes for spn matching.
func LoadServiceTicketFromKirbiBytes
func LoadServiceTicketFromKirbiBytes(data []byte, spn string) (*ServiceTicket, error)
LoadServiceTicketFromKirbiBytes parses .kirbi bytes and returns the service ticket they carry for pass-the-ticket to a single service. When the credential holds several tickets, spn selects one by service principal name (“service/host”, matched case-insensitively); pass "" to take the first ticket.
func LoadServiceTicketFromKirbiFile
func LoadServiceTicketFromKirbiFile(path, spn string) (*ServiceTicket, error)
LoadServiceTicketFromKirbiFile reads a .kirbi file and returns the selected service ticket. See LoadServiceTicketFromKirbiBytes for spn matching.