xref: /freebsd/crypto/heimdal/kdc/mit_dump.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
15e9cd1aeSAssar Westerlund /*
2*ae771770SStanislav Sedov  * Copyright (c) 2000 Kungliga Tekniska Högskolan
35e9cd1aeSAssar Westerlund  * (Royal Institute of Technology, Stockholm, Sweden).
45e9cd1aeSAssar Westerlund  * All rights reserved.
55e9cd1aeSAssar Westerlund  *
65e9cd1aeSAssar Westerlund  * Redistribution and use in source and binary forms, with or without
75e9cd1aeSAssar Westerlund  * modification, are permitted provided that the following conditions
85e9cd1aeSAssar Westerlund  * are met:
95e9cd1aeSAssar Westerlund  *
105e9cd1aeSAssar Westerlund  * 1. Redistributions of source code must retain the above copyright
115e9cd1aeSAssar Westerlund  *    notice, this list of conditions and the following disclaimer.
125e9cd1aeSAssar Westerlund  *
135e9cd1aeSAssar Westerlund  * 2. Redistributions in binary form must reproduce the above copyright
145e9cd1aeSAssar Westerlund  *    notice, this list of conditions and the following disclaimer in the
155e9cd1aeSAssar Westerlund  *    documentation and/or other materials provided with the distribution.
165e9cd1aeSAssar Westerlund  *
175e9cd1aeSAssar Westerlund  * 3. Neither the name of the Institute nor the names of its contributors
185e9cd1aeSAssar Westerlund  *    may be used to endorse or promote products derived from this software
195e9cd1aeSAssar Westerlund  *    without specific prior written permission.
205e9cd1aeSAssar Westerlund  *
215e9cd1aeSAssar Westerlund  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
225e9cd1aeSAssar Westerlund  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
235e9cd1aeSAssar Westerlund  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
245e9cd1aeSAssar Westerlund  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
255e9cd1aeSAssar Westerlund  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
265e9cd1aeSAssar Westerlund  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
275e9cd1aeSAssar Westerlund  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
285e9cd1aeSAssar Westerlund  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
295e9cd1aeSAssar Westerlund  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
305e9cd1aeSAssar Westerlund  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
315e9cd1aeSAssar Westerlund  * SUCH DAMAGE.
325e9cd1aeSAssar Westerlund  */
335e9cd1aeSAssar Westerlund 
345e9cd1aeSAssar Westerlund #include "hprop.h"
355e9cd1aeSAssar Westerlund 
365e9cd1aeSAssar Westerlund /*
375e9cd1aeSAssar Westerlund can have any number of princ stanzas.
385e9cd1aeSAssar Westerlund format is as follows (only \n indicates newlines)
395e9cd1aeSAssar Westerlund princ\t%d\t (%d is KRB5_KDB_V1_BASE_LENGTH, always 38)
405e9cd1aeSAssar Westerlund %d\t (strlen of principal e.g. shadow/foo@ANDREW.CMU.EDU)
415e9cd1aeSAssar Westerlund %d\t (number of tl_data)
425e9cd1aeSAssar Westerlund %d\t (number of key data, e.g. how many keys for this user)
435e9cd1aeSAssar Westerlund %d\t (extra data length)
445e9cd1aeSAssar Westerlund %s\t (principal name)
455e9cd1aeSAssar Westerlund %d\t (attributes)
465e9cd1aeSAssar Westerlund %d\t (max lifetime, seconds)
475e9cd1aeSAssar Westerlund %d\t (max renewable life, seconds)
485e9cd1aeSAssar Westerlund %d\t (expiration, seconds since epoch or 2145830400 for never)
495e9cd1aeSAssar Westerlund %d\t (password expiration, seconds, 0 for never)
505e9cd1aeSAssar Westerlund %d\t (last successful auth, seconds since epoch)
515e9cd1aeSAssar Westerlund %d\t (last failed auth, per above)
525e9cd1aeSAssar Westerlund %d\t (failed auth count)
535e9cd1aeSAssar Westerlund foreach tl_data 0 to number of tl_data - 1 as above
545e9cd1aeSAssar Westerlund   %d\t%d\t (data type, data length)
555e9cd1aeSAssar Westerlund   foreach tl_data 0 to length-1
565e9cd1aeSAssar Westerlund     %02x (tl data contents[element n])
575e9cd1aeSAssar Westerlund   except if tl_data length is 0
585e9cd1aeSAssar Westerlund     %d (always -1)
595e9cd1aeSAssar Westerlund   \t
605e9cd1aeSAssar Westerlund foreach key 0 to number of keys - 1 as above
615e9cd1aeSAssar Westerlund   %d\t%d\t (key data version, kvno)
625e9cd1aeSAssar Westerlund   foreach version 0 to key data version - 1 (a key or a salt)
635e9cd1aeSAssar Westerlund     %d\t%d\t(data type for this key, data length for this key)
645e9cd1aeSAssar Westerlund     foreach key data length 0 to length-1
655e9cd1aeSAssar Westerlund       %02x (key data contents[element n])
665e9cd1aeSAssar Westerlund     except if key_data length is 0
675e9cd1aeSAssar Westerlund       %d (always -1)
685e9cd1aeSAssar Westerlund     \t
695e9cd1aeSAssar Westerlund foreach extra data length 0 to length - 1
705e9cd1aeSAssar Westerlund   %02x (extra data part)
715e9cd1aeSAssar Westerlund unless no extra data
725e9cd1aeSAssar Westerlund   %d (always -1)
735e9cd1aeSAssar Westerlund ;\n
745e9cd1aeSAssar Westerlund 
755e9cd1aeSAssar Westerlund */
765e9cd1aeSAssar Westerlund 
775e9cd1aeSAssar Westerlund static int
hex_to_octet_string(const char * ptr,krb5_data * data)785e9cd1aeSAssar Westerlund hex_to_octet_string(const char *ptr, krb5_data *data)
795e9cd1aeSAssar Westerlund {
80*ae771770SStanislav Sedov     size_t i;
815e9cd1aeSAssar Westerlund     unsigned int v;
825e9cd1aeSAssar Westerlund     for(i = 0; i < data->length; i++) {
835e9cd1aeSAssar Westerlund 	if(sscanf(ptr + 2 * i, "%02x", &v) != 1)
845e9cd1aeSAssar Westerlund 	    return -1;
855e9cd1aeSAssar Westerlund 	((unsigned char*)data->data)[i] = v;
865e9cd1aeSAssar Westerlund     }
875e9cd1aeSAssar Westerlund     return 2 * i;
885e9cd1aeSAssar Westerlund }
895e9cd1aeSAssar Westerlund 
905e9cd1aeSAssar Westerlund static char *
nexttoken(char ** p)915e9cd1aeSAssar Westerlund nexttoken(char **p)
925e9cd1aeSAssar Westerlund {
935e9cd1aeSAssar Westerlund     char *q;
945e9cd1aeSAssar Westerlund     do {
955e9cd1aeSAssar Westerlund 	q = strsep(p, " \t");
965e9cd1aeSAssar Westerlund     } while(q && *q == '\0');
975e9cd1aeSAssar Westerlund     return q;
985e9cd1aeSAssar Westerlund }
995e9cd1aeSAssar Westerlund 
1005e9cd1aeSAssar Westerlund static size_t
getdata(char ** p,unsigned char * buf,size_t len)1015e9cd1aeSAssar Westerlund getdata(char **p, unsigned char *buf, size_t len)
1025e9cd1aeSAssar Westerlund {
1035e9cd1aeSAssar Westerlund     size_t i;
1045e9cd1aeSAssar Westerlund     int v;
1055e9cd1aeSAssar Westerlund     char *q = nexttoken(p);
1065e9cd1aeSAssar Westerlund     i = 0;
1075e9cd1aeSAssar Westerlund     while(*q && i < len) {
1085e9cd1aeSAssar Westerlund 	if(sscanf(q, "%02x", &v) != 1)
1095e9cd1aeSAssar Westerlund 	    break;
1105e9cd1aeSAssar Westerlund 	buf[i++] = v;
1115e9cd1aeSAssar Westerlund 	q += 2;
1125e9cd1aeSAssar Westerlund     }
1135e9cd1aeSAssar Westerlund     return i;
1145e9cd1aeSAssar Westerlund }
1155e9cd1aeSAssar Westerlund 
1165e9cd1aeSAssar Westerlund static int
getint(char ** p)1175e9cd1aeSAssar Westerlund getint(char **p)
1185e9cd1aeSAssar Westerlund {
1195e9cd1aeSAssar Westerlund     int val;
1205e9cd1aeSAssar Westerlund     char *q = nexttoken(p);
1215e9cd1aeSAssar Westerlund     sscanf(q, "%d", &val);
1225e9cd1aeSAssar Westerlund     return val;
1235e9cd1aeSAssar Westerlund }
1245e9cd1aeSAssar Westerlund 
1255e9cd1aeSAssar Westerlund #include <kadm5/admin.h>
1265e9cd1aeSAssar Westerlund 
1275e9cd1aeSAssar Westerlund static void
attr_to_flags(unsigned attr,HDBFlags * flags)1285e9cd1aeSAssar Westerlund attr_to_flags(unsigned attr, HDBFlags *flags)
1295e9cd1aeSAssar Westerlund {
1305e9cd1aeSAssar Westerlund     flags->postdate =		!(attr & KRB5_KDB_DISALLOW_POSTDATED);
1315e9cd1aeSAssar Westerlund     flags->forwardable =	!(attr & KRB5_KDB_DISALLOW_FORWARDABLE);
1325e9cd1aeSAssar Westerlund     flags->initial =	       !!(attr & KRB5_KDB_DISALLOW_TGT_BASED);
1335e9cd1aeSAssar Westerlund     flags->renewable =		!(attr & KRB5_KDB_DISALLOW_RENEWABLE);
1345e9cd1aeSAssar Westerlund     flags->proxiable =		!(attr & KRB5_KDB_DISALLOW_PROXIABLE);
1355e9cd1aeSAssar Westerlund     /* DUP_SKEY */
1365e9cd1aeSAssar Westerlund     flags->invalid =	       !!(attr & KRB5_KDB_DISALLOW_ALL_TIX);
1375e9cd1aeSAssar Westerlund     flags->require_preauth =   !!(attr & KRB5_KDB_REQUIRES_PRE_AUTH);
138*ae771770SStanislav Sedov     flags->require_hwauth =    !!(attr & KRB5_KDB_REQUIRES_HW_AUTH);
1395e9cd1aeSAssar Westerlund     flags->server =		!(attr & KRB5_KDB_DISALLOW_SVR);
1405e9cd1aeSAssar Westerlund     flags->change_pw = 	       !!(attr & KRB5_KDB_PWCHANGE_SERVICE);
1415e9cd1aeSAssar Westerlund     flags->client =	        1; /* XXX */
1425e9cd1aeSAssar Westerlund }
1435e9cd1aeSAssar Westerlund 
1445e9cd1aeSAssar Westerlund #define KRB5_KDB_SALTTYPE_NORMAL	0
1455e9cd1aeSAssar Westerlund #define KRB5_KDB_SALTTYPE_V4		1
1465e9cd1aeSAssar Westerlund #define KRB5_KDB_SALTTYPE_NOREALM	2
1475e9cd1aeSAssar Westerlund #define KRB5_KDB_SALTTYPE_ONLYREALM	3
1485e9cd1aeSAssar Westerlund #define KRB5_KDB_SALTTYPE_SPECIAL	4
1495e9cd1aeSAssar Westerlund #define KRB5_KDB_SALTTYPE_AFS3		5
1505e9cd1aeSAssar Westerlund 
1515e9cd1aeSAssar Westerlund static krb5_error_code
fix_salt(krb5_context context,hdb_entry * ent,int key_num)1525e9cd1aeSAssar Westerlund fix_salt(krb5_context context, hdb_entry *ent, int key_num)
1535e9cd1aeSAssar Westerlund {
1545e9cd1aeSAssar Westerlund     krb5_error_code ret;
1555e9cd1aeSAssar Westerlund     Salt *salt = ent->keys.val[key_num].salt;
1565e9cd1aeSAssar Westerlund     /* fix salt type */
1575e9cd1aeSAssar Westerlund     switch((int)salt->type) {
1585e9cd1aeSAssar Westerlund     case KRB5_KDB_SALTTYPE_NORMAL:
1595e9cd1aeSAssar Westerlund 	salt->type = KRB5_PADATA_PW_SALT;
1605e9cd1aeSAssar Westerlund 	break;
1615e9cd1aeSAssar Westerlund     case KRB5_KDB_SALTTYPE_V4:
1625e9cd1aeSAssar Westerlund 	krb5_data_free(&salt->salt);
1635e9cd1aeSAssar Westerlund 	salt->type = KRB5_PADATA_PW_SALT;
1645e9cd1aeSAssar Westerlund 	break;
1655e9cd1aeSAssar Westerlund     case KRB5_KDB_SALTTYPE_NOREALM:
1665e9cd1aeSAssar Westerlund     {
1675e9cd1aeSAssar Westerlund 	size_t len;
168*ae771770SStanislav Sedov 	size_t i;
1695e9cd1aeSAssar Westerlund 	char *p;
1705e9cd1aeSAssar Westerlund 
1715e9cd1aeSAssar Westerlund 	len = 0;
1725e9cd1aeSAssar Westerlund 	for (i = 0; i < ent->principal->name.name_string.len; ++i)
1735e9cd1aeSAssar Westerlund 	    len += strlen(ent->principal->name.name_string.val[i]);
1745e9cd1aeSAssar Westerlund 	ret = krb5_data_alloc (&salt->salt, len);
1755e9cd1aeSAssar Westerlund 	if (ret)
1765e9cd1aeSAssar Westerlund 	    return ret;
1775e9cd1aeSAssar Westerlund 	p = salt->salt.data;
1785e9cd1aeSAssar Westerlund 	for (i = 0; i < ent->principal->name.name_string.len; ++i) {
1795e9cd1aeSAssar Westerlund 	    memcpy (p,
1805e9cd1aeSAssar Westerlund 		    ent->principal->name.name_string.val[i],
1815e9cd1aeSAssar Westerlund 		    strlen(ent->principal->name.name_string.val[i]));
1825e9cd1aeSAssar Westerlund 	    p += strlen(ent->principal->name.name_string.val[i]);
1835e9cd1aeSAssar Westerlund 	}
1845e9cd1aeSAssar Westerlund 
1855e9cd1aeSAssar Westerlund 	salt->type = KRB5_PADATA_PW_SALT;
1865e9cd1aeSAssar Westerlund 	break;
1875e9cd1aeSAssar Westerlund     }
1885e9cd1aeSAssar Westerlund     case KRB5_KDB_SALTTYPE_ONLYREALM:
1895e9cd1aeSAssar Westerlund 	krb5_data_free(&salt->salt);
1905e9cd1aeSAssar Westerlund 	ret = krb5_data_copy(&salt->salt,
1915e9cd1aeSAssar Westerlund 			     ent->principal->realm,
1925e9cd1aeSAssar Westerlund 			     strlen(ent->principal->realm));
1935e9cd1aeSAssar Westerlund 	if(ret)
1945e9cd1aeSAssar Westerlund 	    return ret;
1955e9cd1aeSAssar Westerlund 	salt->type = KRB5_PADATA_PW_SALT;
1965e9cd1aeSAssar Westerlund 	break;
1975e9cd1aeSAssar Westerlund     case KRB5_KDB_SALTTYPE_SPECIAL:
1985e9cd1aeSAssar Westerlund 	salt->type = KRB5_PADATA_PW_SALT;
1995e9cd1aeSAssar Westerlund 	break;
2005e9cd1aeSAssar Westerlund     case KRB5_KDB_SALTTYPE_AFS3:
2015e9cd1aeSAssar Westerlund 	krb5_data_free(&salt->salt);
2025e9cd1aeSAssar Westerlund 	ret = krb5_data_copy(&salt->salt,
2035e9cd1aeSAssar Westerlund 		       ent->principal->realm,
2045e9cd1aeSAssar Westerlund 		       strlen(ent->principal->realm));
2055e9cd1aeSAssar Westerlund 	if(ret)
2065e9cd1aeSAssar Westerlund 	    return ret;
2075e9cd1aeSAssar Westerlund 	salt->type = KRB5_PADATA_AFS3_SALT;
2085e9cd1aeSAssar Westerlund 	break;
2095e9cd1aeSAssar Westerlund     default:
2105e9cd1aeSAssar Westerlund 	abort();
2115e9cd1aeSAssar Westerlund     }
2125e9cd1aeSAssar Westerlund     return 0;
2135e9cd1aeSAssar Westerlund }
2145e9cd1aeSAssar Westerlund 
2155e9cd1aeSAssar Westerlund int
mit_prop_dump(void * arg,const char * file)2165e9cd1aeSAssar Westerlund mit_prop_dump(void *arg, const char *file)
2175e9cd1aeSAssar Westerlund {
2185e9cd1aeSAssar Westerlund     krb5_error_code ret;
219c19800e8SDoug Rabson     char line [2048];
2205e9cd1aeSAssar Westerlund     FILE *f;
2215e9cd1aeSAssar Westerlund     int lineno = 0;
222c19800e8SDoug Rabson     struct hdb_entry_ex ent;
2235e9cd1aeSAssar Westerlund 
2245e9cd1aeSAssar Westerlund     struct prop_data *pd = arg;
2255e9cd1aeSAssar Westerlund 
2265e9cd1aeSAssar Westerlund     f = fopen(file, "r");
2275e9cd1aeSAssar Westerlund     if(f == NULL)
2285e9cd1aeSAssar Westerlund 	return errno;
2295e9cd1aeSAssar Westerlund 
230c19800e8SDoug Rabson     while(fgets(line, sizeof(line), f)) {
231c19800e8SDoug Rabson 	char *p = line, *q;
2325e9cd1aeSAssar Westerlund 
2335e9cd1aeSAssar Westerlund 	int i;
2345e9cd1aeSAssar Westerlund 
2355e9cd1aeSAssar Westerlund 	int num_tl_data;
2365e9cd1aeSAssar Westerlund 	int num_key_data;
237*ae771770SStanislav Sedov 	int high_kvno;
2385e9cd1aeSAssar Westerlund 	int attributes;
2395e9cd1aeSAssar Westerlund 
2405e9cd1aeSAssar Westerlund 	int tmp;
2415e9cd1aeSAssar Westerlund 
2425e9cd1aeSAssar Westerlund 	lineno++;
2435e9cd1aeSAssar Westerlund 
2445e9cd1aeSAssar Westerlund 	memset(&ent, 0, sizeof(ent));
2455e9cd1aeSAssar Westerlund 
2465e9cd1aeSAssar Westerlund 	q = nexttoken(&p);
2475e9cd1aeSAssar Westerlund 	if(strcmp(q, "kdb5_util") == 0) {
2485e9cd1aeSAssar Westerlund 	    int major;
2495e9cd1aeSAssar Westerlund 	    q = nexttoken(&p); /* load_dump */
2505e9cd1aeSAssar Westerlund 	    if(strcmp(q, "load_dump"))
2515e9cd1aeSAssar Westerlund 		errx(1, "line %d: unknown version", lineno);
2525e9cd1aeSAssar Westerlund 	    q = nexttoken(&p); /* load_dump */
2535e9cd1aeSAssar Westerlund 	    if(strcmp(q, "version"))
2545e9cd1aeSAssar Westerlund 		errx(1, "line %d: unknown version", lineno);
2555e9cd1aeSAssar Westerlund 	    q = nexttoken(&p); /* x.0 */
2565e9cd1aeSAssar Westerlund 	    if(sscanf(q, "%d", &major) != 1)
2575e9cd1aeSAssar Westerlund 		errx(1, "line %d: unknown version", lineno);
258*ae771770SStanislav Sedov 	    if(major != 4 && major != 5 && major != 6)
259*ae771770SStanislav Sedov 		errx(1, "unknown dump file format, got %d, expected 4-6",
260*ae771770SStanislav Sedov 		     major);
261*ae771770SStanislav Sedov 	    continue;
262*ae771770SStanislav Sedov 	} else if(strcmp(q, "policy") == 0) {
2635e9cd1aeSAssar Westerlund 	    continue;
2645e9cd1aeSAssar Westerlund 	} else if(strcmp(q, "princ") != 0) {
2655e9cd1aeSAssar Westerlund 	    warnx("line %d: not a principal", lineno);
2665e9cd1aeSAssar Westerlund 	    continue;
2675e9cd1aeSAssar Westerlund 	}
2685e9cd1aeSAssar Westerlund 	tmp = getint(&p);
2695e9cd1aeSAssar Westerlund 	if(tmp != 38) {
2705e9cd1aeSAssar Westerlund 	    warnx("line %d: bad base length %d != 38", lineno, tmp);
2715e9cd1aeSAssar Westerlund 	    continue;
2725e9cd1aeSAssar Westerlund 	}
273*ae771770SStanislav Sedov 	nexttoken(&p); /* length of principal */
2745e9cd1aeSAssar Westerlund 	num_tl_data = getint(&p); /* number of tl-data */
2755e9cd1aeSAssar Westerlund 	num_key_data = getint(&p); /* number of key-data */
276*ae771770SStanislav Sedov 	getint(&p);  /* length of extra data */
2775e9cd1aeSAssar Westerlund 	q = nexttoken(&p); /* principal name */
278c19800e8SDoug Rabson 	krb5_parse_name(pd->context, q, &ent.entry.principal);
2795e9cd1aeSAssar Westerlund 	attributes = getint(&p); /* attributes */
280c19800e8SDoug Rabson 	attr_to_flags(attributes, &ent.entry.flags);
2815e9cd1aeSAssar Westerlund 	tmp = getint(&p); /* max life */
2825e9cd1aeSAssar Westerlund 	if(tmp != 0) {
283c19800e8SDoug Rabson 	    ALLOC(ent.entry.max_life);
284c19800e8SDoug Rabson 	    *ent.entry.max_life = tmp;
2855e9cd1aeSAssar Westerlund 	}
2865e9cd1aeSAssar Westerlund 	tmp = getint(&p); /* max renewable life */
2875e9cd1aeSAssar Westerlund 	if(tmp != 0) {
288c19800e8SDoug Rabson 	    ALLOC(ent.entry.max_renew);
289c19800e8SDoug Rabson 	    *ent.entry.max_renew = tmp;
2905e9cd1aeSAssar Westerlund 	}
2915e9cd1aeSAssar Westerlund 	tmp = getint(&p); /* expiration */
2925e9cd1aeSAssar Westerlund 	if(tmp != 0 && tmp != 2145830400) {
293c19800e8SDoug Rabson 	    ALLOC(ent.entry.valid_end);
294c19800e8SDoug Rabson 	    *ent.entry.valid_end = tmp;
2955e9cd1aeSAssar Westerlund 	}
2965e9cd1aeSAssar Westerlund 	tmp = getint(&p); /* pw expiration */
2975e9cd1aeSAssar Westerlund 	if(tmp != 0) {
298c19800e8SDoug Rabson 	    ALLOC(ent.entry.pw_end);
299c19800e8SDoug Rabson 	    *ent.entry.pw_end = tmp;
3005e9cd1aeSAssar Westerlund 	}
301*ae771770SStanislav Sedov 	nexttoken(&p); /* last auth */
302*ae771770SStanislav Sedov 	nexttoken(&p); /* last failed auth */
303*ae771770SStanislav Sedov 	nexttoken(&p); /* fail auth count */
3045e9cd1aeSAssar Westerlund 	for(i = 0; i < num_tl_data; i++) {
3055e9cd1aeSAssar Westerlund 	    unsigned long val;
3065e9cd1aeSAssar Westerlund 	    int tl_type, tl_length;
3075e9cd1aeSAssar Westerlund 	    unsigned char *buf;
3085e9cd1aeSAssar Westerlund 	    krb5_principal princ;
3095e9cd1aeSAssar Westerlund 
3105e9cd1aeSAssar Westerlund 	    tl_type = getint(&p); /* data type */
3115e9cd1aeSAssar Westerlund 	    tl_length = getint(&p); /* data length */
3125e9cd1aeSAssar Westerlund 
313c19800e8SDoug Rabson #define mit_KRB5_TL_LAST_PWD_CHANGE	1
314c19800e8SDoug Rabson #define mit_KRB5_TL_MOD_PRINC		2
3155e9cd1aeSAssar Westerlund 	    switch(tl_type) {
316*ae771770SStanislav Sedov 	    case mit_KRB5_TL_LAST_PWD_CHANGE:
317*ae771770SStanislav Sedov 		buf = malloc(tl_length);
318*ae771770SStanislav Sedov 		if (buf == NULL)
319*ae771770SStanislav Sedov 		    errx(ENOMEM, "malloc");
320*ae771770SStanislav Sedov 		getdata(&p, buf, tl_length); /* data itself */
321*ae771770SStanislav Sedov 		val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
322*ae771770SStanislav Sedov 		free(buf);
323*ae771770SStanislav Sedov 		ALLOC(ent.entry.extensions);
324*ae771770SStanislav Sedov 		ALLOC_SEQ(ent.entry.extensions, 1);
325*ae771770SStanislav Sedov 		ent.entry.extensions->val[0].mandatory = 0;
326*ae771770SStanislav Sedov 		ent.entry.extensions->val[0].data.element
327*ae771770SStanislav Sedov 		    = choice_HDB_extension_data_last_pw_change;
328*ae771770SStanislav Sedov 		ent.entry.extensions->val[0].data.u.last_pw_change = val;
329*ae771770SStanislav Sedov 		break;
330c19800e8SDoug Rabson 	    case mit_KRB5_TL_MOD_PRINC:
3315e9cd1aeSAssar Westerlund 		buf = malloc(tl_length);
332c19800e8SDoug Rabson 		if (buf == NULL)
333c19800e8SDoug Rabson 		    errx(ENOMEM, "malloc");
3345e9cd1aeSAssar Westerlund 		getdata(&p, buf, tl_length); /* data itself */
3355e9cd1aeSAssar Westerlund 		val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
336c19800e8SDoug Rabson 		ret = krb5_parse_name(pd->context, (char *)buf + 4, &princ);
337*ae771770SStanislav Sedov 		if (ret)
338*ae771770SStanislav Sedov 		    krb5_err(pd->context, 1, ret,
339*ae771770SStanislav Sedov 			     "parse_name: %s", (char *)buf + 4);
3405e9cd1aeSAssar Westerlund 		free(buf);
341c19800e8SDoug Rabson 		ALLOC(ent.entry.modified_by);
342c19800e8SDoug Rabson 		ent.entry.modified_by->time = val;
343c19800e8SDoug Rabson 		ent.entry.modified_by->principal = princ;
3445e9cd1aeSAssar Westerlund 		break;
3455e9cd1aeSAssar Westerlund 	    default:
3465e9cd1aeSAssar Westerlund 		nexttoken(&p);
3475e9cd1aeSAssar Westerlund 		break;
3485e9cd1aeSAssar Westerlund 	    }
3495e9cd1aeSAssar Westerlund 	}
350c19800e8SDoug Rabson 	ALLOC_SEQ(&ent.entry.keys, num_key_data);
351*ae771770SStanislav Sedov 	high_kvno = -1;
3525e9cd1aeSAssar Westerlund 	for(i = 0; i < num_key_data; i++) {
3535e9cd1aeSAssar Westerlund 	    int key_versions;
354*ae771770SStanislav Sedov 	    int kvno;
3555e9cd1aeSAssar Westerlund 	    key_versions = getint(&p); /* key data version */
356*ae771770SStanislav Sedov 	    kvno = getint(&p);
3575e9cd1aeSAssar Westerlund 
358*ae771770SStanislav Sedov 	    /*
359*ae771770SStanislav Sedov 	     * An MIT dump file may contain multiple sets of keys with
360*ae771770SStanislav Sedov 	     * different kvnos.  Since the Heimdal database can only represent
361*ae771770SStanislav Sedov 	     * one kvno per principal, we only want the highest set.  Assume
362*ae771770SStanislav Sedov 	     * that set will be given first, and discard all keys with lower
363*ae771770SStanislav Sedov 	     * kvnos.
364*ae771770SStanislav Sedov 	     */
365*ae771770SStanislav Sedov 	    if (kvno > high_kvno && high_kvno != -1)
366*ae771770SStanislav Sedov 		errx(1, "line %d: high kvno keys given after low kvno keys",
367*ae771770SStanislav Sedov 		     lineno);
368*ae771770SStanislav Sedov 	    else if (kvno < high_kvno) {
369*ae771770SStanislav Sedov 		nexttoken(&p); /* key type */
370*ae771770SStanislav Sedov 		nexttoken(&p); /* key length */
371*ae771770SStanislav Sedov 		nexttoken(&p); /* key */
372*ae771770SStanislav Sedov 		if (key_versions > 1) {
373*ae771770SStanislav Sedov 		    nexttoken(&p); /* salt type */
374*ae771770SStanislav Sedov 		    nexttoken(&p); /* salt length */
375*ae771770SStanislav Sedov 		    nexttoken(&p); /* salt */
376*ae771770SStanislav Sedov 		}
377*ae771770SStanislav Sedov 		ent.entry.keys.len--;
378*ae771770SStanislav Sedov 		continue;
379*ae771770SStanislav Sedov 	    }
380*ae771770SStanislav Sedov 	    ent.entry.kvno = kvno;
381*ae771770SStanislav Sedov 	    high_kvno = kvno;
382c19800e8SDoug Rabson 	    ALLOC(ent.entry.keys.val[i].mkvno);
383*ae771770SStanislav Sedov 	    *ent.entry.keys.val[i].mkvno = 1;
3845e9cd1aeSAssar Westerlund 
3855e9cd1aeSAssar Westerlund 	    /* key version 0 -- actual key */
386c19800e8SDoug Rabson 	    ent.entry.keys.val[i].key.keytype = getint(&p); /* key type */
3875e9cd1aeSAssar Westerlund 	    tmp = getint(&p); /* key length */
3885e9cd1aeSAssar Westerlund 	    /* the first two bytes of the key is the key length --
3895e9cd1aeSAssar Westerlund 	       skip it */
390c19800e8SDoug Rabson 	    krb5_data_alloc(&ent.entry.keys.val[i].key.keyvalue, tmp - 2);
3915e9cd1aeSAssar Westerlund 	    q = nexttoken(&p); /* key itself */
392c19800e8SDoug Rabson 	    hex_to_octet_string(q + 4, &ent.entry.keys.val[i].key.keyvalue);
3935e9cd1aeSAssar Westerlund 
3945e9cd1aeSAssar Westerlund 	    if(key_versions > 1) {
3955e9cd1aeSAssar Westerlund 		/* key version 1 -- optional salt */
396c19800e8SDoug Rabson 		ALLOC(ent.entry.keys.val[i].salt);
397c19800e8SDoug Rabson 		ent.entry.keys.val[i].salt->type = getint(&p); /* salt type */
3985e9cd1aeSAssar Westerlund 		tmp = getint(&p); /* salt length */
3995e9cd1aeSAssar Westerlund 		if(tmp > 0) {
400c19800e8SDoug Rabson 		    krb5_data_alloc(&ent.entry.keys.val[i].salt->salt, tmp - 2);
4015e9cd1aeSAssar Westerlund 		    q = nexttoken(&p); /* salt itself */
402c19800e8SDoug Rabson 		    hex_to_octet_string(q + 4,
403c19800e8SDoug Rabson 					&ent.entry.keys.val[i].salt->salt);
4045e9cd1aeSAssar Westerlund 		} else {
405c19800e8SDoug Rabson 		    ent.entry.keys.val[i].salt->salt.length = 0;
406c19800e8SDoug Rabson 		    ent.entry.keys.val[i].salt->salt.data = NULL;
407*ae771770SStanislav Sedov 		    getint(&p);	/* -1, if no data. */
4085e9cd1aeSAssar Westerlund 		}
409c19800e8SDoug Rabson 		fix_salt(pd->context, &ent.entry, i);
4105e9cd1aeSAssar Westerlund 	    }
4115e9cd1aeSAssar Westerlund 	}
412*ae771770SStanislav Sedov 	nexttoken(&p); /* extra data */
4135e9cd1aeSAssar Westerlund 	v5_prop(pd->context, NULL, &ent, arg);
4145e9cd1aeSAssar Westerlund     }
415c19800e8SDoug Rabson     fclose(f);
4165e9cd1aeSAssar Westerlund     return 0;
4175e9cd1aeSAssar Westerlund }
418