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