krb5 commit: Implement 32-bit keytab kvno extension

Greg Hudson ghudson at mit.edu
Wed Apr 15 00:40:39 EDT 2015


https://github.com/krb5/krb5/commit/54b4ccf510b67140caec76b12fff4b30462e7e50
commit 54b4ccf510b67140caec76b12fff4b30462e7e50
Author: Greg Hudson <ghudson at mit.edu>
Date:   Wed Mar 4 14:43:00 2015 -0500

    Implement 32-bit keytab kvno extension
    
    Heimdal and Shishi support a 32-bit kvno at the end of a keytab entry,
    overriding the 8-bit version if present.  Implement this in the FILE
    keytab type and document it in keytab_file_format.rst.
    
    ticket: 7532

 doc/formats/keytab_file_format.rst |   10 +++++-----
 src/lib/krb5/keytab/kt_file.c      |   26 +++++++++++++++++++++++++-
 2 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/doc/formats/keytab_file_format.rst b/doc/formats/keytab_file_format.rst
index 10caf95..92f3733 100644
--- a/doc/formats/keytab_file_format.rst
+++ b/doc/formats/keytab_file_format.rst
@@ -31,6 +31,7 @@ the key entry.  Key entries use the following informal grammar::
         enctype (16 bits)
         key length (32 bits)
         key contents
+        key version (32 bits) [in release 1.14 and later]
 
     principal ::=
         count of components (32 bits) [includes realm in version 1]
@@ -44,8 +45,7 @@ the key entry.  Key entries use the following informal grammar::
         length (16 bits)
         value (length bytes)
 
-Some implementations of Kerberos recognize a 32-bit key version at the
-end of an entry, if the record length is at least 4 bytes longer than
-the entry and the value of those 32 bits is not 0.  If present, this
-key version supersedes the 8-bit key version.  MIT krb5 does not yet
-implement this extension.
+The 32-bit key version overrides the 8-bit key version.  To determine
+if it is present, the implementation must check that at least 4 bytes
+remain in the record after the other fields are read, and that the
+value of the 32-bit integer contained in those bytes is non-zero.
diff --git a/src/lib/krb5/keytab/kt_file.c b/src/lib/krb5/keytab/kt_file.c
index 722ebe6..a54a06b 100644
--- a/src/lib/krb5/keytab/kt_file.c
+++ b/src/lib/krb5/keytab/kt_file.c
@@ -1185,10 +1185,11 @@ krb5_ktfileint_internal_read_entry(krb5_context context, krb5_keytab id, krb5_ke
     krb5_int16 princ_size;
     register int i;
     krb5_int32 size;
-    krb5_int32 start_pos;
+    krb5_int32 start_pos, pos;
     krb5_error_code error;
     char        *tmpdata;
     krb5_data   *princ;
+    uint32_t    vno32;
 
     KTCHECKLOCK(id);
     memset(ret_entry, 0, sizeof(krb5_keytab_entry));
@@ -1367,6 +1368,20 @@ krb5_ktfileint_internal_read_entry(krb5_context context, krb5_keytab id, krb5_ke
         goto fail;
     }
 
+    /* Check for a 32-bit kvno extension if four or more bytes remain. */
+    pos = ftell(KTFILEP(id));
+    if (pos - start_pos + 4 <= size) {
+        if (!fread(&vno32, sizeof(vno32), 1, KTFILEP(id))) {
+            error = KRB5_KT_END;
+            goto fail;
+        }
+        if (KTVERSION(id) != KRB5_KT_VNO_1)
+            vno32 = ntohl(vno32);
+        /* If the value is 0, the bytes are just zero-fill. */
+        if (vno32)
+            ret_entry->vno = vno32;
+    }
+
     /*
      * Reposition file pointer to the next inter-record length field.
      */
@@ -1406,6 +1421,7 @@ krb5_ktfileint_write_entry(krb5_context context, krb5_keytab id, krb5_keytab_ent
     krb5_int32  princ_type;
     krb5_int32  size_needed;
     krb5_int32  commit_point = -1;
+    uint32_t    vno32;
     int         i;
 
     KTCHECKLOCK(id);
@@ -1508,6 +1524,13 @@ krb5_ktfileint_write_entry(krb5_context context, krb5_keytab id, krb5_keytab_ent
         goto abend;
     }
 
+    /* 32-bit key version number */
+    vno32 = entry->vno;
+    if (KTVERSION(id) != KRB5_KT_VNO_1)
+        vno32 = htonl(vno32);
+    if (!fwrite(&vno32, sizeof(vno32), 1, KTFILEP(id)))
+        goto abend;
+
     if (fflush(KTFILEP(id)))
         goto abend;
 
@@ -1556,6 +1579,7 @@ krb5_ktfileint_size_entry(krb5_context context, krb5_keytab_entry *entry, krb5_i
     total_size += sizeof(krb5_octet);
     total_size += sizeof(krb5_int16);
     total_size += sizeof(krb5_int16) + entry->key.length;
+    total_size += sizeof(uint32_t);
 
     *size_needed = total_size;
     return retval;


More information about the cvs-krb5 mailing list