Help us shape the future of Go! Take the 2026 Go Developer Survey

kdc

package module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 4, 2026 License: BSD-3-Clause Imports: 23 Imported by: 1

README

kdc

Go Reference License CI

Issue Kerberos tickets from a go-authn/directory, in Go, with no cgo.

srv, err := kdc.New(kdc.Config{
    Realm:    "EXAMPLE.ORG",
    People:   people,          // sqldir, hcldir — anything holding passwords
    Services: keytab,          // krbtgt/REALM, and a key per service
})
go srv.ServeUDP(pc)
go srv.ServeTCP(ln)

This is the issuing half. go-authn/krb5 is the accepting half, and a service that only verifies tickets needs this package not at all.

⛔ What can and cannot back a realm

A KDC must decrypt the client's pre-authentication with that person's long-term key. It follows that only a source holding the password can back one: sqldir and hcldir can, and a Verifier — a bind against somebody else's LDAP, or a hash comparison — cannot, however well it answers "is this the right password".

That is a property of Kerberos rather than a limitation here. This package refuses at configuration time, so an operator is told before the first kinit rather than after.

What it implements

AS-REQ and TGS-REQ, over UDP and TCP, with encrypted-timestamp pre-authentication required.

Not implemented: cross-realm referrals, PKINIT, FAST, renewable or postdated tickets, and any kadmin protocol. Keys come from the directory and from a keytab, and they change where they live.

One encryption type

Tickets and keys are made with aes256-cts-hmac-sha1-96 (etype 18), and nothing else is issued — the weaker types a client may offer are refused even when asked for. It is what every Kerberos implementation in use agrees on, so this costs no interoperability that a modern client would notice.

The realm says so rather than leaving it to be discovered. The KRB-ERROR that demands pre-authentication carries an ETYPE-INFO2 hint naming that etype and the salt — which is where a client looks before it derives a key, and why the exchange starts with a refusal rather than a reply.

A client that insists on something else fails pre-authentication and is answered KDC_ERR_PREAUTH_FAILED — the same code a wrong password gets, because an unauthenticated caller is told no more than no. The server log records both etypes, its own and the client's, so an operator can tell a mismatched cipher from a mistyped password.

The judge

MIT's own kinit and kvno. No MIT KDC is involved — the keytab is built in Go and only the client is borrowed, which is the point: a realm judged by a client it did not write.

go test ./...          # KDC_REQUIRE_JUDGE=1 turns a missing MIT into a failure

The tests also pin the refusals a real client never triggers: a timestamp under the wrong key, one from an hour ago, a three-byte cipher, a service asked for straight from an AS-REQ, and a realm backed by a verifier.

Licence

BSD-3-Clause.

Documentation

Overview

Package kdc issues Kerberos tickets from a go-authn/directory.

It is the other half of github.com/go-authn/krb5, which accepts them. A service that verifies tickets needs no KDC and should not import this; a site that wants its own realm, backed by the same people its LDAP and its NFS already know, does.

What it can and cannot be backed by

A KDC must DECRYPT the client's pre-authentication with that person's long-term key. It follows that only a directory source holding the PASSWORD can back one: sqldir and hcldir can, and a directory.Verifier — a bind against somebody else's LDAP, or a hash comparison — CANNOT, however well it answers "is this the right password".

That is a property of Kerberos rather than a limitation here, and this package refuses at configuration time rather than at the first kinit.

What it implements

AS-REQ and TGS-REQ over UDP and TCP, with encrypted-timestamp pre-authentication required. It does not implement cross-realm referrals, PKINIT, FAST, renewable or postdated tickets, or a kadmin protocol: keys come from the directory and from a keytab, and change where they live.

One encryption type

Tickets and keys are made with aes256-cts-hmac-sha1-96 (etype 18) and nothing else is issued, even when a client offers something weaker. The KRB-ERROR that demands pre-authentication carries an ETYPE-INFO2 hint naming that etype and the salt, so a client learns what to derive its key with rather than guessing. A client that insists on another type is answered KDC_ERR_PREAUTH_FAILED, the same code a wrong password gets; the server log records both etypes so an operator can tell the two apart.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNoRealm reports a configuration with no realm name.
	ErrNoRealm = errors.New("kdc: no realm")
	// ErrNoPeople reports one with nowhere to look up users.
	ErrNoPeople = errors.New("kdc: no directory")
	// ErrNoServices reports one with no keytab, which means no krbtgt key
	// and therefore nothing to sign a TGT with.
	ErrNoServices = errors.New("kdc: no keytab")
	// ErrNoTGTKey reports a keytab without krbtgt/REALM@REALM. A KDC without
	// it can authenticate somebody and then have nothing to hand them.
	ErrNoTGTKey = errors.New("kdc: the keytab has no krbtgt key for this realm")
)

Errors a configuration can have.

View Source
var ErrClosed = errors.New("kdc: server closed")

ErrClosed is returned by ServeUDP and ServeTCP after Close.

View Source
var ErrNotAPerson = errors.New("kdc: not a user principal")

ErrNotAPerson reports a principal that is not a single name — a service like nfs/host asking for a TGT of its own. Services authenticate from a keytab, not from this directory.

Functions

This section is empty.

Types

type Config

type Config struct {
	// Realm is the realm name, conventionally the DNS domain in capitals.
	Realm string

	// People is where users come from. It must publish passwords; see the
	// package comment for why a verifier cannot serve Kerberos.
	People directory.Source

	// Services holds the keys for service principals, including the
	// krbtgt/REALM@REALM this KDC issues its own tickets under. It is the
	// same file a service like an NFS server reads, which is the point: one
	// keytab, two readers, no third place for a key to drift.
	Services *keytab.Keytab

	// Lifetime caps a ticket. Zero means ten hours, which is MIT's default.
	Lifetime time.Duration

	// MaxSkew is how far a client's clock may be from this one. Zero means
	// five minutes, which is what every Kerberos implementation assumes.
	MaxSkew time.Duration

	// Logf, when set, is told why a request was refused.
	//
	// It exists because the protocol cannot say: a client is given an error
	// CODE, and "pre-authentication failed" covers a wrong password, a wrong
	// salt, a clock an hour out and a malformed message. Only this side can
	// tell them apart, and only to an operator.
	//
	// ⛔ It is never given a password, a key, or a decrypted anything.
	Logf func(format string, args ...any)
}

Config describes one realm.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server answers Kerberos requests for one realm.

The zero value is not usable; use New.

func New

func New(cfg Config) (*Server, error)

New checks a configuration and returns a server for it.

It refuses a realm it could not serve — no keytab, no krbtgt key, a directory that publishes no passwords — rather than starting and failing at the first kinit, where the error reaches a person who cannot fix it.

func (*Server) Close

func (s *Server) Close() error

Close stops the server and drops what it is serving.

func (*Server) ServeTCP

func (s *Server) ServeTCP(ln net.Listener) error

ServeTCP answers connections. Each carries a four-byte length in front of every message, which UDP does not (RFC 4120 §7.2.2).

func (*Server) ServeUDP

func (s *Server) ServeUDP(pc net.PacketConn) error

ServeUDP answers datagrams. It is the transport a client tries first: MIT's kinit sends UDP and falls back to TCP only when the reply does not fit or the KDC says so.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL