RFC 4120
The Kerberos Network Authentication Service (V5)
RFC 4120: The Kerberos Network Authentication Service (V5) ๐
okay bestie, let's get into it ๐ซถ this one is RFC 4120, and it's all about Kerberos, the authentication service that helps systems confirm who's who ๐. It came out in July 2005 from the Network Working Group. The main authors are C. Neuman from USC-ISI, plus T. Yu, S. Hartman, and K. Raeburn, all from MIT ๐. It's on the Standards Track, and it obsoletes RFC 1510, which was the earlier Kerberos spec ๐
Status of This Memo โจ
okay so this doc is an Internet standards track protocol for the Internet community ๐ธ They want feedback and suggestions for making it better ๐ If you want to know where this protocol stands in the standardization process, check the current edition of "Internet Official Protocol Standards" (STD 1) ๐ And the memo can be distributed freely, no limits ๐ฆ
Copyright Notice ๐
Copyright (C) The Internet Society (2005) โจ
Abstract ๐ฆ
so this document gives an overview and specification of Version 5 of the Kerberos protocol ๐ฅ It also obsoletes RFC 1510, because RFC 1510 needed some clearer explanations of how the protocol works and how it's supposed to be used ๐ This doc is meant to be a detailed description you can actually implement, along with info on how to use the protocol messages and their fields properly ๐
Table of Contents ๐
1. Introduction ....................................................5
1.1. The Kerberos Protocol ......................................6
1.2. Cross-Realm Operation ......................................8
1.3. Choosing a Principal with Which to Communicate .............9
1.4. Authorization .............................................10
1.5. Extending Kerberos without Breaking Interoperability ......11
1.5.1. Compatibility with RFC 1510 ........................11
1.5.2. Sending Extensible Messages ........................12
1.6. Environmental Assumptions .................................12
1.7. Glossary of Terms .........................................13
2. Ticket Flag Uses and Requests ..................................16
2.1. Initial, Pre-authenticated, and
Hardware-Authenticated Tickets ............................17
2.2. Invalid Tickets ...........................................17
2.3. Renewable Tickets .........................................17
2.4. Postdated Tickets .........................................18
2.5. Proxiable and Proxy Tickets ...............................19
2.6. Forwardable Tickets .......................................19
2.7. Transited Policy Checking .................................20
2.8. OK as Delegate ............................................21
2.9. Other KDC Options .........................................21
2.9.1. Renewable-OK .......................................21
2.9.2. ENC-TKT-IN-SKEY ....................................22
2.9.3. Passwordless Hardware Authentication ...............22
3. Message Exchanges ..............................................22
3.1. The Authentication Service Exchange .......................22
3.1.1. Generation of KRB_AS_REQ Message ...................24
3.1.2. Receipt of KRB_AS_REQ Message ......................24
3.1.3. Generation of KRB_AS_REP Message ...................24
3.1.4. Generation of KRB_ERROR Message ....................27
3.1.5. Receipt of KRB_AS_REP Message ......................27
3.1.6. Receipt of KRB_ERROR Message .......................28
3.2. The Client/Server Authentication Exchange .................29
3.2.1. The KRB_AP_REQ Message .............................29
3.2.2. Generation of a KRB_AP_REQ Message .................29
3.2.3. Receipt of KRB_AP_REQ Message ......................30
3.2.4. Generation of a KRB_AP_REP Message .................33
3.2.5. Receipt of KRB_AP_REP Message ......................33
3.2.6. Using the Encryption Key ...........................33
3.3. The Ticket-Granting Service (TGS) Exchange ................34
3.3.1. Generation of KRB_TGS_REQ Message ..................35
3.3.2. Receipt of KRB_TGS_REQ Message .....................37
3.3.3. Generation of KRB_TGS_REP Message ..................38
3.3.4. Receipt of KRB_TGS_REP Message .....................42
3.4. The KRB_SAFE Exchange .....................................42
3.4.1. Generation of a KRB_SAFE Message ...................42
3.4.2. Receipt of KRB_SAFE Message ........................43
3.5. The KRB_PRIV Exchange .....................................44
3.5.1. Generation of a KRB_PRIV Message ...................44
3.5.2. Receipt of KRB_PRIV Message ........................44
3.6. The KRB_CRED Exchange .....................................45
3.6.1. Generation of a KRB_CRED Message ...................45
3.6.2. Receipt of KRB_CRED Message ........................46
3.7. User-to-User Authentication Exchanges .....................47
4. Encryption and Checksum Specifications .........................48
5. Message Specifications .........................................50
5.1. Specific Compatibility Notes on ASN.1 .....................51
5.1.1. ASN.1 Distinguished Encoding Rules .................51
5.1.2. Optional Integer Fields ............................52
5.1.3. Empty SEQUENCE OF Types ............................52
5.1.4. Unrecognized Tag Numbers ...........................52
5.1.5. Tag Numbers Greater Than 30 ........................53
5.2. Basic Kerberos Types ......................................53
5.2.1. KerberosString .....................................53
5.2.2. Realm and PrincipalName ............................55
5.2.3. KerberosTime .......................................55
5.2.4. Constrained Integer Types ..........................55
5.2.5. HostAddress and HostAddresses ......................56
5.2.6. AuthorizationData ..................................57
5.2.7. PA-DATA ............................................60
5.2.8. KerberosFlags ......................................64
5.2.9. Cryptosystem-Related Types .........................65
5.3. Tickets ...................................................66
5.4. Specifications for the AS and TGS Exchanges ...............73
5.4.1. KRB_KDC_REQ Definition .............................73
5.4.2. KRB_KDC_REP Definition .............................81
5.5. Client/Server (CS) Message Specifications .................84
5.5.1. KRB_AP_REQ Definition ..............................84
5.5.2. KRB_AP_REP Definition ..............................88
5.5.3. Error Message Reply ................................89
5.6. KRB_SAFE Message Specification ............................89
5.6.1. KRB_SAFE definition ................................89
5.7. KRB_PRIV Message Specification ............................91
5.7.1. KRB_PRIV Definition ................................91
5.8. KRB_CRED Message Specification ............................92
5.8.1. KRB_CRED Definition ................................92
5.9. Error Message Specification ...............................94
5.9.1. KRB_ERROR Definition ...............................94
5.10. Application Tag Numbers ..................................96
6. Naming Constraints .............................................97
6.1. Realm Names ...............................................97
6.2. Principal Names .......................................... 99
6.2.1. Name of Server Principals .........................100
7. Constants and Other Defined Values ............................101
7.1. Host Address Types .......................................101
7.2. KDC Messaging: IP Transports .............................102
7.2.1. UDP/IP transport ..................................102
7.2.2. TCP/IP Transport ..................................103
7.2.3. KDC Discovery on IP Networks ......................104
7.3. Name of the TGS ..........................................105
7.4. OID Arc for KerberosV5 ...................................106
7.5. Protocol Constants and Associated Values .................106
7.5.1. Key Usage Numbers .................................106
7.5.2. PreAuthentication Data Types ......................108
7.5.3. Address Types .....................................109
7.5.4. Authorization Data Types ..........................109
7.5.5. Transited Encoding Types ..........................109
7.5.6. Protocol Version Number ...........................109
7.5.7. Kerberos Message Types ............................110
7.5.8. Name Types ........................................110
7.5.9. Error Codes .......................................110
8. Interoperability Requirements .................................113
8.1. Specification 2 ..........................................113
8.2. Recommended KDC Values ...................................116
9. IANA Considerations ...........................................116
10. Security Considerations ......................................117
11. Acknowledgements .............................................121
A. ASN.1 Module ..................................................123
B. Changes since RFC 1510 ........................................131
Normative References .............................................134
Informative References ...........................................135
1. Introduction ๐
Okay bestie, this doc is all about the concepts and model that the Kerberos network authentication system is built on โจ. It also spells out Version 5 of the Kerberos protocol ๐ฆ. The why behind most design choices (motivations, goals, assumptions, rationale) only gets a quick glance here, since it's explained way more fully in a paper in IEEE communications [NT94] and, earlier, in the Kerberos part of the Athena Technical Plan [MNSS87].
This doc is NOT meant to explain Kerberos to end users, sysadmins, or app developers ๐. If you want higher-level reading, [NT94] covers Version 5 and [SNS88] documents version 4, and both are out there elsewhere ๐.
Kerberos' model is partly based on Needham and Schroeder's trusted third-party authentication protocol [NS78], plus some modifications Denning and Sacco suggested [DS81] ๐ง . The original design and implementation of Kerberos Versions 1 through 4 was done by two former Project Athena staff members, Steve Miller of Digital Equipment Corporation and Clifford Neuman (now at the Information Sciences Institute of the University of Southern California), along with Jerome Saltzer, Technical Director of Project Athena, and Jeffrey Schiller, MIT Campus Network Manager. Lots of other Project Athena folks helped with Kerberos too ๐ซถ.
Version 5 (the one this doc describes) evolved because of new requirements and features that Version 4 just didn't have ๐ . Clifford Neuman and John Kohl led the design, with a ton of input from the community. At MIT, John Kohl and Theodore Ts'o led development of the MIT reference implementation, with help and contributed code from many others ๐. Since RFC 1510 came out, lots of people have proposed extensions and revisions to the protocol. This doc reflects some of those proposals, and where a change took serious effort, it credits the person who proposed it ๐ธ.
Reference implementations of both Version 4 and Version 5 are publicly available, and commercial implementations have been developed and are widely used โจ. The differences between Versions 4 and 5 are covered in [KNT94] ๐.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119] ๐ฅ.
1.1. The Kerberos Protocol ๐
Kerberos provides a means of verifying the identities of principals (e.g., a workstation user or a network server) on an open (unprotected) network ๐. Here's the iconic part: it does this without relying on assertions by the host operating system, without basing trust on host addresses, without requiring physical security of all the hosts on the network, and under the assumption that packets traveling along the network can be read, modified, and inserted at will ๐. It pulls this off as a trusted third-party authentication service using conventional (shared secret key) cryptography ๐ง. Extensions to Kerberos (outside the scope of this document) can provide for the use of public key cryptography during certain phases of the authentication protocol ๐. Those extensions support Kerberos authentication for users registered with public key certification authorities, and provide certain benefits of public key cryptography in situations where they're needed โจ.
The basic Kerberos authentication process goes like this: A client sends a request to the authentication server (AS) for "credentials" for a given server. The AS responds with those credentials, encrypted in the client's key. The credentials consist of a "ticket" for the server and a temporary encryption key (often called a "session key"). The client transmits the ticket (which contains the client's identity and a copy of the session key, all encrypted in the server's key) to the server. The session key, now shared by the client and server, is used to authenticate the client and may optionally be used to authenticate the server ๐. It may also be used to encrypt further communication between the two parties, or to exchange a separate sub-session key to be used to encrypt further communication ๐ฆ. Note that many apps only use Kerberos' functions when they initiate a stream-based network connection. Unless an app performs encryption or integrity protection for the data stream, the identity verification only applies to initiating the connection, and it does NOT guarantee that subsequent messages on the connection come from the same principal ๐ญ.
Implementation of the basic protocol consists of one or more authentication servers running on physically secure hosts. These servers maintain a database of principals (i.e., users and servers) and their secret keys ๐. Code libraries provide encryption and implement the Kerberos protocol. To add authentication to its transactions, a typical network application adds calls to the Kerberos library directly, or goes through the Generic Security Services Application Programming Interface (GSS-API) described in a separate document [RFC4121] ๐ . These calls result in the transmission of the messages necessary to achieve authentication ๐.
The Kerberos protocol consists of several sub-protocols (or exchanges). There are two basic methods by which a client can ask a Kerberos server for credentials ๐ง. In the first approach, the client sends a cleartext request for a ticket for the desired server to the AS. The reply is sent encrypted in the client's secret key. Usually this request is for a ticket-granting ticket (TGT), which can later be used with the ticket-granting server (TGS). In the second method, the client sends a request to the TGS. The client uses the TGT to authenticate itself to the TGS in the same manner as if it were contacting any other application server that requires Kerberos authentication. The reply is encrypted in the session key from the TGT ๐. Though the protocol specification describes the AS and the TGS as separate servers, in practice they are implemented as different protocol entry points within a single Kerberos server ๐.
Once obtained, credentials may be used to verify the identity of the principals in a transaction, to ensure the integrity of messages exchanged between them, or to preserve privacy of the messages ๐ธ. The application is free to choose whatever protection may be necessary โจ.
To verify the identities of the principals in a transaction, the client transmits the ticket to the application server. Because the ticket is sent "in the clear" (parts of it are encrypted, but this encryption doesn't thwart replay) and might be intercepted and reused by an attacker, additional information is sent to prove that the message originated with the principal to whom the ticket was issued ๐ต๏ธ. This information (called the authenticator) is encrypted in the session key and includes a timestamp โฐ. The timestamp proves that the message was recently generated and is not a replay. Encrypting the authenticator in the session key proves that it was generated by a party possessing the session key. Since no one except the requesting principal and the server know the session key (it is never sent over the network in the clear), this guarantees the identity of the client ๐ซถ.
The integrity of the messages exchanged between principals can also be guaranteed by using the session key (passed in the ticket and contained in the credentials) ๐. This approach provides detection of both replay attacks and message stream modification attacks ๐จ. It is accomplished by generating and transmitting a collision-proof checksum (elsewhere called a hash or digest function) of the client's message, keyed with the session key. Privacy and integrity of the messages exchanged between principals can be secured by encrypting the data to be passed by using the session key contained in the ticket or the sub-session key found in the authenticator ๐ฆ.
The authentication exchanges mentioned above require read-only access to the Kerberos database. Sometimes, however, the entries in the database must be modified, such as when adding new principals or changing a principal's key ๐ ๏ธ. This is done using a protocol between a client and a third Kerberos server, the Kerberos Administration Server (KADM). There is also a protocol for maintaining multiple copies of the Kerberos database. Neither of these protocols are described in this document ๐.
1.2. Cross-Realm Operation ๐
okay bestie, Kerberos is literally built to work across organizations ๐ซถ A client in one org can get authenticated to a server in a totally different org. Every org that wants to run a Kerberos server sets up its own "realm" ๐ฐ The realm a client is registered in is part of the client's name โจ, and the end-service can use that name to decide whether to honor a request ๐
So when two realms' admins set up "inter-realm" keys ๐, a client who's authenticated in their home realm can prove who they are to servers in the other realm. You can use a separate key for each direction (iykyk ๐). Exchanging them registers each realm's ticket-granting service as a principal in the other realm ๐. Now the client can grab a TGT for the remote realm's ticket-granting service from their own local realm ๐๏ธ. When that TGT gets used, the remote ticket-granting service decrypts it with the inter-realm key, which is usually different from its own normal TGS key. That means it's certain the ticket came from the client's own TGS ๐. Tickets the remote ticket-granting service hands out will tell the end-service that the client was authenticated from another realm ๐ฆ.
Without cross-realm operation, a client can (with the right permission) get a separately-named principal set up in a remote realm and do normal stuff with that realm's services. But even for small numbers of clients that gets super cumbersome ๐ญ, so the more automatic methods described here are necessary.
A realm communicates with another realm if they share an inter-realm key, or if the local realm shares one with an intermediate realm that talks to the remote realm ๐. An authentication path is just the sequence of intermediate realms you pass through to get from one realm to another ๐ค๏ธ.
Realms can be arranged hierarchically ๐ณ. Each realm shares a key with its parent and a different key with each child. If two realms don't directly share an inter-realm key, the hierarchy makes it pretty easy to build an authentication path ๐ง.
If there's no hierarchical organization, you might have to consult a database to build an authentication path between realms ๐.
Even though realms are usually hierarchical, intermediate realms can be skipped to do cross-realm auth through alternate paths. (Those might be set up to make things between two realms more efficient โก.) It really matters for the end-service to know which realms were transited when it decides how much faith to put in the auth ๐ค. So a field in each ticket holds the names of the realms that were involved in authenticating the client ๐.
The application server is ultimately responsible for accepting or rejecting authentication, and it SHOULD check the transited field ๐ก๏ธ. It can choose to rely on the Key Distribution Center (KDC) for its own realm to check the transited field instead. In that case, the application server's KDC sets the TRANSITED-POLICY-CHECKED flag. KDCs for intermediate realms can check the transited field too when they issue TGTs for other realms, but they're encouraged not to ๐. A client can ask the KDCs not to check the transited field by setting the DISABLE-TRANSITED-CHECK flag, and KDCs SHOULD honor this flag ๐ซก.
1.3. Choosing a Principal with Which to Communicate ๐ฏ
Kerberos gives you a way to verify (subject to the assumptions in Section 1.6) that the entity you're talking to is the one registered with the KDC under the claimed identity (principal name) ๐ต๏ธ. You still have to figure out whether that identity is the entity you actually meant to talk to ๐คจ.
When the right data was exchanged in advance, the application can make that call syntactically, based on the application protocol spec, info the user gave, and config files ๐. For example, the server principal name (realm included) for a telnet server might come from the host name the user typed on the telnet command line, the host/ prefix from the application protocol spec, and a mapping to a Kerberos realm derived syntactically from the domain part of the host name plus info from the local Kerberos realms database ๐บ๏ธ.
You can also lean on trusted third parties for this, but only when the data they give you is suitably integrity-protected, both while it sits on their server and while it's being sent. So, for example, don't rely on an unprotected DNS record to map a host alias to a server's primary name and then accept that primary name as the party you meant to contact ๐ซ. An attacker can modify the mapping and impersonate the party, bestie ๐ฑ.
Implementations of Kerberos and protocols based on Kerberos MUST NOT use insecure DNS queries to canonicalize the hostname components of service principal names (basically, they MUST NOT use insecure DNS queries to map one name to another and figure out the host part of the principal name you're about to talk to) ๐ โโ๏ธ
In an environment without a secure name service, application authors MAY append a statically configured domain name to unqualified hostnames before passing the name to the security mechanisms, but they should do no more than that ๐ง. Secure name service facilities, if available, might be trusted for hostname canonicalization, but client-side canonicalization like that SHOULD NOT be required by KDC implementations ๐.
Implementation note: Lots of current implementations canonicalize the provided service name in some way, often using DNS even though that creates security problems ๐. But there's no consistency among them. Some case-fold the name to lowercase and some don't, and some use reverse resolution while others don't ๐คท. To maximize interoperability and security, applications SHOULD give security mechanisms names that result from folding the user-entered name to lowercase, without any other modifications or canonicalization โจ.
1.4. Authorization ๐
As an authentication service, Kerberos gives you a means of verifying the identity of principals on a network ๐ชช. Authentication is usually most useful as the first step of authorization, which is figuring out whether a client may use a service, which objects it's allowed to access, and what type of access it gets for each one ๐. But Kerberos does not provide authorization by itself ๐ . Having a client ticket for a service only gets you authentication to that service. Without a separate authorization procedure, an application should not consider the ticket to authorize use of that service ๐ช.
Separate authorization methods MAY be implemented as application-specific access control functions. They may use files on the application server, separately issued authorization credentials (like ones based on proxies [Neu93]), or other authorization services ๐๏ธ. Separately authenticated authorization credentials MAY be embedded in a ticket's authorization data when they're encapsulated by the KDC-issued authorization data element ๐.
Applications should not accept the mere issuance of a service ticket by the Kerberos server (even by a modified Kerberos server) as granting authority to use the service โ. Why? Because those apps may become vulnerable to bypassing this authorization check in an environment where other options for application authentication exist, or if they interoperate with other KDCs ๐ฌ.
1.5. Extending Kerberos without Breaking Interoperability ๐งฉ
As the deployed base of Kerberos implementations grows, extending Kerberos gets more important ๐. Unfortunately, some extensions to the existing protocol create interoperability issues, because of uncertainty about how some implementations treat certain extensibility options ๐ต. This section has guidelines that will help future implementations keep interoperating ๐ซถ.
Kerberos has a general mechanism for protocol extensibility. Some protocol messages contain typed holes, which are sub-messages that contain an octet-string along with an integer that defines how to interpret that octet-string ๐ง . The integer types are registered centrally, but they can be used both for vendor extensions and for extensions standardized through the IETF ๐.
In this document, the word "extension" refers to extension by defining a new type to insert into an existing typed hole in a protocol message. It doesn't refer to extension by adding new fields to ASN.1 types, unless the text explicitly indicates otherwise ๐.
1.5.1. Compatibility with RFC 1510 ๐
Existing Kerberos message formats can't readily be extended by adding fields to the ASN.1 types ๐ . Sending extra fields often gets the entire message discarded without any error indication ๐. Future versions of this specification will give guidelines to make sure ASN.1 fields can be added without creating an interoperability problem ๐ฎ.
In the meantime, all new or modified implementations of Kerberos that receive an unknown message extension SHOULD preserve the encoding of the extension but otherwise ignore its presence ๐ซถ. Recipients MUST NOT decline a request simply because an extension is present ๐.
There's one exception to this rule. If an unknown authorization data element type is received by a server other than the ticket-granting service, either in an AP-REQ or in a ticket contained in an AP-REQ, then authentication MUST fail ๐จ. One of the main uses of authorization data is restricting the use of the ticket. If the service can't determine whether the restriction applies to it, a security weakness may result if the ticket can be used for that service ๐ฑ.
Authorization elements that are optional SHOULD be enclosed in the AD-IF-RELEVANT element ๐.
The ticket-granting service MUST ignore but propagate to derivative tickets any unknown authorization data types, unless those data types are embedded in a MANDATORY-FOR-KDC element, in which case the request will be rejected ๐ซ. This behavior makes sense because requiring the ticket-granting service to understand unknown authorization data types would mean KDC software has to be upgraded to understand new application-level restrictions before applications use them. That would decrease the usefulness of authorization data as a way to restrict ticket use ๐. No security problem is created, because the services the tickets are issued to will verify the authorization data ๐ก๏ธ.
Implementation note: Many RFC 1510 implementations ignore unknown authorization data elements. Depending on these implementations to honor authorization data restrictions may create a security weakness ๐ฅบ
1.5.2. Sending Extensible Messages โจ
okay so old implementations need to be able to understand messages sent to them, even if they don't understand an extension that's being used ๐ Unless the sender knows an extension is supported, that extension can't change the semantics of the core message or the extensions that were already defined ๐
for example, an extension that includes the key info needed to decrypt the encrypted part of a KDC-REP could only be used when the recipient is known to support it ๐ so when you design these, you have to give the recipient a way to tell the sender it supports the extension ๐ซถ like, if an extension changes the KDC-REP reply key, the client can signal support by including a padata element in the AS-REQ sequence ๐ the KDC should only use the extension if that padata element is there in the AS-REQ ๐ even if policy says the extension is required, it's better to return an error saying so than to use it when the recipient might not support it ๐ญ debugging implementations that don't interoperate is way easier when errors actually get returned ๐ง
1.6. Environmental Assumptions ๐ธ
Kerberos has a few assumptions about the environment it needs to work properly, and they're lowkey important, so let's go ๐
- "Denial of service" attacks aren't solved by Kerberos ๐ There are spots in the protocols where an intruder can stop an application from taking part in the proper authentication steps. Spotting and fixing those attacks (some of which can look like totally normal failure modes for the system) is usually best left to the human admins and users ๐
- Principals MUST keep their secret keys secret ๐ฅ If an intruder steals a principal's key, they can masquerade as that principal, or impersonate any server to the legit principal. Not me being dramatic, this is serious ๐ญ
- "Password guessing" attacks aren't solved by Kerberos either ๐ If a user picks a weak password, an attacker can run an offline dictionary attack: they keep trying to decrypt messages they've grabbed, which are encrypted under a key derived from the user's password, using entries from a dictionary ๐ฆ
- Each host on the network MUST have a clock that's "loosely synchronized" with the other hosts' clocks โฐ This synchronization is used to cut down on the bookkeeping application servers need for replay detection. The amount of "looseness" can be configured per server, but it's typically around 5 minutes โจ If the clocks are synchronized over the network, the clock synchronization protocol MUST itself be secured from network attackers ๐ก๏ธ
- Principal identifiers aren't recycled on a short-term basis ๐ A common way to do access control is with access control lists (ACLs) that grant permissions to particular principals. If a stale ACL entry sticks around for a deleted principal, and that principal identifier gets reused, the new principal would inherit the rights in the stale entry ๐ณ Not reusing principal identifiers removes the danger of accidental access ๐ซถ
1.7. Glossary of Terms ๐
Here's a list of terms used all through this document, so you're never lost ๐ง
Authentication Verifying the claimed identity of a principal. โ
Authentication header A record containing a Ticket and an Authenticator, presented to a server as part of the authentication process. ๐๏ธ
Authentication path A sequence of intermediate realms that get transited during the authentication process when you're communicating from one realm to another. ๐ค๏ธ
Authenticator A record with info that can be shown to have been recently generated using the session key that only the client and server know. ๐
Authorization The process of figuring out whether a client may use a service, which objects the client can access, and what type of access is allowed for each. ๐
Capability A token that grants the bearer permission to access an object or service. In Kerberos, this might be a ticket whose use is restricted by the contents of the authorization data field, but which lists no network addresses, together with the session key needed to use the ticket. ๐ซ
Ciphertext The output of an encryption function. Encryption turns plaintext into ciphertext. ๐
Client A process that uses a network service on behalf of a user. Note that in some cases a Server may itself be a client of some other server (for example, a print server may be a client of a file server). ๐ป
Credentials A ticket plus the secret session key needed to use that ticket successfully in an authentication exchange. ๐ชช
Encryption Type (etype) When it's attached to encrypted data, an encryption type tells you which algorithm was used to encrypt the data, and it's used to pick the right algorithm for decrypting it ๐งฉ Encryption type tags get passed around in other messages to list algorithms that are desired, supported, preferred, or allowed for encrypting data between parties. That preference gets combined with local info and policy to choose the algorithm that actually gets used โจ
KDC Key Distribution Center ๐ฐ A network service that supplies tickets and temporary session keys, or an instance of that service, or the host it runs on. The KDC services both initial ticket and ticket-granting ticket requests. The initial ticket portion is sometimes called the Authentication Server (or service), and the ticket-granting ticket portion is sometimes called the ticket-granting server (or service). ๐
Kerberos The name given to Project Athena's authentication service, the protocol that service uses, or the code that implements it. The name comes from the three-headed dog that guards Hades ๐โ๐ฆบ๐ฅ
Key Version Number (kvno) A tag attached to encrypted data that says which key was used for encryption when a long-lived key tied to a principal changes over time ๐ It's used during the transition to a new key, so whoever decrypts a message can tell whether the data was encrypted with the old key or the new one ๐๏ธ
Plaintext The input to an encryption function, or the output of a decryption function. Decryption turns ciphertext back into plaintext ๐
Principal A named client or server entity that takes part in a network communication, with one name considered canonical ๐ค
Principal identifier The canonical name used to uniquely identify each different principal ๐
Seal To encipher a record with several fields in a way that the fields can't be individually replaced without knowing the encryption key, or without leaving evidence of tampering ๐ซ
Secret key An encryption key shared by a principal and the KDC, distributed outside the bounds of the system, with a long lifetime. For a human user's principal, the secret key MAY be derived from a password ๐คซ
Server A particular Principal that provides a resource to network clients. The server is sometimes called the Application Server ๐ฅ๏ธ
Service A resource provided to network clients, often provided by more than one server (remote file service is a classic example) ๐๏ธ
Session key A temporary encryption key used between two principals, lasting only as long as a single login "session". In the Kerberos system, the KDC generates the session key. It's different from the sub-session key, which comes next ๐
Sub-session key A temporary encryption key used between two principals, selected and exchanged by the principals using the session key, and lasting only as long as a single association. It's also called the subkey ๐ง
Ticket A record that helps a client authenticate itself to a server. It contains the client's identity, a session key, a timestamp, and other info, all sealed using the server's secret key ๐๏ธ It only authenticates a client when it's presented along with a fresh Authenticator ๐
2. Ticket Flag Uses and Requests ๐ฉ
Every Kerberos ticket has a set of flags that describe its attributes โจ Most flags can be requested by a client when the ticket is obtained, and some get turned on and off automatically by a Kerberos server when needed ๐ค The sections below explain what the flags mean and give examples of why you'd use them ๐ Apart from the INVALID flag, clients MUST ignore ticket flags they don't recognize ๐ KDCs MUST ignore KDC options they don't recognize too ๐ซถ Some RFC 1510 implementations are known to reject unknown KDC options, so clients may need to resend a request without the new KDC options if it got rejected when those options were added after RFC 1510 ๐ญ Because new KDCs ignore unknown options, clients MUST confirm that the ticket the KDC returns actually meets their needs ๐
Heads up: it's generally not possible to tell whether an option wasn't honored because the KDC didn't understand it, or because it was rejected by configuration or policy ๐ซ When you add a new option to Kerberos, designers should consider whether that distinction matters for their option. If it does, the spec of the option needs to provide a way for the KDC to say the option was understood but rejected. Usually that mechanism has to be broad enough to return an error or a reason ๐
2.1. Initial, Pre-authenticated, and Hardware-Authenticated Tickets ๐ซ
The INITIAL flag means a ticket was issued using the AS protocol, rather than being issued based on a TGT ๐ฑ Application servers that want proof the client knows its secret key (like a password-changing program) can insist that this flag is set on any tickets they accept. That way they can be sure the client's key was recently presented to the authentication server ๐
The PRE-AUTHENT and HW-AUTHENT flags give extra info about the initial authentication ๐ง This is true whether the current ticket was issued directly (in which case INITIAL will also be set) or issued based on a TGT (in which case the INITIAL flag is clear, but PRE-AUTHENT and HW-AUTHENT are carried forward from the TGT) ๐ฆ
2.2. Invalid Tickets ๐ซ
The INVALID flag means a ticket is invalid. Application servers MUST reject tickets that have this flag set ๐ โโ๏ธ A postdated ticket gets issued in this form. Invalid tickets MUST be validated by the KDC before use, by presenting them to the KDC in a TGS request with the VALIDATE option specified ๐ซถ The KDC only validates tickets after their starttime has passed ๐ฐ๏ธ The validation is required so that postdated tickets stolen before their starttime can be made permanently invalid (through a hot-list mechanism) (see Section 3.3.3.1) ๐ฅ Main character energy for security, honestly ๐
2.3. Renewable Tickets โจ
okay so apps sometimes want tickets that stay valid for super long stretches ๐ฐ๏ธ, but that's kinda risky bc if someone steals one, it works until it expires ๐ญ. Grabbing short-lived tickets over and over sounds safer, but then the client needs long-term access to its secret key, and that's an even bigger risk ๐. Enter renewable tickets ๐ฆ, which help limit the damage from theft.
Renewable tickets have two "expiration times." The first is when the current instance of the ticket expires. The second is the latest permissible value for an individual expiration time. So an application client has to keep refreshing (i.e., before it expires) by presenting a renewable ticket to the KDC with the RENEW option set in the KDC request ๐. The KDC then issues a new ticket with a new session key and a later expiration time ๐ธ. Every other field stays the same during renewal. Once the latest permissible expiration time arrives, the ticket expires for good ๐ชฆ. At each renewal, the KDC MAY consult a hot-list to check whether the ticket was reported stolen since its last renewal. If it was, the KDC will refuse to renew it, so stolen tickets get a much shorter usable life ๐ซ.
The RENEWABLE flag is normally only interpreted by the ticket-granting service (discussed below in Section 3.3). Application servers can usually ignore it. However, some particularly careful application servers MAY disallow renewable tickets ๐ง.
If a renewable ticket isn't renewed by its expiration time, the KDC won't renew it. The RENEWABLE flag is reset by default, but a client MAY request that it be set by setting the RENEWABLE option in the KRB_AS_REQ message ๐. If it's set, then the renew-till field in the ticket holds the time after which the ticket may not be renewed โณ.
2.4. Postdated Tickets ๐ง
sometimes apps need tickets for way later, like a batch submission system that needs tickets to be valid when the batch job actually gets serviced ๐ฆ. But holding valid tickets in a batch queue is risky, since they're online longer and more prone to theft ๐. Postdated tickets fix this ๐ . You get them from the KDC at job submission time, but they stay "dormant" until they're activated and validated by a further request to the KDC. If a theft got reported in the meantime, the KDC would refuse to validate the ticket, and the thief is foiled ๐ โโ๏ธโจ.
The MAY-POSTDATE flag is normally only interpreted by the ticket-granting service. Application servers can ignore it. This flag MUST be set in a TGT in order to issue a postdated ticket based on the presented ticket ๐. It's reset by default, but a client MAY request it by setting the ALLOW-POSTDATE option in the KRB_AS_REQ message. This flag does NOT let a client get a postdated TGT. Postdated TGTs can only be obtained by requesting the postdating in the KRB_AS_REQ message ๐.
The life (endtime-starttime) of a postdated ticket will be the remaining life of the TGT at request time. The exception is when the RENEWABLE option is also set. Then it can be the full life (endtime-starttime) of the TGT ๐. The KDC MAY limit how far in the future a ticket may be postdated ๐
.
The POSTDATED flag shows that a ticket has been postdated. The application server can check the authtime field in the ticket to see when the original authentication happened ๐ต๏ธโโ๏ธ. Some services MAY choose to reject postdated tickets, or they may only accept them within a certain period after the original authentication. When the KDC issues a POSTDATED ticket, it'll also be marked as INVALID, so the application client MUST present the ticket to the KDC to be validated before use ๐ซถ.
2.5. Proxiable and Proxy Tickets ๐ญ
sometimes a principal needs to let a service do something on its behalf. The service has to be able to take on the client's identity, but only for one particular purpose ๐ฏ. A principal can allow this by granting the service a proxy.
Granting a proxy with the proxy and proxiable flags is how you get credentials for specific services. It's kinda a proxy too, but users who want to delegate their identity in a form that works for ALL purposes MUST use the ticket forwarding mechanism described in the next section to forward a TGT ๐๏ธ.
The PROXIABLE flag is normally only interpreted by the ticket-granting service. Application servers can ignore it. When it's set, it tells the ticket-granting server that it's OK to issue a new ticket (but not a TGT) with a different network address based on this ticket ๐โโ๏ธ. This flag is set if the client requests it on initial authentication. By default, the client asks for it to be set when requesting a TGT, and asks for it to be reset when requesting any other ticket ๐.
This flag lets a client pass a proxy to a server so it can make a remote request on the client's behalf. Like, a print service client can give the print server a proxy to access the client's files on a particular file server so the print job can go through ๐จ๏ธ๐.
Kerberos tickets are often only valid from the network addresses included in them, which makes stolen credentials harder to use ๐งฑ. It's also allowed as a policy option to allow requests and issue tickets with no network addresses specified. When granting a proxy, the client MUST specify the new network address the proxy will be used from, OR say that the proxy is for use from any address ๐.
The PROXY flag gets set in a ticket by the TGS when it issues a proxy ticket. Application servers MAY check this flag. They can also, at their option, MAY require additional authentication from the agent presenting the proxy, which gives them an audit trail ๐ต๏ธ.
2.6. Forwardable Tickets ๐ฆ
authentication forwarding is a kind of proxy where the service gets COMPLETE use of the client's identity ๐ชช. Example: a user logs in to a remote system and wants authentication to work from there like the login was local ๐ .
The FORWARDABLE flag is normally only interpreted by the ticket-granting service. Application servers can ignore it. It works a lot like PROXIABLE, except TGTs can also be issued with different network addresses ๐. The flag is reset by default, but users MAY request that it be set by setting the FORWARDABLE option in the AS request when they ask for their initial TGT ๐.
This flag lets authentication be forwarded without the user having to type their password again ๐. If the flag isn't set, authentication forwarding isn't allowed. You can still get the same result if the user goes through the AS exchange, specifies the requested network addresses, and supplies a password ๐.
The TGS sets the FORWARDED flag when a client presents a ticket with FORWARDABLE set and asks for a forwarded ticket by specifying the FORWARDED KDC option and giving a set of addresses for the new ticket ๐จ. It's also set in all tickets issued based on tickets with the FORWARDED flag set. Application servers may choose to process FORWARDED tickets differently from non-FORWARDED tickets ๐.
If addressless tickets get forwarded from one system to another, clients SHOULD still use this option to get a new TGT, so the different systems end up with different session keys ๐โจ.
2.7. Transited Policy Checking ๐ต๏ธโโ๏ธ
in Kerberos, the application server is ultimately responsible for accepting or rejecting authentication. It SHOULD check that only suitably trusted KDCs are relied on to authenticate a principal ๐ง. The transited field in the ticket says which realms (and therefore which KDCs) were involved in the authentication process, and an application server would normally check it ๐. If any of those are untrusted to authenticate the client principal (usually decided by a realm-based policy), the authentication attempt MUST be rejected ๐ซ. Having trusted KDCs on that list doesn't guarantee anything, though, bc an untrusted KDC could have faked the list ๐.
Even though the end server makes the final call, the KDC for the end server's realm MAY apply a realm-specific policy for validating the transited field and accepting credentials for cross-realm authentication. When the KDC runs those checks and accepts the cross-realm authentication, it sets the TRANSITED-POLICY-CHECKED flag in the service tickets it issues based on the cross-realm TGT ๐๏ธ. A client MAY ask the KDCs not to check the transited field by setting the DISABLE-TRANSITED-CHECK flag. KDCs are encouraged but not required to honor this flag ๐คทโโ๏ธ.
Application servers MUST either do the transited-realm checks themselves, or reject cross-realm tickets without TRANSITED-POLICY-CHECKED set ๐ก๏ธ.
2.8. OK as Delegate ๐
sometimes a client needs to give a server the authority to act on its behalf when it contacts other services ๐ฌ. That means the client forwards credentials to an intermediate server. Being able to get a service ticket for a server tells the client NOTHING about whether that server should be trusted to accept delegated credentials ๐
โโ๏ธ. The OK-AS-DELEGATE flag gives the KDC a way to share local realm policy with the client about whether an intermediate server can be trusted with those credentials ๐ซก.
The copy of the ticket flags in the encrypted part of the KDC reply may have the OK-AS-DELEGATE flag set. That tells the client the realm's policy has decided the server named in the ticket is a suitable recipient of delegation โ
. The client can use that flag to help decide whether to delegate credentials (grant either a proxy or a forwarded TGT) to this server ๐ค. It's totally acceptable to ignore the value of this flag. When setting it, an administrator should think about the security and placement of the server where the service runs, plus whether the service even needs delegated credentials ๐๏ธ.
2.9. Other KDC Options ๐ธ
there are three additional options that MAY be set in a client's request to the KDC. Here's the first one ๐.
2.9.1. Renewable-OK ๐
The RENEWABLE-OK option says the client will accept a renewable ticket if a ticket with the requested life can't be provided any other way ๐. If that's the case, the KDC MAY issue a renewable ticket with a renew-till equal to the requested endtime ๐ซ. The value of the renew-till field MAY still be adjusted by site-determined limits, or by limits imposed by the individual principal or server ๐ง.
2.9.2. ENC-TKT-IN-SKEY โจ
okay so basic Kerberos is giving client-server energy ๐ and it's not really built for peer-to-peer, because the user's long-term key doesn't stick around on the workstation after initial login ๐ญ. peers can still get authenticated though, through the user-to-user variant ๐ซถ. the ENC-TKT-IN-SKEY option is how that works: it lets the KDC issue a service ticket encrypted with the session key from another TGT that was issued to a different user ๐ . only the ticket-granting service honors this one ๐. it basically says the ticket for the end server should be encrypted in the session key from the extra second TGT that came along with the request. check Section 3.3.3 for the deets ๐ง
2.9.3. Passwordless Hardware Authentication
OPT-HARDWARE-AUTH means the client wants some kind of hardware authentication, either instead of or on top of its password or other long-lived encryption key ๐. only the authentication service honors this one ๐. if it's supported and policy allows it, the KDC sends back KDC_ERR_PREAUTH_REQUIRED along with the required METHOD-DATA for doing that authentication ๐.
3. Message Exchanges ๐ฆ
these sections are all about how clients and servers talk to each other and which messages get passed back and forth ๐ฌ.
3.1. The Authentication Service Exchange
Summary
Message direction Message type Section
1. Client to Kerberos KRB_AS_REQ 5.4.1
2. Kerberos to client KRB_AS_REP or 5.4.2
KRB_ERROR 5.9.1
okay so the Authentication Service (AS) Exchange happens between the client and the Kerberos Authentication Server, and a client starts it when it wants credentials for a server but doesn't have any yet ๐ซ. in its basic form it uses the client's secret key for encryption and decryption ๐. this is usually how a login session kicks off: you grab credentials for a Ticket-Granting Server, and that one gets you credentials for other servers (see Section 3.3) without needing your secret key again ๐. it's also used for services that must not go through the Ticket-Granting Service and need you to prove you know a principal's secret key, like the password-changing service ๐. that one denies requests unless you can show your old password, because otherwise someone walking up to an unattended session could change your password ๐.
this exchange doesn't prove who the user is by itself ๐จ. to log a user in locally, the AS credentials can first be used in a TGS exchange to get credentials for a local server, and then those credentials have to be verified by a local server through a successful Client/Server exchange โ .
the AS exchange has two messages: KRB_AS_REQ from the client to Kerberos, and KRB_AS_REP or KRB_ERROR back in reply. the formats are in Sections 5.4.1, 5.4.2, and 5.9.1 ๐.
in the request, the client sends (in cleartext) its own identity, the identity of the server it wants credentials for, other info about those credentials, and a randomly generated nonce ๐ฒ. the nonce can be used to detect replays and to match replies with their requests. this nonce MUST be generated randomly by the client and remembered so it can be checked against the nonce in the expected reply ๐ง . the response, KRB_AS_REP, has a ticket for the client to show the server, plus a session key that the client and server will share ๐ค. the session key and extra info are encrypted in the client's secret key ๐. the encrypted part of KRB_AS_REP also contains the nonce, which MUST be matched with the nonce from the KRB_AS_REQ message โจ.
without pre-authentication, the authentication server doesn't know whether the client is actually the principal named in the request ๐คทโโ๏ธ. it just sends a reply without knowing or caring whether they're the same. that's fine because nobody except the principal named in the request can use the reply, since the critical info is encrypted in that principal's key ๐๏ธ. but an attacker can send a KRB_AS_REQ message to get known plaintext and go after the principal's key ๐ฑ. especially if the key is based on a password, that's a real security exposure ๐. so the initial request has an optional field that can pass extra info the initial exchange might need. this field SHOULD be used for pre-authentication, as described in sections 3.1.1 and 5.2.7 ๐ก๏ธ.
various errors can happen, and they show up as a KRB_ERROR response instead of KRB_AS_REP ๐. the error message is not encrypted. the KRB_ERROR message has info that helps associate it with the message it replies to. its contents aren't integrity-protected, so the client can't detect replays, fabrications, or modifications ๐ซฃ. a fix for this will be included in a future version of the protocol ๐ฎ.
3.1.1. Generation of KRB_AS_REQ Message
the client can set a bunch of options in the initial request ๐. these include whether pre-authentication is performed, whether the requested ticket is renewable, proxiable, or forwardable, and whether it should be postdated or allow postdating of derivative tickets ๐ . they also include whether a renewable ticket will be accepted in place of a non-renewable one, if the requested expiration date can't be met by a non-renewable ticket because of configuration constraints โ๏ธ.
the client prepares the KRB_AS_REQ message and sends it to the KDC ๐จ.
3.1.2. Receipt of KRB_AS_REQ Message
if all goes well, processing the KRB_AS_REQ message creates a ticket for the client to present to the server ๐๏ธ. the format is in Section 5.3 ๐ซ.
because Kerberos can run over unreliable transports like UDP, the KDC MUST be prepared to retransmit responses in case they get lost ๐. if a KDC gets a request identical to one it recently processed successfully, the KDC MUST respond with a KRB_AS_REP message rather than a replay error ๐. to reduce the ciphertext given to a potential attacker, KDCs MAY send the same response that was generated when the request was first handled ๐ค. KDCs MUST obey this replay behavior even if the actual transport in use is reliable ๐ซถ.
3.1.3. Generation of KRB_AS_REP Message โจ
Okay bestie, the authentication server (aka the KDC, the main character here ๐) starts by looking up the client and server principals named in the KRB_AS_REQ in its database and pulling out their keys ๐. If the client principal in the request doesn't exist in the KDC's principal database, it sends back KDC_ERR_C_PRINCIPAL_UNKNOWN. ๐
Next, if the server is supposed to pre-authenticate the request, it does. If that check fails, you get KDC_ERR_PREAUTH_FAILED. ๐ If pre-auth is required but the request didn't include it, you get KDC_ERR_PREAUTH_REQUIRED, and a METHOD-DATA object goes in the e-data field of the KRB-ERROR to say which pre-auth mechanisms are acceptable. Usually that includes PA-ETYPE-INFO and/or PA-ETYPE-INFO2 elements, as described below. And if the server can't support any encryption type the client asked for, it's KDC_ERR_ETYPE_NOSUPP time ๐ญ
Then comes the fun part: the KDC makes a 'random' session key. That means, among other things, it should be impossible to guess the next session key from the past ones ๐. A pseudo-random number generator can do this if it's built on cryptographic principles, but it's way more iconic to use a truly random number generator, like one based on measurements of random physical phenomena ๐. For the full tea on randomness, check out [RFC4086].
When there are multiple encryption keys registered for a client in the Kerberos database, the KDC uses the etype field from the AS request to pick the encryption method that protects the encrypted part of the KRB_AS_REP message going back to the client. If there's more than one supported strong encryption type in the etype list, the KDC SHOULD use the first valid strong etype that has an encryption key available ๐
When the user's key comes from a password or pass phrase, the string-to-key function for that encryption key type is used, as specified in [RFC3961] โจ. The salt and the extra parameters for that function have default values (set by Section 4 and by the encryption mechanism spec, respectively), but pre-authentication data (PA-PW-SALT, PA-AFS3-SALT, PA-ETYPE-INFO, PA-ETYPE-INFO2, etc.) can override them. Since the KDC is presumed to store only a copy of the resulting key, these values should not be changed for password-based keys, except when changing the principal's key ๐ซถ
When the AS server includes pre-authentication data in a KRB-ERROR or an AS-REP, it MUST use PA-ETYPE-INFO2, not PA-ETYPE-INFO, if the etype field of the client's AS-REQ lists at least one "newer" encryption type. Otherwise, when the etype field doesn't list any "newer" encryption types, it MUST send both PA-ETYPE-INFO2 and PA-ETYPE-INFO, with an entry for each enctype ๐ฆ. A "newer" enctype is any enctype first officially specified at the same time as, or after, the issue of this RFC. DES, 3DES, RC4, and anything defined in [RFC1510] are NOT "newer" enctypes ๐
Also, you can't reliably generate a user's key from a pass phrase without contacting the KDC, because nobody can know ahead of time whether alternate salt or parameter values are needed ๐
The KDC tries to assign the type of the random session key from the list of methods in the etype field. It picks the right type using that list plus info from the Kerberos database about which encryption methods are acceptable for the application server. The KDC will not issue tickets with a weak session key encryption type ๐ซ
If the requested starttime is absent, points to the past, or is within the acceptable clock skew for the KDC, and the POSTDATE option hasn't been specified, then the ticket's starttime is set to the authentication server's current time โฐ. If it points to the future beyond the acceptable clock skew, but the POSTDATED option hasn't been specified, you get KDC_ERR_CANNOT_POSTDATE. Otherwise, the requested starttime gets checked against the local realm's policy, since the administrator might ban certain types or ranges of postdated tickets. If the starttime is acceptable, it's set as requested and the INVALID flag is set in the new ticket ๐ธ. A postdated ticket MUST be validated before use, by presenting it to the KDC after the starttime has been reached.
The expiration time of the ticket is set to the earlier of the requested endtime and a time determined by local policy, which can use realm- or principal-specific factors. For example, the expiration time MAY be set to the earliest of the following:
- The expiration time (endtime) requested in the KRB_AS_REQ message.
- The ticket's starttime plus the maximum allowable lifetime associated with the client principal from the authentication server's database.
- The ticket's starttime plus the maximum allowable lifetime associated with the server principal.
- The ticket's starttime plus the maximum lifetime set by the policy of the local realm.
If the requested expiration time minus the starttime (as worked out above) is less than a site-determined minimum lifetime, you get KDC_ERR_NEVER_VALID ๐. If the requested expiration time for the ticket goes beyond what was determined above, and the 'RENEWABLE-OK' option was requested, then the RENEWABLE flag gets set in the new ticket, and the renew-till value is set as if the 'RENEWABLE' option had been requested. (The field and option names are fully described in Section 5.4.1 โจ.)
If the RENEWABLE option was requested, or RENEWABLE-OK was set and a renewable ticket is being issued, then the renew-till field MAY be set to the earliest of:
- Its requested value.
- The starttime of the ticket plus the minimum of the two maximum renewable lifetimes associated with the principals' database entries.
- The starttime of the ticket plus the maximum renewable lifetime set by the policy of the local realm.
The flags field of the new ticket gets these options set, if they were requested and the local realm's policy allows: FORWARDABLE, MAY-POSTDATE, POSTDATED, PROXIABLE, RENEWABLE. If the new ticket is postdated (the starttime is in the future), its INVALID flag gets set too ๐
If all of the above succeeds, the server encrypts the ciphertext part of the ticket with the encryption key pulled from the server principal's record in the Kerberos database, using the encryption type associated with that principal's key. (This choice is NOT affected by the etype field in the request.) Then it formats a KRB_AS_REP message (see Section 5.4.2 ๐ฆ), copies the addresses from the request into the caddr of the response, puts any required pre-authentication data into the padata of the response, and encrypts the ciphertext part with the client's key, using an acceptable encryption method requested in the etype field of the request, or some key specified by the pre-authentication mechanisms in use.
3.1.4. Generation of KRB_ERROR Message
Several errors can happen, and the Authentication Server responds by sending an error message, KRB_ERROR, back to the client, with the error-code and e-text fields set to appropriate values ๐จ. The details of the error message contents are in Section 5.9.1 ๐.
3.1.5. Receipt of KRB_AS_REP Message
If the reply message type is KRB_AS_REP, the client checks that the cname and crealm fields in the cleartext portion of the reply match what it asked for ๐. If any padata fields are present, they can be used to derive the right secret key for decrypting the message. The client decrypts the encrypted part of the response with its secret key, and checks that the nonce in there matches the nonce it sent in its request (this catches replays ๐ต๏ธโโ๏ธ). It also verifies that the sname and srealm in the response match the request (or are otherwise expected values), and that the host address field is correct too. Then it stores the ticket, session key, start and expiration times, and other info for later use ๐. The last-req field (and the deprecated key-expiration field) from the encrypted part of the response MAY be checked to warn the user that their key is about to expire. This lets the client program suggest remedial action, like a password change ๐
After validating the KRB_AS_REP message by checking the returned nonce against the one sent in the KRB_AS_REQ message, the client knows the current time on the KDC is whatever is in the authtime field of the encrypted part of the reply โฐ. The client can optionally use this value for clock synchronization in later messages, by recording with the ticket the difference (offset) between the authtime value and the local clock. That offset can then be used by the same user to adjust the time read from the system clock when generating messages [DGT96].
This technique MUST be used when adjusting for clock skew, instead of directly changing the system clock. The KDC reply is only authenticated to the user whose secret key was used, not to the system or workstation. If the clock were adjusted, an attacker colluding with a user logging into a workstation could agree on a password, and the resulting KDC reply would validate correctly even though it didn't come from a KDC the workstation trusts. This is serious business ๐ฑ
Proper decryption of the KRB_AS_REP message is NOT enough for the host to verify the user's identity, though. The user and an attacker could team up to generate a KRB_AS_REP format message that decrypts properly but isn't from the real KDC. If the host wants to verify the user's identity, it MUST require the user to present application credentials that can be verified using a securely-stored secret key for the host. If those credentials check out, then the user's identity can be assured ๐ซถ
3.1.6. Receipt of KRB_ERROR Message
If the reply message type is KRB_ERROR, the client treats it as an error and does whatever application-specific tasks are needed for recovery ๐ง
3.2. The Client/Server Authentication Exchange โจ
Summary
Message direction Message type Section
Client to Application server KRB_AP_REQ 5.5.1
[optional] Application server to client KRB_AP_REP or 5.5.2
KRB_ERROR 5.9.1
The client/server authentication (CS) exchange is how network applications authenticate the client to the server, and the server back to the client ๐๐. The client MUST have already acquired credentials for the server using the AS or TGS exchange ๐
3.2.1. The KRB_AP_REQ Message โจ
okay so KRB_AP_REQ is the message that carries your auth info, and it SHOULD be part of the very first message in an authenticated transaction ๐
It bundles a ticket, an authenticator, and some extra bookkeeping (check Section 5.5.1 for the exact format ๐). But the ticket on its own is NOT enough to authenticate a client, bestie ๐ญ Tickets travel across the network in cleartext. (A ticket has an encrypted part and an unencrypted part, so "cleartext" means the whole unit, and anyone can copy it from one message and replay it in another without any real cryptography skills ๐) That's where the authenticator comes in. It stops invalid replays of tickets by proving to the server that you know the session key for the ticket, so you're actually entitled to use it ๐ Fun fact: KRB_AP_REQ is also called the 'authentication header' elsewhere ๐ฆ
3.2.2. Generation of a KRB_AP_REQ Message ๐ธ
When a client wants to authenticate to a server, it gets a ticket and session key for the service it wants, either from a credentials cache, the AS exchange, or the TGS exchange ๐ง The client MAY re-use any tickets it holds until they expire ๐ To use a ticket, the client builds a new Authenticator from the system time and its name. It can optionally add an application-specific checksum, an initial sequence number to be used in KRB_SAFE or KRB_PRIV messages, and/or a session subkey for negotiating a session key unique to this one session ๐ซถ
Authenticators MUST NOT be re-used, and they SHOULD be rejected if replayed to a server ๐ซ Heads up, this can make apps on unreliable transports really tricky to code correctly ๐ฉ If the transport might deliver duplicated messages, then either a new authenticator MUST be generated for each retry, or the application server MUST match requests and replies and replay the first reply whenever it spots a duplicate ๐ฌ
If a sequence number is included, it SHOULD be randomly chosen so that even after lots of messages it's not likely to collide with other sequence numbers in use ๐ฒ
The client MAY indicate that it requires mutual authentication, or the use of a session-key based ticket (for user-to-user authentication, see section 3.7 ๐ค), by setting the appropriate flag(s) in the ap-options field of the message ๐ณ๏ธ
The Authenticator is encrypted in the session key and combined with the ticket to form the KRB_AP_REQ message, which then gets sent to the end server along with any extra application-specific info ๐
3.2.3. Receipt of KRB_AP_REQ Message ๐
Authentication is based on the server's current time of day (clocks MUST be loosely synchronized โฐ), the authenticator, and the ticket. Several errors are possible ๐ฌ If something goes wrong, the server is expected to reply to the client with a KRB_ERROR message. That message MAY be wrapped inside the application protocol if its raw form isn't acceptable to the protocol ๐ The format of error messages is described in Section 5.9.1.
Here's the algorithm for verifying auth info, it's basically a checklist โ
If the message type is not KRB_AP_REQ, the server returns the KRB_AP_ERR_MSG_TYPE error. If the key version indicated by the Ticket in the KRB_AP_REQ isn't one the server can use (e.g., it points to an old key the server no longer has), the KRB_AP_ERR_BADKEYVER error is returned. If the USE-SESSION-KEY flag is set in the ap-options field, that tells the server user-to-user auth is in use, and the ticket is encrypted in the session key from the server's TGT rather than the server's secret key. See Section 3.7 for the full tea on how user-to-user authentication affects all messages in the Kerberos protocol ๐
Because a server can be registered in multiple realms with different keys in each, the srealm field in the unencrypted portion of the ticket in the KRB_AP_REQ is used to say which secret key the server should use to decrypt that ticket ๐๏ธ If the server doesn't have the proper key to decipher the ticket, the KRB_AP_ERR_NOKEY error code is returned ๐ช
The ticket is decrypted using the version of the server's key specified by the ticket. If the decryption routines detect a modification of the ticket (each encryption system MUST provide safeguards to detect modified ciphertext), the KRB_AP_ERR_BAD_INTEGRITY error is returned (chances are good that different keys were used to encrypt and decrypt) ๐จ
The authenticator is decrypted using the session key extracted from the decrypted ticket. If decryption shows that it has been modified, the KRB_AP_ERR_BAD_INTEGRITY error is returned. The name and realm of the client from the ticket are compared against the same fields in the authenticator. If they don't match, the KRB_AP_ERR_BADMATCH error is returned, and normally that's caused by a client error or an attempted attack ๐ต๏ธ The addresses in the ticket (if any) are then searched for an address matching the operating-system reported address of the client. If no match is found, or the server insists on ticket addresses but none are present in the ticket, the KRB_AP_ERR_BADADDR error is returned. If the local (server) time and the client time in the authenticator differ by more than the allowable clock skew (e.g., 5 minutes), the KRB_AP_ERR_SKEW error is returned โณ
Unless the application server provides its own suitable means to protect against replay (for example, a challenge-response sequence initiated by the server after authentication, or use of a server-generated encryption subkey), the server MUST utilize a replay cache to remember any authenticator presented within the allowable clock skew. Careful analysis of the application protocol and implementation is recommended before eliminating this cache ๐ง The replay cache stores at least the server name, along with the client name, time, and microsecond fields from the recently-seen authenticators. If a matching tuple is found, the KRB_AP_ERR_REPEAT error is returned. Note that the rejection here is restricted to authenticators from the same principal to the same server. Other client principals communicating with the same server should not have their authenticators rejected just because the time and microsecond fields happen to match some other client's authenticator ๐
If a server loses track of authenticators presented within the allowable clock skew, it MUST reject all requests until the clock skew interval has passed. That gives assurance that any lost or replayed authenticators will fall outside the allowable clock skew and can no longer be successfully replayed โธ๏ธ If this were not done, an attacker could subvert the authentication by recording the ticket and authenticator sent over the network to a server, then replaying them following an event that caused the server to lose track of recently seen authenticators ๐ฑ Dramatic, I know, but it's real.
Implementation note: If a client generates multiple requests to the KDC with the same timestamp, including the microsecond field, all but the first of the requests received will be rejected as replays. This might happen, for example, if the resolution of the client's clock is too coarse ๐ฐ๏ธ Client implementations SHOULD ensure that the timestamps are not reused, possibly by incrementing the microseconds field in the time stamp when the clock returns the same time for multiple requests โ
If multiple servers (for example, different services on one machine, or a single service implemented on multiple machines) share a service principal (a practice we do not recommend in general, but that we acknowledge will be used in some cases), then either they MUST share this replay cache, or the application protocol MUST be designed so as to eliminate the need for it. Note that this applies to all of the services. If any of the application protocols does not have replay protection built in, an authenticator used with such a service could later be replayed to a different service with the same service principal but no replay protection, if the former doesn't record the authenticator information in the common replay cache ๐ต๏ธโโ๏ธ
If a sequence number is provided in the authenticator, the server saves it for later use in processing KRB_SAFE and/or KRB_PRIV messages. If a subkey is present, the server either saves it for later use or uses it to help generate its own choice for a subkey to be returned in a KRB_AP_REP message ๐
The server computes the age of the ticket: local (server) time minus the starttime inside the Ticket. If the starttime is later than the current time by more than the allowable clock skew, or if the INVALID flag is set in the ticket, the KRB_AP_ERR_TKT_NYV error is returned. Otherwise, if the current time is later than end time by more than the allowable clock skew, the KRB_AP_ERR_TKT_EXPIRED error is returned โ
If all these checks succeed without an error, the server is assured that the client possesses the credentials of the principal named in the ticket, and thus that the client has been authenticated to the server ๐
Passing these checks provides only authentication of the named principal. It does not imply authorization to use the named service. Applications MUST make a separate authorization decision based upon the authenticated name of the user, the requested operation, local access control information such as that contained in a.k5loginor.k5usersfile, and possibly a separate distributed authorization service ๐ง
3.2.4. Generation of a KRB_AP_REP Message ๐ฆ
Typically, a client's request includes both the authentication information and its initial request in the same message, so the server doesn't need to explicitly reply to the KRB_AP_REQ ๐จ However, if mutual authentication (authenticating not only the client to the server, but also the server to the client ๐ค) is being performed, the KRB_AP_REQ message will have MUTUAL-REQUIRED set in its ap-options field, and a KRB_AP_REP message is required in response. As with the error message, this message MAY be encapsulated in the application protocol if its "raw" form is not acceptable to the application's protocol ๐ The timestamp and microsecond field used in the reply MUST be the client's timestamp and microsecond field (as provided in the authenticator) โฑ๏ธ If a sequence number is to be included, it SHOULD be randomly chosen as described above for the authenticator ๐ฒ A subkey MAY be included if the server desires to negotiate a different subkey ๐๏ธ The KRB_AP_REP message is encrypted in the session key extracted from the ticket ๐
Note that in the Kerberos Version 4 protocol, the timestamp in the reply was the client's timestamp plus one. This is not necessary in Version 5, because Version 5 messages are formatted in such a way that it is not possible to create the reply by judicious message surgery (even in encrypted form) without knowledge of the appropriate encryption keys ๐ง
3.2.5. Receipt of KRB_AP_REP Message โจ
okay so if a KRB_AP_REP message comes back, the client grabs the session key from the credentials it got for the server and uses it to decrypt the message ๐. Then it checks that the timestamp and microsecond fields match the ones in the Authenticator it sent over. If they match, the client knows the server is legit ๐ซถ. The sequence number and subkey (if there is one) get saved for later ๐พ. (Heads up: when encrypting the KRB_AP_REP message, the sub-session key is NOT used, even if one shows up in the Authenticator ๐ โโ๏ธ.)
3.2.6. Using the Encryption Key
once the KRB_AP_REQ/KRB_AP_REP exchange is done, the client and server share an encryption key the application can use ๐๏ธ. Sometimes using that session key is just built into the protocol, and other times you have to pick a method from a few options ๐ค. The application MAY choose the actual encryption key for KRB_PRIV, KRB_SAFE, or other application-specific uses, based on the session key from the ticket and the subkeys in the KRB_AP_REP message and the authenticator ๐ . Implementations of the protocol MAY provide routines to pick subkeys from session keys and random numbers, and to generate a negotiated key to send back in the KRB_AP_REP message โจ.
To protect against random number generation failing on the client, it is strongly encouraged that any key an application derives for later use includes the full key entropy from the KDC-generated session key in the ticket ๐ฒ. How to use the key (like choosing an encryption or checksum type) is left up to the application programmer ๐งโ๐ป. Kerberos doesn't restrict your implementation options, but here's one way it could be done ๐ธ.
One way an application can negotiate a key for later integrity and privacy protection: the client proposes a key in the subkey field of the authenticator ๐ฆ. The server then picks a key using the client's proposed key as input, and sends the new subkey back in the subkey field of the application reply ๐. That key can then be used for the rest of the communication ๐.
With both one-way and mutual authentication exchanges, the peers should be careful not to send sensitive info to each other without proper assurances ๐. Especially, applications that need privacy or integrity SHOULD use the KRB_AP_REP response from the server to the client, so both sides can confirm who the other one is ๐. If an application protocol needs its messages to be private, it can use the KRB_PRIV message (section 3.5) ๐. The KRB_SAFE message (Section 3.4) can be used to make sure nothing got messed with ๐ก๏ธ.
3.3. The Ticket-Granting Service (TGS) Exchange
Summary
Message direction Message type Section
1. Client to Kerberos KRB_TGS_REQ 5.4.1
2. Kerberos to client KRB_TGS_REP or 5.4.2
KRB_ERROR 5.9.1
okay so the TGS exchange is the convo between a client and the Kerberos TGS ๐๏ธ. A client starts it when it wants credentials for a given server (which might be registered in a remote realm), when it wants to renew or validate an existing ticket, or when it wants a proxy ticket ๐ง. In the first case, the client already needs a ticket for the Ticket-Granting Service from the AS exchange (the TGT usually shows up when a client first authenticates, like when a user logs in) ๐. The TGS message format is almost identical to the AS exchange, and the big difference is that encryption and decryption here do NOT happen under the client's key ๐ฎ. Instead, it uses the session key from the TGT or renewable ticket, or the sub-session key from an Authenticator ๐๏ธ. Just like every application server, the TGS won't accept expired tickets, so once a renewable or TGT expires, the client has to run a separate exchange to get valid ones โฐ.
The TGS exchange has two messages: a request (KRB_TGS_REQ) from the client to the Kerberos Ticket-Granting Server, and a reply (KRB_TGS_REP or KRB_ERROR) ๐จ. The KRB_TGS_REQ message has info that authenticates the client plus a request for credentials ๐ชช. The authentication info is the authentication header (KRB_AP_REQ), which includes the client's previously obtained ticket-granting, renewable, or invalid ticket ๐ซ. In the TGT and proxy cases, the request MAY include one or more of these: a list of network addresses, a collection of typed authorization data to be sealed in the ticket for the application server to use, or additional tickets (more on those later) ๐. The TGS reply (KRB_TGS_REP) has the requested credentials, encrypted in the session key from the TGT or renewable ticket, or, if there is one, in the sub-session key from the Authenticator (part of the authentication header) ๐. The KRB_ERROR message has an error code and text explaining what went wrong, and it is NOT encrypted ๐. The KRB_TGS_REP message has info that can be used to detect replays and to match it to the message it replies to ๐. The KRB_ERROR message also has info that can be used to match it to the message it replies to ๐งฉ. The same comments about integrity protection of KRB_ERROR messages from Section 3.1 apply to the TGS exchange too ๐ .
3.3.1. Generation of KRB_TGS_REQ Message
Before sending a request to the ticket-granting service, the client MUST figure out which realm the application server is believed to be registered in ๐บ๏ธ. There are a few ways to do this. It might already be known beforehand (since the realm is part of the principal identifier), it might be stored in a nameserver, or it might come from a configuration file ๐. If the realm comes from a nameserver, watch out: there's a danger of being spoofed if the nameservice giving out the realm name isn't authenticated ๐ฑ. That could lead to using a realm that's been compromised, which would let an attacker mess with the application server's authentication to the client ๐.
If the client knows the service principal name and realm and doesn't already have a TGT for the right realm, then it has to get one ๐ซ. It tries first by asking a Kerberos server it already has a TGT for, for a TGT to the destination realm (using the KRB_TGS_REQ message, recursively) ๐. The Kerberos server MAY return a TGT for the desired realm, and then you're good to go โจ. Or, the Kerberos server MAY return a TGT for a realm that's "closer" to the desired one (further along the standard hierarchical path between the client's realm and the requested server's realm) ๐ค๏ธ. Heads up: if the Kerberos servers are misconfigured, the authentication path could loop, so the client should be careful to catch and avoid that ๐.
If the Kerberos server gives back a TGT for a realm that's "closer" than the desired one, the client MAY use local policy configuration to check that the authentication path is acceptable ๐ง. Or, a client MAY choose its own authentication path instead of relying on the Kerberos server to pick one ๐บ๏ธ. Either way, any policy or configuration info used to choose or validate authentication paths (whether it came from the Kerberos server or the client) MUST come from a trusted source ๐.
When a client gets a TGT that's "closer" to the destination realm, it MAY cache that ticket and reuse it in future KRB-TGS exchanges with services in the "closer" realm ๐พ. But, if the client got a TGT for the "closer" realm by starting at the initial KDC instead of as part of getting another ticket, a shorter path to the "closer" realm might be used ๐ฃ๏ธ. That shorter path can be nicer because fewer intermediate KDCs would know the session key of the ticket involved ๐คซ. So for this reason, clients SHOULD check whether they trust the realms that were transited to get the "closer" ticket before deciding to use it later ๐ง .
Once the client has a TGT for the right realm, it figures out which Kerberos servers serve that realm and contacts one of them ๐. The list might come from a configuration file or network service, or it MAY be generated from the realm name ๐. As long as the secret keys exchanged between realms stay secret, using a false Kerberos server only causes denial of service ๐ซ.
Just like in the AS exchange, the client MAY set a bunch of options in the KRB_TGS_REQ message ๐๏ธ. One option is ENC-TKT-IN-SKEY, which is used for user-to-user authentication. You can find an overview of user-to-user authentication in Section 3.7 ๐. When the client generates the KRB_TGS_REQ message with this option, it means the client is including a TGT obtained from the application server in the additional tickets field of the request, and the KDC SHOULD encrypt the ticket for the application server using the session key from this additional ticket, instead of a server key from the principal database ๐ซง.
The client prepares the KRB_TGS_REQ message, putting an authentication header in the padata field as an element, and including the same fields as in the KRB_AS_REQ message plus a few optional ones: the enc-authorizatfion-data field for application server use, and additional tickets required by some options ๐.
When preparing the authentication header, the client can pick a sub-session key that the Kerberos server's response will be encrypted under ๐. If the client does pick one, it has to make sure the sub-session key is random ๐ฒ.
If no sub-session key is specified, the session key from the TGT will be used ๐๏ธ. If enc-authorization-data is present, it MUST be encrypted in the sub-session key from the authenticator portion of the authentication header (if present), or, if there isn't one, by using the session key from the TGT ๐.
Once it's all prepared, the message gets sent to a Kerberos server for the destination realm ๐.
3.3.2. Receipt of KRB_TGS_REQ Message
okay so the KRB_TGS_REQ message gets processed kinda like KRB_AS_REQ ๐
, but there are WAY more checks to do ๐ญ. First, the Kerberos server MUST figure out which server the accompanying ticket is for, and it MUST pick the right key to decrypt it ๐. For a normal KRB_TGS_REQ, the ticket is for the ticket-granting service, so the TGS's key gets used. If the TGT was issued by another realm, then the appropriate inter-realm key MUST be used ๐. If (a) the accompanying ticket is not a TGT for the current realm, but it is for an application server in the current realm, (b) the RENEW, VALIDATE, or PROXY options are specified in the request, and (c) the server being asked for a ticket is the server named in that accompanying ticket, then the KDC decrypts the ticket in the authentication header using the key of the server it was issued for. If no ticket can be found in the padata field, the KDC_ERR_PADATA_TYPE_NOSUPP error is returned ๐.
Once the accompanying ticket is decrypted, the user-supplied checksum in the Authenticator MUST be verified against the contents of the request, and the message MUST be rejected if the checksums don't match (with an error code of KRB_AP_ERR_MODIFIED) or if the checksum isn't collision-proof (with an error code of KRB_AP_ERR_INAPP_CKSUM) ๐ซ. If the checksum type isn't supported, the KDC_ERR_SUMTYPE_NOSUPP error is returned. If the authorization-data are present, they get decrypted using the sub-session key from the Authenticator ๐.
If any of the decryptions show failed integrity checks, the KRB_AP_ERR_BAD_INTEGRITY error is returned ๐.
As discussed in Section 3.1.2, the KDC MUST send a valid KRB_TGS_REP message if it gets a KRB_TGS_REQ message that's identical to one it has recently processed โจ. However, if the authenticator is a replay but the rest of the request isn't identical, then the KDC SHOULD return KRB_AP_ERR_REPEAT ๐.
3.3.3. Generation of KRB_TGS_REP Message
the KRB_TGS_REP message shares its format with the KRB_AS_REP (KRB_KDC_REP), it's just that its type field is set to KRB_TGS_REP ๐. The detailed spec lives in Section 5.4.2 ๐.
The response includes a ticket for the requested server, or for a ticket granting server of an intermediate KDC that the client needs to contact to get the requested ticket ๐ฆ. The Kerberos database gets queried to pull up the record for the right server (including the key the ticket will be encrypted with) ๐๏ธ. If the request is for a TGT for a remote realm, and no key is shared with that requested realm, then the Kerberos server selects the realm 'closest' to the requested realm that it does share a key with, and uses that realm instead ๐ธ. This is the only case where the KDC's response is for a different server than the one the client asked for, so it's kind of a big deal ๐.
By default, the address field, the client's name and realm, the list of transited realms, the time of initial authentication, the expiration time, and the authorization data of the newly-issued ticket all get copied from the TGT or renewable ticket ๐. If the transited field needs updating but the transited type isn't supported, the KDC_ERR_TRTYPE_NOSUPP error is returned.
If the request specifies an endtime, then the endtime of the new ticket is set to the minimum of (a) that request, (b) the endtime from the TGT, and (c) the starttime of the TGT plus the minimum of the maximum life for the application server and the maximum life for the local realm. (The maximum life for the requesting principal was already applied when the TGT was issued, so we don't redo that one ๐.) If the new ticket is going to be a renewal, then the endtime above gets replaced by the minimum of (a) the value of the renew_till field of the ticket and (b) the starttime for the new ticket plus the life (endtime-starttime) of the old ticket โณ.
If the FORWARDED option was requested, the resulting ticket will contain the addresses the client specified ๐ง. This option only gets honored if the FORWARDABLE flag is set in the TGT. The PROXY option is similar: the resulting ticket will contain the addresses the client specified, but it only gets honored if the PROXIABLE flag in the TGT is set. The PROXY option will NOT be honored on requests for additional TGTs ๐
โโ๏ธ.
If the requested starttime is absent, points to a time in the past, or is within the window of acceptable clock skew for the KDC and the POSTDATE option hasn't been specified, then the starttime of the ticket is set to the authentication server's current time โฐ. If it points to a time in the future beyond the acceptable clock skew, but the POSTDATED option hasn't been specified or the MAY-POSTDATE flag isn't set in the TGT, then the error KDC_ERR_CANNOT_POSTDATE is returned ๐ค. Otherwise, if the TGT has the MAY-POSTDATE flag set, the resulting ticket gets postdated, and the requested starttime is checked against the policy of the local realm. If that's acceptable, the ticket's starttime is set as requested and the INVALID flag is set ๐. The postdated ticket MUST be validated before use by presenting it to the KDC after the starttime has been reached ๐ฐ๏ธ. And no matter what, the starttime, endtime, or renew-till time of a newly-issued postdated ticket can NEVER extend beyond the renew-till time of the TGT ๐ง.
If the ENC-TKT-IN-SKEY option has been specified and an additional ticket has been included in the request, it means the client is using user-to-user authentication to prove its identity to a server that doesn't have access to a persistent key ๐ค. Section 3.7 describes the effect of this option on the entire Kerberos protocol. When generating the KRB_TGS_REP message, this option in the KRB_TGS_REQ message tells the KDC to decrypt the additional ticket using the key for the server it was issued to, and to verify that it's a TGT ๐. If the name of the requested server is missing from the request, the name of the client in the additional ticket gets used. Otherwise, the name of the requested server gets compared to the name of the client in the additional ticket. If they're different, the request gets rejected ๐
. If the request succeeds, the session key from the additional ticket is used to encrypt the new ticket that gets issued, instead of using the key of the server the new ticket is for ๐.
If (a) the name of the server in the ticket presented to the KDC as part of the authentication header is NOT that of the TGS itself, (b) the server is registered in the realm of the KDC, and (c) the RENEW option is requested, then the KDC verifies that the RENEWABLE flag is set in the ticket, that the INVALID flag is NOT set, and that the renew_till time is still in the future ๐. If the VALIDATE option is requested, the KDC checks that the starttime has passed and that the INVALID flag is set โ
. If the PROXY option is requested, the KDC checks that the PROXIABLE flag is set in the ticket ๐ช. If the tests succeed and the ticket passes the hot-list check described in the next section, the KDC issues the appropriate new ticket ๐.
The ciphertext part of the response in the KRB_TGS_REP message is encrypted in the sub-session key from the Authenticator if one is present, or in the session key from the TGT ๐๏ธ. It is NOT encrypted using the client's secret key ๐. Also, the client's key's expiration date and the key version number fields are left out, since those values are stored with the client's database record, and that record isn't needed to satisfy a request based on a TGT ๐ญ.
3.3.3.1. Checking for Revoked Tickets
Whenever a request is made to the ticket-granting server, the presented ticket(s) get checked against a hot-list of tickets that have been canceled ๐จ. This hot-list might be implemented by storing a range of issue timestamps for 'suspect tickets'; if a presented ticket had an authtime in that range, it gets rejected ๐. This way, a stolen TGT or renewable ticket can't be used to get additional tickets (renewals or otherwise) once the theft has been reported to the KDC for the realm the server lives in ๐ต๏ธโโ๏ธ. Any normal ticket obtained before it was reported stolen will still be valid (because tickets don't need any interaction with the KDC), but only until its normal expiration time โณ. If TGTs have been issued for cross-realm authentication, using that cross-realm TGT won't be affected unless the hot-list gets propagated to the KDCs for the realms those cross-realm tickets were issued for ๐.
3.3.3.2. Encoding the Transited Field โจ
okay so if the server in the TGT that the client shows the KDC (as part of the authentication header) is the ticket-granting service, but that TGT was issued from a different realm, the KDC goes and grabs the inter-realm key it shares with that realm ๐ and uses it to decrypt the ticket. if the ticket checks out, the KDC honors the request, subject to the constraints outlined above in the section describing the AS exchange ๐ . the realm part of the client's identity gets taken from the TGT.
now here's the fun part ๐ง. the name of the realm that issued the TGT gets added to the transited field of the new ticket, but only if it's not the realm of the client principal. how that works: read the transited field from the TGT (it's treated as an unordered set of realm names ๐ซง), toss the new realm into the set, then build and write out its encoded (shorthand) form. that last step might shuffle the existing encoding around a bit.
ngl this next bit is so iconic ๐. the ticket-granting service does not add its own realm name. its job is to add the previous realm. why? it stops a sketchy Kerberos server from just leaving out its own name on purpose ๐. (it could still leave out other realms' names though, so yeah, not perfect.)
the names of the local realm and the principal's realm are NOT supposed to go in the transited field. they're already listed elsewhere in the ticket, and both are known to have been part of authenticating the principal, so it's giving redundancy ๐. because endpoints get skipped, both local and single-hop inter-realm auth end up with a transited field that's empty ๐ธ.
because every transited realm gets added, this field could get really long ๐ญ. so its contents are encoded to keep it short. the first encoding was built for the super normal case of inter-realm communication: a hierarchical setup of realms using either domain or X.500 style realm names ๐. it's called DOMAIN-X500-COMPRESS, and here's how it works.
realm names in the transited field are separated by a ",". the ",", "\", trailing "."s, and leading spaces (" ") are special characters. if any of them is part of a realm name, they MUST be quoted in the transited field by putting a "\" in front of them ๐.
a realm name ending with a "." gets read as being prepended to the previous realm. so traversing EDU, MIT.EDU, ATHENA.MIT.EDU, WASHINGTON.EDU, and CS.WASHINGTON.EDU looks like this:
"EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.".
if ATHENA.MIT.EDU or CS.WASHINGTON.EDU were endpoints, they wouldn't show up in the field, so you'd get:
"EDU,MIT.,WASHINGTON.EDU"
a realm name beginning with a "/" gets read as being appended to the previous realm. for appending purposes, the realm before the first listed realm counts as the null realm (""). if a "/"-starting realm name is going to stand by itself, then it SHOULD be preceded by a space (" "). traversing /COM/HP/APOLLO, /COM/HP, /COM, and /COM/DEC looks like this:
"/COM,/HP,/APOLLO, /COM/DEC".
same deal as before: if /COM/HP/APOLLO and /COM/DEC were endpoints, they'd get left out, and you'd have:
"/COM,/HP"
a null subfield sitting next to a","means every realm between the previous realm and the next one got traversed ๐ง . for null subfield purposes, the client's realm counts as coming before everything in the field, and the server's realm counts as coming after. so","on its own means all realms on the path between client and server were traversed.",EDU, /COM,"means every realm from the client's realm up to EDU (domain style hierarchy) was traversed, AND everything from /COM down to the server's realm (X.500 style) was traversed too. this could happen if the EDU realm in one hierarchy shares an inter-realm key directly with the /COM realm in another hierarchy ๐คฏ.
3.3.4. Receipt of KRB_TGS_REP Message ๐
when the client gets the KRB_TGS_REP, it's processed the same way as the KRB_AS_REP processing we went over earlier ๐. the main difference is that the ciphertext part of the response has to be decrypted using the sub-session key from the Authenticator (if one was specified in the request) or the session key from the TGT, NOT the client's secret key. the server name in the reply is the true principal name of the service ๐ซถ.
3.4. The KRB_SAFE Exchange ๐ก๏ธ
the KRB_SAFE message MAY be used by clients who need to detect modifications to the messages they exchange ๐. how it does that: it includes a keyed collision-proof checksum of the user data plus some control information. the checksum is keyed with an encryption key (usually the last key negotiated via subkeys, or the session key if no negotiation happened) ๐.
3.4.1. Generation of a KRB_SAFE Message ๐
when an application wants to send a KRB_SAFE message, it collects its data and the right control information, then computes a checksum over all of it. the checksum algorithm should be the keyed checksum that's mandated to be implemented alongside the crypto system used for the sub-session or session key. the checksum gets generated with the sub-session key if one's present, or with the session key. some implementations use a different checksum algorithm for KRB_SAFE messages, but doing that in an interoperable way isn't always possible ๐.
the control information for a KRB_SAFE message includes both a timestamp and a sequence number. the designer of an application that uses KRB_SAFE MUST choose at least one of the two mechanisms, and that choice SHOULD be based on what the application protocol actually needs ๐ฏ.
sequence numbers are useful when all the messages sent will be received by one's peer. connection state is already required to keep the session key, so keeping track of the next sequence number shouldn't be an extra headache ๐ .
if the application protocol is expected to tolerate lost messages without them being resent, then the timestamp is the right replay detection mechanism. timestamps are also the right call for multi-cast protocols where all of one's peers share a common sub-session key, but some messages only go to a subset of those peers ๐ก.
after computing the checksum, the client transmits the information and checksum to the recipient in the message format specified in Section 5.6.1 ๐ฆ.
3.4.2. Receipt of KRB_SAFE Message ๐
when an application receives a KRB_SAFE message, it verifies it like this. if any error happens, an error code gets reported for the application to use ๐จ.
first, the message gets checked by verifying that the protocol version and type fields match the current version and KRB_SAFE, respectively. a mismatch generates a KRB_AP_ERR_BADVERSION or KRB_AP_ERR_MSG_TYPE error ๐ฌ. next, the application verifies that the checksum used is a collision-proof keyed checksum that uses keys compatible with the sub-session or session key (or with the application key derived from the session or sub-session keys). if it isn't, a KRB_AP_ERR_INAPP_CKSUM error is generated.
the sender's address MUST be included in the control information. the recipient checks that the operating system's report of the sender's address matches the sender's address in the message. and if a recipient address is specified (or the recipient requires one), one of the recipient's addresses has to show up as the recipient's address in the message ๐ . to play nice with network address translation, senders MAY use the directional address type specified in Section 8.1 for the sender address and leave out recipient addresses ๐. a failed match in either case generates a KRB_AP_ERR_BADADDR error.
then the timestamp and usec and/or the sequence number fields get checked. if timestamp and usec are expected but not present, or they're present but not current, the KRB_AP_ERR_SKEW error is generated โฐ. timestamps don't have to be strictly ordered; they only have to be in the skew window. if the server name, along with the client name, time, and microsecond fields from the Authenticator match any recently-seen (sent or received) tuple, the KRB_AP_ERR_REPEAT error is generated ๐. if an incorrect sequence number is included, or a sequence number is expected but missing, the KRB_AP_ERR_BADORDER error is generated. and if neither a timestamp and usec nor a sequence number is present, a KRB_AP_ERR_MODIFIED error is generated ๐ฑ.
finally, the checksum is computed over the data and control information. if it doesn't match the received checksum, a KRB_AP_ERR_MODIFIED error is generated ๐ฅ.
if all the checks succeed, the application can be sure the message came from its peer and wasn't modified in transit ๐ซถโจ.
implementations SHOULD accept any checksum algorithm they implement that has both adequate security and keys compatible with the sub-session or session key. unkeyed or non-collision-proof checksums are NOT suitable for this use ๐ โโ๏ธ.
3.5. The KRB_PRIV Exchange ๐
the KRB_PRIV message MAY be used by clients who need confidentiality AND the ability to detect modifications to exchanged messages ๐คซ. it does this by encrypting the messages and adding control information.
3.5.1. Generation of a KRB_PRIV Message ๐๏ธ
when an application wants to send a KRB_PRIV message, it collects its data and the appropriate control information (specified in Section 5.7.1), then encrypts all of it under an encryption key (usually the last key negotiated via subkeys, or the session key if no negotiation has occurred) ๐. as part of the control information, the client MUST choose to use a timestamp or a sequence number (or both). see the discussion in Section 3.4.1 for guidelines on which to pick ๐. after the user data and control information are encrypted, the client sends the ciphertext and some "envelope" information to the recipient ๐ฌ.
3.5.2. Receipt of KRB_PRIV Message
okay so when an app gets a KRB_PRIV message ๐, it has to check it before trusting anything. If something goes wrong, an error code gets reported so the app can handle it ๐ซถ.
First, the protocol version and type fields get checked to make sure they match the current version and KRB_PRIV. If they don't, you get KRB_AP_ERR_BADVERSION or KRB_AP_ERR_MSG_TYPE ๐ญ. Then the app decrypts the ciphertext and processes the plaintext. If decryption shows the data was modified, that's a KRB_AP_ERR_BAD_INTEGRITY error ๐.
Next up are addresses ๐ก. The sender's address MUST be included in the control information, and the recipient checks that the operating system's report of the sender's address matches the sender's address in the message. If a recipient address is specified or the recipient requires an address, then one of the recipient's addresses MUST also appear as the recipient's address in the message. Where a sender's or receiver's address might not otherwise match the address in a message because of network address translation, an application MAY be written to use addresses of the directional address type in place of the actual network address ๐ง.
If either case fails to match, you get a KRB_AP_ERR_BADADDR error ๐. To work with network address translation, implementations MAY use the directional address type defined in Section 7.1 for the sender address and include no recipient address ๐ธ.
Then the timestamp and usec and/or the sequence number fields get checked โฐ. If timestamp and usec are expected and not present, or if they're present but not current, the KRB_AP_ERR_SKEW error is generated. If the server name, along with the client name, time, and microsecond fields from the Authenticator match any such recently-seen tuples, the KRB_AP_ERR_REPEAT error is generated. If an incorrect sequence number is included, or if a sequence number is expected but not present, the KRB_AP_ERR_BADORDER error is generated. If neither a timestamp and usec nor a sequence number is present, a KRB_AP_ERR_MODIFIED error is generated ๐ค.
If all the checks pass, the application can assume the message was generated by its peer and was securely transmitted, with no intruders peeking at the unencrypted contents ๐ฅโจ.
3.6. The KRB_CRED Exchange
the KRB_CRED message MAY be used by clients who need to send Kerberos credentials from one host to another ๐จ. It does this by sending the tickets together with encrypted data that holds the session keys and other info about those tickets ๐.
3.6.1. Generation of a KRB_CRED Message
when an app wants to send a KRB_CRED message, it first gets credentials to send to the remote host using the KRB_TGS exchange ๐๏ธ. Then it builds the KRB_CRED message using the ticket or tickets it got, and puts the session key needed to use each ticket in the key field of the matching KrbCredInfo sequence in the encrypted part of the KRB_CRED message ๐๏ธ.
Other info about each ticket, the stuff obtained during the KRB_TGS exchange, also goes into that same KrbCredInfo sequence in the encrypted part ๐ฆ. The current time goes in too, and if the application specifically needs them, the nonce, s-address, and r-address fields go in as well. Then the whole encrypted part gets encrypted under an encryption key that was previously exchanged in the KRB_AP exchange (usually the last key negotiated via subkeys, or the session key if no negotiation happened) ๐.
Implementation note: When building a KRB_CRED message for a GSSAPI initial context token, the MIT implementation of Kerberos won't encrypt the KRB_CRED message if the session key is a DES or triple DES key ๐ฌ. For interop with MIT, the Microsoft implementation won't encrypt the KRB_CRED in a GSSAPI token if it's using a DES session key. Starting at version 1.2.5, MIT Kerberos can receive and decode either encrypted or unencrypted KRB_CRED tokens in the GSSAPI exchange ๐. The Heimdal implementation of Kerberos can also accept either encrypted or unencrypted KRB_CRED messages. Since the KRB_CRED message in a GSSAPI token is encrypted in the authenticator, the MIT behavior doesn't present a security problem, although it is a violation of the Kerberos specification ๐ค.
3.6.2. Receipt of KRB_CRED Message
when an app receives a KRB_CRED message, it verifies it, and if anything goes wrong, an error code gets reported for the app to use ๐ต๏ธโโ๏ธ. The message is verified by checking that the protocol version and type fields match the current version and KRB_CRED. If they don't, you get KRB_AP_ERR_BADVERSION or KRB_AP_ERR_MSG_TYPE ๐ญ. Then the app decrypts the ciphertext and processes the plaintext. If decryption shows the data was modified, a KRB_AP_ERR_BAD_INTEGRITY error is generated ๐.
If present or required, the recipient MAY verify that the operating system's report of the sender's address matches the sender's address in the message, and that one of the recipient's addresses appears as the recipient's address in the message. Honestly, the address check doesn't add any real security ๐. The address, if present, was already checked in the KRB_AP_REQ message, and there's no benefit for an attacker in reflecting a KRB_CRED message back to its originator. So the recipient MAY ignore the address even if it's present, which helps out in Network Address Translation (NAT) environments ๐. If either case fails to match, you get a KRB_AP_ERR_BADADDR error. Recipients MAY skip the address check, since the KRB_CRED message generally can't be reflected back to the originator ๐ฆ. Next, the timestamp and usec fields (and the nonce field, if required) get checked โฑ๏ธ. If the timestamp and usec aren't present, or they're present but not current, the KRB_AP_ERR_SKEW error is generated.
If all the checks pass, the application stores each of the new tickets in its credentials cache, together with the session key and other info from the matching KrbCredInfo sequence in the encrypted part of the KRB_CRED message ๐โจ.
3.7. User-to-User Authentication Exchanges
user-to-user authentication gives you a way to authenticate when the verifier doesn't have access to a long-term service key ๐. This might happen when a server (like a window server) is running as a user on a workstation. In that case the server may have the TGT that the user got when they logged in to the workstation, but since the server runs as an unprivileged user, it might not have access to system keys ๐ฉ. Similar situations can come up when running peer-to-peer applications ๐.
Summary
Message direction Message type Sections
0. Message from application server Not specified
1. Client to Kerberos KRB_TGS_REQ 3.3 & 5.4.1
2. Kerberos to client KRB_TGS_REP or 3.3 & 5.4.2
KRB_ERROR 5.9.1
3. Client to application server KRB_AP_REQ 3.2 & 5.5.1
so to deal with this, the Kerberos protocol lets the client ask that the ticket issued by the KDC be encrypted using a session key from a TGT issued to the party that will verify the authentication ๐ช. That TGT has to be obtained from the verifier through an exchange outside the Kerberos protocol, usually as part of the application protocol. This message shows up in the summary above as message 0 ๐ฌ. Note that because the TGT is encrypted in the KDC's secret key, it can't be used for authentication without the corresponding secret key ๐. And since the verifier doesn't reveal its corresponding secret key, handing over a copy of the verifier's TGT doesn't let anyone impersonate the verifier ๐ โโ๏ธ.
Message 0 in the table above is an application-specific negotiation between the client and server ๐ค. At the end of it, both sides have decided they'll use user-to-user authentication, and the client has obtained the server's TGT ๐.
Next, the client includes the server's TGT as an additional ticket in its KRB_TGS_REQ request to the KDC (message 1 in the table above) and specifies the ENC-TKT-IN-SKEY option in that request ๐ฏ.
If it's validated according to the instructions in Section 3.3.3, the application ticket returned to the client (message 2 in the table above) will be encrypted using the session key from the additional ticket, and the client will note this when it uses or stores the application ticket ๐.
When the client contacts the server using a ticket obtained for user-to-user authentication (message 3 in the table above), the client MUST specify the USE-SESSION-KEY flag in the ap-options field ๐ฉ. This tells the application server to use the session key associated with its TGT to decrypt the server ticket provided in the application request ๐.
4. Encryption and Checksum Specifications โจ
Okay bestie, so the Kerberos protocols in this document are built to encrypt messages of any size, using stream or block ciphers ๐. Encryption is how everyone proves who they are. Every realm's Key Distribution Center is trusted by all the principals registered in that realm to keep a secret key safe ๐ซถ. If you can prove you know that secret key, that's how the Kerberos system checks you're really you ๐ .
The KDC uses the principal's secret key (in the AS exchange) or a shared session key (in the TGS exchange) to encrypt its responses to ticket requests. Being able to get the secret key or session key means you know the right keys, and that proves who the KDC is ๐. A principal can decrypt the KDC response and then show a Ticket and a properly formed Authenticator (made with the session key from that response) to a service, and that proves the principal's identity. It goes the other way too: the service can pull the session key out of the Ticket and prove it knows it, and that proves the service's identity ๐ฆ.
[RFC3961] defines a framework for making encryption and checksum mechanisms for Kerberos. It also defines several of those mechanisms, and more might get added in future updates to that document ๐.
The string-to-key operation from [RFC3961] is used to make a long-term key for a principal (usually a user) ๐. If no salt string is given through pre-authentication data, the default salt is the realm and name components of the principal, joined in order with no separators ๐. Unless it's stated otherwise, the default string-to-key opaque parameter set defined in [RFC3961] is used โจ.
Encrypted data, keys, and checksums are sent using the EncryptedData, EncryptionKey, and Checksum data objects from Section 5.2.9 ๐. The encryption, decryption, and checksum operations in this document use the matching encryption, decryption, and get_mic operations from [RFC3961]. Each one implicitly makes a "specific key" using the "key usage" value given in the description of that EncryptedData or Checksum object, so every operation gets its own key ๐ง. Heads up, in some cases the value you use depends on how the key was picked or on the context of the message ๐.
Key usages are unsigned 32-bit integers, and zero is not allowed ๐ โโ๏ธ. The key usage values for encrypting or checksumming Kerberos messages are listed in Section 5 with the message definitions. Key usage values 512-1023 are reserved for uses inside a Kerberos implementation (like seeding a pseudo-random number generator with the result of encrypting something with a session key and a key usage value that isn't used for anything else) ๐ง . Key usage values from 1024 to 2047 (inclusive) are reserved for applications, and applications SHOULD use even values for encryption and odd values for checksums in that range ๐. Key usage values are also summed up in a table in Section 7.5.1 ๐.
Key usages 1024 and 1025 are the fallback. If no key usage values are specified, they are the ones that must be used to derive keys for encryption and checksums.
Hmm, I need to keep the original's exact meaning, so let me say it plainly without changing it. There might be other documents out there that define protocols in terms of the RFC 1510 encryption or checksum types. Those documents wouldn't know about key usages ๐. So that these specs stay meaningful until they get updated, if no key usage values are specified, then key usages 1024 and 1025 must be used to derive keys for encryption and checksums, respectively ๐. (This doesn't cover protocols that do their own encryption outside this framework, by using the key straight from the Kerberos authentication exchange.) New protocols defined in terms of the Kerberos encryption and checksum types SHOULD use their own key usage values ๐ซถ.
Unless it's indicated otherwise, no cipher state chaining happens from one encryption operation to the next ๐.
Implementation note: Even though it is not recommended, some application protocols will keep using the key data directly, even if it's only in protocol specs that already exist ๐ฌ. So an implementation meant to support general Kerberos applications might need to make the key data available, along with the attributes and operations described in [RFC3961] ๐ ๏ธ. One of the most common reasons to encrypt directly is to have direct control over choosing a "sufficiently strong" encryption algorithm for a given application ๐ช. Kerberos doesn't directly give you a way to negotiate encryption types between the application client and server, but there are approaches that use Kerberos to help with that negotiation. For example, a client can ask the KDC for only "sufficiently strong" session key types, and expect that the application server will understand and support any type the KDC sends back ๐ธ.
5. Message Specifications ๐
The ASN.1 collected here should be identical to the contents of Appendix A. If they conflict, the contents of Appendix A shall take precedence ๐.
The Kerberos protocol is defined here in terms of Abstract Syntax Notation One (ASN.1) [X680], which gives you a syntax for describing both the abstract layout of protocol messages and how they get encoded ๐งฉ. Implementors who aren't using an existing ASN.1 compiler or support library should really understand the actual ASN.1 specification thoroughly so they get the implementation behavior right ๐. The notation is more complicated than it first looks, and some ASN.1 tutorials and guides are misleading or wrong ๐ญ.
Note that in several places, abstract types have changed from RFC 1510. This partly addresses widespread assumptions that many implementors made, which in some cases led to accidental violations of the ASN.1 standard ๐. These changes are clearly flagged where they occur. The differences between the abstract types in RFC 1510 and the ones in this document can cause incompatible encodings when certain encoding rules are used, such as the Packed Encoding Rules (PER). This theoretical incompatibility should not be relevant for Kerberos, since Kerberos explicitly requires the Distinguished Encoding Rules (DER). It might be an issue for protocols that try to use Kerberos types with other encoding rules. (This practice is not recommended.) With very few exceptions (most notably the usages of BIT STRING), the encodings from using DER stay identical between the types in RFC 1510 and the types in this document ๐.
The type definitions in this section assume an ASN.1 module definition of the following form:
KerberosV5Spec2 {
iso(1) identified-organization(3) dod(6) internet(1)
security(5) kerberosV5(2) modules(4) krb5spec2(2)
} DEFINITIONS EXPLICIT TAGS ::= BEGIN
-- rest of definitions here
END
This says the tagging context for the module is explicit and non-automatic ๐ท๏ธ.
Note that in some other publications (like [RFC1510] and [RFC1964]), the "dod" part of the object identifier is wrongly given the value "5". For RFC 1964, using the "correct" OID value would change the wire protocol, so it stays unchanged for now ๐.
Note that nomenclature for message types is inconsistent elsewhere in this document, but it mostly follows C language conventions, including underscores (_) and all-caps names for things meant to be numeric constants ๐ค. Also, in some places, identifiers (especially ones for constants) are written in all caps so they stand out from the surrounding explanation โจ.
ASN.1 doesn't allow underscores in identifiers, so in the actual ASN.1 definitions, underscores get swapped for hyphens (-). Also, structure member names and defined values in ASN.1 MUST begin with a lowercase letter, while type names MUST begin with an uppercase letter ๐ .
5.1. Specific Compatibility Notes on ASN.1 ๐ฐ๏ธ
For compatibility, implementors should heed these specific notes about how ASN.1 is used in Kerberos. These notes don't describe deviations from standard ASN.1 usage. Instead, they describe some historical quirks and non-compliance in various implementations, plus historical ambiguities that, even though they're valid ASN.1, can cause confusion during implementation ๐ค.
5.1.1. ASN.1 Distinguished Encoding Rules
The encoding of Kerberos protocol messages shall obey the Distinguished Encoding Rules (DER) of ASN.1 as described in [X690]. Some implementations (believed to be mainly those derived from DCE 1.1 and earlier) are known to use the more general Basic Encoding Rules (BER). In particular, these implementations send indefinite encodings of lengths. Implementations MAY accept such encodings for the sake of backward compatibility, but implementors are warned that decoding fully general BER is fraught with peril ๐.
5.1.2. Optional Integer Fields
Some implementations don't internally tell apart an omitted optional integer value from a transmitted value of zero ๐คทโโ๏ธ. The places in the protocol where this matters include various microseconds fields, nonces, and sequence numbers. Implementations SHOULD treat omitted optional integer values as if they had been transmitted with a value of zero, if the application expects that ๐ซถ.
5.1.3. Empty SEQUENCE OF Types
There are places in the protocol where a message contains a SEQUENCE OF type as an optional member. That can result in an encoding that has an empty SEQUENCE OF encoding. The Kerberos protocol doesn't semantically tell apart an absent optional SEQUENCE OF type and a present but empty optional SEQUENCE OF type. Implementations SHOULD NOT send empty SEQUENCE OF encodings that are marked OPTIONAL, but SHOULD accept them as equivalent to an omitted OPTIONAL type. In the ASN.1 syntax describing Kerberos messages, these problem optional SEQUENCE OF types are marked with a comment ๐ฌ.
5.1.4. Unrecognized Tag Numbers
Future revisions of this protocol might add new message types with different APPLICATION class tag numbers ๐ฎ. Those revisions should protect older implementations by only sending the new message types to parties known to understand them, for example by using a flag bit that the receiver sets in an earlier request. For robust error handling, implementations SHOULD gracefully handle receiving a message with an unrecognized tag anyway, and return an error message if that's appropriate ๐ก๏ธ.
In particular, KDCs SHOULD return KRB_AP_ERR_MSG_TYPE if the wrong tag is sent over a TCP transport. KDCs SHOULD NOT respond to messages with an unknown tag over UDP transport, in order to avoid denial of service attacks ๐ซ. For non-KDC applications, the Kerberos implementation typically reports an error to the application, which then takes whatever steps make sense for its application protocol ๐งโโ๏ธ.
5.1.5. Tag Numbers Greater Than 30 ๐ธ
okay bestie, heads up ๐ซถ a naive DER ASN.1 decoder can totally trip over tag numbers bigger than 30, because those get encoded using more than one byte ๐ญ. future versions of this protocol might use tag numbers above 30, so implementations SHOULD be prepared to gracefully return an error, if appropriate, when they don't recognize the tag โจ
5.2. Basic Kerberos Types ๐
this section defines a bunch of basic types that could show up in multiple Kerberos protocol messages ๐
5.2.1. KerberosString ๐
so the original Kerberos spec in RFC 1510 uses GeneralString all over the place for human-readable string data ๐. historical implementations can't use the full power of GeneralString, and honestly that's kind of a mood ๐. this ASN.1 type needs designation and invocation escape sequences from ISO-2022/ECMA-35 [ISO-2022/ECMA-35] to switch character sets. the default character set designated as G0 is ISO-646/ECMA-6 [ISO-646/ECMA-6] International Reference Version (IRV) (a.k.a. U.S. ASCII), which mostly works ๐ธ
ISO-2022/ECMA-35 defines four character-set code elements (G0..G3) and two Control-function code elements (C0..C1) ๐ฆ. DER prohibits designating character sets as anything but the G0 and C0 sets. unfortunately, this seems to have the side effect of prohibiting ISO-8859 (ISO Latin) [ISO-8859] character sets, or any other character sets that use a 96-character set, since ISO-2022/ECMA-35 prohibits designating them as the G0 code element. this side effect is being investigated in the ASN.1 standards community ๐
in practice, a lot of implementations treat GeneralStrings as if they were 8-bit strings of whatever character set the implementation defaults to, without caring about correct usage of the character-set designation escape sequences ๐. the default is often determined by the current user's operating-system-dependent locale. at least one major implementation puts unescaped UTF-8 encoded Unicode characters in the GeneralString, and this failure to follow the GeneralString specs leads to interoperability issues when clients, services, and the KDC are using conflicting character encodings ๐ญ
this whole mess is the result of improper documentation of the restrictions on the ASN.1 GeneralString type in earlier Kerberos specs. not it ๐
the new (post-RFC 1510) type KerberosString, defined below, is a GeneralString that's constrained to contain only characters in IA5String ๐ง
KerberosString ::= GeneralString (IA5String)
in general, US-ASCII control characters should not be used in KerberosString. Control characters SHOULD NOT be used in principal names or realm names ๐ซ
for compatibility, implementations MAY choose to accept GeneralString values that contain characters other than those permitted by IA5String. they should be aware that character set designation codes will likely be absent, and that the encoding should probably be treated as locale-specific in almost every way ๐. implementations MAY also choose to emit GeneralString values that go beyond those permitted by IA5String, but they should be aware that doing so is extraordinarily risky from an interoperability perspective ๐
some existing implementations use GeneralString to encode unescaped locale-specific characters. this is a violation of the ASN.1 standard. most of these implementations encode US-ASCII in the left-hand half, so as long as the implementation only transmits US-ASCII, the ASN.1 standard isn't violated in this regard. as soon as one of them encodes unescaped locale-specific characters with the high bit set, it violates the ASN.1 standard ๐
other implementations have been known to use GeneralString to contain a UTF-8 encoding. that also violates the ASN.1 standard, since UTF-8 is a different encoding, not a 94 or 96 character "G" set as defined by ISO 2022 ๐ซ . it's believed these implementations don't even use the ISO 2022 escape sequence to change the character encoding. even if they did announce the encoding change with that escape sequence, the ASN.1 standard prohibits any escape sequences other than the ones used to designate or invoke "G" or "C" sets allowed by GeneralString ๐
future revisions of this protocol will almost certainly allow for a more interoperable representation of principal names, probably including UTF8String โจ
also, applying a new constraint to a previously unconstrained type creates a new ASN.1 type. in this particular case, the change doesn't result in a changed encoding under DER ๐
5.2.2. Realm and PrincipalName ๐
Realm ::= KerberosString
PrincipalName ::= SEQUENCE {
name-type [0] Int32,
name-string [1] SEQUENCE OF KerberosString
}
Kerberos realm names are encoded as KerberosStrings. Realms shall not contain a character with the code 0 (the US-ASCII NUL) ๐ . most realms will usually consist of several components separated by periods (.), in the style of Internet Domain Names, or separated by slashes (/), in the style of X.500 names. acceptable forms for realm names are specified in Section 6.1. a PrincipalName is a typed sequence of components made up of these subfields:
name-type: this field specifies the type of name that follows. pre-defined values for this field are specified in Section 6.2. The name-type SHOULD be treated as a hint. ignoring the name type, no two names can be the same (i.e., at least one of the components, or the realm, must be different) ๐งname-string: this field encodes a sequence of components that form a name, with each component encoded as a KerberosString. taken together, a PrincipalName and a Realm form a principal identifier ๐ฆ. most PrincipalNames will have only a few components (typically one or two)
5.2.3. KerberosTime โฐ
KerberosTime ::= GeneralizedTime -- with no fractional seconds
the timestamps used in Kerberos are encoded as GeneralizedTimes. a KerberosTime value shall not include any fractional portions of the seconds. as required by the DER, it further shall not include any separators, and it shall specify the UTC time zone (Z) ๐ธ. example: the only valid format for UTC time 6 minutes, 27 seconds after 9 pm on 6 November 1985 is 19851106210627Z ๐ง
5.2.4. Constrained Integer Types ๐ข
some integer members of types SHOULD be constrained to values representable in 32 bits, for compatibility with reasonable implementation limits ๐
Int32 ::= INTEGER (-2147483648..2147483647)
-- signed values representable in 32 bits
UInt32 ::= INTEGER (0..4294967295)
-- unsigned 32 bit values
Microseconds ::= INTEGER (0..999999)
-- microseconds
even though this changes the abstract types from the RFC 1510 version, the encoding in DER should be unaltered. historical implementations were typically limited to 32-bit integer values anyway, and assigned numbers SHOULD fall in the space of integer values representable in 32 bits, to promote interoperability anyway ๐ซถ
several integer fields in messages are constrained to fixed values:
pvno(also TKT-VNO or AUTHENTICATOR-VNO): this recurring field is always the constant integer 5. there's no easy way to make this field into a useful protocol version number, so its value is fixed ๐msg-type: this integer field is usually identical to the application tag number of the containing message type ๐ท๏ธ
5.2.5. HostAddress and HostAddresses ๐
HostAddress ::= SEQUENCE {
addr-type [0] Int32,
address [1] OCTET STRING
}
-- NOTE: HostAddresses is always used as an OPTIONAL field and
-- should not be empty.
HostAddresses -- NOTE: subtly different from rfc1510,
-- but has a value mapping and encodes the same
::= SEQUENCE OF HostAddress
the host address encodings consist of two fields:
addr-type: this field specifies the type of address that follows. Pre-defined values for this field are specified in Section 7.5.3 ๐address: this field encodes a single address of type addr-type ๐ฌ
5.2.6. AuthorizationData ๐๏ธ
-- NOTE: AuthorizationData is always used as an OPTIONAL field and
-- should not be empty.
AuthorizationData ::= SEQUENCE OF SEQUENCE {
ad-type [0] Int32,
ad-data [1] OCTET STRING
}
ad-data: this field contains authorization data to be interpreted according to the value of the corresponding ad-type field ๐ฆad-type: this field specifies the format for the ad-data subfield. All negative values are reserved for local use. Non-negative values are reserved for registered use ๐๏ธ
each sequence of type and data is called an authorization element. Elements MAY be application specific; however, there's a common set of recursive elements that should be understood by all implementations ๐. these elements contain other elements embedded within them, and the interpretation of the encapsulating element decides which of the embedded elements must be interpreted, and which ones may be ignored ๐ง
these common authorization data elements are recursively defined, meaning the ad-data for these types will itself contain a sequence of authorization data whose interpretation is affected by the encapsulating element. depending on what the encapsulating element means, the encapsulated elements may be ignored, might be interpreted as issued directly by the KDC, or might be stored in a separate plaintext part of the ticket. the types of the encapsulating elements are specified as part of the Kerberos specification, because the behavior based on these values should be understood across implementations, whereas other elements only need to be understood by the applications they affect ๐
authorization data elements are considered critical if present in a ticket or authenticator. if an unknown authorization data element type is received by a server, either in an AP-REQ or in a ticket contained in an AP-REQ, then, unless it's encapsulated in a known authorization data element that amends the criticality of the elements it contains, authentication MUST fail ๐จ. authorization data is intended to restrict the use of a ticket. if the service can't determine whether the restriction applies to that service, then a security weakness may result if the ticket can be used for that service ๐. authorization elements that are optional can be enclosed in an AD-IF-RELEVANT element ๐ซถ
in the definitions that follow, the value of the ad-type for the element is specified as the least significant part of the subsection number, and the value of the ad-data is as shown in the ASN.1 structure that follows the subsection heading โจ
Contents of ad-data ad-type
DER encoding of AD-IF-RELEVANT 1
DER encoding of AD-KDCIssued 4
DER encoding of AD-AND-OR 5
DER encoding of AD-MANDATORY-FOR-KDC 8
5.2.6.1. IF-RELEVANT ๐
AD-IF-RELEVANT ::= AuthorizationData
okay bestie, so AD elements tucked inside the if-relevant wrapper are only meant for application servers that actually understand that embedded ad-type ๐ . If an application server doesn't understand the type of an element inside it, that server MAY ignore the uninterpretable element ๐. This is giving interoperability queen ๐, because implementations can have their own local extensions for authorization and still play nice together ๐ฆ. The ad-type for AD-IF-RELEVANT is (1) โจ.
5.2.6.2. KDCIssued ๐
AD-KDCIssued ::= SEQUENCE {
ad-checksum [0] Checksum,
i-realm [1] Realm OPTIONAL,
i-sname [2] PrincipalName OPTIONAL,
elements [3] AuthorizationData
}
here's the breakdown of the fields ๐
ad-checksum: a cryptographic checksum computed over the DER encoding of the AuthorizationData in the "elements" field, keyed with the session key. Its checksumtype is the mandatory checksum type for the encryption type of the session key, and its key usage value is 19 ๐ธi-realmandi-sname: the name of the issuing principal, but only if it's different from the KDC itself. This field would be used when the KDC can verify the authenticity of elements signed by the issuing principal, and it lets this KDC tell the application server whether those elements are valid ๐งelements: a sequence of authorization data elements issued by the KDC โญ
the KDC-issued ad-data field is basically a way for Kerberos principal credentials to carry their own privilege attributes and other mechanisms for positive authorization, boosting the principal's privileges beyond what's possible with credentials that don't have an ad-data element like this ๐โจ
the above can't be done without this element, because the authorization-data field lets whoever holds a TGT add elements at will when they request service tickets, and elements can also be added to a delegated ticket by putting them in the authenticator ๐
for KDC-issued elements, this gets blocked because the KDC signs them by including a checksum encrypted with the server's key (the same key used to encrypt the ticket, or a key derived from that key) ๐ฅ elements encapsulated within the KDC-issued element MUST be ignored by the application server if this "signature" is not present ๐ โโ๏ธ also, elements inside this element that come from a TGT MAY be interpreted by the KDC and used, according to policy, as a basis for including new signed elements in derivative tickets, but they will NOT be copied directly into a derivative ticket. if a KDC that doesn't know about this element copies them over directly anyway, the signature won't be correct for the application ticket elements, and the application server will ignore that field ๐ญ
this element and the elements it encapsulates MAY safely be ignored by applications, application servers, and KDCs that don't implement it ๐ซถ
the ad-type for AD-KDC-ISSUED is (4) ๐
โ ๏ธ reminder: the MUST and MAY rules above are not optional vibes. the "signature" check is what keeps these elements trustworthy.
5.2.6.3. AND-OR ๐
AD-AND-OR ::= SEQUENCE {
condition-count [0] Int32,
elements [1] AuthorizationData
}
when restrictive AD elements are wrapped inside the and-or element, the and-or element counts as satisfied if and only if at least the number of encapsulated elements listed in condition-count are satisfied ๐ง so this element MAY be used to build an "or" operation by setting condition-count to 1, and it MAY specify an "and" operation by setting condition-count to the number of embedded elements ๐ application servers that don't implement this element MUST reject tickets containing authorization data elements of this type ๐ซ
the ad-type for AD-AND-OR is (5) ๐ฆ
5.2.6.4. MANDATORY-FOR-KDC ๐
AD-MANDATORY-FOR-KDC ::= AuthorizationData
AD elements wrapped inside the mandatory-for-kdc element are meant to be interpreted by the KDC ๐ KDCs that don't understand the type of an element embedded in here MUST reject the request ๐ โโ๏ธ
the ad-type for AD-MANDATORY-FOR-KDC is (8) ๐
5.2.7. PA-DATA ๐ธ
historically, PA-DATA was known as "pre-authentication data", meaning it was used to augment the initial authentication with the KDC ๐ฐ๏ธ but since then, it's also been used as a typed hole for extending protocol exchanges with the KDC, which is so iconic ๐งโโ๏ธ
PA-DATA ::= SEQUENCE {
-- NOTE: first tag is [1], not [0]
padata-type [1] Int32,
padata-value [2] OCTET STRING -- might be encoded AP-REQ
}
padata-type: tells you how to interpret the padata-value element. Negative values are reserved for unregistered use, and non-negative values are used for a registered interpretation of the element type ๐ขpadata-value: usually contains the DER encoding of another type, and the padata-type field tells you which type is encoded there โจ
padata-type Name Contents of padata-value
1 pa-tgs-req DER encoding of AP-REQ
2 pa-enc-timestamp DER encoding of PA-ENC-TIMESTAMP
3 pa-pw-salt salt (not ASN.1 encoded)
11 pa-etype-info DER encoding of ETYPE-INFO
19 pa-etype-info2 DER encoding of ETYPE-INFO2
this field MAY also contain info needed by certain extensions to the Kerberos protocol ๐ซ for example, it might verify a client's identity before any response goes back ๐
the padata field can also carry info that helps the KDC or the client pick the key needed for generating or decrypting the response ๐ this is super useful for supporting certain token cards with Kerberos ๐ณ the details of those extensions live in separate documents ๐ see [Pat92] for more uses of this field ๐
5.2.7.1. PA-TGS-REQ ๐ซ
for requests for additional tickets (KRB_TGS_REQ), padata-value will contain an encoded AP-REQ ๐ the checksum in the authenticator (which MUST be collision-proof) gets computed over the KDC-REQ-BODY encoding ๐
5.2.7.2. Encrypted Timestamp Pre-authentication โฐ
there are pre-authentication types that can pre-authenticate a client using an encrypted timestamp โจ
PA-ENC-TIMESTAMP ::= EncryptedData -- PA-ENC-TS-ENC
PA-ENC-TS-ENC ::= SEQUENCE {
patimestamp [0] KerberosTime -- client's time --,
pausec [1] Microseconds OPTIONAL
}
patimestamp holds the client's time, and pausec holds the microseconds ๐ pausec MAY be omitted if a client won't generate more than one request per second ๐โโ๏ธ the ciphertext (padata-value) is the PA-ENC-TS-ENC encoding, encrypted using the client's secret key and a key usage value of 1 ๐ฆ
this pre-authentication type wasn't in RFC 1510, but lots of implementations support it ๐ซถ
5.2.7.3. PA-PW-SALT ๐ง
the padata-value for this pre-authentication type contains the salt for the string-to-key that the client uses to get the key for decrypting the encrypted part of an AS-REP message ๐ unfortunately, for historical reasons, the character set is unspecified and probably locale-specific ๐ (not ideal, bestie ๐ญ)
this pre-authentication type wasn't in RFC 1510, but many implementations support it ๐ it's necessary in any case where the salt for the string-to-key algorithm isn't the default ๐
in the simplest example, a zero-length salt string is super common for realms that converted their principal databases from Kerberos Version 4 ๐ธ
a KDC SHOULD NOT send PA-PW-SALT when issuing a KRB-ERROR message that requests additional pre-authentication ๐ซ
๐ ๏ธ implementation note: some KDC implementations send an erroneous PA-PW-SALT when issuing a KRB-ERROR message that requests additional pre-authentication. so clients SHOULD ignore a PA-PW-SALT that comes with a KRB-ERROR message requesting additional pre-authentication ๐
as noted in section 3.1.3, a KDC MUST NOT send PA-PW-SALT when the client's AS-REQ includes at least one "newer" etype ๐ซโจ
5.2.7.4. PA-ETYPE-INFO ๐๏ธ
the ETYPE-INFO pre-authentication type is sent by the KDC in a KRB-ERROR that indicates a requirement for additional pre-authentication ๐ it's usually used to tell a client which key to use for encrypting an encrypted timestamp, for the purposes of sending a PA-ENC-TIMESTAMP pre-authentication value ๐ it MAY also be sent in an AS-REP to tell the client which key salt to use for the string-to-key, so the client can get the key for decrypting the encrypted part of the AS-REP ๐ง
ETYPE-INFO-ENTRY ::= SEQUENCE {
etype [0] Int32,
salt [1] OCTET STRING OPTIONAL
}
ETYPE-INFO ::= SEQUENCE OF ETYPE-INFO-ENTRY
the salt, like PA-PW-SALT's, is also completely unspecified when it comes to character set and is probably locale-specific ๐
if ETYPE-INFO is sent in an AS-REP, there shall be exactly one ETYPE-INFO-ENTRY, and its etype shall match that of the enc-part in the AS-REP ๐ฏ
this pre-authentication type wasn't in RFC 1510, but many implementations that support encrypted timestamps for pre-authentication need ETYPE-INFO as well ๐ as noted in Section 3.1.3, a KDC MUST NOT send PA-ETYPE-INFO when the client's AS-REQ includes at least one "newer" etype ๐ซ
5.2.7.5. PA-ETYPE-INFO2 ๐
the ETYPE-INFO2 pre-authentication type is sent by the KDC in a KRB-ERROR that indicates a requirement for additional pre-authentication ๐ it's usually used to tell a client which key to use for encrypting an encrypted timestamp, for the purposes of sending a PA-ENC-TIMESTAMP pre-authentication value ๐ it MAY also be sent in an AS-REP to tell the client which key salt to use for the string-to-key, so the client can get the key for decrypting the encrypted part of the AS-REP ๐งโโ๏ธ
ETYPE-INFO2-ENTRY ::= SEQUENCE {
etype [0] Int32,
salt [1] KerberosString OPTIONAL,
s2kparams [2] OCTET STRING OPTIONAL
}
ETYPE-INFO2 ::= SEQUENCE SIZE (1..MAX) OF ETYPE-INFO2-ENTRY
the salt's type is KerberosString, but existing installations might have locale-specific characters stored in salt strings, and implementors MAY choose to handle them ๐๐
the interpretation of s2kparams is specified in the cryptosystem description tied to the etype ๐งช each cryptosystem has a default interpretation of s2kparams that applies if that element is left out of the ETYPE-INFO2-ENTRY encoding โจ
if ETYPE-INFO2 is sent in an AS-REP, there shall be exactly one ETYPE-INFO2-ENTRY, and its etype shall match that of the enc-part in the AS-REP ๐ฏ
the preferred ordering of the "hint" pre-authentication data that affects client key selection is: ETYPE-INFO2, then ETYPE-INFO, then PW-SALT ๐ฅ as noted in Section 3.1.3, a KDC MUST NOT send ETYPE-INFO or PW-SALT when the client's AS-REQ includes at least one "newer" etype ๐ โโ๏ธ๐
the ETYPE-INFO2 pre-authentication type wasn't in RFC 1510 ๐ธ
5.2.8. KerberosFlags โจ
Okay so for a bunch of message types, Kerberos uses a special bit string type called KerberosFlags ๐ It's basically a compact row of on/off switches, and it's giving very specific vibes ๐
KerberosFlags ::= BIT STRING (SIZE (32..MAX))
-- minimum number of bits shall be sent,
-- but no fewer than 32
Compatibility note: this next part describes a change from the RFC 1510 description of bit strings. It would break an implementation that strictly followed ASN.1 DER and RFC 1510 ๐
ASN.1 bit strings have a few jobs. The simplest one is just holding a vector of bits with no special meaning for any individual bit, and that vector doesn't have to be a multiple of eight bits long ๐ง Kerberos wants something different: a bit string used as a compact boolean vector, where every bit has its own meaning. The natural way to write that is the ASN.1 "NamedBit" notation, but DER says that encodings using "NamedBit" notation have to leave off any trailing zero bits. That truncation is super easy to forget, especially in C implementations, which tend to store boolean vectors as 32-bit integers ๐ญ
Here's an example. Say the KDCOptions notation included "NamedBit" like RFC 1510 did, and you were encoding a KDCOptions value where only the "forwardable" bit (bit number one) was set. The DER encoding MUST include only two bits: the first reserved bit ("reserved", bit number zero, value zero) and the one-valued bit (bit number one) for "forwardable". Bestie, that's the whole thing ๐
Most existing Kerberos implementations just send 32 bits on the wire whenever they encode a bit string used as a boolean vector. That breaks the ASN.1 syntax RFC 1510 used for flag values, but the install base is so huge that this protocol description is being changed to accommodate it ๐
So this document takes the "NamedBit" notations for individual bits out and moves them into comments. The size constraint on KerberosFlags means at least 32 bits have to be encoded every time. A lenient implementation MAY choose to accept fewer than 32 bits, though, and treat the missing bits as set to zero ๐ซถ
Right now no use of KerberosFlags needs more than 32 bits of flags, but future revisions of this document might. If more than 32 bits ever get sent in a KerberosFlags value, future revisions will probably say to send the smallest number of bits needed to encode the highest-numbered one-valued bit. That's kind of similar to how DER encodes a bit string declared with the "NamedBit" notation ๐ฆ
5.2.9. Cryptosystem-Related Types โจ
Lots of Kerberos messages carry an EncryptedData as a container for arbitrary encrypted data. Usually that data is the encrypted encoding of some other data type. The fields inside EncryptedData help the recipient pick the right key to decrypt what's inside ๐ฅ
EncryptedData ::= SEQUENCE {
etype [0] Int32 -- EncryptionType --,
kvno [1] UInt32 OPTIONAL,
cipher [2] OCTET STRING -- ciphertext
}
etype: this field says which encryption algorithm was used to encipher the cipher.
kvno: this field has the version number of the key the data is encrypted under. It only shows up in messages encrypted under long-lasting keys, like principals' secret keys ๐
cipher: this field holds the enciphered text, encoded as an OCTET STRING. (Also, the encryption mechanisms defined in [RFC3961] MUST incorporate integrity protection as well, so you don't need any extra checksum. Iconic, right? ๐
)
The EncryptionKey type is how cryptographic keys used for encryption get transferred ๐
EncryptionKey ::= SEQUENCE {
keytype [0] Int32 -- actually encryption type --,
keyvalue [1] OCTET STRING
}
keytype: this field specifies the encryption type of the key in the keyvalue field that follows. Even though it's called "keytype", it actually specifies an encryption type ๐ Back in the day, cryptosystems that encrypted differently but could use keys with the same characteristics were allowed to share one assigned number for the key type. That usage is deprecated now.
keyvalue: this field contains the key itself, encoded as an octet string.
Messages with cleartext data that needs authenticating will usually do it with a Checksum member. Most Checksum instances use a keyed hash, but the exceptions will be called out ๐
Checksum ::= SEQUENCE {
cksumtype [0] Int32,
checksum [1] OCTET STRING
}
cksumtype: this field says which algorithm made the accompanying checksum.
checksum: this field contains the checksum itself, encoded as an octet string.
For a quick rundown of how encryption and checksums get used in Kerberos, see Section 4 โจ
5.3. Tickets ๐๏ธ
This section covers the format and encryption parameters for tickets and authenticators. When a ticket or authenticator shows up in a protocol message, it's treated as an opaque object ๐ซฃ A ticket is a record that helps a client authenticate to a service. A Ticket has the following information:
Ticket ::= [APPLICATION 1] SEQUENCE {
tkt-vno [0] INTEGER (5),
realm [1] Realm,
sname [2] PrincipalName,
enc-part [3] EncryptedData -- EncTicketPart
}
-- Encrypted part of ticket
EncTicketPart ::= [APPLICATION 3] SEQUENCE {
flags [0] TicketFlags,
key [1] EncryptionKey,
crealm [2] Realm,
cname [3] PrincipalName,
transited [4] TransitedEncoding,
authtime [5] KerberosTime,
starttime [6] KerberosTime OPTIONAL,
endtime [7] KerberosTime,
renew-till [8] KerberosTime OPTIONAL,
caddr [9] HostAddresses OPTIONAL,
authorization-data [10] AuthorizationData OPTIONAL
}
-- encoded Transited field
TransitedEncoding ::= SEQUENCE {
tr-type [0] Int32 -- must be registered --,
contents [1] OCTET STRING
}
TicketFlags ::= KerberosFlags
-- reserved(0),
-- forwardable(1),
-- forwarded(2),
-- proxiable(3),
-- proxy(4),
-- may-postdate(5),
-- postdated(6),
-- invalid(7),
-- renewable(8),
-- initial(9),
-- pre-authent(10),
-- hw-authent(11),
-- the following are new since 1510
-- transited-policy-checked(12),
-- ok-as-delegate(13)
tkt-vno: this field specifies the version number of the ticket format. This document describes version number 5 โจ
realm: this field says which realm issued the ticket. It also identifies the realm part of the server's principal identifier. A Kerberos server can only issue tickets for servers inside its own realm, so the two are always identical ๐
sname: this field specifies every component of the name part of the server's identity, including the parts that identify a specific instance of a service ๐ง
enc-part: this field holds the encrypted encoding of the EncTicketPart sequence. It's encrypted under the key shared by Kerberos and the end server (the server's secret key), using a key usage value of 2 ๐
flags: this field shows which options were used or requested when the ticket was issued. Here's what the flags mean:
Bit(s) Name Description
0 reserved Reserved for future expansion of this field.
1 forwardable The FORWARDABLE flag is normally only
interpreted by the TGS, and can be ignored
by end servers. When set, this flag tells
the ticket-granting server that it is OK to
issue a new TGT with a different network
address based on the presented ticket.
2 forwarded When set, this flag indicates that the
ticket has either been forwarded or was
issued based on authentication involving a
forwarded TGT.
3 proxiable The PROXIABLE flag is normally only
interpreted by the TGS, and can be ignored
by end servers. The PROXIABLE flag has an
interpretation identical to that of the
FORWARDABLE flag, except that the PROXIABLE
flag tells the ticket-granting server that
only non-TGTs may be issued with different
network addresses.
4 proxy When set, this flag indicates that a ticket
is a proxy.
5 may-postdate The MAY-POSTDATE flag is normally only
interpreted by the TGS, and can be ignored
by end servers. This flag tells the
ticket-granting server that a post-dated
ticket MAY be issued based on this TGT.
6 postdated This flag indicates that this ticket has
been postdated. The end-service can check
the authtime field to see when the original
authentication occurred.
7 invalid This flag indicates that a ticket is
invalid, and it must be validated by the KDC
before use. Application servers must reject
tickets which have this flag set.
8 renewable The RENEWABLE flag is normally only
interpreted by the TGS, and can usually be
ignored by end servers (some particularly
careful servers MAY disallow renewable
tickets). A renewable ticket can be used to
obtain a replacement ticket that expires at
a later date.
9 initial This flag indicates that this ticket was
issued using the AS protocol, and not issued
based on a TGT.
10 pre-authent This flag indicates that during initial
authentication, the client was authenticated
by the KDC before a ticket was issued. The
strength of the pre-authentication method is
not indicated, but is acceptable to the KDC.
Okay, so the ticket flags keep going, and bestie, these are the flags that tell the server what kind of trust the ticket carries ๐ฆ
11 hw-authent This flag indicates that the protocol
employed for initial authentication required
the use of hardware expected to be possessed
solely by the named client. The hardware
authentication method is selected by the KDC
and the strength of the method is not
indicated.
12 transited- This flag indicates that the KDC for
policy-checked the realm has checked the transited field
against a realm-defined policy for trusted
certifiers. If this flag is reset (0), then
the application server must check the
transited field itself, and if unable to do
so, it must reject the authentication. If
the flag is set (1), then the application
server MAY skip its own validation of the
transited field, relying on the validation
performed by the KDC. At its option the
application server MAY still apply its own
validation based on a separate policy for
acceptance.
This flag is new since RFC 1510.
13 ok-as-delegate This flag indicates that the server (not the
client) specified in the ticket has been
determined by policy of the realm to be a
suitable recipient of delegation. A client
can use the presence of this flag to help it
decide whether to delegate credentials
(either grant a proxy or a forwarded TGT) to
this server. The client is free to ignore
the value of this flag. When setting this
flag, an administrator should consider the
security and placement of the server on
which the service will run, as well as
whether the service requires the use of
delegated credentials.
This flag is new since RFC 1510.
14-31 reserved Reserved for future use.
hw-authent (flag 11) says the first login used hardware that only the named client should have, like a security key ๐. The KDC picks that hardware method, but the flag doesn't say how strong it is, so don't assume it's bulletproof, babe ๐
transited-policy-checked (flag 12) is all about the transited field. If it's reset (0), the application server has to check that field itself, and if it can't, it has to reject the authentication, no excuses ๐
โโ๏ธ If it's set (1), the application server MAY skip its own check and trust the KDC's check instead. It can still run its own check with a separate acceptance policy if it wants to, because it's the server's call โจ This flag is new since RFC 1510 ๐ธ
ok-as-delegate (flag 13) means the realm's policy has said the server named in the ticket (not the client!) is a good place to send delegated credentials ๐ง The client can look at this flag to decide whether to hand over a proxy or a forwarded TGT, but it's totally free to ignore it ๐ Admins, though, should think hard about how secure the server is and where it's sitting, plus whether the service even needs delegated credentials at all ๐ก๏ธ This flag is new since RFC 1510 ๐
Flags 14-31 are reserved for future use ๐
Now the fields. These are the bits that hold the actual ticket info, so pay attention โจ
key is in the ticket and in the KDC response. It's how the session key gets passed from Kerberos to both the application server and the client ๐
crealm is the realm where the client is registered and where the first authentication happened ๐ฐ
cname holds the name part of the client's principal identifier ๐ชช
transited lists the names of the Kerberos realms that helped authenticate the user this ticket was issued to. The order the realms were passed through is NOT part of it, so don't go looking for a sequence ๐
โโ๏ธ Check out Section 3.3.3.2 for how the traversed realms actually get encoded. When CA names are meant to go in the transited field (some protocol extensions do this), the X.500 names of those CAs SHOULD be mapped into transited items using the mapping defined by RFC 2253 ๐
authtime is the time of the principal's initial authentication, which is the issue time of the original ticket this one is based on โฐ It's in the ticket so the end service gets extra info, and so the KDC can run a "hot list" service. A super paranoid end service could refuse tickets whose initial authentication was "too far" in the past ๐ค It also comes back in the KDC response. In a KRB_AS_REP, it's the current time on the Kerberos server ๐ฐ๏ธ It is NOT recommended that you use this time to set the workstation's clock, because the workstation can't reliably confirm that the KRB_AS_REP really came from the right KDC in a timely way ๐ซ
starttime is the time after which the ticket is valid ๐
Together with endtime, it sets the ticket's life. If starttime is missing from the ticket, authtime SHOULD be used in its place to figure out the ticket's life ๐ซ
endtime is when the ticket stops being honored, its expiration time ๐ฅ Heads up: individual services MAY put their own limits on a ticket's life, and they MAY reject tickets that haven't expired yet. So think of endtime as an upper bound on expiration, not a guarantee ๐
renew-till only shows up in tickets with the RENEWABLE flag set in the flags field ๐ It's the latest endtime a renewal can get, so you can think of it as the ticket's absolute expiration, renewals and all ๐๏ธ
caddr holds zero (if left out) or more host addresses, which are the places the ticket can be used from. No addresses means the ticket works from anywhere ๐ Whether the KDC issues addressless tickets, or the end server accepts them, is a policy call left to the Kerberos and end-service admins, and they MAY refuse to issue or accept them ๐ Since network address translation is everywhere now, it's recommended that policy allows issuing and accepting these tickets ๐ซถ
Addresses are in the ticket to make life harder for attackers who steal credentials ๐ต๏ธโโ๏ธ The session key never travels over the network in cleartext, so just sniffing the wire won't steal a ticket. The attacker needs the session key too, maybe from an OS breach or someone's unlocked laptop, before the stolen ticket is any use ๐ป
Network addresses can't be reliably determined from where a connection comes in. Even if they could, an attacker who has compromised the client's workstation could use the credentials from there. Addresses only make it harder, not impossible, for someone to walk off with stolen credentials and then use them from a "safe" spot. Don't treat them as a security blanket, bestie ๐ญ
authorization-data carries authorization data from the principal the ticket was issued for over to the application service ๐ซ If there's no authorization data, the field is left out. Honestly, the name is confusing. A better name would've been "restrictions", but it can't be changed now ๐
This field holds restrictions on any authority you get from authenticating with the ticket. Anyone holding credentials can add entries, since entries only narrow what the ticket can do. They can add them by asking for a new ticket during the TGS exchange, or they MAY add them during chained delegation through the authenticator's authorization data field ๐
Here's the rule that matters: since credential holders can add entries, an entry in a ticket's authorization data can never amplify the privileges you'd get from the ticket. The only exception is when an entry is separately authenticated by being wrapped in the KDC-issued element, so the KDC vouched for it ๐ก๏ธ
The data here can be specific to the end service. The field holds the names of service-specific objects and the rights to those objects ๐๏ธ Kerberos doesn't care what's inside the subfields, but it does carry type information through ad-type ๐ท๏ธ The format is described in Section 5.2.6 ๐
With authorization-data, a principal can issue a proxy that's only valid for one purpose โจ For example, a client who wants to print a file can get a file server proxy and pass it to the print server. By naming the file in the field, the file server knows the print server can only use the client's rights for that one file ๐จ๏ธ
A separate service that grants authorization or certifies group membership can use this field too ๐ In that setup, the entity granting the authority (not the one getting it) can get a ticket in its own name, like a privilege server's. It adds restrictions to its own authority and delegates that restricted authority to the client through a proxy ๐ค The client then shows that authorization credential to the application server separately from the authentication exchange. Or, the authorization credentials MAY be embedded in the ticket that authenticates the authorized entity, as long as the authorization is separately authenticated with the KDC-issued authorization data element (see 5.2.6.2) ๐งฉ
Also, if you set up the authorization-data field of a proxy and leave the host addresses blank, the resulting ticket and session key can be treated as a capability ๐ฆ See [Neu93] for some suggested uses of this field ๐
The authorization-data field is optional, so a ticket doesn't have to include it ๐ธ
5.4. Specifications for the AS and TGS Exchanges โจ
This section lays out the format of the messages exchanged between the client and the Kerberos server ๐ The format for possible error messages is in Section 5.9.1 ๐จ
5.4.1. KRB_KDC_REQ Definition
The KRB_KDC_REQ message doesn't have its own application tag number ๐
โโ๏ธ Instead, it gets folded into either KRB_AS_REQ or KRB_TGS_REQ, and each of those has its own application tag. Which one you use depends on whether you're asking for an initial ticket or an additional one ๐๏ธ Either way, the message goes from the client to the KDC to request credentials for a service ๐ซถ
The message fields are as follows:
AS-REQ ::= [APPLICATION 10] KDC-REQ
TGS-REQ ::= [APPLICATION 12] KDC-REQ
KDC-REQ ::= SEQUENCE {
-- NOTE: first tag is [1], not [0]
pvno [1] INTEGER (5) ,
msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --),
padata [3] SEQUENCE OF PA-DATA OPTIONAL
-- NOTE: not empty --,
req-body [4] KDC-REQ-BODY
}
KDC-REQ-BODY ::= SEQUENCE { kdc-options [0] KDCOptions, cname [1] PrincipalName OPTIONAL -- Used only in AS-REQ --, realm [2] Realm -- Server's realm -- Also client's in AS-REQ --, sname [3] PrincipalName OPTIONAL, from [4] KerberosTime OPTIONAL, till [5] KerberosTime, rtime [6] KerberosTime OPTIONAL, nonce [7] UInt32, etype [8] SEQUENCE OF Int32 -- EncryptionType -- in preference order --, addresses [9] HostAddresses OPTIONAL, enc-authorization-data [10] EncryptedData OPTIONAL -- AuthorizationData --, additional-tickets [11] SEQUENCE OF Ticket OPTIONAL -- NOTE: not empty }
KDCOptions ::= KerberosFlags -- reserved(0), -- forwardable(1), -- forwarded(2), -- proxiable(3), -- proxy(4), -- allow-postdate(5), -- postdated(6), -- unused7(7), -- renewable(8), -- unused9(9), -- unused10(10), -- opt-hardware-auth(11), -- unused12(12), -- unused13(13), -- 15 is reserved for canonicalize -- unused15(15), -- 26 was unused in 1510 -- disable-transited-check(26), -- -- renewable-ok(27), -- enc-tkt-in-skey(28), -- renew(30), -- validate(31)
Okay, let's break down the fields in this message, because each one has its own job ๐งโจ
pvno shows up in every single message ๐ It holds the protocol version number, and this spec is all about version 5.
msg-type tells you what kind of message you're looking at ๐ฆ It's almost always the same as the application identifier for the message. It's basically there so apps can grab it easily. For the KDC-REQ message, this type is going to be KRB_AS_REQ or KRB_TGS_REQ.
padata holds pre-authentication data, and it's giving main character energy ๐ Requests for additional tickets (KRB_TGS_REQ) MUST contain a padata of PA-TGS-REQ. No skipping that one, bestie ๐ญ
The padata (pre-authentication data) field is a list of auth info that might be needed before credentials can be issued or decrypted ๐
req-body is a placeholder that marks where the rest of the fields live ๐ If you're calculating a checksum over the request, you do it over an encoding of the KDC-REQ-BODY sequence that's enclosed within req-body. โจ
kdc-options shows up in the KRB_AS_REQ and KRB_TGS_REQ requests sent to the KDC ๐ธ It tells the KDC which flags the client wants set on its tickets, plus other info that changes how the KDC behaves. When an option has a name, that name can match the flag it sets. Usually the bit in the options field matches the bit in the flags field, but that's not guaranteed, so it's not acceptable to just copy the options field over to the flags field. Babe, no shortcuts ๐ โโ๏ธ There are also various checks that must be made before an option gets honored anyway.
The kdc_options field is a bit-field ๐ Selected options get the bit set to 1, and unselected options and reserved fields get reset to 0. The encoding of the bits is in Section 5.2. The options are described in more detail above in Section 2. Here's the tea on what each one means:
Bits Name Description
0 RESERVED Reserved for future expansion of
this field.
1 FORWARDABLE The FORWARDABLE option indicates
that the ticket to be issued is to
have its forwardable flag set. It
may only be set on the initial
request, or in a subsequent request
if the TGT on which it is based is
also forwardable.
2 FORWARDED The FORWARDED option is only
specified in a request to the
ticket-granting server and will only
be honored if the TGT in the request
has its FORWARDABLE bit set. This
option indicates that this is a
request for forwarding. The
address(es) of the host from which
the resulting ticket is to be valid
are included in the addresses field
of the request.
3 PROXIABLE The PROXIABLE option indicates that
the ticket to be issued is to have
its proxiable flag set. It may only
be set on the initial request, or a
subsequent request if the TGT on
which it is based is also proxiable.
4 PROXY The PROXY option indicates that this
is a request for a proxy. This
option will only be honored if the
TGT in the request has its PROXIABLE
bit set. The address(es) of the
host from which the resulting ticket
is to be valid are included in the
addresses field of the request.
5 ALLOW-POSTDATE The ALLOW-POSTDATE option indicates
that the ticket to be issued is to
have its MAY-POSTDATE flag set. It
may only be set on the initial
request, or in a subsequent request
if the TGT on which it is based also
has its MAY-POSTDATE flag set.
6 POSTDATED The POSTDATED option indicates that
this is a request for a postdated
ticket. This option will only be
honored if the TGT on which it is
based has its MAY-POSTDATE flag set.
The resulting ticket will also have
its INVALID flag set, and that flag
may be reset by a subsequent request
to the KDC after the starttime in
the ticket has been reached.
7 RESERVED This option is presently unused.
8 RENEWABLE The RENEWABLE option indicates that
the ticket to be issued is to have
its RENEWABLE flag set. It may only
be set on the initial request, or
when the TGT on which the request is
based is also renewable. If this
option is requested, then the rtime
field in the request contains the
desired absolute expiration time for
the ticket.
9 RESERVED Reserved for PK-Cross.
10 RESERVED Reserved for future use.
11 RESERVED Reserved for opt-hardware-auth.
12-25 RESERVED Reserved for future use.
26 DISABLE-TRANSITED-CHECK By default the KDC will check the
transited field of a TGT against the
policy of the local realm before it
will issue derivative tickets based
on the TGT. If this flag is set in
the request, checking of the
transited field is disabled.
Tickets issued without the
performance of this check will be
noted by the reset (0) value of the
TRANSITED-POLICY-CHECKED flag,
indicating to the application server
that the transited field must be
checked locally. KDCs are
encouraged but not required to honor
the DISABLE-TRANSITED-CHECK option.
This flag is new since RFC 1510.
27 RENEWABLE-OK The RENEWABLE-OK option indicates
that a renewable ticket will be
acceptable if a ticket with the
requested life cannot otherwise be
provided, in which case a renewable
ticket may be issued with a renew-
till equal to the requested endtime.
The value of the renew-till field
may still be limited by local
limits, or limits selected by the
individual principal or server.
28 ENC-TKT-IN-SKEY This option is used only by the
ticket-granting service. The ENC-
TKT-IN-SKEY option indicates that
the ticket for the end server is to
be encrypted in the session key from
the additional TGT provided.
29 RESERVED Reserved for future use.
30 RENEW This option is used only by the
ticket-granting service. The RENEW
option indicates that the present
request is for a renewal. The
ticket provided is encrypted in the
secret key for the server on which
it is valid. This option will only
be honored if the ticket to be
renewed has its RENEWABLE flag set
and if the time in its renew-till
field has not passed. The ticket to
be renewed is passed in the padata
field as part of the authentication
header.
31 VALIDATE This option is used only by the
ticket-granting service. The
VALIDATE option indicates that the
request is to validate a postdated
ticket. It will only be honored if
the ticket presented is postdated,
presently has its INVALID flag set,
and would otherwise be usable at
this time. A ticket cannot be
validated before its starttime. The
ticket presented for validation is
encrypted in the key of the server
for which it is valid and is passed
in the padata field as part of the
authentication header.
okay so bit 31 is VALIDATE ๐ฆ and it's giving "only for the ticket-granting service" energy ๐
. It's basically the request saying "hey, please check this postdated ticket for me." ๐ It only gets honored if the ticket is postdated, has its INVALID flag set, and would otherwise be usable right now โจ. And no validating a ticket before its starttime, bestie, that's a no-go ๐. The ticket you hand over is encrypted in the key of the server it's valid for, and it rides along in the padata field inside the authentication header ๐ง.
cname and sname: these work the same as the ones we went over for the ticket in Section 5.3 ๐. The sname can only be missing when the ENC-TKT-IN-SKEY option is on ๐ธ. If sname is absent, the server's name gets pulled from the client's name in the ticket you pass as additional-tickets ๐ซถ.
enc-authorization-data: this one is only allowed in the TGS_REQ form ๐. It's the authorization data you want, encrypted under the sub-session key if there's one in the Authenticator, or else under the session key from the TGT ๐. Both the Authenticator and the TGT come from the padata field in the KRB_TGS_REQ. The key usage value is 5 if you're using a sub-session key, or 4 if it's the session key ๐ฅ.
realm: this is the realm part of the server's principal identifier ๐. In the AS exchange, it's also the realm part of the client's principal identifier, so it does double duty ๐.
from: included in the KRB_AS_REQ and KRB_TGS_REQ ticket requests when you want the ticket postdated โญ. It sets the desired starttime. If you leave it out, the KDC SHOULD use the current time instead ๐.
till: this is the expiration date the client is asking for ๐. It's not optional, bestie! But if the requested endtime is "19700101000000Z", the client is asking for the maximum endtime that KDC policy allows ๐. Fun fact from the implementation note: that special timestamp matches a UNIX time_t value of zero on most systems ๐คโจ.
rtime: the requested renew-till time, sent from client to KDC in a ticket request ๐ฆ. It's optional, so no pressure ๐ธ.
nonce: this is part of both the KDC request and response ๐. It's meant to hold a random number the client generated. If that same number shows up in the encrypted response from the KDC, it proves the response is fresh and hasn't been replayed by some attacker ๐. Nonces MUST NEVER be reused. Never, ever, ever ๐ญ๐ฅ.
etype: this is the encryption algorithm you'd like used in the response ๐.
addresses: this shows up in the initial ticket request, and it's optional in requests for additional tickets from the ticket-granting server ๐ง. It lists the addresses where the requested ticket is valid. Normally that's the client's host addresses, but if a proxy is requested, this field holds other addresses instead ๐. The KDC usually copies these into the caddr field of the resulting ticket ๐
.
additional-tickets: additional tickets MAY be included in a request to the ticket-granting server ๐ซถ. If ENC-TKT-IN-SKEY is specified, then the session key from the additional ticket gets used in place of the server's key to encrypt the new ticket ๐. When ENC-TKT-IN-SKEY is used for user-to-user authentication, this additional ticket MAY be a TGT issued by the local realm, or an inter-realm TGT issued for the current KDC's realm by a remote KDC ๐. If you ask for more than one option that needs additional tickets, they get used in the order set by the ordering of the options bits (see kdc-options, above) โจ.
The application tag number is either ten (10) or twelve (12), depending on whether the request is for an initial ticket (AS-REQ) or for an additional ticket (TGS-REQ) ๐.
The optional fields (addresses, authorization-data, and additional-tickets) only get included when they're actually needed to perform the operation specified in the kdc-options field ๐.
Note that in KRB_TGS_REQ, the protocol version number shows up twice, and two different message types show up too ๐. The KRB_TGS_REQ message has these fields, and so does the authentication header (KRB_AP_REQ) that gets passed in the padata field ๐ง๐.
5.4.2. KRB_KDC_REP Definition ๐
okay so the KRB_KDC_REP message is the reply the KDC sends back for either an initial (AS) request or a later (TGS) request ๐. bestie, there's no message type literally called KRB_KDC_REP ๐. the type is either KRB_AS_REP or KRB_TGS_REP, and which one it is decides which key encrypts the ciphertext part of the reply ๐. for KRB_AS_REP, the ciphertext is encrypted in the client's secret key, and the client's key version number gets included in the key version number for the encrypted data โจ. for KRB_TGS_REP, the ciphertext is encrypted in the sub-session key from the Authenticator. if that's absent, it's encrypted in the session key from the TGT used in the request ๐ฆ. in that case, no version number will be present in the EncryptedData sequence ๐ .
The KRB_KDC_REP message contains the following fields:
AS-REP ::= [APPLICATION 11] KDC-REP
TGS-REP ::= [APPLICATION 13] KDC-REP
KDC-REP ::= SEQUENCE {
pvno [0] INTEGER (5),
msg-type [1] INTEGER (11 -- AS -- | 13 -- TGS --),
padata [2] SEQUENCE OF PA-DATA OPTIONAL
-- NOTE: not empty --,
crealm [3] Realm,
cname [4] PrincipalName,
ticket [5] Ticket,
enc-part [6] EncryptedData
-- EncASRepPart or EncTGSRepPart,
-- as appropriate
}
EncASRepPart ::= [APPLICATION 25] EncKDCRepPart
EncTGSRepPart ::= [APPLICATION 26] EncKDCRepPart
EncKDCRepPart ::= SEQUENCE {
key [0] EncryptionKey,
last-req [1] LastReq,
nonce [2] UInt32,
key-expiration [3] KerberosTime OPTIONAL,
flags [4] TicketFlags,
authtime [5] KerberosTime,
starttime [6] KerberosTime OPTIONAL,
endtime [7] KerberosTime,
renew-till [8] KerberosTime OPTIONAL,
srealm [9] Realm,
sname [10] PrincipalName,
caddr [11] HostAddresses OPTIONAL
}
LastReq ::= SEQUENCE OF SEQUENCE {
lr-type [0] Int32,
lr-value [1] KerberosTime
}
pvno and msg-type ๐งพ These fields are described above in Section 5.4.1. msg-type is either KRB_AS_REP or KRB_TGS_REP.
padata ๐ธ This field is described in detail in Section 5.4.1. one possible use for it is encoding an alternate "salt" string to be used with a string-to-key algorithm. this is super useful for easing transitions if a realm name needs to change (like when a company gets acquired) ๐ข. in that case, all existing password-derived entries in the KDC database would be flagged as needing a special salt string until the next password change ๐.
crealm, cname, srealm, and sname ๐ These fields are the same as those described for the ticket in Section 5.3.
ticket ๐๏ธ The newly-issued ticket, from Section 5.3.
enc-part ๐ซถ This field is a placeholder for the ciphertext and related information that forms the encrypted part of a message. the description of the encrypted part of the message follows each appearance of this field.
the key usage value for encrypting this field is 3 in an AS-REP message, using the client's long-term key or another key selected via pre-authentication mechanisms. in a TGS-REP message, the key usage value is 8 if the TGS session key is used, or 9 if a TGS authenticator subkey is used ๐ฅ.
Compatibility note: some implementations unconditionally send an encrypted EncTGSRepPart (application tag number 26) in this field, regardless of whether the reply is an AS-REP or a TGS-REP. for compatibility's sake, implementors MAY relax the check on the tag number of the decrypted ENC-PART ๐.
key ๐๏ธ This field is the same as described for the ticket in Section 5.3.
last-req โฐ This field is returned by the KDC and specifies the time(s) of the last request by a principal. depending on what info is available, this might be the last time a request for a TGT was made, or the last time a request based on a TGT was successful. it also might cover all servers for a realm, or just the particular server. some implementations MAY display this information to the user to help spot unauthorized use of one's identity ๐. it's kinda like the last login time you see when logging in to timesharing systems ๐.
lr-type ๐ฆ This field indicates how the following lr-value field is to be interpreted. negative values mean the information pertains only to the responding server. non-negative values pertain to all servers for the realm ๐.
if the lr-type field is zero (0), then no information is conveyed by the lr-value subfield. if the absolute value of the lr-type field is one (1), then the lr-value subfield is the time of last initial request for a TGT. if it is two (2), then the lr-value subfield is the time of last initial request. if it is three (3), then the lr-value subfield is the time of issue for the newest TGT used. if it is four (4), then the lr-value subfield is the time of the last renewal. if it is five (5), then the lr-value subfield is the time of last request (of any type). if it is (6), then the lr-value subfield is the time when the password will expire. if it is (7), then the lr-value subfield is the time when the account will expire ๐ง.
lr-value ๐ฏ This field contains the time of the last request. the time MUST be interpreted according to the contents of the accompanying lr-type subfield ๐.
nonce ๐ฒ This field is described above in Section 5.4.1.
key-expiration ๐ฅ The key-expiration field is part of the response from the KDC and specifies the time that the client's secret key is due to expire. the expiration might be the result of password aging or an account expiration. if present, it SHOULD be set to the earlier of the user's key expiration and account expiration. the use of this field is deprecated, and the last-req field SHOULD be used to convey this information instead ๐. this field will usually be left out of the TGS reply, since the response to the TGS request is encrypted in a session key and no client information has to be retrieved from the KDC database ๐ โโ๏ธ. it's up to the application client (usually the login program) to take appropriate action, like notifying the user, if the expiration time is imminent โ ๏ธ.
flags, authtime, starttime, endtime, renew-till and caddr ๐ These fields are duplicates of those found in the encrypted portion of the attached ticket (see Section 5.3). they're provided so the client MAY verify that they match the intended request, and to help with proper ticket caching ๐ง . if the message is of type KRB_TGS_REP, the caddr field will only be filled in if the request was for a proxy or forwarded ticket, or if the user is substituting a subset of the addresses from the TGT. if the client-requested addresses are not present or not used, then the addresses contained in the ticket will be the same as those included in the TGT ๐ซง.
5.5. Client/Server (CS) Message Specifications ๐
this section specifies the format of the messages used for the authentication of the client to the application server ๐โจ.
5.5.1. KRB_AP_REQ Definition โจ
okay bestie, the KRB_AP_REQ message is where the client walks up to the server with its ticket and basically says "it's me ๐ ". It carries the Kerberos protocol version number, the message type KRB_AP_REQ, an options field for any options in use, and the ticket and authenticator themselves. People love calling this one the "authentication header" ๐
AP-REQ ::= [APPLICATION 14] SEQUENCE {
pvno [0] INTEGER (5),
msg-type [1] INTEGER (14),
ap-options [2] APOptions,
ticket [3] Ticket,
authenticator [4] EncryptedData -- Authenticator
}
APOptions ::= KerberosFlags
-- reserved(0),
-- use-session-key(1),
-- mutual-required(2)
pvno and msg-type ๐ธ These fields are the same ones we went over above in Section 5.4.1. msg-type is KRB_AP_REQ, so nothing fancy there.
ap-options ๐ฆ This field shows up in the application request (KRB_AP_REQ) and changes how the request gets processed. It's a bit-field, so a selected option is a bit set to 1, and anything unselected or reserved is reset to 0. The bit encoding lives in Section 5.2. Here's what each option means:
Bit(s) Name Description
0 reserved Reserved for future expansion of this field.
1 use-session-key The USE-SESSION-KEY option indicates that
the ticket the client is presenting to a
server is encrypted in the session key from
the server's TGT. When this option is not
specified, the ticket is encrypted in the
server's secret key.
2 mutual-required The MUTUAL-REQUIRED option tells the server
that the client requires mutual
authentication, and that it must respond
with a KRB_AP_REP message.
3-31 reserved Reserved for future use.
ticket ๐ This is the ticket that authenticates the client to the server. Main character energy โจ
authenticator ๐ This carries the encrypted authenticator, which includes the client's choice of a subkey.
The encrypted authenticator rides along in the AP-REQ and proves to the server that the sender recently knew the encryption key inside the ticket, which helps the server catch replays ๐ต๏ธโโ๏ธ It also helps pick out the "true session key" for that particular session. The DER encoding of the following gets encrypted with the ticket's session key, using a key usage value of 11 in normal application exchanges, or 7 when it's used as the PA-TGS-REQ PA-DATA field of a TGS-REQ exchange (see Section 5.4.1):
-- Unencrypted authenticator
Authenticator ::= [APPLICATION 2] SEQUENCE {
authenticator-vno [0] INTEGER (5),
crealm [1] Realm,
cname [2] PrincipalName,
cksum [3] Checksum OPTIONAL,
cusec [4] Microseconds,
ctime [5] KerberosTime,
subkey [6] EncryptionKey OPTIONAL,
seq-number [7] UInt32 OPTIONAL,
authorization-data [8] AuthorizationData OPTIONAL
}
Here's the rundown on each field inside the authenticator ๐
authenticator-vno ๐ This field says which version of the authenticator format is being used. This document specifies version 5.
crealm and cname ๐ง These are the same as what we described for the ticket in Section 5.3.
cksum ๐ This is a checksum of the application data that comes along with the KRB_AP_REQ. It's computed with a key usage value of 10 in normal application exchanges, or 6 when it's used in the TGS-REQ PA-TGS-REQ AP-DATA field.
cusec โญ This is the microsecond part of the client's timestamp. Before encryption, its value runs from 0 to 999999. It usually shows up alongside ctime, and the two of them together give you a reasonably accurate timestamp.
ctime ๐ธ This is the current time on the client's host.
subkey ๐ฆ This is the client's pick for an encryption key to protect this one specific application session. Unless an application says otherwise, if this field gets left out, the session key from the ticket is used instead.
seq-number ๐ This optional field holds the initial sequence number for KRB_PRIV or KRB_SAFE messages, for when sequence numbers are used to catch replays. (Application-specific messages can use it too.) When it's in the authenticator, it sets the initial sequence number for messages going from the client to the server. When it's in the AP-REP message, the initial sequence number is for messages going from the server to the client. In KRB_PRIV or KRB_SAFE messages, it goes up by one after each message gets sent. Sequence numbers run from 0 through 2^32 - 1, then wrap back to zero after 2^32 - 1.
For sequence numbers to catch replays properly, they SHOULD be non-repeating, even across connection boundaries. The initial sequence number SHOULD be random and spread evenly across the whole space of possible sequence numbers, so an attacker can't guess it and so it and the successive numbers don't end up repeating other sequences. If a series of KRB_PRIV or KRB_SAFE messages is going to produce more than 2^32 messages, rekeying SHOULD be performed before sequence numbers get reused with the same encryption key. ๐ญ
Implmentation note: Historically, some implementations send signed twos-complement numbers for sequence numbers. For compatibility's sake, implementations MAY accept the equivalent negative number where a positive number greater than 2^31 - 1 is expected. ๐
Implementation note: Like we said before, some implementations leave out the optional sequence number when its value would be zero. Implementations MAY accept an omitted sequence number when they expect a value of zero, and they SHOULD NOT transmit an Authenticator with an initial sequence number of zero. ๐
authorization-data ๐ This is the same as what Section 5.3 describes for the ticket. It's optional, and it only shows up when you want extra restrictions on using the ticket, on top of the ones already in the ticket itself.
5.5.2. KRB_AP_REP Definition โจ
The KRB_AP_REP message carries the Kerberos protocol version number, the message type, and an encrypted time-stamp. The server sends it back in response to a KRB_AP_REQ where the mutual authentication option was picked in the ap-options field. It's the server saying "yep, I'm legit too" ๐ซถ
AP-REP ::= [APPLICATION 15] SEQUENCE {
pvno [0] INTEGER (5),
msg-type [1] INTEGER (15),
enc-part [2] EncryptedData -- EncAPRepPart
}
EncAPRepPart ::= [APPLICATION 27] SEQUENCE {
ctime [0] KerberosTime,
cusec [1] Microseconds,
subkey [2] EncryptionKey OPTIONAL,
seq-number [3] UInt32 OPTIONAL
}
The encoded EncAPRepPart gets encrypted with the shared session key from the ticket. The optional subkey field can be used in an application-arranged negotiation to pick a per-association session key ๐ฅ
pvno and msg-type ๐ธ These are described above in Section 5.4.1. msg-type is KRB_AP_REP.
enc-part ๐ฆ This is described above in Section 5.4.2. It's computed with a key usage value of 12.
ctime ๐ This is the current time on the client's host.
cusec โญ This is the microsecond part of the client's timestamp.
subkey ๐ This is an encryption key that's going to protect this specific application session. For how this field is used to negotiate a key, check out Section 3.2.6. Unless an application says otherwise, if this field gets left out, the sub-session key from the authenticator gets used. And if that's also left out, the session key from the ticket takes over ๐
seq-number ๐ This field is described above in Section 5.3.2.
5.5.3. Error Message Reply โจ
If something goes wrong while the server is processing the application request, a KRB_ERROR message gets sent back instead. The format of that error message is in Section 5.9.1 ๐ โโ๏ธ The cname and crealm fields MAY be left out if the server can't figure out their right values from the corresponding KRB_AP_REQ message. And if the authenticator was decipherable, the ctime and cusec fields will hold the values from it ๐ง
5.6. KRB_SAFE Message Specification ๐
okay so this section is all about the KRB_SAFE message, which either side of an application (client or server) can use to send a tamper-proof message to its peer ๐ It assumes a session key has already been swapped, for example through the KRB_AP_REQ/KRB_AP_REP messages. Rule one: no session key, no KRB_SAFE, periodt ๐
5.6.1. KRB_SAFE definition โจ
okay so the KRB_SAFE message is giving "tamper-proof but not secret" ๐ It carries the user data plus a collision-proof checksum, keyed with the last encryption key negotiated via subkeys, or with the session key if no negotiation happened. ๐
KRB-SAFE ::= [APPLICATION 20] SEQUENCE {
pvno [0] INTEGER (5),
msg-type [1] INTEGER (20),
safe-body [2] KRB-SAFE-BODY,
cksum [3] Checksum
}
KRB-SAFE-BODY ::= SEQUENCE {
user-data [0] OCTET STRING,
timestamp [1] KerberosTime OPTIONAL,
usec [2] Microseconds OPTIONAL,
seq-number [3] UInt32 OPTIONAL,
s-address [4] HostAddress,
r-address [5] HostAddress OPTIONAL
}
pvno and msg-type ๐ These fields are described above in Section 5.4.1. msg-type is KRB_SAFE.
safe-body ๐ This is a placeholder for the body of the KRB-SAFE message.
cksum ๐ This field holds the checksum of the application data, computed with a key usage value of 15.
The checksum is computed over the encoding of the KRB-SAFE sequence. First, the cksum is set to a type zero, zero-length value, and the checksum is computed over the encoding of the KRB-SAFE sequence. Then the checksum is set to the result of that computation. Finally, the KRB-SAFE sequence is encoded again. This method, although different than the one specified in RFC 1510, corresponds to existing practice. ๐ง โจ
user-data ๐ This field is part of the KRB_SAFE and KRB_PRIV messages, and holds the application-specific data being passed from the sender to the recipient.
timestamp โฐ This field is part of the KRB_SAFE and KRB_PRIV messages. Its contents are the current time as known by the sender of the message. By checking the timestamp, the recipient can make sure the message was recently generated and is not a replay. no replays allowed bestie ๐ โโ๏ธ
usec โฑ๏ธ This field is part of the KRB_SAFE and KRB_PRIV headers. It holds the microsecond part of the timestamp.
seq-number ๐ข This field is described above in Section 5.3.2.
s-address ๐ค Sender's address.
This field specifies the address in use by the sender of the message.
r-address ๐ฅ This field specifies the address in use by the recipient of the message. It MAY be omitted for some uses (such as broadcast protocols), but the recipient MAY arbitrarily reject such messages. This field, along with s-address, can be used to help detect messages that have been incorrectly or maliciously delivered to the wrong recipient. this pair is literally the bouncer at the door ๐ฆ
5.7. KRB_PRIV Message Specification ๐ธ
This section specifies the format of a message that either side (client or server) of an application can use to send a message to its peer securely and privately. ๐คซ It presumes that a session key has previously been exchanged, for example by using the KRB_AP_REQ/KRB_AP_REP messages.
5.7.1. KRB_PRIV Definition
The KRB_PRIV message contains user data encrypted in the Session Key. ๐๐ The message fields are as follows:
KRB-PRIV ::= [APPLICATION 21] SEQUENCE {
pvno [0] INTEGER (5),
msg-type [1] INTEGER (21),
-- NOTE: there is no [2] tag
enc-part [3] EncryptedData -- EncKrbPrivPart
}
EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE {
user-data [0] OCTET STRING,
timestamp [1] KerberosTime OPTIONAL,
usec [2] Microseconds OPTIONAL,
seq-number [3] UInt32 OPTIONAL,
s-address [4] HostAddress -- sender's addr --,
r-address [5] HostAddress OPTIONAL -- recip's addr
}
pvno and msg-type ๐ These fields are described above in Section 5.4.1. msg-type is KRB_PRIV.
enc-part ๐ซถ This field holds an encoding of the EncKrbPrivPart sequence, encrypted under the session key with a key usage value of 13. This encrypted encoding is used for the enc-part field of the KRB-PRIV message.
user-data, timestamp, usec, s-address, and r-address ๐ These fields are described above in Section 5.6.1.
seq-number ๐ข This field is described above in Section 5.3.2.
5.8. KRB_CRED Message Specification ๐ง
This section specifies the format of a message that can be used to send Kerberos credentials from one principal to another. ๐ช It's presented here to encourage a common mechanism that applications can use when forwarding tickets or providing proxies to subordinate servers. It presumes that a session key has already been exchanged, perhaps by using the KRB_AP_REQ/KRB_AP_REP messages.
5.8.1. KRB_CRED Definition
The KRB_CRED message contains a sequence of tickets to be sent, plus the information needed to use them, including the session key from each. โจ That information is encrypted under an encryption key that was previously exchanged or transferred alongside the KRB_CRED message. The message fields are as follows:
KRB-CRED ::= [APPLICATION 22] SEQUENCE {
pvno [0] INTEGER (5),
msg-type [1] INTEGER (22),
tickets [2] SEQUENCE OF Ticket,
enc-part [3] EncryptedData -- EncKrbCredPart
}
EncKrbCredPart ::= [APPLICATION 29] SEQUENCE {
ticket-info [0] SEQUENCE OF KrbCredInfo,
nonce [1] UInt32 OPTIONAL,
timestamp [2] KerberosTime OPTIONAL,
usec [3] Microseconds OPTIONAL,
s-address [4] HostAddress OPTIONAL,
r-address [5] HostAddress OPTIONAL
}
KrbCredInfo ::= SEQUENCE {
key [0] EncryptionKey,
prealm [1] Realm OPTIONAL,
pname [2] PrincipalName OPTIONAL,
flags [3] TicketFlags OPTIONAL,
authtime [4] KerberosTime OPTIONAL,
starttime [5] KerberosTime OPTIONAL,
endtime [6] KerberosTime OPTIONAL,
renew-till [7] KerberosTime OPTIONAL,
srealm [8] Realm OPTIONAL,
sname [9] PrincipalName OPTIONAL,
caddr [10] HostAddresses OPTIONAL
}
pvno and msg-type ๐ These fields are described above in Section 5.4.1. msg-type is KRB_CRED.
tickets ๐๏ธ These are the tickets obtained from the KDC specifically for use by the intended recipient. Successive tickets are paired with the corresponding KrbCredInfo sequence from the enc-part of the KRB-CRED message.
enc-part ๐ This field holds an encoding of the EncKrbCredPart sequence, encrypted under the session key shared by the sender and the intended recipient, with a key usage value of 14. This encrypted encoding is used for the enc-part field of the KRB-CRED message.
Implementation note: Implementations of certain applications, most notably certain implementations of the Kerberos GSS-API mechanism, do not separately encrypt the contents of the EncKrbCredPart of the KRB-CRED message when sending it. In the case of those GSS-API mechanisms, this is not a security vulnerability, as the entire KRB-CRED message is itself embedded in an encrypted message. phew, layers of encryption ๐
nonce ๐ฒ If practical, an application MAY require the inclusion of a nonce generated by the recipient of the message. If the same value is included as the nonce in the message, it provides evidence that the message is fresh and has not been replayed by an attacker. A nonce MUST NEVER be reused. ๐ซ nonces are one-and-done, no exceptions, periodt
timestamp and usec โฐ These fields specify the time that the KRB-CRED message was generated. The time is used to provide assurance that the message is fresh.
s-address and r-address ๐ These fields are described above in Section 5.6.1. They are used optionally to provide additional assurance of the integrity of the KRB-CRED message.
key ๐๏ธ This field exists in the corresponding ticket passed by the KRB-CRED message, and it's used to pass the session key from the sender to the intended recipient. The field's encoding is described in Section 5.2.9.
The following fields are optional. If present, they can be associated with the credentials in the remote ticket file. If left out, it is assumed that the recipient of the credentials already knows their values. ๐ซง
prealm and pname ๐ The name and realm of the delegated principal identity.
flags, authtime, starttime, endtime, renew-till, srealm, sname, and caddr ๐ These fields contain the values of the corresponding fields from the ticket found in the ticket field. Descriptions of the fields are identical to the descriptions in the KDC-REP message.
5.9. Error Message Specification ๐
This section specifies the format for the KRB_ERROR message. The fields in the message are meant to return as much information as possible about an error. ๐งพ It's not expected that all the information the fields require will be available for every type of error. If the appropriate information isn't available when the message is composed, the corresponding field is left out of the message.
Heads up: because the KRB_ERROR message is not integrity protected, it's quite possible for an intruder to synthesize or modify it. ๐ฑ That means the client SHOULD NOT use any fields in this message for security-critical purposes, such as setting a system clock or generating a fresh authenticator. The message can still be useful for advising a user on the reason for some failure. ๐
5.9.1. KRB_ERROR Definition
Okay so the KRB_ERROR message is made of these fields, bestie ๐
KRB-ERROR ::= [APPLICATION 30] SEQUENCE {
pvno [0] INTEGER (5),
msg-type [1] INTEGER (30),
ctime [2] KerberosTime OPTIONAL,
cusec [3] Microseconds OPTIONAL,
stime [4] KerberosTime,
susec [5] Microseconds,
error-code [6] Int32,
crealm [7] Realm OPTIONAL,
cname [8] PrincipalName OPTIONAL,
realm [9] Realm -- service realm --,
sname [10] PrincipalName -- service name --,
e-text [11] KerberosString OPTIONAL,
e-data [12] OCTET STRING OPTIONAL
}
pvno and msg-type ๐ These fields were already explained up in Section 5.4.1. msg-type is KRB_ERROR, so you know exactly what kind of message this is ๐ฆ
ctime and cusec โฐ These were covered above in Section 5.5.2. If the entity making the error already knows these values (like when it's replying to a failed authentication service request, for example), they should be filled in on the KRB-ERROR. If the values aren't available, these fields can just be left out. No drama โจ
stime ๐ฐ๏ธ This is the current time on the server, and it's of type KerberosTime.
susec ๐ฌ This is the microsecond part of the server's timestamp. It goes from 0 to 999999. It shows up right alongside stime, and the two work together to give you a reasonably accurate timestamp. Teamwork makes the dream work ๐ซถ
error-code ๐จ This holds the error code that Kerberos or the server returns when a request fails. To figure out what the number means, check the list of error codes in Section 7.5.9. Implementations are encouraged to support national language support when they display error messages, so people can read them in their own language ๐
crealm, and cname ๐ These were described above in Section 5.3. When the entity making the error knows these values, they should be filled in on the KRB-ERROR. If they aren't known, the crealm and cname fields SHOULD be omitted.
realm and sname ๐ธ Same deal as before, these are described above in Section 5.3.
e-text ๐ This is extra text that helps explain the error code for the failed request. For example, it might include a principal name that turned out to be unknown. Context is everything, periodt ๐
e-data ๐ง This is extra data about the error that the application can use to recover from it or handle it. If the errorcode is KDC_ERR_PREAUTH_REQUIRED, then the e-data field will hold an encoding of a sequence of padata fields. Each one matches an acceptable pre-authentication method and can optionally carry data for that method:
METHOD-DATA ::= SEQUENCE OF PA-DATA
For error codes defined in this document other than KDC_ERR_PREAUTH_REQUIRED, the format and contents of the e-data field are implementation-defined. Same goes for future error codes: their e-data format and contents are implementation-defined unless something says otherwise. Whether it's defined by the implementation or by a future document, the e-data field MAY take the form of TYPED-DATA:
TYPED-DATA ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
data-type [0] Int32,
data-value [1] OCTET STRING OPTIONAL
}
5.10. Application Tag Numbers
Okay here's the tea on the application class tag numbers, which are used by the various data types we've covered in this section ๐ The table below lists them all:
Tag Number(s) Type Name Comments
0 unused
1 Ticket PDU
2 Authenticator non-PDU
3 EncTicketPart non-PDU
4-9 unused
10 AS-REQ PDU
11 AS-REP PDU
12 TGS-REQ PDU
13 TGS-REP PDU
14 AP-REQ PDU
15 AP-REP PDU
16 RESERVED16 TGT-REQ (for user-to-user)
17 RESERVED17 TGT-REP (for user-to-user)
18-19 unused
20 KRB-SAFE PDU
21 KRB-PRIV PDU
22 KRB-CRED PDU
23-24 unused
25 EncASRepPart non-PDU
26 EncTGSRepPart non-PDU
27 EncApRepPart non-PDU
28 EncKrbPrivPart non-PDU
29 EncKrbCredPart non-PDU
30 KRB-ERROR PDU
The ASN.1 types marked above as "PDU" (Protocol Data Unit) are the only ASN.1 types intended as top-level types of the Kerberos protocol. They're also the only types that may be used as elements in another protocol that makes use of Kerberos. So PDUs are the main characters, and everything else is a supporting cast ๐๐ฆ
6. Naming Constraints โจ
6.1. Realm Names
Realm names are encoded as GeneralStrings, and technically a realm can pick whatever name it wants ๐ BUT interoperability across realm boundaries needs everyone to agree on how realm names get assigned and what info they imply. Otherwise it's chaos ๐
To keep those conventions enforced, each realm MUST conform to the conventions itself. It MUST also require that any realms it shares inter-realm keys with also conform to the conventions, and require the same from its neighbors. Accountability vibes ๐ซถ
Kerberos realm names are case sensitive. Realm names that differ only in the case of their characters are not equivalent, so ATHENA.MIT.EDU and athena.mit.edu are not the same realm, bestie ๐ญ Right now there are three styles of realm names: domain, X500, and other. Here are examples of each:
domain: ATHENA.MIT.EDU
X500: C=US/O=OSF
other: NAMETYPE:rest/of.name=without-restrictions
Domain style ๐ Domain style realm names MUST look like domain names. They consist of components separated by periods (.), and they contain neither colons (:) nor slashes (/). Domain names themselves are case insensitive, but for realms to match, the case has to match too. When you're making a new realm name based on an internet domain name, it is recommended by convention that the characters be converted to uppercase.
X.500 style ๐ธ X.500 names contain an equals sign (=) and cannot contain a colon (:) before the equals sign. The realm names for X.500 names are string representations of the names, with components separated by slashes. Leading and trailing slashes are not included. Note that the slash separator matches Kerberos implementations based on RFC 1510, but it's different from the separator recommended in RFC 2253. Plot twist ๐ญ
Other style ๐ง Names that fall into the other category MUST begin with a prefix that contains no equals sign (=) or period (.). That prefix MUST be followed by a colon (:) and then the rest of the name. All prefixes except those beginning with used are expected. Presently none are assigned.
Reserved ๐ The reserved category includes strings that don't fall into the first three categories. Every name in this category is reserved. It's unlikely that names will get assigned to this category unless there's a very strong argument for not using the 'other' category.
These rules guarantee there won't be any conflicts between the various name styles, which is honestly so iconic ๐
The following additional constraints apply to assigning realm names in the domain and X.500 categories. Either the name of a realm for the domain or X.500 formats must be used by the organization that owns (the one it was assigned to) an Internet domain name or X.500 name. Or, if no such names are registered, authority to use a realm name MAY be derived from the authority of the parent realm. For example, if there's no domain name for E40.MIT.EDU, then the administrator of the MIT.EDU realm can authorize the creation of a realm with that name ๐ฆ
This works because the organization the parent is assigned to is presumably the organization authorized to assign names to its children in the X.500 and domain name systems too. If the parent assigns a realm name without also registering it in the domain name or X.500 hierarchy, then it's the parent's responsibility to make sure that in the future there won't exist a name identical to the child's realm name unless it's assigned to the same entity as the realm name. Responsibility is giving main character energy ๐ โจ
6.2. Principal Names โจ
Okay so realm names had their rules, and principal names need the same kind of agreement ๐ Everybody has to be on the same page about what a principal name is actually saying. The name-type field is the bit that tells you what kind of info the name is carrying ๐ Honestly it's a hint. The name-type SHOULD be treated only as a hint to interpreting the meaning of a name, and it doesn't count when you're checking if two names are equivalent ๐ฆ Two principal names that only differ in name-type are the same principal, no cap. The name type doesn't split up the namespace into separate little rooms ๐ธ Ignore the name type and no two names can be the same, so at least one of the components, or the realm, MUST be different. Here are the name types that are defined:
Name Type Value Meaning
NT-UNKNOWN 0 Name type not known
NT-PRINCIPAL 1 Just the name of the principal as in DCE,
or for users
NT-SRV-INST 2 Service and other unique instance (krbtgt)
NT-SRV-HST 3 Service with host name as instance
(telnet, rcommands)
NT-SRV-XHST 4 Service with host as remaining components
NT-UID 5 Unique ID
NT-X500-PRINCIPAL 6 Encoded X.509 Distinguished name [RFC2253]
NT-SMTP-NAME 7 Name in form of SMTP email name
(e.g., user@example.com)
NT-ENTERPRISE 10 Enterprise name - may be mapped to principal
name
When a name only tells you that it's unique at one particular time and nothing else, the name type PRINCIPAL SHOULD be used ๐ The principal name type SHOULD be used for users, and it might also show up for a unique server. If the name is a unique machine-generated ID that's guaranteed never to get reassigned, then UID SHOULD be used ๐ง (Note that reassigning names of any type is generally a bad idea, since stale entries might stick around in access control lists ๐)
If the first component of a name identifies a service, and the remaining components identify an instance of that service in a server-specified way, then SRV-INST SHOULD be used ๐ The Kerberos ticket-granting service is a good example of this. Its first component is krbtgt, and its second component says which realm the ticket is valid for.
If the first component is a service and there's a single component after it that names the host the server runs on, then SRV-HST SHOULD be used ๐ This one is mostly for Internet services like telnet and the Berkeley R commands. If the separate parts of the host name show up as successive components after the service name, then SRV-XHST SHOULD be used โจ This might be used to identify servers on hosts with X.500 names, where the slash (/) could otherwise be ambiguous.
A name type of NT-X500-PRINCIPAL SHOULD be used when a name from an X.509 certificate gets translated into a Kerberos name ๐ฆ The encoding of the X.509 name as a Kerberos principal shall conform to the encoding rules specified in RFC 2253.
The SMTP name type lets a name look like an SMTP email name ๐ That name, including an "@" and a domain name, gets used as the one component of the principal name.
A name type of UNKNOWN SHOULD be used when the form of the name isn't known ๐ซถ When you're comparing names, a name of type UNKNOWN will match principals authenticated with names of any type. A principal authenticated with a name of type UNKNOWN, though, will only match other names of type UNKNOWN. Main character energy of "I'm not sure what I am," but it's still valid ๐
Names of any type with an initial component of 'krbtgt' are reserved for the Kerberos ticket-granting service ๐ฅ See Section 7.3 for the form of such names.
6.2.1. Name of Server Principals ๐
The principal identifier for a server on a host is usually made of two parts ๐ First, the realm of the KDC the server is registered with. Second, a two-component name of type NT-SRV-HST, if the host name is an Internet domain name, or a multi-component name of type NT-SRV-XHST, if the host name is in a form (like X.500) that allows slash (/) separators. The first component of that two- or multi-component name identifies the service, and the later components identify the host ๐ธ When the host name isn't case sensitive (like Internet domain names), the host name MUST be lowercase ๐ If the application protocol says so for services like telnet and the Berkeley R commands that run with system privileges, the first component MAY be the string 'host' instead of a service-specific identifier โจ
7. Constants and Other Defined Values ๐
7.1. Host Address Types ๐ฆ
Negative values for the host address type are all reserved for local use. Non-negative values are all reserved for officially assigned type fields and interpretations ๐
Internet (IPv4) Addresses
IPv4 addresses are 32-bit (4-octet) quantities, encoded in MSB order (most significant byte first) ๐ The IPv4 loopback address SHOULD NOT appear in a Kerberos PDU. The type of IPv4 addresses is two (2) ๐ง
Internet (IPv6) Addresses
IPv6 addresses [RFC3513] are 128-bit (16-octet) quantities, encoded in MSB order (most significant byte first) ๐ The following addresses MUST NOT appear in any Kerberos PDU:
- the Unspecified Address
- the Loopback Address
- Link-Local addresses
This restriction covers the address fields of Kerberos PDUs, but not the address fields of packets that might carry those PDUs ๐ It's needed because an address with non-global scope could let a message get accepted from a node that happens to share that address, even though it isn't the host the entity that added the restriction had in mind. Kinda dangerous, honestly ๐ญ If the link-local address type does need to be used for communication, then the address restriction in tickets must not be used (i.e., addressless tickets must be used) ๐ซถ
IPv4-mapped IPv6 addresses MUST be represented as addresses of type 2 ๐ฅ
DECnet Phase IV Addresses
DECnet Phase IV addresses are 16-bit addresses, encoded in LSB order. The type of DECnet Phase IV addresses is twelve (12) ๐
Netbios Addresses
Netbios addresses are 16-octet addresses that are typically made of 1 to 15 alphanumeric characters, padded with the US-ASCII SPC character (code 32) ๐ธ The 16th octet MUST be the US-ASCII NUL character (code 0). The type of Netbios addresses is twenty (20) ๐
Directional Addresses
Including the sender address in KRB_SAFE and KRB_PRIV messages is kinda annoying in lots of environments, because addresses can get changed in transport by network address translators ๐ฉ But if you take those addresses out, the messages might be open to a reflection attack, where a message gets reflected back to whoever originated it ๐ The directional address type is the way to dodge both transport addresses and reflection attacks ๐ฆ Directional addresses are encoded as four-byte unsigned integers in network byte order. If the message is originated by the party that sent the original KRB_AP_REQ message, then an address of 0 SHOULD be used. If the message is originated by the party that KRB_AP_REQ was sent to, then the address 1 SHOULD be used. Applications with multiple parties can specify other addresses ๐ง
Directional addresses MUST only be used for the sender address field in the KRB_SAFE or KRB_PRIV messages. They MUST NOT be used as a ticket address or in a KRB_AP_REQ message ๐ โโ๏ธ This address type SHOULD only be used when the sending party knows that the receiving party supports it. That generally means directional addresses should only show up when the application protocol requires their support ๐ Directional addresses are type (3) โจ
7.2. KDC Messaging: IP Transports ๐
Kerberos has two IP transport mechanisms for communication between clients and servers: UDP/IP and TCP/IP ๐
7.2.1. UDP/IP transport ๐
Kerberos servers (KDCs) that support IP transports MUST accept UDP requests. They SHOULD listen for them on port 88 (decimal), unless they're specifically configured to listen on an alternative UDP port ๐ซถ Alternate ports MAY be used when you're running multiple KDCs for multiple realms on the same host ๐
Kerberos clients that support IP transports SHOULD support sending UDP requests ๐ฆ Clients SHOULD use KDC discovery [7.2.3] to identify the IP address and port they'll send their request to ๐ฅ
When contacting a KDC for a KRB_KDC_REQ request using UDP/IP transport, the client shall send a UDP datagram containing only an encoding of the request to the KDC ๐ธ The KDC will respond with a reply datagram containing only an encoding of the reply message (either a KRB_ERROR or a KRB_KDC_REP) to the sending port at the sender's IP address. The response to a request made through UDP/IP transport MUST also use UDP/IP transport ๐ If the response can't be handled using UDP (for example, because it's too large), the KDC MUST return KRB_ERR_RESPONSE_TOO_BIG, which forces the client to retry the request using the TCP transport ๐ญโจ
7.2.2. TCP/IP Transport โจ
okay so KDCs that support IP transports MUST accept TCP requests ๐ and SHOULD listen for them on port 88 (decimal), unless they've been specifically configured to use an alternate TCP port. alternate ports MAY be used when you're running multiple KDCs for multiple realms on the same host ๐ง
Clients MUST support sending TCP requests ๐ซถ, but they MAY choose to try a request first over the UDP transport. Clients SHOULD use KDC discovery [7.2.3] to figure out the IP address and port they'll send their request to ๐ฆ
ngl this implementation note is a whole vibe ๐: some extensions to the Kerberos protocol just won't succeed if any client or KDC that doesn't support the TCP transport is involved. implementations of RFC 1510 weren't required to support TCP/IP transports at all ๐
When the KRB_KDC_REQ message is sent to the KDC over a TCP stream, the response (KRB_KDC_REP or KRB-ERROR message) MUST be returned to the client on the same TCP stream that was established for the request ๐. the KDC MAY close the TCP stream after sending a response, but it MAY also leave the stream open for a reasonable period of time if it expects a follow-up. the KDC has to manage its TCP/IP connections carefully so nobody can pull a denial of service attack based on how many open TCP/IP connections there are ๐ญ
The client MUST be prepared to have the stream closed by the KDC at any time after receiving a response ๐ . a stream closure SHOULD NOT be treated as a fatal error. instead, if multiple exchanges are required (like certain forms of pre-authentication), the client may need to set up a new connection when it's ready to send the next messages. a client MAY close the stream after receiving a response, and SHOULD close it if it doesn't expect to send follow-up messages ๐
A client MAY send multiple requests before receiving responses ๐, though it must be ready to handle the connection being closed after the first response.
Each request (KRB_KDC_REQ) and response (KRB_KDC_REP or KRB-ERROR) sent over the TCP stream is preceded by the length of the request as 4 octets in network byte order. the high bit of the length is reserved for future expansion and MUST currently be set to zero. if a KDC that doesn't understand how to interpret a set high bit in the length encoding receives a request with the high order bit of the length set, it MUST return a KRB-ERROR message with the error KRB_ERR_FIELD_TOOLONG and MUST close the TCP stream. ๐ญ that's a lot of MUSTs, babe
If multiple requests are sent over a single TCP connection and the KDC sends multiple responses, the KDC is not required to send the responses in the order of the corresponding requests. this can let some implementations send each response as soon as it's ready ๐ฅ, even if earlier requests are still being processed (like waiting on an external device or database). iconic, honestly ๐ฆ
7.2.3. KDC Discovery on IP Networks
Kerberos client implementations MUST provide a means for the client to determine the location of the Kerberos Key Distribution Centers (KDCs). traditionally, implementations stored this configuration info in a file on each client machine ๐, but experience showed that method causes problems with out-of-date information and scaling, especially with cross-realm authentication ๐ฉ. this section describes a method for using the Domain Name System [RFC1035] to store KDC location information ๐
7.2.3.1. DNS vs. Kerberos: Case Sensitivity of Realm Names
In Kerberos, realm names are case sensitive ๐. it's strongly encouraged that all realm names be all uppercase, but not every site got the memo. some use all lowercase names and others use mixed case. DNS, on the other hand, is case insensitive for queries. the realm names MYREALM, myrealm, and MyRealm are all different, but they resolve the same in the domain name system, so it's necessary that only one of the possible combinations of upper- and lowercase characters be used in realm names ๐
7.2.3.2. Specifying KDC Location Information with DNS SRV records
KDC location information is to be stored using the DNS SRV RR [RFC2782]. the format of this RR is as follows:
_Service._Proto.Realm TTL Class SRV Priority Weight Port Target
The Service name for Kerberos is always "kerberos".
The Proto can be either "udp" or "tcp". If these SRV records are to be used, both "udp" and "tcp" records MUST be specified for all KDC deployments ๐
The Realm is the Kerberos realm that this record corresponds to. The realm MUST be a domain-style realm name โจ
TTL, Class, SRV, Priority, Weight, and Target have the standard meaning as defined in RFC 2782.
As per RFC 2782, the Port number used for "_udp" and "_tcp" SRV records SHOULD be the value assigned to "kerberos" by the Internet Assigned Number Authority: 88 (decimal), unless the KDC is configured to listen on an alternate TCP port ๐ฆ
Implementation note: many existing client implementations don't support KDC Discovery and are configured to send requests to the IANA assigned port (88 decimal), so it is strongly recommended that KDCs be configured to listen on that port ๐ซถ
7.2.3.3. KDC Discovery for Domain Style Realm Names on IP Networks
These are DNS records for a Kerberos realm EXAMPLE.COM ๐ง It has two Kerberos servers, kdc1.example.com and kdc2.example.com. Queries should be directed to kdc1.example.com first, as per the specified priority. Weights are not used in these sample records.
_kerberos._udp.EXAMPLE.COM. IN SRV 0 0 88 kdc1.example.com.
_kerberos._udp.EXAMPLE.COM. IN SRV 1 0 88 kdc2.example.com.
_kerberos._tcp.EXAMPLE.COM. IN SRV 0 0 88 kdc1.example.com.
_kerberos._tcp.EXAMPLE.COM. IN SRV 1 0 88 kdc2.example.com.
7.3. Name of the TGS ๐
The principal identifier of the ticket-granting service shall be composed of three parts: the realm of the KDC issuing the TGS ticket, and a two-part name of type NT-SRV-INST, with the first part "krbtgt" and the second part the name of the realm that will accept the TGT. For example, a TGT issued by the ATHENA.MIT.EDU realm to be used to get tickets from the ATHENA.MIT.EDU KDC has a principal identifier of "ATHENA.MIT.EDU" (realm), ("krbtgt", "ATHENA.MIT.EDU") (name). A TGT issued by the ATHENA.MIT.EDU realm to be used to get tickets from the MIT.EDU realm has a principal identifier of "ATHENA.MIT.EDU" (realm), ("krbtgt", "MIT.EDU") (name) ๐
7.4. OID Arc for KerberosV5 ๐
This OID MAY be used to identify Kerberos protocol messages encapsulated in other protocols. It also designates the OID arc for KerberosV5-related OIDs assigned by future IETF action.
Implementation note: RFC 1510 had an incorrect value (5) for "dod" in its OID ๐
id-krb5 OBJECT IDENTIFIER ::= {
iso(1) identified-organization(3) dod(6) internet(1)
security(5) kerberosV5(2)
}
Assignment of OIDs beneath the id-krb5 arc must be obtained by contacting the registrar for the id-krb5 arc, or its designee. At the time of the issuance of this RFC, such registrations can be obtained by contacting krb5-oid-registrar@mit.edu ๐
7.5. Protocol Constants and Associated Values ๐ฅ
The following tables list constants used in the protocol and define their meanings. In the "specification" section, ranges are specified that limit the values of constants for which values are defined here. This allows implementations to make assumptions about the maximum values that will be received for these constants. Implementations receiving values outside the range specified in the "specification" section MAY reject the request, but they MUST recover cleanly. ๐ซถ
7.5.1. Key Usage Numbers ๐
The encryption and checksum specifications in [RFC3961] require as input a "key usage number", to alter the encryption key used in any specific message in order to make certain types of cryptographic attack more difficult. These are the key usage values assigned in this document ๐
1. AS-REQ PA-ENC-TIMESTAMP padata timestamp, encrypted with
the client key (Section 5.2.7.2)
2. AS-REP Ticket and TGS-REP Ticket (includes TGS session
key or application session key), encrypted with the
service key (Section 5.3)
3. AS-REP encrypted part (includes TGS session key or
application session key), encrypted with the client key
(Section 5.4.2)
4. TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with
the TGS session key (Section 5.4.1)
5. TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with
the TGS authenticator subkey (Section 5.4.1)
6. TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator cksum,
keyed with the TGS session key (Section 5.5.1)
7. TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator (includes
TGS authenticator subkey), encrypted with the TGS session
key (Section 5.5.1)
8. TGS-REP encrypted part (includes application session
key), encrypted with the TGS session key (Section 5.4.2)
9. TGS-REP encrypted part (includes application session
key), encrypted with the TGS authenticator subkey
(Section 5.4.2)
10. AP-REQ Authenticator cksum, keyed with the application
session key (Section 5.5.1)
11. AP-REQ Authenticator (includes application authenticator
subkey), encrypted with the application session key
(Section 5.5.1)
12. AP-REP encrypted part (includes application session
subkey), encrypted with the application session key
(Section 5.5.2)
13. KRB-PRIV encrypted part, encrypted with a key chosen by
the application (Section 5.7.1)
14. KRB-CRED encrypted part, encrypted with a key chosen by
the application (Section 5.8.1)
15. KRB-SAFE cksum, keyed with a key chosen by the
application (Section 5.6.1)
16-18. Reserved for future use in Kerberos and related
protocols.
19. AD-KDC-ISSUED checksum (ad-checksum in 5.2.6.4)
20-21. Reserved for future use in Kerberos and related
protocols.
22-25. Reserved for use in the Kerberos Version 5 GSS-API
mechanisms [RFC4121].
26-511. Reserved for future use in Kerberos and related
protocols.
512-1023. Reserved for uses internal to a Kerberos implementation.
1024. Encryption for application use in protocols that do not
specify key usage values
1025. Checksums for application use in protocols that do not
specify key usage values
1026-2047. Reserved for application use.
7.5.2. PreAuthentication Data Types โจ
okay bestie, this is the padata menu ๐ every preauth data type gets its own number and a little label, and some of them come with notes like "deprecated" or who-wrote-it credits. no cap, the credits are so iconic ๐
Padata and Data Type Padata-type Comment
Value
PA-TGS-REQ 1
PA-ENC-TIMESTAMP 2
PA-PW-SALT 3
[reserved] 4
PA-ENC-UNIX-TIME 5 (deprecated)
PA-SANDIA-SECUREID 6
PA-SESAME 7
PA-OSF-DCE 8
PA-CYBERSAFE-SECUREID 9
PA-AFS3-SALT 10
PA-ETYPE-INFO 11
PA-SAM-CHALLENGE 12 (sam/otp)
PA-SAM-RESPONSE 13 (sam/otp)
PA-PK-AS-REQ_OLD 14 (pkinit)
PA-PK-AS-REP_OLD 15 (pkinit)
PA-PK-AS-REQ 16 (pkinit)
PA-PK-AS-REP 17 (pkinit)
PA-ETYPE-INFO2 19 (replaces pa-etype-info)
PA-USE-SPECIFIED-KVNO 20
PA-SAM-REDIRECT 21 (sam/otp)
PA-GET-FROM-TYPED-DATA 22 (embedded in typed data)
TD-PADATA 22 (embeds padata)
PA-SAM-ETYPE-INFO 23 (sam/otp)
PA-ALT-PRINC 24 (crawdad@fnal.gov)
PA-SAM-CHALLENGE2 30 (kenh@pobox.com)
PA-SAM-RESPONSE2 31 (kenh@pobox.com)
PA-EXTRA-TGT 41 Reserved extra TGT
TD-PKINIT-CMS-CERTIFICATES 101 CertificateSet from CMS
TD-KRB-PRINCIPAL 102 PrincipalName
TD-KRB-REALM 103 Realm
TD-TRUSTED-CERTIFIERS 104 from PKINIT
TD-CERTIFICATE-INDEX 105 from PKINIT
TD-APP-DEFINED-ERROR 106 application specific
TD-REQ-NONCE 107 INTEGER
TD-REQ-SEQ 108 INTEGER
PA-PAC-REQUEST 128 (jbrezak@exchange.microsoft.com)
7.5.3. Address Types ๐ธ
the address type list is a lil roll call of network families, from IPv4 all the way to IPv6 ๐ฆ the numbers are the whole point here, so don't you dare fudge them ๐ซถ
Address Type Value
IPv4 2
Directional 3
ChaosNet 5
XNS 6
ISO 7
DECNET Phase IV 12
AppleTalk DDP 16
NetBios 20
IPv6 24
7.5.4. Authorization Data Types ๐ฅ
this one is giving full authorization drama ๐ there's a numbered run of AD types, then a reserved range, then a few vendor-flavored ones with their credits. the reserved range is literally just "9-63" so yes, that's the whole vibe ๐
Authorization Data Type Ad-type Value
AD-IF-RELEVANT 1
AD-INTENDED-FOR-SERVER 2
AD-INTENDED-FOR-APPLICATION-CLASS 3
AD-KDC-ISSUED 4
AD-AND-OR 5
AD-MANDATORY-TICKET-EXTENSIONS 6
AD-IN-TICKET-EXTENSIONS 7
AD-MANDATORY-FOR-KDC 8
Reserved values 9-63
OSF-DCE 64
SESAME 65
AD-OSF-DCE-PKI-CERTID 66 (hemsath@us.ibm.com)
AD-WIN2K-PAC 128 (jbrezak@exchange.microsoft.com)
AD-ETYPE-NEGOTIATION 129 (lzhu@windows.microsoft.com)
7.5.5. Transited Encoding Types ๐ง
bestie, the transited encoding list is tiny but mighty โจ one real type, and then everything else is reserved ๐
Transited Encoding Type Tr-type Value
DOMAIN-X500-COMPRESS 1
Reserved values All others
7.5.6. Protocol Version Number ๐
pvno is just 5 right now, and that's the current Kerberos protocol version number. one number, zero drama ๐
Label Value Meaning or MIT Code
pvno 5 Current Kerberos protocol version number
7.5.7. Kerberos Message Types ๐
okay this is the message type lineup and it's a whole vibe ๐ requests and responses come in pairs, there are a couple of reserved slots that are literally just waiting, and KRB_ERROR is the drama queen at 30 ๐ญ
Message Type Value Meaning
KRB_AS_REQ 10 Request for initial authentication
KRB_AS_REP 11 Response to KRB_AS_REQ request
KRB_TGS_REQ 12 Request for authentication based on TGT
KRB_TGS_REP 13 Response to KRB_TGS_REQ request
KRB_AP_REQ 14 Application request to server
KRB_AP_REP 15 Response to KRB_AP_REQ_MUTUAL
KRB_RESERVED16 16 Reserved for user-to-user krb_tgt_request
KRB_RESERVED17 17 Reserved for user-to-user krb_tgt_reply
KRB_SAFE 20 Safe (checksummed) application message
KRB_PRIV 21 Private (encrypted) application message
KRB_CRED 22 Private (encrypted) message to forward
credentials
KRB_ERROR 30 Error response
7.5.8. Name Types ๐ฆ
last one in this part, and it's the name type gallery ๐ผ๏ธ from the unknown basic one to the enterprise name that can get mapped to a principal name. the X.500 one is literally pointing back to [RFC2253] so the citation stays put ๐ซถ
Name Type Value Meaning
KRB_NT_UNKNOWN 0 Name type not known
KRB_NT_PRINCIPAL 1 Just the name of the principal as in DCE,
or for users
KRB_NT_SRV_INST 2 Service and other unique instance (krbtgt)
KRB_NT_SRV_HST 3 Service with host name as instance
(telnet, rcommands)
KRB_NT_SRV_XHST 4 Service with host as remaining components
KRB_NT_UID 5 Unique ID
KRB_NT_X500_PRINCIPAL 6 Encoded X.509 Distinguished name [RFC2253]
KRB_NT_SMTP_NAME 7 Name in form of SMTP email name
(e.g., user@example.com)
KRB_NT_ENTERPRISE 10 Enterprise name; may be mapped to
principal name
7.5.9. Error Codes
okay bestie, this is the error code table, and it's giving whole encyclopedia ๐๐ซถ every code has a number and a meaning, so when something breaks you can look up exactly what the KDC or the application server is complaining about. The table is copied exactly as it appears in the spec, with no changes to the codes, values, or meanings.
Error Code Value Meaning
KDC_ERR_NONE 0 No error
KDC_ERR_NAME_EXP 1 Client's entry in database
has expired
KDC_ERR_SERVICE_EXP 2 Server's entry in database
has expired
KDC_ERR_BAD_PVNO 3 Requested protocol version
number not supported
KDC_ERR_C_OLD_MAST_KVNO 4 Client's key encrypted in
old master key
KDC_ERR_S_OLD_MAST_KVNO 5 Server's key encrypted in
old master key
KDC_ERR_C_PRINCIPAL_UNKNOWN 6 Client not found in
Kerberos database
KDC_ERR_S_PRINCIPAL_UNKNOWN 7 Server not found in
Kerberos database
KDC_ERR_PRINCIPAL_NOT_UNIQUE 8 Multiple principal entries
in database
KDC_ERR_NULL_KEY 9 The client or server has a
null key
KDC_ERR_CANNOT_POSTDATE 10 Ticket not eligible for
postdating
KDC_ERR_NEVER_VALID 11 Requested starttime is
later than end time
KDC_ERR_POLICY 12 KDC policy rejects request
KDC_ERR_BADOPTION 13 KDC cannot accommodate
requested option
KDC_ERR_ETYPE_NOSUPP 14 KDC has no support for
encryption type
KDC_ERR_SUMTYPE_NOSUPP 15 KDC has no support for
checksum type
KDC_ERR_PADATA_TYPE_NOSUPP 16 KDC has no support for
padata type
KDC_ERR_TRTYPE_NOSUPP 17 KDC has no support for
transited type
KDC_ERR_CLIENT_REVOKED 18 Clients credentials have
been revoked
KDC_ERR_SERVICE_REVOKED 19 Credentials for server have
been revoked
KDC_ERR_TGT_REVOKED 20 TGT has been revoked
KDC_ERR_CLIENT_NOTYET 21 Client not yet valid; try
again later
KDC_ERR_SERVICE_NOTYET 22 Server not yet valid; try
again later
KDC_ERR_KEY_EXPIRED 23 Password has expired;
change password to reset
KDC_ERR_PREAUTH_FAILED 24 Pre-authentication
information was invalid
KDC_ERR_PREAUTH_REQUIRED 25 Additional pre-
authentication required
KDC_ERR_SERVER_NOMATCH 26 Requested server and ticket
don't match
KDC_ERR_MUST_USE_USER2USER 27 Server principal valid for
user2user only
KDC_ERR_PATH_NOT_ACCEPTED 28 KDC Policy rejects
transited path
KDC_ERR_SVC_UNAVAILABLE 29 A service is not available
KRB_AP_ERR_BAD_INTEGRITY 31 Integrity check on
decrypted field failed
KRB_AP_ERR_TKT_EXPIRED 32 Ticket expired
KRB_AP_ERR_TKT_NYV 33 Ticket not yet valid
KRB_AP_ERR_REPEAT 34 Request is a replay
KRB_AP_ERR_NOT_US 35 The ticket isn't for us
KRB_AP_ERR_BADMATCH 36 Ticket and authenticator
don't match
KRB_AP_ERR_SKEW 37 Clock skew too great
KRB_AP_ERR_BADADDR 38 Incorrect net address
KRB_AP_ERR_BADVERSION 39 Protocol version mismatch
KRB_AP_ERR_MSG_TYPE 40 Invalid msg type
KRB_AP_ERR_MODIFIED 41 Message stream modified
KRB_AP_ERR_BADORDER 42 Message out of order
KRB_AP_ERR_BADKEYVER 44 Specified version of key is
not available
KRB_AP_ERR_NOKEY 45 Service key not available
KRB_AP_ERR_MUT_FAIL 46 Mutual authentication
failed
KRB_AP_ERR_BADDIRECTION 47 Incorrect message direction
KRB_AP_ERR_METHOD 48 Alternative authentication
method required
KRB_AP_ERR_BADSEQ 49 Incorrect sequence number
in message
KRB_AP_ERR_INAPP_CKSUM 50 Inappropriate type of
checksum in message
KRB_AP_PATH_NOT_ACCEPTED 51 Policy rejects transited
path
KRB_ERR_RESPONSE_TOO_BIG 52 Response too big for UDP;
retry with TCP
KRB_ERR_GENERIC 60 Generic error (description
in e-text)
KRB_ERR_FIELD_TOOLONG 61 Field is too long for this
implementation
KDC_ERROR_CLIENT_NOT_TRUSTED 62 Reserved for PKINIT
KDC_ERROR_KDC_NOT_TRUSTED 63 Reserved for PKINIT
KDC_ERROR_INVALID_SIG 64 Reserved for PKINIT
KDC_ERR_KEY_TOO_WEAK 65 Reserved for PKINIT
KDC_ERR_CERTIFICATE_MISMATCH 66 Reserved for PKINIT
KRB_AP_ERR_NO_TGT 67 No TGT available to
validate USER-TO-USER
KDC_ERR_WRONG_REALM 68 Reserved for future use
KRB_AP_ERR_USER_TO_USER_REQUIRED 69 Ticket must be for
USER-TO-USER
KDC_ERR_CANT_VERIFY_CERTIFICATE 70 Reserved for PKINIT
KDC_ERR_INVALID_CERTIFICATE 71 Reserved for PKINIT
KDC_ERR_REVOKED_CERTIFICATE 72 Reserved for PKINIT
KDC_ERR_REVOCATION_STATUS_UNKNOWN 73 Reserved for PKINIT
KDC_ERR_REVOCATION_STATUS_UNAVAILABLE 74 Reserved for PKINIT
KDC_ERR_CLIENT_NAME_MISMATCH 75 Reserved for PKINIT
KDC_ERR_KDC_NAME_MISMATCH 76 Reserved for PKINIT
8. Interoperability Requirements โจ
okay so Kerberos version 5 comes with SO many options ๐ like, a ton. you've got multiple encryption and checksum types, alternative encoding schemes for the transited field, optional pre-authentication mechanisms, how to handle tickets with no addresses, options for mutual authentication, user-to-user authentication, proxies, the format of realm names, how authorization data gets handled, and forwarding, postdating, and renewing tickets. literally so much choice ๐ญ
BUT if realms are gonna work together (interoperability, periodt ๐ ), everyone needs to agree on a minimal configuration that every implementation supports. this baseline isn't set in stone tho, it can change as the tech changes ๐ฆ like, if one of the required encryption or checksum algorithms turns out to be insecure someday, it gets swapped out for something better. growth era fr ๐ฑ๐
8.1. Specification 2 ๐
Okay so this section is where the second specification of these options gets defined ๐ Implementations set up this way can say they support Kerberos Version 5 Specification 2 (5.2). Specification 1 (deprecated) is over in RFC 1510, so go look there if you're curious ๐ง
Transport
TCP/IP and UDP/IP transport MUST be supported by clients and KDCs claiming conformance to specification 2. No cap, this one's a must ๐ซถ
Encryption and Checksum Methods
The following encryption and checksum mechanisms MUST be supported:
Implementations SHOULD support other mechanisms as well, but the additional mechanisms may only be used when communicating with principals known to also support them. The following mechanisms from [RFC3961] and [RFC3962] SHOULD be supported:
- Encryption:
AES128-CTS-HMAC-SHA1-96,DES-CBC-MD5,DES3-CBC-SHA1-KD - Checksums:
DES-MD5,HMAC-SHA1-DES3-KD,HMAC-SHA1-96-AES128
Implementations MAY support other mechanisms as well, but the additional mechanisms may only be used when communicating with principals known to support them also. ๐
Implementation note: Earlier implementations of Kerberos generate messages using the CRC-32 and RSA-MD5 checksum methods. For interoperability with these earlier releases, implementors MAY consider supporting these checksum methods but should carefully analyze the security implications to limit the situations within which these methods are accepted. ๐ Careful with these ones, bestie!!
Realm Names
All implementations MUST understand hierarchical realms in both the Internet Domain and the X.500 style. When a TGT for an unknown realm is requested, the KDC MUST be able to determine the names of the intermediate realms between the KDCs realm and the requested realm. ๐ฆ
Transited Field Encoding
DOMAIN-X500-COMPRESS (described in Section 3.3.3.2) MUST be supported. Alternative encodings MAY be supported, but they may only be used when that encoding is supported by ALL intermediate realms. โจ
Pre-authentication Methods
The TGS-REQ method MUST be supported. It is not used on the initial request. The PA-ENC-TIMESTAMP method MUST be supported by clients, but whether it is enabled by default MAY be determined on a realm-by-realm basis. If the method is not used in the initial request and the error KDC_ERR_PREAUTH_REQUIRED is returned specifying PA-ENC-TIMESTAMP as an acceptable method, the client SHOULD retry the initial request using the PA-ENC-TIMESTAMP pre-authentication method. Servers need not support the PA-ENC-TIMESTAMP method, but if it is not supported the server SHOULD ignore the presence of PA-ENC-TIMESTAMP pre-authentication in a request. ๐
The ETYPE-INFO2 method MUST be supported; this method is used to communicate the set of supported encryption types, and corresponding salt and string to key parameters. The ETYPE-INFO method SHOULD be supported for interoperability with older implementation. ๐
Mutual Authentication
Mutual authentication (via the KRB_AP_REP message) MUST be supported. It's giving two-way trust, iconic ๐
Ticket Addresses and Flags
All KDCs MUST pass through tickets that carry no addresses (i.e., if a TGT contains no addresses, the KDC will return derivative tickets). Implementations SHOULD default to requesting addressless tickets, as this significantly increases interoperability with network address translation. In some cases, realms or application servers MAY require that tickets have an address. ๐ธ
Implementations SHOULD accept directional address type for the KRB_SAFE and KRB_PRIV message and SHOULD include directional addresses in these messages when other address types are not available.
Proxies and forwarded tickets MUST be supported. Individual realms and application servers can set their own policy on when such tickets will be accepted. ๐ซถ
All implementations MUST recognize renewable and postdated tickets, but they need not actually implement them. If these options are not supported, the starttime and endtime in the ticket SHALL specify a ticket's entire useful life. When a postdated ticket is decoded by a server, all implementations SHALL make the presence of the postdated flag visible to the calling server. โฐ
User-to-User Authentication
Support for user-to-user authentication (via the ENC-TKT-IN-SKEY KDC option) MUST be provided by implementations, but individual realms MAY decide as a matter of policy to reject such requests on a per-principal or realm-wide basis. ๐
Authorization Data
Implementations MUST pass all authorization data subfields from TGTs to any derivative tickets unless they are directed to suppress a subfield as part of the definition of that registered subfield type. (It is never incorrect to pass on a subfield, and no registered subfield types presently specify suppression at the KDC.)
Implementations MUST make the contents of any authorization data subfields available to the server when a ticket is used. Implementations are not required to allow clients to specify the contents of the authorization data fields. ๐ฅ
Constant Ranges
All protocol constants are constrained to 32-bit (signed) values unless further constrained by the protocol definition. This limit is provided to allow implementations to make assumptions about the maximum values that will be received for these constants. Implementations receiving values outside this range MAY reject the request, but they MUST recover cleanly. Bestie, the vibe is "handle the weird stuff gracefully" ๐ง
8.2. Recommended KDC Values โญ
Following is a list of recommended values for a KDC configuration. Lowkey the cutest little table ever ๐
Minimum lifetime 5 minutes
Maximum renewable lifetime 1 week
Maximum ticket lifetime 1 day
Acceptable clock skew 5 minutes
Empty addresses Allowed
Proxiable, etc. Allowed
9. IANA Considerations ๐
Section 7 of this document specifies protocol constants and other defined values required for the interoperability of multiple implementations. Until a subsequent RFC specifies otherwise, or the Kerberos working group is shut down, allocations of additional protocol constants and other defined values required for extensions to the Kerberos protocol will be administered by the Kerberos working group. Following the recommendations outlined in [RFC2434], guidance is provided to the IANA as follows:
"reserved" realm name types in Section 6.1 and "other" realm types except those beginning with "X-" or "x-" will not be registered without IETF standards action, at which point guidelines for further assignment will be specified. Realm name types beginning with "X-" or "x-" are for private use. ๐
For host address types described in Section 7.1, negative values are for private use. Assignment of additional positive numbers is subject to review by the Kerberos working group or other expert review.
Additional key usage numbers, as defined in Section 7.5.1, will be assigned subject to review by the Kerberos working group or other expert review.
Additional preauthentication data type values, as defined in section 7.5.2, will be assigned subject to review by the Kerberos working group or other expert review.
Additional authorization data types as defined in Section 7.5.4, will be assigned subject to review by the Kerberos working group or other expert review. Although it is anticipated that there may be significant demand for private use types, provision is intentionally not made for a private use portion of the namespace because conflicts between privately assigned values could have detrimental security implications. ๐ญ Private-use drama is a real risk, so no private corner for these!
Additional transited encoding types, as defined in Section 7.5.5, present special concerns for interoperability with existing implementations. As such, such assignments will only be made by standards action, except that the Kerberos working group or another other working group with competent jurisdiction may make preliminary assignments for documents that are moving through the standards process. ๐ง
Additional Kerberos message types, as described in Section 7.5.7, will be assigned subject to review by the Kerberos working group or other expert review.
Additional name types, as described in Section 7.5.8, will be assigned subject to review by the Kerberos working group or other expert review.
Additional error codes described in Section 7.5.9 will be assigned subject to review by the Kerberos working group or other expert review. โจ
10. Security Considerations ๐โจ
okay bestie, this is the spicy section and I need you to actually read it ๐ญ๐ซถ Kerberos is an authentication service, so it helps verify who a principal is on the network. But by itself, it does not do authorization ๐ . Apps should not treat a service ticket from the Kerberos server as permission to use a service, because they can get bypassed when they interoperate with other KDCs or when other ways of authenticating the app exist ๐.
Denial of service is not solved by Kerberos ๐. An intruder can stop an app from taking part in the proper authentication steps. Since authentication is required for lots of services, a successful DoS attack on a Kerberos server could take down other network services that rely on it. Kerberos is vulnerable to a few kinds of this: attacks on the network that stop clients from reaching the KDC, attacks on the domain name system that stop a client from finding the Kerberos server's IP address, and overloading the KDC with repeated requests.
Interoperability conflicts from incompatible character-set usage (see 5.2.1) can also cause denial of service for clients that use character sets in Kerberos strings other than the ones stored in the KDC database ๐ธ.
Authentication servers keep a database of principals (users and servers) and their secret keys, so the security of those machines is critical ๐จ. If an authentication server gets breached, every server that relies on that KDC is compromised, and so is the authentication of every principal registered in that KDC's realm.
Principals have to keep their secret keys secret ๐คซ. If an intruder steals a principal's key, they can masquerade as that principal or impersonate any server to the legit principal.
Password-guessing attacks are also not solved by Kerberos ๐. If a user picks a weak password, an attacker can run an off-line dictionary attack, trying dictionary entries over and over to decrypt messages that are encrypted under a key derived from that password.
Unless pre-authentication is required by the policy of a realm, the KDC won't know whether an authentication request succeeds. An attacker can request a reply with credentials for any principal. Those credentials probably won't be much use unless the attacker knows the client's secret key, but the reply is encrypted in the client's secret key, which gives the attacker ciphertext to use for brute force or dictionary attacks against the user's password ๐. That's why it is strongly encouraged that Kerberos realms require pre-authentication. Even with pre-authentication, attackers may still try brute force or dictionary attacks against credentials they've observed by eavesdropping on the network.
A client can request a ticket for any server principal and then try a brute force or dictionary attack against that server principal's key using that ticket. So it is strongly encouraged that keys be randomly generated (rather than generated from passwords) for any principals that can be used as the target principal for a KRB_TGS_REQ or KRB_AS_REQ message ๐ฒ. [RFC4086]
The DES-CBC-MD5 encryption method and the DES-MD5 checksum method are listed as SHOULD be implemented for backward compatibility ๐ฐ๏ธ. But the single DES encryption algorithm they're based on is weak, so stronger algorithms should be used whenever possible ๐ช.
Each host on the network needs a clock that is loosely synchronized with the clocks of the other hosts โฐ. This synchronization reduces the bookkeeping application servers need to do for replay detection. The degree of "looseness" can be configured on a per-server basis, but it is typically on the order of 5 minutes. If clocks are synchronized over the network, the clock synchronization protocol MUST itself be secured from network attackers ๐ก๏ธ.
Principal identifiers must not be recycled on a short-term basis โป๏ธ๐ซ. A typical access control setup uses access control lists (ACLs) to grant permissions to particular principals. If a stale ACL entry is left behind for a deleted principal and that principal identifier gets reused, the new principal will inherit the rights in the stale ACL entry ๐ฑ. Not reusing principal identifiers removes the danger of accidental access.
Successfully decrypting a KRB_AS_REP message from the KDC is not enough for a host to verify the user's identity ๐ต๏ธ. The user and an attacker could work together to generate a KRB_AS_REP-format message that decrypts properly but isn't from the proper KDC. To authenticate a user logging on to a local system, the credentials obtained in the AS exchange may first be used in a TGS exchange to get credentials for a local server. Those credentials must then be verified by a local server through successful completion of the Client/Server exchange โ .
Many RFC 1510-compliant implementations ignore unknown authorization data elements ๐. Relying on those implementations to honor authorization data restrictions may create a security weakness.
Kerberos credentials contain clear-text information identifying the principals they apply to ๐. If privacy of this information is needed, the exchange itself should be wrapped in a protocol that provides confidentiality for the exchange of these credentials ๐.
Applications must take care to protect communications after authentication ๐. They can use the KRB_PRIV or KRB_SAFE messages as appropriate, or apply their own confidentiality or integrity mechanisms to those communications. Completing the KRB_AP_REQ and KRB_AP_REP exchange without later using confidentiality and integrity mechanisms only gives authentication of the parties to the communication, not confidentiality and integrity for what comes next. Applications that use confidentiality and integrity protection mechanisms other than KRB_PRIV and KRB_SAFE must make sure the authentication step is appropriately linked with the protected communication channel the application sets up ๐.
Unless the application server has its own suitable way to protect against replay (for example, a challenge-response sequence the server starts after authentication, or a server-generated encryption subkey), the server must use a replay cache to remember any authenticator presented within the allowable clock skew ๐ผ. All services that share a key need to use the same replay cache. If separate replay caches are used, an authenticator used with one of those services could later be replayed to a different service with the same service principal ๐ฌ.
If a server loses track of authenticators presented within the allowable clock skew, it must reject all requests until the clock skew interval has passed โณ. That way, any lost or replayed authenticators will fall outside the allowable clock skew and can't be successfully replayed anymore.
Implementations of Kerberos should not use untrusted directory servers to determine the realm of a host ๐๐ซ. Allowing that would let someone who compromises the directory server trick an attacker into directing the client to accept authentication with the wrong principal, one with a similar name but in a realm the legitimate host was never registered with ๐ญ.
Implementations of Kerberos must not use DNS to map one name to another (canonicalize) in order to determine the host part of the principal name you're about to talk to ๐๐ซ. Allowing that canonicalization would let a compromise of DNS cause a client to obtain credentials and authenticate correctly to the wrong principal. The client will know who it is communicating with, but it won't be the principal it intended to talk to ๐ญ.
If the Kerberos server returns a TGT for a realm that is 'closer' than the desired realm, the client may use local policy configuration to verify that the authentication path used is an acceptable one ๐งญ. Alternatively, a client may choose its own authentication path rather than rely on the Kerberos server to pick one. Either way, any policy or configuration information used to choose or validate authentication paths, whether by the Kerberos server or the client, must come from a trusted source ๐.
The Kerberos protocol in its basic form does not provide perfect forward secrecy for communications ๐จ. If an eavesdropper has recorded traffic, then messages encrypted using the KRB_PRIV message, or messages encrypted using application-specific encryption under keys exchanged using Kerberos, can be decrypted if the user's, application server's, or KDC's key is discovered later. This happens because the session key used to encrypt such messages is, when sent over the network, encrypted in the key of the application server. It is also encrypted under the session key from the user's TGT when it is returned to the user in the KRB_TGS_REP message. The session key from the TGT is sent to the user in the KRB_AS_REP message, encrypted in the user's secret key, and it is embedded in the TGT, which was encrypted in the key of the KDC. Applications that require perfect forward secrecy must exchange keys through mechanisms that provide that assurance, but they may still use Kerberos for authentication of the encrypted channel established through those other means ๐.
11. Acknowledgements ๐ซถ๐ท
This document is a revision of RFC 1510, which was co-authored with John Kohl ๐. The specification of the Kerberos protocol described here is the result of many years of effort ๐ฅน. Over that time, lots of people contributed to defining the protocol and writing the specification. Sadly, it isn't possible to list every contributor as an author of this document, but there are many who aren't listed who are authors in spirit. That includes people who contributed text for parts of some sections, people who helped design parts of the protocol, and people who contributed significantly to the discussion of the protocol in the IETF common authentication technology (CAT) and Kerberos working groups ๐.
Among those who contributed to the development and specification of Kerberos were Jeffrey Altman, John Brezak, Marc Colan, Johan Danielsson, Don Davis, Doug Engert, Dan Geer, Paul Hill, John Kohl, Marc Horowitz, Matt Hur, Jeffrey Hutzelman, Paul Leach, John Linn, Ari Medvinsky, Sasha Medvinsky, Steve Miller, Jon Rochlis, Jerome Saltzer, Jeffrey Schiller, Jennifer Steiner, Ralph Swick, Mike Swift, Jonathan Trostle, Theodore Ts'o, Brian Tung, Jacques Vidrine, Assar Westerlund, and Nicolas Williams ๐โจ. Many other members of MIT Project Athena, the MIT networking group, and the Kerberos and CAT working groups of the IETF also contributed, but they aren't listed here ๐ง.
A. ASN.1 module ๐งฉ
KerberosV5Spec2 {
iso(1) identified-organization(3) dod(6) internet(1)
security(5) kerberosV5(2) modules(4) krb5spec2(2)
} DEFINITIONS EXPLICIT TAGS ::= BEGIN
-- OID arc for KerberosV5 -- -- This OID may be used to identify Kerberos protocol messages -- encapsulated in other protocols. -- -- This OID also designates the OID arc for KerberosV5-related OIDs. -- -- NOTE: RFC 1510 had an incorrect value (5) for "dod" in its OID. id-krb5 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) dod(6) internet(1) security(5) kerberosV5(2) }
Int32 ::= INTEGER (-2147483648..2147483647) -- signed values representable in 32 bits
UInt32 ::= INTEGER (0..4294967295) -- unsigned 32 bit values
Microseconds ::= INTEGER (0..999999) -- microseconds
KerberosString ::= GeneralString (IA5String)
Realm ::= KerberosString
PrincipalName ::= SEQUENCE { name-type [0] Int32, name-string [1] SEQUENCE OF KerberosString }
KerberosTime ::= GeneralizedTime -- with no fractional seconds
HostAddress ::= SEQUENCE { addr-type [0] Int32, address [1] OCTET STRING }
-- NOTE: HostAddresses is always used as an OPTIONAL field and -- should not be empty. HostAddresses -- NOTE: subtly different from rfc1510,
-- but has a value mapping and encodes the same ::= SEQUENCE OF HostAddress
-- NOTE: AuthorizationData is always used as an OPTIONAL field and -- should not be empty. AuthorizationData ::= SEQUENCE OF SEQUENCE { ad-type [0] Int32, ad-data [1] OCTET STRING }
PA-DATA ::= SEQUENCE { -- NOTE: first tag is [1], not [0] padata-type [1] Int32, padata-value [2] OCTET STRING -- might be encoded AP-REQ }
KerberosFlags ::= BIT STRING (SIZE (32..MAX)) -- minimum number of bits shall be sent, -- but no fewer than 32
EncryptedData ::= SEQUENCE { etype [0] Int32 -- EncryptionType --, kvno [1] UInt32 OPTIONAL, cipher [2] OCTET STRING -- ciphertext }
EncryptionKey ::= SEQUENCE { keytype [0] Int32 -- actually encryption type --, keyvalue [1] OCTET STRING }
Checksum ::= SEQUENCE { cksumtype [0] Int32, checksum [1] OCTET STRING }
Ticket ::= [APPLICATION 1] SEQUENCE { tkt-vno [0] INTEGER (5), realm [1] Realm, sname [2] PrincipalName, enc-part [3] EncryptedData -- EncTicketPart }
-- Encrypted part of ticket EncTicketPart ::= [APPLICATION 3] SEQUENCE { flags [0] TicketFlags, key [1] EncryptionKey, crealm [2] Realm, cname [3] PrincipalName, transited [4] TransitedEncoding, authtime [5] KerberosTime, starttime [6] KerberosTime OPTIONAL, endtime [7] KerberosTime, renew-till [8] KerberosTime OPTIONAL, caddr [9] HostAddresses OPTIONAL, authorization-data [10] AuthorizationData OPTIONAL }
-- encoded Transited field TransitedEncoding ::= SEQUENCE { tr-type [0] Int32 -- must be registered --, contents [1] OCTET STRING }
TicketFlags ::= KerberosFlags -- reserved(0), -- forwardable(1), -- forwarded(2), -- proxiable(3), -- proxy(4), -- may-postdate(5), -- postdated(6), -- invalid(7), -- renewable(8), -- initial(9), -- pre-authent(10), -- hw-authent(11), -- the following are new since 1510 -- transited-policy-checked(12), -- ok-as-delegate(13)
AS-REQ ::= [APPLICATION 10] KDC-REQ
TGS-REQ ::= [APPLICATION 12] KDC-REQ
KDC-REQ ::= SEQUENCE { -- NOTE: first tag is [1], not [0] pvno [1] INTEGER (5) , msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --), padata [3] SEQUENCE OF PA-DATA OPTIONAL -- NOTE: not empty --, req-body [4] KDC-REQ-BODY }
KDC-REQ-BODY ::= SEQUENCE { kdc-options [0] KDCOptions, cname [1] PrincipalName OPTIONAL -- Used only in AS-REQ --, realm [2] Realm -- Server's realm -- Also client's in AS-REQ --, sname [3] PrincipalName OPTIONAL, from [4] KerberosTime OPTIONAL, till [5] KerberosTime, rtime [6] KerberosTime OPTIONAL, nonce [7] UInt32, etype [8] SEQUENCE OF Int32 -- EncryptionType -- in preference order --, addresses [9] HostAddresses OPTIONAL, enc-authorization-data [10] EncryptedData OPTIONAL -- AuthorizationData --, additional-tickets [11] SEQUENCE OF Ticket OPTIONAL -- NOTE: not empty }
KDCOptions ::= KerberosFlags -- reserved(0), -- forwardable(1), -- forwarded(2), -- proxiable(3), -- proxy(4), -- allow-postdate(5), -- postdated(6), -- unused7(7), -- renewable(8), -- unused9(9), -- unused10(10), -- opt-hardware-auth(11), -- unused12(12), -- unused13(13), -- 15 is reserved for canonicalize -- unused15(15), -- 26 was unused in 1510 -- disable-transited-check(26), -- -- renewable-ok(27), -- enc-tkt-in-skey(28), -- renew(30), -- validate(31)
AS-REP ::= [APPLICATION 11] KDC-REP
TGS-REP ::= [APPLICATION 13] KDC-REP KDC-REP ::= SEQUENCE { pvno [0] INTEGER (5), msg-type [1] INTEGER (11 -- AS -- | 13 -- TGS --), padata [2] SEQUENCE OF PA-DATA OPTIONAL -- NOTE: not empty --, crealm [3] Realm, cname [4] PrincipalName, ticket [5] Ticket, enc-part [6] EncryptedData -- EncASRepPart or EncTGSRepPart, -- as appropriate }
EncASRepPart ::= [APPLICATION 25] EncKDCRepPart
EncTGSRepPart ::= [APPLICATION 26] EncKDCRepPart
EncKDCRepPart ::= SEQUENCE { key [0] EncryptionKey, last-req [1] LastReq, nonce [2] UInt32, key-expiration [3] KerberosTime OPTIONAL, flags [4] TicketFlags, authtime [5] KerberosTime, starttime [6] KerberosTime OPTIONAL, endtime [7] KerberosTime, renew-till [8] KerberosTime OPTIONAL, srealm [9] Realm, sname [10] PrincipalName, caddr [11] HostAddresses OPTIONAL }
LastReq ::= SEQUENCE OF SEQUENCE { lr-type [0] Int32, lr-value [1] KerberosTime }
AP-REQ ::= [APPLICATION 14] SEQUENCE { pvno [0] INTEGER (5), msg-type [1] INTEGER (14), ap-options [2] APOptions, ticket [3] Ticket, authenticator [4] EncryptedData -- Authenticator }
APOptions ::= KerberosFlags -- reserved(0), -- use-session-key(1), -- mutual-required(2)
-- Unencrypted authenticator Authenticator ::= [APPLICATION 2] SEQUENCE { authenticator-vno [0] INTEGER (5), crealm [1] Realm, cname [2] PrincipalName, cksum [3] Checksum OPTIONAL, cusec [4] Microseconds, ctime [5] KerberosTime, subkey [6] EncryptionKey OPTIONAL, seq-number [7] UInt32 OPTIONAL, authorization-data [8] AuthorizationData OPTIONAL }
AP-REP ::= [APPLICATION 15] SEQUENCE { pvno [0] INTEGER (5), msg-type [1] INTEGER (15), enc-part [2] EncryptedData -- EncAPRepPart }
EncAPRepPart ::= [APPLICATION 27] SEQUENCE { ctime [0] KerberosTime, cusec [1] Microseconds, subkey [2] EncryptionKey OPTIONAL, seq-number [3] UInt32 OPTIONAL }
KRB-SAFE ::= [APPLICATION 20] SEQUENCE { pvno [0] INTEGER (5), msg-type [1] INTEGER (20), safe-body [2] KRB-SAFE-BODY, cksum [3] Checksum }
KRB-SAFE-BODY ::= SEQUENCE { user-data [0] OCTET STRING, timestamp [1] KerberosTime OPTIONAL, usec [2] Microseconds OPTIONAL, seq-number [3] UInt32 OPTIONAL, s-address [4] HostAddress, r-address [5] HostAddress OPTIONAL }
KRB-PRIV ::= [APPLICATION 21] SEQUENCE { pvno [0] INTEGER (5), msg-type [1] INTEGER (21), -- NOTE: there is no [2] tag
enc-part [3] EncryptedData -- EncKrbPrivPart }
EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE { user-data [0] OCTET STRING, timestamp [1] KerberosTime OPTIONAL, usec [2] Microseconds OPTIONAL, seq-number [3] UInt32 OPTIONAL, s-address [4] HostAddress -- sender's addr --, r-address [5] HostAddress OPTIONAL -- recip's addr }
KRB-CRED ::= [APPLICATION 22] SEQUENCE { pvno [0] INTEGER (5), msg-type [1] INTEGER (22), tickets [2] SEQUENCE OF Ticket, enc-part [3] EncryptedData -- EncKrbCredPart }
EncKrbCredPart ::= [APPLICATION 29] SEQUENCE { ticket-info [0] SEQUENCE OF KrbCredInfo, nonce [1] UInt32 OPTIONAL, timestamp [2] KerberosTime OPTIONAL, usec [3] Microseconds OPTIONAL, s-address [4] HostAddress OPTIONAL, r-address [5] HostAddress OPTIONAL }
KrbCredInfo ::= SEQUENCE { key [0] EncryptionKey, prealm [1] Realm OPTIONAL, pname [2] PrincipalName OPTIONAL, flags [3] TicketFlags OPTIONAL, authtime [4] KerberosTime OPTIONAL, starttime [5] KerberosTime OPTIONAL, endtime [6] KerberosTime OPTIONAL, renew-till [7] KerberosTime OPTIONAL, srealm [8] Realm OPTIONAL, sname [9] PrincipalName OPTIONAL, caddr [10] HostAddresses OPTIONAL }
KRB-ERROR ::= [APPLICATION 30] SEQUENCE { pvno [0] INTEGER (5), msg-type [1] INTEGER (30), ctime [2] KerberosTime OPTIONAL, cusec [3] Microseconds OPTIONAL, stime [4] KerberosTime, susec [5] Microseconds, error-code [6] Int32, crealm [7] Realm OPTIONAL, cname [8] PrincipalName OPTIONAL, realm [9] Realm -- service realm --, sname [10] PrincipalName -- service name --, e-text [11] KerberosString OPTIONAL, e-data [12] OCTET STRING OPTIONAL }
METHOD-DATA ::= SEQUENCE OF PA-DATA
TYPED-DATA ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { data-type [0] Int32, data-value [1] OCTET STRING OPTIONAL }
-- preauth stuff follows
PA-ENC-TIMESTAMP ::= EncryptedData -- PA-ENC-TS-ENC
PA-ENC-TS-ENC ::= SEQUENCE {
patimestamp [0] KerberosTime -- client's time --,
pausec [1] Microseconds OPTIONAL
}
ETYPE-INFO-ENTRY ::= SEQUENCE {
etype [0] Int32,
salt [1] OCTET STRING OPTIONAL
}
ETYPE-INFO ::= SEQUENCE OF ETYPE-INFO-ENTRY
ETYPE-INFO2-ENTRY ::= SEQUENCE {
etype [0] Int32,
salt [1] KerberosString OPTIONAL,
s2kparams [2] OCTET STRING OPTIONAL
}
ETYPE-INFO2 ::= SEQUENCE SIZE (1..MAX) OF ETYPE-INFO2-ENTRY
AD-IF-RELEVANT ::= AuthorizationData
AD-KDCIssued ::= SEQUENCE {
ad-checksum [0] Checksum,
i-realm [1] Realm OPTIONAL,
i-sname [2] PrincipalName OPTIONAL,
elements [3] AuthorizationData
}
AD-AND-OR ::= SEQUENCE {
condition-count [0] Int32,
elements [1] AuthorizationData
}
AD-MANDATORY-FOR-KDC ::= AuthorizationData
END
B. Changes since RFC 1510 ๐
Okay, so this doc replaces RFC 1510 and finally clarifies the stuff that was never fully specified ๐ซถ Anywhere the recommended implementation choices changed, or new options got added, those changes are described in the document and listed right here. The big glow-up is "Specification 2" in Section 8, which changes the required encryption and checksum methods so they match current best practices and deprecates the methods that aren't considered strong enough anymore ๐ฅ
Section 1 got a discussion about relying on the KDC to check the transited field, plus a flag in a ticket that says this check has happened. That's a brand-new capability that RFC 1510 didn't have โจ Older implementations may ignore or not set this flag, and that doesn't bring any negative security implications, which is kind of iconic ๐
The definition of the secret key used to say that for a user, the key is derived from a password. RFC 1510 said the key was derived from the password. Now it's softer: for a user the key may be derived from a password ๐ธ This was done so things like a smart-card, or any other way of getting the user key without a password, actually fit ๐
The introduction now mentions public key cryptography for initial authentication in Kerberos, by reference. RFC 1510 didn't have that reference at all ๐ฆ
Section 1.3 is new, and it explains that even though Kerberos authenticates a named principal, it's still the application's job to make sure that the authenticated name is the actual entity it wants to talk to ๐ Very main character of the app, honestly.
Discussion of extensibility was added to the introduction ๐ง
Discussion of how extensibility affects ticket flags and KDC options went into the introduction of Section 2 ๐ No existing options or flags from RFC 1510 were changed. Some sections got renumbered, and text was revised so the existing options are clearer, especially the ENC-TKT-IN-SKEY option (now section 2.9.2), which is used for user-to-user authentication. The brand-new option and ticket flag, transited policy checking (Section 2.7), was added too โจ
Section 3 got a warning about generating session keys for application use. It urges including key entropy from the KDC generated session key in the ticket ๐ฅ An example about using the sub-session key was added to Section 3.2.6 ๐ Descriptions of the pa-etype-info, pa-etype-info2, and pa-pw-salt pre-authentication data items were added too. The recommendation for using pre-authentication changed from "MAY" to "SHOULD", and there's now a note about known plaintext attacks ๐ญ
In RFC 1510, Section 4 described the database in the KDC. That discussion wasn't needed for interoperability and it unnecessarily boxed in implementations, so the old Section 4 is gone ๐
The current Section 4 used to be Section 6, all about encryption and checksum specifications ๐ Most of that got updated to support new encryption methods and moved into a separate document. The few bits that are specific to Kerberos now live in Section 4 ๐ง
Section 5 got a major layout glow-up to make the correct behavior for optional fields clear ๐ A lot of this was necessary because the original Kerberos ASN.1 description was improper, and it left the correct behavior underspecified. The wording was also tightened wherever possible, so implementations that conform to this spec will stay extensible when new fields get added in future specs โจ
Text was added about time_t=0 issues in the ASN.1 ๐ There's also new text clarifying issues where implementations treat omitted optional integers as zero ๐ซถ Behavior for optional SEQUENCE or SEQUENCE OF that may be empty got clarified too. Sequence numbers got a discussion covering how some implementations behave, including "zero" behavior and negative numbers ๐ฅ A compatibility note was added about always sending EncTGSRepPart no matter what the enclosing reply type is ๐
Minor changes were made to the HostAddresses description, and integer types got constrained. KerberosString is now defined as a (significantly) constrained GeneralString ๐ KerberosFlags was defined to match existing implementation behavior that departs from RFC 1510's definition. The transited-policy-checked(12) and ok-as-delegate(13) ticket flags were added, and so was the disable-transited-check(26) KDC option ๐ฆ
Descriptions of commonly implemented PA-DATA were added to Section 5 ๐ธ The KRB-SAFE description was updated to note the existing implementation behavior of double-encoding ๐ง
There used to be two definitions of METHOD-DATA in RFC 1510. The second one, meant for use with KRB_AP_ERR_METHOD, got removed, which leaves the SEQUENCE OF PA-DATA definition ๐
Section 7, naming constraints, moved from RFC 1510 into Section 6 โจ
Words were added saying that domain-based realm names for newly created realms should be specified in uppercase. That recommendation doesn't make lowercase realm names illegal ๐ More words were added to point out that the slash-separated components in the X.500 style of realm names match existing RFC 1510 based implementations, but they conflict with the general X.500 name representation recommendation in RFC 2253 ๐ญ
Section 8, network transport, constants and defined values, moved from RFC 1510 into Section 7 ๐ Since RFC 1510, the TCP transport for Kerberos messages got defined, and the encryption and checksum number assignments moved into a separate document ๐
Again, "Specification 2" in Section 8 of the current document changes the required encryption and checksum methods to match the best current practices and deprecates the methods that are no longer considered sufficiently strong ๐ฅ
Two brand-new sections were added, one on IANA considerations and one on security considerations ๐ซถ
The pseudo-code got removed from the appendix ๐ It was sometimes misread as limiting implementation choices, and in RFC 1510 it wasn't always consistent with the words in the specification. So the effort went into clearing up ambiguities in the specification itself, instead of relying on the pseudo-code ๐
An appendix was added with the complete ASN.1 module, drawn from the discussion in Section 5 of the current document ๐ง
END NOTES ๐ธ
(*TM) Project Athena, Athena, and Kerberos are trademarks of the Massachusetts Institute of Technology (MIT). ๐
Normative References ๐ฆ
- [RFC3961] Raeburn, K., "Encryption and Checksum Specifications for Kerberos 5", RFC 3961, February 2005.
- [RFC3962] Raeburn, K., "Advanced Encryption Standard (AES) Encryption for Kerberos 5", RFC 3962, February 2005.
- [ISO-646/ECMA-6] International Organization for Standardization, "7-bit Coded Character Set for Information Interchange", ISO/IEC 646:1991.
- [ISO-2022/ECMA-35] International Organization for Standardization, "Character code structure and extension techniques", ISO/IEC 2022:1994.
- [RFC1035] Mockapetris, P., "Domain names - implementation and specification", STD 13, RFC 1035, November 1987.
- [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
- [RFC2434] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 2434, October 1998.
- [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for specifying the location of services (DNS SRV)", RFC 2782, February 2000.
- [RFC2253] Wahl, M., Kille, S., and T. Howes, "Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names", RFC 2253, December 1997.
- [RFC3513] Hinden, R. and S. Deering, "Internet Protocol Version 6 (IPv6) Addressing Architecture", RFC 3513, April 2003.
- [X680] Abstract Syntax Notation One (ASN.1): Specification of Basic Notation, ITU-T Recommendation X.680 (1997) | ISO/IEC International Standard 8824-1:1998.
- [X690] ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER), ITU-T Recommendation X.690 (1997)| ISO/IEC International Standard 8825-1:1998.
Informative References
Okay, bestie, these are the receipts ๐งพโจ Every paper and spec the RFC leans on, so you can go read the originals if you're curious.
- [ISO-8859] International Organization for Standardization, "8-bit Single-byte Coded Graphic Character Sets -- Latin Alphabet", ISO/IEC 8859. ๐ธ
- [RFC1964] Linn, J., "The Kerberos Version 5 GSS-API Mechanism", RFC 1964, June 1996. ๐
- [DGT96] Don Davis, Daniel Geer, and Theodore Ts'o, "Kerberos With Clocks Adrift: History, Protocols, and Implementation", USENIX Computing Systems 9:1, January 1996. โฐ
- [DS81] Dorothy E. Denning and Giovanni Maria Sacco, "Time-stamps in Key Distribution Protocols," Communications of the ACM, Vol. 24 (8), p. 533-536, August 1981. ๐ฐ๏ธ
- [KNT94] John T. Kohl, B. Clifford Neuman, and Theodore Y. Ts'o, "The Evolution of the Kerberos Authentication System". In Distributed Open Systems, pages 78-94. IEEE Computer Society Press, 1994. ๐ง
- [MNSS87] S. P. Miller, B. C. Neuman, J. I. Schiller, and J. H. Saltzer, Section E.2.1: Kerberos Authentication and Authorization System, M.I.T. Project Athena, Cambridge, Massachusetts, December 21, 1987. ๐๏ธ
- [NS78] Roger M. Needham and Michael D. Schroeder, "Using Encryption for Authentication in Large Networks of Computers," Communications of the ACM, Vol. 21 (12), pp. 993-999, December 1978. ๐
- [Neu93] B. Clifford Neuman, "Proxy-Based Authorization and Accounting for Distributed Systems," in Proceedings of the 13th International Conference on Distributed Computing Systems, Pittsburgh, PA, May 1993. ๐
- [NT94] B. Clifford Neuman and Theodore Y. Ts'o, "An Authentication Service for Computer Networks," IEEE Communications Magazine, Vol. 32 (9), p. 33-38, September 1994. ๐ก
- [Pat92] J. Pato, Using Pre-Authentication to Avoid Password Guessing Attacks, Open Software Foundation DCE Request for Comments 26 (December 1992. ๐
- [RFC1510] Kohl, J. and C. Neuman, "The Kerberos Network Authentication Service (V5)", RFC 1510, September 1993. ๐
- [RFC4086] Eastlake, D., 3rd, Schiller, J., and S. Crocker, "Randomness Requirements for Security", BCP 106, RFC 4086, June 2005. ๐ฒ
- [SNS88] J. G. Steiner, B. C. Neuman, and J. I. Schiller, "Kerberos: An Authentication Service for Open Network Systems," p. 191-202, Usenix Conference Proceedings, Dallas, Texas, February 1988. ๐ฆ
- [RFC4121] Zhu, L., Jaganathan, K., and S. Hartman, "The Kerberos Version 5 Generic Security Service Application Program Interface (GSS-API) Mechanism: Version 2", RFC 4121, July 2005. โญ
Authors' Addresses โจ
Meet the squad who built this thing ๐ซถ Here's where you can find them:
Clifford Neuman
Information Sciences Institute
University of Southern California
4676 Admiralty Way
Marina del Rey, CA 90292, USA
EMail: bcn@isi.edu
Tom Yu
Massachusetts Institute of Technology
77 Massachusetts Avenue
Cambridge, MA 02139, USA
EMail: tlyu@mit.edu
Sam Hartman
Massachusetts Institute of Technology
77 Massachusetts Avenue
Cambridge, MA 02139, USA
EMail: hartmans-ietf@mit.edu
Kenneth Raeburn
Massachusetts Institute of Technology
77 Massachusetts Avenue
Cambridge, MA 02139, USA
EMail: raeburn@mit.edu
Full Copyright Statement ๐
Copyright (C) The Internet Society (2005).
This document is covered by the rights, licenses, and restrictions in BCP 78. Except as BCP 78 says otherwise, the authors keep all their rights. ๐
The legal bit, verbatim because it matters ๐ญ:
This document and the information contained herein are provided on an
"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
No warranties, no vibes-based guarantees. Read it as-is, bestie. ๐
Intellectual Property ๐ฅ
The IETF doesn't pick a side on whether any IPR (Intellectual Property Rights) or other rights might cover the tech in this doc. It also doesn't say whether you can get a license for it, and it hasn't done its own hunt for those rights either ๐ต๏ธโโ๏ธ For the rules on RFC rights, check BCP 78 and BCP 79.
Got IPR disclosures or license assurances? Those live with the IETF Secretariat, and you can find them in the IETF online IPR repository at http://www.ietf.org/ipr. The same goes for any attempt to get a general license or permission for implementers or users. ๐๏ธ
If you think you've got a copyright, patent, patent application, or other proprietary right that covers tech this standard might need, tell the IETF! Send it to ietf-ipr@ietf.org. Be the helpful one ๐ซถ
Acknowledgement ๐
Funding for the RFC Editor function is currently provided by the Internet Society. Thank you, Internet Society ๐โจ
That's a wrap on RFC 4120, bestie!! ๐๐ฆ๐
๐ฆ where this page comes from
- ietf: rfc4120 2005-07
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms