krb5 commit: Add database format documentation

ghudson at mit.edu ghudson at mit.edu
Thu Feb 27 16:33:12 EST 2025


https://github.com/krb5/krb5/commit/16f8b9821c6306e38c855cbfcab9d0ef309d081f
commit 16f8b9821c6306e38c855cbfcab9d0ef309d081f
Author: Greg Hudson <ghudson at mit.edu>
Date:   Mon Jan 20 22:47:54 2025 -0500

    Add database format documentation
    
    Add a new file under doc/formats documenting the dump format, tl-data
    formats, alias principals, and the DB2 and LMDB principal and policy
    formats.
    
    Also correct some formatting in cookie.rst, changing a nested list to
    a code block for consistency with other documentation of binary
    formats.
    
    ticket: 9164 (new)

 doc/formats/cookie.rst           |  38 +++-
 doc/formats/database_formats.rst | 459 +++++++++++++++++++++++++++++++++++++++
 doc/formats/index.rst            |   1 +
 3 files changed, 486 insertions(+), 12 deletions(-)

diff --git a/doc/formats/cookie.rst b/doc/formats/cookie.rst
index e32365daa..3c7d0b03c 100644
--- a/doc/formats/cookie.rst
+++ b/doc/formats/cookie.rst
@@ -1,3 +1,5 @@
+.. highlight:: abnf
+
 KDC cookie format
 =================
 
@@ -42,7 +44,9 @@ principal name with realm, marshalled according to :rfc:`1964` section
 2.1.1.
 
 The plain text of the encrypted part of a cookie is the DER encoding
-of the following ASN.1 type::
+of the following ASN.1 type:
+
+.. code-block:: bnf
 
     SecureCookie ::= SEQUENCE {
         time     INTEGER,
@@ -63,17 +67,27 @@ SPAKE cookie format (version 1)
 -------------------------------
 
 Inside the SecureCookie wrapper, a data value of type 151 contains
-state for SPAKE pre-authentication.  This data is the concatenation of
-the following:
-
-* a two-byte big-endian version number with the value 1
-* a two-byte big-endian stage number
-* a four-byte big-endian group number
-* a four-byte big-endian length and data for the SPAKE value
-* a four-byte big-endian length and data for the transcript hash
-* zero or more second factor records, each consisting of:
-  - a four-byte big-endian second-factor type
-  - a four-byte big-endian length and data
+state for SPAKE pre-authentication.  This data has the following
+binary format with big-endian integer encoding:
+
+.. code-block:: bnf
+
+    cookie ::=
+        version (16 bits) [with the value 1]
+        stage number (16 bits)
+        group number (32 bits)
+        SPAKE value length (32 bits)
+        SPAKE value
+        transcript hash length (32 bits)
+        transcript hash
+        second factor record 1 (factor-record)
+        second factor record 2 (factor-record)
+        ...
+
+    factor-record ::=
+        second factor type (32 bits)
+        second factor data length (32 bits)
+        second factor data
 
 The stage value is 0 if the cookie was sent with a challenge message.
 Otherwise it is 1 for the first encdata message sent by the KDC during
diff --git a/doc/formats/database_formats.rst b/doc/formats/database_formats.rst
new file mode 100644
index 000000000..fca5979c1
--- /dev/null
+++ b/doc/formats/database_formats.rst
@@ -0,0 +1,459 @@
+Kerberos Database (KDB) Formats
+===============================
+
+Dump format
+-----------
+
+Files created with the :ref:`kdb5_util(8)` **dump** command begin with
+a versioned header "kdb5_util load_dump version 7".  This version has
+been in use since MIT krb5 release 1.11; some previous versions are
+supported but are not described here.
+
+Each subsequent line of the dump file contains one or more
+tab-separated fields describing either a principal entry or a policy
+entry.  The fields of a principal entry line are:
+
+* the word "princ"
+* the string "38" (this was originally a length field)
+* the length of the principal name in string form
+* the decimal number of tag-length data elements
+* the decimal number of key-data elements
+* the string "0" (this was originally an extension length field)
+* the principal name in string form
+* the principal attributes as a decimal number; when converted to
+  binary, the bits from least significant to most significant are:
+
+  - disallow_postdated
+  - disallow_forwardable
+  - disallow_tgt_based
+  - disallow_renewable
+  - disallow_proxiable
+  - disallow_dup_skey
+  - disallow_all_tix
+  - requires_preauth
+  - requires_hwauth
+  - requires_pwchange
+  - disallow_svr
+  - pwchange_service
+  - support_desmd5
+  - new_princ
+  - ok_as_delegate
+  - ok_to_auth_as_delegate
+  - no_auth_data_required
+  - lockdown_keys
+
+* the maximum ticket lifetime, as a decimal number of seconds
+* the maximum renewable ticket lifetime, as a decimal number of seconds
+* the principal expiration time, as a decimal POSIX timestamp
+* the password expiration time, as a decimal POSIX timestamp
+* the last successful authentication time, as a decimal POSIX
+  timestamp
+* the last failed authentication time, as a decimal POSIX timestamp
+* the decimal number of failed authentications since the last
+  successful authentication time
+* for each tag-length data value:
+
+  - the tag value in decimal
+  - the length in decimal
+  - the data as a lowercase hexadecimal byte string, or "-1" if the length is 0
+
+* for each key-data element:
+
+  - the string "2" if this element has non-normal salt type, "1"
+    otherwise
+  - the key version number of this element
+  - the encryption type
+  - the length of the encrypted key value
+  - the encrypted key as a lowercase hexadecimal byte string
+  - if this element has non-normal salt type:
+
+    - the salt type
+    - the length of the salt data
+    - the salt data as a lowercase hexadecimal byte string, or the
+      string "-1" if the salt data length is 0
+
+* the string "-1;" (this was originally an extension field)
+
+The fields of a policy entry line are:
+
+* the string "policy"
+* the policy name
+* the minimum password lifetime as a decimal number of seconds
+* the maximum password lifetime as a decimal number of seconds
+* the minimum password length, in decimal
+* the minimum number of character classes, in decimal
+* the number of historical keys to be stored, in decimal
+* the policy reference count (no longer used)
+* the maximum number of failed authentications before lockout
+* the time interval after which the failed authentication count is
+  reset, as a decimal number of seconds
+* the lockout duration, as a decimal number of seconds
+* the required principal attributes, in decimal (currently unenforced)
+* the maximum ticket lifetime as a decimal number of seconds
+  (currently unenforced)
+* the maximum renewable lifetime as a decimal number of seconds
+  (currently unenforced)
+* the allowed key/salt types, or "-" if unrestricted
+* the number of tag-length values
+* for each tag-length data value:
+
+  - the tag value in decimal
+  - the length in decimal
+  - the data as a lowercase hexadecimal byte string, or "-1" if the
+    length is 0
+
+
+Tag-length data formats
+-----------------------
+
+The currently defined tag-length data types are:
+
+* (1) last password change: a four-byte little-endian POSIX timestamp
+  giving the last password change time
+* (2) last modification data: a four-byte little-endian POSIX
+  timestamp followed by a zero-terminated principal name in string
+  form, giving the time of the last principal change and the principal
+  who performed it
+* (3) kadmin data: the XDR encoding of a per-principal kadmin data
+  record (see below)
+* (8) master key version: a two-byte little-endian integer containing
+  the master key version used to encrypt this principal's key data
+* (9) active kvno: see below
+* (10) master key auxiliary data: see below
+* (11) string attributes: one or more iterations of a zero-terminated
+  string key followed by a zero-terminated string value
+* (12) alias target principal: a zero-terminated principal name in
+  string form
+* (255) LDAP object information: see below
+* (768) referral padata: a DER-encoded PA-SVR-REFERRAL-DATA to be sent
+  to a TGS-REQ client within encrypted padata (see Appendix A of
+  :rfc:`1606`)
+* (1792) last admin unlock: a four-byte little-endian POSIX timestamp
+  giving the time of the last administrative account unlock
+* (32767) database arguments: a zero-terminated key=value string (may
+  appear multiple times); used by the kadmin protocol to
+  communicate -x arguments to kadmind
+
+Per-principal kadmin data
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Per-principal kadmin data records use a modified XDR encoding of the
+kadmin_data type defined as follows:
+
+.. code-block:: c
+
+    struct key_data {
+        int numfields;
+        unsigned int kvno;
+        int enctype;
+        int salttype;
+        unsigned int keylen;
+        unsigned int saltlen;
+        opaque key<>;
+        opaque salt<>;
+    };
+
+    struct hist_entry {
+        key_data keys<>;
+    };
+
+    struct kadmin_data {
+        int version_number;
+        nullstring policy;
+        int aux_attributes;
+        unsigned int old_key_next;
+        unsigned int admin_history_kvno;
+        hist_entry old_keysets<>;
+    };
+
+The type "nullstring" uses a custom string encoder where the length
+field is zero or the string length plus one; a length of zero
+indicates that no policy object is specified for the principal.  The
+field "version_number" contains 0x12345C01.  The aux_attributes field
+contains the bit 0x800 if a policy object is associated with the
+principal.
+
+Within a key_data record, numfields is 2 if the key data has
+non-normal salt type, 1 otherwise.
+
+Active kvno and master key auxiliary data
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These types only appear in the entry of the master key principal
+(K/M).  They use little-endian binary integer encoding.
+
+The active kvno table determines which master key version is active
+for a given timestamp.  It uses the following binary format:
+
+.. code-block:: bnf
+
+    active-key-version-table ::=
+        version (16 bits) [with the value 1]
+        version entry 1 (key-version-entry)
+        version entry 2 (key-version-entry)
+        ...
+
+    key-version-entry ::=
+        key version (16 bits)
+        timestamp (32 bits) [when this key version becomes active]
+
+The master key auxiliary data record contains copies of the current
+master key encrypted in each older master key.  It uses the following
+binary format:
+
+.. code-block:: bnf
+
+    master-key-aux ::=
+        version (16 bits) [with the value 1]
+        key entry 1 (key-entry)
+        key entry 2 (key-entry)
+        ...
+
+    key-entry ::=
+        old master key version (16 bits)
+        latest master key version (16 bits)
+        latest master key encryption type (16 bits)
+        encrypted key length (16 bits)
+        encrypted key contents
+
+LDAP object information
+~~~~~~~~~~~~~~~~~~~~~~~
+
+This type appears in principal entries retrieved with the LDAP KDB
+module.  The value uses the following binary format, using big-endian
+integer encoding:
+
+.. code-block:: bnf
+
+    ldap-principal-data ::=
+        record 1 (ldap-tl-data)
+        record 2 (ldap-tl-data)
+        ...
+
+    ldap-tl-data ::=
+        type (8 bits)
+        length (16 bits)
+        data
+
+The currently defined ldap-tl-data types are (all integers are
+big-endian):
+
+* (1) principal type: 16 bits containing the value 1, indicating that
+  the LDAP object containing the principal entry is a standalone
+  principal object
+* (2) principal count: 16 bits containing the number of
+  krbPrincipalName values in the LDAP object
+* (3) user DN: the string representation of the distinguished name of
+  the LDAP object
+* (5) attribute mask: 16 bits indicating which Kerberos-specific LDAP
+  attributes are present in the LDAP object (see below)
+* (7) link DN: the string representation of the distinguished name of
+  an LDAP object this object is linked to; may appear multiple times
+
+When converted to binary, the attribute mask bits, from least
+significant to most significant, correspond to the following LDAP
+attributes:
+
+* krbMaxTicketLife
+* krbMaxRenewableAge
+* krbTicketFlags
+* krbPrincipalExpiration
+* krbTicketPolicyReference
+* krbPrincipalAuthInd
+* krbPwdPolicyReference
+* krbPasswordExpiration
+* krbPrincipalKey
+* krbLastPwdChange
+* krbExtraData
+* krbLastSuccessfulAuth
+* krbLastFailedAuth
+* krbLoginFailedCount
+* krbLastAdminUnlock
+* krbPwdHistory
+
+
+Alias principal entries
+-----------------------
+
+To allow aliases to be represented in dump files and within the
+incremental update protocol, the krb5 database library supports the
+concept of an alias principal entry.  An alias principal entry
+contains an alias target principal in its tag-length data, has its
+attributes set to disallow_all_tix, and has zero or empty values for
+all other fields.  The database glue library recognizes alias entries
+and iteratively looks up the alias target up to a depth of 10 chained
+aliases.  (Added in release 1.22.)
+
+
+DB2 principal and policy formats
+--------------------------------
+
+The DB2 KDB module uses the string form of a principal name, with zero
+terminator, as a lookup key for principal entries.  Principal entry
+values use the following binary format with little-endian integer
+encoding:
+
+.. code-block:: bnf
+
+    db2-principal-entry ::=
+        len (16 bits) [always has the value 38]
+        attributes (32 bits)
+        max ticket lifetime (32 bits)
+        max renewable lifetime (32 bits)
+        principal expiration timestamp (32 bits)
+        password expiration timestamp (32 bits)
+        last successful authentication timestamp (32 bits)
+        last failed authentication timestamp (32 bits)
+        failed authentication counter (32 bits)
+        number of tag-length elements (16 bits)
+        number of key-data elements (16 bits)
+        length of string-form principal with zero terminator (16 bits)
+        string-form principal with zero terminator
+        tag-length entry 1 (tag-length-data)
+        tag-length entry 2 (tag-length-data)
+        ...
+        key-data entry 1 (key-data)
+        key-data entry 2 (key-data)
+        ...
+
+    tag-length-data ::=
+        type tag (16 bits)
+        data length (16 bits)
+        data
+
+    key-data ::=
+        salt indicator (16 bits) [1 for default salt, 2 otherwise]
+        key version (16 bits)
+        encryption type (16 bits)
+        encrypted key length (16 bits)
+        encrypted key
+        salt type (16 bits) [omitted if salt indicator is 1]
+        salt data length (16 bits) [omitted if salt indicator is 1]
+        salt data [omitted if salt indicator is 1]
+
+DB2 policy entries reside in a separate database file.  The lookup key
+is the policy name with zero terminator.  Policy entry values use a
+modified XDR encoding of the policy type defined as follows:
+
+.. code-block:: c
+
+    struct tl_data {
+        int type;
+        opaque data<>;
+        tl_data *next;
+    };
+
+    struct policy {
+        int version_number;
+        unsigned int min_life;
+        unsigned int max_pw_life;
+        unsigned int min_length;
+        unsigned int min_classes;
+        unsigned int history_num;
+        unsigned int refcount;
+        unsigned int max_fail;
+        unsigned int failcount_interval;
+        unsigned int lockout_duration;
+        unsigned int attributes;
+        unsigned int max_ticket_life;
+        unsigned int max_renewable_life;
+        nullstring allowed_keysalts;
+        int n_tl_data;
+        tl_data *tag_length_data;
+    };
+
+The type "nullstring" uses the same custom encoder as in the
+per-principal kadmin data.
+
+The field "version_number" contains 0x12345D01, 0x12345D02, or
+0x12345D03 for versions 1, 2, and 3 respectively.  Versions 1 and 2
+omit the fields "attributes" through "tag_length_data".  Version 1
+also omits the fields "max_fail" through "lockout_duration".  Encoding
+uses the lowest version that can represent the policy entry.
+
+The field "refcount" is no longer used and its value is ignored.
+
+
+LMDB principal and policy formats
+---------------------------------
+
+In the LMDB KDB module, principal entries are stored in the
+"principal" database within the main LMDB environment (typically named
+"principal.mdb"), with the exception of lockout-related fields which
+are stored in the "lockout" table of the lockout LMDB environment
+(typically named "principal.lockout.mdb").  For both databases the key
+is the principal name in string form, with no zero terminator.  Values
+in the "principal" database use the following binary format with
+little-endian integer encoding:
+
+.. code-block:: bnf
+
+    lmdb-principal-entry ::=
+        attributes (32 bits)
+        max ticket lifetime (32 bits)
+        max renewable lifetime (32 bits)
+        principal expiration timestamp (32 bits)
+        password expiration timestamp (32 bits)
+        number of tag-length elements (16 bits)
+        number of key-data elements (16 bits)
+        tag-length entry 1 (tag-length-data)
+        tag-length entry 2 (tag-length-data)
+        ...
+        key-data entry 1 (key-data)
+        key-data entry 2 (key-data)
+        ...
+
+    tag-length-data ::=
+        type tag (16 bits)
+        data length (16 bits)
+        data value
+
+    key-data ::=
+        salt indicator (16 bits) [1 for default salt, 2 otherwise]
+        key version (16 bits)
+        encryption type (16 bits)
+        encrypted key length (16 bits)
+        encrypted key
+        salt type (16 bits) [omitted if salt indicator is 1]
+        salt data length (16 bits) [omitted if salt indicator is 1]
+        salt data [omitted if salt indicator is 1]
+
+Values in the "lockout" database have the following binary format with
+little-endian integer encoding:
+
+.. code-block:: bnf
+
+    lmdb-lockout-entry ::=
+        last successful authentication timestamp (32 bits)
+        last failed authentication timestamp (32 bits)
+        failed authentication counter (32 bits)
+
+In the "policy" database, the lookup key is the policy name with no
+zero terminator.  Values in this database use the following binary
+format with little-endian integer encoding:
+
+.. code-block:: bnf
+
+    lmdb-policy-entry ::=
+        minimum password lifetime (32 bits)
+        maximum password lifetime (32 bits)
+        minimum password length (32 bits)
+        minimum character classes (32 bits)
+        number of historical keys (32 bits)
+        maximum failed authentications before lockout (32 bits)
+        time interval to reset failed authentication counter (32 bits)
+        lockout duration (32 bits)
+        required principal attributes (32 bits) [currently unenforced]
+        maximum ticket lifetime (32 bits) [currently unenforced]
+        maximum renewable lifetime (32 bits) [currently unenforced]
+        allowed key/salt type specification length [32 bits]
+        allowed key/salt type specification
+        number of tag-length values (16 bits)
+        tag-length entry 1 (tag-length-data)
+        tag-length entry 2 (tag-length-data)
+        ...
+
+    tag-length-data ::=
+        type tag (16 bits)
+        data length (16 bits)
+        data value
diff --git a/doc/formats/index.rst b/doc/formats/index.rst
index 47dea12fc..819b839de 100644
--- a/doc/formats/index.rst
+++ b/doc/formats/index.rst
@@ -9,3 +9,4 @@ Protocols and file formats
    rcache_file_format
    cookie
    freshness_token
+   database_formats


More information about the cvs-krb5 mailing list