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