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