skip to content

In Kerberos, how does a principal name for a user differ from one for a service, and what does the realm part fix?

level: middleimportance: should knowfreq 40%

answer

  1. two halves, carried separately
  2. the @ is not a component separator
  3. one component for a user, two for a host service
  4. name type says how to read the components
  5. matching is byte-for-byte, case included

basics

~20 s

A user principal is usually one name component, written user@REALM; a host-based service is two, written service/host@REALM. The realm is a separate field, not a component, and it fixes which KDC's database holds the principal and therefore which long-term key exists for it.

solid answer

~40 s

On the wire a principal identifier is two things: a `PrincipalName`, which is a name type plus an ordered sequence of components, and a `Realm` carried in its own field beside it — `cname` with `crealm` for the client, `sname` with the request's `realm` for the server. The `@` in the familiar string form is a rendering convention, not a component separator. A user is typically one component of name type **NT-PRINCIPAL (1)**; a host-based service is two components, `service/host`, of type **NT-SRV-HST (3)**; a unique instance such as the ticket-granting service uses **NT-SRV-INST (2)**. Components are matched byte for byte, so case matters. The realm decides which KDC can name the principal at all, and thus which long-term key can seal a ticket for it.

code

asn1 · 26 lines
asn1
PrincipalName ::= SEQUENCE {
        name-type       [0] Int32,
        name-string     [1] SEQUENCE OF KerberosString
}

Realm ::= KerberosString

-- [email protected]
--   cname  = { name-type 1 (NT-PRINCIPAL), name-string { "mkeita" } }
--   crealm = "MET.EXAMPLE"

-- archive/[email protected]
--   sname  = { name-type 3 (NT-SRV-HST),
--              name-string { "archive", "store1.met.example" } }
--   realm  = "MET.EXAMPLE"

KDC-REQ-BODY ::= SEQUENCE {
        kdc-options     [0] KDCOptions,
        cname           [1] PrincipalName OPTIONAL,
        realm           [2] Realm,          -- the realm of the server named below
        sname           [3] PrincipalName OPTIONAL,
        till            [5] KerberosTime,
        nonce           [7] UInt32,
        etype           [8] SEQUENCE OF Int32
        -- remaining fields omitted
}

go deeper

for a junior

Learn the two written forms and what they are for: user@REALM for a person, service/host@REALM for a server. Knowing that the second half after the @ is the realm is enough at this stage.

for a middle

Explain that the realm is a separate field rather than a component, say which name type goes with which shape, and state that lookup is an exact match including case.

for a senior

Bring the failure modes: an alias-derived host component, a realm that does not match the host-naming suffix, and a service registered under a name no client ever constructs.

for a principal

The design question is naming policy across an estate — whether realm names track an existing naming hierarchy, and what a mismatch between host names and realm names costs every integration afterwards.

## A principal identifier is components plus a realm A Kerberos principal identifier has two halves and they are carried separately. The `PrincipalName` holds a **name type** and an ordered **sequence of components**. The realm is a distinct field alongside it. In a request body the client is `cname` plus `crealm`, and the server is `sname` plus the body's `realm`; in a ticket, the server's `realm` and `sname` sit in the clear while the client's `crealm` and `cname` are inside the sealed `EncTicketPart`. The string forms everyone writes — `[email protected]`, `archive/[email protected]` — are a rendering of those fields. The `/` separates components; the `@` introduces the realm, which is not a component. ## The two shapes you meet constantly - **A user**: one component, the account name. Name type **NT-PRINCIPAL (1)**, the general-purpose type for a named principal. - **A host-based service**: two components, the service name and the host it runs on — `archive/store1.met.example`. Name type **NT-SRV-HST (3)**, the type whose second component is a host name. This is the form a client constructs when it wants to talk to a specific server, and getting it wrong is the commonest cause of an unknown-server error. | name type | shape | typical use | |---|---|---| | `NT-PRINCIPAL (1)` | one component | a user principal in the realm | | `NT-SRV-INST (2)` | service plus unique instance | the ticket-granting service, `krbtgt/REALM` | | `NT-SRV-HST (3)` | service plus host name | a service reached at a named host | | `NT-ENTERPRISE (10)` | a name in another form | a name the KDC must map to a principal before use | `NT-ENTERPRISE (10)` is the odd one: it carries an identifier a user recognises that is not itself a principal name, and the KDC is expected to resolve it. A client that is willing to be told a different name back sets the **`canonicalize` KDC option (bit 15)** on the request, which signals that it can accept the name the KDC substitutes. ## Matching is exact, which is stricter than people expect The database lookup is a comparison of components, byte for byte: - **Case is significant.** `archive/Store1.met.example` and `archive/store1.met.example` are different principals. Only one of them is likely to exist. - **The host component is a name, not an address.** If the client resolves a server through an alias and builds the principal from the alias, it asks for a principal that may not be registered, even though the connection reaches the right machine. - **The realm is not inferred from the network.** It is carried explicitly; a client configured with the wrong realm asks the wrong KDC, whatever host it connects to. - **A trailing or missing component changes the name.** `[email protected]` is not `archive/[email protected]`. ## What the realm actually fixes Calling a realm "the domain-shaped part at the end" misses what it decides. A realm is: 1. **A namespace.** Within it, a component sequence names exactly one principal. Two realms may each hold `archive/store1.met.example` and they are different principals. 2. **A key set.** The realm's KDC holds a long-term key for each of its principals. A ticket for a principal can only be sealed by a KDC that holds that principal's key. 3. **A trust boundary.** Because keys are per-realm, reaching a principal in another realm is not a matter of presenting better credentials; it needs a key shared between the two realms. Realm names are conventionally written in upper case, and where they are derived from a domain-style naming hierarchy that convention is what visually distinguishes `MET.EXAMPLE` the realm from `met.example` the host-naming suffix. They are not required to match the host names inside them, and in estates that grew by merger they frequently do not — which is exactly when the difference between a host component and a realm stops being pedantry. ## Why interviewers ask this Because naming is where Kerberos deployments actually break, and because the two halves fail differently: a wrong or unknown **client** name is a sign-in problem in the user's own realm, while a wrong or unknown **server** name is a per-service problem that shows up only for the one service nobody registered under the name the client constructs.

  • How does a KDC treat two principal names that differ only in the case of a component?
    As two different names. Component matching is byte-for-byte, so one of them simply does not exist in the database and the request for it fails as an unknown principal. This is why a client that builds a service name from user input, or from a case-mangled host lookup, fails against a service that is genuinely registered.
  • What is name type NT-ENTERPRISE (10) for, and what does a client have to be willing to accept to use one?
    It carries an identifier a user knows that is not itself a principal name, leaving the KDC to map it to one. A client that uses it must be prepared to be handed back a different name than it asked with, which it signals by setting the canonicalize KDC option (bit 15) on the request.

saying these in an interview costs you the question

  • Says principal names are case-insensitive so the host component's case is irrelevant.
  • Treats the realm as display text the KDC ignores when looking a principal up.
  • Claims a service principal is written with one component, exactly like a user's.
  • Believes the realm is carried as the last component of the name-string sequence.
  • Assumes every principal in a realm uses name type NT-PRINCIPAL (1).