xref: /illumos-gate/usr/src/lib/krb5/plugins/kdb/db2/kdb_xdr.c (revision 54925bf60766fbb4f1f2d7c843721406a7b7a3fb)
1*54925bf6Swillf #pragma ident	"%Z%%M%	%I%	%E% SMI"
2*54925bf6Swillf 
3*54925bf6Swillf /*
4*54925bf6Swillf  * lib/kdb/kdb_xdr.c
5*54925bf6Swillf  *
6*54925bf6Swillf  * Copyright 1995 by the Massachusetts Institute of Technology.
7*54925bf6Swillf  * All Rights Reserved.
8*54925bf6Swillf  *
9*54925bf6Swillf  * Export of this software from the United States of America may
10*54925bf6Swillf  *   require a specific license from the United States Government.
11*54925bf6Swillf  *   It is the responsibility of any person or organization contemplating
12*54925bf6Swillf  *   export to obtain such a license before exporting.
13*54925bf6Swillf  *
14*54925bf6Swillf  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
15*54925bf6Swillf  * distribute this software and its documentation for any purpose and
16*54925bf6Swillf  * without fee is hereby granted, provided that the above copyright
17*54925bf6Swillf  * notice appear in all copies and that both that copyright notice and
18*54925bf6Swillf  * this permission notice appear in supporting documentation, and that
19*54925bf6Swillf  * the name of M.I.T. not be used in advertising or publicity pertaining
20*54925bf6Swillf  * to distribution of the software without specific, written prior
21*54925bf6Swillf  * permission.  Furthermore if you modify this software you must label
22*54925bf6Swillf  * your software as modified software and not distribute it in such a
23*54925bf6Swillf  * fashion that it might be confused with the original M.I.T. software.
24*54925bf6Swillf  * M.I.T. makes no representations about the suitability of
25*54925bf6Swillf  * this software for any purpose.  It is provided "as is" without express
26*54925bf6Swillf  * or implied warranty.
27*54925bf6Swillf  *
28*54925bf6Swillf  */
29*54925bf6Swillf 
30*54925bf6Swillf #include "k5-int.h"
31*54925bf6Swillf #include <string.h>
32*54925bf6Swillf #include <stdio.h>
33*54925bf6Swillf #include <errno.h>
34*54925bf6Swillf #include "kdb_xdr.h"
35*54925bf6Swillf 
36*54925bf6Swillf krb5_error_code
37*54925bf6Swillf krb5_encode_princ_dbkey(context, key, principal)
38*54925bf6Swillf     krb5_context context;
39*54925bf6Swillf     krb5_data  *key;
40*54925bf6Swillf     krb5_const_principal principal;
41*54925bf6Swillf {
42*54925bf6Swillf     char *princ_name;
43*54925bf6Swillf     krb5_error_code retval;
44*54925bf6Swillf 
45*54925bf6Swillf     if (!(retval = krb5_unparse_name(context, principal, &princ_name))) {
46*54925bf6Swillf         /* need to store the NULL for decoding */
47*54925bf6Swillf         key->length = strlen(princ_name)+1;
48*54925bf6Swillf         key->data = princ_name;
49*54925bf6Swillf     }
50*54925bf6Swillf     return(retval);
51*54925bf6Swillf }
52*54925bf6Swillf 
53*54925bf6Swillf void
54*54925bf6Swillf krb5_free_princ_dbkey(context, key)
55*54925bf6Swillf     krb5_context context;
56*54925bf6Swillf     krb5_data  *key;
57*54925bf6Swillf {
58*54925bf6Swillf     (void) krb5_free_data_contents(context, key);
59*54925bf6Swillf }
60*54925bf6Swillf 
61*54925bf6Swillf krb5_error_code
62*54925bf6Swillf krb5_encode_princ_contents(context, content, entry)
63*54925bf6Swillf     krb5_context 	  context;
64*54925bf6Swillf     krb5_data  		* content;
65*54925bf6Swillf     krb5_db_entry 	* entry;
66*54925bf6Swillf {
67*54925bf6Swillf     int 		  i, j;
68*54925bf6Swillf     unsigned int	  unparse_princ_size;
69*54925bf6Swillf     char 		* unparse_princ;
70*54925bf6Swillf     char		* nextloc;
71*54925bf6Swillf     krb5_tl_data	* tl_data;
72*54925bf6Swillf     krb5_error_code 	  retval;
73*54925bf6Swillf     krb5_int16		  psize16;
74*54925bf6Swillf 
75*54925bf6Swillf     /*
76*54925bf6Swillf      * Generate one lump of data from the krb5_db_entry.
77*54925bf6Swillf      * This data must be independent of byte order of the machine,
78*54925bf6Swillf      * compact and extensible.
79*54925bf6Swillf      */
80*54925bf6Swillf 
81*54925bf6Swillf     /*
82*54925bf6Swillf      * First allocate enough space for all the data.
83*54925bf6Swillf      * Need  2 bytes for the length of the base structure
84*54925bf6Swillf      * then 36 [ 8 * 4 + 2 * 2] bytes for the base information
85*54925bf6Swillf      *         [ attributes, max_life, max_renewable_life, expiration,
86*54925bf6Swillf      *	  	 pw_expiration, last_success, last_failed, fail_auth_count ]
87*54925bf6Swillf      *         [ n_key_data, n_tl_data ]
88*54925bf6Swillf      * then XX bytes [ e_length ] for the extra data [ e_data ]
89*54925bf6Swillf      * then XX bytes [ 2 for length + length for string ] for the principal,
90*54925bf6Swillf      * then (4 [type + length] + tl_data_length) bytes per tl_data
91*54925bf6Swillf      * then (4 + (4 + key_data_length) per key_data_contents) bytes per key_data
92*54925bf6Swillf      */
93*54925bf6Swillf     content->length = entry->len + entry->e_length;
94*54925bf6Swillf 
95*54925bf6Swillf     if ((retval = krb5_unparse_name(context, entry->princ, &unparse_princ)))
96*54925bf6Swillf 	return(retval);
97*54925bf6Swillf 
98*54925bf6Swillf     unparse_princ_size = strlen(unparse_princ) + 1;
99*54925bf6Swillf     content->length += unparse_princ_size;
100*54925bf6Swillf     content->length += 2;
101*54925bf6Swillf 
102*54925bf6Swillf     i = 0;
103*54925bf6Swillf     /* tl_data is a linked list */
104*54925bf6Swillf     for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
105*54925bf6Swillf 	content->length += tl_data->tl_data_length;
106*54925bf6Swillf 	content->length += 4; /* type, length */
107*54925bf6Swillf 	i++;
108*54925bf6Swillf     }
109*54925bf6Swillf 
110*54925bf6Swillf     if (i != entry->n_tl_data) {
111*54925bf6Swillf 	retval = KRB5_KDB_TRUNCATED_RECORD;
112*54925bf6Swillf 	goto epc_error;
113*54925bf6Swillf     }
114*54925bf6Swillf 
115*54925bf6Swillf     /* key_data is an array */
116*54925bf6Swillf     for (i = 0; i < entry->n_key_data; i++) {
117*54925bf6Swillf 	content->length += 4; /* Version, KVNO */
118*54925bf6Swillf 	for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
119*54925bf6Swillf 	    content->length += entry->key_data[i].key_data_length[j];
120*54925bf6Swillf 	    content->length += 4; /* type + length */
121*54925bf6Swillf 	}
122*54925bf6Swillf     }
123*54925bf6Swillf 
124*54925bf6Swillf     if ((content->data = malloc(content->length)) == NULL) {
125*54925bf6Swillf 	retval = ENOMEM;
126*54925bf6Swillf 	goto epc_error;
127*54925bf6Swillf     }
128*54925bf6Swillf 
129*54925bf6Swillf     /*
130*54925bf6Swillf      * Now we go through entry again, this time copying data
131*54925bf6Swillf      * These first entries are always saved regardless of version
132*54925bf6Swillf      */
133*54925bf6Swillf     nextloc = content->data;
134*54925bf6Swillf 
135*54925bf6Swillf 	/* Base Length */
136*54925bf6Swillf     krb5_kdb_encode_int16(entry->len, nextloc);
137*54925bf6Swillf     nextloc += 2;
138*54925bf6Swillf 
139*54925bf6Swillf 	/* Attributes */
140*54925bf6Swillf     krb5_kdb_encode_int32(entry->attributes, nextloc);
141*54925bf6Swillf     nextloc += 4;
142*54925bf6Swillf 
143*54925bf6Swillf 	/* Max Life */
144*54925bf6Swillf     krb5_kdb_encode_int32(entry->max_life, nextloc);
145*54925bf6Swillf     nextloc += 4;
146*54925bf6Swillf 
147*54925bf6Swillf 	/* Max Renewable Life */
148*54925bf6Swillf     krb5_kdb_encode_int32(entry->max_renewable_life, nextloc);
149*54925bf6Swillf     nextloc += 4;
150*54925bf6Swillf 
151*54925bf6Swillf 	/* When the client expires */
152*54925bf6Swillf     krb5_kdb_encode_int32(entry->expiration, nextloc);
153*54925bf6Swillf     nextloc += 4;
154*54925bf6Swillf 
155*54925bf6Swillf 	/* When its passwd expires */
156*54925bf6Swillf     krb5_kdb_encode_int32(entry->pw_expiration, nextloc);
157*54925bf6Swillf     nextloc += 4;
158*54925bf6Swillf 
159*54925bf6Swillf 	/* Last successful passwd */
160*54925bf6Swillf     krb5_kdb_encode_int32(entry->last_success, nextloc);
161*54925bf6Swillf     nextloc += 4;
162*54925bf6Swillf 
163*54925bf6Swillf 	/* Last failed passwd attempt */
164*54925bf6Swillf     krb5_kdb_encode_int32(entry->last_failed, nextloc);
165*54925bf6Swillf     nextloc += 4;
166*54925bf6Swillf 
167*54925bf6Swillf 	/* # of failed passwd attempt */
168*54925bf6Swillf     krb5_kdb_encode_int32(entry->fail_auth_count, nextloc);
169*54925bf6Swillf     nextloc += 4;
170*54925bf6Swillf 
171*54925bf6Swillf 	/* # tl_data strutures */
172*54925bf6Swillf     krb5_kdb_encode_int16(entry->n_tl_data, nextloc);
173*54925bf6Swillf     nextloc += 2;
174*54925bf6Swillf 
175*54925bf6Swillf 	/* # key_data strutures */
176*54925bf6Swillf     krb5_kdb_encode_int16(entry->n_key_data, nextloc);
177*54925bf6Swillf     nextloc += 2;
178*54925bf6Swillf 
179*54925bf6Swillf     	/* Put extended fields here */
180*54925bf6Swillf     if (entry->len != KRB5_KDB_V1_BASE_LENGTH)
181*54925bf6Swillf 	abort();
182*54925bf6Swillf 
183*54925bf6Swillf 	/* Any extra data that this version doesn't understand. */
184*54925bf6Swillf     if (entry->e_length) {
185*54925bf6Swillf 	memcpy(nextloc, entry->e_data, entry->e_length);
186*54925bf6Swillf 	nextloc += entry->e_length;
187*54925bf6Swillf     }
188*54925bf6Swillf 
189*54925bf6Swillf 	/*
190*54925bf6Swillf 	 * Now we get to the principal.
191*54925bf6Swillf 	 * To squeze a few extra bytes out it is always assumed to come
192*54925bf6Swillf 	 * after the base type.
193*54925bf6Swillf 	 */
194*54925bf6Swillf     psize16 = (krb5_int16) unparse_princ_size;
195*54925bf6Swillf     krb5_kdb_encode_int16(psize16, nextloc);
196*54925bf6Swillf     nextloc += 2;
197*54925bf6Swillf     (void) memcpy(nextloc, unparse_princ, unparse_princ_size);
198*54925bf6Swillf     nextloc += unparse_princ_size;
199*54925bf6Swillf 
200*54925bf6Swillf     	/* tl_data is a linked list, of type, legth, contents */
201*54925bf6Swillf     for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
202*54925bf6Swillf 	krb5_kdb_encode_int16(tl_data->tl_data_type, nextloc);
203*54925bf6Swillf 	nextloc += 2;
204*54925bf6Swillf 	krb5_kdb_encode_int16(tl_data->tl_data_length, nextloc);
205*54925bf6Swillf 	nextloc += 2;
206*54925bf6Swillf 
207*54925bf6Swillf 	memcpy(nextloc, tl_data->tl_data_contents, tl_data->tl_data_length);
208*54925bf6Swillf 	nextloc += tl_data->tl_data_length;
209*54925bf6Swillf     }
210*54925bf6Swillf 
211*54925bf6Swillf     	/* key_data is an array */
212*54925bf6Swillf     for (i = 0; i < entry->n_key_data; i++) {
213*54925bf6Swillf 	krb5_kdb_encode_int16(entry->key_data[i].key_data_ver, nextloc);
214*54925bf6Swillf 	nextloc += 2;
215*54925bf6Swillf 	krb5_kdb_encode_int16(entry->key_data[i].key_data_kvno, nextloc);
216*54925bf6Swillf 	nextloc += 2;
217*54925bf6Swillf 
218*54925bf6Swillf 	for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
219*54925bf6Swillf 	    krb5_int16 type = entry->key_data[i].key_data_type[j];
220*54925bf6Swillf 	    krb5_ui_2  length = entry->key_data[i].key_data_length[j];
221*54925bf6Swillf 
222*54925bf6Swillf     	    krb5_kdb_encode_int16(type, nextloc);
223*54925bf6Swillf 	    nextloc += 2;
224*54925bf6Swillf     	    krb5_kdb_encode_int16(length, nextloc);
225*54925bf6Swillf 	    nextloc += 2;
226*54925bf6Swillf 
227*54925bf6Swillf 	    if (length) {
228*54925bf6Swillf 	        memcpy(nextloc, entry->key_data[i].key_data_contents[j],length);
229*54925bf6Swillf 	        nextloc += length;
230*54925bf6Swillf 	    }
231*54925bf6Swillf 	}
232*54925bf6Swillf     }
233*54925bf6Swillf 
234*54925bf6Swillf epc_error:;
235*54925bf6Swillf     free(unparse_princ);
236*54925bf6Swillf     return retval;
237*54925bf6Swillf }
238*54925bf6Swillf 
239*54925bf6Swillf void
240*54925bf6Swillf krb5_free_princ_contents(context, contents)
241*54925bf6Swillf     krb5_context 	  context;
242*54925bf6Swillf     krb5_data *contents;
243*54925bf6Swillf {
244*54925bf6Swillf     krb5_free_data_contents(context, contents);
245*54925bf6Swillf     return;
246*54925bf6Swillf }
247*54925bf6Swillf 
248*54925bf6Swillf krb5_error_code
249*54925bf6Swillf krb5_decode_princ_contents(context, content, entry)
250*54925bf6Swillf     krb5_context 	  context;
251*54925bf6Swillf     krb5_data  		* content;
252*54925bf6Swillf     krb5_db_entry 	* entry;
253*54925bf6Swillf {
254*54925bf6Swillf     int			  sizeleft, i;
255*54925bf6Swillf     char 		* nextloc;
256*54925bf6Swillf     krb5_tl_data       ** tl_data;
257*54925bf6Swillf     krb5_int16		  i16;
258*54925bf6Swillf 
259*54925bf6Swillf     krb5_error_code retval;
260*54925bf6Swillf 
261*54925bf6Swillf     /* Zero out entry and NULL pointers */
262*54925bf6Swillf     memset(entry, 0, sizeof(krb5_db_entry));
263*54925bf6Swillf 
264*54925bf6Swillf     /*
265*54925bf6Swillf      * undo the effects of encode_princ_contents.
266*54925bf6Swillf      *
267*54925bf6Swillf      * The first part is decoding the base type. If the base type is
268*54925bf6Swillf      * bigger than the original base type then the additional fields
269*54925bf6Swillf      * need to be filled in. If the base type is larger than any
270*54925bf6Swillf      * known base type the additional data goes in e_data.
271*54925bf6Swillf      */
272*54925bf6Swillf 
273*54925bf6Swillf     /* First do the easy stuff */
274*54925bf6Swillf     nextloc = content->data;
275*54925bf6Swillf     sizeleft = content->length;
276*54925bf6Swillf     if ((sizeleft -= KRB5_KDB_V1_BASE_LENGTH) < 0)
277*54925bf6Swillf 	return KRB5_KDB_TRUNCATED_RECORD;
278*54925bf6Swillf 
279*54925bf6Swillf 	/* Base Length */
280*54925bf6Swillf     krb5_kdb_decode_int16(nextloc, entry->len);
281*54925bf6Swillf     nextloc += 2;
282*54925bf6Swillf 
283*54925bf6Swillf 	/* Attributes */
284*54925bf6Swillf     krb5_kdb_decode_int32(nextloc, entry->attributes);
285*54925bf6Swillf     nextloc += 4;
286*54925bf6Swillf 
287*54925bf6Swillf 	/* Max Life */
288*54925bf6Swillf     krb5_kdb_decode_int32(nextloc, entry->max_life);
289*54925bf6Swillf     nextloc += 4;
290*54925bf6Swillf 
291*54925bf6Swillf 	/* Max Renewable Life */
292*54925bf6Swillf     krb5_kdb_decode_int32(nextloc, entry->max_renewable_life);
293*54925bf6Swillf     nextloc += 4;
294*54925bf6Swillf 
295*54925bf6Swillf 	/* When the client expires */
296*54925bf6Swillf     krb5_kdb_decode_int32(nextloc, entry->expiration);
297*54925bf6Swillf     nextloc += 4;
298*54925bf6Swillf 
299*54925bf6Swillf 	/* When its passwd expires */
300*54925bf6Swillf     krb5_kdb_decode_int32(nextloc, entry->pw_expiration);
301*54925bf6Swillf     nextloc += 4;
302*54925bf6Swillf 
303*54925bf6Swillf 	/* Last successful passwd */
304*54925bf6Swillf     krb5_kdb_decode_int32(nextloc, entry->last_success);
305*54925bf6Swillf     nextloc += 4;
306*54925bf6Swillf 
307*54925bf6Swillf 	/* Last failed passwd attempt */
308*54925bf6Swillf     krb5_kdb_decode_int32(nextloc, entry->last_failed);
309*54925bf6Swillf     nextloc += 4;
310*54925bf6Swillf 
311*54925bf6Swillf 	/* # of failed passwd attempt */
312*54925bf6Swillf     krb5_kdb_decode_int32(nextloc, entry->fail_auth_count);
313*54925bf6Swillf     nextloc += 4;
314*54925bf6Swillf 
315*54925bf6Swillf 	/* # tl_data strutures */
316*54925bf6Swillf     krb5_kdb_decode_int16(nextloc, entry->n_tl_data);
317*54925bf6Swillf     nextloc += 2;
318*54925bf6Swillf 
319*54925bf6Swillf     if (entry->n_tl_data < 0)
320*54925bf6Swillf 	return KRB5_KDB_TRUNCATED_RECORD;
321*54925bf6Swillf 
322*54925bf6Swillf 	/* # key_data strutures */
323*54925bf6Swillf     krb5_kdb_decode_int16(nextloc, entry->n_key_data);
324*54925bf6Swillf     nextloc += 2;
325*54925bf6Swillf 
326*54925bf6Swillf     if (entry->n_key_data < 0)
327*54925bf6Swillf 	return KRB5_KDB_TRUNCATED_RECORD;
328*54925bf6Swillf 
329*54925bf6Swillf 	/* Check for extra data */
330*54925bf6Swillf     if (entry->len > KRB5_KDB_V1_BASE_LENGTH) {
331*54925bf6Swillf 	entry->e_length = entry->len - KRB5_KDB_V1_BASE_LENGTH;
332*54925bf6Swillf 	if ((entry->e_data = (krb5_octet *)malloc(entry->e_length))) {
333*54925bf6Swillf 	    memcpy(entry->e_data, nextloc, entry->e_length);
334*54925bf6Swillf 	    nextloc += entry->e_length;
335*54925bf6Swillf 	} else {
336*54925bf6Swillf 	    return ENOMEM;
337*54925bf6Swillf 	}
338*54925bf6Swillf     }
339*54925bf6Swillf 
340*54925bf6Swillf     /*
341*54925bf6Swillf      * Get the principal name for the entry
342*54925bf6Swillf      * (stored as a string which gets unparsed.)
343*54925bf6Swillf      */
344*54925bf6Swillf     if ((sizeleft -= 2) < 0) {
345*54925bf6Swillf 	retval = KRB5_KDB_TRUNCATED_RECORD;
346*54925bf6Swillf 	goto error_out;
347*54925bf6Swillf     }
348*54925bf6Swillf 
349*54925bf6Swillf     i = 0;
350*54925bf6Swillf     krb5_kdb_decode_int16(nextloc, i16);
351*54925bf6Swillf     i = (int) i16;
352*54925bf6Swillf     nextloc += 2;
353*54925bf6Swillf 
354*54925bf6Swillf     if ((retval = krb5_parse_name(context, nextloc, &(entry->princ))))
355*54925bf6Swillf 	goto error_out;
356*54925bf6Swillf     if (((size_t) i != (strlen(nextloc) + 1)) || (sizeleft < i)) {
357*54925bf6Swillf 	retval = KRB5_KDB_TRUNCATED_RECORD;
358*54925bf6Swillf 	goto error_out;
359*54925bf6Swillf     }
360*54925bf6Swillf     sizeleft -= i;
361*54925bf6Swillf     nextloc += i;
362*54925bf6Swillf 
363*54925bf6Swillf     	/* tl_data is a linked list */
364*54925bf6Swillf     tl_data = &entry->tl_data;
365*54925bf6Swillf     for (i = 0; i < entry->n_tl_data; i++) {
366*54925bf6Swillf     	if ((sizeleft -= 4) < 0) {
367*54925bf6Swillf 	    retval = KRB5_KDB_TRUNCATED_RECORD;
368*54925bf6Swillf 	    goto error_out;
369*54925bf6Swillf 	}
370*54925bf6Swillf 	if ((*tl_data = (krb5_tl_data *)
371*54925bf6Swillf 	  malloc(sizeof(krb5_tl_data))) == NULL) {
372*54925bf6Swillf 	    retval = ENOMEM;
373*54925bf6Swillf 	    goto error_out;
374*54925bf6Swillf 	}
375*54925bf6Swillf 	(*tl_data)->tl_data_next = NULL;
376*54925bf6Swillf 	(*tl_data)->tl_data_contents = NULL;
377*54925bf6Swillf 	krb5_kdb_decode_int16(nextloc, (*tl_data)->tl_data_type);
378*54925bf6Swillf 	nextloc += 2;
379*54925bf6Swillf 	krb5_kdb_decode_int16(nextloc, (*tl_data)->tl_data_length);
380*54925bf6Swillf 	nextloc += 2;
381*54925bf6Swillf 
382*54925bf6Swillf     	if ((sizeleft -= (*tl_data)->tl_data_length) < 0) {
383*54925bf6Swillf 	    retval = KRB5_KDB_TRUNCATED_RECORD;
384*54925bf6Swillf 	    goto error_out;
385*54925bf6Swillf 	}
386*54925bf6Swillf 	if (((*tl_data)->tl_data_contents = (krb5_octet *)
387*54925bf6Swillf 	  malloc((*tl_data)->tl_data_length)) == NULL) {
388*54925bf6Swillf 	    retval = ENOMEM;
389*54925bf6Swillf 	    goto error_out;
390*54925bf6Swillf 	}
391*54925bf6Swillf 	memcpy((*tl_data)->tl_data_contents,nextloc,(*tl_data)->tl_data_length);
392*54925bf6Swillf 	nextloc += (*tl_data)->tl_data_length;
393*54925bf6Swillf 	tl_data = &((*tl_data)->tl_data_next);
394*54925bf6Swillf     }
395*54925bf6Swillf 
396*54925bf6Swillf     	/* key_data is an array */
397*54925bf6Swillf     if (entry->n_key_data && ((entry->key_data = (krb5_key_data *)
398*54925bf6Swillf       malloc(sizeof(krb5_key_data) * entry->n_key_data)) == NULL)) {
399*54925bf6Swillf         retval = ENOMEM;
400*54925bf6Swillf 	goto error_out;
401*54925bf6Swillf     }
402*54925bf6Swillf     for (i = 0; i < entry->n_key_data; i++) {
403*54925bf6Swillf 	krb5_key_data * key_data;
404*54925bf6Swillf         int j;
405*54925bf6Swillf 
406*54925bf6Swillf     	if ((sizeleft -= 4) < 0) {
407*54925bf6Swillf 	    retval = KRB5_KDB_TRUNCATED_RECORD;
408*54925bf6Swillf 	    goto error_out;
409*54925bf6Swillf 	}
410*54925bf6Swillf 	key_data = entry->key_data + i;
411*54925bf6Swillf 	memset(key_data, 0, sizeof(krb5_key_data));
412*54925bf6Swillf 	krb5_kdb_decode_int16(nextloc, key_data->key_data_ver);
413*54925bf6Swillf 	nextloc += 2;
414*54925bf6Swillf 	krb5_kdb_decode_int16(nextloc, key_data->key_data_kvno);
415*54925bf6Swillf 	nextloc += 2;
416*54925bf6Swillf 
417*54925bf6Swillf 	/* key_data_ver determins number of elements and how to unparse them. */
418*54925bf6Swillf 	if (key_data->key_data_ver <= KRB5_KDB_V1_KEY_DATA_ARRAY) {
419*54925bf6Swillf 	    for (j = 0; j < key_data->key_data_ver; j++) {
420*54925bf6Swillf     	        if ((sizeleft -= 4) < 0) {
421*54925bf6Swillf 	            retval = KRB5_KDB_TRUNCATED_RECORD;
422*54925bf6Swillf 	            goto error_out;
423*54925bf6Swillf 	        }
424*54925bf6Swillf 		krb5_kdb_decode_int16(nextloc, key_data->key_data_type[j]);
425*54925bf6Swillf 		nextloc += 2;
426*54925bf6Swillf 		krb5_kdb_decode_int16(nextloc, key_data->key_data_length[j]);
427*54925bf6Swillf 		nextloc += 2;
428*54925bf6Swillf 
429*54925bf6Swillf     	        if ((sizeleft -= key_data->key_data_length[j]) < 0) {
430*54925bf6Swillf 	            retval = KRB5_KDB_TRUNCATED_RECORD;
431*54925bf6Swillf 	            goto error_out;
432*54925bf6Swillf 	        }
433*54925bf6Swillf 	        if (key_data->key_data_length[j]) {
434*54925bf6Swillf 	    	    if ((key_data->key_data_contents[j] = (krb5_octet *)
435*54925bf6Swillf 	    	      malloc(key_data->key_data_length[j])) == NULL) {
436*54925bf6Swillf 	                retval = ENOMEM;
437*54925bf6Swillf 	                goto error_out;
438*54925bf6Swillf 	            }
439*54925bf6Swillf 	            memcpy(key_data->key_data_contents[j], nextloc,
440*54925bf6Swillf 		           key_data->key_data_length[j]);
441*54925bf6Swillf 	            nextloc += key_data->key_data_length[j];
442*54925bf6Swillf 		}
443*54925bf6Swillf 	    }
444*54925bf6Swillf 	} else {
445*54925bf6Swillf 	    /* This isn't right. I'll fix it later */
446*54925bf6Swillf 	    abort();
447*54925bf6Swillf 	}
448*54925bf6Swillf     }
449*54925bf6Swillf     return 0;
450*54925bf6Swillf 
451*54925bf6Swillf error_out:;
452*54925bf6Swillf     krb5_dbe_free_contents(context, entry);
453*54925bf6Swillf     return retval;
454*54925bf6Swillf }
455*54925bf6Swillf 
456*54925bf6Swillf void
457*54925bf6Swillf krb5_dbe_free_contents(context, entry)
458*54925bf6Swillf      krb5_context 	  context;
459*54925bf6Swillf      krb5_db_entry 	* entry;
460*54925bf6Swillf {
461*54925bf6Swillf     krb5_tl_data 	* tl_data_next;
462*54925bf6Swillf     krb5_tl_data 	* tl_data;
463*54925bf6Swillf     int i, j;
464*54925bf6Swillf 
465*54925bf6Swillf     if (entry->e_data)
466*54925bf6Swillf 	free(entry->e_data);
467*54925bf6Swillf     if (entry->princ)
468*54925bf6Swillf 	krb5_free_principal(context, entry->princ);
469*54925bf6Swillf     for (tl_data = entry->tl_data; tl_data; tl_data = tl_data_next) {
470*54925bf6Swillf 	tl_data_next = tl_data->tl_data_next;
471*54925bf6Swillf 	if (tl_data->tl_data_contents)
472*54925bf6Swillf 	    free(tl_data->tl_data_contents);
473*54925bf6Swillf 	free(tl_data);
474*54925bf6Swillf     }
475*54925bf6Swillf     if (entry->key_data) {
476*54925bf6Swillf     	for (i = 0; i < entry->n_key_data; i++) {
477*54925bf6Swillf 	    for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
478*54925bf6Swillf 	    	if (entry->key_data[i].key_data_length[j]) {
479*54925bf6Swillf 		    if (entry->key_data[i].key_data_contents[j]) {
480*54925bf6Swillf 		        memset(entry->key_data[i].key_data_contents[j],
481*54925bf6Swillf 			       0,
482*54925bf6Swillf 			       (unsigned) entry->key_data[i].key_data_length[j]);
483*54925bf6Swillf 		    	free (entry->key_data[i].key_data_contents[j]);
484*54925bf6Swillf 		    }
485*54925bf6Swillf 		}
486*54925bf6Swillf 		entry->key_data[i].key_data_contents[j] = NULL;
487*54925bf6Swillf 		entry->key_data[i].key_data_length[j] = 0;
488*54925bf6Swillf 		entry->key_data[i].key_data_type[j] = 0;
489*54925bf6Swillf 	    }
490*54925bf6Swillf 	}
491*54925bf6Swillf 	free(entry->key_data);
492*54925bf6Swillf     }
493*54925bf6Swillf     memset(entry, 0, sizeof(*entry));
494*54925bf6Swillf     return;
495*54925bf6Swillf }
496