1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/gssapi/krb5/ser_sctx.c - [De]serialization of security context */
3 /*
4 * Copyright 1995, 2004, 2008 by the Massachusetts Institute of Technology.
5 * All Rights Reserved.
6 *
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
11 *
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
25 */
26
27 #include "k5-int.h"
28 #include "gssapiP_krb5.h"
29
30 /*
31 * This module contains routines to [de]serialize
32 * krb5_gss_enc_desc and krb5_gss_ctx_id_t.
33 * XXX This whole serialization abstraction is unnecessary in a
34 * non-messaging environment, which krb5 is. Someday, this should
35 * all get redone without the extra level of indirection. I've done
36 * some of this work here, since adding new serializers is an internal
37 * krb5 interface, and I won't use those. There is some more
38 * deobfuscation (no longer anonymizing pointers, mostly) which could
39 * still be done. --marc
40 */
41
42 static krb5_error_code
kg_oid_externalize(gss_OID oid,krb5_octet ** buffer,size_t * lenremain)43 kg_oid_externalize(gss_OID oid, krb5_octet **buffer, size_t *lenremain)
44 {
45 krb5_error_code err;
46
47 err = krb5_ser_pack_int32(KV5M_GSS_OID, buffer, lenremain);
48 if (err)
49 return err;
50 err = krb5_ser_pack_int32((krb5_int32) oid->length,
51 buffer, lenremain);
52 if (err)
53 return err;
54 err = krb5_ser_pack_bytes((krb5_octet *) oid->elements,
55 oid->length, buffer, lenremain);
56 if (err)
57 return err;
58 err = krb5_ser_pack_int32(KV5M_GSS_OID, buffer, lenremain);
59 return err;
60 }
61
62 static krb5_error_code
kg_oid_internalize(gss_OID * argp,krb5_octet ** buffer,size_t * lenremain)63 kg_oid_internalize(gss_OID *argp, krb5_octet **buffer, size_t *lenremain)
64 {
65 gss_OID oid;
66 krb5_int32 ibuf;
67 krb5_octet *bp;
68 size_t remain;
69
70 bp = *buffer;
71 remain = *lenremain;
72
73 /* Read in and check our magic number */
74 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
75 return (EINVAL);
76
77 if (ibuf != KV5M_GSS_OID)
78 return (EINVAL);
79
80 oid = (gss_OID) malloc(sizeof(gss_OID_desc));
81 if (oid == NULL)
82 return ENOMEM;
83 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) {
84 free(oid);
85 return EINVAL;
86 }
87 oid->length = ibuf;
88 oid->elements = malloc((size_t)ibuf);
89 if (oid->elements == 0) {
90 free(oid);
91 return ENOMEM;
92 }
93 if (krb5_ser_unpack_bytes((krb5_octet *) oid->elements,
94 oid->length, &bp, &remain)) {
95 free(oid->elements);
96 free(oid);
97 return EINVAL;
98 }
99
100 /* Read in and check our trailing magic number */
101 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) {
102 free(oid->elements);
103 free(oid);
104 return (EINVAL);
105 }
106
107 if (ibuf != KV5M_GSS_OID) {
108 free(oid->elements);
109 free(oid);
110 return (EINVAL);
111 }
112
113 *buffer = bp;
114 *lenremain = remain;
115 *argp = oid;
116 return 0;
117 }
118
119 static krb5_error_code
kg_oid_size(gss_OID oid,size_t * sizep)120 kg_oid_size(gss_OID oid, size_t *sizep)
121 {
122 krb5_error_code kret;
123 size_t required;
124
125 kret = EINVAL;
126 if (oid != NULL) {
127 required = 2*sizeof(krb5_int32); /* For the header and trailer */
128 required += sizeof(krb5_int32);
129 required += oid->length;
130
131 kret = 0;
132
133 *sizep += required;
134 }
135
136 return(kret);
137 }
138
139 static krb5_error_code
kg_seqstate_externalize(g_seqnum_state arg,krb5_octet ** buffer,size_t * lenremain)140 kg_seqstate_externalize(g_seqnum_state arg, krb5_octet **buffer,
141 size_t *lenremain)
142 {
143 krb5_error_code err;
144 err = krb5_ser_pack_int32(KV5M_GSS_QUEUE, buffer, lenremain);
145 if (err == 0)
146 err = g_seqstate_externalize(arg, buffer, lenremain);
147 if (err == 0)
148 err = krb5_ser_pack_int32(KV5M_GSS_QUEUE, buffer, lenremain);
149 return err;
150 }
151
152 static krb5_error_code
kg_seqstate_internalize(g_seqnum_state * argp,krb5_octet ** buffer,size_t * lenremain)153 kg_seqstate_internalize(g_seqnum_state *argp, krb5_octet **buffer,
154 size_t *lenremain)
155 {
156 krb5_int32 ibuf;
157 krb5_octet *bp;
158 size_t remain;
159 krb5_error_code err;
160
161 bp = *buffer;
162 remain = *lenremain;
163
164 /* Read in and check our magic number */
165 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
166 return (EINVAL);
167
168 if (ibuf != KV5M_GSS_QUEUE)
169 return (EINVAL);
170
171 err = g_seqstate_internalize(argp, &bp, &remain);
172 if (err)
173 return err;
174
175 /* Read in and check our trailing magic number */
176 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) {
177 g_seqstate_free(*argp);
178 return (EINVAL);
179 }
180
181 if (ibuf != KV5M_GSS_QUEUE) {
182 g_seqstate_free(*argp);
183 return (EINVAL);
184 }
185
186 *buffer = bp;
187 *lenremain = remain;
188 return 0;
189 }
190
191 static krb5_error_code
kg_seqstate_size(g_seqnum_state arg,size_t * sizep)192 kg_seqstate_size(g_seqnum_state arg, size_t *sizep)
193 {
194 krb5_error_code kret;
195 size_t required;
196
197 kret = EINVAL;
198 if (arg) {
199 required = 2*sizeof(krb5_int32); /* For the header and trailer */
200 g_seqstate_size(arg, &required);
201
202 kret = 0;
203 *sizep += required;
204 }
205 return(kret);
206 }
207
208 /*
209 * Determine the size required for this krb5_gss_ctx_id_rec.
210 */
211 krb5_error_code
kg_ctx_size(krb5_context kcontext,krb5_gss_ctx_id_t ctx,size_t * sizep)212 kg_ctx_size(krb5_context kcontext, krb5_gss_ctx_id_t ctx, size_t *sizep)
213 {
214 krb5_error_code kret;
215 size_t required;
216
217 /*
218 * krb5_gss_ctx_id_rec requires:
219 * krb5_int32 for KG_CONTEXT
220 * krb5_int32 for initiate.
221 * krb5_int32 for established.
222 * krb5_int32 for have_acceptor_subkey.
223 * krb5_int32 for seed_init.
224 * krb5_int32 for gss_flags.
225 * sizeof(seed) for seed
226 * ... for here
227 * ... for there
228 * ... for subkey
229 * krb5_int32 for signalg.
230 * krb5_int32 for cksum_size.
231 * krb5_int32 for sealalg.
232 * ... for enc
233 * ... for seq
234 * krb5_int32 for authtime.
235 * krb5_int32 for starttime.
236 * krb5_int32 for endtime.
237 * krb5_int32 for renew_till.
238 * krb5_int32 for flags.
239 * int64_t for seq_send.
240 * int64_t for seq_recv.
241 * ... for seqstate
242 * ... for auth_context
243 * ... for mech_used
244 * krb5_int32 for proto
245 * krb5_int32 for cksumtype
246 * ... for acceptor_subkey
247 * krb5_int32 for acceptor_key_cksumtype
248 * krb5_int32 for cred_rcache
249 * krb5_int32 for number of elements in authdata array
250 * ... for authdata array
251 * krb5_int32 for trailer.
252 */
253 kret = EINVAL;
254 if (ctx != NULL) {
255 required = 21*sizeof(krb5_int32);
256 required += 2*sizeof(int64_t);
257 required += sizeof(ctx->seed);
258
259 kret = 0;
260 if (!kret && ctx->here)
261 kret = k5_size_principal(ctx->here->princ, &required);
262
263 if (!kret && ctx->there)
264 kret = k5_size_principal(ctx->there->princ, &required);
265
266 if (!kret && ctx->subkey)
267 kret = k5_size_keyblock(&ctx->subkey->keyblock, &required);
268
269 if (!kret && ctx->enc)
270 kret = k5_size_keyblock(&ctx->enc->keyblock, &required);
271
272 if (!kret && ctx->seq)
273 kret = k5_size_keyblock(&ctx->seq->keyblock, &required);
274
275 if (!kret)
276 kret = kg_oid_size(ctx->mech_used, &required);
277
278 if (!kret && ctx->seqstate)
279 kret = kg_seqstate_size(ctx->seqstate, &required);
280
281 if (!kret)
282 kret = k5_size_context(ctx->k5_context, &required);
283 if (!kret)
284 kret = k5_size_auth_context(ctx->auth_context, &required);
285 if (!kret && ctx->acceptor_subkey)
286 kret = k5_size_keyblock(&ctx->acceptor_subkey->keyblock,
287 &required);
288 if (!kret && ctx->authdata) {
289 krb5_int32 i;
290
291 for (i = 0; !kret && ctx->authdata[i]; i++)
292 kret = k5_size_authdata(ctx->authdata[i], &required);
293 }
294 if (!kret) {
295 krb5_gss_name_t initiator_name;
296
297 initiator_name = ctx->initiate ? ctx->here : ctx->there;
298
299 if (initiator_name && initiator_name->ad_context) {
300 kret = k5_size_authdata_context(kcontext,
301 initiator_name->ad_context,
302 &required);
303 }
304 }
305 *sizep += required;
306 }
307 return(kret);
308 }
309
310 /*
311 * Externalize this krb5_gss_ctx_id_ret.
312 */
313 krb5_error_code
kg_ctx_externalize(krb5_context kcontext,krb5_gss_ctx_id_t ctx,krb5_octet ** buffer,size_t * lenremain)314 kg_ctx_externalize(krb5_context kcontext, krb5_gss_ctx_id_t ctx,
315 krb5_octet **buffer, size_t *lenremain)
316 {
317 krb5_error_code kret;
318 size_t required;
319 krb5_octet *bp;
320 size_t remain;
321 krb5int_access kaccess;
322
323 kret = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
324 if (kret)
325 return(kret);
326
327 required = 0;
328 bp = *buffer;
329 remain = *lenremain;
330 kret = EINVAL;
331 if (ctx != NULL) {
332 kret = ENOMEM;
333 if (!kg_ctx_size(kcontext, ctx, &required) &&
334 (required <= remain)) {
335 /* Our identifier */
336 (void) krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain);
337
338 /* Now static data */
339 (void) krb5_ser_pack_int32((krb5_int32) ctx->initiate,
340 &bp, &remain);
341 (void) krb5_ser_pack_int32((krb5_int32) ctx->established,
342 &bp, &remain);
343 (void) krb5_ser_pack_int32((krb5_int32) ctx->have_acceptor_subkey,
344 &bp, &remain);
345 (void) krb5_ser_pack_int32((krb5_int32) ctx->seed_init,
346 &bp, &remain);
347 (void) krb5_ser_pack_int32((krb5_int32) ctx->gss_flags,
348 &bp, &remain);
349 (void) krb5_ser_pack_bytes((krb5_octet *) ctx->seed,
350 sizeof(ctx->seed),
351 &bp, &remain);
352 (void) krb5_ser_pack_int32((krb5_int32) ctx->signalg,
353 &bp, &remain);
354 (void) krb5_ser_pack_int32((krb5_int32) ctx->cksum_size,
355 &bp, &remain);
356 (void) krb5_ser_pack_int32((krb5_int32) ctx->sealalg,
357 &bp, &remain);
358 (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_times.authtime,
359 &bp, &remain);
360 (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_times.starttime,
361 &bp, &remain);
362 (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_times.endtime,
363 &bp, &remain);
364 (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_times.renew_till,
365 &bp, &remain);
366 (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_flags,
367 &bp, &remain);
368 (void) (*kaccess.ser_pack_int64)((int64_t) ctx->seq_send,
369 &bp, &remain);
370 (void) (*kaccess.ser_pack_int64)((int64_t) ctx->seq_recv,
371 &bp, &remain);
372
373 /* Now dynamic data */
374 kret = 0;
375
376 if (!kret && ctx->mech_used)
377 kret = kg_oid_externalize(ctx->mech_used, &bp, &remain);
378
379 if (!kret && ctx->here)
380 kret = k5_externalize_principal(ctx->here->princ,
381 &bp, &remain);
382
383 if (!kret && ctx->there)
384 kret = k5_externalize_principal(ctx->there->princ,
385 &bp, &remain);
386
387 if (!kret && ctx->subkey)
388 kret = k5_externalize_keyblock(&ctx->subkey->keyblock,
389 &bp, &remain);
390
391 if (!kret && ctx->enc)
392 kret = k5_externalize_keyblock(&ctx->enc->keyblock,
393 &bp, &remain);
394
395 if (!kret && ctx->seq)
396 kret = k5_externalize_keyblock(&ctx->seq->keyblock,
397 &bp, &remain);
398
399 if (!kret && ctx->seqstate)
400 kret = kg_seqstate_externalize(ctx->seqstate, &bp, &remain);
401
402 if (!kret)
403 kret = k5_externalize_context(ctx->k5_context, &bp, &remain);
404
405 if (!kret)
406 kret = k5_externalize_auth_context(ctx->auth_context,
407 &bp, &remain);
408
409 if (!kret)
410 kret = krb5_ser_pack_int32((krb5_int32) ctx->proto,
411 &bp, &remain);
412 if (!kret)
413 kret = krb5_ser_pack_int32((krb5_int32) ctx->cksumtype,
414 &bp, &remain);
415 if (!kret && ctx->acceptor_subkey)
416 kret = k5_externalize_keyblock(&ctx->acceptor_subkey->keyblock,
417 &bp, &remain);
418 if (!kret)
419 kret = krb5_ser_pack_int32((krb5_int32) ctx->acceptor_subkey_cksumtype,
420 &bp, &remain);
421
422 if (!kret)
423 kret = krb5_ser_pack_int32((krb5_int32) ctx->cred_rcache,
424 &bp, &remain);
425 if (!kret) {
426 krb5_int32 i = 0;
427
428 if (ctx->authdata) {
429 for (; ctx->authdata[i]; i++)
430 ;
431 }
432 /* authdata count */
433 kret = krb5_ser_pack_int32(i, &bp, &remain);
434 if (!kret && ctx->authdata) {
435 /* authdata */
436 for (i = 0; !kret && ctx->authdata[i]; i++)
437 kret = k5_externalize_authdata(ctx->authdata[i],
438 &bp, &remain);
439 }
440 }
441 /* authdata context */
442 if (!kret) {
443 krb5_gss_name_t initiator_name;
444
445 initiator_name = ctx->initiate ? ctx->here : ctx->there;
446
447 if (initiator_name && initiator_name->ad_context) {
448 kret = k5_externalize_authdata_context(kcontext,
449 initiator_name->
450 ad_context,
451 &bp, &remain);
452 }
453 }
454 /* trailer */
455 if (!kret)
456 kret = krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain);
457 if (!kret) {
458 *buffer = bp;
459 *lenremain = remain;
460 }
461 }
462 }
463 return(kret);
464 }
465
466 /* Internalize a keyblock and convert it to a key. */
467 static krb5_error_code
intern_key(krb5_key * key,krb5_octet ** bp,size_t * sp)468 intern_key(krb5_key *key, krb5_octet **bp, size_t *sp)
469 {
470 krb5_keyblock *keyblock;
471 krb5_error_code ret;
472
473 ret = k5_internalize_keyblock(&keyblock, bp, sp);
474 if (ret != 0)
475 return ret;
476 ret = krb5_k_create_key(NULL, keyblock, key);
477 krb5_free_keyblock(NULL, keyblock);
478 return ret;
479 }
480
481 /*
482 * Internalize this krb5_gss_ctx_id_t.
483 */
484 krb5_error_code
kg_ctx_internalize(krb5_context kcontext,krb5_gss_ctx_id_t * argp,krb5_octet ** buffer,size_t * lenremain)485 kg_ctx_internalize(krb5_context kcontext, krb5_gss_ctx_id_t *argp,
486 krb5_octet **buffer, size_t *lenremain)
487 {
488 krb5_error_code kret;
489 krb5_gss_ctx_id_rec *ctx;
490 krb5_int32 ibuf;
491 krb5_octet *bp;
492 size_t remain;
493 krb5int_access kaccess;
494 krb5_principal princ;
495
496 kret = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
497 if (kret)
498 return(kret);
499
500 bp = *buffer;
501 remain = *lenremain;
502 kret = EINVAL;
503 princ = NULL;
504 /* Read our magic number */
505 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
506 ibuf = 0;
507 if (ibuf == KG_CONTEXT) {
508 kret = ENOMEM;
509
510 /* Get a context */
511 if ((remain >= (17*sizeof(krb5_int32)
512 + 2*sizeof(int64_t)
513 + sizeof(ctx->seed))) &&
514 (ctx = (krb5_gss_ctx_id_rec *)
515 xmalloc(sizeof(krb5_gss_ctx_id_rec)))) {
516 memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
517
518 ctx->magic = ibuf;
519
520 /* Get static data */
521 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
522 ctx->initiate = (int) ibuf;
523 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
524 ctx->established = (int) ibuf;
525 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
526 ctx->have_acceptor_subkey = (int) ibuf;
527 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
528 ctx->seed_init = (int) ibuf;
529 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
530 ctx->gss_flags = (int) ibuf;
531 (void) krb5_ser_unpack_bytes((krb5_octet *) ctx->seed,
532 sizeof(ctx->seed),
533 &bp, &remain);
534 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
535 ctx->signalg = (int) ibuf;
536 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
537 ctx->cksum_size = (int) ibuf;
538 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
539 ctx->sealalg = (int) ibuf;
540 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
541 ctx->krb_times.authtime = (krb5_timestamp) ibuf;
542 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
543 ctx->krb_times.starttime = (krb5_timestamp) ibuf;
544 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
545 ctx->krb_times.endtime = (krb5_timestamp) ibuf;
546 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
547 ctx->krb_times.renew_till = (krb5_timestamp) ibuf;
548 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
549 ctx->krb_flags = (krb5_flags) ibuf;
550 (void) (*kaccess.ser_unpack_int64)((int64_t *)&ctx->seq_send,
551 &bp, &remain);
552 kret = (*kaccess.ser_unpack_int64)((int64_t *)&ctx->seq_recv,
553 &bp, &remain);
554 if (kret) {
555 free(ctx);
556 return kret;
557 }
558
559 {
560 gss_OID tmp;
561 kret = kg_oid_internalize(&tmp, &bp, &remain);
562 if (kret == 0)
563 ctx->mech_used = tmp;
564 else if (kret == EINVAL)
565 kret = 0;
566 }
567 /* Now get substructure data */
568 kret = k5_internalize_principal(&princ, &bp, &remain);
569 if (kret == 0) {
570 kret = kg_init_name(kcontext, princ, NULL, NULL, NULL,
571 KG_INIT_NAME_NO_COPY, &ctx->here);
572 if (kret)
573 krb5_free_principal(kcontext, princ);
574 } else if (kret == EINVAL)
575 kret = 0;
576 if (!kret) {
577 kret = k5_internalize_principal(&princ, &bp, &remain);
578 if (kret == 0) {
579 kret = kg_init_name(kcontext, princ, NULL, NULL, NULL,
580 KG_INIT_NAME_NO_COPY, &ctx->there);
581 if (kret)
582 krb5_free_principal(kcontext, princ);
583 } else if (kret == EINVAL)
584 kret = 0;
585 }
586 if (!kret &&
587 (kret = intern_key(&ctx->subkey, &bp, &remain))) {
588 if (kret == EINVAL)
589 kret = 0;
590 }
591 if (!kret &&
592 (kret = intern_key(&ctx->enc, &bp, &remain))) {
593 if (kret == EINVAL)
594 kret = 0;
595 }
596 if (!kret &&
597 (kret = intern_key(&ctx->seq, &bp, &remain))) {
598 if (kret == EINVAL)
599 kret = 0;
600 }
601
602 if (!kret) {
603 kret = kg_seqstate_internalize(&ctx->seqstate, &bp, &remain);
604 if (kret == EINVAL)
605 kret = 0;
606 }
607
608 if (!kret)
609 kret = k5_internalize_context(&ctx->k5_context, &bp, &remain);
610
611 if (!kret)
612 kret = k5_internalize_auth_context(&ctx->auth_context,
613 &bp, &remain);
614
615 if (!kret)
616 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
617 ctx->proto = ibuf;
618 if (!kret)
619 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
620 ctx->cksumtype = ibuf;
621 if (!kret &&
622 (kret = intern_key(&ctx->acceptor_subkey, &bp, &remain))) {
623 if (kret == EINVAL)
624 kret = 0;
625 }
626 if (!kret)
627 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
628 ctx->acceptor_subkey_cksumtype = ibuf;
629 if (!kret)
630 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
631 ctx->cred_rcache = ibuf;
632 /* authdata */
633 if (!kret)
634 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
635 if (!kret) {
636 krb5_int32 nadata = ibuf, i;
637
638 if (nadata > 0) {
639 ctx->authdata = (krb5_authdata **)calloc((size_t)nadata + 1,
640 sizeof(krb5_authdata *));
641 if (ctx->authdata == NULL) {
642 kret = ENOMEM;
643 } else {
644 for (i = 0; !kret && i < nadata; i++)
645 kret = k5_internalize_authdata(&ctx->authdata[i],
646 &bp, &remain);
647 }
648 }
649 }
650 /* authdata context */
651 if (!kret) {
652 krb5_gss_name_t initiator_name;
653
654 initiator_name = ctx->initiate ? ctx->here : ctx->there;
655 if (initiator_name == NULL) {
656 kret = EINVAL;
657 } else {
658 kret = k5_internalize_authdata_context(kcontext,
659 &initiator_name->
660 ad_context,
661 &bp, &remain);
662 if (kret == EINVAL)
663 kret = 0;
664 }
665 }
666 /* Get trailer */
667 if (!kret)
668 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
669 if (!kret && ibuf != KG_CONTEXT)
670 kret = EINVAL;
671
672 if (!kret) {
673 *buffer = bp;
674 *lenremain = remain;
675 *argp = ctx;
676 } else {
677 if (ctx->seq)
678 krb5_k_free_key(kcontext, ctx->seq);
679 if (ctx->enc)
680 krb5_k_free_key(kcontext, ctx->enc);
681 if (ctx->subkey)
682 krb5_k_free_key(kcontext, ctx->subkey);
683 if (ctx->there)
684 kg_release_name(kcontext, &ctx->there);
685 if (ctx->here)
686 kg_release_name(kcontext, &ctx->here);
687 xfree(ctx);
688 }
689 }
690 }
691 return(kret);
692 }
693