Update to new kadmin protocol
authorPaul Park <pjpark@mit.edu>
Mon, 31 Jul 1995 20:01:40 +0000 (20:01 +0000)
committerPaul Park <pjpark@mit.edu>
Mon, 31 Jul 1995 20:01:40 +0000 (20:01 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@6363 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/kadm/adm_kw_dec.c
src/lib/kadm/adm_kw_enc.c
src/lib/kadm/t_dbentry.c

index 4ee0d7bdd1d0e32b68d629c46c374eda42b15cfb..9258353757422ce0389e1d845a43f427a976e895 100644 (file)
 
 #define        char2int(c)     ((c) - '0')
 \f
-/*
- * string_to_salt_type()       - Convert from salt string to salt type.
- */
-static krb5_int32
-string_to_salt_type(sstring, retp)
-    char               *sstring;
-    krb5_error_code    *retp;
-{
-    krb5_error_code    kret;
-    krb5_int32         stype;
-
-    kret = EINVAL;
-    stype = -1;
-    if (!strcmp(sstring, KRB5_ADM_SALTTYPE_NORMAL))
-       stype = KRB5_KDB_SALTTYPE_NORMAL;
-    else if (!strcmp(sstring, KRB5_ADM_SALTTYPE_V4))
-       stype = KRB5_KDB_SALTTYPE_V4;
-    else if (!strcmp(sstring, KRB5_ADM_SALTTYPE_NOREALM))
-       stype = KRB5_KDB_SALTTYPE_NOREALM;
-    else if (!strcmp(sstring, KRB5_ADM_SALTTYPE_ONLYREALM))
-       stype = KRB5_KDB_SALTTYPE_ONLYREALM;
-    else if (!strcmp(sstring, KRB5_ADM_SALTTYPE_SPECIAL))
-       stype = KRB5_KDB_SALTTYPE_SPECIAL;
-
-    if (stype != -1)
-       kret = 0;
-
-    *retp = kret;
-    return(stype);
-}
-\f
 /*
  * keyword_value()     - Find index of keyword value if keyword is present.
  *
@@ -200,31 +169,59 @@ decode_kw_gentime(dataentp, keyword, gtimep)
 }
 \f
 /*
- * decode_kw_salttype()        - Decode a keyword=<salttype> pair and fill in the
- *                       salt type values if the pair is present.
+ * decode_kw_tagged()  - Decode a keyword=<taglist>...<data> list and return
+ *                       the values of the tags and the data if the list is
+ *                       present.
  */
 static krb5_error_code
-decode_kw_salttype(dataentp, keyword, dbentp)
+decode_kw_tagged(dataentp, keyword, ntags, taglist, lenp, datap)
     krb5_data          *dataentp;
     char               *keyword;
-    krb5_db_entry      *dbentp;
+    krb5_int32         ntags;
+    krb5_int32         *taglist;
+    size_t             *lenp;
+    krb5_octet         **datap;
 {
     krb5_error_code    kret;
-    char               *saltstring;
-    char               *sentp;
+    off_t              valueoff;
+    size_t             len2copy;
+    unsigned char      *cp, *ep;
+    int                        i;
 
-    saltstring = (char *) NULL;
-    if (!(kret = decode_kw_string(dataentp, keyword, &saltstring))) {
-       kret = EINVAL;
-       if (sentp = strchr(saltstring, (int) ',')) {
-           *sentp = '\0';
-           sentp++;
-       }
-       dbentp->salt_type = string_to_salt_type(saltstring, &kret);
-       if (!kret && sentp) {
-           dbentp->alt_salt_type = string_to_salt_type(sentp, &kret);
+    kret = ENOENT;
+    if ((valueoff = keyword_value(dataentp, keyword, 1)) >= 0) {
+       /*
+        * Blast through the tags.
+        */
+       kret = 0;
+       cp = (unsigned char *) &dataentp->data[valueoff];
+       ep = (unsigned char *) &dataentp->data[dataentp->length];
+       for (i=0; i<ntags; i++) {
+           if (&cp[sizeof(krb5_int32)] > ep) {
+               kret = EINVAL;
+               break;
+           }
+           taglist[i] = (((krb5_int32) ((unsigned char) cp[0]) << 24) +
+                         ((krb5_int32) ((unsigned char) cp[1]) << 16) +
+                         ((krb5_int32) ((unsigned char) cp[2]) << 8) +
+                         ((krb5_int32) ((unsigned char) cp[3])));
+           cp += sizeof(krb5_int32);
+       }
+       if (!kret) {
+           /*
+            * If we were successful, copy out the remaining bytes for value.
+            */
+           len2copy = (size_t) (ep - cp);
+           if (len2copy &&
+               (*datap = (krb5_octet *) malloc(len2copy+1))) {
+               memcpy(*datap, cp, len2copy);
+               (*datap)[len2copy] = '\0';
+           }
+           if (len2copy && !*datap)
+               kret = ENOMEM;
+           else
+               *lenp = len2copy;
        }
-       free(saltstring);
     }
     return(kret);
 }
@@ -255,12 +252,21 @@ krb5_adm_proto_to_dbent(kcontext, nent, data, validp, dbentp, pwordp)
     int                        i;
     krb5_error_code    retval;
     krb5_ui_4          parsed_mask;
-    char               *modifier_name;
+    krb5_int32         taglist[4];
+    size_t             data_length;
+    krb5_octet         *tagged_data;
+    struct key_tag_correlator {
+       krb5_int32      key_tag;
+       int             key_data_index;
+    } *correlators, *correlation;
+    int                        ncorrelations;
 
     /* Initialize */
     retval = 0;
     parsed_mask = 0;
     *pwordp = (char *) NULL;
+    correlators = (struct key_tag_correlator *) NULL;
+    ncorrelations = 0;
 
     /* Loop through all the specified keyword=value pairs. */
     for (i=0; i<nent; i++) {
@@ -276,18 +282,6 @@ krb5_adm_proto_to_dbent(kcontext, nent, data, validp, dbentp, pwordp)
                break;
        }
 
-       /* Check for key version number */
-       if (!(retval = decode_kw_integer(&data[i],
-                                        KRB5_ADM_KW_KVNO,
-                                        (krb5_ui_4 *) &dbentp->kvno))) {
-           parsed_mask |= KRB5_ADM_M_KVNO;
-           continue;
-       }
-       else {
-           if (retval != ENOENT)
-               break;
-       }
-
        /* Check for maximum lifetime */
        if (!(retval = decode_kw_integer(&data[i],
                                         KRB5_ADM_KW_MAXLIFE,
@@ -368,42 +362,6 @@ krb5_adm_proto_to_dbent(kcontext, nent, data, validp, dbentp, pwordp)
                break;
        }
 
-       /* Check for salttype */
-       if (!(retval = decode_kw_salttype(&data[i],
-                                         KRB5_ADM_KW_SALTTYPE,
-                                         dbentp))) {
-           parsed_mask |= KRB5_ADM_M_SALTTYPE;
-           continue;
-       }
-       else {
-           if (retval != ENOENT)
-               break;
-       }
-
-       /* Check for master key version number */
-       if (!(retval = decode_kw_integer(&data[i],
-                                        KRB5_ADM_KW_MKVNO,
-                                        (krb5_ui_4 *) &dbentp->mkvno))) {
-           parsed_mask |= KRB5_ADM_M_MKVNO;
-           continue;
-       }
-       else {
-           if (retval != ENOENT)
-               break;
-       }
-
-       /* Check for last password change */
-       if (!(retval = decode_kw_gentime(&data[i],
-                                        KRB5_ADM_KW_LASTPWCHANGE,
-                                        &dbentp->last_pwd_change))) {
-           parsed_mask |= KRB5_ADM_M_LASTPWCHANGE;
-           continue;
-       }
-       else {
-           if (retval != ENOENT)
-               break;
-       }
-
        /* Check for last successful password entry */
        if (!(retval = decode_kw_gentime(&data[i],
                                         KRB5_ADM_KW_LASTSUCCESS,
@@ -441,37 +399,158 @@ krb5_adm_proto_to_dbent(kcontext, nent, data, validp, dbentp, pwordp)
                break;
        }
 
-       /* Check for modification principal */
-       if (!(retval = decode_kw_string(&data[i],
-                                       KRB5_ADM_KW_MODNAME,
-                                       &modifier_name))) {
-           krb5_principal      modifier;
-           retval = krb5_parse_name(kcontext, modifier_name, &modifier);
-           free(modifier_name);
-           if (!retval) {
-               if (dbentp->mod_name)
-                   krb5_free_principal(kcontext, dbentp->mod_name);
-               dbentp->mod_name = modifier;
-               parsed_mask |= KRB5_ADM_M_MODNAME;
-               continue;
+       /* Check for auxiliary data */
+       if (!(retval = decode_kw_tagged(&data[i],
+                                       KRB5_ADM_KW_AUXDATA,
+                                       1,
+                                       taglist,
+                                       &data_length,
+                                       &tagged_data))) {
+           krb5_tl_data        **fixupp;
+           krb5_tl_data        *tl_data, *new_tl;
+
+           /*
+            * We've got a tagged data value here.  We've got to do a little
+            * work to put it in the right place.  First, find the right place.
+            */
+           fixupp = &dbentp->tl_data;
+           for (tl_data = dbentp->tl_data;
+                tl_data; 
+                tl_data = tl_data->tl_data_next)
+               fixupp = &tl_data->tl_data_next;
+
+           /* Get memory */
+           if (new_tl = (krb5_tl_data *) malloc(sizeof(krb5_tl_data))) {
+               /* Fill in the supplied values */
+               new_tl->tl_data_type = (krb5_int16) taglist[0];
+               new_tl->tl_data_length = (krb5_int16) data_length;
+               new_tl->tl_data_contents = tagged_data;
+
+               /* Link in the right place */
+               new_tl->tl_data_next= *fixupp;
+               *fixupp = new_tl;
+
+               /* Update counters and flags */
+               dbentp->n_tl_data++;
+               parsed_mask |= KRB5_ADM_M_AUXDATA;
+           }
+           else {
+               retval = ENOMEM;
+               break;
+           }
+           continue;
+       }
+       else {
+           if ((retval != ENOENT) && (retval != EINVAL))
+               break;
+       }
+
+       /* Check for key data */
+       if (!(retval = decode_kw_tagged(&data[i],
+                                       KRB5_ADM_KW_KEYDATA,
+                                       3,
+                                       taglist,
+                                       &data_length,
+                                       &tagged_data))) {
+           krb5_boolean        corr_found;
+           int                 cindex, kindex;
+           krb5_key_data       *kdata;
+
+           /*
+            * See if we already have a correlation betwen our key-tag and
+            * an index into the key table.
+            */
+           corr_found = 0;
+           for (cindex = 0; cindex < ncorrelations; cindex++) {
+               if (correlators[cindex].key_tag == taglist[0]) {
+                   correlation = &correlators[cindex];
+                   corr_found = 1;
+                   break;
+               }
+           }
+
+           /* If not, then we had better make one up */
+           if (!corr_found) {
+               /* Get a new list */
+               if (correlation = (struct key_tag_correlator *)
+                   malloc((ncorrelations+1)*
+                          sizeof(struct key_tag_correlator))) {
+                   /* Save the contents of the old one. */
+                   if (ncorrelations) {
+                       memcpy(correlation, correlators,
+                              ncorrelations*
+                              sizeof(struct key_tag_correlator));
+                       /* Free the old one */
+                       free(correlators);
+                   }
+                   /* Point us at the new relation */
+                   correlators = correlation;
+                   correlation = &correlators[ncorrelations];
+                   ncorrelations++;
+                   correlation->key_tag = taglist[0];
+                   /* Make a new key data entry */
+                   if (kdata = (krb5_key_data *)
+                       malloc((dbentp->n_key_data+1)*sizeof(krb5_key_data))) {
+                       /* Copy the old list */
+                       if (dbentp->n_key_data) {
+                           memcpy(kdata, dbentp->key_data,
+                                  dbentp->n_key_data*sizeof(krb5_key_data));
+                           free(dbentp->key_data);
+                       }
+                       dbentp->key_data = kdata;
+                       correlation->key_data_index = dbentp->n_key_data;
+                       memset(&kdata[dbentp->n_key_data], 0,
+                              sizeof(krb5_key_data));
+                       kdata[dbentp->n_key_data].key_data_ver = 1;
+                       dbentp->n_key_data++;
+                       corr_found = 1;
+                   }
+                   else
+                       retval = ENOMEM;
+               }
+               else
+                   retval = ENOMEM;
+           }
+
+           /* Check to see if we either found a correlation or made one */
+           if (corr_found) {
+               /* Special case for key version number */
+               if (taglist[1] == -1) {
+                   dbentp->key_data[correlation->key_data_index].
+                       key_data_kvno = taglist[2];
+               }
+               else {
+                   dbentp->key_data[correlation->key_data_index].
+                       key_data_type[taglist[1]] = taglist[2];
+                   dbentp->key_data[correlation->key_data_index].
+                       key_data_length[taglist[1]] = (krb5_int16) data_length;
+                   dbentp->key_data[correlation->key_data_index].
+                       key_data_contents[taglist[1]] = tagged_data;
+               }
+               parsed_mask |= KRB5_ADM_M_KEYDATA;
            }
            else
                break;
+           continue;
        }
        else {
-           if (retval != ENOENT)
+           if ((retval != ENOENT) && (retval != EINVAL))
                break;
        }
 
-       /* Check for modification time */
-       if (!(retval = decode_kw_gentime(&data[i],
-                                        KRB5_ADM_KW_MODDATE,
-                                        &dbentp->mod_date))) {
-           parsed_mask |= KRB5_ADM_M_MODDATE;
+       /* Check for extra data */
+       if (!(retval = decode_kw_tagged(&data[i],
+                                       KRB5_ADM_KW_EXTRADATA,
+                                       0,
+                                       taglist,
+                                       &data_length,
+                                       &dbentp->e_data))) {
+           dbentp->e_length = (krb5_int16) data_length;
+           parsed_mask |= KRB5_ADM_M_EXTRADATA;
            continue;
        }
        else {
-           if (retval != ENOENT)
+           if ((retval != ENOENT) && (retval != EINVAL))
                break;
        }
 
@@ -490,6 +569,8 @@ krb5_adm_proto_to_dbent(kcontext, nent, data, validp, dbentp, pwordp)
        }
        parsed_mask = 0;
     }
+    if (correlators)
+       free(correlators);
     *validp |= parsed_mask;
     return(retval);
 }
index 9bc4c5cba9b32812f48854b3e6d52aee96485e5d..4e0318712e71b80f74b3fccf9eb9a1908bc9d895 100644 (file)
 #include "adm.h"
 #include "adm_proto.h"
 
-\f
-/*
- * salt_type_to_string()       - Return a string for a given salt type.
- *
- * Add support for different salt types here.
- */
-static char *
-salt_type_to_string(stype)
-    krb5_int32 stype;
-{
-    char       *retval = (char *) NULL;
-
-    switch (stype) {
-    case KRB5_KDB_SALTTYPE_NORMAL:
-       retval = KRB5_ADM_SALTTYPE_NORMAL;  break;
-    case KRB5_KDB_SALTTYPE_V4:
-       retval = KRB5_ADM_SALTTYPE_V4;  break;
-    case KRB5_KDB_SALTTYPE_NOREALM:
-       retval = KRB5_ADM_SALTTYPE_NOREALM;  break;
-    case KRB5_KDB_SALTTYPE_ONLYREALM:
-       retval = KRB5_ADM_SALTTYPE_ONLYREALM;  break;
-    case KRB5_KDB_SALTTYPE_SPECIAL:
-       retval = KRB5_ADM_SALTTYPE_SPECIAL;  break;
-    }
-    return(retval);
-}
 \f
 /*
  * format_kw_string()  - Format a keyword=<string> pair.
@@ -100,10 +74,10 @@ format_kw_integer(datap, kwordp, val)
     if (datap->data) {
        datap->length = strlen(fbuffer);
        strcpy(datap->data, fbuffer);
-       datap->data[datap->length]   = (char) ((val >> 24) & 0xff);
-       datap->data[datap->length+1] = (char) ((val >> 16) & 0xff);
-       datap->data[datap->length+2] = (char) ((val >> 8) & 0xff);
-       datap->data[datap->length+3] = (char) (val & 0xff);
+       datap->data[datap->length]   = (unsigned char) ((val >> 24) & 0xff);
+       datap->data[datap->length+1] = (unsigned char) ((val >> 16) & 0xff);
+       datap->data[datap->length+2] = (unsigned char) ((val >> 8) & 0xff);
+       datap->data[datap->length+3] = (unsigned char) (val & 0xff);
        datap->length += sizeof(krb5_ui_4);
        retval = 0;
     }
@@ -143,29 +117,46 @@ format_kw_gentime(datap, kwordp, timep)
 }
 \f
 /*
- * format_kw_salttype()        - Format a keyword=<salttype> pair.
+ * format_kw_tagged()  - Format a <tagged>=<taglist>...<value> list.
  */
 static krb5_error_code
-format_kw_salttype(datap, kwordp, dbentp)
-     krb5_data         *datap;
-     char              *kwordp;
-     krb5_db_entry     *dbentp;
+format_kw_tagged(datap, kwordp, ntags, taglist, vallen, val)
+    krb5_data  *datap;
+    char       *kwordp;
+    const int  ntags;
+    krb5_int32 *taglist;
+    krb5_int32 vallen;
+    krb5_octet *val;
 {
     krb5_error_code    retval;
-    char               fbuffer[BUFSIZ];
-    char               *sstring;
+    unsigned char      *cp;
+    int                        i;
 
-    retval = EINVAL;
-    sstring = salt_type_to_string(dbentp->salt_type);
-    if (sstring) {
-       strcpy(fbuffer, sstring);
-       /* Only add secondary salt type if it's different and valid */
-       if ((dbentp->salt_type != dbentp->alt_salt_type) &&
-           (sstring = salt_type_to_string(dbentp->alt_salt_type))) {
-           strcat(fbuffer,",");
-           strcat(fbuffer,sstring);
+    /* Calculate the size required:
+     * strlen(kwordp) + 1 for "kword"=
+     * 4 * ntags for tags
+     * vallen for value;
+     */
+    datap->data = (char *) malloc(strlen(kwordp)+
+                                 1+
+                                 (ntags*sizeof(krb5_int32))+
+                                 vallen+1);
+    if (datap->data) {
+       datap->length = strlen(kwordp)+1+(ntags*sizeof(krb5_int32))+vallen;
+       cp = (unsigned char *) datap->data;
+       cp[datap->length] = '\0';
+       sprintf((char *) cp, "%s=", kwordp);
+       cp += strlen((char *) cp);
+       for (i=0; i<ntags; i++) {
+           cp[0] = (unsigned char) ((taglist[i] >> 24) & 0xff);
+           cp[1] = (unsigned char) ((taglist[i] >> 16) & 0xff);
+           cp[2] = (unsigned char) ((taglist[i] >> 8) & 0xff);
+           cp[3] = (unsigned char) (taglist[i] & 0xff);
+           cp += sizeof(krb5_int32);
        }
-       retval = format_kw_string(datap, kwordp, fbuffer);
+       if (val && vallen)
+           memcpy(cp, val, vallen);
+       retval = 0;
     }
     return(retval);
 }
@@ -199,6 +190,10 @@ krb5_adm_dbent_to_proto(kcontext, valid, dbentp, password, nentp, datap)
     size_t             n2alloc;
     int                        outindex;
     krb5_boolean       is_set;
+    krb5_ui_4          tmp;
+    krb5_int32         taglist[4];
+    krb5_tl_data       *tl_data;
+    int                        keyind, attrind;
 
     kret = 0;
     /* First check out whether this is a set or get and the mask */
@@ -208,8 +203,26 @@ krb5_adm_dbent_to_proto(kcontext, valid, dbentp, password, nentp, datap)
        (!is_set && ((valid & KRB5_ADM_M_GET) == 0)))
        return(EINVAL);
 
-    /* Allocate a new array of output data */
-    n2alloc = (is_set) ? KRB5_ADM_KW_MAX_SET : KRB5_ADM_KW_MAX_GET;
+    /*
+     * Compute the number of elements to allocate.  First count set bits.
+     */
+    n2alloc = 0;
+    for (tmp = valid & ~(KRB5_ADM_M_SET|KRB5_ADM_M_GET);
+        tmp;
+        tmp >>= 1) {
+       if (tmp & 1)
+           n2alloc++;
+    }
+    if (valid & KRB5_ADM_M_AUXDATA)
+       n2alloc += (dbentp->n_tl_data - 1);
+    /*
+     * NOTE: If the number of per-key attributes increases, you must increase
+     * the 3 below.  The 3 represents 1 for key version, 1 for key type and
+     * one for salt type.
+     */
+    if (valid & KRB5_ADM_M_KEYDATA)
+       n2alloc += ((dbentp->n_key_data*3)-1);
+
     n2alloc *= sizeof(krb5_data);
     outindex = 0;
     outlist = (krb5_data *) malloc(n2alloc);
@@ -228,15 +241,6 @@ krb5_adm_dbent_to_proto(kcontext, valid, dbentp, password, nentp, datap)
            else
                outindex++;
        }
-       /* Handle key version number */
-       if ((valid & KRB5_ADM_M_KVNO) != 0) {
-           if (kret = format_kw_integer(&outlist[outindex],
-                                        KRB5_ADM_KW_KVNO,
-                                        (krb5_ui_4) dbentp->kvno))
-               goto choke;
-           else
-               outindex++;
-       }
        /* Handle maximum ticket lifetime */
        if ((valid & KRB5_ADM_M_MAXLIFE) != 0) {
            if (kret = format_kw_integer(&outlist[outindex],
@@ -292,35 +296,6 @@ krb5_adm_dbent_to_proto(kcontext, valid, dbentp, password, nentp, datap)
            else
                outindex++;
        }
-       /* Handle salt types */
-       if ((valid & KRB5_ADM_M_SALTTYPE) != 0) {
-           if (kret = format_kw_salttype(&outlist[outindex],
-                                         KRB5_ADM_KW_SALTTYPE,
-                                         dbentp))
-               goto choke;
-           else
-               outindex++;
-       }
-       /* Handle master key version number */
-       if (!is_set &&
-           ((valid & KRB5_ADM_M_MKVNO) != 0)) {
-           if (kret = format_kw_integer(&outlist[outindex],
-                                        KRB5_ADM_KW_MKVNO,
-                                        (krb5_ui_4) dbentp->mkvno))
-               goto choke;
-           else
-               outindex++;
-       }
-       /* Handle last successful password change */
-       if (!is_set &&
-           ((valid & KRB5_ADM_M_LASTPWCHANGE) != 0)) {
-           if (kret = format_kw_gentime(&outlist[outindex],
-                                        KRB5_ADM_KW_LASTPWCHANGE,
-                                        &dbentp->last_pwd_change))
-               goto choke;
-           else
-               outindex++;
-       }
        /* Handle last successful password entry */
        if (!is_set &&
            ((valid & KRB5_ADM_M_LASTSUCCESS) != 0)) {
@@ -351,39 +326,89 @@ krb5_adm_dbent_to_proto(kcontext, valid, dbentp, password, nentp, datap)
            else
                outindex++;
        }
-       /* Handle last modification principal name */
-       if (!is_set &&
-           ((valid & KRB5_ADM_M_MODNAME) != 0)) {
-           char *modifier_name;
 
-           /* Flatten the name, format it then free it. */
-           if (kret = krb5_unparse_name(kcontext,
-                                        dbentp->mod_name,
-                                        &modifier_name))
-               goto choke;
-
-           kret = format_kw_string(&outlist[outindex],
-                                   KRB5_ADM_KW_MODNAME,
-                                   modifier_name);
-           krb5_xfree(modifier_name);
-           if (kret)
-               goto choke;
-           else
-               outindex++;
+       /* Handle the auxiliary data */
+       if ((valid & KRB5_ADM_M_AUXDATA) != 0) {
+           for (tl_data = dbentp->tl_data; tl_data; tl_data =
+                tl_data->tl_data_next) {
+               taglist[0] = (krb5_int32) tl_data->tl_data_type;
+               if (kret = format_kw_tagged(&outlist[outindex],
+                                           KRB5_ADM_KW_AUXDATA,
+                                           1,
+                                           taglist,
+                                           (krb5_int32) tl_data->
+                                               tl_data_length,
+                                           tl_data->tl_data_contents))
+                   goto choke;
+               else
+                   outindex++;
+           }
        }
-       /* Handle last modification time */
+
+       /* Handle the key data */
        if (!is_set &&
-           ((valid & KRB5_ADM_M_MODDATE) != 0)) {
-           if (kret = format_kw_gentime(&outlist[outindex],
-                                        KRB5_ADM_KW_MODDATE,
-                                        &dbentp->mod_date))
+           ((valid  & KRB5_ADM_M_KEYDATA) != 0)) {
+           for (keyind = 0; keyind < dbentp->n_key_data; keyind++) {
+               /*
+                * First handle kvno
+                */
+               taglist[0] = (krb5_int32) keyind;
+               taglist[1] = (krb5_int32) -1;
+               taglist[2] = (krb5_int32) dbentp->key_data[keyind].
+                   key_data_kvno;
+               if (kret = format_kw_tagged(&outlist[outindex],
+                                           KRB5_ADM_KW_KEYDATA,
+                                           3,
+                                           taglist,
+                                           0,
+                                           (krb5_octet *) NULL))
+                   goto choke;
+               else
+                   outindex++;
+
+               /*
+                * Then each attribute as supported.
+                */
+               for (attrind = 0;
+                    attrind < KRB5_KDB_V1_KEY_DATA_ARRAY;
+                    attrind++) {
+                   taglist[1] = (krb5_int32) attrind;
+                   taglist[2] = (krb5_int32) dbentp->key_data[keyind].
+                       key_data_type[attrind];
+                   if (kret = format_kw_tagged(&outlist[outindex],
+                                               KRB5_ADM_KW_KEYDATA,
+                                               3,
+                                               taglist,
+                                               (krb5_int32) dbentp->
+                                                   key_data[keyind].
+                                                   key_data_length[attrind],
+                                               dbentp->key_data[keyind].
+                                                   key_data_contents[attrind])
+                       )
+                       goto choke;
+                   else
+                       outindex++;
+               }
+           }
+       }
+
+       /* Finally, handle the extra data */
+       if ((valid & KRB5_ADM_M_EXTRADATA) != 0) {
+           if (kret = format_kw_tagged(&outlist[outindex],
+                                       KRB5_ADM_KW_EXTRADATA,
+                                       0,
+                                       (krb5_int32 *) NULL,
+                                       (krb5_int32) dbentp->e_length,
+                                       dbentp->e_data))
                goto choke;
            else
                outindex++;
        }
     }
-    else
-       kret = ENOMEM;
+    else {
+       if (n2alloc)
+           kret = ENOMEM;
+    }
  choke:
     if (kret) {
        if (outlist) {
index c59bb9fa743751dca6093d7ae1b95e704fdc9054..6c71234b3ecdbf1a6bd121528881325750291053 100644 (file)
@@ -73,6 +73,7 @@ There is no random number generator.
 #define        FAILCOUNT_EVENT         RANDOM_EVENT(2,5)
 #define        MODNAME_EVENT           RANDOM_EVENT(2,5)
 #define        MODDATE_EVENT           RANDOM_EVENT(2,5)
+#define        EXTRA_EVENT             RANDOM_EVENT(1,5)
 #define        SET_EVENT               RANDOM_EVENT(1,4)
 
 /*
@@ -90,6 +91,145 @@ time2string(ts)
     return(buf);
 }
 
+static krb5_boolean
+aux_data_inequal(in, out)
+    krb5_db_entry      *in, *out;
+{
+    krb5_tl_data       *intl, *outtl;
+    krb5_boolean       found;
+
+    if (in->n_tl_data != out->n_tl_data)
+       return(1);
+    found = 1;
+    for (intl = in->tl_data; intl; intl = intl->tl_data_next) {
+       found = 0;
+       for (outtl = out->tl_data; outtl; outtl = outtl->tl_data_next) {
+           if ((intl->tl_data_type == outtl->tl_data_type) &&
+               (intl->tl_data_length == outtl->tl_data_length) &&
+               !memcmp(intl->tl_data_contents,
+                       outtl->tl_data_contents,
+                       intl->tl_data_length)) {
+               outtl->tl_data_length = -outtl->tl_data_length;
+               found = 1;
+           }
+       }
+       if (!found)
+           break;
+    }
+    for (outtl = out->tl_data; outtl; outtl = outtl->tl_data_next) {
+       if (outtl->tl_data_length < 0)
+           outtl->tl_data_length = -outtl->tl_data_length;
+    }
+    return(!found);
+}
+
+static void
+print_auxdata(entp)
+    krb5_db_entry      *entp;
+{
+    krb5_tl_data       *tl;
+    int                        i;
+
+    for (tl = entp->tl_data; tl; tl = tl->tl_data_next) {
+       printf("tl_data(%d)[len=%d] ", tl->tl_data_type, tl->tl_data_length);
+       for (i=0; i<tl->tl_data_length; i++)
+           printf("%02x ", tl->tl_data_contents[i]);
+       printf("\n");
+    }
+}
+
+static krb5_boolean
+key_data_inequal(in, out)
+    krb5_db_entry      *in, *out;
+{
+    krb5_boolean       found;
+    int                i, j;
+
+    if (in->n_key_data != out->n_key_data)
+       return(1);
+    found = 1;
+    for (i=0; i<in->n_key_data; i++) {
+       found = 0;
+       for (j=0; j<out->n_key_data; j++) {
+           if ((in->key_data[i].key_data_kvno ==
+                out->key_data[j].key_data_kvno) &&
+               (in->key_data[i].key_data_type[0] ==
+                out->key_data[j].key_data_type[0]) &&
+               (in->key_data[i].key_data_type[1] ==
+                out->key_data[j].key_data_type[1]) &&
+               (in->key_data[i].key_data_length[0] ==
+                out->key_data[j].key_data_length[0]) &&
+               (in->key_data[i].key_data_length[1] ==
+                out->key_data[j].key_data_length[1]) &&
+               !memcmp(in->key_data[i].key_data_contents[0],
+                       out->key_data[j].key_data_contents[0],
+                       in->key_data[i].key_data_length[0]) &&
+               (!in->key_data[i].key_data_length[1] ||
+                !memcmp(in->key_data[i].key_data_contents[1],
+                       out->key_data[j].key_data_contents[1],
+                       in->key_data[i].key_data_length[1]))) {
+               out->key_data[j].key_data_length[0] = 
+                   -out->key_data[j].key_data_length[0];
+               found = 1;
+           }
+       }
+       if (!found)
+           break;
+    }
+    for (j=0; j<out->n_key_data; j++) {
+       if (out->key_data[j].key_data_length[0] < 0)
+           out->key_data[j].key_data_length[0] = 
+               -out->key_data[j].key_data_length[0];
+    }
+    return(!found);
+}
+
+static void
+print_keydata(entp)
+    krb5_db_entry      *entp;
+{
+    int                        i, j;
+
+    for (j=0; j<entp->n_key_data; j++) {
+       printf("key(vno=%d):key(type=%d)[contents= ",
+              entp->key_data[j].key_data_kvno,
+              entp->key_data[j].key_data_type[0]);
+       for (i=0; i<entp->key_data[j].key_data_length[0]; i++)
+           printf("%02x ", entp->key_data[j].key_data_contents[0][i]);
+       printf("] salt(type=%d)", entp->key_data[j].key_data_type[1]);
+       if (entp->key_data[j].key_data_length[1]) {
+           printf("[contents= ");
+           for (i=0; i<entp->key_data[j].key_data_length[1]; i++)
+               printf("%02x ", entp->key_data[j].key_data_contents[1][i]);
+           printf("]");
+       }
+       printf("\n");
+    }
+}
+
+static krb5_boolean
+extra_data_inequal(in, out)
+    krb5_db_entry      *in, *out;
+{
+    if (in->e_length != out->e_length)
+       return(1);
+    if (in->e_length && memcmp(in->e_data, out->e_data, (size_t) in->e_length))
+       return(1);
+    return(0);
+}
+
+static void
+print_extradata(entp)
+    krb5_db_entry      *entp;
+{
+    int i;
+
+    printf("extra:");
+    for (i=0; i<entp->e_length; i++)
+       printf("%02x ", entp->e_data[i]);
+    printf("\n");
+}
+
 /*
  * Generate a database entry, either randomly, or using well known values.
  */
@@ -134,18 +274,6 @@ gen_dbent(kcontext, dbentp, isrand, validp, pwdp, expectp)
        }
     }
 
-    /* Do kvno */
-    if (isrand) {
-       if (KVNO_EVENT) {
-           dbentp->kvno = RAND();
-           *validp |= KRB5_ADM_M_KVNO;
-       }
-    }
-    else {
-       dbentp->kvno = 1;
-       *validp |= KRB5_ADM_M_KVNO;
-    }
-
     /* Do maxlife */
     if (isrand) {
        if (MAXLIFE_EVENT) {
@@ -211,47 +339,6 @@ gen_dbent(kcontext, dbentp, isrand, validp, pwdp, expectp)
        *validp |= KRB5_ADM_M_FLAGS;
     }
 
-    /* Do salts */
-    if (isrand) {
-       if (SALT_EVENT) {
-           dbentp->salt_type = (RAND() % 1);
-           dbentp->alt_salt_type = (RAND() % 1);
-           *validp |= KRB5_ADM_M_SALTTYPE;
-       }
-    }
-    else {
-       dbentp->salt_type = dbentp->alt_salt_type = KRB5_KDB_SALTTYPE_NORMAL;
-       *validp |= KRB5_ADM_M_SALTTYPE;
-    }
-
-    /* Do mkvno */
-    if (isrand) {
-       if (MKVNO_EVENT) {
-           dbentp->mkvno = RAND();
-           *validp |= KRB5_ADM_M_MKVNO;
-       }
-    }
-    else {
-       if (!is_set) {
-           dbentp->mkvno = 1;
-           *validp |= KRB5_ADM_M_MKVNO;
-       }
-    }
-
-    /* Do lastpwchange */
-    if (isrand) {
-       if (LASTPWCHANGE_EVENT) {
-           dbentp->last_pwd_change = RAND();
-           *validp |= KRB5_ADM_M_LASTPWCHANGE;
-       }
-    }
-    else {
-       if (!is_set) {
-           dbentp->last_pwd_change = (krb5_timestamp) now - 3600;
-           *validp |= KRB5_ADM_M_LASTPWCHANGE;
-       }
-    }
-
     /* Do lastsuccess */
     if (isrand) {
        if (LASTSUCCESS_EVENT) {
@@ -294,36 +381,139 @@ gen_dbent(kcontext, dbentp, isrand, validp, pwdp, expectp)
        }
     }
 
-    /* Do modname */
+    /*
+     * Generate auxiliary data.
+     */
     if (isrand) {
-       if (MODNAME_EVENT) {
-           if (!krb5_parse_name(kcontext, defprinc, &dbentp->mod_name)) {
-               *validp |= KRB5_ADM_M_MODNAME;
+       krb5_octet *lpw_change;
+       krb5_tl_data *tldata;
+       krb5_timestamp lpw;
+       krb5_tl_mod_princ mprinc;
+       int     didone;
+
+       didone = 0;
+       if (LASTPWCHANGE_EVENT) {
+           if ((tldata = (krb5_tl_data *) malloc(sizeof(krb5_tl_data))) &&
+               (lpw_change = (krb5_octet *) malloc(sizeof(krb5_timestamp)))) {
+               lpw = (krb5_timestamp) RAND();
+               lpw_change[0] = (unsigned char) ((lpw >> 24) & 0xff);
+               lpw_change[1] = (unsigned char) ((lpw >> 16) & 0xff);
+               lpw_change[2] = (unsigned char) ((lpw >> 8) & 0xff);
+               lpw_change[3] = (unsigned char) (lpw & 0xff);
+               tldata->tl_data_next = (krb5_tl_data *) NULL;
+               tldata->tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
+               tldata->tl_data_length = sizeof(krb5_timestamp);
+               tldata->tl_data_contents = lpw_change;
+               dbentp->n_tl_data = 1;
+               dbentp->tl_data = tldata;
+               didone++;
+           }
+       }
+       if (MODNAME_EVENT || MODDATE_EVENT) {
+           mprinc.mod_date = (krb5_timestamp) RAND();
+           if (!krb5_parse_name(kcontext, defprinc, &mprinc.mod_princ)) {
+               if (!krb5_dbe_encode_mod_princ_data(kcontext, &mprinc, dbentp))
+                   didone++;
            }
        }
+       if (didone)
+           *validp |= KRB5_ADM_M_AUXDATA;
     }
     else {
-       if (!is_set) {
-           if (!krb5_parse_name(kcontext, defprinc, &dbentp->mod_name)) {
-               *validp |= KRB5_ADM_M_MODNAME;
-           }
+       krb5_octet *lpw_change;
+       krb5_tl_data *tldata;
+       krb5_timestamp lpw;
+       krb5_tl_mod_princ mprinc;
+
+       if ((tldata = (krb5_tl_data *) malloc(sizeof(krb5_tl_data))) &&
+           (lpw_change = (krb5_octet *) malloc(sizeof(krb5_timestamp)))) {
+           lpw = (krb5_timestamp) now - 3600;
+           lpw_change[0] = (unsigned char) ((lpw >> 24) & 0xff);
+           lpw_change[1] = (unsigned char) ((lpw >> 16) & 0xff);
+           lpw_change[2] = (unsigned char) ((lpw >> 8) & 0xff);
+           lpw_change[3] = (unsigned char) (lpw & 0xff);
+           tldata->tl_data_next = (krb5_tl_data *) NULL;
+           tldata->tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
+           tldata->tl_data_length = sizeof(krb5_timestamp);
+           tldata->tl_data_contents = lpw_change;
+           dbentp->n_tl_data = 1;
+           dbentp->tl_data = tldata;
        }
+       mprinc.mod_date = (krb5_timestamp) now;
+       if (!krb5_parse_name(kcontext, defprinc, &mprinc.mod_princ))
+           krb5_dbe_encode_mod_princ_data(kcontext, &mprinc, dbentp);
+       *validp |= KRB5_ADM_M_AUXDATA;
     }
 
-    /* Do mod_date */
+    /* Make key data */
     if (isrand) {
-       if (MODDATE_EVENT) {
-           dbentp->mod_date = RAND();
-           *validp |= KRB5_ADM_M_MODDATE;
+       int i, j, kl, sl;
+
+       if (!is_set) {
+           for (i=0; i<(1+(RAND()%8)); i++) {
+               if (!krb5_dbe_create_key_data(kcontext, dbentp)) {
+                   dbentp->key_data[i].key_data_kvno = RAND() % 32768;
+                   dbentp->key_data[i].key_data_type[0] = RAND() % 32768;
+                   dbentp->key_data[i].key_data_type[1] = RAND() % 32768;
+                   kl = dbentp->key_data[i].key_data_length[0] =
+                       8 + (RAND() % 128);
+                   sl = dbentp->key_data[i].key_data_length[1] =
+                       0 + (RAND() % 128);
+                   if (dbentp->key_data[i].key_data_contents[0] =
+                       (krb5_octet *) malloc(kl)) {
+                       for (j=0; j<kl; j++) {
+                           dbentp->key_data[i].key_data_contents[0][j] =
+                               RAND() % 256;
+                       }
+                   }
+                   if (dbentp->key_data[i].key_data_contents[1] =
+                       (krb5_octet *) malloc(sl)) {
+                       for (j=0; j<sl; j++) {
+                           dbentp->key_data[i].key_data_contents[1][j] =
+                               RAND() % 256;
+                       }
+                   }
+                   *validp |= KRB5_ADM_M_KEYDATA;
+               }
+           }
        }
     }
     else {
        if (!is_set) {
-           dbentp->mod_date = (krb5_timestamp) now;
-           *validp |= KRB5_ADM_M_MODDATE;
+           if (!krb5_dbe_create_key_data(kcontext, dbentp)) {
+               int i;
+
+               dbentp->key_data[0].key_data_kvno = 1;
+               dbentp->key_data[0].key_data_type[0] = 1;
+               dbentp->key_data[0].key_data_type[1] = 0;
+               dbentp->key_data[0].key_data_length[0] = 24;
+               dbentp->key_data[0].key_data_length[1] = 0;
+               if (dbentp->key_data[0].key_data_contents[0] =
+                   (krb5_octet *) malloc(24)) {
+                   for (i=0; i<24; i++)
+                       dbentp->key_data[0].key_data_contents[0][i] = RAND() % 256;
+               }
+               dbentp->key_data[0].key_data_contents[1] = (krb5_octet *) NULL;
+               *validp |= KRB5_ADM_M_KEYDATA;
+           }
        }
     }
 
+    /* Make extra data */
+    if (isrand && EXTRA_EVENT) {
+       dbentp->e_length = 8 + (RAND() % 504);
+       if (dbentp->e_data = (krb5_octet *)
+           malloc((size_t) dbentp->e_length)) {
+           int j;
+           for (j=0; j<dbentp->e_length; j++) {
+               dbentp->e_data[j] = RAND() % 256;
+           }
+           *validp |= KRB5_ADM_M_EXTRADATA;
+       }
+       else
+           dbentp->e_length = 0;
+    }
+
     if (is_set) {
        /* Only 25% may fail at most */
        if (isrand && ((RAND() % 100) < 75)) {
@@ -362,12 +552,6 @@ compare_entries(kcontext, ivalid, ientp, ipwd, ovalid, oentp, opwd)
         strcmp(ipwd, opwd)))
            return(0);
 
-    /* Handle/compare kvno */
-    if (((ivalid & KRB5_ADM_M_KVNO) != 0) &&
-       (((ovalid & KRB5_ADM_M_KVNO) == 0) ||
-        (ientp->kvno != oentp->kvno)))
-       return(0);
-
     /* Handle/compare maxlife */
     if (((ivalid & KRB5_ADM_M_MAXLIFE) != 0) &&
        (((ovalid & KRB5_ADM_M_MAXLIFE) == 0) ||
@@ -405,25 +589,6 @@ compare_entries(kcontext, ivalid, ientp, ipwd, ovalid, oentp, opwd)
         (ientp->attributes != oentp->attributes)))
        return(0);
 
-    /* Handle/compare salts */
-    if (((ivalid & KRB5_ADM_M_SALTTYPE) != 0) &&
-       (((ovalid & KRB5_ADM_M_SALTTYPE) == 0) ||
-        (ientp->salt_type != oentp->salt_type) ||
-        (ientp->alt_salt_type != oentp->alt_salt_type)))
-       return(0);
-
-    /* Handle/compare mkvno */
-    if (((ivalid & KRB5_ADM_M_MKVNO) != 0) &&
-       (((ovalid & KRB5_ADM_M_MKVNO) == 0) ||
-        (ientp->mkvno != oentp->mkvno)))
-       return(0);
-
-    /* Handle/compare lastpwchange */
-    if (((ivalid & KRB5_ADM_M_LASTPWCHANGE) != 0) &&
-       (((ovalid & KRB5_ADM_M_LASTPWCHANGE) == 0) ||
-        (ientp->last_pwd_change != oentp->last_pwd_change)))
-       return(0);
-
     /* Handle/compare lastsuccess */
     if (((ivalid & KRB5_ADM_M_LASTSUCCESS) != 0) &&
        (((ovalid & KRB5_ADM_M_LASTSUCCESS) == 0) ||
@@ -442,17 +607,24 @@ compare_entries(kcontext, ivalid, ientp, ipwd, ovalid, oentp, opwd)
         (ientp->fail_auth_count != oentp->fail_auth_count)))
        return(0);
 
-    /* Handle/compare mod_name */
-    if (((ivalid & KRB5_ADM_M_MODNAME) != 0) &&
-       (((ovalid & KRB5_ADM_M_MODNAME) == 0) ||
-        !krb5_principal_compare(kcontext, ientp->mod_name, oentp->mod_name)))
+    /* Handle/compare auxiliary data */
+    if (((ivalid & KRB5_ADM_M_AUXDATA) != 0) &&
+       (((ovalid & KRB5_ADM_M_AUXDATA) == 0) ||
+        aux_data_inequal(ientp, oentp)))
+       return(0);
+
+    /* Handle/compare key data */
+    if (((ivalid & KRB5_ADM_M_KEYDATA) != 0) &&
+       (((ovalid & KRB5_ADM_M_KEYDATA) == 0) ||
+        key_data_inequal(ientp, oentp)))
        return(0);
 
-    /* Handle/compare mod_date */
-    if (((ivalid & KRB5_ADM_M_MODDATE) != 0) &&
-       (((ovalid & KRB5_ADM_M_MODDATE) == 0) ||
-        (ientp->mod_date != oentp->mod_date)))
+    /* Handle/compare extra data */
+    if (((ivalid & KRB5_ADM_M_EXTRADATA) != 0) &&
+       (((ovalid & KRB5_ADM_M_EXTRADATA) == 0) ||
+        extra_data_inequal(ientp, oentp)))
        return(0);
+
     return(1);
 }
 
@@ -472,10 +644,6 @@ print_dbent(kcontext, ivalid, ientp, ipwd)
     if ((ivalid & KRB5_ADM_M_PASSWORD) != 0)
        printf("Password:\t%s\n", ipwd);
 
-    /* Print kvno */
-    if ((ivalid & KRB5_ADM_M_KVNO) != 0)
-       printf("kvno:\t\t%8d\t%08x\n", ientp->kvno, ientp->kvno);
-
     /* Print maxlife */
     if ((ivalid & KRB5_ADM_M_MAXLIFE) != 0)
        printf("max_life:\t%8d\t%08x\n", ientp->max_life, ientp->max_life);
@@ -503,19 +671,6 @@ print_dbent(kcontext, ivalid, ientp, ipwd)
     if ((ivalid & KRB5_ADM_M_FLAGS) != 0)
        printf("flags:\t\t%8d\t%08x\n", ientp->attributes, ientp->attributes);
 
-    /* Print salts */
-    if ((ivalid & KRB5_ADM_M_SALTTYPE) != 0)
-       printf("salts:\t\t%d, %d\n", ientp->salt_type, ientp->alt_salt_type);
-
-    /* Print mkvno */
-    if ((ivalid & KRB5_ADM_M_MKVNO) != 0)
-       printf("mkvno:\t\t%8d\t%08x\n", ientp->mkvno, ientp->mkvno);
-
-    /* Print lastpwchange */
-    if ((ivalid & KRB5_ADM_M_LASTPWCHANGE) != 0)
-       printf("lastpwchg:\t%8d\t%08x\t%s\n", ientp->last_pwd_change,
-              ientp->last_pwd_change, time2string(ientp->last_pwd_change));
-
     /* Print lastsuccess */
     if ((ivalid & KRB5_ADM_M_LASTSUCCESS) != 0)
        printf("lastsucc:\t%8d\t%08x\t%s\n", ientp->last_success,
@@ -531,20 +686,17 @@ print_dbent(kcontext, ivalid, ientp, ipwd)
        printf("failcount:\t%8d\t%08x\n", ientp->fail_auth_count,
               ientp->fail_auth_count);
 
-    /* Print mod_name */
-    if ((ivalid & KRB5_ADM_M_MODNAME) != 0) {
-       char *mprinc;
+    /* Print auxiliary data */
+    if ((ivalid & KRB5_ADM_M_AUXDATA) != 0)
+       print_auxdata(ientp);
 
-       if (!krb5_unparse_name(kcontext, ientp->mod_name, &mprinc)) {
-           printf("modname:\t%s\n", mprinc);
-           krb5_xfree(mprinc);
-       }
-    }
+    /* Print key data */
+    if ((ivalid & KRB5_ADM_M_KEYDATA) != 0)
+       print_keydata(ientp);
 
-    /* Print mod_date */
-    if ((ivalid & KRB5_ADM_M_MODDATE) != 0)
-       printf("moddate:\t%8d\t%08x\t%s\n", ientp->mod_date,
-              ientp->mod_date, time2string(ientp->mod_date));
+    /* Print extra data */
+    if ((ivalid & KRB5_ADM_M_EXTRADATA) != 0)
+       print_extradata(ientp);
 }
 
 /*
@@ -714,11 +866,25 @@ do_test(pname, verbose, isrand, is_a_set, title, passno)
        /* Cleanup */
        if (in_password)
            free(in_password);
-       if (in_dbent->mod_name)
-           krb5_free_principal(kcontext, in_dbent->mod_name);
+       if (in_dbent->tl_data) {
+           krb5_tl_data *xxx, *xxx1;
+
+           for (xxx=in_dbent->tl_data; xxx; ) {
+               xxx1 = xxx;
+               xxx = xxx->tl_data_next;
+               free(xxx1);
+           }
+       }
        free(in_dbent);
-       if (out_dbent->mod_name)
-           krb5_free_principal(kcontext, out_dbent->mod_name);
+       if (out_dbent->tl_data) {
+           krb5_tl_data *xxx, *xxx1;
+
+           for (xxx=out_dbent->tl_data; xxx; ) {
+               xxx1 = xxx;
+               xxx = xxx->tl_data_next;
+               free(xxx1);
+           }
+       }
        free(out_dbent);
     }
     else {