-- $Id$
HDB DEFINITIONS ::=
BEGIN

IMPORTS EncryptionKey, KerberosTime, Principal FROM krb5;

hdb_db_format INTEGER ::= 2	-- format of database, 
				-- update when making changes

-- these must have the same value as the pa-* counterparts
hdb-pw-salt	INTEGER	::= 3
hdb-afs3-salt	INTEGER	::= 10

Salt ::= SEQUENCE {
	type[0]		INTEGER (0..4294967295),
	salt[1]		OCTET STRING,
	opaque[2]	OCTET STRING OPTIONAL
}

Key ::= SEQUENCE {
	mkvno[0]	INTEGER (0..4294967295) OPTIONAL, -- master key version number
	key[1]		EncryptionKey,
	salt[2]		Salt OPTIONAL
}

Event ::= SEQUENCE {
	time[0]		KerberosTime,
	principal[1]	Principal OPTIONAL
}

HDBFlags ::= BIT STRING {
	initial(0),			-- require as-req
	forwardable(1),			-- may issue forwardable
	proxiable(2),			-- may issue proxiable
	renewable(3),			-- may issue renewable
	postdate(4),			-- may issue postdatable
	server(5),			-- may be server
	client(6),			-- may be client
	invalid(7),			-- entry is invalid
	require-preauth(8),		-- must use preauth
	change-pw(9),			-- change password service
	require-hwauth(10),		-- must use hwauth
	ok-as-delegate(11),		-- as in TicketFlags
	user-to-user(12),		-- may use user-to-user auth
	immutable(13),			-- may not be deleted
	trusted-for-delegation(14),	-- Trusted to print forwardabled tickets
	allow-kerberos4(15),		-- Allow Kerberos 4 requests
	allow-digest(16),		-- Allow digest requests
	locked-out(17),			-- Account is locked out,
					-- authentication will be denied
	require-pwchange(18),		-- require a passwd change

	materialize(19),		-- store even if within virtual namespace
	virtual-keys(20),		-- entry     stored; keys mostly derived
	virtual(21),			-- entry not stored; keys always derived
	synthetic(22),			-- entry not stored; for PKINIT
	no-auth-data-reqd(23),		-- omit PAC from service tickets
	auth-data-reqd(24),		-- include PAC in service tickets

	force-canonicalize(30),		-- force the KDC to return the canonical
					-- principal irrespective of the setting
					-- of the canonicalize KDC option
                                        -- (principals cannot have this flag
                                        -- set when stored into the HDB)
	do-not-store(31)		-- Not to be modified and stored in HDB
}

GENERATION ::= SEQUENCE {
	time[0]		KerberosTime,			-- timestamp
	usec[1]		INTEGER (0..4294967295),	-- microseconds
	gen[2]		INTEGER (0..4294967295)		-- generation number
}

HDB-Ext-PKINIT-acl ::= SEQUENCE OF SEQUENCE {
	subject[0]	UTF8String,
	issuer[1]	UTF8String OPTIONAL,
	anchor[2]	UTF8String OPTIONAL
}

HDB-Ext-PKINIT-hash ::= SEQUENCE OF SEQUENCE {
	digest-type[0] OBJECT IDENTIFIER,
	digest[1] OCTET STRING
}

HDB-Ext-PKINIT-cert ::= SEQUENCE OF SEQUENCE {
	cert[0] OCTET STRING
}

HDB-Ext-Constrained-delegation-acl ::= SEQUENCE OF Principal

-- hdb-ext-referrals ::= PA-SERVER-REFERRAL-DATA

HDB-Ext-Lan-Manager-OWF ::= OCTET STRING

HDB-Ext-Password ::= SEQUENCE {
	mkvno[0]	INTEGER (0..4294967295) OPTIONAL, -- master key version number
	password	OCTET STRING
}

HDB-Ext-Aliases ::= SEQUENCE {
	case-insensitive[0]	BOOLEAN, -- case insensitive name allowed
	aliases[1]		SEQUENCE OF Principal -- all names, inc primary
}

Keys ::= SEQUENCE OF Key

HDB_keyset ::= SEQUENCE {
	kvno[0]		INTEGER (0..4294967295),
	keys[1]		Keys,
	set-time[2]	KerberosTime OPTIONAL,	-- time this keyset was created/set
	...
}

HDB-Ext-KeySet ::= SEQUENCE OF HDB_keyset

--
-- We need a function of current (or given, but it will always be current) time
-- and a base hdb_entry or its HDB-Ext-KeyRotation and service ticket lifetime,
-- that outputs a sequence of {kvno, set_time, max_life} representing past keys
-- (up to one per past and current KeyRotation), current keys (for the current
-- KeyRotation), up to one future key for the current KeyRotation, and up to
-- one future key for the _next_ (future) KeyRotation if there is one.
--
-- We have to impose constraints on new KeyRotation elements of
-- HDB-Ext-KeyRotation.
--
-- So virtual keysets (keytabs) will contain:
--
--  - up to one past   keyset for all KeyRotation periods that are "applicable"
--  - the   current    keyset for all KeyRotation periods that are "applicable"
--  - up to one future keyset for all KeyRotation periods that are "applicable"
--
-- An applicable KeyRotation period is:
--
--  - the KeyRotation whose `epoch` is a) in the past and b) nearest to the
--    current time - we call this the current KeyRotation
--  - a   KeyRotation whose `epoch` is nearest but in the past of the current
--    one
--  - a   KeyRotation whose `epoch` is nearest but in the future of the current
--    one
--
-- A service principal's max ticket life will be bounded by half the current
-- key rotation period.
--
-- Note: There can be more than one applicable past KeyRotation, and more than
--       one applicable KeyRotation.  We might not want to permit this.
--       However, it's probably easier to permit it, though we might not test
--       end-to-end.
--
-- Testing:
--
--  - We should have standalone unit tests for all these pure functions.
--
--  - We should have a test that uses kadm5 and GSS to test against a KDC using
--    small key rotation periods on the order of seconds, with back-off in case
--    of losing a race condition.
--
KeyRotationFlags ::= BIT STRING {
	deleted(0),	-- if set on a materialized principal, this will mean
			-- the principal does not exist
			-- if set on a namespace, this will mean that
			-- only materialized principal below it exist
	parent(1) 	-- if set on a materialized principal, this will mean
			-- that the keys for kvnos in this KeyRotation spec
			-- will be derived from the parent's base keys and
                        -- corresponding KeyRotation spec
                        -- if set on a namespace, this flag will be ignored
                        -- (or we could support nested namespaces?)
}
KeyRotation ::= SEQUENCE {
	-- base-kvno is always computed at set time and set for the principal,
	-- and is never subject to admin choice.  The base-kvno is that of the
	-- current kvno at that period's `from` given the previous period.
	--
	-- Also, insertion of KeyRotation elements before existing ones (in
	-- time) is never permitted, and all new KeyRotation elements must be
	-- in the future relative to existing ones.
	--
	-- HDB-Ext-KeyRotation will always be sorted (as stored) by `from`, in
	-- descending order.
	--
	-- Max service ticket lifetime will be constrained to no more than half
        -- the period of the the applicable KeyRotation elements.
	--
	flags[0]	KeyRotationFlags,	
	epoch[1]	KerberosTime,		-- start of this period
	period[2]	INTEGER(0..4294967295), -- key rotation seconds
	base-kvno[3]	INTEGER(0..4294967295), -- starting from this kvno
	base-key-kvno[4]INTEGER(0..4294967295), -- kvno of base-key
	...
}

HDB-Ext-KeyRotation ::= SEQUENCE SIZE (1..3) OF KeyRotation

HDB-extension ::= SEQUENCE {
        mandatory[0]    BOOLEAN,        -- kdc MUST understand this extension,
                                        --   if not the whole entry must
                                        --   be rejected
        data[1]          CHOICE {
	        pkinit-acl[0]			HDB-Ext-PKINIT-acl,
	        pkinit-cert-hash[1]  		HDB-Ext-PKINIT-hash,
		allowed-to-delegate-to[2]       HDB-Ext-Constrained-delegation-acl,
--		referral-info[3]		HDB-Ext-Referrals,
		lm-owf[4]			HDB-Ext-Lan-Manager-OWF,
		password[5]			HDB-Ext-Password,
		aliases[6]			HDB-Ext-Aliases,
		last-pw-change[7]		KerberosTime,
	        pkinit-cert[8]  		HDB-Ext-PKINIT-cert,
	        hist-keys[9]			HDB-Ext-KeySet,
		hist-kvno-diff-clnt[10]		INTEGER (0..4294967295),
		hist-kvno-diff-svc[11]		INTEGER (0..4294967295),
	        policy[12]			UTF8String,
		principal-id[13]		INTEGER(-9223372036854775808..9223372036854775807),
		key-rotation[14]		HDB-Ext-KeyRotation,
		krb5-config[15]		        OCTET STRING,
		...
	},
	...
}

HDB-extensions ::= SEQUENCE OF HDB-extension

-- Just for convenience, for encoding this as TL data in lib/kadm5
HDB-EncTypeList ::= SEQUENCE OF INTEGER (0..4294967295)

HDB_entry ::= SEQUENCE {
	principal[0]	Principal  OPTIONAL, -- this is optional only 
					     -- for compatibility with libkrb5
	kvno[1]		INTEGER (0..4294967295),
	keys[2]		Keys,
	created-by[3]	Event,
	modified-by[4]	Event OPTIONAL,
	valid-start[5]	KerberosTime OPTIONAL,
	valid-end[6]	KerberosTime OPTIONAL,
	pw-end[7]	KerberosTime OPTIONAL,
	max-life[8]	INTEGER (-2147483648..2147483647) OPTIONAL,
	max-renew[9]	INTEGER (-2147483648..2147483647) OPTIONAL,
	flags[10]	HDBFlags,
	etypes[11]	HDB-EncTypeList OPTIONAL,
	generation[12]	GENERATION OPTIONAL,
        extensions[13]  HDB-extensions OPTIONAL
}

HDB_entry_alias ::= [APPLICATION 0] SEQUENCE {
	principal[0]	Principal  OPTIONAL
}

HDB-EntryOrAlias ::= CHOICE {
        entry       HDB_entry,
        alias       HDB_entry_alias
}

END
