xref: /titanic_52/usr/src/uts/common/gssapi/mechs/krb5/krb5/krb/kfree.c (revision 159d09a20817016f09b3ea28d1bdada4a336bb91)
1 /*
2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 
7 /*
8  * Copyright 1990-1998 by the Massachusetts Institute of Technology.
9  *
10  * Export of this software from the United States of America may
11  *   require a specific license from the United States Government.
12  *   It is the responsibility of any person or organization contemplating
13  *   export to obtain such a license before exporting.
14  *
15  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
16  * distribute this software and its documentation for any purpose and
17  * without fee is hereby granted, provided that the above copyright
18  * notice appear in all copies and that both that copyright notice and
19  * this permission notice appear in supporting documentation, and that
20  * the name of M.I.T. not be used in advertising or publicity pertaining
21  * to distribution of the software without specific, written prior
22  * permission.  Furthermore if you modify this software you must label
23  * your software as modified software and not distribute it in such a
24  * fashion that it might be confused with the original M.I.T. software.
25  * M.I.T. makes no representations about the suitability of
26  * this software for any purpose.  It is provided "as is" without express
27  * or implied warranty.
28  *
29  *
30  * krb5_free_address()
31  */
32 
33 #include "k5-int.h"
34 
35 static void cleanup_dk_list(krb5_context, krb5_keyblock *);
36 
37 /* ARGSUSED */
38 void KRB5_CALLCONV
39 krb5_free_address(krb5_context context, krb5_address *val)
40 {
41     if (val->contents)
42 	krb5_xfree_wrap(val->contents, val->length);
43     krb5_xfree_wrap(val, sizeof(krb5_address));
44 }
45 
46 #ifndef _KERNEL
47 void KRB5_CALLCONV
48 krb5_free_addresses(krb5_context context, krb5_address **val)
49 {
50     register krb5_address **temp;
51 
52     for (temp = val; *temp; temp++) {
53 	if ((*temp)->contents)
54 	    krb5_xfree((*temp)->contents);
55 	krb5_xfree(*temp);
56     }
57     krb5_xfree(val);
58 }
59 
60 
61 void KRB5_CALLCONV
62 krb5_free_ap_rep(krb5_context context, register krb5_ap_rep *val)
63 {
64     if (val->enc_part.ciphertext.data) {
65 	krb5_xfree(val->enc_part.ciphertext.data);
66 	val->enc_part.ciphertext.data = 0;
67     }
68     krb5_xfree(val);
69 }
70 
71 void KRB5_CALLCONV
72 krb5_free_ap_req(krb5_context context, register krb5_ap_req *val)
73 {
74     if (val->ticket) {
75 	krb5_free_ticket(context, val->ticket);
76 	val->ticket = 0;
77     }
78     if (val->authenticator.ciphertext.data) {
79 	krb5_xfree(val->authenticator.ciphertext.data);
80 	val->authenticator.ciphertext.data = 0;
81     }
82     krb5_xfree(val);
83 }
84 
85 void KRB5_CALLCONV
86 krb5_free_ap_rep_enc_part(krb5_context context, krb5_ap_rep_enc_part *val)
87 {
88     if (val->subkey)
89 	krb5_free_keyblock(context, val->subkey);
90     krb5_xfree(val);
91 }
92 #endif	/* !_KERNEL */
93 
94 void KRB5_CALLCONV
95 krb5_free_authenticator_contents(krb5_context context, krb5_authenticator *val)
96 {
97     if (val->checksum) {
98 	krb5_free_checksum(context, val->checksum);
99 	val->checksum = 0;
100     }
101     if (val->client) {
102 	krb5_free_principal(context, val->client);
103 	val->client = 0;
104     }
105     if (val->subkey) {
106 	krb5_free_keyblock(context, val->subkey);
107 	val->subkey = 0;
108     }
109     if (val->authorization_data) {
110 	krb5_free_authdata(context, val->authorization_data);
111 	val->authorization_data = 0;
112     }
113 }
114 
115 /* ARGSUSED */
116 void KRB5_CALLCONV
117 krb5_free_authdata(krb5_context context, krb5_authdata **val)
118 {
119     register krb5_authdata **temp;
120 
121     for (temp = val; *temp; temp++) {
122 	if ((*temp)->contents)
123 	    krb5_xfree_wrap((*temp)->contents, (*temp)->length);
124 	krb5_xfree_wrap(*temp, sizeof(krb5_authdata));
125     }
126     /* Note val points to an array of pointers and (++temp - val) is # of bytes
127      * in that array.
128      */
129     krb5_xfree_wrap(val, (++temp - val));
130 }
131 
132 void KRB5_CALLCONV
133 krb5_free_authenticator(krb5_context context, krb5_authenticator *val)
134 {
135     krb5_free_authenticator_contents(context, val);
136     krb5_xfree_wrap(val, sizeof(krb5_authenticator));
137 }
138 
139 void KRB5_CALLCONV
140 krb5_free_checksum(krb5_context context, register krb5_checksum *val)
141 {
142     krb5_free_checksum_contents(context, val);
143     krb5_xfree_wrap(val, sizeof(krb5_checksum));
144 }
145 
146 /* ARGSUSED */
147 void KRB5_CALLCONV
148 krb5_free_checksum_contents(krb5_context context, register krb5_checksum *val)
149 {
150     if (val->contents) {
151 	krb5_xfree_wrap(val->contents, val->length);
152 	val->length = 0;
153 	val->contents = 0;
154     }
155 }
156 
157 #ifndef _KERNEL
158 void KRB5_CALLCONV
159 krb5_free_cred(krb5_context context, register krb5_cred *val)
160 {
161     if (val->tickets) {
162         krb5_free_tickets(context, val->tickets);
163 	val->tickets = 0;
164     }
165     if (val->enc_part.ciphertext.data) {
166 	krb5_xfree(val->enc_part.ciphertext.data);
167 	val->enc_part.ciphertext.data = 0;
168     }
169     krb5_xfree(val);
170 }
171 
172 /*
173  * krb5_free_cred_contents zeros out the session key, and then frees
174  * the credentials structures
175  */
176 
177 void KRB5_CALLCONV
178 krb5_free_cred_contents(krb5_context context, krb5_creds *val)
179 {
180     if (val->client) {
181 	krb5_free_principal(context, val->client);
182 	val->client = 0;
183     }
184     if (val->server) {
185 	krb5_free_principal(context, val->server);
186 	val->server = 0;
187     }
188 
189     krb5_free_keyblock_contents(context, &val->keyblock);
190 
191     if (val->ticket.data) {
192 	krb5_xfree(val->ticket.data);
193 	val->ticket.data = 0;
194     }
195     if (val->second_ticket.data) {
196 	krb5_xfree(val->second_ticket.data);
197 	val->second_ticket.data = 0;
198     }
199     if (val->addresses) {
200 	krb5_free_addresses(context, val->addresses);
201 	val->addresses = 0;
202     }
203     if (val->authdata) {
204 	krb5_free_authdata(context, val->authdata);
205 	val->authdata = 0;
206     }
207 }
208 
209 void KRB5_CALLCONV
210 krb5_free_cred_enc_part(krb5_context context, register krb5_cred_enc_part *val)
211 {
212     register krb5_cred_info **temp;
213 
214     if (val->r_address) {
215 	krb5_free_address(context, val->r_address);
216 	val->r_address = 0;
217     }
218     if (val->s_address) {
219 	krb5_free_address(context, val->s_address);
220 	val->s_address = 0;
221     }
222 
223     if (val->ticket_info) {
224 	for (temp = val->ticket_info; *temp; temp++) {
225 	    if ((*temp)->session)
226 		krb5_free_keyblock(context, (*temp)->session);
227 	    if ((*temp)->client)
228 		krb5_free_principal(context, (*temp)->client);
229 	    if ((*temp)->server)
230 		krb5_free_principal(context, (*temp)->server);
231 	    if ((*temp)->caddrs)
232 		krb5_free_addresses(context, (*temp)->caddrs);
233 	    krb5_xfree((*temp));
234 	}
235 	krb5_xfree(val->ticket_info);
236 	val->ticket_info = 0;
237     }
238 }
239 
240 
241 void KRB5_CALLCONV
242 krb5_free_creds(krb5_context context, krb5_creds *val)
243 {
244     krb5_free_cred_contents(context, val);
245     krb5_xfree(val);
246 }
247 
248 /* ARGSUSED */
249 void KRB5_CALLCONV
250 krb5_free_data(krb5_context context, krb5_data *val)
251 {
252     if (val->data) {
253 	krb5_xfree(val->data);
254 	val->data = 0;
255     }
256     krb5_xfree(val);
257 }
258 #endif	/* !_KERNEL */
259 
260 /* ARGSUSED */
261 void KRB5_CALLCONV
262 krb5_free_data_contents(krb5_context context, krb5_data *val)
263 {
264     if (val->data) {
265 	krb5_xfree_wrap(val->data, val->length);
266 	val->length = 0;
267         val->data = 0;
268     }
269 }
270 
271 #ifndef _KERNEL
272 void krb5_free_etype_info(krb5_context context, krb5_etype_info info)
273 {
274   int i;
275 
276   for(i=0; info[i] != NULL; i++) {
277       if (info[i]->salt)
278 	  free(info[i]->salt);
279       krb5_free_data_contents(context, &info[i]->s2kparams);
280       free(info[i]);
281   }
282   free(info);
283 }
284 
285 
286 void KRB5_CALLCONV
287 krb5_free_enc_kdc_rep_part(krb5_context context, register krb5_enc_kdc_rep_part *val)
288 {
289     if (val->session)
290 	krb5_free_keyblock(context, val->session);
291     if (val->last_req)
292 	krb5_free_last_req(context, val->last_req);
293     if (val->server)
294 	krb5_free_principal(context, val->server);
295     if (val->caddrs)
296 	krb5_free_addresses(context, val->caddrs);
297     krb5_xfree(val);
298 }
299 
300 void KRB5_CALLCONV
301 krb5_free_enc_tkt_part(krb5_context context, krb5_enc_tkt_part *val)
302 {
303     if (val->session) {
304 	krb5_free_keyblock(context, val->session);
305 	val->session = 0;
306     }
307     if (val->client)
308 	krb5_free_principal(context, val->client);
309     if (val->transited.tr_contents.data) {
310 	krb5_xfree(val->transited.tr_contents.data);
311 	val->transited.tr_contents.data = 0;
312     }
313     if (val->caddrs)
314 	krb5_free_addresses(context, val->caddrs);
315     if (val->authorization_data) {
316 	krb5_free_authdata(context, val->authorization_data);
317 	val->authorization_data = 0;
318     }
319     krb5_xfree(val);
320 }
321 #endif	/* !_KERNEL */
322 
323 void KRB5_CALLCONV
324 krb5_free_error(krb5_context context, register krb5_error *val)
325 {
326     if (val->client)
327 	krb5_free_principal(context, val->client);
328     if (val->server)
329 	krb5_free_principal(context, val->server);
330     if (val->text.data)
331 	krb5_xfree_wrap(val->text.data, val->text.length);
332     if (val->e_data.data)
333 	krb5_xfree_wrap(val->e_data.data, val->e_data.length);
334     krb5_xfree_wrap(val, sizeof (krb5_error));
335 }
336 
337 #ifndef _KERNEL
338 void KRB5_CALLCONV
339 krb5_free_kdc_rep(krb5_context context, krb5_kdc_rep *val)
340 {
341     if (val->padata) {
342 	krb5_free_pa_data(context, val->padata);
343 	val->padata = 0;
344     }
345     if (val->client) {
346 	krb5_free_principal(context, val->client);
347 	val->client = 0;
348     }
349     if (val->ticket) {
350 	krb5_free_ticket(context, val->ticket);
351 	val->ticket = 0;
352     }
353     if (val->enc_part.ciphertext.data) {
354 	krb5_xfree(val->enc_part.ciphertext.data);
355 	val->enc_part.ciphertext.data = 0;
356     }
357     if (val->enc_part2) {
358 	krb5_free_enc_kdc_rep_part(context, val->enc_part2);
359 	val->enc_part2 = 0;
360     }
361     krb5_xfree(val);
362 }
363 
364 
365 void KRB5_CALLCONV
366 krb5_free_kdc_req(krb5_context context, krb5_kdc_req *val)
367 {
368     if (val->padata) {
369 	krb5_free_pa_data(context, val->padata);
370 	val->padata = 0;
371     }
372     if (val->client) {
373 	krb5_free_principal(context, val->client);
374 	val->client = 0;
375     }
376     if (val->server) {
377 	krb5_free_principal(context, val->server);
378 	val->server = 0;
379     }
380     if (val->ktype) {
381 	krb5_xfree(val->ktype);
382 	val->ktype = 0;
383     }
384     if (val->addresses) {
385 	krb5_free_addresses(context, val->addresses);
386 	val->addresses = 0;
387     }
388     if (val->authorization_data.ciphertext.data) {
389 	krb5_xfree(val->authorization_data.ciphertext.data);
390 	val->authorization_data.ciphertext.data = 0;
391     }
392     if (val->unenc_authdata) {
393 	krb5_free_authdata(context, val->unenc_authdata);
394 	val->unenc_authdata = 0;
395     }
396     if (val->second_ticket) {
397 	krb5_free_tickets(context, val->second_ticket);
398 	val->second_ticket = 0;
399     }
400     krb5_xfree(val);
401 }
402 #endif	/* !_KERNEL */
403 
404 /*
405  * Delete a key's derived key list
406  */
407 static void
408 cleanup_dk_list(krb5_context context, krb5_keyblock *key)
409 {
410 	krb5_dk_node *dn = key->dk_list;
411 	krb5_dk_node *nxt;
412 
413 	while (dn != NULL) {
414 		nxt = dn->next;
415 
416 		if (dn->derived_key != NULL) {
417 			/*
418 			 * Some recursion here but its OK,
419 			 * it stops when a NULL dk_list
420 			 * is encountered.
421 			 */
422 			krb5_free_keyblock(context, dn->derived_key);
423 			dn->derived_key = NULL;
424 		}
425 
426 		FREE(dn, sizeof(krb5_dk_node));
427 
428 		dn = nxt;
429 	}
430 	key->dk_list = NULL;
431 }
432 
433 /* ARGSUSED */
434 void KRB5_CALLCONV
435 krb5_free_keyblock_contents(krb5_context context, register krb5_keyblock *key)
436 {
437      if (key->contents) {
438 	  (void) memset(key->contents, 0, key->length);
439 	  krb5_xfree_wrap(key->contents, key->length);
440 	  key->length = 0;
441 	  key->contents = 0;
442      }
443 #ifdef _KERNEL
444      if (key->key_tmpl != NULL)
445 	(void) crypto_destroy_ctx_template(key->key_tmpl);
446 #else
447      if (key->hKey != CK_INVALID_HANDLE) {
448 	CK_RV rv;
449 	rv = C_DestroyObject(krb_ctx_hSession(context), key->hKey);
450 	if (rv != CKR_OK) {
451 		KRB5_LOG(KRB5_ERR, "krb5_free_keyblock_contents: "
452 			"C_DestroyObject = %0x", rv);
453 	}
454 	key->hKey = CK_INVALID_HANDLE;
455      }
456 #endif /* _KERNEL */
457      /*
458       * If the original key data is freed, we should also free
459       * any keys derived from that data.
460       * This saves us from making additional calls to "cleanup_dk_list"
461       * in all of the many function which have keyblock structures
462       * declared on the stack that re-use the keyblock data contents
463       * without freeing the entire keyblock record.
464       */
465      cleanup_dk_list(context, key);
466 }
467 
468 void KRB5_CALLCONV
469 krb5_free_keyblock(krb5_context context, register krb5_keyblock *val)
470 {
471     if (!val)
472         return;
473 
474     krb5_free_keyblock_contents(context, val);
475 
476     krb5_xfree_wrap(val, sizeof(krb5_keyblock));
477 }
478 
479 #ifndef _KERNEL
480 void KRB5_CALLCONV
481 krb5_free_last_req(krb5_context context, krb5_last_req_entry **val)
482 {
483     register krb5_last_req_entry **temp;
484 
485     for (temp = val; *temp; temp++)
486 	krb5_xfree(*temp);
487     krb5_xfree(val);
488 }
489 
490 void KRB5_CALLCONV
491 krb5_free_pa_data(krb5_context context, krb5_pa_data **val)
492 {
493     register krb5_pa_data **temp;
494 
495     for (temp = val; *temp; temp++) {
496 	if ((*temp)->contents)
497 	    krb5_xfree((*temp)->contents);
498 	krb5_xfree(*temp);
499     }
500     krb5_xfree(val);
501 }
502 #endif	/* !_KERNEL */
503 
504 /* ARGSUSED */
505 void KRB5_CALLCONV
506 krb5_free_principal(krb5_context context, krb5_principal val)
507 {
508     register krb5_int32 i;
509 
510     if (!val)
511 	return;
512 
513     if (val->data) {
514 	i = krb5_princ_size(context, val);
515 	while(--i >= 0)
516             FREE(krb5_princ_component(context, val, i)->data,
517                 krb5_princ_component(context, val, i)->length+1);
518 	krb5_xfree_wrap(val->data,
519 		sizeof(krb5_data) * krb5_princ_size(context, val));
520     }
521     if (val->realm.data)
522 	krb5_xfree_wrap(val->realm.data, val->realm.length+1);
523     krb5_xfree_wrap(val, sizeof (krb5_principal_data));
524 }
525 
526 #ifndef _KERNEL
527 void KRB5_CALLCONV
528 krb5_free_priv(krb5_context context, register krb5_priv *val)
529 {
530     if (val->enc_part.ciphertext.data) {
531 	krb5_xfree(val->enc_part.ciphertext.data);
532 	val->enc_part.ciphertext.data = 0;
533     }
534     krb5_xfree(val);
535 }
536 
537 void KRB5_CALLCONV
538 krb5_free_priv_enc_part(krb5_context context, register krb5_priv_enc_part *val)
539 {
540     if (val->user_data.data) {
541 	krb5_xfree(val->user_data.data);
542 	val->user_data.data = 0;
543     }
544     if (val->r_address) {
545 	krb5_free_address(context, val->r_address);
546 	val->r_address = 0;
547     }
548     if (val->s_address) {
549 	krb5_free_address(context, val->s_address);
550 	val->s_address = 0;
551     }
552     krb5_xfree(val);
553 }
554 
555 void KRB5_CALLCONV
556 krb5_free_pwd_data(krb5_context context, krb5_pwd_data *val)
557 {
558     if (val->element)
559 	krb5_free_pwd_sequences(context, val->element);
560     krb5_xfree(val);
561 }
562 
563 
564 void KRB5_CALLCONV
565 krb5_free_pwd_sequences(krb5_context context, passwd_phrase_element **val)
566 {
567     register passwd_phrase_element **temp;
568 
569     for (temp = val; *temp; temp++) {
570 	if ((*temp)->passwd) {
571 	   krb5_free_data(context, (*temp)->passwd);
572 	   (*temp)->passwd = 0;
573 	}
574 	if ((*temp)->phrase) {
575 	   krb5_free_data(context, (*temp)->phrase);
576 	   (*temp)->phrase = 0;
577 	}
578 	krb5_xfree(*temp);
579     }
580     krb5_xfree(val);
581 }
582 
583 
584 void KRB5_CALLCONV
585 krb5_free_safe(krb5_context context, register krb5_safe *val)
586 {
587     if (val->user_data.data) {
588 	krb5_xfree(val->user_data.data);
589 	val->user_data.data = 0;
590     }
591     if (val->r_address) {
592 	krb5_free_address(context, val->r_address);
593 	val->r_address = 0;
594     }
595     if (val->s_address) {
596 	krb5_free_address(context, val->s_address);
597 	val->s_address = 0;
598     }
599     if (val->checksum) {
600 	krb5_free_checksum(context, val->checksum);
601 	val->checksum = 0;
602     }
603     krb5_xfree(val);
604 }
605 
606 
607 void KRB5_CALLCONV
608 krb5_free_ticket(krb5_context context, krb5_ticket *val)
609 {
610     if (val->server)
611 	krb5_free_principal(context, val->server);
612     if (val->enc_part.ciphertext.data) {
613 	krb5_xfree(val->enc_part.ciphertext.data);
614 	val->enc_part.ciphertext.data = 0;
615     }
616     if (val->enc_part2)
617 	krb5_free_enc_tkt_part(context, val->enc_part2);
618     krb5_xfree(val);
619 }
620 
621 void KRB5_CALLCONV
622 krb5_free_tickets(krb5_context context, krb5_ticket **val)
623 {
624     register krb5_ticket **temp;
625 
626     for (temp = val; *temp; temp++)
627         krb5_free_ticket(context, *temp);
628     krb5_xfree(val);
629 }
630 
631 
632 void KRB5_CALLCONV
633 krb5_free_tgt_creds(krb5_context context, krb5_creds **tgts)
634 {
635     register krb5_creds **tgtpp;
636     for (tgtpp = tgts; *tgtpp; tgtpp++)
637 	krb5_free_creds(context, *tgtpp);
638     krb5_xfree(tgts);
639 }
640 
641 void KRB5_CALLCONV
642 krb5_free_tkt_authent(krb5_context context, krb5_tkt_authent *val)
643 {
644     if (val->ticket) {
645 	krb5_free_ticket(context, val->ticket);
646 	val->ticket = 0;
647     }
648     if (val->authenticator) {
649 	krb5_free_authenticator(context, val->authenticator);
650 	val->authenticator = 0;
651     }
652     krb5_xfree(val);
653 }
654 
655 void KRB5_CALLCONV
656 krb5_free_unparsed_name(krb5_context context, char *val)
657 {
658     if (val) {
659 	krb5_xfree(val);
660     }
661 }
662 
663 void KRB5_CALLCONV
664 krb5_free_sam_challenge(krb5_context ctx, krb5_sam_challenge *sc)
665 {
666     if (!sc)
667 	return;
668     krb5_free_sam_challenge_contents(ctx, sc);
669     krb5_xfree(sc);
670 }
671 
672 void KRB5_CALLCONV
673 krb5_free_sam_challenge_2(krb5_context ctx, krb5_sam_challenge_2 *sc2)
674 {
675     if (!sc2)
676 	return;
677     krb5_free_sam_challenge_2_contents(ctx, sc2);
678     krb5_xfree(sc2);
679 }
680 
681 void KRB5_CALLCONV
682 krb5_free_sam_challenge_contents(krb5_context ctx, krb5_sam_challenge *sc)
683 {
684     if (!sc)
685 	return;
686     if (sc->sam_type_name.data)
687 	krb5_free_data_contents(ctx, &sc->sam_type_name);
688     if (sc->sam_track_id.data)
689 	krb5_free_data_contents(ctx, &sc->sam_track_id);
690     if (sc->sam_challenge_label.data)
691 	krb5_free_data_contents(ctx, &sc->sam_challenge_label);
692     if (sc->sam_challenge.data)
693 	krb5_free_data_contents(ctx, &sc->sam_challenge);
694     if (sc->sam_response_prompt.data)
695 	krb5_free_data_contents(ctx, &sc->sam_response_prompt);
696     if (sc->sam_pk_for_sad.data)
697 	krb5_free_data_contents(ctx, &sc->sam_pk_for_sad);
698     if (sc->sam_cksum.contents) {
699 	krb5_xfree(sc->sam_cksum.contents);
700 	sc->sam_cksum.contents = 0;
701     }
702 }
703 
704 void KRB5_CALLCONV
705 krb5_free_sam_challenge_2_contents(krb5_context ctx,
706 				   krb5_sam_challenge_2 *sc2)
707 {
708     krb5_checksum **cksump;
709 
710     if (!sc2)
711 	return;
712     if (sc2->sam_challenge_2_body.data)
713 	krb5_free_data_contents(ctx, &sc2->sam_challenge_2_body);
714     if (sc2->sam_cksum) {
715 	cksump = sc2->sam_cksum;
716 	while (*cksump) {
717             krb5_free_checksum(ctx, *cksump);
718             cksump++;
719 	}
720 	krb5_xfree(sc2->sam_cksum);
721 	sc2->sam_cksum = 0;
722     }
723 }
724 
725 void KRB5_CALLCONV
726 krb5_free_sam_challenge_2_body(krb5_context ctx,
727 			       krb5_sam_challenge_2_body *sc2)
728 {
729     if (!sc2)
730 	return;
731     krb5_free_sam_challenge_2_body_contents(ctx, sc2);
732     krb5_xfree(sc2);
733 }
734 
735 void KRB5_CALLCONV
736 krb5_free_sam_challenge_2_body_contents(krb5_context ctx,
737 					krb5_sam_challenge_2_body *sc2)
738 {
739     if (!sc2)
740 	return;
741     if (sc2->sam_type_name.data)
742 	krb5_free_data_contents(ctx, &sc2->sam_type_name);
743     if (sc2->sam_track_id.data)
744 	krb5_free_data_contents(ctx, &sc2->sam_track_id);
745     if (sc2->sam_challenge_label.data)
746 	krb5_free_data_contents(ctx, &sc2->sam_challenge_label);
747     if (sc2->sam_challenge.data)
748 	krb5_free_data_contents(ctx, &sc2->sam_challenge);
749     if (sc2->sam_response_prompt.data)
750 	krb5_free_data_contents(ctx, &sc2->sam_response_prompt);
751     if (sc2->sam_pk_for_sad.data)
752 	krb5_free_data_contents(ctx, &sc2->sam_pk_for_sad);
753 }
754 
755 void KRB5_CALLCONV
756 krb5_free_sam_response(krb5_context ctx, krb5_sam_response *sr)
757 {
758     if (!sr)
759 	return;
760     krb5_free_sam_response_contents(ctx, sr);
761     krb5_xfree(sr);
762 }
763 
764 void KRB5_CALLCONV
765 krb5_free_sam_response_2(krb5_context ctx, krb5_sam_response_2 *sr2)
766 {
767     if (!sr2)
768 	return;
769     krb5_free_sam_response_2_contents(ctx, sr2);
770     krb5_xfree(sr2);
771 }
772 
773 void KRB5_CALLCONV
774 krb5_free_sam_response_contents(krb5_context ctx, krb5_sam_response *sr)
775 {
776     if (!sr)
777 	return;
778     if (sr->sam_track_id.data)
779 	krb5_free_data_contents(ctx, &sr->sam_track_id);
780     if (sr->sam_enc_key.ciphertext.data)
781 	krb5_free_data_contents(ctx, &sr->sam_enc_key.ciphertext);
782     if (sr->sam_enc_nonce_or_ts.ciphertext.data)
783 	krb5_free_data_contents(ctx, &sr->sam_enc_nonce_or_ts.ciphertext);
784 }
785 
786 void KRB5_CALLCONV
787 krb5_free_sam_response_2_contents(krb5_context ctx, krb5_sam_response_2 *sr2)
788 {
789     if (!sr2)
790 	return;
791     if (sr2->sam_track_id.data)
792 	krb5_free_data_contents(ctx, &sr2->sam_track_id);
793     if (sr2->sam_enc_nonce_or_sad.ciphertext.data)
794 	krb5_free_data_contents(ctx, &sr2->sam_enc_nonce_or_sad.ciphertext);
795 }
796 
797 void KRB5_CALLCONV
798 krb5_free_predicted_sam_response(krb5_context ctx,
799 				 krb5_predicted_sam_response *psr)
800 {
801     if (!psr)
802 	return;
803     krb5_free_predicted_sam_response_contents(ctx, psr);
804     krb5_xfree(psr);
805 }
806 
807 void KRB5_CALLCONV
808 krb5_free_predicted_sam_response_contents(krb5_context ctx,
809 				 krb5_predicted_sam_response *psr)
810 {
811     if (!psr)
812 	return;
813     if (psr->sam_key.contents)
814 	krb5_free_keyblock_contents(ctx, &psr->sam_key);
815     if (psr->client) {
816 	krb5_free_principal(ctx, psr->client);
817 	psr->client = 0;
818     }
819     if (psr->msd.data)
820 	krb5_free_data_contents(ctx, &psr->msd);
821 }
822 
823 void KRB5_CALLCONV
824 krb5_free_enc_sam_response_enc(krb5_context ctx,
825 			       krb5_enc_sam_response_enc *esre)
826 {
827     if (!esre)
828 	return;
829     krb5_free_enc_sam_response_enc_contents(ctx, esre);
830     krb5_xfree(esre);
831 }
832 
833 void KRB5_CALLCONV
834 krb5_free_enc_sam_response_enc_2(krb5_context ctx,
835 				 krb5_enc_sam_response_enc_2 *esre2)
836 {
837     if (!esre2)
838 	return;
839     krb5_free_enc_sam_response_enc_2_contents(ctx, esre2);
840     krb5_xfree(esre2);
841 }
842 
843 void KRB5_CALLCONV
844 krb5_free_enc_sam_response_enc_contents(krb5_context ctx,
845 			       krb5_enc_sam_response_enc *esre)
846 {
847     if (!esre)
848 	return;
849     if (esre->sam_sad.data)
850 	krb5_free_data_contents(ctx, &esre->sam_sad);
851 }
852 
853 void KRB5_CALLCONV
854 krb5_free_enc_sam_response_enc_2_contents(krb5_context ctx,
855 					  krb5_enc_sam_response_enc_2 *esre2)
856 {
857     if (!esre2)
858 	return;
859     if (esre2->sam_sad.data)
860 	krb5_free_data_contents(ctx, &esre2->sam_sad);
861 }
862 
863 void KRB5_CALLCONV
864 krb5_free_pa_enc_ts(krb5_context ctx, krb5_pa_enc_ts *pa_enc_ts)
865 {
866     if (!pa_enc_ts)
867 	return;
868     krb5_xfree(pa_enc_ts);
869 }
870 #endif	/* !_KERNEL */
871