]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Implement 32-bit keytab kvno extension
authorGreg Hudson <ghudson@mit.edu>
Wed, 4 Mar 2015 19:43:00 +0000 (14:43 -0500)
committerGreg Hudson <ghudson@mit.edu>
Wed, 15 Apr 2015 04:37:38 +0000 (00:37 -0400)
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
src/lib/krb5/keytab/kt_file.c

index 10caf95124e04180484ba7439f6d2ee1381701f2..92f37331e0593a7a7ff4991510f7c8d70e5053ef 100644 (file)
@@ -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.
index 722ebe6fb60e2037ecaa364aaa211801c90262ec..a54a06b32080bccf0ad715473af309c94ea4ef70 100644 (file)
@@ -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;